├── .babelrc
├── .editorconfig
├── .gitignore
├── .prettierrc
├── .yarnrc.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── dist
├── vue-navigation-bar.css
├── vue-navigation-bar.esm.js
├── vue-navigation-bar.min.js
└── vue-navigation-bar.umd.js
├── docs
├── assets
│ ├── index.2f3ff1f9.css
│ ├── index.d2236a20.js
│ └── lockup-color.5dabaa34.png
└── index.html
├── example
├── App.vue
├── index.html
└── index.js
├── package.json
├── rollup.config.js
├── src
├── assets
│ ├── css
│ │ └── main.scss
│ └── images
│ │ ├── badge.png
│ │ ├── chevron-down.svg
│ │ ├── collapse-menu-dark.svg
│ │ ├── collapse-menu-light.svg
│ │ ├── favicon.png
│ │ ├── lockup-color.png
│ │ ├── social.png
│ │ └── times.svg
├── common
│ └── uuidV4.js
├── components
│ ├── BrandImage.vue
│ ├── CollapseButton.vue
│ ├── DesktopMenuItemButton.vue
│ ├── DesktopMenuItemLink.vue
│ ├── DesktopMenuItemSpacer.vue
│ ├── DynamicLink.vue
│ ├── MenuOptions.vue
│ └── Popup.vue
├── index.js
└── vue-navigation-bar.vue
├── test
├── VueNavigationBar.spec.js
└── styleMock.js
├── vite.config.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": {
7 | "browsers": [
8 | "last 2 versions",
9 | "safari >= 7"
10 | ]
11 | }
12 | }
13 | ]
14 | ],
15 | "plugins": [
16 | [
17 | "@babel/plugin-transform-runtime"
18 | ]
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 |
4 | # https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
5 | .pnp.*
6 | .yarn/*
7 | !.yarn/patches
8 | !.yarn/plugins
9 | !.yarn/releases
10 | !.yarn/sdks
11 | !.yarn/versions
12 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "semi": true,
4 | "singleQuote": true,
5 | "tabWidth": 2,
6 | "trailingComma": "all",
7 | "useTabs": false
8 | }
9 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | enableTelemetry: false
2 | nodeLinker: node-modules
3 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG.md
2 |
3 | ## 5.0.2 (2022-03-20)
4 |
5 | - Upgrade to Vue 3 support at `v5.0.0` and beyond. Vue 2 support is available at `v4.1.0`.
6 |
7 | ## 4.1.0 (2020-10-15)
8 |
9 | - Adds `tooltipPlacement` prop to control direction of menu tooltip. This prevents the tooltip libraries from adjusting the position once set. This is preferable for a dropdown-type system we have here. Thank you @jeffreykthomas for your research and help on this.
10 |
11 | ## 1.3.1 (2019-08-06)
12 |
13 | - Adjusting project formatting.
14 | - Renamed events `mobile-popup-shown` and `mobile-popup-hidden` to `vnb-mobile-popup-shown` and `vnb-mobile-popup-hidden`.
15 | - Added ability to make links `emit` events instead of triggering their path. Good for cases when you want to run a function using a `menuOption` instead of following a link.
16 | - Hiding the popup and collapse button if there are no `menuOptions` to show.
17 | - Added `tooltipAnimationType` to the options so that you can change the dropdown animation type.
18 |
19 | ## 1.3.0 (2019-04-23)
20 |
21 | - Added the ability to provide your own collapse open and close image - `collapseButtonImageOpen` and `collapseButtonImageClose` . Added dynamic `id` functionality to the menu options to allow for multiple instances of the component.
22 |
23 | ## 1.2.0 (2019-03-29)
24 |
25 | - Added optional `slot` option named `custom-slot` .
26 |
27 | ## 1.0.0 (2019-03-18)
28 |
29 | - Initial work
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 John Datserakis
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # vue-navigation-bar
4 |
5 | A simple, pretty navbar for your Vue projects.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ## Vue 3 Support
15 |
16 | Vue 3 is supported from `v5.0.0` and beyond (current `master`). To use `vue-navigation-bar` with Vue 2, use `v4.1.0`.
17 |
18 | ## Links
19 |
20 | - [Demo](https://johndatserakis.github.io/vue-navigation-bar/)
21 | - [View on GitHub](https://github.com/johndatserakis/vue-navigation-bar)
22 | - [View on npm](https://www.npmjs.com/package/vue-navigation-bar)
23 |
24 | ## Install
25 |
26 | ```bash
27 | yarn add vue-navigation-bar
28 | ```
29 |
30 | Or you can include it through the browser at the bottom of your page along with the css:
31 |
32 | ```html
33 |
34 |
35 |
40 | ```
41 |
42 | ## Usage
43 |
44 | ```js
45 | import { createApp } from 'vue';
46 | import VueNavigationBar from 'vue-navigation-bar';
47 | import 'vue-navigation-bar/dist/vue-navigation-bar.css';
48 |
49 | const app = createApp(App);
50 |
51 | app.component('vue-navigation-bar', VueNavigationBar);
52 | ```
53 |
54 | ## About
55 |
56 | Often when starting a new project I like to get together the main foundation pieces first. A main part of that process is working on the main navbar.
57 |
58 | This component is meant to help with that process - it gives you a standard looking navigation bar for for your app that can be easily defined using `JSON` or a just an array of objects.
59 |
60 | `vue-navigation-bar` is meant to be used for the 80% of cases that exist when you need a standard navbar for your app/website. The layout has the `brand-image` anchored on the left side, and two slots for `menu-options` that push and pull based on designation.
61 |
62 | I know there are lots of other styles that navbar's can be, for instance the `brand-image` could be in the middle - but this component won't be allowing you to do that at the moment - so if that's your thing then I would probably look to roll out something on your own, or fork this to apply to your needs if possible. That being said, the actual `css` here is very easy to override - I'm using `BEM` with `SASS` ( `.scss` ) and have the style skeleton posted below - so you should be able to style it quite nicely without issue. I've put a lot of time in placing sensible defaults that should work well against any style.
63 |
64 | The trade-off is that the initialization and usage of this component is very easy and won't force you to do anything except declare the structure initially and declare a few `css` styles as necessary.
65 |
66 | `vue-navigation-bar` is compatible with both `vue-router` projects and non- `vue-router` projects - just make sure to pass in `true` for the `isUsingVueRouter` option if you're using `vue-router`.
67 |
68 | The component will work well with frontend component frameworks. I'm using Bootstrap 4 in the demo page and have it sitting in a container - that helps keep it from stretching too far across the page - although that may be the style you're going for, so have at it.
69 |
70 | ## Usage Example
71 |
72 | ```javascript
73 |
74 |
75 |
76 |
77 |
184 |
185 |
196 | ```
197 |
198 | ## Notes
199 |
200 | Above is a basic usage example. You'll see that a lot of the work is actually just declaring your `options` object.
201 |
202 | In the style section you'll see that I provide a button class to color a button in the navbar. This is done like this to give you the most control over the button color and other pseudo properties. In this case, I want one of my buttons to be red, so I provide a class in my `options` object and then style the class appropriately like this:
203 |
204 | Note - the first example uses basic `css` , the second example is the same thing just using `sass` nesting - same result.
205 |
206 | ```css
207 | .vnb .button-red {
208 | background: #ff3b30;
209 | }
210 |
211 | .vnb .button-red:hover {
212 | background: #fc0d00;
213 | }
214 | ```
215 |
216 | ```scss
217 | .vnb {
218 | .button-red {
219 | background: #ff3b30;
220 |
221 | &:hover {
222 | background: darken(#ff3b30, 10%);
223 | }
224 | }
225 | }
226 | ```
227 |
228 | You can make a bunch of button-color classes and set them up just like above.
229 |
230 | Take a look at the `./example` folder in this project - it has the complete working example that you see in the demo.(FYI - the `vue-router` setup there is really rudimentary so all the different pages aren't real - doesn't affect the demo.)
231 |
232 | You may need to adjust your `brand-image` a bit - that's normal as brand images come in different shapes and sizes - go ahead and set a `max-width` or `max-height` in pixels using this selector: `.vnb__brand-image-wrapper__link__image` . Even a little margin may help. For instance, the base I have it at is `max-height: 34px;` - should work for most cases.
233 |
234 | Sometimes you may want your links to perform an action instead of following a link. To do this, add the `isLinkAction` property to your `menuOption` and it'll `emit` the `vnb-item-clicked` event with the `text` property of the `menuOption` . This will suppress the `path` option so the link no longer goes anywhere, but instead just sends the event. Checkout the example page to see this in action.
235 |
236 | ### Props
237 |
238 | | prop | type | required | default | possible values | description |
239 | | ---------------------------------------- | ---------------- | -------- | ----------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
240 | | elementId | String | no | A generated uuid | | This value will be set as the `id` of the instance |
241 | | isUsingVueRouter | Boolean | no | false | | If you want to use vue-router, set this to true and all links will automatically be `` |
242 | | mobileBreakpoint | Number | no | 992 | | Width at which the navbar turns into the mobile version |
243 | | brandImagePath | String or Object | no | '/' | | Link path of menu-option. If you have `isUsingVueRouter === true`, then this needs to be an `Object` with a `name` property or just a `String` of your path. Otherwise, just provide a `String`. link |
244 | | brandImage | Image | no | | | `import` your image here to use your brand image |
245 | | brandImageAltText | String | no | 'brand-image' | | The `alt` tag text for your brand image |
246 | | collapseButtonImageOpen | Image | no | A hamburger icon | | `import` your image here |
247 | | collapseButtonImageClose | Image | no | A times icon | | `import` your image here |
248 | | collapseButtonOpenColor | String | no | `#373737` | | CSS hex - `#FFF`. Only applicable if you don't supply a `collapseButtonImageOpen`. |
249 | | collapseButtonCloseColor | String | no | `#373737` | | CSS hex - `#FFF`. Only applicable if you don't supply a `collapseButtonImageClose`. |
250 | | showBrandImageInMobilePopup | Boolean | no | false | | If you want to show your brand logo in the mobile popup |
251 | | ariaLabelMainNav | String | no | 'Main Navigation' | | The `aria-label` value for the main navbar element |
252 | | tooltipAnimationType | String | no | 'shift-away' | 'shift-away', 'shift-toward', 'scale', 'perspective' | See [tippy.js docs](https://atomiks.github.io/tippyjs/all-options/) |
253 | | tooltipPlacement | String | no | 'bottom' | 'top', 'bottom', 'left', 'right' ... and more. | See [tippy.js docs](https://atomiks.github.io/tippyjs/v6/all-props/#placement) for the complete list. Also, make sure to cross reference with popper.js's options. The tooltip dropdown will always drop in the direction you set here. |
254 | | menuOptionsLeft | Object | no | {} | | Menu options that will be _pulled_ to the left towards the `brand-image` |
255 | | menuOptionsLeft.type | String | yes | | 'link', 'button', 'spacer', 'dropdown' | What type of link will this menu-option be? `link` will be a link, `button` will be a button, `spacer` will be a spacer with a width of `30px` , `dropdown` will create a dropdown on desktop and a `ul/li` list on mobile. `dropdown` only works on menuOptions, not subMenuOptions. |
256 | | menuOptionsLeft.text | String | yes | | | Text of menu-option |
257 | | menuOptionsLeft.path | String or Object | no | | | Link path of menu-option. If you have `isUsingVueRouter === true`, then this needs to be an `Object` with at least a `name` property or just a `String` of your path. Otherwise, just provide a `String`. Not applicable to `dropdown` menuOption types. Do not use when setting `isLinkAction`. |
258 | | menuOptionsLeft.arrowColor | String | no | | | CSS hex - `#FFF`. This styles the little chevron icon. |
259 | | menuOptionsLeft.class | String | no | | | Only for `menuOptionsLeft.type === 'button'` - provide a class name so you can style your buttons |
260 | | menuOptionsLeft.isLinkAction | Boolean | no | false | | When `true`, any `path` option of the `menuOption` will not fire - instead, you'll be able to register for the `@vnb-item-clicked` event which will spit you out the `text` value of your `menuOption` . That way, you can do an action you may want to trigger. |
261 | | menuOptionsLeft.iconLeft | HTML String | no | | | Only for `menuOptionsLeft.type === 'link or menuOptionsLeft.type === 'dropdown'`. HTML string of the icon you want to use. See more info on the `Icon` section of the README. |
262 | | menuOptionsLeft.iconRight | HTML String | no | | | Only for `menuOptionsLeft.type === 'link or menuOptionsLeft.type === 'dropdown'`. HTML string of the icon you want to use. See more info on the `Icon` section of the README. |
263 | | menuOptionsLeft.subMenuOptions | Object | no | | | Sub-menu-options that will be shown |
264 | | menuOptionsLeft.subMenuOptions.type | String | yes | | 'link', 'hr' | What type of link will this sub-menu-option be? `link` will be a link, `hr` will be a `hr` spacer |
265 | | menuOptionsLeft.subMenuOptions.text | String | yes | | | Text of sub-menu-option |
266 | | menuOptionsLeft.subMenuOptions.subText | String | no | | | Sub text of sub-menu-option |
267 | | menuOptionsLeft.subMenuOptions.path | String | no | | | Link path of sub-menu-option |
268 | | menuOptionsLeft.subMenuOptions.iconLeft | HTML String | no | | | HTML string of the icon you want to use. See more info on the `Icon` section of the README. |
269 | | menuOptionsLeft.subMenuOptions.iconRight | HTML String | no | | | HTML string of the icon you want to use. See more info on the `Icon` section of the README. |
270 | | menuOptionsRight | Object | no | {} | | Menu options that will be pushed to the right of the navbar. See above - all `menuOptionsLeft` apply |
271 |
272 | ## Events
273 |
274 | | event | value | description |
275 | | ----------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
276 | | vnb-mobile-popup-shown | null | Emitted when the mobile popup is shown |
277 | | vnb-mobile-popup-hidden | null | Emitted when the mobile popup is hidden |
278 | | vnb-item-clicked | String, `menuOption.text` | Emitted when a menu option is clicked. Listen to this event to then trigger a function based on the returned value, which is the `text` value of the `menuOption` that was clicked. |
279 |
280 | ## Methods
281 |
282 | | method | parameters | description |
283 | | ---------------- | ---------- | ---------------------- |
284 | | closeMobilePopup | | Close the mobile popup |
285 | | showMobilePopup | | Show the mobile popup |
286 |
287 | Note - to call these methods set a `ref` on your `` , something like this: `` . Then, manually call the methods like this in your javascript: `this.$refs.myNavbar.closeMobilePopup()` .
288 |
289 | ## Slots
290 |
291 | | name | description |
292 | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
293 | | custom-section | Use this to provide custom content in the navbar. Checkout the example code - in the commented-out section is an example search-bar setup. |
294 |
295 | ## SCSS Structure
296 |
297 | ```scss
298 | .vnb {
299 | &__brand-image-wrapper {
300 | &__link {
301 | &__image {
302 | }
303 | }
304 | }
305 |
306 | &__menu-options {
307 | &--left {
308 | }
309 |
310 | &--right {
311 | }
312 |
313 | &__option {
314 | &__link {
315 | &:hover {
316 | }
317 |
318 | &__icon {
319 | svg {
320 | }
321 |
322 | &--left {
323 | }
324 |
325 | &--right {
326 | }
327 | }
328 | }
329 |
330 | &__arrow {
331 | &--hover {
332 | }
333 | }
334 |
335 | &__button {
336 | &__icon {
337 | svg {
338 | }
339 |
340 | &--left {
341 | }
342 |
343 | &--right {
344 | }
345 | }
346 | }
347 |
348 | &__spacer {
349 | }
350 | }
351 | }
352 |
353 | &__sub-menu-options {
354 | &__option {
355 | &__link {
356 | &:hover {
357 | }
358 |
359 | &__icon {
360 | svg {
361 | }
362 |
363 | &--left {
364 | }
365 |
366 | &--right {
367 | }
368 | }
369 |
370 | &__text-wrapper {
371 | &__text {
372 | }
373 |
374 | &__sub-text {
375 | }
376 | }
377 | }
378 |
379 | &__hr {
380 | }
381 | }
382 | }
383 |
384 | &__collapse-button {
385 | &:hover {
386 | }
387 |
388 | &__image {
389 | }
390 | }
391 |
392 | &__popup {
393 | &__top {
394 | &__image {
395 | }
396 |
397 | &__close-button {
398 | &:hover {
399 | }
400 |
401 | &__image {
402 | }
403 | }
404 | }
405 |
406 | &__bottom {
407 | &__custom-section {
408 | }
409 |
410 | &__menu-options {
411 | &__option {
412 | &:not(:last-child) {
413 | }
414 |
415 | &__link {
416 | &:hover {
417 | }
418 |
419 | &--no-highlight {
420 | &:hover {
421 | }
422 | }
423 |
424 | &__icon {
425 | svg {
426 | }
427 |
428 | &--left {
429 | }
430 |
431 | &--right {
432 | }
433 | }
434 | }
435 | }
436 | }
437 |
438 | &__sub-menu-options {
439 | &__option {
440 | &__link {
441 | &:hover {
442 | }
443 |
444 | &__sub-text {
445 | }
446 | }
447 | }
448 | }
449 | }
450 | }
451 | }
452 |
453 | .vnb-button {
454 | &:hover {
455 | }
456 | }
457 | ```
458 |
459 | ## Icons
460 |
461 | So right now to use icons in some of the options, you need to pass in full `HTML` strings which get rendered as `HTML` in the desktop version of the navbar.
462 |
463 | In the demo I use this really great set of `svg` icons called [bytesize-icons](https://github.com/danklammer/bytesize-icons). You can just copy the `` code and pass it in your initialization object. You can do the same thing with the FontAwesome style of `` . In the future I'll be looking at a way to pass in full components as icons. Right now, passing in `svg` icons works well and does the job. Check out the `.example` folder to see how I have it in the demo.
464 |
465 | ## Accessibility
466 |
467 | Throughout the development of this component I've been making sure to allow for proper a11y options to be set when possible. This means things like `aria-haspopup` and `aria-expanded` are set on the popup-menus, `aria-label` 's are set on the elements, and any user can come through and use the navbar nicely using the `tab` button. Of course there can probably be improvements on this front, so I'll keep an eye on it myself and look for any pull-requests that improve it.
468 |
469 | ## Browser Support
470 |
471 | To have this work with a browser like IE11, stick this at the bottom of your `index.html`
472 |
473 | ```html
474 |
475 | ```
476 |
477 | Or, you can install `babel-polyfill` and import that in the main script of your app. You can read more about `babel-polyfill` [here](https://babeljs.io/docs/en/babel-polyfill). In the example folder I use the external script method.
478 |
479 | ## Development
480 |
481 | ```bash
482 | # Install dependencies
483 | yarn
484 |
485 | # Serve with hot reload
486 | yarn dev
487 |
488 | # Run the tests
489 | yarn test
490 |
491 | # Build demo page
492 | yarn build:example
493 |
494 | # Build library
495 | yarn build:library
496 |
497 | # Build everything and run tests
498 | yarn build
499 | ```
500 |
501 | ## TODO
502 |
503 | - [x] ~~Add an optional search input bar.~~ What I've done is add an optional `slot` named `custom-section` . Use this `slot` to add whatever custom content you want to show in the nav bar. In the demo, I have an example search bar shown. Look at the `./example` folder to check it out.
504 | - [ ] See if there's a way to let users pass a component for an icon and not be limited to HTML strings of the icon they want.
505 | - [ ] Add more thorough tests.
506 | - [ ] Add `prettier`, and `eslint` to the project. Pretty much mirror the settings from something like [this](https://github.com/johndatserakis/koa-vue-notes-web).
507 | - [ ] Fix the awful nesting job I did with the `SCSS` `BEM` nesting. I took the nesting way too far - really I should only need to go one level deep - maybe two. Anyways - I'll get to this soon - sorry about that until then. It's not anything too bad, but I've grown since then and realized the error in my ways ha.
508 |
509 | ## Other
510 |
511 | Go ahead and fork the project! Submit an issue if needed. Have fun!
512 |
513 | ## Thank You
514 |
515 | Thank you to [Stripe](https://stripe.com/) for making that sick navbar - absolutely filthy. A lot of my styling is inspired by them - although I'm definitely butchering it. Also to [Bootstrap](https://getbootstrap.com/) - I've used Bootstrap and their navbar for many years and drew inspiration from lessons I've learned using it.
516 |
517 | ## License
518 |
519 | [MIT](http://opensource.org/licenses/MIT)
520 |
--------------------------------------------------------------------------------
/dist/vue-navigation-bar.css:
--------------------------------------------------------------------------------
1 | .vnb {
2 | background: #fff;
3 | padding-top: 15px;
4 | padding-bottom: 15px;
5 | display: flex;
6 | flex-direction: row;
7 | align-items: center;
8 | justify-content: space-between;
9 | }
10 | .vnb * {
11 | box-sizing: border-box;
12 | }
13 | .vnb a {
14 | text-decoration: none;
15 | }
16 |
17 | .tippy-tooltip {
18 | padding: 0;
19 | }
20 |
21 | .vnb-image {
22 | max-width: 100%;
23 | height: auto;
24 | }
25 |
26 | .vnb__menu-options {
27 | display: flex;
28 | flex-direction: row;
29 | align-items: center;
30 | }
31 | .vnb__menu-options--left {
32 | margin-right: auto;
33 | justify-content: flex-start;
34 | padding-left: 30px;
35 | }
36 | .vnb__menu-options--right {
37 | margin-left: auto;
38 | justify-content: flex-end;
39 | padding-right: 10px;
40 | }
41 | .vnb__menu-options__option:not(:last-child) {
42 | margin-right: 20px;
43 | }
44 |
45 | .vnb__collapse-button {
46 | cursor: pointer;
47 | border: 0;
48 | background: transparent;
49 | margin-right: 10px;
50 | }
51 | .vnb__collapse-button:hover {
52 | opacity: 0.75;
53 | }
54 | .vnb__collapse-button__image {
55 | max-height: 30px;
56 | max-width: 30px;
57 | }
58 |
59 | .vnb__popup {
60 | background: #fff;
61 | position: absolute;
62 | left: 10px;
63 | top: 10px;
64 | right: 10px;
65 | display: flex;
66 | flex-direction: column;
67 | perspective: 2000px;
68 | box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.1);
69 | margin-bottom: 20px;
70 | z-index: 100000;
71 | }
72 | .vnb__popup__top {
73 | padding: 15px 24px 0;
74 | border-top: 1px solid #e0e0e0;
75 | border-left: 1px solid #e0e0e0;
76 | border-right: 1px solid #e0e0e0;
77 | border-top-right-radius: 6px;
78 | border-top-left-radius: 6px;
79 | }
80 | .vnb__popup__top__image {
81 | max-height: 27px;
82 | margin-bottom: 5px;
83 | }
84 | .vnb__popup__top__close-button {
85 | position: absolute;
86 | top: 10px;
87 | right: 10px;
88 | cursor: pointer;
89 | border: 0;
90 | background: transparent;
91 | }
92 | .vnb__popup__top__close-button:hover {
93 | opacity: 0.75;
94 | }
95 | .vnb__popup__top__close-button__image {
96 | max-height: 15px;
97 | }
98 | .vnb__popup__top__close-button svg {
99 | width: auto;
100 | }
101 | .vnb__popup__bottom {
102 | background: #fff;
103 | padding: 10px 0 10px;
104 | border-left: 1px solid #e0e0e0;
105 | border-right: 1px solid #e0e0e0;
106 | border-bottom: 1px solid #e0e0e0;
107 | border-bottom-right-radius: 6px;
108 | border-bottom-left-radius: 6px;
109 | }
110 | .vnb__popup__bottom__custom-section {
111 | padding: 12px 24px;
112 | }
113 | .vnb__popup__bottom__menu-options {
114 | list-style-type: none;
115 | padding-left: 0;
116 | display: flex;
117 | flex-direction: column;
118 | }
119 | .vnb__popup__bottom__menu-options__option:not(:last-child) {
120 | margin-bottom: 10px;
121 | }
122 | .vnb__popup__bottom__menu-options__option__link {
123 | padding: 12px 24px;
124 | color: #595959;
125 | font-weight: 500;
126 | display: flex;
127 | flex-direction: row;
128 | justify-content: flex-start;
129 | align-items: center;
130 | transition: color 0.2s ease-in, background 0.2s ease-in, border 0.2s ease-in;
131 | border-left: 2px solid #fff;
132 | width: 100%;
133 | }
134 | .vnb__popup__bottom__menu-options__option__link:hover {
135 | color: #333;
136 | text-decoration: none;
137 | background: #f3f3f3;
138 | border-left: 2px solid #007aff;
139 | }
140 | .vnb__popup__bottom__menu-options__option__link--no-highlight {
141 | padding: 12px 24px 6px;
142 | font-weight: 400;
143 | font-size: 0.8rem;
144 | color: #757575;
145 | }
146 | .vnb__popup__bottom__menu-options__option__link--no-highlight:hover {
147 | color: #757575;
148 | background: #fff;
149 | border-left: 2px solid #fff;
150 | }
151 | .vnb__popup__bottom__menu-options__option__link__icon svg {
152 | max-height: 16px;
153 | max-width: 16px;
154 | }
155 | .vnb__popup__bottom__menu-options__option__link__icon--left {
156 | margin-right: 5px;
157 | }
158 | .vnb__popup__bottom__menu-options__option__link__icon--right {
159 | margin-left: 5px;
160 | }
161 | .vnb__popup__bottom__sub-menu-options {
162 | display: flex;
163 | flex-direction: row;
164 | flex-wrap: wrap;
165 | width: 100%;
166 | font-size: 0.9rem;
167 | }
168 | .vnb__popup__bottom__sub-menu-options__option {
169 | width: 100%;
170 | }
171 | .vnb__popup__bottom__sub-menu-options__option__link {
172 | padding: 6px 24px;
173 | width: 100%;
174 | display: block;
175 | color: #595959;
176 | font-weight: 500;
177 | transition: color 0.2s ease-in, background 0.2s ease-in, border 0.2s ease-in;
178 | border-left: 2px solid #fff;
179 | }
180 | .vnb__popup__bottom__sub-menu-options__option__link:hover {
181 | color: #333;
182 | text-decoration: none;
183 | background: #eee;
184 | border-left: 2px solid #333;
185 | }
186 | .vnb__popup__bottom__sub-menu-options__option__link__sub-text {
187 | margin-top: 5px;
188 | display: block;
189 | font-size: 0.75rem;
190 | color: #8c8c8c;
191 | }
192 |
193 | .vnb-image {
194 | max-width: 100%;
195 | height: auto;
196 | }
197 |
198 | .vnb__brand-image-wrapper {
199 | padding-left: 10px;
200 | }
201 | .vnb__brand-image-wrapper__link__image {
202 | max-height: 30px;
203 | }
204 |
205 | .vnb-image {
206 | max-width: 100%;
207 | height: auto;
208 | }
209 |
210 | .vnb__menu-options__option__link {
211 | cursor: pointer;
212 | font-weight: 500;
213 | color: #595959;
214 | transition: color 0.2s ease-in;
215 | display: flex;
216 | flex-direction: row;
217 | align-items: center;
218 | justify-content: center;
219 | font-size: 0.9rem;
220 | }
221 | .vnb__menu-options__option__link:hover {
222 | color: #333;
223 | text-decoration: none;
224 | }
225 | .vnb__menu-options__option__link__icon svg {
226 | max-height: 20px;
227 | }
228 | .vnb__menu-options__option__link__icon--left {
229 | margin-right: 5px;
230 | }
231 | .vnb__menu-options__option__link__icon--right {
232 | margin-left: 5px;
233 | }
234 | .vnb__menu-options__option__arrow {
235 | max-height: 5px;
236 | max-width: 25px;
237 | transition: transform 0.2s ease-in-out;
238 | }
239 | .vnb__menu-options__option__arrow--hover {
240 | transform: rotate(180deg);
241 | }
242 | .vnb__sub-menu-options {
243 | background: #fff;
244 | max-width: 500px;
245 | display: flex;
246 | flex-direction: column;
247 | justify-content: center;
248 | align-items: center;
249 | border-radius: 4px;
250 | padding: 10px 0;
251 | }
252 | .vnb__sub-menu-options__option {
253 | min-width: 250px;
254 | max-width: 300px;
255 | }
256 | .vnb__sub-menu-options__option__link {
257 | padding: 12px 12px;
258 | width: 100%;
259 | display: flex;
260 | flex-direction: row;
261 | justify-content: center;
262 | align-items: center;
263 | color: #595959;
264 | transition: color 0.2s ease-in, background 0.2s ease-in, border 0.2s ease-in;
265 | border-left: 2px solid #fff;
266 | }
267 | .vnb__sub-menu-options__option__link:hover {
268 | color: #333;
269 | text-decoration: none;
270 | background: #f3f3f3;
271 | border-left: 2px solid #007aff;
272 | cursor: pointer;
273 | }
274 | .vnb__sub-menu-options__option__link__icon svg {
275 | max-height: 40px;
276 | }
277 | .vnb__sub-menu-options__option__link__icon--left {
278 | margin-right: 15px;
279 | }
280 | .vnb__sub-menu-options__option__link__icon--right {
281 | margin-left: 15px;
282 | }
283 | .vnb__sub-menu-options__option__link__text-wrapper {
284 | width: 100%;
285 | }
286 | .vnb__sub-menu-options__option__link__text-wrapper__text {
287 | display: block;
288 | text-align: left;
289 | }
290 | .vnb__sub-menu-options__option__link__text-wrapper__sub-text {
291 | margin-top: 5px;
292 | display: block;
293 | font-size: 0.8rem;
294 | text-align: left;
295 | color: #8c8c8c;
296 | }
297 | .vnb__sub-menu-options__option__hr {
298 | margin-top: 10px;
299 | margin-bottom: 10px;
300 | border-color: rgba(0, 0, 0, 0.1);
301 | }
302 |
303 | .vnb__menu-options__option__button {
304 | display: flex;
305 | flex-direction: row;
306 | justify-content: center;
307 | align-items: center;
308 | font-weight: 400;
309 | color: #fff;
310 | text-align: center;
311 | vertical-align: middle;
312 | user-select: none;
313 | font-size: 0.9rem;
314 | line-height: 1;
315 | border-radius: 0.25rem;
316 | text-transform: uppercase;
317 | letter-spacing: 1px;
318 | padding: 0.5rem 1rem;
319 | transition: background 0.2s ease-in;
320 | }
321 | .vnb__menu-options__option__button__icon svg {
322 | max-height: 16px;
323 | max-width: 16px;
324 | }
325 | .vnb__menu-options__option__button__icon--left {
326 | margin-right: 5px;
327 | }
328 | .vnb__menu-options__option__button__icon--right {
329 | margin-left: 5px;
330 | }
331 |
332 | .vnb-button {
333 | background: #007aff;
334 | }
335 | .vnb-button:hover {
336 | color: #fff;
337 | background: #0062cc;
338 | text-decoration: none;
339 | }
340 |
341 | .vnb__menu-options__option__spacer {
342 | width: 30px;
343 | }
344 |
345 | .tippy-box[data-animation=scale][data-placement^=top] {
346 | transform-origin: bottom;
347 | }
348 |
349 | .tippy-box[data-animation=scale][data-placement^=bottom] {
350 | transform-origin: top;
351 | }
352 |
353 | .tippy-box[data-animation=scale][data-placement^=left] {
354 | transform-origin: right;
355 | }
356 |
357 | .tippy-box[data-animation=scale][data-placement^=right] {
358 | transform-origin: left;
359 | }
360 |
361 | .tippy-box[data-animation=scale][data-state=hidden] {
362 | transform: scale(0.5);
363 | opacity: 0;
364 | }
365 |
366 | .tippy-box[data-animation=shift-toward][data-state=hidden] {
367 | opacity: 0;
368 | }
369 |
370 | .tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=top] {
371 | transform: translateY(-10px);
372 | }
373 |
374 | .tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=bottom] {
375 | transform: translateY(10px);
376 | }
377 |
378 | .tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=left] {
379 | transform: translateX(-10px);
380 | }
381 |
382 | .tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=right] {
383 | transform: translateX(10px);
384 | }
385 |
386 | .tippy-box[data-animation=perspective][data-placement^=top] {
387 | transform-origin: bottom;
388 | }
389 |
390 | .tippy-box[data-animation=perspective][data-placement^=top][data-state=visible] {
391 | transform: perspective(700px);
392 | }
393 |
394 | .tippy-box[data-animation=perspective][data-placement^=top][data-state=hidden] {
395 | transform: perspective(700px) translateY(8px) rotateX(60deg);
396 | }
397 |
398 | .tippy-box[data-animation=perspective][data-placement^=bottom] {
399 | transform-origin: top;
400 | }
401 |
402 | .tippy-box[data-animation=perspective][data-placement^=bottom][data-state=visible] {
403 | transform: perspective(700px);
404 | }
405 |
406 | .tippy-box[data-animation=perspective][data-placement^=bottom][data-state=hidden] {
407 | transform: perspective(700px) translateY(-8px) rotateX(-60deg);
408 | }
409 |
410 | .tippy-box[data-animation=perspective][data-placement^=left] {
411 | transform-origin: right;
412 | }
413 |
414 | .tippy-box[data-animation=perspective][data-placement^=left][data-state=visible] {
415 | transform: perspective(700px);
416 | }
417 |
418 | .tippy-box[data-animation=perspective][data-placement^=left][data-state=hidden] {
419 | transform: perspective(700px) translateX(8px) rotateY(-60deg);
420 | }
421 |
422 | .tippy-box[data-animation=perspective][data-placement^=right] {
423 | transform-origin: left;
424 | }
425 |
426 | .tippy-box[data-animation=perspective][data-placement^=right][data-state=visible] {
427 | transform: perspective(700px);
428 | }
429 |
430 | .tippy-box[data-animation=perspective][data-placement^=right][data-state=hidden] {
431 | transform: perspective(700px) translateX(-8px) rotateY(60deg);
432 | }
433 |
434 | .tippy-box[data-animation=perspective][data-state=hidden] {
435 | opacity: 0;
436 | }
437 |
438 | .tippy-box[data-theme~=light] {
439 | color: #26323d;
440 | box-shadow: 0 0 20px 4px rgba(154, 161, 177, 0.15), 0 4px 80px -8px rgba(36, 40, 47, 0.25), 0 4px 4px -2px rgba(91, 94, 105, 0.15);
441 | background-color: #fff;
442 | }
443 |
444 | .tippy-box[data-theme~=light][data-placement^=top] > .tippy-arrow:before {
445 | border-top-color: #fff;
446 | }
447 |
448 | .tippy-box[data-theme~=light][data-placement^=bottom] > .tippy-arrow:before {
449 | border-bottom-color: #fff;
450 | }
451 |
452 | .tippy-box[data-theme~=light][data-placement^=left] > .tippy-arrow:before {
453 | border-left-color: #fff;
454 | }
455 |
456 | .tippy-box[data-theme~=light][data-placement^=right] > .tippy-arrow:before {
457 | border-right-color: #fff;
458 | }
459 |
460 | .tippy-box[data-theme~=light] > .tippy-backdrop {
461 | background-color: #fff;
462 | }
463 |
464 | .tippy-box[data-theme~=light] > .tippy-svg-arrow {
465 | fill: #fff;
466 | }
467 |
468 | .tippy-box[data-animation=shift-away][data-state=hidden] {
469 | opacity: 0;
470 | }
471 |
472 | .tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=top] {
473 | transform: translateY(10px);
474 | }
475 |
476 | .tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=bottom] {
477 | transform: translateY(-10px);
478 | }
479 |
480 | .tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=left] {
481 | transform: translateX(10px);
482 | }
483 |
484 | .tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=right] {
485 | transform: translateX(-10px);
486 | }
--------------------------------------------------------------------------------
/dist/vue-navigation-bar.esm.js:
--------------------------------------------------------------------------------
1 | import { VueScreenSizeMixin } from 'vue-screen-size';
2 | import { resolveComponent, openBlock, createElementBlock, Fragment, createBlock, mergeProps, withCtx, renderSlot, createCommentVNode, createVNode, normalizeStyle, createElementVNode, normalizeClass, createTextVNode, toDisplayString, renderList, withKeys } from 'vue';
3 | import tippy, { hideAll } from 'tippy.js';
4 |
5 | // https://stackoverflow.com/a/2117523/8014660
6 | function uuidV4() {
7 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
8 | var r = (Math.random() * 16) | 0,
9 | v = c == 'x' ? r : (r & 0x3) | 0x8;
10 | return v.toString(16);
11 | });
12 | }
13 |
14 | var script$8 = {
15 | name: 'dynamic-link',
16 | props: {
17 | isUsingVueRouter: {
18 | type: Boolean,
19 | required: true,
20 | },
21 | path: {
22 | type: [String, Object],
23 | required: false,
24 | },
25 | isLinkAction: {
26 | type: Boolean,
27 | required: true,
28 | },
29 | },
30 | computed: {
31 | localPath: function localPath() {
32 | if (!this.path) { return; }
33 |
34 | return typeof this.path === 'string' ? this.path : Object.assign({}, this.path);
35 | },
36 | },
37 | };
38 |
39 | var _hoisted_1$7 = ["href"];
40 |
41 | function render$8(_ctx, _cache, $props, $setup, $data, $options) {
42 | var _component_router_link = resolveComponent("router-link");
43 |
44 | return (openBlock(), createElementBlock(Fragment, null, [
45 | ($props.isUsingVueRouter && $props.path)
46 | ? (openBlock(), createBlock(_component_router_link, mergeProps({ key: 0 }, _ctx.$attrs, { to: $options.localPath }), {
47 | default: withCtx(function () { return [
48 | renderSlot(_ctx.$slots, "content")
49 | ]; }),
50 | _: 3 /* FORWARDED */
51 | }, 16 /* FULL_PROPS */, ["to"]))
52 | : createCommentVNode("v-if", true),
53 | (!$props.isUsingVueRouter && !$props.isLinkAction && $props.path)
54 | ? (openBlock(), createElementBlock("a", mergeProps({ key: 1 }, _ctx.$attrs, { href: $props.path }), [
55 | renderSlot(_ctx.$slots, "content")
56 | ], 16 /* FULL_PROPS */, _hoisted_1$7))
57 | : createCommentVNode("v-if", true),
58 | ($props.isLinkAction)
59 | ? (openBlock(), createElementBlock("a", mergeProps({ key: 2 }, _ctx.$attrs, { href: "javascript:void(0);" }), [
60 | renderSlot(_ctx.$slots, "content")
61 | ], 16 /* FULL_PROPS */))
62 | : createCommentVNode("v-if", true)
63 | ], 64 /* STABLE_FRAGMENT */))
64 | }
65 |
66 | script$8.render = render$8;
67 | script$8.__file = "src/components/DynamicLink.vue";
68 |
69 | var script$7 = {
70 | name: 'brand-image',
71 | props: {
72 | options: {
73 | type: Object,
74 | required: true,
75 | },
76 | },
77 | data: function data () {
78 | return {};
79 | },
80 | components: {
81 | DynamicLink: script$8,
82 | },
83 | emits: [
84 | 'vnb-item-clicked' ]
85 | };
86 |
87 | var _hoisted_1$6 = { class: "vnb__brand-image-wrapper" };
88 | var _hoisted_2$4 = ["src", "alt"];
89 |
90 | function render$7(_ctx, _cache, $props, $setup, $data, $options) {
91 | var _component_dynamic_link = resolveComponent("dynamic-link");
92 |
93 | return (openBlock(), createElementBlock("div", _hoisted_1$6, [
94 | createVNode(_component_dynamic_link, {
95 | path: $props.options.brandImagePath,
96 | isUsingVueRouter: $props.options.isUsingVueRouter,
97 | class: "vnb__brand-image-wrapper__link",
98 | "aria-label": "Homepage",
99 | isLinkAction: false,
100 | onClick: _cache[0] || (_cache[0] = function ($event) { return (_ctx.$emit('vnb-item-clicked', 'brand-image')); })
101 | }, {
102 | content: withCtx(function () { return [
103 | ($props.options.brandImage)
104 | ? (openBlock(), createElementBlock("img", {
105 | key: 0,
106 | src: $props.options.brandImage,
107 | alt: $props.options.brandImageAltText,
108 | class: "vnb-image vnb__brand-image-wrapper__link__image"
109 | }, null, 8 /* PROPS */, _hoisted_2$4))
110 | : createCommentVNode("v-if", true)
111 | ]; }),
112 | _: 1 /* STABLE */
113 | }, 8 /* PROPS */, ["path", "isUsingVueRouter"])
114 | ]))
115 | }
116 |
117 | script$7.render = render$7;
118 | script$7.__file = "src/components/BrandImage.vue";
119 |
120 | var script$6 = {
121 | name: 'collapse-button',
122 | mixins: [VueScreenSizeMixin],
123 | props: {
124 | options: {
125 | type: Object,
126 | required: true,
127 | },
128 | menuIsVisible: {
129 | type: Boolean,
130 | required: true,
131 | },
132 | },
133 | data: function data () {
134 | return {};
135 | },
136 | methods: {
137 | collapseButtonClicked: function collapseButtonClicked () {
138 | this.$emit('collapse-button-clicked');
139 | },
140 | },
141 | emits: [
142 | 'collapse-button-clicked' ]
143 | };
144 |
145 | var _hoisted_1$5 = ["aria-expanded"];
146 | var _hoisted_2$3 = ["src"];
147 | var _hoisted_3$2 = /*#__PURE__*/createElementVNode("title", null, "Menu", -1 /* HOISTED */);
148 | var _hoisted_4$2 = /*#__PURE__*/createElementVNode("g", { transform: "matrix(.1 0 0 -.1 0 100)" }, [
149 | /*#__PURE__*/createElementVNode("path", { d: "m0 850v-40h500 500v40 40h-500-500z" }),
150 | /*#__PURE__*/createElementVNode("path", { d: "m0 495v-45h500 500v45 45h-500-500z" }),
151 | /*#__PURE__*/createElementVNode("path", { d: "m0 140v-40h500 500v40 40h-500-500z" })
152 | ], -1 /* HOISTED */);
153 | var _hoisted_5$2 = [
154 | _hoisted_3$2,
155 | _hoisted_4$2
156 | ];
157 |
158 | function render$6(_ctx, _cache, $props, $setup, $data, $options) {
159 | return (_ctx.$vssWidth < $props.options.mobileBreakpoint)
160 | ? (openBlock(), createElementBlock("button", {
161 | key: 0,
162 | class: "vnb__collapse-button",
163 | onClick: _cache[0] || (_cache[0] = function () {
164 | var args = [], len = arguments.length;
165 | while ( len-- ) args[ len ] = arguments[ len ];
166 |
167 | return ($options.collapseButtonClicked && $options.collapseButtonClicked.apply($options, args));
168 | }),
169 | type: "button",
170 | "aria-expanded": $props.menuIsVisible ? 'true' : 'false'
171 | }, [
172 | ($props.options.collapseButtonImageOpen)
173 | ? (openBlock(), createElementBlock("img", {
174 | key: 0,
175 | src: $props.options.collapseButtonImageOpen,
176 | alt: 'Menu',
177 | class: "vnb__collapse-button__image"
178 | }, null, 8 /* PROPS */, _hoisted_2$3))
179 | : (openBlock(), createElementBlock("svg", {
180 | key: 1,
181 | height: "100pt",
182 | preserveAspectRatio: "xMidYMid meet",
183 | viewBox: "0 0 100 100",
184 | width: "100pt",
185 | xmlns: "http://www.w3.org/2000/svg",
186 | class: "vnb__collapse-button__image",
187 | style: normalizeStyle({fill: $props.options.collapseButtonOpenColor})
188 | }, _hoisted_5$2, 4 /* STYLE */))
189 | ], 8 /* PROPS */, _hoisted_1$5))
190 | : createCommentVNode("v-if", true)
191 | }
192 |
193 | script$6.render = render$6;
194 | script$6.__file = "src/components/CollapseButton.vue";
195 |
196 | var script$5 = {
197 | name: 'desktop-menu-item-button',
198 | props: {
199 | option: {
200 | type: Object,
201 | required: true,
202 | },
203 | options: {
204 | type: Object,
205 | required: true,
206 | },
207 | },
208 | data: function data () {
209 | return {};
210 | },
211 | components: {
212 | DynamicLink: script$8,
213 | },
214 | emits: [
215 | 'vnb-item-clicked' ]
216 | };
217 |
218 | var _hoisted_1$4 = ["innerHTML"];
219 | var _hoisted_2$2 = ["innerHTML"];
220 |
221 | function render$5(_ctx, _cache, $props, $setup, $data, $options) {
222 | var _component_dynamic_link = resolveComponent("dynamic-link");
223 |
224 | return (openBlock(), createBlock(_component_dynamic_link, {
225 | path: $props.option.path,
226 | isUsingVueRouter: $props.options.isUsingVueRouter,
227 | class: normalizeClass(['vnb__menu-options__option__button', 'vnb-button', $props.option.class]),
228 | "aria-label": $props.option.text,
229 | isLinkAction: $props.option.isLinkAction ? true : false,
230 | onClick: _cache[0] || (_cache[0] = function ($event) { return (_ctx.$emit('vnb-item-clicked', $props.option.text)); })
231 | }, {
232 | content: withCtx(function () { return [
233 | ($props.option.iconLeft)
234 | ? (openBlock(), createElementBlock("span", {
235 | key: 0,
236 | class: "vnb__menu-options__option__button__icon vnb__menu-options__option__button__icon--left",
237 | innerHTML: $props.option.iconLeft
238 | }, null, 8 /* PROPS */, _hoisted_1$4))
239 | : createCommentVNode("v-if", true),
240 | createTextVNode(" " + toDisplayString($props.option.text) + " ", 1 /* TEXT */),
241 | ($props.option.iconRight)
242 | ? (openBlock(), createElementBlock("span", {
243 | key: 1,
244 | class: "vnb__menu-options__option__button__icon vnb__menu-options__option__button__icon--right",
245 | innerHTML: $props.option.iconRight
246 | }, null, 8 /* PROPS */, _hoisted_2$2))
247 | : createCommentVNode("v-if", true)
248 | ]; }),
249 | _: 1 /* STABLE */
250 | }, 8 /* PROPS */, ["path", "isUsingVueRouter", "class", "aria-label", "isLinkAction"]))
251 | }
252 |
253 | script$5.render = render$5;
254 | script$5.__file = "src/components/DesktopMenuItemButton.vue";
255 |
256 | var script$4 = {
257 | name: 'desktop-menu-item-link',
258 | props: {
259 | option: {
260 | type: Object,
261 | required: true,
262 | },
263 | options: {
264 | type: Object,
265 | required: true,
266 | },
267 | },
268 | data: function data () {
269 | return {
270 | currentExpandedStatus: 'closed',
271 | };
272 | },
273 | computed: {
274 | isExpanded: function isExpanded () {
275 | if (this.currentExpandedStatus === 'open') {
276 | return true;
277 | }
278 |
279 | return false;
280 | },
281 | },
282 | methods: {
283 | // Each time a sub-menu-option is clicked, close all the tooltips
284 | subMenuItemSelected: function subMenuItemSelected (text) {
285 | this.closeAllTooltips();
286 | },
287 |
288 | // When we keydown tab on the last sub-menu-option, we want to close
289 | // all the tooltips
290 | subMenuItemTabbed: function subMenuItemTabbed (text) {
291 | // Let's check to see if this item is the last
292 | // item in the subMenuOptions array
293 | if (this.option.subMenuOptions[this.option.subMenuOptions.length - 1].text === text) {
294 | this.closeAllTooltips();
295 | }
296 | },
297 |
298 | menuShown: function menuShown () {
299 | this.currentExpandedStatus = 'open';
300 | },
301 | menuHidden: function menuHidden () {
302 | this.currentExpandedStatus = 'closed';
303 | },
304 |
305 | closeAllTooltips: function closeAllTooltips () {
306 | // https://atomiks.github.io/tippyjs/v6/methods/#hideall
307 | hideAll();
308 | },
309 |
310 | initTippy: function initTippy () {
311 | var this$1$1 = this;
312 |
313 | var el = document.getElementById('dropdown-menu-parent-' + this.option.id);
314 |
315 | var template = document.getElementById('sub-menu-options-' + this.option.id);
316 | template.style.display = 'block';
317 |
318 | tippy(el, {
319 | theme: 'light',
320 | content: template,
321 | interactive: true,
322 | animation: this.options.tooltipAnimationType,
323 | role: 'Menu',
324 | // trigger: 'click', // for testing
325 | trigger: 'click mouseenter focus',
326 | appendTo: 'parent',
327 | arrow: true,
328 | inertia: false,
329 | placement: this.options.tooltipPlacement,
330 | popperOptions: {
331 | modifiers: [
332 | {
333 | name: 'flip',
334 | options: {
335 | fallbackPlacements: [this.options.tooltipPlacement],
336 | },
337 | } ],
338 | },
339 | onShow: function (instance) {
340 | hideAll({exclude: instance});
341 |
342 | // fire the menuShown function
343 | this$1$1.menuShown();
344 | },
345 | onHide: function () {
346 | // fire the menuHidden function
347 | this$1$1.menuHidden();
348 | },
349 | });
350 | },
351 | },
352 | mounted: function mounted () {
353 | // Let's setup our tippy here in mounted
354 | if (this.option.subMenuOptions && this.option.subMenuOptions.length) {
355 | this.initTippy();
356 | }
357 | },
358 | components: {
359 | DynamicLink: script$8,
360 | },
361 | emits: [
362 | 'vnb-item-clicked' ]
363 | };
364 |
365 | var _hoisted_1$3 = ["innerHTML"];
366 | var _hoisted_2$1 = ["innerHTML"];
367 | var _hoisted_3$1 = ["id", "aria-expanded", "aria-label"];
368 | var _hoisted_4$1 = ["innerHTML"];
369 | var _hoisted_5$1 = ["innerHTML"];
370 | var _hoisted_6$1 = /*#__PURE__*/createElementVNode("title", null, "Toggle Arrow", -1 /* HOISTED */);
371 | var _hoisted_7$1 = /*#__PURE__*/createElementVNode("path", {
372 | d: "m12 268c-7-7-12-17-12-23 0-13 232-245 245-245 6 0 64 54 129 119 119 119 132 142 90 158-11 4-44-23-113-91-53-53-101-96-106-96-6 0-53 43-105 95s-99 95-105 95-16-5-23-12z",
373 | transform: "matrix(.1 0 0 -.1 0 28)"
374 | }, null, -1 /* HOISTED */);
375 | var _hoisted_8$1 = [
376 | _hoisted_6$1,
377 | _hoisted_7$1
378 | ];
379 | var _hoisted_9$1 = ["id"];
380 | var _hoisted_10$1 = {
381 | class: "vnb__sub-menu-options__option",
382 | tabindex: "-1"
383 | };
384 | var _hoisted_11$1 = ["innerHTML"];
385 | var _hoisted_12$1 = { class: "vnb__sub-menu-options__option__link__text-wrapper" };
386 | var _hoisted_13$1 = { class: "vnb__sub-menu-options__option__link__text-wrapper__text" };
387 | var _hoisted_14$1 = {
388 | key: 0,
389 | class: "vnb__sub-menu-options__option__link__text-wrapper__sub-text"
390 | };
391 | var _hoisted_15$1 = ["innerHTML"];
392 | var _hoisted_16$1 = {
393 | key: 1,
394 | class: "vnb__sub-menu-options__option__hr",
395 | tabindex: "-1"
396 | };
397 |
398 | function render$4(_ctx, _cache, $props, $setup, $data, $options) {
399 | var _component_dynamic_link = resolveComponent("dynamic-link");
400 |
401 | return (!$props.option.subMenuOptions || !$props.option.subMenuOptions.length)
402 | ? (openBlock(), createBlock(_component_dynamic_link, {
403 | key: 0,
404 | path: $props.option.path,
405 | isUsingVueRouter: $props.options.isUsingVueRouter,
406 | class: normalizeClass(['vnb__menu-options__option__link', $props.option.class]),
407 | "aria-label": $props.option.text,
408 | tabindex: "0",
409 | isLinkAction: $props.option.isLinkAction ? true : false,
410 | onClick: _cache[0] || (_cache[0] = function ($event) { return (_ctx.$emit('vnb-item-clicked', $props.option.text)); })
411 | }, {
412 | content: withCtx(function () { return [
413 | ($props.option.iconLeft)
414 | ? (openBlock(), createElementBlock("span", {
415 | key: 0,
416 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--left",
417 | innerHTML: $props.option.iconLeft
418 | }, null, 8 /* PROPS */, _hoisted_1$3))
419 | : createCommentVNode("v-if", true),
420 | createTextVNode(" " + toDisplayString($props.option.text) + " ", 1 /* TEXT */),
421 | ($props.option.iconRight)
422 | ? (openBlock(), createElementBlock("span", {
423 | key: 1,
424 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--right",
425 | innerHTML: $props.option.iconRight
426 | }, null, 8 /* PROPS */, _hoisted_2$1))
427 | : createCommentVNode("v-if", true)
428 | ]; }),
429 | _: 1 /* STABLE */
430 | }, 8 /* PROPS */, ["path", "isUsingVueRouter", "class", "aria-label", "isLinkAction"]))
431 | : (openBlock(), createElementBlock("span", {
432 | key: 1,
433 | class: normalizeClass(['vnb__menu-options__option__link', $props.option.class]),
434 | id: 'dropdown-menu-parent-' + $props.option.id,
435 | "aria-haspopup": "true",
436 | "aria-expanded": $options.isExpanded ? 'true' : 'false',
437 | "aria-label": $props.option.text,
438 | tabindex: "0"
439 | }, [
440 | ($props.option.iconLeft)
441 | ? (openBlock(), createElementBlock("span", {
442 | key: 0,
443 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--left",
444 | innerHTML: $props.option.iconLeft
445 | }, null, 8 /* PROPS */, _hoisted_4$1))
446 | : createCommentVNode("v-if", true),
447 | createTextVNode(" " + toDisplayString($props.option.text) + " ", 1 /* TEXT */),
448 | ($props.option.iconRight)
449 | ? (openBlock(), createElementBlock("span", {
450 | key: 1,
451 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--right",
452 | innerHTML: $props.option.iconRight
453 | }, null, 8 /* PROPS */, _hoisted_5$1))
454 | : createCommentVNode("v-if", true),
455 | (openBlock(), createElementBlock("svg", {
456 | height: "28pt",
457 | preserveAspectRatio: "xMidYMid meet",
458 | viewBox: "0 0 49 28",
459 | width: "49pt",
460 | xmlns: "http://www.w3.org/2000/svg",
461 | style: normalizeStyle({fill: $props.option.arrowColor}),
462 | class: normalizeClass([
463 | 'vnb__menu-options__option__arrow',
464 | {'vnb__menu-options__option__arrow--hover': $options.isExpanded} ])
465 | }, _hoisted_8$1, 6 /* CLASS, STYLE */)),
466 | ($props.option.type === 'link')
467 | ? (openBlock(), createElementBlock("div", {
468 | key: 2,
469 | class: "vnb__sub-menu-options",
470 | id: 'sub-menu-options-' + $props.option.id
471 | }, [
472 | createElementVNode("div", _hoisted_10$1, [
473 | (openBlock(true), createElementBlock(Fragment, null, renderList($props.option.subMenuOptions, function (subOption, index) {
474 | return (openBlock(), createElementBlock("div", null, [
475 | (subOption.type === 'link')
476 | ? (openBlock(), createBlock(_component_dynamic_link, {
477 | path: subOption.path,
478 | isUsingVueRouter: $props.options.isUsingVueRouter,
479 | key: index,
480 | class: "vnb__sub-menu-options__option__link",
481 | onClick: function ($event) {
482 | $options.subMenuItemSelected(subOption.text);
483 | _ctx.$emit('vnb-item-clicked', subOption.text);
484 | },
485 | "aria-label": subOption.text,
486 | tabindex: "0",
487 | onKeydown: withKeys(function ($event) { return ($options.subMenuItemTabbed(subOption.text)); }, ["tab"]),
488 | isLinkAction: subOption.isLinkAction ? true : false
489 | }, {
490 | content: withCtx(function () { return [
491 | (subOption.iconLeft)
492 | ? (openBlock(), createElementBlock("span", {
493 | key: 0,
494 | class: "vnb__sub-menu-options__option__link__icon vnb__sub-menu-options__option__link__icon--left",
495 | innerHTML: subOption.iconLeft
496 | }, null, 8 /* PROPS */, _hoisted_11$1))
497 | : createCommentVNode("v-if", true),
498 | createElementVNode("span", _hoisted_12$1, [
499 | createElementVNode("span", _hoisted_13$1, toDisplayString(subOption.text), 1 /* TEXT */),
500 | (subOption.subText)
501 | ? (openBlock(), createElementBlock("span", _hoisted_14$1, toDisplayString(subOption.subText), 1 /* TEXT */))
502 | : createCommentVNode("v-if", true)
503 | ]),
504 | (subOption.iconRight)
505 | ? (openBlock(), createElementBlock("span", {
506 | key: 1,
507 | class: "vnb__sub-menu-options__option__link__icon vnb__sub-menu-options__option__link__icon--right",
508 | innerHTML: subOption.iconRight
509 | }, null, 8 /* PROPS */, _hoisted_15$1))
510 | : createCommentVNode("v-if", true)
511 | ]; }),
512 | _: 2 /* DYNAMIC */
513 | }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["path", "isUsingVueRouter", "onClick", "aria-label", "onKeydown", "isLinkAction"]))
514 | : (openBlock(), createElementBlock("hr", _hoisted_16$1))
515 | ]))
516 | }), 256 /* UNKEYED_FRAGMENT */))
517 | ])
518 | ], 8 /* PROPS */, _hoisted_9$1))
519 | : createCommentVNode("v-if", true)
520 | ], 10 /* CLASS, PROPS */, _hoisted_3$1))
521 | }
522 |
523 | script$4.render = render$4;
524 | script$4.__file = "src/components/DesktopMenuItemLink.vue";
525 |
526 | var script$3 = {
527 | name: 'desktop-menu-item-spacer',
528 | props: {
529 | option: {
530 | type: Object,
531 | required: true
532 | }
533 | },
534 | data: function data () {
535 | return {
536 | }
537 | }
538 | };
539 |
540 | var _hoisted_1$2 = { class: "vnb__menu-options__option__spacer" };
541 |
542 | function render$3(_ctx, _cache, $props, $setup, $data, $options) {
543 | return (openBlock(), createElementBlock("div", _hoisted_1$2))
544 | }
545 |
546 | script$3.render = render$3;
547 | script$3.__file = "src/components/DesktopMenuItemSpacer.vue";
548 |
549 | var script$2 = {
550 | name: 'menu-options',
551 | mixins: [VueScreenSizeMixin],
552 | props: {
553 | options: {
554 | type: Object,
555 | required: true,
556 | },
557 | type: {
558 | type: String,
559 | required: true,
560 | },
561 | },
562 | data: function data () {
563 | return {};
564 | },
565 | methods: {
566 | vnbItemClicked: function vnbItemClicked (text) {
567 | this.$emit('vnb-item-clicked', text);
568 | },
569 | },
570 | components: {
571 | DesktopMenuItemLink: script$4,
572 | DesktopMenuItemButton: script$5,
573 | DesktopMenuItemSpacer: script$3,
574 | },
575 | emits: [
576 | 'vnb-item-clicked' ]
577 | };
578 |
579 | function render$2(_ctx, _cache, $props, $setup, $data, $options) {
580 | var _component_desktop_menu_item_link = resolveComponent("desktop-menu-item-link");
581 | var _component_desktop_menu_item_button = resolveComponent("desktop-menu-item-button");
582 | var _component_desktop_menu_item_spacer = resolveComponent("desktop-menu-item-spacer");
583 |
584 | return (_ctx.$vssWidth > $props.options.mobileBreakpoint)
585 | ? (openBlock(), createElementBlock("div", {
586 | key: 0,
587 | class: normalizeClass([
588 | 'vnb__menu-options',
589 | {'vnb__menu-options--left': $props.type === 'left'},
590 | {'vnb__menu-options--right': $props.type === 'right'} ])
591 | }, [
592 | (openBlock(true), createElementBlock(Fragment, null, renderList($props.type === 'left'
593 | ? $props.options.menuOptionsLeft
594 | : $props.options.menuOptionsRight, function (option, index) {
595 | return (openBlock(), createElementBlock("div", {
596 | key: index,
597 | class: "vnb__menu-options__option"
598 | }, [
599 | (option.type === 'link')
600 | ? (openBlock(), createBlock(_component_desktop_menu_item_link, {
601 | key: 0,
602 | class: normalizeClass(option.class),
603 | option: option,
604 | options: $props.options,
605 | onVnbItemClicked: $options.vnbItemClicked
606 | }, null, 8 /* PROPS */, ["class", "option", "options", "onVnbItemClicked"]))
607 | : (option.type === 'button')
608 | ? (openBlock(), createBlock(_component_desktop_menu_item_button, {
609 | key: 1,
610 | option: option,
611 | options: $props.options,
612 | onVnbItemClicked: $options.vnbItemClicked
613 | }, null, 8 /* PROPS */, ["option", "options", "onVnbItemClicked"]))
614 | : (openBlock(), createBlock(_component_desktop_menu_item_spacer, {
615 | key: 2,
616 | option: option
617 | }, null, 8 /* PROPS */, ["option"]))
618 | ]))
619 | }), 128 /* KEYED_FRAGMENT */))
620 | ], 2 /* CLASS */))
621 | : createCommentVNode("v-if", true)
622 | }
623 |
624 | script$2.render = render$2;
625 | script$2.__file = "src/components/MenuOptions.vue";
626 |
627 | var script$1 = {
628 | name: 'popup',
629 | props: {
630 | options: {
631 | type: Object,
632 | required: true,
633 | },
634 | menuIsVisible: {
635 | type: Boolean,
636 | required: true,
637 | },
638 | },
639 | data: function data() {
640 | return {};
641 | },
642 | computed: {
643 | combinedMenuItems: function combinedMenuItems() {
644 | var combinedArray = this.options.menuOptionsLeft.concat(this.options.menuOptionsRight);
645 | return combinedArray;
646 | },
647 | },
648 | methods: {
649 | closeButtonClicked: function closeButtonClicked() {
650 | this.$emit('close-button-clicked');
651 | },
652 | itemSelected: function itemSelected(option) {
653 | this.$emit('vnb-item-clicked', option.text);
654 | this.closeButtonClicked();
655 | },
656 | },
657 | components: {
658 | DynamicLink: script$8,
659 | },
660 | emits: ['close-button-clicked', 'vnb-item-clicked'],
661 | };
662 |
663 | var _hoisted_1$1 = {
664 | key: 0,
665 | class: "vnb__popup"
666 | };
667 | var _hoisted_2 = { class: "vnb__popup__top" };
668 | var _hoisted_3 = ["src", "alt"];
669 | var _hoisted_4 = ["aria-expanded"];
670 | var _hoisted_5 = ["src"];
671 | var _hoisted_6 = /*#__PURE__*/createElementVNode("title", null, "Close button", -1 /* HOISTED */);
672 | var _hoisted_7 = /*#__PURE__*/createElementVNode("path", {
673 | d: "m42 967c-12-13-22-27-22-33 0-5 93-102 207-216l208-208-208-208c-114-114-207-214-207-223 0-8 11-26 25-39l26-24 214 214 215 215 215-215 214-214 26 24c14 13 25 28 25 34s-92 103-205 216-205 209-205 215 92 102 205 215 205 210 205 216c0 12-42 54-55 54-5 0-104-94-220-210l-210-210-210 210c-115 116-212 210-216 210-3 0-15-10-27-23z",
674 | transform: "matrix(.1 0 0 -.1 0 100)"
675 | }, null, -1 /* HOISTED */);
676 | var _hoisted_8 = [
677 | _hoisted_6,
678 | _hoisted_7
679 | ];
680 | var _hoisted_9 = { class: "vnb__popup__bottom" };
681 | var _hoisted_10 = {
682 | key: 0,
683 | class: "vnb__popup__bottom__custom-section"
684 | };
685 | var _hoisted_11 = { class: "vnb__popup__bottom__menu-options" };
686 | var _hoisted_12 = ["innerHTML"];
687 | var _hoisted_13 = ["innerHTML"];
688 | var _hoisted_14 = {
689 | key: 1,
690 | class: "vnb__popup__bottom__menu-options__option__link vnb__popup__bottom__menu-options__option__link--no-highlight"
691 | };
692 | var _hoisted_15 = { class: "vnb__popup__bottom__sub-menu-options" };
693 | var _hoisted_16 = { class: "vnb__popup__bottom__sub-menu-options__option__link__sub-text" };
694 |
695 | function render$1(_ctx, _cache, $props, $setup, $data, $options) {
696 | var _component_dynamic_link = resolveComponent("dynamic-link");
697 |
698 | return ($props.menuIsVisible)
699 | ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
700 | createElementVNode("div", _hoisted_2, [
701 | ($props.options.showBrandImageInMobilePopup && $props.options.brandImage)
702 | ? (openBlock(), createElementBlock("img", {
703 | key: 0,
704 | src: $props.options.brandImage,
705 | alt: $props.options.brandImageAltText,
706 | class: "vnb-image vnb__popup__top__image"
707 | }, null, 8 /* PROPS */, _hoisted_3))
708 | : createCommentVNode("v-if", true),
709 | createElementVNode("button", {
710 | class: "vnb__popup__top__close-button",
711 | onClick: _cache[0] || (_cache[0] = function () {
712 | var args = [], len = arguments.length;
713 | while ( len-- ) args[ len ] = arguments[ len ];
714 |
715 | return ($options.closeButtonClicked && $options.closeButtonClicked.apply($options, args));
716 | }),
717 | "aria-label": "Close Button",
718 | title: "Close",
719 | "aria-expanded": $props.menuIsVisible ? 'true' : 'false'
720 | }, [
721 | ($props.options.collapseButtonImageClose)
722 | ? (openBlock(), createElementBlock("img", {
723 | key: 0,
724 | src: $props.options.collapseButtonImageClose,
725 | alt: 'Close button',
726 | class: "vnb__popup__top__close-button__image"
727 | }, null, 8 /* PROPS */, _hoisted_5))
728 | : (openBlock(), createElementBlock("svg", {
729 | key: 1,
730 | height: "100pt",
731 | preserveAspectRatio: "xMidYMid meet",
732 | viewBox: "0 0 100 100",
733 | width: "100pt",
734 | xmlns: "http://www.w3.org/2000/svg",
735 | class: "vnb__popup__top__close-button__image",
736 | style: normalizeStyle({ fill: $props.options.collapseButtonCloseColor })
737 | }, _hoisted_8, 4 /* STYLE */))
738 | ], 8 /* PROPS */, _hoisted_4)
739 | ]),
740 | createElementVNode("div", _hoisted_9, [
741 | (!!this.$slots['custom-section'])
742 | ? (openBlock(), createElementBlock("div", _hoisted_10, [
743 | renderSlot(_ctx.$slots, "custom-section")
744 | ]))
745 | : createCommentVNode("v-if", true),
746 | createElementVNode("ul", _hoisted_11, [
747 | (openBlock(true), createElementBlock(Fragment, null, renderList($options.combinedMenuItems, function (option, index) {
748 | return (openBlock(), createElementBlock("li", {
749 | key: index,
750 | class: "vnb__popup__bottom__menu-options__option"
751 | }, [
752 | (!option.subMenuOptions)
753 | ? (openBlock(), createBlock(_component_dynamic_link, {
754 | key: 0,
755 | path: option.path,
756 | isUsingVueRouter: $props.options.isUsingVueRouter,
757 | class: normalizeClass(['vnb__popup__bottom__menu-options__option__link', option.class]),
758 | onClick: function ($event) { return ($options.itemSelected(option)); },
759 | "aria-label": option.text,
760 | isLinkAction: option.isLinkAction ? true : false
761 | }, {
762 | content: withCtx(function () { return [
763 | (option.iconLeft)
764 | ? (openBlock(), createElementBlock("span", {
765 | key: 0,
766 | class: "vnb__popup__bottom__menu-options__option__link__icon vnb__popup__bottom__menu-options__option__link__icon--left",
767 | innerHTML: option.iconLeft
768 | }, null, 8 /* PROPS */, _hoisted_12))
769 | : createCommentVNode("v-if", true),
770 | createTextVNode(" " + toDisplayString(option.text) + " ", 1 /* TEXT */),
771 | (option.iconRight)
772 | ? (openBlock(), createElementBlock("span", {
773 | key: 1,
774 | class: "vnb__popup__bottom__menu-options__option__link__icon vnb__popup__bottom__menu-options__option__link__icon--right",
775 | innerHTML: option.iconRight
776 | }, null, 8 /* PROPS */, _hoisted_13))
777 | : createCommentVNode("v-if", true)
778 | ]; }),
779 | _: 2 /* DYNAMIC */
780 | }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["path", "isUsingVueRouter", "class", "onClick", "aria-label", "isLinkAction"]))
781 | : (openBlock(), createElementBlock("span", _hoisted_14, toDisplayString(option.text), 1 /* TEXT */)),
782 | createElementVNode("div", _hoisted_15, [
783 | (openBlock(true), createElementBlock(Fragment, null, renderList(option.subMenuOptions, function (subOption, index) {
784 | return (openBlock(), createElementBlock("div", {
785 | key: index,
786 | class: "vnb__popup__bottom__sub-menu-options__option"
787 | }, [
788 | (subOption.type === 'link')
789 | ? (openBlock(), createBlock(_component_dynamic_link, {
790 | key: 0,
791 | path: subOption.path,
792 | isUsingVueRouter: $props.options.isUsingVueRouter,
793 | class: "vnb__popup__bottom__sub-menu-options__option__link",
794 | onClick: function ($event) { return ($options.itemSelected(subOption)); },
795 | "aria-label": subOption.text,
796 | isLinkAction: subOption.isLinkAction ? true : false
797 | }, {
798 | content: withCtx(function () { return [
799 | createTextVNode(toDisplayString(subOption.text) + " ", 1 /* TEXT */),
800 | createElementVNode("span", _hoisted_16, toDisplayString(subOption.subText), 1 /* TEXT */)
801 | ]; }),
802 | _: 2 /* DYNAMIC */
803 | }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["path", "isUsingVueRouter", "onClick", "aria-label", "isLinkAction"]))
804 | : createCommentVNode("v-if", true)
805 | ]))
806 | }), 128 /* KEYED_FRAGMENT */))
807 | ])
808 | ]))
809 | }), 128 /* KEYED_FRAGMENT */))
810 | ])
811 | ])
812 | ]))
813 | : createCommentVNode("v-if", true)
814 | }
815 |
816 | script$1.render = render$1;
817 | script$1.__file = "src/components/Popup.vue";
818 |
819 | var script = {
820 | name: 'vue-navigation-bar',
821 | mixins: [VueScreenSizeMixin],
822 | props: {
823 | options: {
824 | type: Object,
825 | required: true,
826 | },
827 | },
828 | data: function data () {
829 | return {
830 | menuIsVisible: false,
831 | };
832 | },
833 | computed: {
834 | finalOptions: function finalOptions () {
835 | // What we're doing here is giving each top-level menu-option a unique id
836 | if (this.options.menuOptionsLeft) {
837 | for (var x = 0; x < this.options.menuOptionsLeft.length; x++) {
838 | this.options.menuOptionsLeft[x].id = uuidV4();
839 | }
840 | }
841 | if (this.options.menuOptionsRight) {
842 | for (var x$1 = 0; x$1 < this.options.menuOptionsRight.length; x$1++) {
843 | this.options.menuOptionsRight[x$1].id = uuidV4();
844 | }
845 | }
846 |
847 | return {
848 | elementId: this.options.elementId ? this.options.elementId : uuidV4(),
849 | isUsingVueRouter: this.options.isUsingVueRouter ? true : false,
850 | mobileBreakpoint: this.options.mobileBreakpoint ? this.options.mobileBreakpoint : 992,
851 | brandImagePath: this.options.brandImagePath ? this.options.brandImagePath : '/',
852 | brandImage: this.options.brandImage ? this.options.brandImage : null,
853 | brandImageAltText: this.options.brandImageAltText
854 | ? this.options.brandImageAltText
855 | : 'brand-image',
856 | collapseButtonImageOpen: this.options.collapseButtonImageOpen
857 | ? this.options.collapseButtonImageOpen
858 | : null,
859 | collapseButtonImageClose: this.options.collapseButtonImageClose
860 | ? this.options.collapseButtonImageClose
861 | : null,
862 | collapseButtonOpenColor: this.options.collapseButtonOpenColor
863 | ? this.options.collapseButtonOpenColor
864 | : '#373737',
865 | collapseButtonCloseColor: this.options.collapseButtonCloseColor
866 | ? this.options.collapseButtonCloseColor
867 | : '#373737',
868 | showBrandImageInMobilePopup: this.options.showBrandImageInMobilePopup ? true : false,
869 | ariaLabelMainNav: this.options.ariaLabelMainNav
870 | ? this.options.ariaLabelMainNav
871 | : 'Main Navigation',
872 | tooltipAnimationType: this.options.tooltipAnimationType
873 | ? this.options.tooltipAnimationType
874 | : 'shift-away',
875 | tooltipPlacement: this.options.tooltipPlacement || 'bottom',
876 | menuOptionsLeft: this.options.menuOptionsLeft ? this.options.menuOptionsLeft : [],
877 | menuOptionsRight: this.options.menuOptionsRight ? this.options.menuOptionsRight : [],
878 | };
879 | },
880 | },
881 | methods: {
882 | closeMobilePopup: function closeMobilePopup () {
883 | this.menuIsVisible = false;
884 | this.$emit('vnb-mobile-popup-hidden');
885 | },
886 | showMobilePopup: function showMobilePopup () {
887 | this.menuIsVisible = true;
888 | this.$emit('vnb-mobile-popup-shown');
889 | },
890 | vnbItemClicked: function vnbItemClicked (text) {
891 | this.$emit('vnb-item-clicked', text);
892 | },
893 | },
894 | components: {
895 | BrandImage: script$7,
896 | MenuOptions: script$2,
897 | CollapseButton: script$6,
898 | Popup: script$1,
899 | },
900 | emits: [
901 | 'vnb-mobile-popup-hidden',
902 | 'vnb-mobile-popup-shown',
903 | 'vnb-item-clicked' ]
904 | };
905 |
906 | var _hoisted_1 = ["id", "aria-label"];
907 |
908 | function render(_ctx, _cache, $props, $setup, $data, $options) {
909 | var _component_brand_image = resolveComponent("brand-image");
910 | var _component_menu_options = resolveComponent("menu-options");
911 | var _component_collapse_button = resolveComponent("collapse-button");
912 | var _component_popup = resolveComponent("popup");
913 |
914 | return (openBlock(), createElementBlock("nav", {
915 | class: "vnb",
916 | id: $options.finalOptions.elementId,
917 | "aria-label": $options.finalOptions.ariaLabelMainNav
918 | }, [
919 | createVNode(_component_brand_image, {
920 | options: $options.finalOptions,
921 | onVnbItemClicked: $options.vnbItemClicked
922 | }, null, 8 /* PROPS */, ["options", "onVnbItemClicked"]),
923 | createVNode(_component_menu_options, {
924 | options: $options.finalOptions,
925 | type: 'left',
926 | onVnbItemClicked: $options.vnbItemClicked
927 | }, null, 8 /* PROPS */, ["options", "onVnbItemClicked"]),
928 | (_ctx.$vssWidth > $props.options.mobileBreakpoint)
929 | ? renderSlot(_ctx.$slots, "custom-section", { key: 0 })
930 | : createCommentVNode("v-if", true),
931 | createVNode(_component_menu_options, {
932 | options: $options.finalOptions,
933 | type: 'right',
934 | onVnbItemClicked: $options.vnbItemClicked
935 | }, null, 8 /* PROPS */, ["options", "onVnbItemClicked"]),
936 | ($options.finalOptions.menuOptionsLeft.length || $options.finalOptions.menuOptionsRight.length)
937 | ? (openBlock(), createBlock(_component_collapse_button, {
938 | key: 1,
939 | options: $options.finalOptions,
940 | menuIsVisible: $data.menuIsVisible,
941 | onCollapseButtonClicked: $options.showMobilePopup
942 | }, null, 8 /* PROPS */, ["options", "menuIsVisible", "onCollapseButtonClicked"]))
943 | : createCommentVNode("v-if", true),
944 | ($options.finalOptions.menuOptionsLeft.length || $options.finalOptions.menuOptionsRight.length)
945 | ? (openBlock(), createBlock(_component_popup, {
946 | key: 2,
947 | options: $options.finalOptions,
948 | menuIsVisible: $data.menuIsVisible,
949 | onCloseButtonClicked: $options.closeMobilePopup,
950 | onVnbItemClicked: $options.vnbItemClicked
951 | }, {
952 | "custom-section": withCtx(function () { return [
953 | renderSlot(_ctx.$slots, "custom-section")
954 | ]; }),
955 | _: 3 /* FORWARDED */
956 | }, 8 /* PROPS */, ["options", "menuIsVisible", "onCloseButtonClicked", "onVnbItemClicked"]))
957 | : createCommentVNode("v-if", true)
958 | ], 8 /* PROPS */, _hoisted_1))
959 | }
960 |
961 | script.render = render;
962 | script.__file = "src/vue-navigation-bar.vue";
963 |
964 | // Import vue component
965 |
966 | // install function executed by Vue.use()
967 | function install(app) {
968 | if (install.installed) { return; }
969 |
970 | install.installed = true;
971 | app.component('VueNavigationBar', script);
972 | }
973 |
974 | var plugin = { install: install };
975 |
976 | // To auto-install when vue is found
977 | var GlobalVue = null;
978 | if (typeof window !== 'undefined') {
979 | GlobalVue = window.Vue;
980 | } else if (typeof global !== 'undefined') {
981 | GlobalVue = global.Vue;
982 | }
983 | if (GlobalVue) {
984 | GlobalVue.use(plugin);
985 | }
986 |
987 | // It's possible to expose named exports when writing components that can
988 | // also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
989 | // export const RollupDemoDirective = component;
990 |
991 | export { script as default, install };
992 |
--------------------------------------------------------------------------------
/dist/vue-navigation-bar.umd.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue-screen-size'), require('vue'), require('tippy.js')) :
3 | typeof define === 'function' && define.amd ? define(['exports', 'vue-screen-size', 'vue', 'tippy.js'], factory) :
4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VueNavigationBar = {}, global.VueScreenSize, global.Vue, global.tippy));
5 | })(this, (function (exports, vueScreenSize, vue, tippy) { 'use strict';
6 |
7 | function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8 |
9 | var tippy__default = /*#__PURE__*/_interopDefaultLegacy(tippy);
10 |
11 | // https://stackoverflow.com/a/2117523/8014660
12 | function uuidV4() {
13 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
14 | var r = (Math.random() * 16) | 0,
15 | v = c == 'x' ? r : (r & 0x3) | 0x8;
16 | return v.toString(16);
17 | });
18 | }
19 |
20 | var script$8 = {
21 | name: 'dynamic-link',
22 | props: {
23 | isUsingVueRouter: {
24 | type: Boolean,
25 | required: true,
26 | },
27 | path: {
28 | type: [String, Object],
29 | required: false,
30 | },
31 | isLinkAction: {
32 | type: Boolean,
33 | required: true,
34 | },
35 | },
36 | computed: {
37 | localPath: function localPath() {
38 | if (!this.path) { return; }
39 |
40 | return typeof this.path === 'string' ? this.path : Object.assign({}, this.path);
41 | },
42 | },
43 | };
44 |
45 | var _hoisted_1$7 = ["href"];
46 |
47 | function render$8(_ctx, _cache, $props, $setup, $data, $options) {
48 | var _component_router_link = vue.resolveComponent("router-link");
49 |
50 | return (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
51 | ($props.isUsingVueRouter && $props.path)
52 | ? (vue.openBlock(), vue.createBlock(_component_router_link, vue.mergeProps({ key: 0 }, _ctx.$attrs, { to: $options.localPath }), {
53 | default: vue.withCtx(function () { return [
54 | vue.renderSlot(_ctx.$slots, "content")
55 | ]; }),
56 | _: 3 /* FORWARDED */
57 | }, 16 /* FULL_PROPS */, ["to"]))
58 | : vue.createCommentVNode("v-if", true),
59 | (!$props.isUsingVueRouter && !$props.isLinkAction && $props.path)
60 | ? (vue.openBlock(), vue.createElementBlock("a", vue.mergeProps({ key: 1 }, _ctx.$attrs, { href: $props.path }), [
61 | vue.renderSlot(_ctx.$slots, "content")
62 | ], 16 /* FULL_PROPS */, _hoisted_1$7))
63 | : vue.createCommentVNode("v-if", true),
64 | ($props.isLinkAction)
65 | ? (vue.openBlock(), vue.createElementBlock("a", vue.mergeProps({ key: 2 }, _ctx.$attrs, { href: "javascript:void(0);" }), [
66 | vue.renderSlot(_ctx.$slots, "content")
67 | ], 16 /* FULL_PROPS */))
68 | : vue.createCommentVNode("v-if", true)
69 | ], 64 /* STABLE_FRAGMENT */))
70 | }
71 |
72 | script$8.render = render$8;
73 | script$8.__file = "src/components/DynamicLink.vue";
74 |
75 | var script$7 = {
76 | name: 'brand-image',
77 | props: {
78 | options: {
79 | type: Object,
80 | required: true,
81 | },
82 | },
83 | data: function data () {
84 | return {};
85 | },
86 | components: {
87 | DynamicLink: script$8,
88 | },
89 | emits: [
90 | 'vnb-item-clicked' ]
91 | };
92 |
93 | var _hoisted_1$6 = { class: "vnb__brand-image-wrapper" };
94 | var _hoisted_2$4 = ["src", "alt"];
95 |
96 | function render$7(_ctx, _cache, $props, $setup, $data, $options) {
97 | var _component_dynamic_link = vue.resolveComponent("dynamic-link");
98 |
99 | return (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, [
100 | vue.createVNode(_component_dynamic_link, {
101 | path: $props.options.brandImagePath,
102 | isUsingVueRouter: $props.options.isUsingVueRouter,
103 | class: "vnb__brand-image-wrapper__link",
104 | "aria-label": "Homepage",
105 | isLinkAction: false,
106 | onClick: _cache[0] || (_cache[0] = function ($event) { return (_ctx.$emit('vnb-item-clicked', 'brand-image')); })
107 | }, {
108 | content: vue.withCtx(function () { return [
109 | ($props.options.brandImage)
110 | ? (vue.openBlock(), vue.createElementBlock("img", {
111 | key: 0,
112 | src: $props.options.brandImage,
113 | alt: $props.options.brandImageAltText,
114 | class: "vnb-image vnb__brand-image-wrapper__link__image"
115 | }, null, 8 /* PROPS */, _hoisted_2$4))
116 | : vue.createCommentVNode("v-if", true)
117 | ]; }),
118 | _: 1 /* STABLE */
119 | }, 8 /* PROPS */, ["path", "isUsingVueRouter"])
120 | ]))
121 | }
122 |
123 | script$7.render = render$7;
124 | script$7.__file = "src/components/BrandImage.vue";
125 |
126 | var script$6 = {
127 | name: 'collapse-button',
128 | mixins: [vueScreenSize.VueScreenSizeMixin],
129 | props: {
130 | options: {
131 | type: Object,
132 | required: true,
133 | },
134 | menuIsVisible: {
135 | type: Boolean,
136 | required: true,
137 | },
138 | },
139 | data: function data () {
140 | return {};
141 | },
142 | methods: {
143 | collapseButtonClicked: function collapseButtonClicked () {
144 | this.$emit('collapse-button-clicked');
145 | },
146 | },
147 | emits: [
148 | 'collapse-button-clicked' ]
149 | };
150 |
151 | var _hoisted_1$5 = ["aria-expanded"];
152 | var _hoisted_2$3 = ["src"];
153 | var _hoisted_3$2 = /*#__PURE__*/vue.createElementVNode("title", null, "Menu", -1 /* HOISTED */);
154 | var _hoisted_4$2 = /*#__PURE__*/vue.createElementVNode("g", { transform: "matrix(.1 0 0 -.1 0 100)" }, [
155 | /*#__PURE__*/vue.createElementVNode("path", { d: "m0 850v-40h500 500v40 40h-500-500z" }),
156 | /*#__PURE__*/vue.createElementVNode("path", { d: "m0 495v-45h500 500v45 45h-500-500z" }),
157 | /*#__PURE__*/vue.createElementVNode("path", { d: "m0 140v-40h500 500v40 40h-500-500z" })
158 | ], -1 /* HOISTED */);
159 | var _hoisted_5$2 = [
160 | _hoisted_3$2,
161 | _hoisted_4$2
162 | ];
163 |
164 | function render$6(_ctx, _cache, $props, $setup, $data, $options) {
165 | return (_ctx.$vssWidth < $props.options.mobileBreakpoint)
166 | ? (vue.openBlock(), vue.createElementBlock("button", {
167 | key: 0,
168 | class: "vnb__collapse-button",
169 | onClick: _cache[0] || (_cache[0] = function () {
170 | var args = [], len = arguments.length;
171 | while ( len-- ) args[ len ] = arguments[ len ];
172 |
173 | return ($options.collapseButtonClicked && $options.collapseButtonClicked.apply($options, args));
174 | }),
175 | type: "button",
176 | "aria-expanded": $props.menuIsVisible ? 'true' : 'false'
177 | }, [
178 | ($props.options.collapseButtonImageOpen)
179 | ? (vue.openBlock(), vue.createElementBlock("img", {
180 | key: 0,
181 | src: $props.options.collapseButtonImageOpen,
182 | alt: 'Menu',
183 | class: "vnb__collapse-button__image"
184 | }, null, 8 /* PROPS */, _hoisted_2$3))
185 | : (vue.openBlock(), vue.createElementBlock("svg", {
186 | key: 1,
187 | height: "100pt",
188 | preserveAspectRatio: "xMidYMid meet",
189 | viewBox: "0 0 100 100",
190 | width: "100pt",
191 | xmlns: "http://www.w3.org/2000/svg",
192 | class: "vnb__collapse-button__image",
193 | style: vue.normalizeStyle({fill: $props.options.collapseButtonOpenColor})
194 | }, _hoisted_5$2, 4 /* STYLE */))
195 | ], 8 /* PROPS */, _hoisted_1$5))
196 | : vue.createCommentVNode("v-if", true)
197 | }
198 |
199 | script$6.render = render$6;
200 | script$6.__file = "src/components/CollapseButton.vue";
201 |
202 | var script$5 = {
203 | name: 'desktop-menu-item-button',
204 | props: {
205 | option: {
206 | type: Object,
207 | required: true,
208 | },
209 | options: {
210 | type: Object,
211 | required: true,
212 | },
213 | },
214 | data: function data () {
215 | return {};
216 | },
217 | components: {
218 | DynamicLink: script$8,
219 | },
220 | emits: [
221 | 'vnb-item-clicked' ]
222 | };
223 |
224 | var _hoisted_1$4 = ["innerHTML"];
225 | var _hoisted_2$2 = ["innerHTML"];
226 |
227 | function render$5(_ctx, _cache, $props, $setup, $data, $options) {
228 | var _component_dynamic_link = vue.resolveComponent("dynamic-link");
229 |
230 | return (vue.openBlock(), vue.createBlock(_component_dynamic_link, {
231 | path: $props.option.path,
232 | isUsingVueRouter: $props.options.isUsingVueRouter,
233 | class: vue.normalizeClass(['vnb__menu-options__option__button', 'vnb-button', $props.option.class]),
234 | "aria-label": $props.option.text,
235 | isLinkAction: $props.option.isLinkAction ? true : false,
236 | onClick: _cache[0] || (_cache[0] = function ($event) { return (_ctx.$emit('vnb-item-clicked', $props.option.text)); })
237 | }, {
238 | content: vue.withCtx(function () { return [
239 | ($props.option.iconLeft)
240 | ? (vue.openBlock(), vue.createElementBlock("span", {
241 | key: 0,
242 | class: "vnb__menu-options__option__button__icon vnb__menu-options__option__button__icon--left",
243 | innerHTML: $props.option.iconLeft
244 | }, null, 8 /* PROPS */, _hoisted_1$4))
245 | : vue.createCommentVNode("v-if", true),
246 | vue.createTextVNode(" " + vue.toDisplayString($props.option.text) + " ", 1 /* TEXT */),
247 | ($props.option.iconRight)
248 | ? (vue.openBlock(), vue.createElementBlock("span", {
249 | key: 1,
250 | class: "vnb__menu-options__option__button__icon vnb__menu-options__option__button__icon--right",
251 | innerHTML: $props.option.iconRight
252 | }, null, 8 /* PROPS */, _hoisted_2$2))
253 | : vue.createCommentVNode("v-if", true)
254 | ]; }),
255 | _: 1 /* STABLE */
256 | }, 8 /* PROPS */, ["path", "isUsingVueRouter", "class", "aria-label", "isLinkAction"]))
257 | }
258 |
259 | script$5.render = render$5;
260 | script$5.__file = "src/components/DesktopMenuItemButton.vue";
261 |
262 | var script$4 = {
263 | name: 'desktop-menu-item-link',
264 | props: {
265 | option: {
266 | type: Object,
267 | required: true,
268 | },
269 | options: {
270 | type: Object,
271 | required: true,
272 | },
273 | },
274 | data: function data () {
275 | return {
276 | currentExpandedStatus: 'closed',
277 | };
278 | },
279 | computed: {
280 | isExpanded: function isExpanded () {
281 | if (this.currentExpandedStatus === 'open') {
282 | return true;
283 | }
284 |
285 | return false;
286 | },
287 | },
288 | methods: {
289 | // Each time a sub-menu-option is clicked, close all the tooltips
290 | subMenuItemSelected: function subMenuItemSelected (text) {
291 | this.closeAllTooltips();
292 | },
293 |
294 | // When we keydown tab on the last sub-menu-option, we want to close
295 | // all the tooltips
296 | subMenuItemTabbed: function subMenuItemTabbed (text) {
297 | // Let's check to see if this item is the last
298 | // item in the subMenuOptions array
299 | if (this.option.subMenuOptions[this.option.subMenuOptions.length - 1].text === text) {
300 | this.closeAllTooltips();
301 | }
302 | },
303 |
304 | menuShown: function menuShown () {
305 | this.currentExpandedStatus = 'open';
306 | },
307 | menuHidden: function menuHidden () {
308 | this.currentExpandedStatus = 'closed';
309 | },
310 |
311 | closeAllTooltips: function closeAllTooltips () {
312 | // https://atomiks.github.io/tippyjs/v6/methods/#hideall
313 | tippy.hideAll();
314 | },
315 |
316 | initTippy: function initTippy () {
317 | var this$1$1 = this;
318 |
319 | var el = document.getElementById('dropdown-menu-parent-' + this.option.id);
320 |
321 | var template = document.getElementById('sub-menu-options-' + this.option.id);
322 | template.style.display = 'block';
323 |
324 | tippy__default["default"](el, {
325 | theme: 'light',
326 | content: template,
327 | interactive: true,
328 | animation: this.options.tooltipAnimationType,
329 | role: 'Menu',
330 | // trigger: 'click', // for testing
331 | trigger: 'click mouseenter focus',
332 | appendTo: 'parent',
333 | arrow: true,
334 | inertia: false,
335 | placement: this.options.tooltipPlacement,
336 | popperOptions: {
337 | modifiers: [
338 | {
339 | name: 'flip',
340 | options: {
341 | fallbackPlacements: [this.options.tooltipPlacement],
342 | },
343 | } ],
344 | },
345 | onShow: function (instance) {
346 | tippy.hideAll({exclude: instance});
347 |
348 | // fire the menuShown function
349 | this$1$1.menuShown();
350 | },
351 | onHide: function () {
352 | // fire the menuHidden function
353 | this$1$1.menuHidden();
354 | },
355 | });
356 | },
357 | },
358 | mounted: function mounted () {
359 | // Let's setup our tippy here in mounted
360 | if (this.option.subMenuOptions && this.option.subMenuOptions.length) {
361 | this.initTippy();
362 | }
363 | },
364 | components: {
365 | DynamicLink: script$8,
366 | },
367 | emits: [
368 | 'vnb-item-clicked' ]
369 | };
370 |
371 | var _hoisted_1$3 = ["innerHTML"];
372 | var _hoisted_2$1 = ["innerHTML"];
373 | var _hoisted_3$1 = ["id", "aria-expanded", "aria-label"];
374 | var _hoisted_4$1 = ["innerHTML"];
375 | var _hoisted_5$1 = ["innerHTML"];
376 | var _hoisted_6$1 = /*#__PURE__*/vue.createElementVNode("title", null, "Toggle Arrow", -1 /* HOISTED */);
377 | var _hoisted_7$1 = /*#__PURE__*/vue.createElementVNode("path", {
378 | d: "m12 268c-7-7-12-17-12-23 0-13 232-245 245-245 6 0 64 54 129 119 119 119 132 142 90 158-11 4-44-23-113-91-53-53-101-96-106-96-6 0-53 43-105 95s-99 95-105 95-16-5-23-12z",
379 | transform: "matrix(.1 0 0 -.1 0 28)"
380 | }, null, -1 /* HOISTED */);
381 | var _hoisted_8$1 = [
382 | _hoisted_6$1,
383 | _hoisted_7$1
384 | ];
385 | var _hoisted_9$1 = ["id"];
386 | var _hoisted_10$1 = {
387 | class: "vnb__sub-menu-options__option",
388 | tabindex: "-1"
389 | };
390 | var _hoisted_11$1 = ["innerHTML"];
391 | var _hoisted_12$1 = { class: "vnb__sub-menu-options__option__link__text-wrapper" };
392 | var _hoisted_13$1 = { class: "vnb__sub-menu-options__option__link__text-wrapper__text" };
393 | var _hoisted_14$1 = {
394 | key: 0,
395 | class: "vnb__sub-menu-options__option__link__text-wrapper__sub-text"
396 | };
397 | var _hoisted_15$1 = ["innerHTML"];
398 | var _hoisted_16$1 = {
399 | key: 1,
400 | class: "vnb__sub-menu-options__option__hr",
401 | tabindex: "-1"
402 | };
403 |
404 | function render$4(_ctx, _cache, $props, $setup, $data, $options) {
405 | var _component_dynamic_link = vue.resolveComponent("dynamic-link");
406 |
407 | return (!$props.option.subMenuOptions || !$props.option.subMenuOptions.length)
408 | ? (vue.openBlock(), vue.createBlock(_component_dynamic_link, {
409 | key: 0,
410 | path: $props.option.path,
411 | isUsingVueRouter: $props.options.isUsingVueRouter,
412 | class: vue.normalizeClass(['vnb__menu-options__option__link', $props.option.class]),
413 | "aria-label": $props.option.text,
414 | tabindex: "0",
415 | isLinkAction: $props.option.isLinkAction ? true : false,
416 | onClick: _cache[0] || (_cache[0] = function ($event) { return (_ctx.$emit('vnb-item-clicked', $props.option.text)); })
417 | }, {
418 | content: vue.withCtx(function () { return [
419 | ($props.option.iconLeft)
420 | ? (vue.openBlock(), vue.createElementBlock("span", {
421 | key: 0,
422 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--left",
423 | innerHTML: $props.option.iconLeft
424 | }, null, 8 /* PROPS */, _hoisted_1$3))
425 | : vue.createCommentVNode("v-if", true),
426 | vue.createTextVNode(" " + vue.toDisplayString($props.option.text) + " ", 1 /* TEXT */),
427 | ($props.option.iconRight)
428 | ? (vue.openBlock(), vue.createElementBlock("span", {
429 | key: 1,
430 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--right",
431 | innerHTML: $props.option.iconRight
432 | }, null, 8 /* PROPS */, _hoisted_2$1))
433 | : vue.createCommentVNode("v-if", true)
434 | ]; }),
435 | _: 1 /* STABLE */
436 | }, 8 /* PROPS */, ["path", "isUsingVueRouter", "class", "aria-label", "isLinkAction"]))
437 | : (vue.openBlock(), vue.createElementBlock("span", {
438 | key: 1,
439 | class: vue.normalizeClass(['vnb__menu-options__option__link', $props.option.class]),
440 | id: 'dropdown-menu-parent-' + $props.option.id,
441 | "aria-haspopup": "true",
442 | "aria-expanded": $options.isExpanded ? 'true' : 'false',
443 | "aria-label": $props.option.text,
444 | tabindex: "0"
445 | }, [
446 | ($props.option.iconLeft)
447 | ? (vue.openBlock(), vue.createElementBlock("span", {
448 | key: 0,
449 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--left",
450 | innerHTML: $props.option.iconLeft
451 | }, null, 8 /* PROPS */, _hoisted_4$1))
452 | : vue.createCommentVNode("v-if", true),
453 | vue.createTextVNode(" " + vue.toDisplayString($props.option.text) + " ", 1 /* TEXT */),
454 | ($props.option.iconRight)
455 | ? (vue.openBlock(), vue.createElementBlock("span", {
456 | key: 1,
457 | class: "vnb__menu-options__option__link__icon vnb__menu-options__option__button__icon--right",
458 | innerHTML: $props.option.iconRight
459 | }, null, 8 /* PROPS */, _hoisted_5$1))
460 | : vue.createCommentVNode("v-if", true),
461 | (vue.openBlock(), vue.createElementBlock("svg", {
462 | height: "28pt",
463 | preserveAspectRatio: "xMidYMid meet",
464 | viewBox: "0 0 49 28",
465 | width: "49pt",
466 | xmlns: "http://www.w3.org/2000/svg",
467 | style: vue.normalizeStyle({fill: $props.option.arrowColor}),
468 | class: vue.normalizeClass([
469 | 'vnb__menu-options__option__arrow',
470 | {'vnb__menu-options__option__arrow--hover': $options.isExpanded} ])
471 | }, _hoisted_8$1, 6 /* CLASS, STYLE */)),
472 | ($props.option.type === 'link')
473 | ? (vue.openBlock(), vue.createElementBlock("div", {
474 | key: 2,
475 | class: "vnb__sub-menu-options",
476 | id: 'sub-menu-options-' + $props.option.id
477 | }, [
478 | vue.createElementVNode("div", _hoisted_10$1, [
479 | (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($props.option.subMenuOptions, function (subOption, index) {
480 | return (vue.openBlock(), vue.createElementBlock("div", null, [
481 | (subOption.type === 'link')
482 | ? (vue.openBlock(), vue.createBlock(_component_dynamic_link, {
483 | path: subOption.path,
484 | isUsingVueRouter: $props.options.isUsingVueRouter,
485 | key: index,
486 | class: "vnb__sub-menu-options__option__link",
487 | onClick: function ($event) {
488 | $options.subMenuItemSelected(subOption.text);
489 | _ctx.$emit('vnb-item-clicked', subOption.text);
490 | },
491 | "aria-label": subOption.text,
492 | tabindex: "0",
493 | onKeydown: vue.withKeys(function ($event) { return ($options.subMenuItemTabbed(subOption.text)); }, ["tab"]),
494 | isLinkAction: subOption.isLinkAction ? true : false
495 | }, {
496 | content: vue.withCtx(function () { return [
497 | (subOption.iconLeft)
498 | ? (vue.openBlock(), vue.createElementBlock("span", {
499 | key: 0,
500 | class: "vnb__sub-menu-options__option__link__icon vnb__sub-menu-options__option__link__icon--left",
501 | innerHTML: subOption.iconLeft
502 | }, null, 8 /* PROPS */, _hoisted_11$1))
503 | : vue.createCommentVNode("v-if", true),
504 | vue.createElementVNode("span", _hoisted_12$1, [
505 | vue.createElementVNode("span", _hoisted_13$1, vue.toDisplayString(subOption.text), 1 /* TEXT */),
506 | (subOption.subText)
507 | ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_14$1, vue.toDisplayString(subOption.subText), 1 /* TEXT */))
508 | : vue.createCommentVNode("v-if", true)
509 | ]),
510 | (subOption.iconRight)
511 | ? (vue.openBlock(), vue.createElementBlock("span", {
512 | key: 1,
513 | class: "vnb__sub-menu-options__option__link__icon vnb__sub-menu-options__option__link__icon--right",
514 | innerHTML: subOption.iconRight
515 | }, null, 8 /* PROPS */, _hoisted_15$1))
516 | : vue.createCommentVNode("v-if", true)
517 | ]; }),
518 | _: 2 /* DYNAMIC */
519 | }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["path", "isUsingVueRouter", "onClick", "aria-label", "onKeydown", "isLinkAction"]))
520 | : (vue.openBlock(), vue.createElementBlock("hr", _hoisted_16$1))
521 | ]))
522 | }), 256 /* UNKEYED_FRAGMENT */))
523 | ])
524 | ], 8 /* PROPS */, _hoisted_9$1))
525 | : vue.createCommentVNode("v-if", true)
526 | ], 10 /* CLASS, PROPS */, _hoisted_3$1))
527 | }
528 |
529 | script$4.render = render$4;
530 | script$4.__file = "src/components/DesktopMenuItemLink.vue";
531 |
532 | var script$3 = {
533 | name: 'desktop-menu-item-spacer',
534 | props: {
535 | option: {
536 | type: Object,
537 | required: true
538 | }
539 | },
540 | data: function data () {
541 | return {
542 | }
543 | }
544 | };
545 |
546 | var _hoisted_1$2 = { class: "vnb__menu-options__option__spacer" };
547 |
548 | function render$3(_ctx, _cache, $props, $setup, $data, $options) {
549 | return (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2))
550 | }
551 |
552 | script$3.render = render$3;
553 | script$3.__file = "src/components/DesktopMenuItemSpacer.vue";
554 |
555 | var script$2 = {
556 | name: 'menu-options',
557 | mixins: [vueScreenSize.VueScreenSizeMixin],
558 | props: {
559 | options: {
560 | type: Object,
561 | required: true,
562 | },
563 | type: {
564 | type: String,
565 | required: true,
566 | },
567 | },
568 | data: function data () {
569 | return {};
570 | },
571 | methods: {
572 | vnbItemClicked: function vnbItemClicked (text) {
573 | this.$emit('vnb-item-clicked', text);
574 | },
575 | },
576 | components: {
577 | DesktopMenuItemLink: script$4,
578 | DesktopMenuItemButton: script$5,
579 | DesktopMenuItemSpacer: script$3,
580 | },
581 | emits: [
582 | 'vnb-item-clicked' ]
583 | };
584 |
585 | function render$2(_ctx, _cache, $props, $setup, $data, $options) {
586 | var _component_desktop_menu_item_link = vue.resolveComponent("desktop-menu-item-link");
587 | var _component_desktop_menu_item_button = vue.resolveComponent("desktop-menu-item-button");
588 | var _component_desktop_menu_item_spacer = vue.resolveComponent("desktop-menu-item-spacer");
589 |
590 | return (_ctx.$vssWidth > $props.options.mobileBreakpoint)
591 | ? (vue.openBlock(), vue.createElementBlock("div", {
592 | key: 0,
593 | class: vue.normalizeClass([
594 | 'vnb__menu-options',
595 | {'vnb__menu-options--left': $props.type === 'left'},
596 | {'vnb__menu-options--right': $props.type === 'right'} ])
597 | }, [
598 | (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($props.type === 'left'
599 | ? $props.options.menuOptionsLeft
600 | : $props.options.menuOptionsRight, function (option, index) {
601 | return (vue.openBlock(), vue.createElementBlock("div", {
602 | key: index,
603 | class: "vnb__menu-options__option"
604 | }, [
605 | (option.type === 'link')
606 | ? (vue.openBlock(), vue.createBlock(_component_desktop_menu_item_link, {
607 | key: 0,
608 | class: vue.normalizeClass(option.class),
609 | option: option,
610 | options: $props.options,
611 | onVnbItemClicked: $options.vnbItemClicked
612 | }, null, 8 /* PROPS */, ["class", "option", "options", "onVnbItemClicked"]))
613 | : (option.type === 'button')
614 | ? (vue.openBlock(), vue.createBlock(_component_desktop_menu_item_button, {
615 | key: 1,
616 | option: option,
617 | options: $props.options,
618 | onVnbItemClicked: $options.vnbItemClicked
619 | }, null, 8 /* PROPS */, ["option", "options", "onVnbItemClicked"]))
620 | : (vue.openBlock(), vue.createBlock(_component_desktop_menu_item_spacer, {
621 | key: 2,
622 | option: option
623 | }, null, 8 /* PROPS */, ["option"]))
624 | ]))
625 | }), 128 /* KEYED_FRAGMENT */))
626 | ], 2 /* CLASS */))
627 | : vue.createCommentVNode("v-if", true)
628 | }
629 |
630 | script$2.render = render$2;
631 | script$2.__file = "src/components/MenuOptions.vue";
632 |
633 | var script$1 = {
634 | name: 'popup',
635 | props: {
636 | options: {
637 | type: Object,
638 | required: true,
639 | },
640 | menuIsVisible: {
641 | type: Boolean,
642 | required: true,
643 | },
644 | },
645 | data: function data() {
646 | return {};
647 | },
648 | computed: {
649 | combinedMenuItems: function combinedMenuItems() {
650 | var combinedArray = this.options.menuOptionsLeft.concat(this.options.menuOptionsRight);
651 | return combinedArray;
652 | },
653 | },
654 | methods: {
655 | closeButtonClicked: function closeButtonClicked() {
656 | this.$emit('close-button-clicked');
657 | },
658 | itemSelected: function itemSelected(option) {
659 | this.$emit('vnb-item-clicked', option.text);
660 | this.closeButtonClicked();
661 | },
662 | },
663 | components: {
664 | DynamicLink: script$8,
665 | },
666 | emits: ['close-button-clicked', 'vnb-item-clicked'],
667 | };
668 |
669 | var _hoisted_1$1 = {
670 | key: 0,
671 | class: "vnb__popup"
672 | };
673 | var _hoisted_2 = { class: "vnb__popup__top" };
674 | var _hoisted_3 = ["src", "alt"];
675 | var _hoisted_4 = ["aria-expanded"];
676 | var _hoisted_5 = ["src"];
677 | var _hoisted_6 = /*#__PURE__*/vue.createElementVNode("title", null, "Close button", -1 /* HOISTED */);
678 | var _hoisted_7 = /*#__PURE__*/vue.createElementVNode("path", {
679 | d: "m42 967c-12-13-22-27-22-33 0-5 93-102 207-216l208-208-208-208c-114-114-207-214-207-223 0-8 11-26 25-39l26-24 214 214 215 215 215-215 214-214 26 24c14 13 25 28 25 34s-92 103-205 216-205 209-205 215 92 102 205 215 205 210 205 216c0 12-42 54-55 54-5 0-104-94-220-210l-210-210-210 210c-115 116-212 210-216 210-3 0-15-10-27-23z",
680 | transform: "matrix(.1 0 0 -.1 0 100)"
681 | }, null, -1 /* HOISTED */);
682 | var _hoisted_8 = [
683 | _hoisted_6,
684 | _hoisted_7
685 | ];
686 | var _hoisted_9 = { class: "vnb__popup__bottom" };
687 | var _hoisted_10 = {
688 | key: 0,
689 | class: "vnb__popup__bottom__custom-section"
690 | };
691 | var _hoisted_11 = { class: "vnb__popup__bottom__menu-options" };
692 | var _hoisted_12 = ["innerHTML"];
693 | var _hoisted_13 = ["innerHTML"];
694 | var _hoisted_14 = {
695 | key: 1,
696 | class: "vnb__popup__bottom__menu-options__option__link vnb__popup__bottom__menu-options__option__link--no-highlight"
697 | };
698 | var _hoisted_15 = { class: "vnb__popup__bottom__sub-menu-options" };
699 | var _hoisted_16 = { class: "vnb__popup__bottom__sub-menu-options__option__link__sub-text" };
700 |
701 | function render$1(_ctx, _cache, $props, $setup, $data, $options) {
702 | var _component_dynamic_link = vue.resolveComponent("dynamic-link");
703 |
704 | return ($props.menuIsVisible)
705 | ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
706 | vue.createElementVNode("div", _hoisted_2, [
707 | ($props.options.showBrandImageInMobilePopup && $props.options.brandImage)
708 | ? (vue.openBlock(), vue.createElementBlock("img", {
709 | key: 0,
710 | src: $props.options.brandImage,
711 | alt: $props.options.brandImageAltText,
712 | class: "vnb-image vnb__popup__top__image"
713 | }, null, 8 /* PROPS */, _hoisted_3))
714 | : vue.createCommentVNode("v-if", true),
715 | vue.createElementVNode("button", {
716 | class: "vnb__popup__top__close-button",
717 | onClick: _cache[0] || (_cache[0] = function () {
718 | var args = [], len = arguments.length;
719 | while ( len-- ) args[ len ] = arguments[ len ];
720 |
721 | return ($options.closeButtonClicked && $options.closeButtonClicked.apply($options, args));
722 | }),
723 | "aria-label": "Close Button",
724 | title: "Close",
725 | "aria-expanded": $props.menuIsVisible ? 'true' : 'false'
726 | }, [
727 | ($props.options.collapseButtonImageClose)
728 | ? (vue.openBlock(), vue.createElementBlock("img", {
729 | key: 0,
730 | src: $props.options.collapseButtonImageClose,
731 | alt: 'Close button',
732 | class: "vnb__popup__top__close-button__image"
733 | }, null, 8 /* PROPS */, _hoisted_5))
734 | : (vue.openBlock(), vue.createElementBlock("svg", {
735 | key: 1,
736 | height: "100pt",
737 | preserveAspectRatio: "xMidYMid meet",
738 | viewBox: "0 0 100 100",
739 | width: "100pt",
740 | xmlns: "http://www.w3.org/2000/svg",
741 | class: "vnb__popup__top__close-button__image",
742 | style: vue.normalizeStyle({ fill: $props.options.collapseButtonCloseColor })
743 | }, _hoisted_8, 4 /* STYLE */))
744 | ], 8 /* PROPS */, _hoisted_4)
745 | ]),
746 | vue.createElementVNode("div", _hoisted_9, [
747 | (!!this.$slots['custom-section'])
748 | ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10, [
749 | vue.renderSlot(_ctx.$slots, "custom-section")
750 | ]))
751 | : vue.createCommentVNode("v-if", true),
752 | vue.createElementVNode("ul", _hoisted_11, [
753 | (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList($options.combinedMenuItems, function (option, index) {
754 | return (vue.openBlock(), vue.createElementBlock("li", {
755 | key: index,
756 | class: "vnb__popup__bottom__menu-options__option"
757 | }, [
758 | (!option.subMenuOptions)
759 | ? (vue.openBlock(), vue.createBlock(_component_dynamic_link, {
760 | key: 0,
761 | path: option.path,
762 | isUsingVueRouter: $props.options.isUsingVueRouter,
763 | class: vue.normalizeClass(['vnb__popup__bottom__menu-options__option__link', option.class]),
764 | onClick: function ($event) { return ($options.itemSelected(option)); },
765 | "aria-label": option.text,
766 | isLinkAction: option.isLinkAction ? true : false
767 | }, {
768 | content: vue.withCtx(function () { return [
769 | (option.iconLeft)
770 | ? (vue.openBlock(), vue.createElementBlock("span", {
771 | key: 0,
772 | class: "vnb__popup__bottom__menu-options__option__link__icon vnb__popup__bottom__menu-options__option__link__icon--left",
773 | innerHTML: option.iconLeft
774 | }, null, 8 /* PROPS */, _hoisted_12))
775 | : vue.createCommentVNode("v-if", true),
776 | vue.createTextVNode(" " + vue.toDisplayString(option.text) + " ", 1 /* TEXT */),
777 | (option.iconRight)
778 | ? (vue.openBlock(), vue.createElementBlock("span", {
779 | key: 1,
780 | class: "vnb__popup__bottom__menu-options__option__link__icon vnb__popup__bottom__menu-options__option__link__icon--right",
781 | innerHTML: option.iconRight
782 | }, null, 8 /* PROPS */, _hoisted_13))
783 | : vue.createCommentVNode("v-if", true)
784 | ]; }),
785 | _: 2 /* DYNAMIC */
786 | }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["path", "isUsingVueRouter", "class", "onClick", "aria-label", "isLinkAction"]))
787 | : (vue.openBlock(), vue.createElementBlock("span", _hoisted_14, vue.toDisplayString(option.text), 1 /* TEXT */)),
788 | vue.createElementVNode("div", _hoisted_15, [
789 | (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(option.subMenuOptions, function (subOption, index) {
790 | return (vue.openBlock(), vue.createElementBlock("div", {
791 | key: index,
792 | class: "vnb__popup__bottom__sub-menu-options__option"
793 | }, [
794 | (subOption.type === 'link')
795 | ? (vue.openBlock(), vue.createBlock(_component_dynamic_link, {
796 | key: 0,
797 | path: subOption.path,
798 | isUsingVueRouter: $props.options.isUsingVueRouter,
799 | class: "vnb__popup__bottom__sub-menu-options__option__link",
800 | onClick: function ($event) { return ($options.itemSelected(subOption)); },
801 | "aria-label": subOption.text,
802 | isLinkAction: subOption.isLinkAction ? true : false
803 | }, {
804 | content: vue.withCtx(function () { return [
805 | vue.createTextVNode(vue.toDisplayString(subOption.text) + " ", 1 /* TEXT */),
806 | vue.createElementVNode("span", _hoisted_16, vue.toDisplayString(subOption.subText), 1 /* TEXT */)
807 | ]; }),
808 | _: 2 /* DYNAMIC */
809 | }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["path", "isUsingVueRouter", "onClick", "aria-label", "isLinkAction"]))
810 | : vue.createCommentVNode("v-if", true)
811 | ]))
812 | }), 128 /* KEYED_FRAGMENT */))
813 | ])
814 | ]))
815 | }), 128 /* KEYED_FRAGMENT */))
816 | ])
817 | ])
818 | ]))
819 | : vue.createCommentVNode("v-if", true)
820 | }
821 |
822 | script$1.render = render$1;
823 | script$1.__file = "src/components/Popup.vue";
824 |
825 | var script = {
826 | name: 'vue-navigation-bar',
827 | mixins: [vueScreenSize.VueScreenSizeMixin],
828 | props: {
829 | options: {
830 | type: Object,
831 | required: true,
832 | },
833 | },
834 | data: function data () {
835 | return {
836 | menuIsVisible: false,
837 | };
838 | },
839 | computed: {
840 | finalOptions: function finalOptions () {
841 | // What we're doing here is giving each top-level menu-option a unique id
842 | if (this.options.menuOptionsLeft) {
843 | for (var x = 0; x < this.options.menuOptionsLeft.length; x++) {
844 | this.options.menuOptionsLeft[x].id = uuidV4();
845 | }
846 | }
847 | if (this.options.menuOptionsRight) {
848 | for (var x$1 = 0; x$1 < this.options.menuOptionsRight.length; x$1++) {
849 | this.options.menuOptionsRight[x$1].id = uuidV4();
850 | }
851 | }
852 |
853 | return {
854 | elementId: this.options.elementId ? this.options.elementId : uuidV4(),
855 | isUsingVueRouter: this.options.isUsingVueRouter ? true : false,
856 | mobileBreakpoint: this.options.mobileBreakpoint ? this.options.mobileBreakpoint : 992,
857 | brandImagePath: this.options.brandImagePath ? this.options.brandImagePath : '/',
858 | brandImage: this.options.brandImage ? this.options.brandImage : null,
859 | brandImageAltText: this.options.brandImageAltText
860 | ? this.options.brandImageAltText
861 | : 'brand-image',
862 | collapseButtonImageOpen: this.options.collapseButtonImageOpen
863 | ? this.options.collapseButtonImageOpen
864 | : null,
865 | collapseButtonImageClose: this.options.collapseButtonImageClose
866 | ? this.options.collapseButtonImageClose
867 | : null,
868 | collapseButtonOpenColor: this.options.collapseButtonOpenColor
869 | ? this.options.collapseButtonOpenColor
870 | : '#373737',
871 | collapseButtonCloseColor: this.options.collapseButtonCloseColor
872 | ? this.options.collapseButtonCloseColor
873 | : '#373737',
874 | showBrandImageInMobilePopup: this.options.showBrandImageInMobilePopup ? true : false,
875 | ariaLabelMainNav: this.options.ariaLabelMainNav
876 | ? this.options.ariaLabelMainNav
877 | : 'Main Navigation',
878 | tooltipAnimationType: this.options.tooltipAnimationType
879 | ? this.options.tooltipAnimationType
880 | : 'shift-away',
881 | tooltipPlacement: this.options.tooltipPlacement || 'bottom',
882 | menuOptionsLeft: this.options.menuOptionsLeft ? this.options.menuOptionsLeft : [],
883 | menuOptionsRight: this.options.menuOptionsRight ? this.options.menuOptionsRight : [],
884 | };
885 | },
886 | },
887 | methods: {
888 | closeMobilePopup: function closeMobilePopup () {
889 | this.menuIsVisible = false;
890 | this.$emit('vnb-mobile-popup-hidden');
891 | },
892 | showMobilePopup: function showMobilePopup () {
893 | this.menuIsVisible = true;
894 | this.$emit('vnb-mobile-popup-shown');
895 | },
896 | vnbItemClicked: function vnbItemClicked (text) {
897 | this.$emit('vnb-item-clicked', text);
898 | },
899 | },
900 | components: {
901 | BrandImage: script$7,
902 | MenuOptions: script$2,
903 | CollapseButton: script$6,
904 | Popup: script$1,
905 | },
906 | emits: [
907 | 'vnb-mobile-popup-hidden',
908 | 'vnb-mobile-popup-shown',
909 | 'vnb-item-clicked' ]
910 | };
911 |
912 | var _hoisted_1 = ["id", "aria-label"];
913 |
914 | function render(_ctx, _cache, $props, $setup, $data, $options) {
915 | var _component_brand_image = vue.resolveComponent("brand-image");
916 | var _component_menu_options = vue.resolveComponent("menu-options");
917 | var _component_collapse_button = vue.resolveComponent("collapse-button");
918 | var _component_popup = vue.resolveComponent("popup");
919 |
920 | return (vue.openBlock(), vue.createElementBlock("nav", {
921 | class: "vnb",
922 | id: $options.finalOptions.elementId,
923 | "aria-label": $options.finalOptions.ariaLabelMainNav
924 | }, [
925 | vue.createVNode(_component_brand_image, {
926 | options: $options.finalOptions,
927 | onVnbItemClicked: $options.vnbItemClicked
928 | }, null, 8 /* PROPS */, ["options", "onVnbItemClicked"]),
929 | vue.createVNode(_component_menu_options, {
930 | options: $options.finalOptions,
931 | type: 'left',
932 | onVnbItemClicked: $options.vnbItemClicked
933 | }, null, 8 /* PROPS */, ["options", "onVnbItemClicked"]),
934 | (_ctx.$vssWidth > $props.options.mobileBreakpoint)
935 | ? vue.renderSlot(_ctx.$slots, "custom-section", { key: 0 })
936 | : vue.createCommentVNode("v-if", true),
937 | vue.createVNode(_component_menu_options, {
938 | options: $options.finalOptions,
939 | type: 'right',
940 | onVnbItemClicked: $options.vnbItemClicked
941 | }, null, 8 /* PROPS */, ["options", "onVnbItemClicked"]),
942 | ($options.finalOptions.menuOptionsLeft.length || $options.finalOptions.menuOptionsRight.length)
943 | ? (vue.openBlock(), vue.createBlock(_component_collapse_button, {
944 | key: 1,
945 | options: $options.finalOptions,
946 | menuIsVisible: $data.menuIsVisible,
947 | onCollapseButtonClicked: $options.showMobilePopup
948 | }, null, 8 /* PROPS */, ["options", "menuIsVisible", "onCollapseButtonClicked"]))
949 | : vue.createCommentVNode("v-if", true),
950 | ($options.finalOptions.menuOptionsLeft.length || $options.finalOptions.menuOptionsRight.length)
951 | ? (vue.openBlock(), vue.createBlock(_component_popup, {
952 | key: 2,
953 | options: $options.finalOptions,
954 | menuIsVisible: $data.menuIsVisible,
955 | onCloseButtonClicked: $options.closeMobilePopup,
956 | onVnbItemClicked: $options.vnbItemClicked
957 | }, {
958 | "custom-section": vue.withCtx(function () { return [
959 | vue.renderSlot(_ctx.$slots, "custom-section")
960 | ]; }),
961 | _: 3 /* FORWARDED */
962 | }, 8 /* PROPS */, ["options", "menuIsVisible", "onCloseButtonClicked", "onVnbItemClicked"]))
963 | : vue.createCommentVNode("v-if", true)
964 | ], 8 /* PROPS */, _hoisted_1))
965 | }
966 |
967 | script.render = render;
968 | script.__file = "src/vue-navigation-bar.vue";
969 |
970 | // Import vue component
971 |
972 | // install function executed by Vue.use()
973 | function install(app) {
974 | if (install.installed) { return; }
975 |
976 | install.installed = true;
977 | app.component('VueNavigationBar', script);
978 | }
979 |
980 | var plugin = { install: install };
981 |
982 | // To auto-install when vue is found
983 | var GlobalVue = null;
984 | if (typeof window !== 'undefined') {
985 | GlobalVue = window.Vue;
986 | } else if (typeof global !== 'undefined') {
987 | GlobalVue = global.Vue;
988 | }
989 | if (GlobalVue) {
990 | GlobalVue.use(plugin);
991 | }
992 |
993 | // It's possible to expose named exports when writing components that can
994 | // also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
995 | // export const RollupDemoDirective = component;
996 |
997 | exports["default"] = script;
998 | exports.install = install;
999 |
1000 | Object.defineProperty(exports, '__esModule', { value: true });
1001 |
1002 | }));
1003 |
--------------------------------------------------------------------------------
/docs/assets/index.2f3ff1f9.css:
--------------------------------------------------------------------------------
1 | @import"https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css";@import"https://fonts.googleapis.com/css?family=Montserrat:400,500,700";html{width:100%;font-size:18px;color:#333}body{margin:0;height:100%;height:100vh;width:100%;font-family:Montserrat,sans-serif}#app{height:100%;height:100vh;width:100%;line-height:1.5}.code-text{background:#fff;border:1px solid #ddd;padding:10px 20px;border-radius:4px;margin-bottom:20px;text-align:center}@media (min-width: 992px){.code-text{margin-bottom:0}}.btn{text-transform:uppercase;font-weight:700}.github-corner:hover .octo-arm{animation:octocat-wave .56s ease-in-out}@keyframes octocat-wave{0%,to{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width: 500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave .56s ease-in-out}}.main-content-section{padding:45px 0;background:#eee;min-height:100%}.main-navbar-section{background:#fff}.vnb{font-family:Montserrat,sans-serif}@media (min-width: 992px){.vnb .button-red{background:#ff3b30}.vnb .button-red:hover{background:#fc0d00}}.vnb__menu-options__option__button__icon svg{margin-top:-3px}.vnb__popup__bottom__menu-options__option__link__icon svg{margin-top:-4px}.vnb .custom-section-content{width:100%}@media (min-width: 568px){.vnb .custom-section-content{width:50%}}@media (min-width: 992px){.vnb .custom-section-content{width:15%}}@media (min-width: 1200px){.vnb .custom-section-content{width:20%}}.vnb__brand-image-wrapper{padding-left:10px}.vnb__brand-image-wrapper__link__image{max-height:30px}.vnb__collapse-button{cursor:pointer;border:0;background:transparent;margin-right:10px}.vnb__collapse-button:hover{opacity:.75}.vnb__collapse-button__image{max-height:30px;max-width:30px}.vnb__menu-options__option__button{display:flex;flex-direction:row;justify-content:center;align-items:center;font-weight:400;color:#fff;text-align:center;vertical-align:middle;user-select:none;font-size:.9rem;line-height:1;border-radius:.25rem;text-transform:uppercase;letter-spacing:1px;padding:.5rem 1rem;transition:background .2s ease-in}.vnb__menu-options__option__button__icon svg{max-height:16px;max-width:16px}.vnb__menu-options__option__button__icon--left{margin-right:5px}.vnb__menu-options__option__button__icon--right{margin-left:5px}.vnb-button{background:#007aff}.vnb-button:hover{color:#fff;background:#0062cc;text-decoration:none}.tippy-box[data-animation=perspective][data-placement^=top]{transform-origin:bottom}.tippy-box[data-animation=perspective][data-placement^=top][data-state=visible]{transform:perspective(700px)}.tippy-box[data-animation=perspective][data-placement^=top][data-state=hidden]{transform:perspective(700px) translateY(8px) rotateX(60deg)}.tippy-box[data-animation=perspective][data-placement^=bottom]{transform-origin:top}.tippy-box[data-animation=perspective][data-placement^=bottom][data-state=visible]{transform:perspective(700px)}.tippy-box[data-animation=perspective][data-placement^=bottom][data-state=hidden]{transform:perspective(700px) translateY(-8px) rotateX(-60deg)}.tippy-box[data-animation=perspective][data-placement^=left]{transform-origin:right}.tippy-box[data-animation=perspective][data-placement^=left][data-state=visible]{transform:perspective(700px)}.tippy-box[data-animation=perspective][data-placement^=left][data-state=hidden]{transform:perspective(700px) translate(8px) rotateY(-60deg)}.tippy-box[data-animation=perspective][data-placement^=right]{transform-origin:left}.tippy-box[data-animation=perspective][data-placement^=right][data-state=visible]{transform:perspective(700px)}.tippy-box[data-animation=perspective][data-placement^=right][data-state=hidden]{transform:perspective(700px) translate(-8px) rotateY(60deg)}.tippy-box[data-animation=perspective][data-state=hidden]{opacity:0}.tippy-box[data-animation=scale][data-placement^=top]{transform-origin:bottom}.tippy-box[data-animation=scale][data-placement^=bottom]{transform-origin:top}.tippy-box[data-animation=scale][data-placement^=left]{transform-origin:right}.tippy-box[data-animation=scale][data-placement^=right]{transform-origin:left}.tippy-box[data-animation=scale][data-state=hidden]{transform:scale(.5);opacity:0}.tippy-box[data-animation=shift-away][data-state=hidden]{opacity:0}.tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=top]{transform:translateY(10px)}.tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=bottom]{transform:translateY(-10px)}.tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=left]{transform:translate(10px)}.tippy-box[data-animation=shift-away][data-state=hidden][data-placement^=right]{transform:translate(-10px)}.tippy-box[data-animation=shift-toward][data-state=hidden]{opacity:0}.tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=top]{transform:translateY(-10px)}.tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=bottom]{transform:translateY(10px)}.tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=left]{transform:translate(-10px)}.tippy-box[data-animation=shift-toward][data-state=hidden][data-placement^=right]{transform:translate(10px)}.tippy-box[data-theme~=light]{color:#26323d;box-shadow:0 0 20px 4px #9aa1b126,0 4px 80px -8px #24282f40,0 4px 4px -2px #5b5e6926;background-color:#fff}.tippy-box[data-theme~=light][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=light][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=light][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=light][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}.tippy-box[data-theme~=light]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=light]>.tippy-svg-arrow{fill:#fff}.vnb__menu-options__option__link{cursor:pointer;font-weight:500;color:#595959;transition:color .2s ease-in;display:flex;flex-direction:row;align-items:center;justify-content:center;font-size:.9rem}.vnb__menu-options__option__link:hover{color:#333;text-decoration:none}.vnb__menu-options__option__link__icon svg{max-height:20px}.vnb__menu-options__option__link__icon--left{margin-right:5px}.vnb__menu-options__option__link__icon--right{margin-left:5px}.vnb__menu-options__option__arrow{max-height:5px;max-width:25px;transition:transform .2s ease-in-out}.vnb__menu-options__option__arrow--hover{transform:rotate(180deg)}.vnb__sub-menu-options{background:#fff;max-width:500px;display:flex;flex-direction:column;justify-content:center;align-items:center;border-radius:4px;padding:10px 0}.vnb__sub-menu-options__option{min-width:250px;max-width:300px}.vnb__sub-menu-options__option__link{padding:12px;width:100%;display:flex;flex-direction:row;justify-content:center;align-items:center;color:#595959;transition:color .2s ease-in,background .2s ease-in,border .2s ease-in;border-left:2px solid #fff}.vnb__sub-menu-options__option__link:hover{color:#333;text-decoration:none;background:#f3f3f3;border-left:2px solid #007aff;cursor:pointer}.vnb__sub-menu-options__option__link__icon svg{max-height:40px}.vnb__sub-menu-options__option__link__icon--left{margin-right:15px}.vnb__sub-menu-options__option__link__icon--right{margin-left:15px}.vnb__sub-menu-options__option__link__text-wrapper{width:100%}.vnb__sub-menu-options__option__link__text-wrapper__text{display:block;text-align:left}.vnb__sub-menu-options__option__link__text-wrapper__sub-text{margin-top:5px;display:block;font-size:.8rem;text-align:left;color:#8c8c8c}.vnb__sub-menu-options__option__hr{margin-top:10px;margin-bottom:10px;border-color:#0000001a}.vnb__menu-options__option__spacer{width:30px}.vnb__menu-options{display:flex;flex-direction:row;align-items:center}.vnb__menu-options--left{margin-right:auto;justify-content:flex-start;padding-left:30px}.vnb__menu-options--right{margin-left:auto;justify-content:flex-end;padding-right:10px}.vnb__menu-options__option:not(:last-child){margin-right:20px}.vnb__popup{background:#fff;position:absolute;left:10px;top:10px;right:10px;display:flex;flex-direction:column;perspective:2000px;box-shadow:0 10px 30px #0000001a;margin-bottom:20px;z-index:100000}.vnb__popup__top{padding:15px 24px 0;border-top:1px solid #e0e0e0;border-left:1px solid #e0e0e0;border-right:1px solid #e0e0e0;border-top-right-radius:6px;border-top-left-radius:6px}.vnb__popup__top__image{max-height:27px;margin-bottom:5px}.vnb__popup__top__close-button{position:absolute;top:10px;right:10px;cursor:pointer;border:0;background:transparent}.vnb__popup__top__close-button:hover{opacity:.75}.vnb__popup__top__close-button__image{max-height:15px}.vnb__popup__top__close-button svg{width:auto}.vnb__popup__bottom{background:#fff;padding:10px 0;border-left:1px solid #e0e0e0;border-right:1px solid #e0e0e0;border-bottom:1px solid #e0e0e0;border-bottom-right-radius:6px;border-bottom-left-radius:6px}.vnb__popup__bottom__custom-section{padding:12px 24px}.vnb__popup__bottom__menu-options{list-style-type:none;padding-left:0;display:flex;flex-direction:column}.vnb__popup__bottom__menu-options__option:not(:last-child){margin-bottom:10px}.vnb__popup__bottom__menu-options__option__link{padding:12px 24px;color:#595959;font-weight:500;display:flex;flex-direction:row;justify-content:flex-start;align-items:center;transition:color .2s ease-in,background .2s ease-in,border .2s ease-in;border-left:2px solid #fff;width:100%}.vnb__popup__bottom__menu-options__option__link:hover{color:#333;text-decoration:none;background:#f3f3f3;border-left:2px solid #007aff}.vnb__popup__bottom__menu-options__option__link--no-highlight{padding:12px 24px 6px;font-weight:400;font-size:.8rem;color:#757575}.vnb__popup__bottom__menu-options__option__link--no-highlight:hover{color:#757575;background:#fff;border-left:2px solid #fff}.vnb__popup__bottom__menu-options__option__link__icon svg{max-height:16px;max-width:16px}.vnb__popup__bottom__menu-options__option__link__icon--left{margin-right:5px}.vnb__popup__bottom__menu-options__option__link__icon--right{margin-left:5px}.vnb__popup__bottom__sub-menu-options{display:flex;flex-direction:row;flex-wrap:wrap;width:100%;font-size:.9rem}.vnb__popup__bottom__sub-menu-options__option{width:100%}.vnb__popup__bottom__sub-menu-options__option__link{padding:6px 24px;width:100%;display:block;color:#595959;font-weight:500;transition:color .2s ease-in,background .2s ease-in,border .2s ease-in;border-left:2px solid #fff}.vnb__popup__bottom__sub-menu-options__option__link:hover{color:#333;text-decoration:none;background:#eee;border-left:2px solid #333}.vnb__popup__bottom__sub-menu-options__option__link__sub-text{margin-top:5px;display:block;font-size:.75rem;color:#8c8c8c}.vnb{background:#fff;padding-top:15px;padding-bottom:15px;display:flex;flex-direction:row;align-items:center;justify-content:space-between}.vnb *{box-sizing:border-box}.vnb a{text-decoration:none}.tippy-tooltip{padding:0}.vnb-image{max-width:100%;height:auto}
2 |
--------------------------------------------------------------------------------
/docs/assets/lockup-color.5dabaa34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johndatserakis/vue-navigation-bar/02b44b9120b6ec6ce04448dd74818f416e6ef2fc/docs/assets/lockup-color.5dabaa34.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 | vue-navigation-bar | John Datserakis
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/App.vue:
--------------------------------------------------------------------------------
1 |
2 |