@cnamts/synapse 1.0.19 → 1.0.20
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-CeVuSfJ9.js → DateFilter-XURUmpMl.js} +1 -1
- package/dist/{NumberFilter-C8PAu_sw.js → NumberFilter-BZc0O8wV.js} +1 -1
- package/dist/{PeriodFilter-UMUaxx3d.js → PeriodFilter-ZNdXcl3p.js} +1 -1
- package/dist/{SelectFilter-CqZl8CYt.js → SelectFilter-DshYU5OK.js} +1 -1
- package/dist/{TextFilter-D_RhhNOh.js → TextFilter-D_c5dRPl.js} +1 -1
- package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +4 -4
- package/dist/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.d.ts +17 -7
- package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +4 -4
- package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +4 -4
- package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +2416 -0
- package/dist/components/Customs/Selects/SyAutocomplete/types.d.ts +5 -0
- package/dist/components/Customs/Selects/SyAutocomplete/utils/ariaManager.d.ts +14 -0
- package/dist/components/Customs/Selects/SyAutocomplete/utils/useItemUtils.d.ts +16 -0
- package/dist/components/Customs/Selects/SyAutocomplete/utils/useKeyboardHandler.d.ts +28 -0
- package/dist/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.d.ts +12 -0
- package/dist/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.d.ts +2 -0
- package/dist/components/Customs/SyIcon/SyIcon.d.ts +2 -1
- package/dist/components/DatePicker/composables/useDateSelection.d.ts +1 -0
- package/dist/components/PaginatedTable/PaginatedTable.d.ts +1 -1
- package/dist/components/PaginatedTable/Pagination.d.ts +17 -0
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +5 -5
- package/dist/components/Tables/SyTable/SyTable.d.ts +5 -5
- package/dist/components/index.d.ts +1 -0
- package/dist/components/types.d.ts +15 -0
- package/dist/composables/useFormFieldErrorHandling.d.ts +31 -0
- package/dist/design-system-v3.js +68 -67
- package/dist/design-system-v3.umd.cjs +320 -309
- package/dist/{main-B39UVv5p.js → main-CuI6xaPq.js} +9921 -9194
- package/dist/modules.d.ts +6 -0
- package/dist/style.css +1 -1
- package/package.json +8 -9
- package/src/assets/amelipro/icons.ts +166 -153
- package/src/components/Accordion/Accordion.mdx +4 -1
- package/src/components/Accordion/{Accessibilite/AccessibilityGuide.mdx → accessibilite/Accessibility.mdx} +2 -2
- package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.stories.ts +73 -14
- package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.vue +119 -27
- package/src/components/Amelipro/AmeliproClickableTile/tests/AmeliproClickableTile.a11y.spec.ts +304 -0
- package/src/components/Amelipro/AmeliproClickableTile/tests/AmeliproClickableTile.spec.ts +435 -9
- package/src/components/Amelipro/AmeliproClickableTile/tests/__snapshots__/AmeliproClickableTile.spec.ts.snap +60 -0
- package/src/components/Amelipro/AmeliproIcon/__tests__/AmeliproIcon.spec.ts +1 -1
- package/src/components/Amelipro/AmeliproIcon/iconList.ts +2 -0
- package/src/components/BackBtn/BackBtn.vue +5 -4
- package/src/components/BackBtn/accessibilite/Accessibility.mdx +15 -0
- package/src/components/BackToTopBtn/BackToTopBtn.vue +6 -3
- package/src/components/BackToTopBtn/accessibilite/Accessibility.mdx +15 -0
- package/src/components/Captcha/Captcha.vue +5 -1
- package/src/components/Captcha/CaptchaAlert.vue +9 -7
- package/src/components/Captcha/accessibilite/Accessibility.mdx +10 -0
- package/src/components/ChipList/accessibilite/Accessibility.mdx +15 -0
- package/src/components/CollapsibleList/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +8 -6
- package/src/components/Common/IconSlot/IconSlot.vue +1 -1
- package/src/components/ContextualMenu/accessibilite/Accessibility.mdx +15 -0
- package/src/components/CookieBanner/accessibilite/Accessibility.mdx +15 -0
- package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +5 -4
- package/src/components/CopyBtn/CopyBtn.vue +6 -3
- package/src/components/CopyBtn/accessibilite/Accessibility.mdx +15 -0
- package/src/components/Customs/Selects/SelectBtnField/accessibilite/Accessibility.mdx +15 -0
- package/src/components/Customs/Selects/SelectOverview.mdx +112 -1
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.mdx +52 -0
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +979 -0
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +653 -0
- package/src/components/Customs/Selects/{SySelect → SyAutocomplete/accessibilite}/Accessibilite.stories.ts +7 -38
- package/src/components/Customs/Selects/{SySelect/Accessibilite.mdx → SyAutocomplete/accessibilite/Accessibility.mdx} +15 -20
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +72 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +345 -0
- package/src/components/Customs/Selects/SyAutocomplete/types.ts +7 -0
- package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +180 -0
- package/src/components/Customs/Selects/SyAutocomplete/utils/useItemUtils.ts +46 -0
- package/src/components/Customs/Selects/SyAutocomplete/utils/useKeyboardHandler.ts +107 -0
- package/src/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.ts +74 -0
- package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.vue +13 -9
- package/src/components/Customs/Selects/SyInputSelect/accessibilite/Accessibility.mdx +12 -0
- package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +43 -34
- package/src/components/Customs/Selects/SySelect/SySelect.vue +19 -2
- package/src/components/Customs/Selects/SySelect/accessibilite/Accessibility.mdx +274 -0
- package/src/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.ts +21 -16
- package/src/components/Customs/SyCheckbox/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +2 -2
- package/src/components/Customs/SyForm/accessibilite/Accessibility.mdx +10 -0
- package/src/components/Customs/SyIcon/SyIcon.mdx +4 -1
- package/src/components/Customs/SyIcon/SyIcon.vue +4 -3
- package/src/components/Customs/SyIcon/{Accessibilite.stories.ts → accessibilite/Accessibilite.stories.ts} +3 -3
- package/src/components/Customs/SyIcon/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +2 -2
- package/src/components/Customs/SyPagination/SyPagination.mdx +4 -2
- package/src/components/Customs/SyPagination/accessibilite/Accessibility.mdx +10 -0
- package/src/components/Customs/SyRadioGroup/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +2 -2
- package/src/components/Customs/SyTabs/SyTabs.mdx +4 -2
- package/src/components/Customs/SyTabs/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +2 -2
- package/src/components/Customs/SyTextField/SyTextField.mdx +1 -2
- package/src/components/Customs/SyTextField/SyTextField.vue +13 -0
- package/src/components/Customs/SyTextField/accessibilite/Accessibility.mdx +15 -0
- package/src/components/DataList/accessibilite/Accessibility.mdx +15 -0
- package/src/components/DataListGroup/accessibilite/Accessibility.mdx +14 -0
- package/src/components/DatePicker/Accessibilite.mdx +1 -1
- package/src/components/DatePicker/Accessibilite.stories.ts +1 -1
- package/src/components/DatePicker/CalendarMode/DatePicker.stories.ts +7 -4
- package/src/components/DatePicker/CalendarMode/DatePicker.vue +14 -2
- package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.stories.ts +297 -0
- package/src/components/DatePicker/composables/useDateSelection.ts +5 -0
- package/src/components/DatePicker/docExamples/BidirectionalComplexValidation.vue +273 -0
- package/src/components/DatePicker/docExamples/DatePickerBidirectionalValidation.vue +4 -4
- package/src/components/DatePicker/docExamples/DatePickerValidationExamples.vue +10 -0
- package/src/components/DiacriticPicker/accessibilite/Accessibility.mdx +10 -0
- package/src/components/DialogBox/accessibilite/Accessibility.mdx +15 -0
- package/src/components/DownloadBtn/DownloadBtn.vue +5 -4
- package/src/components/DownloadBtn/accessibilite/Accessibility.mdx +15 -0
- package/src/components/ErrorPage/accessibilite/Accessibility.mdx +15 -0
- package/src/components/ExternalLinks/accessibilite/Accessibility.mdx +15 -0
- package/src/components/FileList/UploadItem/UploadItem.vue +25 -20
- package/src/components/FileList/accessibilite/Accessibility.mdx +12 -0
- package/src/components/FilePreview/accessibilite/Accessibility.mdx +12 -0
- package/src/components/FileUpload/FileUploadContent.vue +5 -4
- package/src/components/FileUpload/accessibilite/Accessibility.mdx +12 -0
- package/src/components/FilterInline/FilterInline.vue +5 -4
- package/src/components/FilterInline/accessibilite/Accessibility.mdx +12 -0
- package/src/components/FilterSideBar/accessibilite/Accessibility.mdx +15 -0
- package/src/components/FooterBar/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +3 -4
- package/src/components/FranceConnectBtn/FranceConnectBtn.vue +6 -5
- package/src/components/FranceConnectBtn/accessibilite/Accessibility.mdx +15 -0
- package/src/components/FranceConnectBtn/tests/__snapshots__/FranceConnectBtn.spec.ts.snap +3 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/accessibilite/Accessibility.mdx +15 -0
- package/src/components/HeaderBar/accessibilite/Accessibility.mdx +15 -0
- package/src/components/HeaderBar/{Usages.mdx → usages/Usages.mdx} +2 -2
- package/src/components/HeaderLoading/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +9 -5
- package/src/components/HeaderToolbar/accessibilite/Accessibility.mdx +15 -0
- package/src/components/LangBtn/LangBtn.vue +5 -4
- package/src/components/LangBtn/accessibilite/Accessibility.mdx +15 -0
- package/src/components/Logo/accessibilite/Accessibility.mdx +17 -0
- package/src/components/LogoBrandSection/accessibilite/Accessibility.mdx +12 -0
- package/src/components/LunarCalendar/accessibilite/Accessibility.mdx +10 -0
- package/src/components/MaintenancePage/accessibilite/Accessibility.mdx +15 -0
- package/src/components/NirField/accessibilite/Accessibility.mdx +15 -0
- package/src/components/NotFoundPage/accessibilite/Accessibility.mdx +15 -0
- package/src/components/NotificationBar/Notification/Notification.vue +1 -1
- package/src/components/NotificationBar/accessibilite/Accessibility.mdx +15 -0
- package/src/components/PageContainer/{AccessibilityGuide.mdx → Accessibilite/Accessibility.mdx} +7 -4
- package/src/components/PageContainer/Accessibilite/AccessibilityGuide.mdx +0 -0
- package/src/components/PaginatedTable/PaginatedTable.vue +27 -47
- package/src/components/PaginatedTable/Pagination.vue +93 -0
- package/src/components/PaginatedTable/accessibilite/Accessibility.mdx +12 -0
- package/src/components/PasswordField/PasswordField.vue +2 -1
- package/src/components/PasswordField/accessibilite/Accessibility.mdx +108 -0
- package/src/components/PeriodField/accessibilite/Accessibility.mdx +12 -0
- package/src/components/PhoneField/accessibilite/Accessibility.mdx +15 -0
- package/src/components/RangeField/accessibilite/Accessibility.mdx +15 -0
- package/src/components/RatingPicker/accessibilite/Accessibility.mdx +15 -0
- package/src/components/SearchListField/SearchListField.vue +6 -3
- package/src/components/SearchListField/accessibilite/Accessibility.mdx +15 -0
- package/src/components/SkipLink/{Accessibilite.mdx → accessibilite/Accessibility.mdx} +7 -4
- package/src/components/SocialMediaLinks/accessibilite/Accessibility.mdx +15 -0
- package/src/components/SubHeader/accessibilite/Accessibility.mdx +15 -0
- package/src/components/SyAlert/SyAlert.vue +6 -6
- package/src/components/SyAlert/accessibilite/Accessibility.mdx +12 -0
- package/src/components/SyTextArea/accessibilite/Accessibility.mdx +10 -0
- package/src/components/TableToolbar/TableToolbar.vue +6 -3
- package/src/components/TableToolbar/accessibilite/Accessibility.mdx +12 -0
- package/src/components/Tables/SyServerTable/SyServerTable.mdx +4 -1
- package/src/components/Tables/SyServerTable/accessibilite/Accessibility.mdx +10 -0
- package/src/components/Tables/SyTable/SyTable.mdx +4 -1
- package/src/components/Tables/SyTable/accessibilite/Accessibility.mdx +10 -0
- package/src/components/Tables/common/TableHeader.vue +3 -1
- package/src/components/Tables/common/organizeColumns/OrganizeColumns.vue +18 -14
- package/src/components/ToolbarContainer/ToolbarContainer.mdx +2 -1
- package/src/components/ToolbarContainer/ToolbarContainer.stories.ts +563 -420
- package/src/components/ToolbarContainer/accessibilite/Accessibility.mdx +69 -0
- package/src/components/UploadWorkflow/accessibilite/Accessibility.mdx +12 -0
- package/src/components/Usages/Usages.vue +3 -2
- package/src/components/UserMenuBtn/UserMenuBtn.vue +7 -5
- package/src/components/UserMenuBtn/accessibilite/Accessibility.mdx +12 -0
- package/src/components/index.ts +2 -0
- package/src/components/types.ts +10 -0
- package/src/composables/rules/useFieldValidation.ts +7 -0
- package/src/composables/useFormFieldErrorHandling.ts +141 -0
- package/src/modules.d.ts +6 -0
- package/src/components/BackBtn/Accessibilite.mdx +0 -14
- package/src/components/BackBtn/Accessibilite.stories.ts +0 -30
- package/src/components/BackToTopBtn/Accessibilite.mdx +0 -14
- package/src/components/BackToTopBtn/Accessibilite.stories.ts +0 -31
- package/src/components/ChipList/Accessibilite.mdx +0 -14
- package/src/components/ChipList/Accessibilite.stories.ts +0 -31
- package/src/components/CollapsibleList/Accessibilite.stories.ts +0 -29
- package/src/components/ContextualMenu/Accessibilite.mdx +0 -13
- package/src/components/ContextualMenu/Accessibilite.stories.ts +0 -29
- package/src/components/CookieBanner/Accessibilite.mdx +0 -13
- package/src/components/CookieBanner/Accessibilite.stories.ts +0 -30
- package/src/components/CopyBtn/Accessibilite.mdx +0 -13
- package/src/components/CopyBtn/Accessibilite.stories.ts +0 -29
- package/src/components/Customs/Selects/SelectBtnField/Accessibilite.mdx +0 -14
- package/src/components/Customs/Selects/SelectBtnField/Accessibilite.stories.ts +0 -29
- package/src/components/Customs/Selects/SyInputSelect/Accessibilite.mdx +0 -13
- package/src/components/Customs/Selects/SyInputSelect/Accessibilite.stories.ts +0 -25
- package/src/components/Customs/SyTextField/Accessibilite.mdx +0 -14
- package/src/components/Customs/SyTextField/Accessibilite.stories.ts +0 -34
- package/src/components/DataList/Accessibilite.mdx +0 -13
- package/src/components/DataList/Accessibilite.stories.ts +0 -29
- package/src/components/DataListGroup/Accessibilite.mdx +0 -13
- package/src/components/DataListGroup/Accessibilite.stories.ts +0 -29
- package/src/components/DialogBox/Accessibilite.mdx +0 -14
- package/src/components/DialogBox/Accessibilite.stories.ts +0 -29
- package/src/components/DownloadBtn/Accessibilite.mdx +0 -14
- package/src/components/DownloadBtn/Accessibilite.stories.ts +0 -29
- package/src/components/ErrorPage/Accessibilite.mdx +0 -13
- package/src/components/ErrorPage/Accessibilite.stories.ts +0 -36
- package/src/components/ExternalLinks/Accessibilite.mdx +0 -18
- package/src/components/ExternalLinks/Accessibilite.stories.ts +0 -62
- package/src/components/FileList/Accessibilite.mdx +0 -13
- package/src/components/FileList/Accessibilite.stories.ts +0 -26
- package/src/components/FilePreview/Accessibilite.mdx +0 -14
- package/src/components/FilePreview/Accessibilite.stories.ts +0 -26
- package/src/components/FileUpload/Accessibilite.mdx +0 -13
- package/src/components/FileUpload/Accessibilite.stories.ts +0 -26
- package/src/components/FilterInline/Accessibilite.mdx +0 -15
- package/src/components/FilterInline/Accessibilite.stories.ts +0 -26
- package/src/components/FilterSideBar/Accessibilite.mdx +0 -13
- package/src/components/FilterSideBar/Accessibilite.stories.ts +0 -30
- package/src/components/FooterBar/Accessibilite.stories.ts +0 -26
- package/src/components/FranceConnectBtn/Accessibilite.mdx +0 -13
- package/src/components/FranceConnectBtn/Accessibilite.stories.ts +0 -30
- package/src/components/HeaderBar/Accessibilite.mdx +0 -13
- package/src/components/HeaderBar/Accessibilite.stories.ts +0 -31
- package/src/components/HeaderBar/HeaderBurgerMenu/Accessibilite.mdx +0 -13
- package/src/components/HeaderBar/HeaderBurgerMenu/Accessibilite.stories.ts +0 -30
- package/src/components/HeaderLoading/Accessibilite.stories.ts +0 -31
- package/src/components/HeaderToolbar/Accessibilite.mdx +0 -13
- package/src/components/HeaderToolbar/Accessibilite.stories.ts +0 -36
- package/src/components/LangBtn/Accessibilite.mdx +0 -13
- package/src/components/LangBtn/Accessibilite.stories.ts +0 -32
- package/src/components/Logo/Accessibilite.mdx +0 -13
- package/src/components/Logo/Accessibilite.stories.ts +0 -30
- package/src/components/LogoBrandSection/Accessibilite.mdx +0 -13
- package/src/components/LogoBrandSection/Accessibilite.stories.ts +0 -26
- package/src/components/MaintenancePage/Accessibilite.mdx +0 -13
- package/src/components/MaintenancePage/Accessibilite.stories.ts +0 -36
- package/src/components/NirField/Accessibilite.mdx +0 -13
- package/src/components/NirField/Accessibilite.stories.ts +0 -31
- package/src/components/NotFoundPage/Accessibilite.mdx +0 -13
- package/src/components/NotFoundPage/Accessibilite.stories.ts +0 -36
- package/src/components/NotificationBar/Accessibilite.mdx +0 -13
- package/src/components/NotificationBar/Accessibilite.stories.ts +0 -30
- package/src/components/PageContainer/Accessibilite.mdx +0 -13
- package/src/components/PageContainer/Accessibilite.stories.ts +0 -30
- package/src/components/PaginatedTable/Accessibilite.mdx +0 -13
- package/src/components/PaginatedTable/Accessibilite.stories.ts +0 -26
- package/src/components/PasswordField/Accessibilite.mdx +0 -13
- package/src/components/PasswordField/Accessibilite.stories.ts +0 -121
- package/src/components/PeriodField/Accessibilite.mdx +0 -13
- package/src/components/PeriodField/Accessibilite.stories.ts +0 -27
- package/src/components/PhoneField/Accessibilite.mdx +0 -13
- package/src/components/PhoneField/Accessibilite.stories.ts +0 -32
- package/src/components/RangeField/Accessibilite.mdx +0 -13
- package/src/components/RangeField/Accessibilite.stories.ts +0 -32
- package/src/components/RatingPicker/Accessibilite.mdx +0 -13
- package/src/components/RatingPicker/Accessibilite.stories.ts +0 -30
- package/src/components/SearchListField/Accessibilite.mdx +0 -13
- package/src/components/SearchListField/Accessibilite.stories.ts +0 -30
- package/src/components/SkipLink/Accessibilite.stories.ts +0 -36
- package/src/components/SocialMediaLinks/Accessibilite.mdx +0 -13
- package/src/components/SocialMediaLinks/Accessibilite.stories.ts +0 -36
- package/src/components/SubHeader/Accessibilite.mdx +0 -13
- package/src/components/SubHeader/Accessibilite.stories.ts +0 -36
- package/src/components/SyAlert/Accessibilite.mdx +0 -13
- package/src/components/SyAlert/Accessibilite.stories.ts +0 -30
- package/src/components/TableToolbar/Accessibilite.mdx +0 -13
- package/src/components/TableToolbar/Accessibilite.stories.ts +0 -26
- package/src/components/UploadWorkflow/Accessibilite.mdx +0 -13
- package/src/components/UploadWorkflow/Accessibilite.stories.ts +0 -26
- package/src/components/UserMenuBtn/Accessibilite.mdx +0 -13
- package/src/components/UserMenuBtn/Accessibilite.stories.ts +0 -25
- /package/src/components/HeaderBar/{Usages.stories.ts → usages/Usages.stories.ts} +0 -0
- /package/src/components/SyBtnMenu/accessibilite/{AccessibilityGuide.mdx → Accessibility.mdx} +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared ARIA helper used by SySelect and future picker components (autocomplete…)
|
|
3
|
+
*/
|
|
4
|
+
import { nextTick, type Ref } from 'vue'
|
|
5
|
+
|
|
6
|
+
export const ariaManager = {
|
|
7
|
+
// Pour cleaner les attrs ARIA de l'input avant de les maj
|
|
8
|
+
cleanInputAttributes(inputElement: HTMLElement): void {
|
|
9
|
+
if (!inputElement) return
|
|
10
|
+
|
|
11
|
+
inputElement.removeAttribute('aria-describedby')
|
|
12
|
+
inputElement.removeAttribute('size')
|
|
13
|
+
inputElement.removeAttribute('tabindex')
|
|
14
|
+
inputElement.removeAttribute('aria-hidden')
|
|
15
|
+
inputElement.removeAttribute('aria-autocomplete')
|
|
16
|
+
inputElement.removeAttribute('aria-owns')
|
|
17
|
+
inputElement.removeAttribute('aria-busy')
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
// Pour maj l'état ARIA de l'input combobox en fonction de l'ouverture du menu
|
|
21
|
+
updateInputState(
|
|
22
|
+
inputElement: HTMLElement,
|
|
23
|
+
isOpenValue: boolean,
|
|
24
|
+
menuId: string,
|
|
25
|
+
activeDescendant?: string,
|
|
26
|
+
options?: {
|
|
27
|
+
ariaAutocomplete?: 'list' | 'both' | 'inline' | 'none'
|
|
28
|
+
ownsId?: string
|
|
29
|
+
isBusy?: boolean
|
|
30
|
+
popupRendered?: boolean
|
|
31
|
+
},
|
|
32
|
+
): void {
|
|
33
|
+
if (!inputElement) return
|
|
34
|
+
|
|
35
|
+
inputElement.setAttribute('role', 'combobox')
|
|
36
|
+
if (options?.ariaAutocomplete) {
|
|
37
|
+
inputElement.setAttribute('aria-autocomplete', options.ariaAutocomplete)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (options?.popupRendered) {
|
|
41
|
+
inputElement.setAttribute('aria-controls', menuId)
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
inputElement.removeAttribute('aria-controls')
|
|
45
|
+
}
|
|
46
|
+
inputElement.setAttribute('aria-expanded', isOpenValue ? 'true' : 'false')
|
|
47
|
+
|
|
48
|
+
const hasPopup = options?.popupRendered !== false
|
|
49
|
+
if (hasPopup) {
|
|
50
|
+
if (options?.ownsId) {
|
|
51
|
+
inputElement.setAttribute('aria-owns', options.ownsId)
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
inputElement.removeAttribute('aria-owns')
|
|
55
|
+
}
|
|
56
|
+
if (options?.isBusy) {
|
|
57
|
+
inputElement.setAttribute('aria-busy', 'true')
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
inputElement.removeAttribute('aria-busy')
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (isOpenValue && activeDescendant) {
|
|
65
|
+
inputElement.setAttribute('aria-activedescendant', activeDescendant)
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
inputElement.removeAttribute('aria-activedescendant')
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
// Pour indiquer les états de validation (requis, erreur) via ARIA
|
|
73
|
+
updateValidationAttributes(
|
|
74
|
+
inputElement: HTMLElement,
|
|
75
|
+
isRequiredValue: boolean,
|
|
76
|
+
hasErrorValue: boolean,
|
|
77
|
+
): void {
|
|
78
|
+
if (!inputElement) return
|
|
79
|
+
|
|
80
|
+
if (isRequiredValue) {
|
|
81
|
+
inputElement.setAttribute('aria-required', 'true')
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
inputElement.removeAttribute('aria-required')
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (hasErrorValue) {
|
|
88
|
+
inputElement.setAttribute('aria-invalid', 'true')
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
inputElement.removeAttribute('aria-invalid')
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// Pour cleaner les attrs ARIA du parent avant de les reconfigurer ds le composant
|
|
96
|
+
cleanParentAttributes(parentElement: HTMLElement): void {
|
|
97
|
+
if (!parentElement) return
|
|
98
|
+
|
|
99
|
+
parentElement.removeAttribute('role')
|
|
100
|
+
parentElement.removeAttribute('aria-expanded')
|
|
101
|
+
parentElement.removeAttribute('aria-controls')
|
|
102
|
+
parentElement.removeAttribute('aria-haspopup')
|
|
103
|
+
parentElement.removeAttribute('aria-activedescendant')
|
|
104
|
+
parentElement.removeAttribute('aria-required')
|
|
105
|
+
parentElement.removeAttribute('aria-invalid')
|
|
106
|
+
parentElement.removeAttribute('aria-hidden')
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
cleanAlertAttributes(parentElement: HTMLElement): void {
|
|
110
|
+
if (!parentElement) return
|
|
111
|
+
const messagesElements = parentElement.querySelectorAll('[role="alert"]')
|
|
112
|
+
messagesElements.forEach((element: Element) => {
|
|
113
|
+
element.removeAttribute('role')
|
|
114
|
+
element.removeAttribute('aria-live')
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
setupAriaAttributesForAutocomplete(
|
|
119
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
120
|
+
textFieldRef: Ref<any>,
|
|
121
|
+
isOpen: Ref<boolean>,
|
|
122
|
+
menuId: string,
|
|
123
|
+
activeDescendant: Ref<string>,
|
|
124
|
+
loading: boolean,
|
|
125
|
+
inputLabel?: string,
|
|
126
|
+
): void {
|
|
127
|
+
nextTick(() => {
|
|
128
|
+
const tf = textFieldRef.value
|
|
129
|
+
if (!tf?.$el) return
|
|
130
|
+
|
|
131
|
+
const parentEl = tf.$el as HTMLElement
|
|
132
|
+
const inputEl = parentEl.querySelector('input') as HTMLElement | null
|
|
133
|
+
const popupRendered = Boolean(document.getElementById(menuId))
|
|
134
|
+
|
|
135
|
+
if (inputEl) {
|
|
136
|
+
ariaManager.cleanInputAttributes(inputEl)
|
|
137
|
+
ariaManager.updateInputState(
|
|
138
|
+
inputEl,
|
|
139
|
+
isOpen.value,
|
|
140
|
+
menuId,
|
|
141
|
+
activeDescendant.value,
|
|
142
|
+
{
|
|
143
|
+
ariaAutocomplete: 'list',
|
|
144
|
+
isBusy: loading,
|
|
145
|
+
popupRendered,
|
|
146
|
+
},
|
|
147
|
+
)
|
|
148
|
+
const labelToApply = inputLabel || inputEl.getAttribute('aria-label') || inputEl.getAttribute('placeholder') || ''
|
|
149
|
+
if (labelToApply) {
|
|
150
|
+
inputEl.setAttribute('aria-label', labelToApply)
|
|
151
|
+
}
|
|
152
|
+
inputEl.setAttribute('aria-haspopup', 'listbox')
|
|
153
|
+
if (!popupRendered) {
|
|
154
|
+
inputEl.removeAttribute('aria-controls')
|
|
155
|
+
if (isOpen.value) {
|
|
156
|
+
nextTick(() => {
|
|
157
|
+
const popupNowRendered = Boolean(document.getElementById(menuId))
|
|
158
|
+
if (popupNowRendered) {
|
|
159
|
+
inputEl.setAttribute('aria-controls', menuId)
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
ariaManager.updateValidationAttributes(inputEl, false, false)
|
|
165
|
+
nextTick(() => {
|
|
166
|
+
const popupStillThere = Boolean(document.getElementById(menuId))
|
|
167
|
+
if (popupStillThere) {
|
|
168
|
+
inputEl.setAttribute('aria-controls', menuId)
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
inputEl.removeAttribute('aria-controls')
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
ariaManager.cleanParentAttributes(parentEl)
|
|
177
|
+
ariaManager.cleanAlertAttributes(parentEl)
|
|
178
|
+
})
|
|
179
|
+
},
|
|
180
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue'
|
|
2
|
+
import type { ItemType } from '../types'
|
|
3
|
+
|
|
4
|
+
interface ItemUtilsProps {
|
|
5
|
+
textKey: string
|
|
6
|
+
valueKey: string
|
|
7
|
+
plainTextKey: string
|
|
8
|
+
returnObject: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useItemUtils(props: ItemUtilsProps, formattedItems: ComputedRef<ItemType[]>) {
|
|
12
|
+
const getItemText = (item: unknown) => {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
return (item as Record<string, any>)[props.textKey]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const getPlainText = (item: ItemType): string => {
|
|
18
|
+
if (props.plainTextKey && item[props.plainTextKey]) return String(item[props.plainTextKey] ?? '')
|
|
19
|
+
return String(item[props.textKey] ?? '')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const getValueKey = (item: ItemType | string | number): string | number =>
|
|
23
|
+
typeof item === 'object'
|
|
24
|
+
? item[props.valueKey] as string | number
|
|
25
|
+
: item
|
|
26
|
+
|
|
27
|
+
const getStoredValue = (item: ItemType | string | number) =>
|
|
28
|
+
props.returnObject ? item : getValueKey(item)
|
|
29
|
+
|
|
30
|
+
const getChipLabel = (chip: ItemType | string | number): string => {
|
|
31
|
+
if (props.returnObject && typeof chip === 'object' && chip !== null) {
|
|
32
|
+
return getPlainText(chip as ItemType)
|
|
33
|
+
}
|
|
34
|
+
const found = formattedItems.value.find(i => i[props.valueKey] === chip)
|
|
35
|
+
if (found) return getPlainText(found)
|
|
36
|
+
return String(chip ?? '')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
getItemText,
|
|
41
|
+
getPlainText,
|
|
42
|
+
getValueKey,
|
|
43
|
+
getStoredValue,
|
|
44
|
+
getChipLabel,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { nextTick, type Ref, type ComputedRef } from 'vue'
|
|
2
|
+
import { useSySelectKeyboard } from '@/components/Customs/Selects/SySelect/composables/useSySelectKeyboard'
|
|
3
|
+
import type { ItemType, SelectValue, SelectArray } from '../types'
|
|
4
|
+
|
|
5
|
+
interface KeyboardHandlerProps {
|
|
6
|
+
multiple: boolean
|
|
7
|
+
chips: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface KeyboardHandlerDeps {
|
|
11
|
+
search: Ref<string>
|
|
12
|
+
selected: Ref<SelectValue | SelectArray>
|
|
13
|
+
isOpen: Ref<boolean>
|
|
14
|
+
selectItem: (item: ItemType | string | number | null | undefined) => void
|
|
15
|
+
getItemText: (item: unknown) => unknown
|
|
16
|
+
filteredItems: ComputedRef<ItemType[]>
|
|
17
|
+
uniqueMenuId: Ref<string>
|
|
18
|
+
focusListItem: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function useSyAutocompleteKeyboard(
|
|
22
|
+
props: KeyboardHandlerProps,
|
|
23
|
+
deps: KeyboardHandlerDeps,
|
|
24
|
+
) {
|
|
25
|
+
const {
|
|
26
|
+
activeDescendantId: keyboardActiveId,
|
|
27
|
+
handleEnterKey,
|
|
28
|
+
handleDownKey,
|
|
29
|
+
handleUpKey,
|
|
30
|
+
handleEscapeKey,
|
|
31
|
+
handleHomeKey,
|
|
32
|
+
handleEndKey,
|
|
33
|
+
handlePageUpKey,
|
|
34
|
+
handlePageDownKey,
|
|
35
|
+
handleTabKey,
|
|
36
|
+
} = useSySelectKeyboard({
|
|
37
|
+
isOpen: deps.isOpen,
|
|
38
|
+
formattedItems: deps.filteredItems,
|
|
39
|
+
toggleMenu: () => { deps.isOpen.value = !deps.isOpen.value },
|
|
40
|
+
selectItem: deps.selectItem,
|
|
41
|
+
getItemText: deps.getItemText,
|
|
42
|
+
optionIdPrefix: `${deps.uniqueMenuId.value}-option`,
|
|
43
|
+
focusListItem: deps.focusListItem,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const keydownAdded = new WeakMap<HTMLInputElement, boolean>()
|
|
47
|
+
|
|
48
|
+
const handleKeydown = (e: KeyboardEvent) => {
|
|
49
|
+
const key = e.key
|
|
50
|
+
if (['ArrowUp', 'ArrowDown', 'Enter', 'Escape', 'Home', 'End', 'PageUp', 'PageDown'].includes(key)) {
|
|
51
|
+
e.preventDefault()
|
|
52
|
+
const handlers: Record<string, () => void> = {
|
|
53
|
+
ArrowUp: handleUpKey,
|
|
54
|
+
ArrowDown: handleDownKey,
|
|
55
|
+
Enter: handleEnterKey,
|
|
56
|
+
Escape: handleEscapeKey,
|
|
57
|
+
Home: handleHomeKey,
|
|
58
|
+
End: handleEndKey,
|
|
59
|
+
PageUp: handlePageUpKey,
|
|
60
|
+
PageDown: handlePageDownKey,
|
|
61
|
+
}
|
|
62
|
+
handlers[key]?.()
|
|
63
|
+
}
|
|
64
|
+
else if (key === 'Backspace' || key === 'Delete') {
|
|
65
|
+
if (deps.search.value === '' && props.multiple && props.chips && Array.isArray(deps.selected.value) && deps.selected.value.length > 0) {
|
|
66
|
+
e.preventDefault()
|
|
67
|
+
const lastItem = deps.selected.value[deps.selected.value.length - 1]
|
|
68
|
+
deps.selectItem(lastItem)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const focusInput = (textFieldRef: Ref<{ $el?: HTMLElement, $refs?: { input?: HTMLInputElement } } | null>, noFocus = false) => {
|
|
74
|
+
nextTick(() => {
|
|
75
|
+
const tf = textFieldRef.value
|
|
76
|
+
const el = tf?.$el as HTMLElement | null
|
|
77
|
+
const inputFromRefs = (tf?.$refs?.input ?? null) as HTMLInputElement | null
|
|
78
|
+
const byId = document.getElementById(`${deps.uniqueMenuId.value}-input`) as HTMLInputElement | null
|
|
79
|
+
const inputEl: HTMLInputElement | null = inputFromRefs ?? byId ?? (el?.querySelector('input') as HTMLInputElement | null)
|
|
80
|
+
if (inputEl) {
|
|
81
|
+
if (!noFocus) {
|
|
82
|
+
inputEl.focus()
|
|
83
|
+
if (props.multiple && !props.chips) {
|
|
84
|
+
// Position cursor at the end for multiple selection
|
|
85
|
+
const len = inputEl.value?.length ?? 0
|
|
86
|
+
inputEl.setSelectionRange(len, len)
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const len = inputEl.value?.length ?? 0
|
|
90
|
+
inputEl.setSelectionRange(len, len)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (!keydownAdded.get(inputEl)) {
|
|
94
|
+
inputEl.addEventListener('keydown', handleKeydown)
|
|
95
|
+
keydownAdded.set(inputEl, true)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
handleKeydown,
|
|
103
|
+
focusInput,
|
|
104
|
+
keyboardActiveId,
|
|
105
|
+
handleTabKey,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import type { ItemType, SelectValue, SelectArray } from '../types'
|
|
3
|
+
|
|
4
|
+
interface SelectionLogicProps {
|
|
5
|
+
multiple: boolean
|
|
6
|
+
returnObject: boolean
|
|
7
|
+
valueKey: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type EmitFunction = (event: 'update:modelValue', value: SelectValue | SelectArray) => void
|
|
11
|
+
|
|
12
|
+
export function useSelectionLogic(
|
|
13
|
+
props: SelectionLogicProps,
|
|
14
|
+
getValueKey: (item: ItemType | string | number) => string | number,
|
|
15
|
+
getStoredValue: (item: ItemType | string | number) => ItemType | string | number,
|
|
16
|
+
getPlainText: (item: ItemType) => string,
|
|
17
|
+
selected: Ref<SelectValue | SelectArray>,
|
|
18
|
+
search: Ref<string>,
|
|
19
|
+
emit: EmitFunction,
|
|
20
|
+
) {
|
|
21
|
+
const resetValue = () => {
|
|
22
|
+
if (props.multiple) {
|
|
23
|
+
selected.value = []
|
|
24
|
+
emit('update:modelValue', [])
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
selected.value = null
|
|
28
|
+
search.value = ''
|
|
29
|
+
emit('update:modelValue', null)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const updateMultipleSelection = (valueKeyValue: string | number, valueToStore: ItemType | string | number) => {
|
|
34
|
+
const arr: (ItemType | string | number)[] = Array.isArray(selected.value) ? [...selected.value] : []
|
|
35
|
+
const index = arr.findIndex(val =>
|
|
36
|
+
props.returnObject
|
|
37
|
+
? (val as ItemType)[props.valueKey] === valueKeyValue
|
|
38
|
+
: val === valueKeyValue,
|
|
39
|
+
)
|
|
40
|
+
if (index >= 0) {
|
|
41
|
+
arr.splice(index, 1)
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
arr.push(valueToStore)
|
|
45
|
+
}
|
|
46
|
+
selected.value = arr as SelectArray
|
|
47
|
+
emit('update:modelValue', arr as SelectArray)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const updateSingleSelection = (valueToStore: SelectValue, item: ItemType) => {
|
|
51
|
+
selected.value = valueToStore
|
|
52
|
+
search.value = getPlainText(item)
|
|
53
|
+
emit('update:modelValue', selected.value)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const updateValue = (item: ItemType | string | number | null) => {
|
|
57
|
+
if (item === null) {
|
|
58
|
+
resetValue()
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const valueKeyValue = getValueKey(item)
|
|
63
|
+
const valueToStore = getStoredValue(item)
|
|
64
|
+
|
|
65
|
+
if (props.multiple) {
|
|
66
|
+
updateMultipleSelection(valueKeyValue, valueToStore)
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
updateSingleSelection(valueToStore as SelectValue, item as ItemType)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { updateValue }
|
|
74
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import useCustomizableOptions, { type CustomizableOptions } from '@/composables/useCustomizableOptions'
|
|
5
5
|
import { useValidation, type ValidationRule } from '@/composables/validation/useValidation'
|
|
6
6
|
import defaultOptions from './config'
|
|
7
|
+
import SyIcon from '@/components/Customs/SyIcon/SyIcon.vue'
|
|
7
8
|
|
|
8
9
|
const props = withDefaults(defineProps<CustomizableOptions & {
|
|
9
10
|
modelValue?: Record<string, unknown> | string | null
|
|
@@ -253,21 +254,24 @@
|
|
|
253
254
|
@keydown.space.prevent="toggleMenu"
|
|
254
255
|
>
|
|
255
256
|
<span :class="{ 'error--text': hasError }">{{ selectedItemText }}</span>
|
|
256
|
-
<
|
|
257
|
+
<SyIcon
|
|
257
258
|
v-if="hasError"
|
|
258
259
|
class="ml-2"
|
|
259
260
|
color="error"
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
<
|
|
264
|
-
|
|
261
|
+
:icon="mdiInformation"
|
|
262
|
+
decorative
|
|
263
|
+
/>
|
|
264
|
+
<SyIcon
|
|
265
|
+
:icon="mdiChevronDown"
|
|
266
|
+
decorative
|
|
267
|
+
/>
|
|
268
|
+
<SyIcon
|
|
265
269
|
v-if="selectedItemText && props.clearable"
|
|
270
|
+
:icon="mdiCloseCircle"
|
|
266
271
|
aria-label="Supprimer"
|
|
272
|
+
role="button"
|
|
267
273
|
@click.stop.prevent="selectItem(null)"
|
|
268
|
-
|
|
269
|
-
{{ mdiCloseCircle }}
|
|
270
|
-
</VIcon>
|
|
274
|
+
/>
|
|
271
275
|
</div>
|
|
272
276
|
<VList
|
|
273
277
|
v-if="isOpen"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Meta, Story } from '@storybook/addon-docs';
|
|
2
|
+
import * as Stories from '../SyInputSelect.stories.ts';
|
|
3
|
+
import '@/stories/styles/shared.css';
|
|
4
|
+
|
|
5
|
+
<Meta of={Stories} />
|
|
6
|
+
|
|
7
|
+
<div className="header">
|
|
8
|
+
<h1>Accessibilité</h1>
|
|
9
|
+
<p>Cette page sera bientôt disponible</p>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<br />
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import SySelect from '@/components/Customs/Selects/SySelect/SySelect.vue'
|
|
3
3
|
import SyAlert from '../../../SyAlert/SyAlert.vue'
|
|
4
|
-
import
|
|
4
|
+
import SyForm from '../../SyForm/SyForm.vue'
|
|
5
|
+
import { VBtn, VMenu, VList, VListItem, VListItemTitle } from 'vuetify/components'
|
|
5
6
|
import { ref } from 'vue'
|
|
6
7
|
import { fn } from '@storybook/test'
|
|
7
8
|
|
|
@@ -136,16 +137,16 @@ export const Default: Story = {
|
|
|
136
137
|
import { SySelect } from '@cnamts/synapse'
|
|
137
138
|
|
|
138
139
|
const items = [
|
|
139
|
-
{ text: '
|
|
140
|
-
{ text: '
|
|
141
|
-
{ text: '
|
|
142
|
-
{ text: '
|
|
143
|
-
{ text: '
|
|
144
|
-
{ text: '
|
|
145
|
-
{ text: '
|
|
146
|
-
{ text: '
|
|
147
|
-
{ text: '
|
|
148
|
-
{ text: '
|
|
140
|
+
{ text: 'Lorem Ipsum is simply dummy text of the printing and typesetting', value: 'Adrien' },
|
|
141
|
+
{ text: 'Industry. Lorem Ipsum has been the industry's standard dummy', value: 'Axel' },
|
|
142
|
+
{ text: 'Text ever since the 1500s, when an unknown printer took a galley', value: 'Baptiste' },
|
|
143
|
+
{ text: 'Of type and scrambled it to make a type specimen book. It has', value: 'Clement' },
|
|
144
|
+
{ text: 'Survived not only five centuries, but also the leap into electronic', value: 'Corentin' },
|
|
145
|
+
{ text: 'Cum haec taliaque sollicitas eius aures everberarent ', value: 'Damien' },
|
|
146
|
+
{ text: 'Expositas semper eius modi rumoribus et patentes, varia ', value: 'David' },
|
|
147
|
+
{ text: 'Expositas semper eius modi rumoribus et patentes, varia', value: 'Eloi' },
|
|
148
|
+
{ text: 'Emensis itaque difficultatibus multis et nive obrutis callibus', value: 'Louis' },
|
|
149
|
+
{ text: 'Plurimis ubi prope Rauracum ventum est ad supercilia', value: 'Valentin' },
|
|
149
150
|
],
|
|
150
151
|
</script>
|
|
151
152
|
`,
|
|
@@ -154,16 +155,16 @@ export const Default: Story = {
|
|
|
154
155
|
},
|
|
155
156
|
args: {
|
|
156
157
|
'items': [
|
|
157
|
-
{ text: '
|
|
158
|
-
{ text: '
|
|
159
|
-
{ text: '
|
|
160
|
-
{ text: '
|
|
161
|
-
{ text: '
|
|
162
|
-
{ text: '
|
|
163
|
-
{ text: '
|
|
164
|
-
{ text: '
|
|
165
|
-
{ text: '
|
|
166
|
-
{ text: '
|
|
158
|
+
{ text: 'Lorem Ipsum is simply dummy text of the printing and typesetting', value: 'Adrien' },
|
|
159
|
+
{ text: 'Industry. Lorem Ipsum has been the industry\'s standard dummy', value: 'Axel' },
|
|
160
|
+
{ text: 'Text ever since the 1500s, when an unknown printer took a galley', value: 'Baptiste' },
|
|
161
|
+
{ text: 'Of type and scrambled it to make a type specimen book. It has', value: 'Clement' },
|
|
162
|
+
{ text: 'Survived not only five centuries, but also the leap into electronic', value: 'Corentin' },
|
|
163
|
+
{ text: 'Cum haec taliaque sollicitas eius aures everberarent ', value: 'Damien' },
|
|
164
|
+
{ text: 'Expositas semper eius modi rumoribus et patentes, varia ', value: 'David' },
|
|
165
|
+
{ text: 'Expositas semper eius modi rumoribus et patentes, varia', value: 'Eloi' },
|
|
166
|
+
{ text: 'Emensis itaque difficultatibus multis et nive obrutis callibus', value: 'Louis' },
|
|
167
|
+
{ text: 'Plurimis ubi prope Rauracum ventum est ad supercilia', value: 'Valentin' },
|
|
167
168
|
],
|
|
168
169
|
'onUpdate:modelValue': fn(),
|
|
169
170
|
},
|
|
@@ -947,7 +948,7 @@ export const FormValidation: Story = {
|
|
|
947
948
|
name: 'Template',
|
|
948
949
|
code: `
|
|
949
950
|
<template>
|
|
950
|
-
<
|
|
951
|
+
<SyForm @submit="onSubmit">
|
|
951
952
|
<SySelect
|
|
952
953
|
v-model="formData.option"
|
|
953
954
|
:items="options"
|
|
@@ -963,7 +964,7 @@ export const FormValidation: Story = {
|
|
|
963
964
|
>
|
|
964
965
|
Soumettre
|
|
965
966
|
</VBtn>
|
|
966
|
-
</
|
|
967
|
+
</SyForm>
|
|
967
968
|
</template>
|
|
968
969
|
`,
|
|
969
970
|
},
|
|
@@ -972,8 +973,8 @@ export const FormValidation: Story = {
|
|
|
972
973
|
code: `
|
|
973
974
|
<script setup lang="ts">
|
|
974
975
|
import { ref } from 'vue'
|
|
975
|
-
import { SySelect } from '@cnamts/synapse'
|
|
976
|
-
import { VBtn
|
|
976
|
+
import { SySelect, SyForm } from '@cnamts/synapse'
|
|
977
|
+
import { VBtn } from 'vuetify/components'
|
|
977
978
|
|
|
978
979
|
const formData = ref({
|
|
979
980
|
option: ''
|
|
@@ -985,9 +986,12 @@ const options = [
|
|
|
985
986
|
{ text: 'Option 3', value: '3' },
|
|
986
987
|
]
|
|
987
988
|
|
|
988
|
-
const
|
|
989
|
-
|
|
990
|
-
|
|
989
|
+
const onSubmit = (event) => {
|
|
990
|
+
if (event.isValid) {
|
|
991
|
+
alert('Formulaire valide : ' + JSON.stringify(formData.value))
|
|
992
|
+
} else {
|
|
993
|
+
alert('Formulaire invalide : veuillez choisir une option.')
|
|
994
|
+
}
|
|
991
995
|
}
|
|
992
996
|
</script>
|
|
993
997
|
`,
|
|
@@ -1007,21 +1011,26 @@ const submitForm = () => {
|
|
|
1007
1011
|
},
|
|
1008
1012
|
render: (args) => {
|
|
1009
1013
|
return {
|
|
1010
|
-
components: { SySelect,
|
|
1014
|
+
components: { SySelect, SyForm, VBtn },
|
|
1011
1015
|
setup() {
|
|
1012
1016
|
const formData = ref({
|
|
1013
1017
|
option: '',
|
|
1014
1018
|
})
|
|
1015
1019
|
|
|
1016
|
-
const
|
|
1017
|
-
|
|
1020
|
+
const onSubmit = (event: { isValid: boolean }) => {
|
|
1021
|
+
if (event.isValid) {
|
|
1022
|
+
alert(`Formulaire valide : ${JSON.stringify(formData.value)}`)
|
|
1023
|
+
}
|
|
1024
|
+
else {
|
|
1025
|
+
alert('Formulaire invalide : veuillez choisir une option.')
|
|
1026
|
+
}
|
|
1018
1027
|
}
|
|
1019
1028
|
|
|
1020
|
-
return { args, formData,
|
|
1029
|
+
return { args, formData, onSubmit }
|
|
1021
1030
|
},
|
|
1022
1031
|
template: `
|
|
1023
1032
|
<div class="pa-4">
|
|
1024
|
-
<
|
|
1033
|
+
<SyForm @submit="onSubmit">
|
|
1025
1034
|
<SySelect
|
|
1026
1035
|
v-model="formData.option"
|
|
1027
1036
|
v-bind="args"
|
|
@@ -1034,7 +1043,7 @@ const submitForm = () => {
|
|
|
1034
1043
|
>
|
|
1035
1044
|
Soumettre
|
|
1036
1045
|
</VBtn>
|
|
1037
|
-
</
|
|
1046
|
+
</SyForm>
|
|
1038
1047
|
</div>
|
|
1039
1048
|
`,
|
|
1040
1049
|
}
|
|
@@ -860,6 +860,21 @@
|
|
|
860
860
|
|
|
861
861
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
862
862
|
function initializeActivatorProps(activatorProps: Record<string, any>) {
|
|
863
|
+
const onFocus = (event: FocusEvent) => {
|
|
864
|
+
// Call original onFocus from Vuetify if it exists
|
|
865
|
+
activatorProps.onFocus?.(event)
|
|
866
|
+
|
|
867
|
+
// Prevents text from scrolling to the end on focus in Firefox
|
|
868
|
+
const target = event.target as HTMLInputElement
|
|
869
|
+
if (target) {
|
|
870
|
+
// We need to use a timeout to ensure this runs after Firefox's default behavior
|
|
871
|
+
setTimeout(() => {
|
|
872
|
+
target.scrollLeft = 0
|
|
873
|
+
target.setSelectionRange(0, 0)
|
|
874
|
+
}, 0)
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
863
878
|
return {
|
|
864
879
|
...activatorProps,
|
|
865
880
|
onKeydown: undefined,
|
|
@@ -869,6 +884,7 @@
|
|
|
869
884
|
textInput.value = el
|
|
870
885
|
activatorProps.ref?.(el)
|
|
871
886
|
},
|
|
887
|
+
onFocus: onFocus,
|
|
872
888
|
}
|
|
873
889
|
}
|
|
874
890
|
</script>
|
|
@@ -1230,9 +1246,10 @@
|
|
|
1230
1246
|
}
|
|
1231
1247
|
|
|
1232
1248
|
.sy-select :deep(.v-field__input input) {
|
|
1233
|
-
position:
|
|
1234
|
-
z-index:
|
|
1249
|
+
position: static;
|
|
1250
|
+
z-index: auto;
|
|
1235
1251
|
text-overflow: ellipsis;
|
|
1252
|
+
white-space: normal;
|
|
1236
1253
|
}
|
|
1237
1254
|
|
|
1238
1255
|
.hidden-label {
|