srcdev-nuxt-components 6.1.0 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,7 @@
14
14
  <template #icon>
15
15
  <slot :name="`accordian-${key}-icon`"></slot>
16
16
  </template>
17
- <template #layout-content>
17
+ <template #content>
18
18
  <slot :name="`accordian-${key}-content`"></slot>
19
19
  </template>
20
20
  </ExpandingPanel>
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <div class="ui-content-grid" :class="[applyClasses]" :data-testid="dataTestid">
3
- <div v-if="hasSlot1" class="col-1">
3
+ <div v-if="slots.slot1" class="col-1">
4
4
  <slot name="slot1"></slot>
5
5
  </div>
6
- <div v-if="hasSlot2" class="col-2">
6
+ <div v-if="slots.slot2" class="col-2">
7
7
  <slot name="slot2"></slot>
8
8
  </div>
9
9
  </div>
@@ -13,17 +13,15 @@
13
13
  const props = defineProps({
14
14
  dataTestid: {
15
15
  type: String,
16
- default: 'ui-content-grid',
16
+ default: "ui-content-grid",
17
17
  },
18
18
  applyClasses: {
19
19
  type: String,
20
- default: '',
20
+ default: "",
21
21
  },
22
- });
22
+ })
23
23
 
24
- const slots = useSlots();
25
- const hasSlot1 = ref(slots.slot1 !== undefined);
26
- const hasSlot2 = ref(slots.slot2 !== undefined);
24
+ const slots = useSlots()
27
25
  </script>
28
26
 
29
27
  <style lang="css">
@@ -1,9 +1,18 @@
1
1
  <template>
2
- <dialog class="display-dialog-core" :class="[elementClasses]" role="dialog" :align-dialog :justify-dialog :open :data-dialog-id="dataDialogId" ref="dialogRef">
2
+ <dialog
3
+ class="display-dialog-core"
4
+ :class="[elementClasses]"
5
+ role="dialog"
6
+ :align-dialog
7
+ :justify-dialog
8
+ :open
9
+ :data-dialog-id="dataDialogId"
10
+ ref="dialogRef"
11
+ >
3
12
  <focus-trap v-model:active="open" :clickOutsideDeactivates="true" @deactivate="closeDialog()">
4
13
  <div class="inner" :class="[variant]">
5
14
  <div class="header">
6
- <div v-if="hasDialogTitle" class="col-left">
15
+ <div v-if="slots.dialogTitle" class="col-left">
7
16
  <slot name="dialogTitle"></slot>
8
17
  </div>
9
18
 
@@ -11,16 +20,24 @@
11
20
  <p class="text-normal wght-700">Center col</p>
12
21
  </div>
13
22
  <div class="col-right">
14
- <button @click.prevent="closeDialog()" data-test-id="display-dialog-header-close" class="display-prompt-action">
23
+ <button
24
+ @click.prevent="closeDialog()"
25
+ data-test-id="display-dialog-header-close"
26
+ class="display-prompt-action"
27
+ >
15
28
  <Icon name="bitcoin-icons:cross-filled" class="icon" />
16
29
  <span class="sr-only">Really Close</span>
17
30
  </button>
18
31
  </div>
19
32
  </div>
20
- <div v-if="hasDialogContent" class="dialog-content" :class="[{ 'allow-content-scroll': allowContentScroll }]">
33
+ <div
34
+ v-if="slots.dialogContent"
35
+ class="dialog-content"
36
+ :class="[{ 'allow-content-scroll': allowContentScroll }]"
37
+ >
21
38
  <slot name="dialogContent"></slot>
22
39
  </div>
23
- <div v-if="hasActionButtons" class="footer">
40
+ <div v-if="slots.actionButtons" class="footer">
24
41
  <slot name="actionButtons"></slot>
25
42
  </div>
26
43
  </div>
@@ -29,7 +46,7 @@
29
46
  </template>
30
47
 
31
48
  <script setup lang="ts">
32
- import { FocusTrap } from 'focus-trap-vue';
49
+ import { FocusTrap } from "focus-trap-vue"
33
50
  const props = defineProps({
34
51
  styleClassPassthrough: {
35
52
  type: Array as PropType<string[]>,
@@ -37,18 +54,18 @@ const props = defineProps({
37
54
  },
38
55
  variant: {
39
56
  type: String,
40
- default: 'dialog',
41
- validator: (val) => ['dialog', 'modal', 'confirm'].includes(val as string),
57
+ default: "dialog",
58
+ validator: (val) => ["dialog", "modal", "confirm"].includes(val as string),
42
59
  },
43
60
  justifyDialog: {
44
61
  type: String,
45
- default: 'center',
46
- validator: (val) => ['start', 'center', 'end'].includes(val as string),
62
+ default: "center",
63
+ validator: (val) => ["start", "center", "end"].includes(val as string),
47
64
  },
48
65
  alignDialog: {
49
66
  type: String,
50
- default: 'center',
51
- validator: (val) => ['start', 'center', 'end'].includes(val as string),
67
+ default: "center",
68
+ validator: (val) => ["start", "center", "end"].includes(val as string),
52
69
  },
53
70
  lockViewport: {
54
71
  type: Boolean,
@@ -62,33 +79,30 @@ const props = defineProps({
62
79
  type: String,
63
80
  required: true,
64
81
  },
65
- });
82
+ })
66
83
 
67
- const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
84
+ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
68
85
 
69
- const open = defineModel<boolean>();
70
- const bodyTag = ref<HTMLBodyElement | null>(null);
71
- const lockViewport = toRef<boolean>(props.lockViewport);
86
+ const open = defineModel<boolean>()
87
+ const bodyTag = ref<HTMLBodyElement | null>(null)
88
+ const lockViewport = toRef<boolean>(props.lockViewport)
72
89
 
73
90
  const closeDialog = () => {
74
- open.value = false;
91
+ open.value = false
75
92
 
76
93
  if (lockViewport.value && bodyTag.value !== null) {
77
- bodyTag.value.classList.remove('lock');
94
+ bodyTag.value.classList.remove("lock")
78
95
  }
79
- };
96
+ }
80
97
 
81
- const slots = useSlots();
82
- const hasDialogTitle = computed(() => slots.dialogTitle !== undefined);
83
- const hasDialogContent = computed(() => slots.dialogContent !== undefined);
84
- const hasActionButtons = computed(() => slots.actionButtons !== undefined);
98
+ const slots = useSlots()
85
99
 
86
100
  onMounted(() => {
87
- bodyTag.value = document.querySelector('body');
101
+ bodyTag.value = document.querySelector("body")
88
102
  if (lockViewport.value && bodyTag.value !== null) {
89
- bodyTag.value.classList.add('lock');
103
+ bodyTag.value.classList.add("lock")
90
104
  }
91
- });
105
+ })
92
106
  </script>
93
107
 
94
108
  <style lang="css">
@@ -121,26 +135,26 @@ onMounted(() => {
121
135
  }
122
136
 
123
137
  /* * Positioning the dialog */
124
- &[justify-dialog='start'] {
138
+ &[justify-dialog="start"] {
125
139
  justify-content: flex-start;
126
140
  }
127
141
 
128
- &[justify-dialog='center'] {
142
+ &[justify-dialog="center"] {
129
143
  justify-content: center;
130
144
  }
131
145
 
132
- &[justify-dialog='end'] {
146
+ &[justify-dialog="end"] {
133
147
  justify-content: flex-end;
134
148
  }
135
149
 
136
- &[align-dialog='start'] {
150
+ &[align-dialog="start"] {
137
151
  align-items: flex-start;
138
152
  }
139
153
 
140
- &[align-dialog='center'] {
154
+ &[align-dialog="center"] {
141
155
  align-items: center;
142
156
  }
143
- &[align-dialog='end'] {
157
+ &[align-dialog="end"] {
144
158
  align-items: flex-end;
145
159
  }
146
160
 
@@ -1,21 +1,35 @@
1
1
  <template>
2
- <div class="display-prompt-core" :class="[{ dismissed: hide }, { 'use-local-style-overrides': useLocalStyleOverrides }]" :data-test-id="`display-prompt-core-${theme}`">
3
- <div class="display-prompt-wrapper" :data-component-theme="theme" :class="[elementClasses]" data-test-id="display-prompt">
2
+ <div
3
+ class="display-prompt-core"
4
+ :class="[{ dismissed: hide }, { 'use-local-style-overrides': useLocalStyleOverrides }]"
5
+ :data-test-id="`display-prompt-core-${theme}`"
6
+ >
7
+ <div
8
+ class="display-prompt-wrapper"
9
+ :data-component-theme="theme"
10
+ :class="[elementClasses]"
11
+ data-test-id="display-prompt"
12
+ >
4
13
  <div class="display-prompt-inner">
5
14
  <div class="display-prompt-icon" data-test-id="prompt-icon">
6
15
  <slot name="customDecoratorIcon">
7
- <Icon :name="displayPromptIcons[theme]" class="icon" :color="iconColor" />
16
+ <Icon :name="displayPromptIcons[theme] ?? 'akar-icons:circle-alert'" class="icon" :color="iconColor" />
8
17
  </slot>
9
18
  </div>
10
19
  <div class="display-prompt-content">
11
20
  <p class="title" data-test-id="display-prompt-title">
12
21
  <slot name="title"></slot>
13
22
  </p>
14
- <p v-if="hasContent" class="text" data-test-id="display-prompt-content">
23
+ <p v-if="slots.content" class="text" data-test-id="display-prompt-content">
15
24
  <slot name="content"></slot>
16
25
  </p>
17
26
  </div>
18
- <button v-if="dismissible" @click.prevent="dismissPrompt()" data-test-id="display-prompt-action" class="display-prompt-action">
27
+ <button
28
+ v-if="dismissible"
29
+ @click.prevent="dismissPrompt()"
30
+ data-test-id="display-prompt-action"
31
+ class="display-prompt-action"
32
+ >
19
33
  <slot name="customCloseIcon">
20
34
  <Icon name="bitcoin-icons:cross-filled" class="icon" />
21
35
  </slot>
@@ -36,9 +50,9 @@ const props = defineProps({
36
50
  },
37
51
  theme: {
38
52
  type: String,
39
- default: 'error',
53
+ default: "error",
40
54
  validator(value: string) {
41
- return ['error', 'info', 'success', 'warning', 'secondary'].includes(value);
55
+ return ["error", "info", "success", "warning", "secondary"].includes(value)
42
56
  },
43
57
  },
44
58
  styleClassPassthrough: {
@@ -47,9 +61,9 @@ const props = defineProps({
47
61
  },
48
62
  iconColor: {
49
63
  type: String as PropType<string>,
50
- default: 'dark-grey',
64
+ default: "dark-grey",
51
65
  validator(value: string) {
52
- return ['dark-grey', 'white'].includes(value);
66
+ return ["dark-grey", "white"].includes(value)
53
67
  },
54
68
  },
55
69
  useLocalStyleOverrides: {
@@ -59,24 +73,23 @@ const props = defineProps({
59
73
  displayPromptIcons: {
60
74
  type: Object as PropType<Record<string, string>>,
61
75
  default: () => ({
62
- error: 'akar-icons:circle-alert',
63
- info: 'akar-icons:info',
64
- success: 'akar-icons:check',
65
- warning: 'akar-icons:circle-alert',
66
- secondary: 'akar-icons:info',
76
+ error: "akar-icons:circle-alert",
77
+ info: "akar-icons:info",
78
+ success: "akar-icons:check",
79
+ warning: "akar-icons:circle-alert",
80
+ secondary: "akar-icons:info",
67
81
  }),
68
82
  },
69
- });
83
+ })
70
84
 
71
- const slots = useSlots();
72
- const hasContent = ref(slots.content !== undefined);
73
- const hide = ref(false);
74
- const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
85
+ const slots = useSlots()
86
+ const hide = ref(false)
87
+ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
75
88
 
76
89
  const dismissPrompt = () => {
77
90
  // styleClassPassthrough.value = '';
78
- hide.value = true;
79
- };
91
+ hide.value = true
92
+ }
80
93
  </script>
81
94
 
82
95
  <style lang="css">
@@ -6,7 +6,7 @@
6
6
  <template #title>
7
7
  <slot name="title"></slot>
8
8
  </template>
9
- <template v-if="hasContent" #content>
9
+ <template v-if="slots.content" #content>
10
10
  <slot name="content"></slot>
11
11
  </template>
12
12
  </DisplayPromptCore>
@@ -22,11 +22,9 @@ const props = defineProps({
22
22
  type: Array as PropType<string[]>,
23
23
  default: () => [],
24
24
  },
25
- });
25
+ })
26
26
 
27
- const slots = useSlots();
28
- const hasContent = ref(slots.content !== undefined);
29
- const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
27
+ const slots = useSlots()
30
28
  </script>
31
29
 
32
30
  <style lang="css">
@@ -24,11 +24,11 @@
24
24
  const props = defineProps({
25
25
  name: {
26
26
  type: String,
27
- default: '',
27
+ default: "",
28
28
  },
29
29
  iconSize: {
30
30
  type: String,
31
- default: 'medium',
31
+ default: "medium",
32
32
  },
33
33
  animationDuration: {
34
34
  type: Number,
@@ -38,15 +38,15 @@ const props = defineProps({
38
38
  type: Array as PropType<string[]>,
39
39
  default: () => [],
40
40
  },
41
- });
41
+ })
42
42
 
43
- const name = computed(() => props.name || useId());
43
+ const name = computed(() => props.name || useId())
44
44
 
45
- const triggerId = computed(() => `id-${name.value}-trigger`);
46
- const contentId = computed(() => `id-${name.value}-content`);
47
- const animationDurationStr = computed(() => `${props.animationDuration}ms`);
45
+ const triggerId = computed(() => `id-${name.value}-trigger`)
46
+ const contentId = computed(() => `id-${name.value}-content`)
47
+ const animationDurationStr = computed(() => `${props.animationDuration}ms`)
48
48
 
49
- const { elementClasses, resetElementClasses, updateElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
49
+ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
50
50
  </script>
51
51
 
52
52
  <style lang="css">
@@ -1,13 +1,23 @@
1
1
  <template>
2
2
  <div class="navigation" :class="[elementClasses, { loaded: navLoaded }]" ref="navigationWrapper" role="banner">
3
3
  <nav class="main-navigation" ref="mainNav" aria-label="Main navigation">
4
- <ul v-for="(navGroup, groupKey) in responsiveNavLinks" :key="groupKey" class="main-navigation-list" :ref="el => setNavRef(String(groupKey), el as HTMLUListElement | null)">
4
+ <ul
5
+ v-for="(navGroup, groupKey) in responsiveNavLinks"
6
+ :key="groupKey"
7
+ class="main-navigation-list"
8
+ :ref="el => setNavRef(String(groupKey), el as HTMLUListElement | null)"
9
+ >
5
10
  <template v-for="(link, localIndex) in navGroup" :key="localIndex">
6
11
  <li
7
12
  v-if="link.path"
8
13
  class="main-navigation-item"
9
- :class="{ 'visually-hidden': !mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.visible }"
10
- :style="{ '--_main-navigation-item-width': mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.width + 'px' }"
14
+ :class="{
15
+ 'visually-hidden': !mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.visible,
16
+ }"
17
+ :style="{
18
+ '--_main-navigation-item-width':
19
+ mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.width + 'px',
20
+ }"
11
21
  ref="mainNavigationItems"
12
22
  :data-group-key="groupKey"
13
23
  :data-local-index="localIndex"
@@ -22,8 +32,13 @@
22
32
  <li
23
33
  v-else
24
34
  class="main-navigation-item"
25
- :class="{ 'visually-hidden': !mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.visible }"
26
- :style="{ '--_main-navigation-item-width': mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.width + 'px' }"
35
+ :class="{
36
+ 'visually-hidden': !mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.visible,
37
+ }"
38
+ :style="{
39
+ '--_main-navigation-item-width':
40
+ mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.width + 'px',
41
+ }"
27
42
  ref="mainNavigationItems"
28
43
  :data-group-key="groupKey"
29
44
  :data-local-index="localIndex"
@@ -45,7 +60,9 @@
45
60
  <div class="main-navigation-sub-nav" role="menu" :aria-labelledby="`summary-${groupKey}-${localIndex}`">
46
61
  <ul class="main-navigation-sub-nav-list">
47
62
  <li class="main-navigation-sub-nav-item" v-for="childLink in link.childLinks" :key="childLink.name">
48
- <NuxtLink :to="childLink.path" class="main-navigation-sub-nav-link" role="menuitem">{{ childLink.name }}</NuxtLink>
63
+ <NuxtLink :to="childLink.path" class="main-navigation-sub-nav-link" role="menuitem">
64
+ {{ childLink.name }}
65
+ </NuxtLink>
49
66
  </li>
50
67
  </ul>
51
68
  </div>
@@ -55,16 +72,31 @@
55
72
  </ul>
56
73
  </nav>
57
74
  <nav class="secondary-navigation" ref="secondaryNav" aria-label="Secondary navigation">
58
- <details class="overflow-details" :class="[{ 'visually-hidden': !navLoaded || !showOverflowDetails }]" ref="overflowDetails" name="overflow-group">
75
+ <details
76
+ class="overflow-details"
77
+ :class="[{ 'visually-hidden': !navLoaded || !showOverflowDetails }]"
78
+ ref="overflowDetails"
79
+ name="overflow-group"
80
+ >
59
81
  <summary class="overflow-details-summary has-toggle-icon">
60
- <Icon :name="overflowDetailsSummaryIcons.more" class="icon" :class="[{ show: !allowNavigationCollapse }]" :aria-hidden="true" />
61
- <Icon :name="overflowDetailsSummaryIcons.burger" class="icon" :class="[{ show: allowNavigationCollapse }]" :aria-hidden="true" />
82
+ <Icon
83
+ :name="overflowDetailsSummaryIcons.more ?? 'gravity-ui:ellipsis'"
84
+ class="icon"
85
+ :class="[{ show: !allowNavigationCollapse }]"
86
+ :aria-hidden="true"
87
+ />
88
+ <Icon
89
+ :name="overflowDetailsSummaryIcons.burger ?? 'gravity-ui:bars'"
90
+ class="icon"
91
+ :class="[{ show: allowNavigationCollapse }]"
92
+ :aria-hidden="true"
93
+ />
62
94
  </summary>
63
95
  <div class="overflow-details-nav" role="menu">
64
96
  <NavigationItems :main-navigation-state="mainNavigationState" />
65
97
  </div>
66
98
  </details>
67
- <slot v-if="hasSecondaryNavigation" name="secondaryNavigation"></slot>
99
+ <slot v-if="slots.secondaryNavigation" name="secondaryNavigation"></slot>
68
100
  </nav>
69
101
  <LayoutRow tag="div" variant="full" :style-class-passthrough="['mb-20', 'debug-grid']">
70
102
  <ClientOnly>
@@ -85,8 +117,8 @@
85
117
  </template>
86
118
 
87
119
  <script setup lang="ts">
88
- import { useResizeObserver, onClickOutside } from '@vueuse/core';
89
- import type { ResponsiveHeaderProp, ResponsiveHeaderState, IFlooredRect } from '@/types/responsiveHeader';
120
+ import { useResizeObserver, onClickOutside } from "@vueuse/core"
121
+ import type { ResponsiveHeaderProp, ResponsiveHeaderState, IFlooredRect } from "@/types/responsiveHeader"
90
122
 
91
123
  const props = defineProps({
92
124
  responsiveNavLinks: {
@@ -100,8 +132,8 @@ const props = defineProps({
100
132
  overflowDetailsSummaryIcons: {
101
133
  type: Object as PropType<Record<string, string>>,
102
134
  default: {
103
- more: 'gravity-ui:ellipsis',
104
- burger: 'gravity-ui:bars',
135
+ more: "gravity-ui:ellipsis",
136
+ burger: "gravity-ui:bars",
105
137
  },
106
138
  },
107
139
  collapseBreakpoint: {
@@ -120,67 +152,68 @@ const props = defineProps({
120
152
  type: Boolean,
121
153
  default: true,
122
154
  },
123
- });
155
+ })
124
156
 
125
- const slots = useSlots();
126
- const hasSecondaryNavigation = computed(() => slots.secondaryNavigation !== undefined);
127
- const collapseNavigationBelowWidth = computed(() => props.collapseBreakpoint !== null || props.collapseAtMainNavIntersection);
128
- const collapseBreakpoint = ref(props.collapseBreakpoint);
129
- const navLoaded = ref(false);
130
- const navigationWrapperRef = useTemplateRef('navigationWrapper');
157
+ const slots = useSlots()
158
+ const collapseNavigationBelowWidth = computed(
159
+ () => props.collapseBreakpoint !== null || props.collapseAtMainNavIntersection
160
+ )
161
+ const collapseBreakpoint = ref(props.collapseBreakpoint)
162
+ const navLoaded = ref(false)
163
+ const navigationWrapperRef = useTemplateRef("navigationWrapper")
131
164
 
132
165
  const closeAllNavigationDetails = () => {
133
166
  navigationDetailsRefs.value?.forEach((element) => {
134
- element?.removeAttribute('open');
135
- });
136
- overflowDetailsRef.value?.removeAttribute('open');
137
- };
167
+ element?.removeAttribute("open")
168
+ })
169
+ overflowDetailsRef.value?.removeAttribute("open")
170
+ }
138
171
 
139
172
  const toggleDetailsElement = (event: Event) => {
140
- const summaryElement = event.currentTarget as HTMLElement;
141
- const parentDetailsElement = summaryElement.closest('details');
142
- if (!parentDetailsElement) return;
173
+ const summaryElement = event.currentTarget as HTMLElement
174
+ const parentDetailsElement = summaryElement.closest("details")
175
+ if (!parentDetailsElement) return
143
176
 
144
- if (parentDetailsElement.hasAttribute('open')) {
145
- parentDetailsElement.removeAttribute('open');
177
+ if (parentDetailsElement.hasAttribute("open")) {
178
+ parentDetailsElement.removeAttribute("open")
146
179
  } else {
147
- parentDetailsElement.setAttribute('open', '');
180
+ parentDetailsElement.setAttribute("open", "")
148
181
  }
149
- overflowDetailsRef.value?.removeAttribute('open');
150
- };
182
+ overflowDetailsRef.value?.removeAttribute("open")
183
+ }
151
184
 
152
185
  const handleSummaryHover = (event: MouseEvent | FocusEvent) => {
153
186
  if (!props.allowExpandOnGesture) {
154
- return;
187
+ return
155
188
  }
156
189
 
157
190
  // Close all other open navigation details first
158
- const summaryElement = event.currentTarget as HTMLElement;
159
- const parentDetailsElement = summaryElement.closest('details');
191
+ const summaryElement = event.currentTarget as HTMLElement
192
+ const parentDetailsElement = summaryElement.closest("details")
160
193
 
161
194
  navigationDetailsRefs.value?.forEach((element) => {
162
195
  if (element !== parentDetailsElement) {
163
- element?.removeAttribute('open');
196
+ element?.removeAttribute("open")
164
197
  }
165
- });
166
- overflowDetailsRef.value?.removeAttribute('open');
198
+ })
199
+ overflowDetailsRef.value?.removeAttribute("open")
167
200
 
168
201
  // Then toggle the current one
169
- toggleDetailsElement(event);
170
- };
202
+ toggleDetailsElement(event)
203
+ }
171
204
 
172
205
  const handleNavigationItemHover = () => {
173
206
  if (!props.allowExpandOnGesture) {
174
- return;
207
+ return
175
208
  }
176
209
 
177
210
  // Close all open navigation details when hovering over regular nav items
178
- closeAllNavigationDetails();
179
- };
211
+ closeAllNavigationDetails()
212
+ }
180
213
 
181
214
  const handleSummaryAction = (event: MouseEvent | KeyboardEvent) => {
182
- toggleDetailsElement(event);
183
- };
215
+ toggleDetailsElement(event)
216
+ }
184
217
 
185
218
  const mainNavigationState = ref<ResponsiveHeaderState>({
186
219
  navListVisibility: {
@@ -189,51 +222,53 @@ const mainNavigationState = ref<ResponsiveHeaderState>({
189
222
  },
190
223
  clonedNavLinks: props.responsiveNavLinks,
191
224
  hasSecondNav: Object.keys(props.responsiveNavLinks).length > 1,
192
- });
225
+ })
193
226
 
194
- const navRefs = ref<Record<string, HTMLUListElement | null>>({});
227
+ const navRefs = ref<Record<string, HTMLUListElement | null>>({})
195
228
 
196
229
  const setNavRef = (key: string, el: HTMLUListElement | null) => {
197
- navRefs.value[key] = el;
198
- };
230
+ navRefs.value[key] = el
231
+ }
199
232
 
200
- const navigationWrapperRects = ref<IFlooredRect | null>(null);
201
- const firstNavRef = ref<HTMLUListElement | null>(null);
202
- const firstNavRects = ref<IFlooredRect | null>(null);
233
+ const navigationWrapperRects = ref<IFlooredRect | null>(null)
234
+ const firstNavRef = ref<HTMLUListElement | null>(null)
235
+ const firstNavRects = ref<IFlooredRect | null>(null)
203
236
 
204
- const secondNavRef = ref<HTMLUListElement | null>(null);
205
- const secondNavRects = ref<IFlooredRect | null>(null);
237
+ const secondNavRef = ref<HTMLUListElement | null>(null)
238
+ const secondNavRects = ref<IFlooredRect | null>(null)
206
239
 
207
- const secondaryNavRef = useTemplateRef('secondaryNav');
208
- const secondaryNavRects = ref<IFlooredRect | null>(null);
240
+ const secondaryNavRef = useTemplateRef("secondaryNav")
241
+ const secondaryNavRects = ref<IFlooredRect | null>(null)
209
242
 
210
- const mainNavigationItemsRefs = useTemplateRef<HTMLLIElement[]>('mainNavigationItems');
243
+ const mainNavigationItemsRefs = useTemplateRef<HTMLLIElement[]>("mainNavigationItems")
211
244
 
212
- const navigationDetailsRefs = useTemplateRef<HTMLElement[]>('navigationDetails');
245
+ const navigationDetailsRefs = useTemplateRef<HTMLElement[]>("navigationDetails")
213
246
 
214
- const overflowDetailsRef = useTemplateRef('overflowDetails');
247
+ const overflowDetailsRef = useTemplateRef("overflowDetails")
215
248
 
216
249
  const showOverflowDetails = computed(() => {
217
- const hasHiddenNav = !mainNavigationState.value.navListVisibility['firstNav'] || (!mainNavigationState.value.navListVisibility['secondNav'] && mainNavigationState.value.hasSecondNav);
218
- return hasHiddenNav;
219
- });
250
+ const hasHiddenNav =
251
+ !mainNavigationState.value.navListVisibility["firstNav"] ||
252
+ (!mainNavigationState.value.navListVisibility["secondNav"] && mainNavigationState.value.hasSecondNav)
253
+ return hasHiddenNav
254
+ })
220
255
 
221
256
  const mainNavigationMarginBlockEnd = computed(() => {
222
- return secondaryNavRects.value ? secondaryNavRects.value.width + props.gapBetweenFirstAndSecondNav : 0;
223
- });
257
+ return secondaryNavRects.value ? secondaryNavRects.value.width + props.gapBetweenFirstAndSecondNav : 0
258
+ })
224
259
 
225
260
  const mainNavigationMarginBlockEndStr = computed(() => {
226
- return mainNavigationMarginBlockEnd.value + 'px';
227
- });
261
+ return mainNavigationMarginBlockEnd.value + "px"
262
+ })
228
263
 
229
264
  const initTemplateRefs = async () => {
230
- firstNavRef.value = navRefs.value['firstNav'] as HTMLUListElement | null;
231
- secondNavRef.value = navRefs.value['secondNav'] as HTMLUListElement | null;
232
- return;
233
- };
265
+ firstNavRef.value = navRefs.value["firstNav"] as HTMLUListElement | null
266
+ secondNavRef.value = navRefs.value["secondNav"] as HTMLUListElement | null
267
+ return
268
+ }
234
269
 
235
270
  const getFlooredRect = (rect: DOMRect | null) => {
236
- if (!rect) return null;
271
+ if (!rect) return null
237
272
  return {
238
273
  left: Math.floor(rect.left),
239
274
  right: Math.floor(rect.right),
@@ -241,19 +276,22 @@ const getFlooredRect = (rect: DOMRect | null) => {
241
276
  bottom: Math.floor(rect.bottom),
242
277
  width: Math.floor(rect.width),
243
278
  height: Math.floor(rect.height),
244
- };
245
- };
279
+ }
280
+ }
246
281
 
247
282
  const updateNavigationConfig = async (source: string) => {
248
- navigationWrapperRects.value = getFlooredRect((navigationWrapperRef.value && navigationWrapperRef.value.getBoundingClientRect()) ?? null) || null;
249
- secondaryNavRects.value = getFlooredRect((secondaryNavRef.value && secondaryNavRef.value.getBoundingClientRect()) ?? null) || null;
250
- firstNavRects.value = getFlooredRect((firstNavRef.value && firstNavRef.value.getBoundingClientRect()) ?? null) || null;
251
- secondNavRects.value = getFlooredRect((secondNavRef.value && secondNavRef.value.getBoundingClientRect()) ?? null) || null;
283
+ navigationWrapperRects.value =
284
+ getFlooredRect((navigationWrapperRef.value && navigationWrapperRef.value.getBoundingClientRect()) ?? null) || null
285
+ secondaryNavRects.value =
286
+ getFlooredRect((secondaryNavRef.value && secondaryNavRef.value.getBoundingClientRect()) ?? null) || null
287
+ firstNavRects.value = getFlooredRect((firstNavRef.value && firstNavRef.value.getBoundingClientRect()) ?? null) || null
288
+ secondNavRects.value =
289
+ getFlooredRect((secondNavRef.value && secondNavRef.value.getBoundingClientRect()) ?? null) || null
252
290
 
253
291
  if (collapseNavigationBelowWidth.value && firstNavRects.value) {
254
- collapseBreakpoint.value = firstNavRects.value?.right;
292
+ collapseBreakpoint.value = firstNavRects.value?.right
255
293
  }
256
- };
294
+ }
257
295
 
258
296
  const allowNavigationCollapse = computed(() => {
259
297
  return (
@@ -261,32 +299,35 @@ const allowNavigationCollapse = computed(() => {
261
299
  navigationWrapperRects.value &&
262
300
  secondaryNavRects.value !== null &&
263
301
  Math.floor(secondaryNavRects.value.left - props.gapBetweenFirstAndSecondNav) <= collapseBreakpoint.value
264
- );
265
- });
302
+ )
303
+ })
266
304
 
267
305
  const determineNavigationItemVisibility = (rect: DOMRect) => {
268
306
  // Check if navigation should be collapsed based on width breakpoint
269
307
  if (allowNavigationCollapse.value) {
270
- return false;
308
+ return false
271
309
  }
272
310
 
273
311
  // Use default responsive visibility logic if wrapper exists
274
312
  if (navigationWrapperRects.value) {
275
- return Math.floor(rect.right + mainNavigationMarginBlockEnd.value + props.gapBetweenFirstAndSecondNav) < navigationWrapperRects.value.right;
313
+ return (
314
+ Math.floor(rect.right + mainNavigationMarginBlockEnd.value + props.gapBetweenFirstAndSecondNav) <
315
+ navigationWrapperRects.value.right
316
+ )
276
317
  }
277
318
 
278
319
  // Default to visible
279
- return true;
280
- };
320
+ return true
321
+ }
281
322
 
282
323
  const initMainNavigationState = () => {
283
- if (!mainNavigationItemsRefs.value) return;
324
+ if (!mainNavigationItemsRefs.value) return
284
325
 
285
326
  mainNavigationItemsRefs.value.forEach((item, index) => {
286
- const rect = item.getBoundingClientRect();
327
+ const rect = item.getBoundingClientRect()
287
328
 
288
- const groupKey = item.dataset.groupKey;
289
- const localIndex = item.dataset.localIndex ? parseInt(item.dataset.localIndex, 10) : 0;
329
+ const groupKey = item.dataset.groupKey
330
+ const localIndex = item.dataset.localIndex ? parseInt(item.dataset.localIndex, 10) : 0
290
331
  if (
291
332
  groupKey !== undefined &&
292
333
  groupKey !== null &&
@@ -302,56 +343,57 @@ const initMainNavigationState = () => {
302
343
  width: item.offsetWidth,
303
344
  visible: determineNavigationItemVisibility(rect),
304
345
  },
305
- };
346
+ }
306
347
  }
307
348
 
308
349
  // Check if a single item has visible set to false and set the visibility of the group accordingly
309
350
  if (
310
- typeof groupKey === 'string' &&
351
+ typeof groupKey === "string" &&
311
352
  mainNavigationState.value.clonedNavLinks &&
312
353
  mainNavigationState.value.clonedNavLinks[groupKey] &&
354
+ mainNavigationState.value.clonedNavLinks[groupKey][localIndex] &&
313
355
  mainNavigationState.value.clonedNavLinks[groupKey][localIndex].config?.visible === false
314
356
  ) {
315
- mainNavigationState.value.navListVisibility[groupKey] = false;
316
- } else if (typeof groupKey === 'string') {
317
- mainNavigationState.value.navListVisibility[groupKey] = true;
357
+ mainNavigationState.value.navListVisibility[groupKey] = false
358
+ } else if (typeof groupKey === "string") {
359
+ mainNavigationState.value.navListVisibility[groupKey] = true
318
360
  }
319
- });
320
- };
361
+ })
362
+ }
321
363
 
322
364
  onMounted(async () => {
323
365
  await initTemplateRefs().then(() => {
324
366
  setTimeout(() => {
325
- navLoaded.value = true;
326
- }, 100);
327
- });
367
+ navLoaded.value = true
368
+ }, 100)
369
+ })
328
370
 
329
371
  navigationDetailsRefs.value?.forEach((element, index) => {
330
372
  onClickOutside(element, () => {
331
- navigationDetailsRefs.value?.[index]?.removeAttribute('open');
332
- });
333
- });
373
+ navigationDetailsRefs.value?.[index]?.removeAttribute("open")
374
+ })
375
+ })
334
376
  // Add onClickOutside to overflowDetailsRef
335
377
  overflowDetailsRef.value &&
336
378
  onClickOutside(overflowDetailsRef.value, () => {
337
- overflowDetailsRef.value?.removeAttribute('open');
338
- });
339
- });
379
+ overflowDetailsRef.value?.removeAttribute("open")
380
+ })
381
+ })
340
382
 
341
383
  useResizeObserver(navigationWrapperRef, async () => {
342
- await updateNavigationConfig('useResizeObserver').then(() => {
343
- initMainNavigationState();
344
- });
345
- });
384
+ await updateNavigationConfig("useResizeObserver").then(() => {
385
+ initMainNavigationState()
386
+ })
387
+ })
346
388
 
347
- const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
389
+ const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
348
390
 
349
391
  watch(
350
392
  () => props.styleClassPassthrough,
351
393
  () => {
352
- resetElementClasses(props.styleClassPassthrough);
394
+ resetElementClasses(props.styleClassPassthrough)
353
395
  }
354
- );
396
+ )
355
397
  </script>
356
398
 
357
399
  <style lang="css">
@@ -378,7 +420,7 @@ watch(
378
420
 
379
421
  /* flex-grow: 1; */
380
422
  display: grid;
381
- grid-template-areas: 'navStack';
423
+ grid-template-areas: "navStack";
382
424
 
383
425
  margin: 12px;
384
426
  border-radius: 8px;
@@ -599,7 +641,7 @@ watch(
599
641
  --_transition-duration: 0.2s;
600
642
 
601
643
  display: grid;
602
- grid-template-areas: 'icon';
644
+ grid-template-areas: "icon";
603
645
  align-items: center;
604
646
  justify-content: center;
605
647
  padding-inline: 5px;
@@ -1,13 +1,15 @@
1
1
  <template>
2
2
  <ul class="home-link-navigation" aria-label="Home Navigation">
3
- <li v-if="hasHomeLink" class="home-link">
3
+ <li v-if="slots.homeLink" class="home-link">
4
4
  <slot name="homeLink">
5
5
  <NuxtLink to="/" class="home-link-default">Logo</NuxtLink>
6
6
  </slot>
7
7
  </li>
8
8
  <li class="skip-links">
9
9
  <ul class="skip-links-nav">
10
- <li class="skip-link-item"><a href="#main-content" class="skip-link" ref="skipLink">Skip to main content</a></li>
10
+ <li class="skip-link-item">
11
+ <a href="#main-content" class="skip-link" ref="skipLink">Skip to main content</a>
12
+ </li>
11
13
  <li class="skip-link-item"><a href="#footer" class="skip-link">Skip to footer</a></li>
12
14
  </ul>
13
15
  </li>
@@ -15,8 +17,7 @@
15
17
  </template>
16
18
 
17
19
  <script lang="ts" setup>
18
- const slots = useSlots();
19
- const hasHomeLink = ref(slots.homeLink !== undefined);
20
+ const slots = useSlots()
20
21
  </script>
21
22
 
22
23
  <style lang="css">
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "6.1.0",
4
+ "version": "6.1.1",
5
5
  "main": "nuxt.config.ts",
6
6
  "scripts": {
7
7
  "clean": "rm -rf .nuxt && rm -rf .output && rm -rf .playground/.nuxt && rm -rf .playground/.output",