@cnamts/synapse 1.0.24 → 1.0.25
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/README.md +27 -5
- package/dist/{AutocompleteFilter-BWLR3U7W.js → AutocompleteFilter-D7qBuCAP.js} +1 -1
- package/dist/{AutocompleteFilter-D9jzRzAL.cjs → AutocompleteFilter-Df9i5mAl.cjs} +1 -1
- package/dist/{DateFilter-DTUl8hb1.cjs → DateFilter-BJD6FMev.cjs} +1 -1
- package/dist/{DateFilter-BpwFexzi.js → DateFilter-BitMWrMU.js} +1 -1
- package/dist/{NumberFilter-Bz_NTdX9.js → NumberFilter-BTLUxw0a.js} +1 -1
- package/dist/{NumberFilter-MAEojdk0.cjs → NumberFilter-DGCzCXzI.cjs} +1 -1
- package/dist/{PeriodFilter-DX_wy9g-.js → PeriodFilter-B5rUIPAC.js} +1 -1
- package/dist/{PeriodFilter-CC4WgIhl.cjs → PeriodFilter-DO_ecTZW.cjs} +1 -1
- package/dist/{SelectFilter-BR3fvl-a.cjs → SelectFilter-CGwcKWLm.cjs} +1 -1
- package/dist/{SelectFilter-xqiPtPgX.js → SelectFilter-l4QnRcuk.js} +2 -2
- package/dist/{TextFilter-CCfYFl5F.cjs → TextFilter-B8nf7xoK.cjs} +1 -1
- package/dist/{TextFilter-BBl3JFqK.js → TextFilter-C9hj6Qrp.js} +1 -1
- package/dist/apLightTheme-CEK4iY3f.cjs +1 -0
- package/dist/{apLightTheme-D1P4jcD0.js → apLightTheme-DnIM24Lv.js} +441 -722
- package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +10 -6
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +3 -0
- package/dist/components/Customs/SyTabs/SyTabs.d.ts +13 -11
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +4 -4
- package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +4 -24
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +2 -12
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +1 -6
- package/dist/components/DatePicker/composables/useDatePickerState.d.ts +1 -0
- package/dist/components/FileList/FileList.d.ts +6 -0
- package/dist/components/FilterSideBar/FilterSideBar.d.ts +2 -0
- package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +13 -13
- package/dist/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.d.ts +3 -3
- package/dist/components/MonthPicker/MonthPicker.d.ts +1 -6
- package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1 -6
- package/dist/components/NirField/NirField.d.ts +4 -16
- package/dist/components/PeriodField/PeriodField.d.ts +8 -48
- package/dist/components/PhoneField/PhoneField.d.ts +1 -6
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +1 -0
- package/dist/components/Tables/SyTable/SyTable.d.ts +1 -0
- package/dist/components/Tables/common/SyTablePagination.d.ts +2 -0
- package/dist/components/Tables/common/TableHeader.d.ts +5 -0
- package/dist/components/Tables/common/locales.d.ts +3 -0
- package/dist/components/Tables/common/types.d.ts +2 -0
- package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +1 -0
- package/dist/composables/unifyValidation/documentationValidationProps.d.ts +230 -0
- package/dist/composables/validation/useValidation.d.ts +5 -1
- package/dist/design-system-v3.js +2 -2
- package/dist/design-system-v3.umd.cjs +1 -1
- package/dist/designTokens/tokens/amelipro/apColors.d.ts +10 -10
- package/dist/designTokens/tokens/amelipro/apColors2026.d.ts +1 -2
- package/dist/designTokens/tokens/amelipro/apContextual.d.ts +44 -0
- package/dist/designTokens/tokens/amelipro/apSemantic.d.ts +1 -1
- package/dist/designTokens/tokens/baseColors.d.ts +127 -0
- package/dist/designTokens/tokens/baseContextualTokens.d.ts +50 -0
- package/dist/designTokens/tokens/cnam/cnamColors.d.ts +10 -10
- package/dist/designTokens/tokens/cnam/cnamSemantic.d.ts +1 -1
- package/dist/designTokens/tokens/pa/paColors.d.ts +1 -166
- package/dist/designTokens/tokens/pa/paSemantic.d.ts +1 -1
- package/dist/designTokens/utils/buildColorClassMap.d.ts +12 -0
- package/dist/designTokens/utils/createFlattenTheme.d.ts +1 -3
- package/dist/designTokens/utils/index.d.ts +2 -2
- package/dist/main-ByDPHpae.cjs +1067 -0
- package/dist/main-Cpx8Co6H.js +38869 -0
- package/dist/synapse.css +1 -1
- package/dist/utils/functions/classToHex.d.ts +1 -1
- package/dist/utils/functions/createHexResolver.d.ts +16 -0
- package/dist/vuetifyConfig.js +113 -152
- package/dist/vuetifyConfig.umd.cjs +1 -1
- package/package.json +29 -18
- package/src/assets/amelipro/apTokens2026.scss +5 -5
- package/src/assets/overrides/_breakpoints.scss +25 -0
- package/src/assets/overrides/_btns.scss +0 -2
- package/src/assets/overrides/_forms.scss +1 -3
- package/src/assets/overrides/_icons.scss +7 -11
- package/src/assets/overrides/_otp.scss +41 -0
- package/src/assets/overrides/_tables.scss +11 -20
- package/src/assets/overrides/_tooltips.scss +17 -7
- package/src/assets/overrides/_typography.scss +35 -37
- package/src/assets/overrides/_utilities.scss +43 -47
- package/src/assets/themes.scss +1 -0
- package/src/components/Amelipro/AmeliproAccordion/AmeliproAccordionTemplate/AmeliproAccordionTemplate.vue +20 -20
- package/src/components/Amelipro/AmeliproAccordionFrieze/AmeliproAccordionFrieze.vue +12 -14
- package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.vue +4 -6
- package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/AmeliproAccordionResultTemplate.vue +5 -5
- package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.vue +4 -6
- package/src/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.vue +4 -6
- package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.vue +4 -6
- package/src/components/Amelipro/AmeliproBreadcrumb/AmeliproBreadcrumb.vue +1 -3
- package/src/components/Amelipro/AmeliproBtn/AmeliproBtn.vue +4 -6
- package/src/components/Amelipro/AmeliproCallback/AmeliproCallback.vue +2 -2
- package/src/components/Amelipro/AmeliproCard/AmeliproCard.vue +31 -31
- package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.vue +5 -7
- package/src/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.vue +13 -15
- package/src/components/Amelipro/AmeliproCheckboxGroup/AmeliproCheckboxGroup.vue +23 -23
- package/src/components/Amelipro/AmeliproChips/AmeliproChips.vue +1 -3
- package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.vue +17 -12
- package/src/components/Amelipro/AmeliproClickableTile/tests/__snapshots__/AmeliproClickableTile.spec.ts.snap +2 -2
- package/src/components/Amelipro/AmeliproCopyBtn/AmeliproCopyBtn.vue +4 -6
- package/src/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.vue +13 -13
- package/src/components/Amelipro/AmeliproDentalChart/AmeliproDentalChart.vue +4 -2
- package/src/components/Amelipro/AmeliproDentalChart/AmeliproTooth/AmeliproTooth.vue +4 -4
- package/src/components/Amelipro/AmeliproDialog/AmeliproDialog.vue +5 -7
- package/src/components/Amelipro/AmeliproDisclosure/AmeliproDisclosure.vue +1 -3
- package/src/components/Amelipro/AmeliproErrorTemplate/AmeliproErrorTemplate.vue +2 -4
- package/src/components/Amelipro/AmeliproFilePreview/AmeliproFilePreview.vue +4 -6
- package/src/components/Amelipro/AmeliproFilters/AmeliproFilters.vue +13 -13
- package/src/components/Amelipro/AmeliproFirstLogin/AmeliproFirstLogin.vue +3 -5
- package/src/components/Amelipro/AmeliproFooter/AmeliproFooter.vue +1 -3
- package/src/components/Amelipro/AmeliproHeader/AmeliproHeader.vue +2 -4
- package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBar.vue +1 -3
- package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/AmeliproHeaderBrandSection.vue +20 -16
- package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/__tests__/__snapshots__/AmeliproHeaderBrandSection.spec.ts.snap +1 -1
- package/src/components/Amelipro/AmeliproIconBtn/AmeliproIconBtn.vue +2 -4
- package/src/components/Amelipro/AmeliproIllustratedDataTile/AmeliproIllustratedDataTile.vue +5 -7
- package/src/components/Amelipro/AmeliproIllustratedRadioGroup/AmeliproIllustratedRadioGroup.vue +6 -8
- package/src/components/Amelipro/AmeliproMailTile/AmeliproMailTile.vue +14 -14
- package/src/components/Amelipro/AmeliproMenu/AmeliproMenu.vue +11 -13
- package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/AmeliproDropdownMenu.vue +2 -4
- package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproMessagingLayout.vue +8 -8
- package/src/components/Amelipro/AmeliproMultipleFoldingCard/AmeliproMultipleFoldingCard.vue +40 -40
- package/src/components/Amelipro/AmeliproNumberedCard/AmeliproNumberedCard.vue +27 -27
- package/src/components/Amelipro/AmeliproOnboarding/AmeliproOnboarding.vue +3 -5
- package/src/components/Amelipro/AmeliproPageLayout/AmeliproPageLayout.vue +2 -4
- package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.vue +2 -4
- package/src/components/Amelipro/AmeliproPagination/AmeliproPaginationBtn/AmeliproPaginationBtn.vue +3 -5
- package/src/components/Amelipro/AmeliproPatientBanner/AmeliproPatientBanner.vue +1 -3
- package/src/components/Amelipro/AmeliproPatientLogged/AmeliproPatientLogged.vue +2 -4
- package/src/components/Amelipro/AmeliproPatientLogin/AmeliproPatientLogin.vue +4 -4
- package/src/components/Amelipro/AmeliproPatientLogin/AmeliproPatientLoginForm/AmeliproPatientLoginForm.vue +1 -3
- package/src/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressCityRow/AmeliproPostalAddressCityRow.vue +3 -5
- package/src/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.vue +3 -5
- package/src/components/Amelipro/AmeliproRadioGroup/AmeliproRadioGroup.vue +23 -23
- package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.vue +4 -6
- package/src/components/Amelipro/AmeliproSelect/AmeliproSelect.vue +12 -22
- package/src/components/Amelipro/AmeliproStateTile/AmeliproStateTile.vue +10 -12
- package/src/components/Amelipro/AmeliproStepper/AmeliproStepper.vue +17 -17
- package/src/components/Amelipro/AmeliproTable/AmeliproTable.vue +8 -10
- package/src/components/Amelipro/AmeliproTabs/AmeliproTabBtn/AmeliproTabBtn.vue +6 -8
- package/src/components/Amelipro/AmeliproTabs/AmeliproTabs.vue +4 -4
- package/src/components/Amelipro/AmeliproTextArea/AmeliproTextArea.vue +4 -6
- package/src/components/Amelipro/AmeliproTextField/AmeliproTextField.vue +7 -9
- package/src/components/Amelipro/AmeliproTileBtn/AmeliproTileBtn.vue +3 -5
- package/src/components/Amelipro/AmeliproTooltips/AmeliproTooltips.vue +0 -2
- package/src/components/Amelipro/AmeliproUpload/AmeliproUpload.vue +6 -6
- package/src/components/Amelipro/ServiceMenu/ServiceMenu.vue +2 -2
- package/src/components/Amelipro/StructureMenu/StructureBtn/StructureBtn.vue +4 -4
- package/src/components/Amelipro/StructureMenu/StructureItem/StructureItem.vue +4 -6
- package/src/components/Amelipro/StructureMenu/StructureMenu.vue +2 -2
- package/src/components/Amelipro/StructureMenu/StructureTabs/StructureTabs.vue +2 -2
- package/src/components/Amelipro/UserMenu/UserMenu.vue +1 -3
- package/src/components/BackBtn/tests/BackBtn.visual.cy.ts +43 -0
- package/src/components/BackBtn/tests/__snapshots__/back-btn-custom-bg.snap.png +0 -0
- package/src/components/BackBtn/tests/__snapshots__/back-btn-dark-mode.snap.png +0 -0
- package/src/components/BackBtn/tests/__snapshots__/back-btn-default.snap.png +0 -0
- package/src/components/BackBtn/tests/__snapshots__/back-btn-no-icon.snap.png +0 -0
- package/src/components/Captcha/Captcha.vue +1 -3
- package/src/components/ChipList/ChipList.vue +14 -16
- package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +0 -2
- package/src/components/CopyBtn/CopyBtn.vue +1 -3
- package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.vue +17 -17
- package/src/components/Customs/Selects/SelectBtnField/tests/SelectBtnField.spec.ts +31 -0
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +66 -0
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +7 -3
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +18 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +66 -0
- package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.vue +4 -6
- package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +1 -39
- package/src/components/Customs/Selects/SySelect/SySelect.vue +263 -63
- package/src/components/Customs/Selects/SySelect/accessibilite/Accessibility.mdx +199 -269
- package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +35 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.mdx +5 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +29 -0
- package/src/components/Customs/SyCheckbox/accessibilite/Accessibility.mdx +18 -3
- package/src/components/Customs/SyPagination/SyPagination.vue +0 -2
- package/src/components/Customs/SyTabs/SyTabs.mdx +0 -58
- package/src/components/Customs/SyTabs/SyTabs.stories.ts +32 -33
- package/src/components/Customs/SyTabs/SyTabs.vue +87 -67
- package/src/components/Customs/SyTabs/accessibilite/Accessibility.mdx +83 -23
- package/src/components/Customs/SyTabs/tests/SyTabs.a11y.spec.ts +88 -0
- package/src/components/Customs/SyTabs/tests/SyTabs.spec.ts +46 -1
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +21 -41
- package/src/components/Customs/SyTextField/SyTextField.vue +4 -6
- package/src/components/DatePicker/CalendarMode/DatePicker.vue +12 -14
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +20 -16
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +23 -0
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +8 -10
- package/src/components/DatePicker/composables/tests/useDatePickerState.spec.ts +53 -0
- package/src/components/DatePicker/composables/useDatePickerState.ts +24 -0
- package/src/components/DatePicker/composables/useDateTextField.ts +0 -1
- package/src/components/DatePicker/composables/useMonthButtonCustomization.ts +9 -8
- package/src/components/DatePicker/playground/DatePickerHolidayRule.vue +1 -1
- package/src/components/DialogBox/DialogBox.vue +3 -5
- package/src/components/DialogBox/tests/DialogBox.visual.cy.ts +76 -0
- package/src/components/DialogBox/tests/__snapshots__/dialog-box-custom-texts.snap.png +0 -0
- package/src/components/DialogBox/tests/__snapshots__/dialog-box-default.snap.png +0 -0
- package/src/components/DialogBox/tests/__snapshots__/dialog-box-no-actions.snap.png +0 -0
- package/src/components/FileList/FileList.vue +9 -2
- package/src/components/FileList/UploadItem/UploadItem.vue +11 -13
- package/src/components/FileList/tests/FileList.spec.ts +47 -0
- package/src/components/FileUpload/FileUpload.vue +3 -5
- package/src/components/FileUpload/FileUploadContent.vue +3 -5
- package/src/components/FilterInline/FilterInline.vue +1 -3
- package/src/components/FilterSideBar/FilterSideBar.mdx +44 -1
- package/src/components/FilterSideBar/FilterSideBar.stories.ts +105 -1
- package/src/components/FilterSideBar/FilterSideBar.vue +7 -0
- package/src/components/FilterSideBar/tests/FilterSideBar.a11y.spec.ts +54 -1
- package/src/components/FilterSideBar/tests/FilterSideBar.spec.ts +42 -0
- package/src/components/FooterBar/FooterBar.vue +9 -13
- package/src/components/FranceConnectBtn/FranceConnectBtn.vue +1 -1
- package/src/components/HeaderBar/HeaderBar.vue +2 -3
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.vue +2 -3
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +2 -3
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.vue +0 -1
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +8 -9
- package/src/components/HeaderBar/HeaderBurgerMenu/menu.scss +0 -8
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/HeaderBurgerMenu.visual.cy.ts +196 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated-submenu-open.snap.png +0 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated.snap.png +0 -0
- package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +0 -1
- package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +6 -7
- package/src/components/HeaderBar/tests/HeaderBar.visual.cy.ts +81 -0
- package/src/components/HeaderBar/tests/__snapshots__/header-bar-custom-width.snap.png +0 -0
- package/src/components/HeaderBar/tests/__snapshots__/header-bar-default.snap.png +0 -0
- package/src/components/HeaderBar/tests/__snapshots__/header-bar-no-sticky.snap.png +0 -0
- package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-prepend.snap.png +0 -0
- package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-side.snap.png +0 -0
- package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-subtitle.snap.png +0 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +12 -3
- package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +15 -8
- package/src/components/HeaderToolbar/HeaderToolbar.vue +6 -7
- package/src/components/LangBtn/LangBtn.vue +2 -4
- package/src/components/Logo/tests/Logo.visual.cy.ts +57 -0
- package/src/components/Logo/tests/__snapshots__/logo-avatar.snap.png +0 -0
- package/src/components/Logo/tests/__snapshots__/logo-dark.snap.png +0 -0
- package/src/components/Logo/tests/__snapshots__/logo-default.snap.png +0 -0
- package/src/components/Logo/tests/__snapshots__/logo-no-organism.snap.png +0 -0
- package/src/components/Logo/tests/__snapshots__/logo-no-signature.snap.png +0 -0
- package/src/components/Logo/tests/__snapshots__/logo-risque-pro.snap.png +0 -0
- package/src/components/LogoBrandSection/LogoBrandSection.vue +2 -2
- package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +1 -1
- package/src/components/NirField/NirField.stories.ts +2 -2
- package/src/components/NirField/NirField.vue +3 -5
- package/src/components/NirField/accessibilite/Accessibility.mdx +100 -5
- package/src/components/NirField/tests/NirField.spec.ts +118 -0
- package/src/components/NirField/tests/useNirValidation.spec.ts +449 -0
- package/src/components/NirField/useNirValidation.ts +38 -32
- package/src/components/NotificationBar/Notification/Notification.vue +5 -7
- package/src/components/NotificationBar/NotificationBar.vue +1 -3
- package/src/components/PaginatedTable/PaginatedTable.vue +2 -3
- package/src/components/PaginatedTable/Pagination.vue +3 -5
- package/src/components/PasswordField/PasswordField.vue +8 -10
- package/src/components/PhoneField/PhoneField.vue +3 -3
- package/src/components/RangeField/RangeSlider/RangeSlider.vue +0 -2
- package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +1 -1
- package/src/components/RangeField/tests/RangeField.visual.cy.ts +65 -0
- package/src/components/RangeField/tests/__snapshots__/range-field-custom-bg.snap.png +0 -0
- package/src/components/RangeField/tests/__snapshots__/range-field-custom-range.snap.png +0 -0
- package/src/components/RangeField/tests/__snapshots__/range-field-default.snap.png +0 -0
- package/src/components/RangeField/tests/__snapshots__/range-field-step.snap.png +0 -0
- package/src/components/RangeField/tests/__snapshots__/range-field-with-label.snap.png +0 -0
- package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +6 -8
- package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +3 -5
- package/src/components/SearchListField/SearchListField.vue +0 -2
- package/src/components/SkipLink/SkipLink.vue +2 -4
- package/src/components/SocialMediaLinks/SocialMediaLinks.vue +6 -6
- package/src/components/SubHeader/SubHeader.vue +1 -1
- package/src/components/SyAlert/SyAlert.vue +7 -9
- package/src/components/SyAlert/tests/SyAlert.visual.cy.ts +46 -0
- package/src/components/SyAlert/tests/__snapshots__/sy-alert-closable.snap.png +0 -0
- package/src/components/SyAlert/tests/__snapshots__/sy-alert-error.snap.png +0 -0
- package/src/components/SyAlert/tests/__snapshots__/sy-alert-info.snap.png +0 -0
- package/src/components/SyAlert/tests/__snapshots__/sy-alert-success.snap.png +0 -0
- package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-outlined.snap.png +0 -0
- package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-tonal.snap.png +0 -0
- package/src/components/SyAlert/tests/__snapshots__/sy-alert-warning.snap.png +0 -0
- package/src/components/SyBtnMenu/SyBtnMenu.vue +2 -4
- package/src/components/TableToolbar/TableToolbar.vue +6 -8
- package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +166 -0
- package/src/components/Tables/SyServerTable/SyServerTable.vue +9 -7
- package/src/components/Tables/SyServerTable/tests/SyServerTable.a11y.spec.ts +23 -0
- package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +268 -0
- package/src/components/Tables/SyTable/SyTable.stories.ts +104 -0
- package/src/components/Tables/SyTable/SyTable.vue +9 -7
- package/src/components/Tables/SyTable/tests/SyTable.a11y.spec.ts +22 -0
- package/src/components/Tables/SyTable/tests/SyTable.spec.ts +274 -0
- package/src/components/Tables/common/SyTableFilter.vue +27 -2
- package/src/components/Tables/common/SyTablePagination.vue +142 -19
- package/src/components/Tables/common/TableHeader.vue +40 -3
- package/src/components/Tables/common/filters/SelectFilter.vue +1 -1
- package/src/components/Tables/common/locales.ts +3 -0
- package/src/components/Tables/common/tableStyles.scss +16 -19
- package/src/components/Tables/common/tests/SyTablePagination.spec.ts +18 -0
- package/src/components/Tables/common/tests/TableHeader.spec.ts +39 -0
- package/src/components/Tables/common/types.ts +2 -0
- package/src/components/Tables/common/useTableHeaders.ts +49 -27
- package/src/components/UploadWorkflow/UploadWorkflow.vue +1 -0
- package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +23 -0
- package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +66 -0
- package/src/components/UploadWorkflow/useFileList.ts +3 -0
- package/src/components/UserMenuBtn/UserMenuBtn.vue +1 -3
- package/src/composables/unifyValidation/documentationValidationProps.ts +235 -0
- package/src/composables/validation/useValidation.ts +17 -1
- package/src/composantsVuetify/VBreadcrumbs/VBreadcrumbs.mdx +28 -0
- package/src/composantsVuetify/VBreadcrumbs/v-breadcrumbs.stories.ts +108 -0
- package/src/composantsVuetify/VOtpInput/VOtpInput.mdx +39 -0
- package/src/composantsVuetify/VOtpInput/v-otp-input.stories.ts +56 -0
- package/src/composantsVuetify/VSkeletonLoader/VSkeletonLoader.mdx +42 -0
- package/src/composantsVuetify/VSkeletonLoader/v-skeleton-loader.stories.ts +77 -0
- package/src/composantsVuetify/VSwitch/VSwitch.mdx +47 -0
- package/src/composantsVuetify/VSwitch/v-switch.stories.ts +166 -0
- package/src/designTokens/tests/buildColorClassMap.spec.ts +31 -0
- package/src/designTokens/tests/generateScssTokens.spec.ts +12 -0
- package/src/designTokens/tests/themeUtils.spec.ts +53 -0
- package/src/designTokens/tokens/amelipro/apColors.ts +8 -130
- package/src/designTokens/tokens/amelipro/apColors2026.ts +3 -15
- package/src/designTokens/tokens/amelipro/apContextual.ts +55 -47
- package/src/designTokens/tokens/amelipro/apLightTheme.ts +1 -1
- package/src/designTokens/tokens/amelipro/apSemantic.ts +1 -1
- package/src/designTokens/tokens/baseColors.ts +129 -0
- package/src/designTokens/tokens/baseContextualTokens.ts +52 -0
- package/src/designTokens/tokens/cnam/cnamColors.ts +3 -125
- package/src/designTokens/tokens/cnam/cnamContextual.ts +4 -48
- package/src/designTokens/tokens/cnam/cnamLightTheme.ts +1 -1
- package/src/designTokens/tokens/cnam/cnamSemantic.ts +1 -1
- package/src/designTokens/tokens/pa/paColors.ts +2 -166
- package/src/designTokens/tokens/pa/paContextual.ts +3 -48
- package/src/designTokens/tokens/pa/paLightTheme.ts +1 -1
- package/src/designTokens/tokens/pa/paSemantic.ts +2 -2
- package/src/designTokens/utils/buildColorClassMap.ts +34 -0
- package/src/designTokens/utils/convertSemanticsToken.ts +8 -11
- package/src/designTokens/utils/createFlattenTheme.ts +15 -7
- package/src/designTokens/utils/index.ts +2 -2
- package/src/stories/Accessibilite/AuditDesignSystem.mdx +0 -11
- package/src/stories/Accessibilite/DesignSystem/Avancement.mdx +433 -0
- package/src/stories/Accessibilite/DesignSystem/a11y-status.json +692 -0
- package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +8 -1
- package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +51 -10
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +16 -9
- package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +48 -58
- package/src/stories/Components/Components.stories.ts +40 -1
- package/src/stories/Demarrer/EnrichirLeDesignSystem.mdx +4 -9
- package/src/stories/Demarrer/EnrichirLeDesignSystem.stories.ts +28 -0
- package/src/stories/Demarrer/Releases.stories.ts +48 -5
- package/src/stories/DesignTokens/ColorDisplay.vue +6 -5
- package/src/stories/DesignTokens/ColorIntegrationExample.vue +2 -4
- package/src/stories/DesignTokens/colors.stories.ts +5 -6
- package/src/stories/GuideDuDev/CreateVuetifyInstance.mdx +95 -0
- package/src/stories/GuideDuDev/Theme.mdx +36 -26
- package/src/stories/GuideDuDev/moduleDeNotification.mdx +3 -2
- package/src/stories/styles/accessibility-guide.css +3 -3
- package/src/utils/functions/classToHex.ts +6 -34
- package/src/utils/functions/createHexResolver.ts +45 -0
- package/src/utils/functions/tests/classToHex.spec.ts +36 -0
- package/src/utils/functions/tests/convertToHex.spec.ts +31 -0
- package/src/utils/functions/tests/createHexResolver.spec.ts +66 -0
- package/src/utils/functions/tests/isCssColor.spec.ts +48 -0
- package/dist/apLightTheme-CFSRrjv2.cjs +0 -1
- package/dist/designTokens/utils/convertGaps.d.ts +0 -5
- package/dist/main-BtTqyn4z.js +0 -38648
- package/dist/main-C1e3eoxd.cjs +0 -1067
- package/src/assets/apTokens.scss +0 -343
- package/src/assets/overrides/_container.scss +0 -36
- package/src/assets/tokens.scss +0 -388
- package/src/designTokens/apColors.md +0 -66
- package/src/designTokens/cnamColors.md +0 -193
- package/src/designTokens/paColors.md +0 -66
- package/src/designTokens/tokens/json/contextual-tokens.json +0 -156
- package/src/designTokens/tokens/json/primitives.json +0 -209
- package/src/designTokens/tokens/json/semantic.json +0 -120
- package/src/designTokens/utils/convertGaps.ts +0 -11
- package/src/stories/Accessibilite/Avancement/Avancement.mdx +0 -533
- package/src/stories/Accessibilite/Avancement/Avancement.stories.ts +0 -306
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import NirField from '../NirField.vue'
|
|
4
|
+
import { locales } from '../locales'
|
|
5
|
+
import { useValidation } from '@/composables/unifyValidation/useValidation'
|
|
6
|
+
|
|
7
|
+
describe('useNirValidation via NirField component', () => {
|
|
8
|
+
let wrapper: ReturnType<typeof mount<typeof NirField & {
|
|
9
|
+
numberValidation: ReturnType<typeof useValidation>
|
|
10
|
+
keyValidation: ReturnType<typeof useValidation>
|
|
11
|
+
validateOnSubmit: () => Promise<boolean>
|
|
12
|
+
}>>
|
|
13
|
+
let activeWrappers: ReturnType<typeof mount>[] = []
|
|
14
|
+
|
|
15
|
+
async function flushPromises() {
|
|
16
|
+
return new Promise(resolve => setTimeout(resolve, 0))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const createWrapper = async (props = {}) => {
|
|
20
|
+
const w = mount(NirField, {
|
|
21
|
+
props: {
|
|
22
|
+
modelValue: undefined,
|
|
23
|
+
...props,
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
activeWrappers.push(w)
|
|
27
|
+
await w.vm.$nextTick()
|
|
28
|
+
await flushPromises()
|
|
29
|
+
return w
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
activeWrappers = []
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
afterEach(async () => {
|
|
37
|
+
await flushPromises()
|
|
38
|
+
for (const w of activeWrappers) {
|
|
39
|
+
if (w && typeof w.unmount === 'function') {
|
|
40
|
+
w.unmount()
|
|
41
|
+
await flushPromises()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
activeWrappers = []
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('ne devrait pas afficher d\'erreurs custom si useVuetifyValidation est vrai', async () => {
|
|
48
|
+
wrapper = await createWrapper({ useVuetifyValidation: true, required: true })
|
|
49
|
+
|
|
50
|
+
await wrapper.find('.number-field input').trigger('focus')
|
|
51
|
+
await wrapper.find('.number-field input').trigger('blur')
|
|
52
|
+
await wrapper.vm.$nextTick()
|
|
53
|
+
await flushPromises()
|
|
54
|
+
|
|
55
|
+
// Les règles custom ne sont pas appliquées, donc le système de validation custom ne remonte pas d'erreur
|
|
56
|
+
expect(wrapper.vm.numberValidation.errors.value).toEqual([])
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('devrait afficher une erreur required si le champ est vide et required est vrai', async () => {
|
|
60
|
+
wrapper = await createWrapper({ required: true })
|
|
61
|
+
|
|
62
|
+
await wrapper.find('.number-field input').trigger('focus')
|
|
63
|
+
await wrapper.find('.number-field input').trigger('blur')
|
|
64
|
+
await wrapper.vm.$nextTick()
|
|
65
|
+
await flushPromises()
|
|
66
|
+
|
|
67
|
+
expect(wrapper.vm.numberValidation.errors.value).toContain(locales.errorRequiredNumber)
|
|
68
|
+
|
|
69
|
+
await wrapper.find('.key-field input').trigger('focus')
|
|
70
|
+
await wrapper.find('.key-field input').trigger('blur')
|
|
71
|
+
await wrapper.vm.$nextTick()
|
|
72
|
+
await flushPromises()
|
|
73
|
+
|
|
74
|
+
expect(wrapper.vm.keyValidation.errors.value).toContain(locales.errorRequiredKey)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('devrait valider correctement le NIR (valide et invalide)', async () => {
|
|
78
|
+
wrapper = await createWrapper()
|
|
79
|
+
|
|
80
|
+
const numberInput = wrapper.find('.number-field input')
|
|
81
|
+
|
|
82
|
+
// Test invalide (trop court)
|
|
83
|
+
await numberInput.trigger('focus')
|
|
84
|
+
await numberInput.setValue('123456789012')
|
|
85
|
+
await numberInput.trigger('blur')
|
|
86
|
+
await wrapper.vm.$nextTick()
|
|
87
|
+
await flushPromises()
|
|
88
|
+
expect(wrapper.vm.numberValidation.errors.value).toContain(locales.errorInvalidNumber)
|
|
89
|
+
|
|
90
|
+
// Test invalide (mauvais NIR - sexe 0 invalide)
|
|
91
|
+
await numberInput.trigger('focus')
|
|
92
|
+
await numberInput.setValue('0000000000000')
|
|
93
|
+
await numberInput.trigger('blur')
|
|
94
|
+
await wrapper.vm.$nextTick()
|
|
95
|
+
await flushPromises()
|
|
96
|
+
expect(wrapper.vm.numberValidation.errors.value).toContain(locales.errorInvalidNumber)
|
|
97
|
+
|
|
98
|
+
// Test valide
|
|
99
|
+
await numberInput.trigger('focus')
|
|
100
|
+
await numberInput.setValue('2940375120005')
|
|
101
|
+
await numberInput.trigger('blur')
|
|
102
|
+
await wrapper.vm.$nextTick()
|
|
103
|
+
await flushPromises()
|
|
104
|
+
expect(wrapper.vm.numberValidation.errors.value).toEqual([])
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('devrait valider correctement la clé', async () => {
|
|
108
|
+
wrapper = await createWrapper()
|
|
109
|
+
|
|
110
|
+
const numberInput = wrapper.find('.number-field input')
|
|
111
|
+
const keyInput = wrapper.find('.key-field input')
|
|
112
|
+
|
|
113
|
+
// Remplissons d'abord le NIR
|
|
114
|
+
await numberInput.setValue('2940375120005')
|
|
115
|
+
await wrapper.vm.$nextTick()
|
|
116
|
+
await flushPromises()
|
|
117
|
+
|
|
118
|
+
// Test clé invalide
|
|
119
|
+
await keyInput.trigger('focus')
|
|
120
|
+
await keyInput.setValue('90')
|
|
121
|
+
await keyInput.trigger('blur')
|
|
122
|
+
await wrapper.vm.$nextTick()
|
|
123
|
+
await flushPromises()
|
|
124
|
+
expect(wrapper.vm.keyValidation.errors.value).toContain(locales.errorInvalidKey)
|
|
125
|
+
|
|
126
|
+
// Test clé valide (clé attendue pour 2940375120005 est 91)
|
|
127
|
+
await keyInput.trigger('focus')
|
|
128
|
+
await keyInput.setValue('91')
|
|
129
|
+
await keyInput.trigger('blur')
|
|
130
|
+
await wrapper.vm.$nextTick()
|
|
131
|
+
await flushPromises()
|
|
132
|
+
expect(wrapper.vm.keyValidation.errors.value).toEqual([])
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('devrait appliquer la précédence des règles customNumberRules si customRulesPrecedence est vrai', async () => {
|
|
136
|
+
const customMessage = 'Erreur custom en premier'
|
|
137
|
+
const customRule1 = {
|
|
138
|
+
type: 'custom',
|
|
139
|
+
options: {
|
|
140
|
+
validate: () => customMessage,
|
|
141
|
+
message: customMessage,
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
wrapper = await createWrapper({
|
|
146
|
+
customRulesPrecedence: true,
|
|
147
|
+
customNumberRules: [customRule1],
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
const numberInput = wrapper.find('.number-field input')
|
|
151
|
+
await numberInput.trigger('focus')
|
|
152
|
+
await numberInput.setValue('0000000000000') // Valeur invalide selon checkNIR
|
|
153
|
+
await numberInput.trigger('blur')
|
|
154
|
+
await wrapper.vm.$nextTick()
|
|
155
|
+
await flushPromises()
|
|
156
|
+
|
|
157
|
+
// Comme la règle custom a la précédence, c'est son erreur qui s'affiche en premier
|
|
158
|
+
// (useValidation s'arrête à la première erreur)
|
|
159
|
+
expect(wrapper.vm.numberValidation.errors.value[0]).toBe(customMessage)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('devrait appliquer les règles customNumberRules à la fin si customRulesPrecedence est faux', async () => {
|
|
163
|
+
const customMessage = 'Erreur custom en dernier'
|
|
164
|
+
const customRule1 = {
|
|
165
|
+
type: 'custom',
|
|
166
|
+
options: {
|
|
167
|
+
validate: () => customMessage,
|
|
168
|
+
message: customMessage,
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
wrapper = await createWrapper({
|
|
173
|
+
customRulesPrecedence: false,
|
|
174
|
+
customNumberRules: [customRule1],
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
const numberInput = wrapper.find('.number-field input')
|
|
178
|
+
await numberInput.trigger('focus')
|
|
179
|
+
await numberInput.setValue('0000000000000') // Valeur invalide selon checkNIR
|
|
180
|
+
await numberInput.trigger('blur')
|
|
181
|
+
await wrapper.vm.$nextTick()
|
|
182
|
+
await flushPromises()
|
|
183
|
+
|
|
184
|
+
// L'erreur par défaut checkNIR s'affiche en premier (useValidation s'arrête à la première)
|
|
185
|
+
expect(wrapper.vm.numberValidation.errors.value[0]).toBe(locales.errorInvalidNumber)
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
it('devrait utiliser customKeyRules et masquer la règle par défaut si elle a validate', async () => {
|
|
189
|
+
const customMessage = 'Clé custom invalide'
|
|
190
|
+
const customKeyRule = {
|
|
191
|
+
type: 'custom',
|
|
192
|
+
options: {
|
|
193
|
+
validate: () => customMessage,
|
|
194
|
+
message: customMessage,
|
|
195
|
+
},
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
wrapper = await createWrapper({
|
|
199
|
+
customKeyRules: [customKeyRule],
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
const keyInput = wrapper.find('.key-field input')
|
|
203
|
+
await keyInput.trigger('focus')
|
|
204
|
+
await keyInput.setValue('91')
|
|
205
|
+
await keyInput.trigger('blur')
|
|
206
|
+
await wrapper.vm.$nextTick()
|
|
207
|
+
await flushPromises()
|
|
208
|
+
|
|
209
|
+
// Seule la règle custom est appliquée (et elle retourne une erreur)
|
|
210
|
+
expect(wrapper.vm.keyValidation.errors.value[0]).toBe(customMessage)
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('devrait valider correctement les deux champs lors de l\'appel à validateOnSubmit()', async () => {
|
|
214
|
+
wrapper = await createWrapper()
|
|
215
|
+
|
|
216
|
+
// Set valid values
|
|
217
|
+
await wrapper.find('.number-field input').setValue('2940375120005')
|
|
218
|
+
await wrapper.find('.key-field input').setValue('91')
|
|
219
|
+
await wrapper.vm.$nextTick()
|
|
220
|
+
await flushPromises()
|
|
221
|
+
|
|
222
|
+
const isValid = await wrapper.vm.validateOnSubmit()
|
|
223
|
+
expect(isValid).toBe(true)
|
|
224
|
+
|
|
225
|
+
// Si on a des valeurs invalides
|
|
226
|
+
await wrapper.find('.key-field input').setValue('90')
|
|
227
|
+
await wrapper.vm.$nextTick()
|
|
228
|
+
await flushPromises()
|
|
229
|
+
|
|
230
|
+
const isInvalid = await wrapper.vm.validateOnSubmit()
|
|
231
|
+
expect(isInvalid).toBe(false)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('devrait valider correctement un NIR avec un département corse (2A / 2B)', async () => {
|
|
235
|
+
wrapper = await createWrapper()
|
|
236
|
+
|
|
237
|
+
const numberInput = wrapper.find('.number-field input')
|
|
238
|
+
const keyInput = wrapper.find('.key-field input')
|
|
239
|
+
|
|
240
|
+
// Corsica suttana
|
|
241
|
+
// 1 90 01 2A 001 001 (remplace 2A par 19 -> 1900119001001)
|
|
242
|
+
// 1900119001001 % 97 = 41 -> Clé attendue: 97 - 41 = 56
|
|
243
|
+
await numberInput.trigger('focus')
|
|
244
|
+
await numberInput.setValue('190012A001001')
|
|
245
|
+
await numberInput.trigger('blur')
|
|
246
|
+
|
|
247
|
+
await keyInput.trigger('focus')
|
|
248
|
+
await keyInput.setValue('56')
|
|
249
|
+
await keyInput.trigger('blur')
|
|
250
|
+
|
|
251
|
+
await wrapper.vm.$nextTick()
|
|
252
|
+
await flushPromises()
|
|
253
|
+
|
|
254
|
+
expect(wrapper.vm.numberValidation.errors.value).toEqual([])
|
|
255
|
+
expect(wrapper.vm.keyValidation.errors.value).toEqual([])
|
|
256
|
+
|
|
257
|
+
// Corsica suprana
|
|
258
|
+
// 1 90 01 2B 001 001 (remplace 2B par 18 -> 1900118001001)
|
|
259
|
+
// 1900118001001 % 97 = 14 -> Clé attendue: 97 - 14 = 83
|
|
260
|
+
await numberInput.trigger('focus')
|
|
261
|
+
await numberInput.setValue('190012B001001')
|
|
262
|
+
await numberInput.trigger('blur')
|
|
263
|
+
|
|
264
|
+
await keyInput.trigger('focus')
|
|
265
|
+
await keyInput.setValue('83')
|
|
266
|
+
await keyInput.trigger('blur')
|
|
267
|
+
|
|
268
|
+
await wrapper.vm.$nextTick()
|
|
269
|
+
await flushPromises()
|
|
270
|
+
|
|
271
|
+
expect(wrapper.vm.numberValidation.errors.value).toEqual([])
|
|
272
|
+
expect(wrapper.vm.keyValidation.errors.value).toEqual([])
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('devrait appliquer des règles différentes selon le nirType (simple vs complexe)', async () => {
|
|
276
|
+
// Le mois '50' est valide pour 'simple' (accepte de 20 à 99 pour le mois)
|
|
277
|
+
// mais invalide pour 'complexe' (n'accepte que jusqu'à 42 pour les pseudo-mois)
|
|
278
|
+
// Format: S AA MM DDD C C C
|
|
279
|
+
// Homme (1), 90, mois 50, corse 2A, 001, 001
|
|
280
|
+
const invalidComplexNir = '190502A001001'
|
|
281
|
+
|
|
282
|
+
// Par défaut, nirType est 'simple' donc le NIR doit être valide
|
|
283
|
+
wrapper = await createWrapper()
|
|
284
|
+
let numberInput = wrapper.find('.number-field input')
|
|
285
|
+
|
|
286
|
+
await numberInput.trigger('focus')
|
|
287
|
+
await numberInput.setValue(invalidComplexNir)
|
|
288
|
+
await numberInput.trigger('blur')
|
|
289
|
+
await wrapper.vm.$nextTick()
|
|
290
|
+
await flushPromises()
|
|
291
|
+
|
|
292
|
+
expect(wrapper.vm.numberValidation.errors.value).toEqual([])
|
|
293
|
+
|
|
294
|
+
// On change le type à 'complexe', le NIR devient invalide
|
|
295
|
+
wrapper = await createWrapper({ nirType: 'complexe' })
|
|
296
|
+
numberInput = wrapper.find('.number-field input')
|
|
297
|
+
|
|
298
|
+
await numberInput.trigger('focus')
|
|
299
|
+
await numberInput.setValue(invalidComplexNir)
|
|
300
|
+
await numberInput.trigger('blur')
|
|
301
|
+
await wrapper.vm.$nextTick()
|
|
302
|
+
await flushPromises()
|
|
303
|
+
|
|
304
|
+
expect(wrapper.vm.numberValidation.errors.value).toContain(locales.errorInvalidNumber)
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
it('ne devrait appliquer les customWarningRules que si la longueur est complète', async () => {
|
|
308
|
+
const numberWarning = 'Attention numéro'
|
|
309
|
+
const keyWarning = 'Attention clé'
|
|
310
|
+
|
|
311
|
+
wrapper = await createWrapper({
|
|
312
|
+
customNumberWarningRules: [{ type: 'custom', options: { validate: () => numberWarning, message: numberWarning } }],
|
|
313
|
+
customKeyWarningRules: [{ type: 'custom', options: { validate: () => keyWarning, message: keyWarning } }],
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
const numberInput = wrapper.find('.number-field input')
|
|
317
|
+
const keyInput = wrapper.find('.key-field input')
|
|
318
|
+
|
|
319
|
+
// Saisie partielle du numéro
|
|
320
|
+
await numberInput.trigger('focus')
|
|
321
|
+
await numberInput.setValue('123456789012') // 12 caractères
|
|
322
|
+
await numberInput.trigger('blur')
|
|
323
|
+
await wrapper.vm.$nextTick()
|
|
324
|
+
await flushPromises()
|
|
325
|
+
|
|
326
|
+
// Le warning n'est pas appliqué car < 13 caractères
|
|
327
|
+
expect(wrapper.vm.numberValidation.warnings.value).toEqual([])
|
|
328
|
+
|
|
329
|
+
// Saisie complète du numéro
|
|
330
|
+
await numberInput.trigger('focus')
|
|
331
|
+
await numberInput.setValue('1234567890123') // 13 caractères
|
|
332
|
+
await numberInput.trigger('blur')
|
|
333
|
+
await wrapper.vm.$nextTick()
|
|
334
|
+
await flushPromises()
|
|
335
|
+
|
|
336
|
+
expect(wrapper.vm.numberValidation.warnings.value).toContain(numberWarning)
|
|
337
|
+
|
|
338
|
+
// Saisie partielle de la clé
|
|
339
|
+
await keyInput.trigger('focus')
|
|
340
|
+
await keyInput.setValue('9') // 1 caractère
|
|
341
|
+
await keyInput.trigger('blur')
|
|
342
|
+
await wrapper.vm.$nextTick()
|
|
343
|
+
await flushPromises()
|
|
344
|
+
|
|
345
|
+
// Le warning n'est pas appliqué car < 2 caractères
|
|
346
|
+
expect(wrapper.vm.keyValidation.warnings.value).toEqual([])
|
|
347
|
+
|
|
348
|
+
// Saisie complète de la clé (le numéro doit être aussi complet pour valider la clé et déclencher le watch)
|
|
349
|
+
await numberInput.trigger('focus')
|
|
350
|
+
await numberInput.setValue('2940375120005') // on s'assure d'avoir un NIR valide
|
|
351
|
+
await numberInput.trigger('blur')
|
|
352
|
+
await wrapper.vm.$nextTick()
|
|
353
|
+
await flushPromises()
|
|
354
|
+
|
|
355
|
+
await keyInput.trigger('focus')
|
|
356
|
+
await keyInput.setValue('91') // 2 caractères (clé valide)
|
|
357
|
+
await keyInput.trigger('blur')
|
|
358
|
+
await wrapper.vm.$nextTick()
|
|
359
|
+
await flushPromises()
|
|
360
|
+
|
|
361
|
+
// Validation explicite pour forcer l'évaluation
|
|
362
|
+
await wrapper.vm.keyValidation.validate()
|
|
363
|
+
await wrapper.vm.$nextTick()
|
|
364
|
+
await flushPromises()
|
|
365
|
+
|
|
366
|
+
expect(wrapper.vm.keyValidation.warnings.value).toContain(keyWarning)
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
it('devrait mettre le focus sur le champ en erreur lors d\'une validation globale', async () => {
|
|
370
|
+
wrapper = await createWrapper({ required: true })
|
|
371
|
+
|
|
372
|
+
// Espionner le focus sur les inputs natifs
|
|
373
|
+
const numberInputEl = wrapper.find('.number-field input').element as HTMLInputElement
|
|
374
|
+
const keyInputEl = wrapper.find('.key-field input').element as HTMLInputElement
|
|
375
|
+
|
|
376
|
+
const numberFocusSpy = vi.spyOn(numberInputEl, 'focus')
|
|
377
|
+
const keyFocusSpy = vi.spyOn(keyInputEl, 'focus')
|
|
378
|
+
|
|
379
|
+
// Les champs sont vides, donc number sera en erreur en premier
|
|
380
|
+
await wrapper.vm.validateOnSubmit()
|
|
381
|
+
await wrapper.vm.$nextTick()
|
|
382
|
+
await flushPromises()
|
|
383
|
+
|
|
384
|
+
expect(numberFocusSpy).toHaveBeenCalled()
|
|
385
|
+
expect(keyFocusSpy).not.toHaveBeenCalled()
|
|
386
|
+
|
|
387
|
+
// On remplit le NIR mais la clé est vide (ou invalide)
|
|
388
|
+
numberFocusSpy.mockClear()
|
|
389
|
+
keyFocusSpy.mockClear()
|
|
390
|
+
|
|
391
|
+
await wrapper.find('.number-field input').setValue('2940375120005')
|
|
392
|
+
await wrapper.vm.$nextTick()
|
|
393
|
+
await flushPromises()
|
|
394
|
+
|
|
395
|
+
await wrapper.vm.validateOnSubmit()
|
|
396
|
+
await wrapper.vm.$nextTick()
|
|
397
|
+
await flushPromises()
|
|
398
|
+
|
|
399
|
+
expect(numberFocusSpy).not.toHaveBeenCalled()
|
|
400
|
+
expect(keyFocusSpy).toHaveBeenCalled()
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
it('ne devrait pas valider la clé lorsque displayKey est à false', async () => {
|
|
404
|
+
wrapper = await createWrapper({ displayKey: false, required: true })
|
|
405
|
+
|
|
406
|
+
const numberInput = wrapper.find('.number-field input')
|
|
407
|
+
|
|
408
|
+
// Saisir un NIR valide
|
|
409
|
+
await numberInput.trigger('focus')
|
|
410
|
+
await numberInput.setValue('2940375120005')
|
|
411
|
+
await numberInput.trigger('blur')
|
|
412
|
+
await wrapper.vm.$nextTick()
|
|
413
|
+
await flushPromises()
|
|
414
|
+
|
|
415
|
+
// Le champ numéro ne doit pas avoir d'erreur
|
|
416
|
+
expect(wrapper.vm.numberValidation.errors.value).toEqual([])
|
|
417
|
+
|
|
418
|
+
// La validation de la clé ne doit pas s'appliquer (pas de règles)
|
|
419
|
+
expect(wrapper.vm.keyValidation.errors.value).toEqual([])
|
|
420
|
+
|
|
421
|
+
// La validation globale doit réussir même sans clé
|
|
422
|
+
const isValid = await wrapper.vm.validateOnSubmit()
|
|
423
|
+
expect(isValid).toBe(true)
|
|
424
|
+
|
|
425
|
+
// hasFieldErrors doit être false car seule la validation du numéro compte
|
|
426
|
+
// On accède à hasFieldErrors via le composant car il est exposé par useNirValidation
|
|
427
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- deso
|
|
428
|
+
const componentInstance = wrapper.vm as any
|
|
429
|
+
expect(componentInstance.hasFieldErrors).toBe(false)
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
it('devrait ignorer les erreurs de clé lors de la validation globale lorsque displayKey est à false', async () => {
|
|
433
|
+
wrapper = await createWrapper({ displayKey: false })
|
|
434
|
+
|
|
435
|
+
const numberInput = wrapper.find('.number-field input')
|
|
436
|
+
|
|
437
|
+
// Saisir un NIR valide
|
|
438
|
+
await numberInput.trigger('focus')
|
|
439
|
+
await numberInput.setValue('2940375120005')
|
|
440
|
+
await numberInput.trigger('blur')
|
|
441
|
+
await wrapper.vm.$nextTick()
|
|
442
|
+
await flushPromises()
|
|
443
|
+
|
|
444
|
+
// Même si la clé n'est pas affichée, on vérifie que la validation globale ignore bien les erreurs de clé
|
|
445
|
+
// (simuler une erreur de clé qui ne devrait pas impacter la validation)
|
|
446
|
+
const isValid = await wrapper.vm.validateOnSubmit()
|
|
447
|
+
expect(isValid).toBe(true)
|
|
448
|
+
})
|
|
449
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ValidationRule as SyValidationRule } from '@/composables/validation/useValidation'
|
|
2
2
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, type Ref } from 'vue'
|
|
3
3
|
import { checkNIR, isNIRKeyValid } from './nirValidation'
|
|
4
|
-
import
|
|
4
|
+
import { locales } from './locales'
|
|
5
5
|
import { useValidation } from '@/composables/unifyValidation/useValidation'
|
|
6
6
|
import type { SyTextField } from '@/main'
|
|
7
7
|
import type { ValidationRule as VuetifyValidationRule } from 'vuetify'
|
|
@@ -66,7 +66,7 @@ export function useNirValidation(
|
|
|
66
66
|
rules.push({
|
|
67
67
|
type: 'required',
|
|
68
68
|
options: {
|
|
69
|
-
message: customLocale.value.errorRequiredNumber,
|
|
69
|
+
message: customLocale.value.errorRequiredNumber || locales.errorRequiredNumber,
|
|
70
70
|
fieldIdentifier: numberLabel.value,
|
|
71
71
|
},
|
|
72
72
|
})
|
|
@@ -88,13 +88,13 @@ export function useNirValidation(
|
|
|
88
88
|
if (!value) return true
|
|
89
89
|
// Ne valider que si tous les caractères sont saisis
|
|
90
90
|
if (value.length < 13) {
|
|
91
|
-
return customLocale.value.errorInvalidNumber ||
|
|
91
|
+
return customLocale.value.errorInvalidNumber || locales.errorInvalidNumber
|
|
92
92
|
}
|
|
93
93
|
const result = checkNIR(value, nirType.value)
|
|
94
|
-
return result ? true : customLocale.value.errorInvalidNumber ||
|
|
94
|
+
return result ? true : customLocale.value.errorInvalidNumber || locales.errorInvalidNumber
|
|
95
95
|
},
|
|
96
|
-
message: customLocale.value.errorInvalidNumber,
|
|
97
|
-
successMessage: customLocale.value.successNumberValid,
|
|
96
|
+
message: customLocale.value.errorInvalidNumber || locales.errorInvalidNumber,
|
|
97
|
+
successMessage: customLocale.value.successNumberValid || locales.successNumberValid,
|
|
98
98
|
fieldIdentifier: numberLabel.value,
|
|
99
99
|
},
|
|
100
100
|
})
|
|
@@ -111,7 +111,7 @@ export function useNirValidation(
|
|
|
111
111
|
})
|
|
112
112
|
|
|
113
113
|
const keyRules = computed(() => {
|
|
114
|
-
if (useVuetifyValidation.value) {
|
|
114
|
+
if (useVuetifyValidation.value || !displayKey.value) {
|
|
115
115
|
return []
|
|
116
116
|
}
|
|
117
117
|
const rules: SyValidationRule[] = []
|
|
@@ -119,7 +119,7 @@ export function useNirValidation(
|
|
|
119
119
|
rules.push({
|
|
120
120
|
type: 'required',
|
|
121
121
|
options: {
|
|
122
|
-
message: customLocale.value.errorRequiredKey,
|
|
122
|
+
message: customLocale.value.errorRequiredKey || locales.errorRequiredKey,
|
|
123
123
|
fieldIdentifier: keyLabel.value,
|
|
124
124
|
},
|
|
125
125
|
})
|
|
@@ -143,8 +143,8 @@ export function useNirValidation(
|
|
|
143
143
|
type: 'custom',
|
|
144
144
|
options: {
|
|
145
145
|
validate: validateKey,
|
|
146
|
-
message: customLocale.value.errorInvalidKey,
|
|
147
|
-
successMessage: customLocale.value.successKeyValid,
|
|
146
|
+
message: customLocale.value.errorInvalidKey || locales.errorInvalidKey,
|
|
147
|
+
successMessage: customLocale.value.successKeyValid || locales.successKeyValid,
|
|
148
148
|
fieldIdentifier: keyLabel.value,
|
|
149
149
|
},
|
|
150
150
|
})
|
|
@@ -156,6 +156,7 @@ export function useNirValidation(
|
|
|
156
156
|
// État pour suivre si une validation est en cours
|
|
157
157
|
const isValidating = ref(false)
|
|
158
158
|
const shouldValidateOnBlur = ref(false)
|
|
159
|
+
let validationPromise: Promise<boolean> | null = null
|
|
159
160
|
const numberFieldFocused = ref(false)
|
|
160
161
|
const keyFieldFocused = ref(false)
|
|
161
162
|
|
|
@@ -230,37 +231,42 @@ export function useNirValidation(
|
|
|
230
231
|
})
|
|
231
232
|
|
|
232
233
|
// Validation des champs
|
|
233
|
-
const validateFields =
|
|
234
|
-
|
|
235
|
-
if (isValidating.value) {
|
|
236
|
-
shouldValidateOnBlur.value = shouldValidateOnBlur.value || onBlur
|
|
237
|
-
return true
|
|
238
|
-
}
|
|
234
|
+
const validateFields = (onBlur = false): Promise<boolean> => {
|
|
235
|
+
shouldValidateOnBlur.value = shouldValidateOnBlur.value || onBlur
|
|
239
236
|
|
|
240
|
-
|
|
237
|
+
if (validationPromise) {
|
|
238
|
+
return validationPromise
|
|
239
|
+
}
|
|
241
240
|
|
|
242
|
-
|
|
241
|
+
validationPromise = (async () => {
|
|
242
|
+
isValidating.value = true
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
await keyValidation.validate()
|
|
246
|
-
}
|
|
244
|
+
await numberValidation.validate()
|
|
247
245
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (numberValidation.hasError.value) {
|
|
251
|
-
numberField.value?.$el?.querySelector?.('input')?.focus()
|
|
246
|
+
if (displayKey.value) {
|
|
247
|
+
await keyValidation.validate()
|
|
252
248
|
}
|
|
253
|
-
|
|
254
|
-
|
|
249
|
+
|
|
250
|
+
if (shouldValidateOnBlur.value) {
|
|
251
|
+
await nextTick()
|
|
252
|
+
if (numberValidation.hasError.value) {
|
|
253
|
+
numberField.value?.$el?.querySelector?.('input')?.focus()
|
|
254
|
+
}
|
|
255
|
+
else if (keyValidation.hasError.value) {
|
|
256
|
+
keyField.value?.$el?.querySelector?.('input')?.focus()
|
|
257
|
+
}
|
|
258
|
+
shouldValidateOnBlur.value = false
|
|
255
259
|
}
|
|
256
|
-
shouldValidateOnBlur.value = false
|
|
257
|
-
}
|
|
258
260
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
+
isValidating.value = false
|
|
262
|
+
validationPromise = null
|
|
263
|
+
return !numberValidation.hasError.value && (!displayKey.value || !keyValidation.hasError.value)
|
|
264
|
+
})()
|
|
265
|
+
|
|
266
|
+
return validationPromise
|
|
261
267
|
}
|
|
262
268
|
|
|
263
|
-
const hasFieldErrors = computed(() => numberValidation.hasError.value || keyValidation.hasError.value)
|
|
269
|
+
const hasFieldErrors = computed(() => numberValidation.hasError.value || (displayKey.value && keyValidation.hasError.value))
|
|
264
270
|
|
|
265
271
|
return {
|
|
266
272
|
numberValidation,
|
|
@@ -107,16 +107,14 @@
|
|
|
107
107
|
</div>
|
|
108
108
|
</template>
|
|
109
109
|
<style scoped lang="scss">
|
|
110
|
-
@use '@/assets/tokens';
|
|
111
|
-
|
|
112
110
|
.notification {
|
|
113
111
|
display: flex;
|
|
114
112
|
align-items: center;
|
|
115
113
|
width: 100%;
|
|
116
114
|
transform: translateX(-50%);
|
|
117
|
-
padding:
|
|
118
|
-
margin-block:
|
|
119
|
-
gap:
|
|
115
|
+
padding: var(--v-gap-2) var(--v-gap-4);
|
|
116
|
+
margin-block: var(--v-gap-1);
|
|
117
|
+
gap: var(--v-gap-2) var(--v-gap-4);
|
|
120
118
|
box-shadow:
|
|
121
119
|
0 3px 5px -1px var(--v-shadow-key-umbra-opacity, rgb(0 0 0 / 20%)),
|
|
122
120
|
0 6px 10px 0 var(--v-shadow-key-penumbra-opacity, rgb(0 0 0 / 14%)),
|
|
@@ -180,10 +178,10 @@
|
|
|
180
178
|
|
|
181
179
|
.notification--long-text {
|
|
182
180
|
/* stylelint-disable-next-line */
|
|
183
|
-
@media screen and (width <=
|
|
181
|
+
@media screen and (width <= 600px) {
|
|
184
182
|
flex-direction: column;
|
|
185
183
|
align-items: flex-start;
|
|
186
|
-
padding:
|
|
184
|
+
padding: var(--v-gap-4);
|
|
187
185
|
|
|
188
186
|
.notification__actions {
|
|
189
187
|
justify-content: space-between;
|
|
@@ -136,8 +136,6 @@
|
|
|
136
136
|
</template>
|
|
137
137
|
|
|
138
138
|
<style lang="scss" scoped>
|
|
139
|
-
@use '@/assets/tokens';
|
|
140
|
-
|
|
141
139
|
.sy-notification-content {
|
|
142
140
|
min-width: 0;
|
|
143
141
|
word-wrap: break-word;
|
|
@@ -202,7 +200,7 @@
|
|
|
202
200
|
opacity: 0;
|
|
203
201
|
height: 0;
|
|
204
202
|
padding-block: 0;
|
|
205
|
-
margin-block:
|
|
203
|
+
margin-block: var(--v-gap-0);
|
|
206
204
|
}
|
|
207
205
|
}
|
|
208
206
|
</style>
|
|
@@ -237,7 +237,6 @@
|
|
|
237
237
|
|
|
238
238
|
<style lang="scss" scoped>
|
|
239
239
|
/* stylelint-disable selector-class-pattern */
|
|
240
|
-
@use '@/assets/tokens';
|
|
241
240
|
|
|
242
241
|
.sy-paginated-table :deep() {
|
|
243
242
|
table thead tr {
|
|
@@ -278,12 +277,12 @@
|
|
|
278
277
|
.v-field__append-inner > .v-icon,
|
|
279
278
|
.v-field__clearable > .v-icon {
|
|
280
279
|
opacity: 1;
|
|
281
|
-
color:
|
|
280
|
+
color: rgb(var(--v-theme-primary));
|
|
282
281
|
}
|
|
283
282
|
}
|
|
284
283
|
|
|
285
284
|
&--focused {
|
|
286
|
-
border-color:
|
|
285
|
+
border-color: rgb(var(--v-theme-primary));
|
|
287
286
|
}
|
|
288
287
|
}
|
|
289
288
|
}
|
|
@@ -58,8 +58,6 @@
|
|
|
58
58
|
</div>
|
|
59
59
|
</template>
|
|
60
60
|
<style scoped lang="scss">
|
|
61
|
-
@use '@/assets/tokens';
|
|
62
|
-
|
|
63
61
|
/* stylelint-disable-next-line selector-class-pattern */
|
|
64
62
|
:deep(.v-field__outline__notch, .v-field-label) {
|
|
65
63
|
width: 0;
|
|
@@ -75,12 +73,12 @@
|
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
:deep(.v-pagination) button:focus-visible {
|
|
78
|
-
outline: 2px solid
|
|
76
|
+
outline: 2px solid var(--v-theme-colors-interactive);
|
|
79
77
|
outline-offset: -2px;
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
:deep(.v-pagination) .v-pagination__list [aria-disabled='false'] svg {
|
|
83
|
-
color:
|
|
81
|
+
color: rgb(var(--v-theme-iconBase));
|
|
84
82
|
}
|
|
85
83
|
|
|
86
84
|
:deep(.v-pagination) .v-btn--variant-plain[aria-disabled='false'] {
|
|
@@ -88,6 +86,6 @@
|
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
:deep(.v-pagination) .v-btn--variant-plain:hover[aria-disabled='false'] svg {
|
|
91
|
-
color:
|
|
89
|
+
color: rgb(var(--v-theme-textBase));
|
|
92
90
|
}
|
|
93
91
|
</style>
|