@cnamts/synapse 1.0.22 → 1.0.23
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.
- package/dist/{DateFilter-B5n-ZkLi.js → DateFilter-Dc-gSGwk.js} +1 -1
- package/dist/{NumberFilter-CtiZ9uj8.js → NumberFilter-vP38Wp6j.js} +1 -1
- package/dist/{PeriodFilter-DzqiMb-b.js → PeriodFilter-Ba1uYUnT.js} +1 -1
- package/dist/{SelectFilter-BOYlF7rX.js → SelectFilter-BioGT6Nn.js} +1 -1
- package/dist/{TextFilter-BOFRNfcX.js → TextFilter-B84dpnoq.js} +1 -1
- package/dist/components/Accordion/Accordion.d.ts +13 -2
- package/dist/components/Accordion/composables/useAccordionState.d.ts +2 -1
- package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +7 -7
- package/dist/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +7 -7
- package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +16 -16
- package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +1 -1
- package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +22 -1
- package/dist/components/Customs/Selects/SyAutocomplete/locales.d.ts +5 -0
- package/dist/components/Customs/Selects/SyInputSelect/SyInputSelect.d.ts +1 -1
- package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +1 -1
- package/dist/components/Customs/Selects/SySelect/locales.d.ts +1 -0
- package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +1 -1
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1 -1
- package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1 -1
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +5 -2
- package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +13 -9
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +7 -5
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +2 -1
- package/dist/components/ErrorPage/ErrorPage.d.ts +3 -1
- package/dist/components/FileList/UploadItem/UploadItem.d.ts +6 -0
- package/dist/components/FileList/UploadItem/locales.d.ts +1 -4
- package/dist/components/FileUpload/FileUploadContent.d.ts +2 -0
- package/dist/components/FileUpload/validateFiles.d.ts +2 -1
- package/dist/components/HeaderBar/HeaderBar.d.ts +2 -1
- package/dist/components/HeaderBar/HeaderLogo/HeaderLogo.d.ts +2 -1
- package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +2 -1
- package/dist/components/MonthPicker/MonthPicker.d.ts +1939 -0
- package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1899 -0
- package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +21 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.d.ts +21 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.d.ts +12 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthSelector.d.ts +11 -0
- package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.d.ts +6 -0
- package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.d.ts +14 -0
- package/dist/components/MonthPicker/MonthPickerVisual/YearSelector.d.ts +14 -0
- package/dist/components/MonthPicker/MonthPickerVisual/useMonthGrid.d.ts +9 -0
- package/dist/components/MonthPicker/MonthPickerVisual/useYearGrid.d.ts +8 -0
- package/dist/components/MonthPicker/MonthPickerVisual/utils.d.ts +8 -0
- package/dist/components/MonthPicker/locales.d.ts +12 -0
- package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +25 -0
- package/dist/components/NirField/NirField.d.ts +3 -1
- package/dist/components/NotificationBar/Notification/Notification.d.ts +3 -0
- package/dist/components/PasswordField/PasswordField.d.ts +1 -1
- package/dist/components/PeriodField/PeriodField.d.ts +29 -21
- package/dist/components/PhoneField/PhoneField.d.ts +2 -1
- package/dist/components/SyBtnMenu/SyBtnMenu.d.ts +1 -1
- package/dist/components/SyHeading/SyHeading.a11y.test.d.ts +1 -0
- package/dist/components/SyHeading/SyHeading.d.ts +4 -2
- package/dist/components/SyHeading/SyHeading.test.d.ts +1 -0
- package/dist/components/SyTextArea/SyTextArea.d.ts +1 -1
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +4 -4
- package/dist/components/Tables/SyTable/SyTable.d.ts +4 -4
- package/dist/components/Tables/common/SyTablePagination.d.ts +6 -6
- package/dist/components/index.d.ts +1 -0
- package/dist/design-system-v3.js +102 -99
- package/dist/design-system-v3.umd.cjs +126 -126
- package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +5 -0
- package/dist/{main-CEl4J8_T.js → main-aLKwdMi1.js} +11167 -10522
- package/dist/main.d.ts +1 -0
- package/dist/style.css +1 -1
- package/package.json +10 -4
- package/src/assets/apTokens.scss +2 -2
- package/src/assets/overrides/_btns.scss +8 -0
- package/src/assets/overrides/_forms.scss +9 -0
- package/src/assets/overrides/_icons.scss +38 -9
- package/src/assets/overrides/_tables.scss +19 -0
- package/src/components/Accordion/Accordion.mdx +23 -9
- package/src/components/Accordion/Accordion.stories.ts +153 -3
- package/src/components/Accordion/Accordion.vue +7 -6
- package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +40 -12
- package/src/components/Accordion/composables/useAccordionState.ts +3 -4
- package/src/components/Accordion/tests/accordion.spec.ts +131 -19
- package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.mdx +3 -1
- package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.stories.ts +8 -0
- package/src/components/BackBtn/accessibilite/Accessibility.mdx +62 -10
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +9 -3
- package/src/components/BackToTopBtn/accessibilite/Accessibility.mdx +86 -6
- package/src/components/Captcha/tests/Captcha.spec.ts +0 -29
- package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +2 -110
- package/src/components/Customs/Selects/SelectBtnField/accessibilite/Accessibility.mdx +133 -10
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +379 -93
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +144 -83
- package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibilite.stories.ts +40 -1
- package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibility.mdx +7 -1
- package/src/components/Customs/Selects/SyAutocomplete/locales.ts +5 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +96 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +234 -9
- package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +13 -3
- package/src/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.ts +9 -10
- package/src/components/Customs/Selects/SySelect/SySelect.vue +46 -3
- package/src/components/Customs/Selects/SySelect/locales.ts +1 -0
- package/src/components/Customs/SyIcon/SyIcon.vue +1 -1
- package/src/components/Customs/SyIcon/tests/SyIcon.a11y.spec.ts +20 -0
- package/src/components/Customs/SyIconButton/SyIconButton.mdx +46 -0
- package/src/components/Customs/SyIconButton/SyIconButton.stories.ts +184 -0
- package/src/components/Customs/SyIconButton/SyIconButton.vue +38 -0
- package/src/components/Customs/SyIconButton/accessibilite/Accessibility.mdx +64 -0
- package/src/components/Customs/SyIconButton/tests/SyIconButton.a11y.spec.ts +87 -0
- package/src/components/Customs/SyIconButton/tests/SyIconButton.spec.ts +152 -0
- package/src/components/Customs/SyIconButton/tests/__snapshots__/SyIconButton.spec.ts.snap +61 -0
- package/src/components/Customs/SyPagination/SyPagination.vue +5 -5
- package/src/components/Customs/SyTextField/SyTextField.vue +20 -2
- package/src/components/Customs/SyTextField/accessibilite/Accessibility.mdx +67 -9
- package/src/components/Customs/SyTextField/tests/SyTextField.a11y.spec.ts +15 -0
- package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +36 -0
- package/src/components/DataList/accessibilite/Accessibility.mdx +79 -11
- package/src/components/DataListGroup/accessibilite/Accessibility.mdx +80 -11
- package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +25 -0
- package/src/components/ErrorPage/ErrorPage.stories.ts +113 -19
- package/src/components/ErrorPage/ErrorPage.vue +17 -2
- package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +17 -0
- package/src/components/ErrorPage/tests/ErrorPage.spec.ts +21 -1
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +0 -1
- package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +23 -0
- package/src/components/FileList/FileList.stories.ts +51 -1
- package/src/components/FileList/UploadItem/UploadItem.vue +13 -6
- package/src/components/FileList/UploadItem/locales.ts +3 -12
- package/src/components/FileList/accessibilite/Accessibility.mdx +3 -0
- package/src/components/FileUpload/FileUpload.vue +2 -1
- package/src/components/FileUpload/FileUploadContent.vue +2 -1
- package/src/components/FileUpload/tests/FileUpload.spec.ts +47 -0
- package/src/components/FileUpload/validateFiles.ts +5 -2
- package/src/components/FranceConnectBtn/accessibilite/Accessibility.mdx +62 -9
- package/src/components/HeaderBar/HeaderBar.vue +2 -1
- package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +2 -1
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +2 -1
- package/src/components/LunarCalendar/accessibilite/Accessibility.mdx +74 -8
- package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +163 -0
- package/src/components/MaintenancePage/MaintenancePage.vue +1 -1
- package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +4 -5
- package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +0 -1
- package/src/components/MonthPicker/MonthPicker.mdx +35 -0
- package/src/components/MonthPicker/MonthPicker.stories.ts +527 -0
- package/src/components/MonthPicker/MonthPicker.vue +79 -0
- package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +89 -0
- package/src/components/MonthPicker/MonthPickerText/useTextField.ts +27 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.vue +154 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.ts +13 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +137 -0
- package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +60 -0
- package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +149 -0
- package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +143 -0
- package/src/components/MonthPicker/MonthPickerVisual/useMonthGrid.ts +45 -0
- package/src/components/MonthPicker/MonthPickerVisual/useYearGrid.ts +45 -0
- package/src/components/MonthPicker/MonthPickerVisual/utils.ts +17 -0
- package/src/components/MonthPicker/accessibilite/Accessibility.mdx +59 -0
- package/src/components/MonthPicker/locales.ts +12 -0
- package/src/components/MonthPicker/tests/MonthPicker.a11y.spec.ts +71 -0
- package/src/components/MonthPicker/tests/MonthPicker.spec.ts +1248 -0
- package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +2545 -0
- package/src/components/MonthPicker/useMonthPickerValidation.ts +30 -0
- package/src/components/NirField/NirField.mdx +1 -2
- package/src/components/NirField/NirField.stories.ts +66 -6
- package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +2 -3
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +22 -14
- package/src/components/NotificationBar/Notification/Notification.vue +3 -1
- package/src/components/NotificationBar/NotificationBar.stories.ts +154 -0
- package/src/components/NotificationBar/tests/NotificationBar.a11y.spec.ts +26 -0
- package/src/components/NotificationBar/tests/NotificationBar.spec.ts +60 -0
- package/src/components/RangeField/accessibilite/Accessibility.mdx +79 -11
- package/src/components/SkipLink/tests/SkipLink.a11y.spec.ts +23 -0
- package/src/components/StatusPage/StatusPage.stories.ts +118 -0
- package/src/components/StatusPage/StatusPage.vue +5 -3
- package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +22 -0
- package/src/components/StatusPage/tests/StatusPage.spec.ts +22 -0
- package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +22 -14
- package/src/components/SubHeader/tests/SubHeader.a11y.spec.ts +20 -0
- package/src/components/SyAlert/SyAlert.vue +1 -0
- package/src/components/SyAlert/accessibilite/Accessibility.mdx +79 -9
- package/src/components/SyAlert/tests/SyAlert.a11y.spec.ts +23 -0
- package/src/components/SyHeading/SyHeading.a11y.test.ts +149 -0
- package/src/components/SyHeading/SyHeading.test.ts +115 -0
- package/src/components/SyHeading/SyHeading.vue +5 -3
- package/src/components/SyTextArea/accessibilite/Accessibility.mdx +80 -8
- package/src/components/SyTextArea/tests/SyTextArea.a11y.spec.ts +151 -0
- package/src/components/ToolbarContainer/tests/ToolbarContainer.a11y.spec.ts +126 -0
- package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +2 -2
- package/src/components/index.ts +1 -0
- package/src/composables/useFormFieldErrorHandling.ts +11 -2
- package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -1
- package/src/main.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cnamts/synapse",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "CNAM DS v3",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,10 @@
|
|
|
18
18
|
"require": "./dist/design-system-v3.umd.cjs"
|
|
19
19
|
},
|
|
20
20
|
"./style.css": "./dist/style.css",
|
|
21
|
-
"./*":
|
|
21
|
+
"./*": {
|
|
22
|
+
"types": "./src/*",
|
|
23
|
+
"default": "./src/*"
|
|
24
|
+
}
|
|
22
25
|
},
|
|
23
26
|
"scripts": {
|
|
24
27
|
"dev": "vite",
|
|
@@ -31,6 +34,7 @@
|
|
|
31
34
|
"test:unit": "vitest run --exclude='**/*.a11y.spec.ts'",
|
|
32
35
|
"test:a11y": "pnpm vitest run a11y.spec.ts",
|
|
33
36
|
"a11y:report": "node ./scripts/a11y-report.mjs",
|
|
37
|
+
"a11y:status": "node generate-a11y-report.mjs",
|
|
34
38
|
"prepare": "husky",
|
|
35
39
|
"generate:changelog": "auto-changelog -o CHANGELOG-TEMP.md -p --starting-date 2024-10-10"
|
|
36
40
|
},
|
|
@@ -83,7 +87,7 @@
|
|
|
83
87
|
"eslint-plugin-storybook": "^0.11.3",
|
|
84
88
|
"eslint-plugin-vue": "^9.30.0",
|
|
85
89
|
"eslint-plugin-vuejs-accessibility": "^2.4.1",
|
|
86
|
-
"happy-dom": "^20.
|
|
90
|
+
"happy-dom": "^20.8.8",
|
|
87
91
|
"husky": "^9.1.6",
|
|
88
92
|
"jsdom": "^27.3.0",
|
|
89
93
|
"marked": "^16.0.0",
|
|
@@ -144,7 +148,9 @@
|
|
|
144
148
|
"parse5": "7.1.2",
|
|
145
149
|
"npm": "^11.8.1",
|
|
146
150
|
"minimatch": ">=10.2.3",
|
|
147
|
-
"immutable": ">=5.1.5"
|
|
151
|
+
"immutable": ">=5.1.5",
|
|
152
|
+
"flatted": ">=3.4.2",
|
|
153
|
+
"handlebars": ">=4.7.9"
|
|
148
154
|
},
|
|
149
155
|
"patchedDependencies": {
|
|
150
156
|
"vuetify@3.12.2": "patches/vuetify@3.12.2.patch"
|
package/src/assets/apTokens.scss
CHANGED
|
@@ -334,8 +334,8 @@ $colors-interactive-negative-primary-action-hover: #99dbf2;
|
|
|
334
334
|
$colors-interactive-negative-primary-action-pressed: #66c9ec;
|
|
335
335
|
$colors-interactive-negative-primary-action-disabled: #dddede;
|
|
336
336
|
$colors-interactive-positive-secondary-action-enabled: rgb(255 255 255 / 0%);
|
|
337
|
-
$colors-interactive-positive-secondary-action-hover: #
|
|
338
|
-
$colors-interactive-positive-secondary-action-pressed: #
|
|
337
|
+
$colors-interactive-positive-secondary-action-hover: #f7fcfe;
|
|
338
|
+
$colors-interactive-positive-secondary-action-pressed: #ccedf9;
|
|
339
339
|
$colors-interactive-positive-secondary-action-disabled: rgb(255 255 255 / 0%);
|
|
340
340
|
$colors-interactive-negative-secondary-action-enabled: rgb(255 255 255 / 0%);
|
|
341
341
|
$colors-interactive-negative-secondary-action-hover: rgb(255 255 255 / 8%);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@use '@/assets/apTokens';
|
|
2
|
+
|
|
1
3
|
.v-btn {
|
|
2
4
|
text-transform: inherit !important;
|
|
3
5
|
font-weight: 700 !important;
|
|
@@ -13,3 +15,9 @@
|
|
|
13
15
|
.v-btn.v-tab {
|
|
14
16
|
text-transform: uppercase !important;
|
|
15
17
|
}
|
|
18
|
+
|
|
19
|
+
.theme-ap .v-btn {
|
|
20
|
+
&:hover {
|
|
21
|
+
background-color: apTokens.$colors-interactive-positive-secondary-action-hover !important;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -12,3 +12,12 @@
|
|
|
12
12
|
.v-radio .v-selection-control {
|
|
13
13
|
min-height: 40px;
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
// AP theme: inset the loader bar to match the larger field border-radius (12px)
|
|
17
|
+
.theme-ap,
|
|
18
|
+
.theme-ap2026 {
|
|
19
|
+
.v-field__loader .v-progress-linear {
|
|
20
|
+
margin-inline: 10px;
|
|
21
|
+
width: calc(100% - 20px);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,20 +1,49 @@
|
|
|
1
1
|
@use '@/assets/apTokens';
|
|
2
2
|
@use '@/assets/amelipro/apTokens2026';
|
|
3
|
+
@use '@/assets/tokens';
|
|
3
4
|
|
|
4
5
|
.v-theme--ap.v-btn--icon .v-icon {
|
|
5
|
-
color: apTokens.$colors-icon-accent-primary
|
|
6
|
+
color: apTokens.$colors-icon-accent-primary;
|
|
6
7
|
transition: color 0.2s ease;
|
|
7
|
-
|
|
8
|
-
&:hover {
|
|
9
|
-
color: apTokens.$colors-icon-accent-secondary !important;
|
|
10
|
-
}
|
|
11
8
|
}
|
|
12
9
|
|
|
13
10
|
.v-theme--ap2026.v-btn--icon .v-icon {
|
|
14
|
-
color: apTokens2026.$ap-blue-darken1
|
|
11
|
+
color: apTokens2026.$ap-blue-darken1;
|
|
12
|
+
transition: color 0.2s ease;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.v-theme--cnam.v-btn--icon .v-icon,
|
|
16
|
+
.v-theme--pa.v-btn--icon .v-icon {
|
|
17
|
+
color: tokens.$colors-icon-accent-primary;
|
|
18
|
+
transition: color 0.2s ease;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.v-theme--ap .v-btn--icon:hover,
|
|
22
|
+
.v-theme--ap2026 .v-btn--icon:hover,
|
|
23
|
+
.v-theme--cnam .v-btn--icon:hover,
|
|
24
|
+
.v-theme--pa .v-btn--icon:hover {
|
|
25
|
+
opacity: 0.08;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.v-theme--ap.v-icon,
|
|
29
|
+
.v-theme--ap2026.v-icon,
|
|
30
|
+
.v-theme--cnam.v-icon,
|
|
31
|
+
.v-theme--pa.v-icon {
|
|
15
32
|
transition: color 0.2s ease;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.v-theme--ap.v-btn--icon .v-ripple__animation {
|
|
36
|
+
background-color: apTokens.$colors-icon-accent-primary !important;
|
|
37
|
+
opacity: 0.18;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.v-theme--ap2026.v-btn--icon .v-ripple__animation {
|
|
41
|
+
background-color: apTokens2026.$ap-blue-darken1 !important;
|
|
42
|
+
opacity: 0.18;
|
|
43
|
+
}
|
|
16
44
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
45
|
+
.v-theme--cnam.v-btn--icon .v-ripple__animation,
|
|
46
|
+
.v-theme--pa.v-btn--icon .v-ripple__animation {
|
|
47
|
+
background-color: tokens.$colors-icon-accent-primary !important;
|
|
48
|
+
opacity: 0.18;
|
|
20
49
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@use '@/assets/tokens';
|
|
2
|
+
@use '@/assets/apTokens';
|
|
2
3
|
|
|
3
4
|
.v-data-table thead th .v-data-table-header__content {
|
|
4
5
|
opacity: 0.65;
|
|
@@ -16,3 +17,21 @@
|
|
|
16
17
|
background: tokens.$primary-base !important;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
|
|
21
|
+
// Pagination color variables
|
|
22
|
+
.theme-cnam,
|
|
23
|
+
.theme-pa {
|
|
24
|
+
--pagination-color: #{tokens.$primary-base};
|
|
25
|
+
--pagination-border: #{tokens.$primary-base};
|
|
26
|
+
--pagination-ellipsis: #{tokens.$primary-base};
|
|
27
|
+
--pagination-focused-background-color: rgba(tokens.$primary-base, 0.1);
|
|
28
|
+
--pagination-background-color: #{tokens.$primary-base};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.theme-ap {
|
|
32
|
+
--pagination-color: #{apTokens.$primary-base};
|
|
33
|
+
--pagination-border: #{apTokens.$primary-base};
|
|
34
|
+
--pagination-ellipsis: #{apTokens.$primary-base};
|
|
35
|
+
--pagination-focused-background-color: rgba(apTokens.$primary-base, 0.1);
|
|
36
|
+
--pagination-background-color: #{apTokens.$primary-base};
|
|
37
|
+
}
|
|
@@ -16,6 +16,17 @@ L'accordéon standard affiche une liste d'éléments avec un titre et un contenu
|
|
|
16
16
|
|
|
17
17
|
<Canvas of={AccordionStories.Default} />
|
|
18
18
|
|
|
19
|
+
## API
|
|
20
|
+
|
|
21
|
+
<Controls of={AccordionStories.Default} />
|
|
22
|
+
|
|
23
|
+
## Événements
|
|
24
|
+
|
|
25
|
+
### update:modelValue
|
|
26
|
+
|
|
27
|
+
- **Type** : `(value: string[]) => void`
|
|
28
|
+
- **Description** : Émis lors de l'ouverture ou la fermeture d'un élément. La valeur est le tableau mis à jour des identifiants des éléments ouverts.
|
|
29
|
+
|
|
19
30
|
## Contenu avec objet
|
|
20
31
|
|
|
21
32
|
L'accordéon peut également afficher un contenu structuré sous forme d'objet avec un titre et un contenu détaillé.
|
|
@@ -34,26 +45,28 @@ Vous pouvez également utiliser des slots pour personnaliser le rendu des titres
|
|
|
34
45
|
|
|
35
46
|
<Canvas of={AccordionStories.WithSlots} />
|
|
36
47
|
|
|
37
|
-
|
|
38
|
-
<h1>Accessibilité</h1>
|
|
39
|
-
</div>
|
|
48
|
+
## Contrôle programmatique (v-model)
|
|
40
49
|
|
|
41
|
-
Le composant
|
|
50
|
+
Le composant supporte `v-model` pour contrôler programmatiquement les éléments ouverts.
|
|
51
|
+
La valeur est un tableau de chaînes correspondant aux `id` des éléments ouverts.
|
|
42
52
|
|
|
43
|
-
|
|
44
|
-
- Chaque bouton possède les attributs `aria-expanded` et `aria-controls`
|
|
45
|
-
- Chaque section de contenu a l'attribut `role="region"` et `aria-labelledby` qui pointe vers l'ID du bouton
|
|
53
|
+
<Canvas of={AccordionStories.WithVModel} />
|
|
46
54
|
|
|
47
|
-
##
|
|
55
|
+
## Éléments pré-ouverts
|
|
48
56
|
|
|
49
|
-
|
|
57
|
+
Vous pouvez pré-ouvrir des éléments en initialisant le `v-model` avec les identifiants souhaités.
|
|
58
|
+
|
|
59
|
+
<Canvas of={AccordionStories.PreOpened} />
|
|
50
60
|
|
|
51
61
|
## Exemple d'utilisation
|
|
52
62
|
|
|
53
63
|
<Source dark code={`
|
|
54
64
|
<script setup lang="ts">
|
|
65
|
+
import { ref } from 'vue'
|
|
55
66
|
import { Accordion } from '@cnamts/synapse'
|
|
56
67
|
|
|
68
|
+
const openItems = ref<string[]>([])
|
|
69
|
+
|
|
57
70
|
const accordionItems = [
|
|
58
71
|
{ id: 'item1', title: 'Section 1', content: 'Contenu de la section 1' },
|
|
59
72
|
{ id: 'item2', title: 'Section 2', content: 'Contenu de la section 2' },
|
|
@@ -71,6 +84,7 @@ const accordionItems = [
|
|
|
71
84
|
<template>
|
|
72
85
|
<main>
|
|
73
86
|
<Accordion
|
|
87
|
+
v-model="openItems"
|
|
74
88
|
:items="accordionItems"
|
|
75
89
|
:heading-level="3"
|
|
76
90
|
/>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { fn } from '@storybook/test'
|
|
2
3
|
import Accordion from './Accordion.vue'
|
|
4
|
+
import { ref } from 'vue'
|
|
3
5
|
|
|
4
6
|
const meta: Meta<typeof Accordion> = {
|
|
5
7
|
title: 'Composants/Données/Accordion',
|
|
@@ -8,20 +10,40 @@ const meta: Meta<typeof Accordion> = {
|
|
|
8
10
|
layout: 'fullscreen',
|
|
9
11
|
},
|
|
10
12
|
argTypes: {
|
|
11
|
-
items: {
|
|
13
|
+
'items': {
|
|
12
14
|
control: { type: 'object' },
|
|
13
15
|
description: 'Liste des éléments de l\'accordéon',
|
|
14
16
|
},
|
|
15
|
-
headingLevel: {
|
|
17
|
+
'headingLevel': {
|
|
16
18
|
control: { type: 'number', min: 1, max: 6 },
|
|
17
19
|
description: 'Niveau de titre pour les boutons de dévoilement',
|
|
18
20
|
default: 3,
|
|
19
21
|
},
|
|
20
|
-
groupId: {
|
|
22
|
+
'groupId': {
|
|
21
23
|
control: { type: 'text' },
|
|
22
24
|
description: 'Identifiant de groupe pour synchroniser le focus entre plusieurs accordions',
|
|
23
25
|
default: 'default',
|
|
24
26
|
},
|
|
27
|
+
'modelValue': {
|
|
28
|
+
control: 'object',
|
|
29
|
+
description: 'Liste des identifiants des éléments ouverts (v-model)',
|
|
30
|
+
table: {
|
|
31
|
+
type: { summary: 'string[]' },
|
|
32
|
+
category: 'props',
|
|
33
|
+
defaultValue: { summary: '[]' },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
'onUpdate:modelValue': {
|
|
37
|
+
action: 'update:modelValue',
|
|
38
|
+
description: 'Événement émis lors de l\'ouverture ou la fermeture d\'un élément',
|
|
39
|
+
table: {
|
|
40
|
+
type: { summary: '(value: string[]) => void' },
|
|
41
|
+
category: 'events',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
args: {
|
|
46
|
+
'onUpdate:modelValue': fn(),
|
|
25
47
|
},
|
|
26
48
|
}
|
|
27
49
|
|
|
@@ -339,3 +361,131 @@ export const WithSlots: Story = {
|
|
|
339
361
|
`,
|
|
340
362
|
}),
|
|
341
363
|
}
|
|
364
|
+
|
|
365
|
+
export const WithVModel: Story = {
|
|
366
|
+
parameters: {
|
|
367
|
+
sourceCode: [
|
|
368
|
+
{
|
|
369
|
+
language: 'vue',
|
|
370
|
+
name: 'Template',
|
|
371
|
+
code: `<script setup lang="ts">
|
|
372
|
+
import { ref } from 'vue'
|
|
373
|
+
import { Accordion } from '@cnamts/synapse'
|
|
374
|
+
|
|
375
|
+
const openItems = ref<string[]>([])
|
|
376
|
+
|
|
377
|
+
const items = [
|
|
378
|
+
{ id: 'item1', title: 'Section 1', content: 'Contenu de la section 1' },
|
|
379
|
+
{ id: 'item2', title: 'Section 2', content: 'Contenu de la section 2' },
|
|
380
|
+
{ id: 'item3', title: 'Section 3', content: 'Contenu de la section 3' },
|
|
381
|
+
]
|
|
382
|
+
|
|
383
|
+
function openAll() {
|
|
384
|
+
openItems.value = items.map(i => i.id)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function closeAll() {
|
|
388
|
+
openItems.value = []
|
|
389
|
+
}
|
|
390
|
+
</script>
|
|
391
|
+
|
|
392
|
+
<template>
|
|
393
|
+
<Accordion
|
|
394
|
+
v-model="openItems"
|
|
395
|
+
:items="items"
|
|
396
|
+
:heading-level="3"
|
|
397
|
+
/>
|
|
398
|
+
|
|
399
|
+
<p>Éléments ouverts : {{ openItems }}</p>
|
|
400
|
+
|
|
401
|
+
<v-btn variant="outlined" color="primary" @click="openAll">Tout ouvrir</v-btn>
|
|
402
|
+
<v-btn variant="outlined" color="primary" @click="closeAll">Tout fermer</v-btn>
|
|
403
|
+
</template>`,
|
|
404
|
+
},
|
|
405
|
+
],
|
|
406
|
+
},
|
|
407
|
+
args: {
|
|
408
|
+
items: defaultItems,
|
|
409
|
+
headingLevel: 3,
|
|
410
|
+
},
|
|
411
|
+
render: args => ({
|
|
412
|
+
components: { Accordion },
|
|
413
|
+
setup() {
|
|
414
|
+
const openItems = ref<string[]>([])
|
|
415
|
+
|
|
416
|
+
const openAll = () => {
|
|
417
|
+
openItems.value = (args.items ?? []).map((i: { id: string }) => i.id)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const closeAll = () => {
|
|
421
|
+
openItems.value = []
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return { args, openItems, openAll, closeAll }
|
|
425
|
+
},
|
|
426
|
+
template: `
|
|
427
|
+
<div class="pa-4">
|
|
428
|
+
<Accordion v-bind="args" v-model="openItems" />
|
|
429
|
+
|
|
430
|
+
<div class="mt-4" style="font-family: monospace; color: #666;">
|
|
431
|
+
Éléments ouverts : {{ openItems }}
|
|
432
|
+
</div>
|
|
433
|
+
|
|
434
|
+
<div class="mt-2 d-flex ga-2">
|
|
435
|
+
<v-btn variant="outlined" color="primary" @click="openAll">Tout ouvrir</v-btn>
|
|
436
|
+
<v-btn variant="outlined" color="primary" @click="closeAll">Tout fermer</v-btn>
|
|
437
|
+
</div>
|
|
438
|
+
</div>
|
|
439
|
+
`,
|
|
440
|
+
}),
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export const PreOpened: Story = {
|
|
444
|
+
parameters: {
|
|
445
|
+
sourceCode: [
|
|
446
|
+
{
|
|
447
|
+
language: 'vue',
|
|
448
|
+
name: 'Template',
|
|
449
|
+
code: `<script setup lang="ts">
|
|
450
|
+
import { ref } from 'vue'
|
|
451
|
+
import { Accordion } from '@cnamts/synapse'
|
|
452
|
+
|
|
453
|
+
// Pré-ouvrir la section 2
|
|
454
|
+
const openItems = ref<string[]>(['item2'])
|
|
455
|
+
</script>
|
|
456
|
+
|
|
457
|
+
<template>
|
|
458
|
+
<Accordion
|
|
459
|
+
v-model="openItems"
|
|
460
|
+
:items="[
|
|
461
|
+
{ id: 'item1', title: 'Section 1', content: 'Contenu de la section 1' },
|
|
462
|
+
{ id: 'item2', title: 'Section 2', content: 'Contenu de la section 2' },
|
|
463
|
+
{ id: 'item3', title: 'Section 3', content: 'Contenu de la section 3' },
|
|
464
|
+
]"
|
|
465
|
+
:heading-level="3"
|
|
466
|
+
/>
|
|
467
|
+
</template>`,
|
|
468
|
+
},
|
|
469
|
+
],
|
|
470
|
+
},
|
|
471
|
+
args: {
|
|
472
|
+
items: defaultItems,
|
|
473
|
+
headingLevel: 3,
|
|
474
|
+
},
|
|
475
|
+
render: args => ({
|
|
476
|
+
components: { Accordion },
|
|
477
|
+
setup() {
|
|
478
|
+
const openItems = ref<string[]>(['item2'])
|
|
479
|
+
return { args, openItems }
|
|
480
|
+
},
|
|
481
|
+
template: `
|
|
482
|
+
<div class="pa-4">
|
|
483
|
+
<Accordion v-bind="args" v-model="openItems" />
|
|
484
|
+
|
|
485
|
+
<div class="mt-4" style="font-family: monospace; color: #666;">
|
|
486
|
+
Éléments ouverts : {{ openItems }}
|
|
487
|
+
</div>
|
|
488
|
+
</div>
|
|
489
|
+
`,
|
|
490
|
+
}),
|
|
491
|
+
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import useCustomizableOptions, { type CustomizableOptions } from '@/composables/useCustomizableOptions'
|
|
3
3
|
import { config } from '@/components/Accordion/config'
|
|
4
4
|
import { mdiChevronRight } from '@mdi/js'
|
|
5
|
-
|
|
6
5
|
// Importation des composables
|
|
7
6
|
import useAccordionState from './composables/useAccordionState'
|
|
8
7
|
import useAccordionGroupCommunication from './composables/useAccordionGroupCommunication'
|
|
@@ -12,7 +11,7 @@
|
|
|
12
11
|
interface AccordionItem {
|
|
13
12
|
id: string
|
|
14
13
|
title: string
|
|
15
|
-
content
|
|
14
|
+
content?: string | { title: string, content: string }
|
|
16
15
|
headingLevel?: number
|
|
17
16
|
disabled?: boolean
|
|
18
17
|
}
|
|
@@ -38,6 +37,8 @@
|
|
|
38
37
|
vuetifyOptions: () => ({}),
|
|
39
38
|
})
|
|
40
39
|
|
|
40
|
+
const openItems = defineModel<string[]>({ default: () => [] })
|
|
41
|
+
|
|
41
42
|
const options = useCustomizableOptions(config, props)
|
|
42
43
|
|
|
43
44
|
// Génération d'un ID unique pour cette instance d'accordéon
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
isItemOpen,
|
|
50
51
|
isItemFocused,
|
|
51
52
|
setFocus,
|
|
52
|
-
} = useAccordionState()
|
|
53
|
+
} = useAccordionState(openItems)
|
|
53
54
|
|
|
54
55
|
// Utilisation du composable pour gérer la communication entre accordéons
|
|
55
56
|
const { emitFocusChange } = useAccordionGroupCommunication(
|
|
@@ -167,13 +168,13 @@
|
|
|
167
168
|
{{ item.content }}
|
|
168
169
|
</p>
|
|
169
170
|
</template>
|
|
170
|
-
<template v-else>
|
|
171
|
+
<template v-else-if="typeof item.content === 'object' && item.content !== null && 'title' in item.content && 'content' in item.content">
|
|
171
172
|
<div class="sy-accordion-content-item">
|
|
172
173
|
<p class="sy-accordion-content-text">
|
|
173
|
-
<strong>{{
|
|
174
|
+
<strong>{{ item.content.title }}</strong>
|
|
174
175
|
</p>
|
|
175
176
|
<p class="sy-accordion-content-text">
|
|
176
|
-
{{
|
|
177
|
+
{{ item.content.content }}
|
|
177
178
|
</p>
|
|
178
179
|
</div>
|
|
179
180
|
</template>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { ref } from 'vue'
|
|
2
3
|
import useAccordionState from '../useAccordionState'
|
|
3
4
|
|
|
4
5
|
describe('useAccordionState', () => {
|
|
5
6
|
describe('toggleItem', () => {
|
|
6
7
|
it('adds an item to openItems when it is not already open', () => {
|
|
7
|
-
const { toggleItem, isItemOpen, openItems } = useAccordionState()
|
|
8
|
+
const { toggleItem, isItemOpen, openItems } = useAccordionState(ref<string[]>([]))
|
|
8
9
|
|
|
9
10
|
toggleItem('item1')
|
|
10
11
|
|
|
@@ -13,7 +14,7 @@ describe('useAccordionState', () => {
|
|
|
13
14
|
})
|
|
14
15
|
|
|
15
16
|
it('removes an item from openItems when it is already open', () => {
|
|
16
|
-
const { toggleItem, isItemOpen, openItems } = useAccordionState()
|
|
17
|
+
const { toggleItem, isItemOpen, openItems } = useAccordionState(ref<string[]>([]))
|
|
17
18
|
|
|
18
19
|
// Ouvrir d'abord l'élément
|
|
19
20
|
toggleItem('item1')
|
|
@@ -29,7 +30,7 @@ describe('useAccordionState', () => {
|
|
|
29
30
|
|
|
30
31
|
describe('isItemOpen', () => {
|
|
31
32
|
it('returns true when the item is open', () => {
|
|
32
|
-
const { toggleItem, isItemOpen } = useAccordionState()
|
|
33
|
+
const { toggleItem, isItemOpen } = useAccordionState(ref<string[]>([]))
|
|
33
34
|
|
|
34
35
|
toggleItem('item1')
|
|
35
36
|
|
|
@@ -37,7 +38,7 @@ describe('useAccordionState', () => {
|
|
|
37
38
|
})
|
|
38
39
|
|
|
39
40
|
it('returns false when the item is not open', () => {
|
|
40
|
-
const { isItemOpen } = useAccordionState()
|
|
41
|
+
const { isItemOpen } = useAccordionState(ref<string[]>([]))
|
|
41
42
|
|
|
42
43
|
expect(isItemOpen('item1')).toBe(false)
|
|
43
44
|
})
|
|
@@ -45,7 +46,7 @@ describe('useAccordionState', () => {
|
|
|
45
46
|
|
|
46
47
|
describe('isItemFocused', () => {
|
|
47
48
|
it('returns true when the item is focused', () => {
|
|
48
|
-
const { setFocus, isItemFocused } = useAccordionState()
|
|
49
|
+
const { setFocus, isItemFocused } = useAccordionState(ref<string[]>([]))
|
|
49
50
|
|
|
50
51
|
setFocus('item1')
|
|
51
52
|
|
|
@@ -53,7 +54,7 @@ describe('useAccordionState', () => {
|
|
|
53
54
|
})
|
|
54
55
|
|
|
55
56
|
it('returns false when the item is not focused', () => {
|
|
56
|
-
const { isItemFocused } = useAccordionState()
|
|
57
|
+
const { isItemFocused } = useAccordionState(ref<string[]>([]))
|
|
57
58
|
|
|
58
59
|
expect(isItemFocused('item1')).toBe(false)
|
|
59
60
|
})
|
|
@@ -61,7 +62,7 @@ describe('useAccordionState', () => {
|
|
|
61
62
|
|
|
62
63
|
describe('setFocus', () => {
|
|
63
64
|
it('sets the focus on the specified item', () => {
|
|
64
|
-
const { setFocus, focusedItemId } = useAccordionState()
|
|
65
|
+
const { setFocus, focusedItemId } = useAccordionState(ref<string[]>([]))
|
|
65
66
|
|
|
66
67
|
setFocus('item1')
|
|
67
68
|
|
|
@@ -69,7 +70,7 @@ describe('useAccordionState', () => {
|
|
|
69
70
|
})
|
|
70
71
|
|
|
71
72
|
it('removes focus when null is passed', () => {
|
|
72
|
-
const { setFocus, focusedItemId } = useAccordionState()
|
|
73
|
+
const { setFocus, focusedItemId } = useAccordionState(ref<string[]>([]))
|
|
73
74
|
|
|
74
75
|
// D'abord définir le focus
|
|
75
76
|
setFocus('item1')
|
|
@@ -82,7 +83,7 @@ describe('useAccordionState', () => {
|
|
|
82
83
|
})
|
|
83
84
|
|
|
84
85
|
it('does nothing when the same item is already focused', () => {
|
|
85
|
-
const { setFocus, focusedItemId } = useAccordionState()
|
|
86
|
+
const { setFocus, focusedItemId } = useAccordionState(ref<string[]>([]))
|
|
86
87
|
|
|
87
88
|
setFocus('item1')
|
|
88
89
|
const originalFocusedItem = focusedItemId.value
|
|
@@ -96,7 +97,7 @@ describe('useAccordionState', () => {
|
|
|
96
97
|
|
|
97
98
|
describe('focus behavior during toggle', () => {
|
|
98
99
|
it('sets focus when opening an item', () => {
|
|
99
|
-
const { toggleItem, focusedItemId } = useAccordionState()
|
|
100
|
+
const { toggleItem, focusedItemId } = useAccordionState(ref<string[]>([]))
|
|
100
101
|
|
|
101
102
|
toggleItem('item1')
|
|
102
103
|
|
|
@@ -104,7 +105,7 @@ describe('useAccordionState', () => {
|
|
|
104
105
|
})
|
|
105
106
|
|
|
106
107
|
it('maintains focus when closing a non-focused item', () => {
|
|
107
|
-
const { toggleItem, setFocus, focusedItemId } = useAccordionState()
|
|
108
|
+
const { toggleItem, setFocus, focusedItemId } = useAccordionState(ref<string[]>([]))
|
|
108
109
|
|
|
109
110
|
// Ouvrir deux éléments
|
|
110
111
|
toggleItem('item1')
|
|
@@ -128,7 +129,7 @@ describe('useAccordionState', () => {
|
|
|
128
129
|
})
|
|
129
130
|
|
|
130
131
|
it('removes focus when closing the focused item', () => {
|
|
131
|
-
const { toggleItem, focusedItemId } = useAccordionState()
|
|
132
|
+
const { toggleItem, focusedItemId } = useAccordionState(ref<string[]>([]))
|
|
132
133
|
|
|
133
134
|
// Ouvrir un élément (qui sera automatiquement focalisé)
|
|
134
135
|
toggleItem('item1')
|
|
@@ -141,4 +142,31 @@ describe('useAccordionState', () => {
|
|
|
141
142
|
expect(focusedItemId.value).toBeNull()
|
|
142
143
|
})
|
|
143
144
|
})
|
|
145
|
+
|
|
146
|
+
describe('external ref synchronization', () => {
|
|
147
|
+
it('uses the provided ref for openItems', () => {
|
|
148
|
+
const externalRef = ref<string[]>(['item1'])
|
|
149
|
+
const { isItemOpen } = useAccordionState(externalRef)
|
|
150
|
+
|
|
151
|
+
expect(isItemOpen('item1')).toBe(true)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('mutates the provided ref when toggling', () => {
|
|
155
|
+
const externalRef = ref<string[]>([])
|
|
156
|
+
const { toggleItem } = useAccordionState(externalRef)
|
|
157
|
+
|
|
158
|
+
toggleItem('item1')
|
|
159
|
+
|
|
160
|
+
expect(externalRef.value).toContain('item1')
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('reflects external changes to the ref', () => {
|
|
164
|
+
const externalRef = ref<string[]>([])
|
|
165
|
+
const { isItemOpen } = useAccordionState(externalRef)
|
|
166
|
+
|
|
167
|
+
externalRef.value = ['item2']
|
|
168
|
+
|
|
169
|
+
expect(isItemOpen('item2')).toBe(true)
|
|
170
|
+
})
|
|
171
|
+
})
|
|
144
172
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref } from 'vue'
|
|
1
|
+
import { ref, type Ref } from 'vue'
|
|
2
2
|
|
|
3
3
|
export interface AccordionState {
|
|
4
4
|
openItems: { value: string[] }
|
|
@@ -9,8 +9,7 @@ export interface AccordionState {
|
|
|
9
9
|
setFocus: (itemId: string | null) => void
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export default function useAccordionState(): AccordionState {
|
|
13
|
-
const openItems = ref<string[]>([])
|
|
12
|
+
export default function useAccordionState(openItems: Ref<string[]>): AccordionState {
|
|
14
13
|
const focusedItemId = ref<string | null>(null)
|
|
15
14
|
|
|
16
15
|
const toggleItem = (itemId: string) => {
|
|
@@ -23,7 +22,7 @@ export default function useAccordionState(): AccordionState {
|
|
|
23
22
|
setFocus(itemId)
|
|
24
23
|
}
|
|
25
24
|
else {
|
|
26
|
-
openItems.value.
|
|
25
|
+
openItems.value = openItems.value.filter(id => id !== itemId)
|
|
27
26
|
if (!wasFocused) {
|
|
28
27
|
setFocus(itemId)
|
|
29
28
|
}
|