@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.
Files changed (367) hide show
  1. package/README.md +27 -5
  2. package/dist/{AutocompleteFilter-BWLR3U7W.js → AutocompleteFilter-D7qBuCAP.js} +1 -1
  3. package/dist/{AutocompleteFilter-D9jzRzAL.cjs → AutocompleteFilter-Df9i5mAl.cjs} +1 -1
  4. package/dist/{DateFilter-DTUl8hb1.cjs → DateFilter-BJD6FMev.cjs} +1 -1
  5. package/dist/{DateFilter-BpwFexzi.js → DateFilter-BitMWrMU.js} +1 -1
  6. package/dist/{NumberFilter-Bz_NTdX9.js → NumberFilter-BTLUxw0a.js} +1 -1
  7. package/dist/{NumberFilter-MAEojdk0.cjs → NumberFilter-DGCzCXzI.cjs} +1 -1
  8. package/dist/{PeriodFilter-DX_wy9g-.js → PeriodFilter-B5rUIPAC.js} +1 -1
  9. package/dist/{PeriodFilter-CC4WgIhl.cjs → PeriodFilter-DO_ecTZW.cjs} +1 -1
  10. package/dist/{SelectFilter-BR3fvl-a.cjs → SelectFilter-CGwcKWLm.cjs} +1 -1
  11. package/dist/{SelectFilter-xqiPtPgX.js → SelectFilter-l4QnRcuk.js} +2 -2
  12. package/dist/{TextFilter-CCfYFl5F.cjs → TextFilter-B8nf7xoK.cjs} +1 -1
  13. package/dist/{TextFilter-BBl3JFqK.js → TextFilter-C9hj6Qrp.js} +1 -1
  14. package/dist/apLightTheme-CEK4iY3f.cjs +1 -0
  15. package/dist/{apLightTheme-D1P4jcD0.js → apLightTheme-DnIM24Lv.js} +441 -722
  16. package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +10 -6
  17. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +3 -0
  18. package/dist/components/Customs/SyTabs/SyTabs.d.ts +13 -11
  19. package/dist/components/Customs/SyTextField/SyTextField.d.ts +4 -4
  20. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +4 -24
  21. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +2 -12
  22. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +1 -6
  23. package/dist/components/DatePicker/composables/useDatePickerState.d.ts +1 -0
  24. package/dist/components/FileList/FileList.d.ts +6 -0
  25. package/dist/components/FilterSideBar/FilterSideBar.d.ts +2 -0
  26. package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +13 -13
  27. package/dist/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.d.ts +3 -3
  28. package/dist/components/MonthPicker/MonthPicker.d.ts +1 -6
  29. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1 -6
  30. package/dist/components/NirField/NirField.d.ts +4 -16
  31. package/dist/components/PeriodField/PeriodField.d.ts +8 -48
  32. package/dist/components/PhoneField/PhoneField.d.ts +1 -6
  33. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +1 -0
  34. package/dist/components/Tables/SyTable/SyTable.d.ts +1 -0
  35. package/dist/components/Tables/common/SyTablePagination.d.ts +2 -0
  36. package/dist/components/Tables/common/TableHeader.d.ts +5 -0
  37. package/dist/components/Tables/common/locales.d.ts +3 -0
  38. package/dist/components/Tables/common/types.d.ts +2 -0
  39. package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +1 -0
  40. package/dist/composables/unifyValidation/documentationValidationProps.d.ts +230 -0
  41. package/dist/composables/validation/useValidation.d.ts +5 -1
  42. package/dist/design-system-v3.js +2 -2
  43. package/dist/design-system-v3.umd.cjs +1 -1
  44. package/dist/designTokens/tokens/amelipro/apColors.d.ts +10 -10
  45. package/dist/designTokens/tokens/amelipro/apColors2026.d.ts +1 -2
  46. package/dist/designTokens/tokens/amelipro/apContextual.d.ts +44 -0
  47. package/dist/designTokens/tokens/amelipro/apSemantic.d.ts +1 -1
  48. package/dist/designTokens/tokens/baseColors.d.ts +127 -0
  49. package/dist/designTokens/tokens/baseContextualTokens.d.ts +50 -0
  50. package/dist/designTokens/tokens/cnam/cnamColors.d.ts +10 -10
  51. package/dist/designTokens/tokens/cnam/cnamSemantic.d.ts +1 -1
  52. package/dist/designTokens/tokens/pa/paColors.d.ts +1 -166
  53. package/dist/designTokens/tokens/pa/paSemantic.d.ts +1 -1
  54. package/dist/designTokens/utils/buildColorClassMap.d.ts +12 -0
  55. package/dist/designTokens/utils/createFlattenTheme.d.ts +1 -3
  56. package/dist/designTokens/utils/index.d.ts +2 -2
  57. package/dist/main-ByDPHpae.cjs +1067 -0
  58. package/dist/main-Cpx8Co6H.js +38869 -0
  59. package/dist/synapse.css +1 -1
  60. package/dist/utils/functions/classToHex.d.ts +1 -1
  61. package/dist/utils/functions/createHexResolver.d.ts +16 -0
  62. package/dist/vuetifyConfig.js +113 -152
  63. package/dist/vuetifyConfig.umd.cjs +1 -1
  64. package/package.json +29 -18
  65. package/src/assets/amelipro/apTokens2026.scss +5 -5
  66. package/src/assets/overrides/_breakpoints.scss +25 -0
  67. package/src/assets/overrides/_btns.scss +0 -2
  68. package/src/assets/overrides/_forms.scss +1 -3
  69. package/src/assets/overrides/_icons.scss +7 -11
  70. package/src/assets/overrides/_otp.scss +41 -0
  71. package/src/assets/overrides/_tables.scss +11 -20
  72. package/src/assets/overrides/_tooltips.scss +17 -7
  73. package/src/assets/overrides/_typography.scss +35 -37
  74. package/src/assets/overrides/_utilities.scss +43 -47
  75. package/src/assets/themes.scss +1 -0
  76. package/src/components/Amelipro/AmeliproAccordion/AmeliproAccordionTemplate/AmeliproAccordionTemplate.vue +20 -20
  77. package/src/components/Amelipro/AmeliproAccordionFrieze/AmeliproAccordionFrieze.vue +12 -14
  78. package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.vue +4 -6
  79. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/AmeliproAccordionResultTemplate.vue +5 -5
  80. package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.vue +4 -6
  81. package/src/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.vue +4 -6
  82. package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.vue +4 -6
  83. package/src/components/Amelipro/AmeliproBreadcrumb/AmeliproBreadcrumb.vue +1 -3
  84. package/src/components/Amelipro/AmeliproBtn/AmeliproBtn.vue +4 -6
  85. package/src/components/Amelipro/AmeliproCallback/AmeliproCallback.vue +2 -2
  86. package/src/components/Amelipro/AmeliproCard/AmeliproCard.vue +31 -31
  87. package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.vue +5 -7
  88. package/src/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.vue +13 -15
  89. package/src/components/Amelipro/AmeliproCheckboxGroup/AmeliproCheckboxGroup.vue +23 -23
  90. package/src/components/Amelipro/AmeliproChips/AmeliproChips.vue +1 -3
  91. package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.vue +17 -12
  92. package/src/components/Amelipro/AmeliproClickableTile/tests/__snapshots__/AmeliproClickableTile.spec.ts.snap +2 -2
  93. package/src/components/Amelipro/AmeliproCopyBtn/AmeliproCopyBtn.vue +4 -6
  94. package/src/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.vue +13 -13
  95. package/src/components/Amelipro/AmeliproDentalChart/AmeliproDentalChart.vue +4 -2
  96. package/src/components/Amelipro/AmeliproDentalChart/AmeliproTooth/AmeliproTooth.vue +4 -4
  97. package/src/components/Amelipro/AmeliproDialog/AmeliproDialog.vue +5 -7
  98. package/src/components/Amelipro/AmeliproDisclosure/AmeliproDisclosure.vue +1 -3
  99. package/src/components/Amelipro/AmeliproErrorTemplate/AmeliproErrorTemplate.vue +2 -4
  100. package/src/components/Amelipro/AmeliproFilePreview/AmeliproFilePreview.vue +4 -6
  101. package/src/components/Amelipro/AmeliproFilters/AmeliproFilters.vue +13 -13
  102. package/src/components/Amelipro/AmeliproFirstLogin/AmeliproFirstLogin.vue +3 -5
  103. package/src/components/Amelipro/AmeliproFooter/AmeliproFooter.vue +1 -3
  104. package/src/components/Amelipro/AmeliproHeader/AmeliproHeader.vue +2 -4
  105. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBar.vue +1 -3
  106. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/AmeliproHeaderBrandSection.vue +20 -16
  107. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/__tests__/__snapshots__/AmeliproHeaderBrandSection.spec.ts.snap +1 -1
  108. package/src/components/Amelipro/AmeliproIconBtn/AmeliproIconBtn.vue +2 -4
  109. package/src/components/Amelipro/AmeliproIllustratedDataTile/AmeliproIllustratedDataTile.vue +5 -7
  110. package/src/components/Amelipro/AmeliproIllustratedRadioGroup/AmeliproIllustratedRadioGroup.vue +6 -8
  111. package/src/components/Amelipro/AmeliproMailTile/AmeliproMailTile.vue +14 -14
  112. package/src/components/Amelipro/AmeliproMenu/AmeliproMenu.vue +11 -13
  113. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/AmeliproDropdownMenu.vue +2 -4
  114. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproMessagingLayout.vue +8 -8
  115. package/src/components/Amelipro/AmeliproMultipleFoldingCard/AmeliproMultipleFoldingCard.vue +40 -40
  116. package/src/components/Amelipro/AmeliproNumberedCard/AmeliproNumberedCard.vue +27 -27
  117. package/src/components/Amelipro/AmeliproOnboarding/AmeliproOnboarding.vue +3 -5
  118. package/src/components/Amelipro/AmeliproPageLayout/AmeliproPageLayout.vue +2 -4
  119. package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.vue +2 -4
  120. package/src/components/Amelipro/AmeliproPagination/AmeliproPaginationBtn/AmeliproPaginationBtn.vue +3 -5
  121. package/src/components/Amelipro/AmeliproPatientBanner/AmeliproPatientBanner.vue +1 -3
  122. package/src/components/Amelipro/AmeliproPatientLogged/AmeliproPatientLogged.vue +2 -4
  123. package/src/components/Amelipro/AmeliproPatientLogin/AmeliproPatientLogin.vue +4 -4
  124. package/src/components/Amelipro/AmeliproPatientLogin/AmeliproPatientLoginForm/AmeliproPatientLoginForm.vue +1 -3
  125. package/src/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressCityRow/AmeliproPostalAddressCityRow.vue +3 -5
  126. package/src/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.vue +3 -5
  127. package/src/components/Amelipro/AmeliproRadioGroup/AmeliproRadioGroup.vue +23 -23
  128. package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.vue +4 -6
  129. package/src/components/Amelipro/AmeliproSelect/AmeliproSelect.vue +12 -22
  130. package/src/components/Amelipro/AmeliproStateTile/AmeliproStateTile.vue +10 -12
  131. package/src/components/Amelipro/AmeliproStepper/AmeliproStepper.vue +17 -17
  132. package/src/components/Amelipro/AmeliproTable/AmeliproTable.vue +8 -10
  133. package/src/components/Amelipro/AmeliproTabs/AmeliproTabBtn/AmeliproTabBtn.vue +6 -8
  134. package/src/components/Amelipro/AmeliproTabs/AmeliproTabs.vue +4 -4
  135. package/src/components/Amelipro/AmeliproTextArea/AmeliproTextArea.vue +4 -6
  136. package/src/components/Amelipro/AmeliproTextField/AmeliproTextField.vue +7 -9
  137. package/src/components/Amelipro/AmeliproTileBtn/AmeliproTileBtn.vue +3 -5
  138. package/src/components/Amelipro/AmeliproTooltips/AmeliproTooltips.vue +0 -2
  139. package/src/components/Amelipro/AmeliproUpload/AmeliproUpload.vue +6 -6
  140. package/src/components/Amelipro/ServiceMenu/ServiceMenu.vue +2 -2
  141. package/src/components/Amelipro/StructureMenu/StructureBtn/StructureBtn.vue +4 -4
  142. package/src/components/Amelipro/StructureMenu/StructureItem/StructureItem.vue +4 -6
  143. package/src/components/Amelipro/StructureMenu/StructureMenu.vue +2 -2
  144. package/src/components/Amelipro/StructureMenu/StructureTabs/StructureTabs.vue +2 -2
  145. package/src/components/Amelipro/UserMenu/UserMenu.vue +1 -3
  146. package/src/components/BackBtn/tests/BackBtn.visual.cy.ts +43 -0
  147. package/src/components/BackBtn/tests/__snapshots__/back-btn-custom-bg.snap.png +0 -0
  148. package/src/components/BackBtn/tests/__snapshots__/back-btn-dark-mode.snap.png +0 -0
  149. package/src/components/BackBtn/tests/__snapshots__/back-btn-default.snap.png +0 -0
  150. package/src/components/BackBtn/tests/__snapshots__/back-btn-no-icon.snap.png +0 -0
  151. package/src/components/Captcha/Captcha.vue +1 -3
  152. package/src/components/ChipList/ChipList.vue +14 -16
  153. package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +0 -2
  154. package/src/components/CopyBtn/CopyBtn.vue +1 -3
  155. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.vue +17 -17
  156. package/src/components/Customs/Selects/SelectBtnField/tests/SelectBtnField.spec.ts +31 -0
  157. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +66 -0
  158. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +7 -3
  159. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +18 -0
  160. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +66 -0
  161. package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.vue +4 -6
  162. package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +1 -39
  163. package/src/components/Customs/Selects/SySelect/SySelect.vue +263 -63
  164. package/src/components/Customs/Selects/SySelect/accessibilite/Accessibility.mdx +199 -269
  165. package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +35 -0
  166. package/src/components/Customs/SyCheckbox/SyCheckbox.mdx +5 -0
  167. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +29 -0
  168. package/src/components/Customs/SyCheckbox/accessibilite/Accessibility.mdx +18 -3
  169. package/src/components/Customs/SyPagination/SyPagination.vue +0 -2
  170. package/src/components/Customs/SyTabs/SyTabs.mdx +0 -58
  171. package/src/components/Customs/SyTabs/SyTabs.stories.ts +32 -33
  172. package/src/components/Customs/SyTabs/SyTabs.vue +87 -67
  173. package/src/components/Customs/SyTabs/accessibilite/Accessibility.mdx +83 -23
  174. package/src/components/Customs/SyTabs/tests/SyTabs.a11y.spec.ts +88 -0
  175. package/src/components/Customs/SyTabs/tests/SyTabs.spec.ts +46 -1
  176. package/src/components/Customs/SyTextField/SyTextField.stories.ts +21 -41
  177. package/src/components/Customs/SyTextField/SyTextField.vue +4 -6
  178. package/src/components/DatePicker/CalendarMode/DatePicker.vue +12 -14
  179. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +20 -16
  180. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +23 -0
  181. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +8 -10
  182. package/src/components/DatePicker/composables/tests/useDatePickerState.spec.ts +53 -0
  183. package/src/components/DatePicker/composables/useDatePickerState.ts +24 -0
  184. package/src/components/DatePicker/composables/useDateTextField.ts +0 -1
  185. package/src/components/DatePicker/composables/useMonthButtonCustomization.ts +9 -8
  186. package/src/components/DatePicker/playground/DatePickerHolidayRule.vue +1 -1
  187. package/src/components/DialogBox/DialogBox.vue +3 -5
  188. package/src/components/DialogBox/tests/DialogBox.visual.cy.ts +76 -0
  189. package/src/components/DialogBox/tests/__snapshots__/dialog-box-custom-texts.snap.png +0 -0
  190. package/src/components/DialogBox/tests/__snapshots__/dialog-box-default.snap.png +0 -0
  191. package/src/components/DialogBox/tests/__snapshots__/dialog-box-no-actions.snap.png +0 -0
  192. package/src/components/FileList/FileList.vue +9 -2
  193. package/src/components/FileList/UploadItem/UploadItem.vue +11 -13
  194. package/src/components/FileList/tests/FileList.spec.ts +47 -0
  195. package/src/components/FileUpload/FileUpload.vue +3 -5
  196. package/src/components/FileUpload/FileUploadContent.vue +3 -5
  197. package/src/components/FilterInline/FilterInline.vue +1 -3
  198. package/src/components/FilterSideBar/FilterSideBar.mdx +44 -1
  199. package/src/components/FilterSideBar/FilterSideBar.stories.ts +105 -1
  200. package/src/components/FilterSideBar/FilterSideBar.vue +7 -0
  201. package/src/components/FilterSideBar/tests/FilterSideBar.a11y.spec.ts +54 -1
  202. package/src/components/FilterSideBar/tests/FilterSideBar.spec.ts +42 -0
  203. package/src/components/FooterBar/FooterBar.vue +9 -13
  204. package/src/components/FranceConnectBtn/FranceConnectBtn.vue +1 -1
  205. package/src/components/HeaderBar/HeaderBar.vue +2 -3
  206. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.vue +2 -3
  207. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +2 -3
  208. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.vue +0 -1
  209. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +8 -9
  210. package/src/components/HeaderBar/HeaderBurgerMenu/menu.scss +0 -8
  211. package/src/components/HeaderBar/HeaderBurgerMenu/tests/HeaderBurgerMenu.visual.cy.ts +196 -0
  212. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated-submenu-open.snap.png +0 -0
  213. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated.snap.png +0 -0
  214. package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +0 -1
  215. package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +6 -7
  216. package/src/components/HeaderBar/tests/HeaderBar.visual.cy.ts +81 -0
  217. package/src/components/HeaderBar/tests/__snapshots__/header-bar-custom-width.snap.png +0 -0
  218. package/src/components/HeaderBar/tests/__snapshots__/header-bar-default.snap.png +0 -0
  219. package/src/components/HeaderBar/tests/__snapshots__/header-bar-no-sticky.snap.png +0 -0
  220. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-prepend.snap.png +0 -0
  221. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-side.snap.png +0 -0
  222. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-subtitle.snap.png +0 -0
  223. package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +12 -3
  224. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +15 -8
  225. package/src/components/HeaderToolbar/HeaderToolbar.vue +6 -7
  226. package/src/components/LangBtn/LangBtn.vue +2 -4
  227. package/src/components/Logo/tests/Logo.visual.cy.ts +57 -0
  228. package/src/components/Logo/tests/__snapshots__/logo-avatar.snap.png +0 -0
  229. package/src/components/Logo/tests/__snapshots__/logo-dark.snap.png +0 -0
  230. package/src/components/Logo/tests/__snapshots__/logo-default.snap.png +0 -0
  231. package/src/components/Logo/tests/__snapshots__/logo-no-organism.snap.png +0 -0
  232. package/src/components/Logo/tests/__snapshots__/logo-no-signature.snap.png +0 -0
  233. package/src/components/Logo/tests/__snapshots__/logo-risque-pro.snap.png +0 -0
  234. package/src/components/LogoBrandSection/LogoBrandSection.vue +2 -2
  235. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +1 -1
  236. package/src/components/NirField/NirField.stories.ts +2 -2
  237. package/src/components/NirField/NirField.vue +3 -5
  238. package/src/components/NirField/accessibilite/Accessibility.mdx +100 -5
  239. package/src/components/NirField/tests/NirField.spec.ts +118 -0
  240. package/src/components/NirField/tests/useNirValidation.spec.ts +449 -0
  241. package/src/components/NirField/useNirValidation.ts +38 -32
  242. package/src/components/NotificationBar/Notification/Notification.vue +5 -7
  243. package/src/components/NotificationBar/NotificationBar.vue +1 -3
  244. package/src/components/PaginatedTable/PaginatedTable.vue +2 -3
  245. package/src/components/PaginatedTable/Pagination.vue +3 -5
  246. package/src/components/PasswordField/PasswordField.vue +8 -10
  247. package/src/components/PhoneField/PhoneField.vue +3 -3
  248. package/src/components/RangeField/RangeSlider/RangeSlider.vue +0 -2
  249. package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +1 -1
  250. package/src/components/RangeField/tests/RangeField.visual.cy.ts +65 -0
  251. package/src/components/RangeField/tests/__snapshots__/range-field-custom-bg.snap.png +0 -0
  252. package/src/components/RangeField/tests/__snapshots__/range-field-custom-range.snap.png +0 -0
  253. package/src/components/RangeField/tests/__snapshots__/range-field-default.snap.png +0 -0
  254. package/src/components/RangeField/tests/__snapshots__/range-field-step.snap.png +0 -0
  255. package/src/components/RangeField/tests/__snapshots__/range-field-with-label.snap.png +0 -0
  256. package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +6 -8
  257. package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +3 -5
  258. package/src/components/SearchListField/SearchListField.vue +0 -2
  259. package/src/components/SkipLink/SkipLink.vue +2 -4
  260. package/src/components/SocialMediaLinks/SocialMediaLinks.vue +6 -6
  261. package/src/components/SubHeader/SubHeader.vue +1 -1
  262. package/src/components/SyAlert/SyAlert.vue +7 -9
  263. package/src/components/SyAlert/tests/SyAlert.visual.cy.ts +46 -0
  264. package/src/components/SyAlert/tests/__snapshots__/sy-alert-closable.snap.png +0 -0
  265. package/src/components/SyAlert/tests/__snapshots__/sy-alert-error.snap.png +0 -0
  266. package/src/components/SyAlert/tests/__snapshots__/sy-alert-info.snap.png +0 -0
  267. package/src/components/SyAlert/tests/__snapshots__/sy-alert-success.snap.png +0 -0
  268. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-outlined.snap.png +0 -0
  269. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-tonal.snap.png +0 -0
  270. package/src/components/SyAlert/tests/__snapshots__/sy-alert-warning.snap.png +0 -0
  271. package/src/components/SyBtnMenu/SyBtnMenu.vue +2 -4
  272. package/src/components/TableToolbar/TableToolbar.vue +6 -8
  273. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +166 -0
  274. package/src/components/Tables/SyServerTable/SyServerTable.vue +9 -7
  275. package/src/components/Tables/SyServerTable/tests/SyServerTable.a11y.spec.ts +23 -0
  276. package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +268 -0
  277. package/src/components/Tables/SyTable/SyTable.stories.ts +104 -0
  278. package/src/components/Tables/SyTable/SyTable.vue +9 -7
  279. package/src/components/Tables/SyTable/tests/SyTable.a11y.spec.ts +22 -0
  280. package/src/components/Tables/SyTable/tests/SyTable.spec.ts +274 -0
  281. package/src/components/Tables/common/SyTableFilter.vue +27 -2
  282. package/src/components/Tables/common/SyTablePagination.vue +142 -19
  283. package/src/components/Tables/common/TableHeader.vue +40 -3
  284. package/src/components/Tables/common/filters/SelectFilter.vue +1 -1
  285. package/src/components/Tables/common/locales.ts +3 -0
  286. package/src/components/Tables/common/tableStyles.scss +16 -19
  287. package/src/components/Tables/common/tests/SyTablePagination.spec.ts +18 -0
  288. package/src/components/Tables/common/tests/TableHeader.spec.ts +39 -0
  289. package/src/components/Tables/common/types.ts +2 -0
  290. package/src/components/Tables/common/useTableHeaders.ts +49 -27
  291. package/src/components/UploadWorkflow/UploadWorkflow.vue +1 -0
  292. package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +23 -0
  293. package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +66 -0
  294. package/src/components/UploadWorkflow/useFileList.ts +3 -0
  295. package/src/components/UserMenuBtn/UserMenuBtn.vue +1 -3
  296. package/src/composables/unifyValidation/documentationValidationProps.ts +235 -0
  297. package/src/composables/validation/useValidation.ts +17 -1
  298. package/src/composantsVuetify/VBreadcrumbs/VBreadcrumbs.mdx +28 -0
  299. package/src/composantsVuetify/VBreadcrumbs/v-breadcrumbs.stories.ts +108 -0
  300. package/src/composantsVuetify/VOtpInput/VOtpInput.mdx +39 -0
  301. package/src/composantsVuetify/VOtpInput/v-otp-input.stories.ts +56 -0
  302. package/src/composantsVuetify/VSkeletonLoader/VSkeletonLoader.mdx +42 -0
  303. package/src/composantsVuetify/VSkeletonLoader/v-skeleton-loader.stories.ts +77 -0
  304. package/src/composantsVuetify/VSwitch/VSwitch.mdx +47 -0
  305. package/src/composantsVuetify/VSwitch/v-switch.stories.ts +166 -0
  306. package/src/designTokens/tests/buildColorClassMap.spec.ts +31 -0
  307. package/src/designTokens/tests/generateScssTokens.spec.ts +12 -0
  308. package/src/designTokens/tests/themeUtils.spec.ts +53 -0
  309. package/src/designTokens/tokens/amelipro/apColors.ts +8 -130
  310. package/src/designTokens/tokens/amelipro/apColors2026.ts +3 -15
  311. package/src/designTokens/tokens/amelipro/apContextual.ts +55 -47
  312. package/src/designTokens/tokens/amelipro/apLightTheme.ts +1 -1
  313. package/src/designTokens/tokens/amelipro/apSemantic.ts +1 -1
  314. package/src/designTokens/tokens/baseColors.ts +129 -0
  315. package/src/designTokens/tokens/baseContextualTokens.ts +52 -0
  316. package/src/designTokens/tokens/cnam/cnamColors.ts +3 -125
  317. package/src/designTokens/tokens/cnam/cnamContextual.ts +4 -48
  318. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +1 -1
  319. package/src/designTokens/tokens/cnam/cnamSemantic.ts +1 -1
  320. package/src/designTokens/tokens/pa/paColors.ts +2 -166
  321. package/src/designTokens/tokens/pa/paContextual.ts +3 -48
  322. package/src/designTokens/tokens/pa/paLightTheme.ts +1 -1
  323. package/src/designTokens/tokens/pa/paSemantic.ts +2 -2
  324. package/src/designTokens/utils/buildColorClassMap.ts +34 -0
  325. package/src/designTokens/utils/convertSemanticsToken.ts +8 -11
  326. package/src/designTokens/utils/createFlattenTheme.ts +15 -7
  327. package/src/designTokens/utils/index.ts +2 -2
  328. package/src/stories/Accessibilite/AuditDesignSystem.mdx +0 -11
  329. package/src/stories/Accessibilite/DesignSystem/Avancement.mdx +433 -0
  330. package/src/stories/Accessibilite/DesignSystem/a11y-status.json +692 -0
  331. package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +8 -1
  332. package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +51 -10
  333. package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +16 -9
  334. package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +48 -58
  335. package/src/stories/Components/Components.stories.ts +40 -1
  336. package/src/stories/Demarrer/EnrichirLeDesignSystem.mdx +4 -9
  337. package/src/stories/Demarrer/EnrichirLeDesignSystem.stories.ts +28 -0
  338. package/src/stories/Demarrer/Releases.stories.ts +48 -5
  339. package/src/stories/DesignTokens/ColorDisplay.vue +6 -5
  340. package/src/stories/DesignTokens/ColorIntegrationExample.vue +2 -4
  341. package/src/stories/DesignTokens/colors.stories.ts +5 -6
  342. package/src/stories/GuideDuDev/CreateVuetifyInstance.mdx +95 -0
  343. package/src/stories/GuideDuDev/Theme.mdx +36 -26
  344. package/src/stories/GuideDuDev/moduleDeNotification.mdx +3 -2
  345. package/src/stories/styles/accessibility-guide.css +3 -3
  346. package/src/utils/functions/classToHex.ts +6 -34
  347. package/src/utils/functions/createHexResolver.ts +45 -0
  348. package/src/utils/functions/tests/classToHex.spec.ts +36 -0
  349. package/src/utils/functions/tests/convertToHex.spec.ts +31 -0
  350. package/src/utils/functions/tests/createHexResolver.spec.ts +66 -0
  351. package/src/utils/functions/tests/isCssColor.spec.ts +48 -0
  352. package/dist/apLightTheme-CFSRrjv2.cjs +0 -1
  353. package/dist/designTokens/utils/convertGaps.d.ts +0 -5
  354. package/dist/main-BtTqyn4z.js +0 -38648
  355. package/dist/main-C1e3eoxd.cjs +0 -1067
  356. package/src/assets/apTokens.scss +0 -343
  357. package/src/assets/overrides/_container.scss +0 -36
  358. package/src/assets/tokens.scss +0 -388
  359. package/src/designTokens/apColors.md +0 -66
  360. package/src/designTokens/cnamColors.md +0 -193
  361. package/src/designTokens/paColors.md +0 -66
  362. package/src/designTokens/tokens/json/contextual-tokens.json +0 -156
  363. package/src/designTokens/tokens/json/primitives.json +0 -209
  364. package/src/designTokens/tokens/json/semantic.json +0 -120
  365. package/src/designTokens/utils/convertGaps.ts +0 -11
  366. package/src/stories/Accessibilite/Avancement/Avancement.mdx +0 -533
  367. 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 type { locales } from './locales'
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 || 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 || 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 = async (onBlur = false) => {
234
- // Éviter les validations redondantes
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
- isValidating.value = true
237
+ if (validationPromise) {
238
+ return validationPromise
239
+ }
241
240
 
242
- await numberValidation.validate()
241
+ validationPromise = (async () => {
242
+ isValidating.value = true
243
243
 
244
- if (displayKey.value) {
245
- await keyValidation.validate()
246
- }
244
+ await numberValidation.validate()
247
245
 
248
- if (onBlur || shouldValidateOnBlur.value) {
249
- await nextTick()
250
- if (numberValidation.hasError.value) {
251
- numberField.value?.$el?.querySelector?.('input')?.focus()
246
+ if (displayKey.value) {
247
+ await keyValidation.validate()
252
248
  }
253
- else if (keyValidation.hasError.value) {
254
- keyField.value?.$el?.querySelector?.('input')?.focus()
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
- isValidating.value = false
260
- return !numberValidation.hasError.value && !keyValidation.hasError.value
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: tokens.$gap-2 tokens.$gap-4;
118
- margin-block: tokens.$gap-1;
119
- gap: tokens.$gap-2 tokens.$gap-4;
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 <= tokens.$container-mobile-max-width) {
181
+ @media screen and (width <= 600px) {
184
182
  flex-direction: column;
185
183
  align-items: flex-start;
186
- padding: tokens.$gap-4;
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: tokens.$gap-0;
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: tokens.$primary-base;
280
+ color: rgb(var(--v-theme-primary));
282
281
  }
283
282
  }
284
283
 
285
284
  &--focused {
286
- border-color: tokens.$primary-base;
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 tokens.$colors-interactive;
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: tokens.$colors-icon-base;
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: #000;
89
+ color: rgb(var(--v-theme-textBase));
92
90
  }
93
91
  </style>