@simple-reporting/base 1.0.12 → 1.0.14

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.
Files changed (40) hide show
  1. package/dev/package.json +15 -15
  2. package/dev/src/assets/scss/app.scss +1 -0
  3. package/dev/src/assets/scss/components/note/accordion.scss +108 -0
  4. package/dev/src/assets/scss/editor.scss +45 -0
  5. package/dev/src/assets/scss/general.scss +1 -0
  6. package/dev/src/components/BypassLinks.vue +3 -5
  7. package/dev/tsconfig.json +1 -1
  8. package/dev/vite.config.ts +1 -1
  9. package/livingdocs/040.Media/030.video/ld-conf.json +1 -1
  10. package/livingdocs/100.Misc/010.anchor/anchor.html +3 -6
  11. package/livingdocs/100.Misc/010.anchor/scss/editor.scss +1 -12
  12. package/livingdocs/110.PDF/010.pdf-pagebreak/pdf-pagebreak.html +2 -2
  13. package/livingdocs/110.PDF/010.pdf-pagebreak/scss/editor.scss +0 -8
  14. package/livingdocs/110.PDF/030.pdf-publication-title/pdf-publication-title.html +2 -5
  15. package/livingdocs/110.PDF/030.pdf-publication-title/scss/editor.scss +0 -11
  16. package/livingdocs/110.PDF/040.pdf-chapter-title/pdf-chapter-title.html +2 -5
  17. package/livingdocs/110.PDF/040.pdf-chapter-title/scss/editor.scss +0 -5
  18. package/package.json +7 -7
  19. package/plugins/viteSrlPlugin.js +270 -0
  20. package/scripts/prepare.d.ts +1 -1
  21. package/scripts/prepare.js +3 -58
  22. package/srl/components/Srl/Menu/Item/Content/Icon.vue +17 -1
  23. package/srl/components/Srl/Menu/Item/Content/IconAfter.vue +26 -3
  24. package/srl/components/Srl/Menu/Item/Content/IconBefore.vue +27 -3
  25. package/srl/components/Srl/Menu/Item/Content/Image.vue +13 -1
  26. package/srl/components/Srl/Menu/Item/Content/ImageAfter.vue +21 -2
  27. package/srl/components/Srl/Menu/Item/Content/ImageBefore.vue +21 -2
  28. package/srl/components/Srl/Menu/Item/Content/Text.vue +14 -3
  29. package/srl/components/Srl/Menu/Item/Content.vue +21 -2
  30. package/srl/components/Srl/Menu/Item.vue +124 -77
  31. package/srl/components/Srl/Menu/List.vue +97 -57
  32. package/srl/components/Srl/Note/Accordion/Content.vue +54 -3
  33. package/srl/components/Srl/Note/Accordion/Toggle.vue +14 -4
  34. package/srl/components/Srl/Note/Accordion.vue +30 -7
  35. package/srl/plugins/vueSrlPlugin.ts +4 -7
  36. package/srl/tsconfig.srl.json +89 -0
  37. package/srl/types/components.d.ts +3 -0
  38. package/srl/utils/html.ts +3 -3
  39. package/srl/utils/uri.ts +3 -1
  40. package/srl/plugins/viteSrlPlugin.ts +0 -224
@@ -1,41 +1,42 @@
1
1
  <script setup lang="ts">
2
- import { computed, nextTick, ref, useId } from 'vue';
3
- import MenuItemContent from './Item/Content.vue';
4
- import MenuList from './List.vue';
5
- import type { RouterLink } from 'vue-router';
6
- import { isExternalPath } from '#utils/uri';
2
+ import { computed, nextTick, ref, useId } from 'vue'
3
+ import MenuItemContent from './Item/Content.vue'
4
+ import MenuList from './List.vue'
5
+ import type { RouterLink } from 'vue-router'
6
+ import { isExternalPath } from '#utils/uri'
7
7
 
8
8
  type BackButtonItem = {
9
- title?: string;
9
+ title?: string
10
10
  img?: {
11
- src: string;
12
- alt?: string;
13
- };
11
+ src: string
12
+ alt?: string
13
+ }
14
14
  imgBefore?: {
15
- src: string;
16
- alt?: string;
17
- };
15
+ src: string
16
+ alt?: string
17
+ }
18
18
  imgAfter?: {
19
- src: string;
20
- alt?: string;
21
- };
19
+ src: string
20
+ alt?: string
21
+ }
22
22
  attributes?: {
23
- [key: string]: string;
24
- };
25
- };
23
+ [key: string]: string
24
+ }
25
+ }
26
26
 
27
27
  const props = defineProps<{
28
- name: string;
29
- item: NsWowNavigationItem;
30
- index: number | string;
31
- disableTab: boolean;
32
- disableTabIndex: boolean;
33
- initOpen: number;
34
- depth: number;
35
- backButonEnabled?: boolean;
36
- backButtonLabel?: string;
28
+ name: string
29
+ item: NsWowNavigationItem
30
+ index: number | string
31
+ disableTab: boolean
32
+ disableTabIndex: boolean
33
+ initOpen: number
34
+ depth: number
35
+ disableClasses: boolean
36
+ backButonEnabled?: boolean
37
+ backButtonLabel?: string
37
38
  backButtonItem: BackButtonItem
38
- }>();
39
+ }>()
39
40
 
40
41
  const emit = defineEmits([
41
42
  'open',
@@ -46,109 +47,135 @@ const emit = defineEmits([
46
47
  'prev',
47
48
  'tab',
48
49
  'back',
49
- ]);
50
- const id = ref<number | string | undefined>();
50
+ ])
51
+ const id = ref<number | string | undefined>()
51
52
  if (props.item.children) {
52
- id.value = useId();
53
+ id.value = useId()
53
54
  }
54
55
 
55
- const external = ref(props.item.href && isExternalPath(props.item.href));
56
+ const external = ref(props.item.href && isExternalPath(props.item.href))
56
57
 
57
- const menu = ref();
58
- const $el = ref<HTMLButtonElement | HTMLAnchorElement | typeof RouterLink>();
59
- const opened = ref(false);
58
+ const menu = ref()
59
+ const $el = ref<HTMLButtonElement | HTMLAnchorElement | typeof RouterLink>()
60
+ const opened = ref(false)
60
61
 
61
62
  function toggle() {
62
- opened.value = !opened.value;
63
+ opened.value = !opened.value
63
64
  if (opened.value) {
64
- emit('open', { index: props.index });
65
+ emit('open', { index: props.index })
65
66
  nextTick(() => {
66
- const item = menu.value?.items[0].$el;
67
- item.$el ? item.$el.focus() : item.focus();
68
- });
67
+ menu.value.$el.focus()
68
+ })
69
69
  } else {
70
- menu.value.closeAll();
70
+ menu.value.closeAll()
71
71
  }
72
72
  }
73
-
74
73
  function close() {
75
- emit('close', { index: props.index });
74
+ emit('close', { index: props.index })
76
75
  }
77
76
 
78
77
  function closeSub() {
79
- $el.value?.focus();
78
+ $el.value?.focus()
80
79
  }
81
80
 
82
81
  function next() {
83
- emit('next', { index: props.index });
82
+ emit('next', { index: props.index })
84
83
  }
85
84
 
86
85
  function prev() {
87
- emit('prev', { index: props.index });
86
+ emit('prev', { index: props.index })
88
87
  }
89
88
 
90
89
  function tab(event: KeyboardEvent) {
91
90
  if (props.disableTab && event) {
92
- event.stopPropagation();
93
- event.preventDefault();
94
- opened.value = false;
91
+ event.stopPropagation()
92
+ event.preventDefault()
93
+ opened.value = false
95
94
  }
96
- emit('tab');
95
+ emit('tab')
97
96
  }
98
97
 
99
98
  function back(event: KeyboardEvent) {
100
99
  if (props.disableTab && event) {
101
- event.stopPropagation();
102
- event.preventDefault();
100
+ event.stopPropagation()
101
+ event.preventDefault()
103
102
  }
104
- emit('back');
103
+ emit('back')
105
104
  }
106
105
 
107
106
  function link() {
108
- !props.item.callback || props.item.callback();
109
- emit('link');
107
+ !props.item.callback || props.item.callback()
108
+ emit('link')
110
109
  }
111
110
 
112
111
  function routerChange() {
113
- !props.item.callback || props.item.callback();
114
- emit('link');
115
- emit('routerChange');
112
+ !props.item.callback || props.item.callback()
113
+ emit('link')
114
+ emit('routerChange')
116
115
  }
117
116
 
118
117
  function closeItem() {
119
- opened.value = false;
120
- menu.value?.closeAll();
118
+ opened.value = false
119
+ menu.value?.closeAll()
121
120
  }
122
121
 
123
122
  defineExpose({
124
123
  closeItem,
125
124
  $el,
126
125
  menu,
127
- });
126
+ })
128
127
 
129
128
  function internalLinkClick(event: Event) {
130
- !props.item.callback || props.item.callback(event);
129
+ !props.item.callback || props.item.callback(event)
131
130
  routerChange()
132
131
  }
133
132
 
134
133
  function externalLinkClick(event: Event) {
135
- !props.item.callback || props.item.callback(event);
134
+ !props.item.callback || props.item.callback(event)
136
135
  link()
137
136
  }
138
137
 
139
138
  const dynamicAttributes = computed(() => {
140
- return props.item.attributes ?? {};
141
- });
139
+ return props.item.attributes ?? {}
140
+ })
141
+
142
+ const classListLi = computed(() => {
143
+ if (props.disableClasses) return []
144
+
145
+ const res = [
146
+ 'srl-menu__item'
147
+ ]
148
+ res.push(`srl-menu__item--level-${props.depth}`)
149
+ if (props.item.children) {
150
+ res.push('srl-menu__item--has-children')
151
+ } else {
152
+ res.push('srl-menu__item--has-no-children')
153
+ }
154
+ return res
155
+ })
156
+
157
+ const classListItem = computed(() => {
158
+ const res = []
159
+
160
+ !props.item.active || res.push('srl-menu__link--active')
161
+
162
+ if (!props.disableClasses) {
163
+ res.push('srl-menu__link')
164
+ res.push(`srl-menu__link--level-${props.depth}`)
165
+ }
166
+ return res
167
+ })
168
+
142
169
  </script>
143
170
 
144
171
  <template>
145
- <li v-if="!item.children && props.item.href">
172
+ <li v-if="!item.children && props.item.href" :class="classListLi">
146
173
  <router-link
147
174
  v-if="!external"
148
175
  ref="$el"
149
- :tabindex="props.index === 0 && !props.disableTabIndex ? 0 : -1"
176
+ tabindex="-1"
150
177
  :to="props.item.href"
151
- :class="{ active: item.active }"
178
+ :class="classListItem"
152
179
  :title="props.item.title ?? props.item.label"
153
180
  v-bind="dynamicAttributes"
154
181
  @click="internalLinkClick"
@@ -160,14 +187,19 @@ const dynamicAttributes = computed(() => {
160
187
  @keydown.shift.tab.exact="back"
161
188
  @keydown.esc.stop.prevent="close"
162
189
  >
163
- <MenuItemContent :item="props.item" />
190
+ <MenuItemContent
191
+ :item="props.item"
192
+ :depth="props.depth"
193
+ :disableClasses="props.disableClasses"
194
+ />
164
195
  </router-link>
165
196
  <a
166
197
  v-else
167
- :tabindex="props.index === 0 && !props.disableTabIndex ? 0 : -1"
198
+ tabindex="-1"
168
199
  ref="$el"
169
200
  :href="props.item.href"
170
201
  :title="props.item.title ?? props.item.label"
202
+ :class="classListItem"
171
203
  :aria-label="props.item.icon ? props.item.title ?? props.item.label : undefined"
172
204
  :target="props.item.href?.startsWith('http') ? '_blank' : undefined"
173
205
  v-bind="dynamicAttributes"
@@ -180,14 +212,19 @@ const dynamicAttributes = computed(() => {
180
212
  @keydown.shift.tab.exact="back"
181
213
  @keydown.esc.stop.prevent="close"
182
214
  >
183
- <MenuItemContent :item="props.item" />
215
+ <MenuItemContent
216
+ :item="props.item"
217
+ :depth="props.depth"
218
+ :disableClasses="props.disableClasses"
219
+ />
184
220
  </a>
185
221
  </li>
186
- <li v-else-if="props.item.callback">
222
+ <li v-else-if="props.item.callback" :class="classListLi">
187
223
  <button
188
224
  type="button"
189
225
  ref="$el"
190
- :tabindex="props.index === 0 && !props.disableTabIndex ? 0 : -1"
226
+ tabindex="-1"
227
+ :class="classListItem"
191
228
  :title="props.item.title ?? props.item.label"
192
229
  :aria-label="props.item.icon ? props.item.title ?? props.item.label : undefined"
193
230
  v-bind="dynamicAttributes"
@@ -200,17 +237,22 @@ const dynamicAttributes = computed(() => {
200
237
  @keydown.shift.tab.exact="back"
201
238
  @keydown.esc.stop.prevent="close"
202
239
  >
203
- <MenuItemContent :item="props.item" />
240
+ <MenuItemContent
241
+ :item="props.item"
242
+ :depth="props.depth"
243
+ :disableClasses="props.disableClasses"
244
+ />
204
245
  </button>
205
246
  </li>
206
- <li v-else>
247
+ <li v-else :class="classListLi">
207
248
  <button
208
249
  type="button"
209
250
  ref="$el"
210
- :tabindex="props.index === 0 ? 0 : -1"
251
+ tabindex="-1"
211
252
  :aria-haspopup="props.item.children ? 'true' : 'false'"
212
253
  :aria-expanded="opened"
213
254
  :aria-controls="`${props.name}-${id}`"
255
+ :class="classListItem"
214
256
  :title="props.item.title ?? props.item.label"
215
257
  :aria-label="props.item.icon ? props.item.title ?? props.item.label : undefined"
216
258
  v-bind="dynamicAttributes"
@@ -223,7 +265,11 @@ const dynamicAttributes = computed(() => {
223
265
  @keydown.shift.tab.exact="back"
224
266
  @keydown.esc.stop.prevent="close"
225
267
  >
226
- <MenuItemContent :item="props.item" />
268
+ <MenuItemContent
269
+ :item="props.item"
270
+ :depth="props.depth"
271
+ :disableClasses="props.disableClasses"
272
+ />
227
273
  </button>
228
274
  <MenuList
229
275
  v-if="props.item.children"
@@ -234,6 +280,7 @@ const dynamicAttributes = computed(() => {
234
280
  :disableTab="props.disableTab"
235
281
  :initOpen="props.initOpen"
236
282
  :depth="props.depth + 1"
283
+ :disableClasses="props.disableClasses"
237
284
  :backButonEnabled="props.backButonEnabled"
238
285
  :backButtonLabel="props.backButonEnabled ? props.item.label : undefined"
239
286
  :backButtonItem="props.backButtonItem"
@@ -51,40 +51,41 @@
51
51
  * />
52
52
  */
53
53
  import { computed, ref } from 'vue'
54
- import MenuItem from './Item.vue';
54
+ import MenuItem from './Item.vue'
55
55
 
56
56
  type BackButtonItem = {
57
- title?: string;
57
+ title?: string
58
58
  img?: {
59
- src: string;
60
- alt?: string;
61
- };
59
+ src: string
60
+ alt?: string
61
+ }
62
62
  imgBefore?: {
63
- src: string;
64
- alt?: string;
65
- };
63
+ src: string
64
+ alt?: string
65
+ }
66
66
  imgAfter?: {
67
- src: string;
68
- alt?: string;
69
- };
67
+ src: string
68
+ alt?: string
69
+ }
70
70
  attributes?: {
71
- [key: string]: string;
72
- };
73
- };
71
+ [key: string]: string
72
+ }
73
+ }
74
74
 
75
75
  const props = withDefaults(
76
76
  defineProps<{
77
- name: string;
78
- menu: NsWowNavigationItem[];
79
- id?: string;
80
- disableTab?: boolean;
81
- disableTabIndex?: boolean;
82
- initOpen?: number;
83
- singleOpen?: boolean;
84
- depth?: number;
85
- backButonEnabled?: boolean;
86
- backButtonItem?: BackButtonItem;
87
- backButtonLabel?: string;
77
+ name: string
78
+ menu: NsWowNavigationItem[]
79
+ id?: string
80
+ disableTab?: boolean
81
+ disableTabIndex?: boolean
82
+ initOpen?: number
83
+ singleOpen?: boolean
84
+ depth?: number
85
+ disableClasses?: boolean
86
+ backButonEnabled?: boolean
87
+ backButtonItem?: BackButtonItem
88
+ backButtonLabel?: string
88
89
  }>(),
89
90
  {
90
91
  disableTab: false,
@@ -92,9 +93,10 @@ const props = withDefaults(
92
93
  initOpen: 0,
93
94
  singleOpen: true,
94
95
  depth: 0,
96
+ disableClasses: false,
95
97
  backButtonItem: {}
96
98
  },
97
- );
99
+ )
98
100
 
99
101
  const emit = defineEmits([
100
102
  'close',
@@ -105,75 +107,92 @@ const emit = defineEmits([
105
107
  'prevExceeded',
106
108
  'tab',
107
109
  'back',
108
- ]);
109
- const items = ref<Array<typeof MenuItem>>([]);
110
+ ])
111
+ const items = ref<Array<typeof MenuItem>>([])
110
112
 
111
- const opened = defineModel('opened', { type: Boolean, default: true });
113
+ const opened = defineModel('opened', { type: Boolean, default: true })
112
114
 
113
115
  function open(event: { index: number }) {
114
116
  if (props.singleOpen) {
115
- closeAll(event.index);
117
+ closeAll(event.index)
116
118
  }
117
119
  }
118
120
 
119
121
  function close() {
120
122
  if (props.initOpen < props.depth) {
121
- opened.value = false;
122
- emit('closeSub');
123
+ opened.value = false
124
+ emit('closeSub')
123
125
  } else {
124
- emit('close');
126
+ emit('close')
125
127
  }
126
128
  }
127
129
 
128
130
  function next(event: { index: number }) {
129
- let newIndex = event.index + 1;
130
- let exceeded = false;
131
+ let newIndex = event.index + 1
132
+ let exceeded = false
131
133
  if (newIndex >= items.value.length) {
132
- exceeded = true;
133
- newIndex = 0;
134
+ exceeded = true
135
+ newIndex = 0
134
136
  }
135
- const item = items.value[newIndex].$el;
136
- item.$el ? item.$el.focus() : item.focus();
137
- !exceeded || emit('nextExceeded');
137
+ const item = items.value[newIndex].$el
138
+ item.$el ? item.$el.focus() : item.focus()
139
+ !exceeded || emit('nextExceeded')
138
140
  }
139
141
 
140
142
  function prev(event: { index: number }) {
141
- let newIndex = event.index - 1;
142
- let exceeded = false;
143
+ let newIndex = event.index - 1
144
+ let exceeded = false
143
145
  if (newIndex < 0) {
144
- exceeded = true;
145
- newIndex = items.value.length - 1;
146
+ exceeded = true
147
+ newIndex = items.value.length - 1
146
148
  }
147
- const item = items.value[newIndex].$el;
148
- item.$el ? item.$el.focus() : item.focus();
149
- !exceeded || emit('prevExceeded');
149
+ const item = items.value[newIndex].$el
150
+ item.$el ? item.$el.focus() : item.focus()
151
+ !exceeded || emit('prevExceeded')
150
152
  }
151
153
 
152
154
  function tab() {
153
- emit('tab');
155
+ emit('tab')
154
156
  }
155
157
 
156
158
  function back() {
157
- emit('back');
159
+ emit('back')
158
160
  }
159
161
 
160
162
  function link() {
161
- emit('link');
163
+ emit('link')
162
164
  }
163
165
 
164
166
  function routerChange() {
165
- emit('routerChange');
167
+ emit('routerChange')
166
168
  }
167
169
 
168
170
  function closeAll(keep?: number | string) {
169
171
  items.value.forEach((item: typeof MenuItem, index: number) => {
170
- if (keep !== index) item.closeItem();
171
- });
172
+ if (keep !== index) item.closeItem()
173
+ })
172
174
  }
173
175
 
174
- const $el = ref<HTMLUListElement>();
176
+ const $el = ref<HTMLUListElement>()
177
+
178
+ function focusClickable(index: number) {
179
+ if (items.value[index]) {
180
+ if (items.value[index].$el.$el) {
181
+ items.value[index].$el.$el.focus()
182
+ } else if (items.value[index].$el) {
183
+ items.value[index].$el.focus()
184
+ }
185
+ }
186
+ }
175
187
 
176
188
  const menuItems = computed<NsWowNavigationItem[]>(() => {
189
+ const classes: string[] = []
190
+ if (props.backButtonItem?.attributes?.class) {
191
+ props.backButtonItem.attributes.class.split(' ').forEach(c => {
192
+ classes.push(c)
193
+ })
194
+ }
195
+ classes.push('srl-menu__link--back')
177
196
  return props.backButonEnabled && props.depth ? [
178
197
  {
179
198
  label: props.backButtonLabel,
@@ -184,11 +203,13 @@ const menuItems = computed<NsWowNavigationItem[]>(() => {
184
203
  attributes: props.backButtonItem.attributes ?
185
204
  Object.assign(props.backButtonItem.attributes,
186
205
  {
206
+ 'class': classes.join(' '),
187
207
  'aria-controls': props.id,
188
208
  'aria-expanded': opened.value
189
209
  }
190
210
  ):
191
211
  {
212
+ 'class': classes.join(' '),
192
213
  'aria-controls': props.id,
193
214
  'aria-expanded': opened.value
194
215
  },
@@ -196,17 +217,35 @@ const menuItems = computed<NsWowNavigationItem[]>(() => {
196
217
  },
197
218
  ...props.menu,
198
219
  ] : props.menu
199
- });
220
+ })
221
+
222
+ const classList = computed(() => {
223
+ return props.disableClasses ? [] : [
224
+ 'srl-menu',
225
+ `srl-menu--level-${props.depth}`,
226
+ ]
227
+ })
200
228
 
201
229
  defineExpose({
202
230
  closeAll,
203
231
  $el,
204
232
  items,
205
- });
233
+ })
206
234
  </script>
207
235
 
208
236
  <template>
209
- <ul ref="$el" :id="props.id" :hidden="!opened">
237
+ <ul
238
+ ref="$el"
239
+ tabindex="0"
240
+ :id="props.id"
241
+ :class="classList"
242
+ :hidden="!opened"
243
+ @keydown.esc.prevent.stop="close"
244
+ @keydown.up.prevent.stop="focusClickable(menuItems.length - 1)"
245
+ @keydown.right.prevent.stop="focusClickable(0)"
246
+ @keydown.down.prevent.stop="focusClickable(0)"
247
+ @keydown.left.prevent.stop="focusClickable(menuItems.length - 1)"
248
+ >
210
249
  <template v-for="(item, index) in menuItems" :key="index">
211
250
  <MenuItem
212
251
  ref="items"
@@ -217,6 +256,7 @@ defineExpose({
217
256
  :disableTabIndex="props.disableTabIndex"
218
257
  :initOpen="props.initOpen"
219
258
  :depth="props.depth"
259
+ :disableClasses="props.disableClasses"
220
260
  :backButonEnabled="props.backButonEnabled"
221
261
  :backButtonLabel="props.backButtonLabel"
222
262
  :backButtonItem="props.backButtonItem"
@@ -1,12 +1,63 @@
1
1
  <script setup lang="ts">
2
+ import { onMounted, onUpdated, ref, watch } from 'vue'
3
+
2
4
  const props = defineProps<{
3
- id: string
4
- open: boolean
5
+ accordion: {
6
+ id: string;
7
+ state: boolean;
8
+ toggle: () => void;
9
+ open: () => void;
10
+ close: () => void;
11
+ };
5
12
  }>()
13
+
14
+ const rootEl = ref<HTMLDivElement>()
15
+ const focusElements = ref<HTMLElement[]>()
16
+
17
+ watch(
18
+ props,
19
+ to => {
20
+ to.accordion.state ? setFocus() : unsetFocus()
21
+ }
22
+ )
23
+
24
+ function getFocusElements() {
25
+ const container = rootEl.value
26
+ const elements = container?.querySelectorAll<HTMLElement>(
27
+ 'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
28
+ )
29
+ return Array.from(elements || []).filter(el => {
30
+ const hiddenParent = el.closest('[hidden]')
31
+ return !hiddenParent || hiddenParent === container
32
+ })
33
+ }
34
+
35
+ function unsetFocus() {
36
+ if (focusElements.value?.length) {
37
+ focusElements.value.forEach(el => {
38
+ el.tabIndex = -1
39
+ })
40
+ }
41
+ }
42
+
43
+ function setFocus() {
44
+ if (focusElements.value?.length) {
45
+ focusElements.value.forEach(el => {
46
+ el.tabIndex = 0
47
+ })
48
+ }
49
+ }
50
+
51
+ onMounted(() => {
52
+ focusElements.value = getFocusElements()
53
+ if (!props.accordion.state) {
54
+ unsetFocus()
55
+ }
56
+ })
6
57
  </script>
7
58
 
8
59
  <template>
9
- <div :id="props.id" :hidden="!props.open">
60
+ <div ref="rootEl" :id="props.accordion.id" :hidden="!props.accordion.state">
10
61
  <slot/>
11
62
  </div>
12
63
  </template>
@@ -1,13 +1,23 @@
1
1
  <script setup lang="ts">
2
2
  const props = defineProps<{
3
- id: string
4
- open: boolean
5
- toggle: () => void
3
+ accordion: {
4
+ id: string;
5
+ state: boolean;
6
+ toggle: () => void;
7
+ open: () => void;
8
+ close: () => void;
9
+ };
6
10
  }>()
11
+
7
12
  </script>
8
13
 
9
14
  <template>
10
- <button @click="props.toggle()" :aria-expanded="props.open" :aria-controls="props.id">
15
+ <button
16
+ type="button"
17
+ :aria-expanded="props.accordion.state"
18
+ :aria-controls="props.accordion.id"
19
+ @click="props.accordion.toggle()"
20
+ >
11
21
  <slot/>
12
22
  </button>
13
23
  </template>