@cnamts/synapse 1.0.22 → 1.0.24

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 (426) hide show
  1. package/dist/AutocompleteFilter-BWLR3U7W.js +114 -0
  2. package/dist/AutocompleteFilter-D9jzRzAL.cjs +1 -0
  3. package/dist/{DateFilter-B5n-ZkLi.js → DateFilter-BpwFexzi.js} +1 -1
  4. package/dist/DateFilter-DTUl8hb1.cjs +1 -0
  5. package/dist/{NumberFilter-CtiZ9uj8.js → NumberFilter-Bz_NTdX9.js} +3 -3
  6. package/dist/NumberFilter-MAEojdk0.cjs +1 -0
  7. package/dist/PeriodFilter-CC4WgIhl.cjs +1 -0
  8. package/dist/{PeriodFilter-DzqiMb-b.js → PeriodFilter-DX_wy9g-.js} +1 -1
  9. package/dist/SelectFilter-BR3fvl-a.cjs +1 -0
  10. package/dist/SelectFilter-xqiPtPgX.js +135 -0
  11. package/dist/{TextFilter-BOFRNfcX.js → TextFilter-BBl3JFqK.js} +7 -7
  12. package/dist/TextFilter-CCfYFl5F.cjs +1 -0
  13. package/dist/apLightTheme-CFSRrjv2.cjs +1 -0
  14. package/dist/apLightTheme-D1P4jcD0.js +1231 -0
  15. package/dist/components/Accordion/Accordion.d.ts +13 -2
  16. package/dist/components/Accordion/composables/useAccordionState.d.ts +2 -1
  17. package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +7022 -9616
  18. package/dist/components/Amelipro/AmeliproCarousel/AmeliproCarousel.d.ts +2 -2
  19. package/dist/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.d.ts +1 -1
  20. package/dist/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.d.ts +1 -1
  21. package/dist/components/Amelipro/AmeliproIconBtn/AmeliproIconBtn.d.ts +2 -2
  22. package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressCityRow/AmeliproPostalAddressCityRow.d.ts +40 -40
  23. package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.d.ts +61 -61
  24. package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +7168 -9762
  25. package/dist/components/Amelipro/AmeliproStepper/AmeliproStepper.d.ts +2 -2
  26. package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +7506 -10100
  27. package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +22 -22
  28. package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +42 -42
  29. package/dist/components/Amelipro/StructureMenu/StructureTabs/StructureTabs.d.ts +2 -2
  30. package/dist/components/CookiesSelection/CookiesInformation/CookiesInformation.d.ts +20 -498
  31. package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +130 -147
  32. package/dist/components/Customs/Selects/SyAutocomplete/locales.d.ts +5 -0
  33. package/dist/components/Customs/Selects/SyInputSelect/SyInputSelect.d.ts +6 -6
  34. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +13 -17
  35. package/dist/components/Customs/Selects/SySelect/locales.d.ts +1 -0
  36. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +9 -9
  37. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +29 -507
  38. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +29 -507
  39. package/dist/components/Customs/SyTextField/SyTextField.d.ts +64 -81
  40. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +640 -780
  41. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +322 -407
  42. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +114 -156
  43. package/dist/components/DatePicker/composables/index.d.ts +1 -0
  44. package/dist/components/DatePicker/composables/useDatePickerFocusTrap.d.ts +11 -0
  45. package/dist/components/DatePicker/composables/useDateTextField.d.ts +4 -4
  46. package/dist/components/DatePicker/composables/useDateValidation.d.ts +3 -3
  47. package/dist/components/DatePicker/composables/useInputBlurHandler.d.ts +2 -2
  48. package/dist/components/DatePicker/composables/useManualDateValidation.d.ts +2 -2
  49. package/dist/components/ErrorPage/ErrorPage.d.ts +3 -1
  50. package/dist/components/FileList/UploadItem/UploadItem.d.ts +6 -0
  51. package/dist/components/FileList/UploadItem/locales.d.ts +1 -4
  52. package/dist/components/FileUpload/FileUploadContent.d.ts +2 -0
  53. package/dist/components/FileUpload/validateFiles.d.ts +2 -1
  54. package/dist/components/HeaderBar/HeaderBar.d.ts +2 -1
  55. package/dist/components/HeaderBar/HeaderLogo/HeaderLogo.d.ts +2 -1
  56. package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +6 -5
  57. package/dist/components/HeaderToolbar/HeaderToolbar.d.ts +20 -28
  58. package/dist/components/LunarCalendar/useLunarCalendarValidation.d.ts +3 -3
  59. package/dist/components/MonthPicker/MonthPicker.d.ts +1903 -0
  60. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1863 -0
  61. package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +21 -0
  62. package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.d.ts +21 -0
  63. package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.d.ts +12 -0
  64. package/dist/components/MonthPicker/MonthPickerVisual/MonthSelector.d.ts +11 -0
  65. package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.d.ts +6 -0
  66. package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.d.ts +14 -0
  67. package/dist/components/MonthPicker/MonthPickerVisual/YearSelector.d.ts +14 -0
  68. package/dist/components/MonthPicker/MonthPickerVisual/useMonthGrid.d.ts +9 -0
  69. package/dist/components/MonthPicker/MonthPickerVisual/useYearGrid.d.ts +8 -0
  70. package/dist/components/MonthPicker/MonthPickerVisual/utils.d.ts +8 -0
  71. package/dist/components/MonthPicker/locales.d.ts +12 -0
  72. package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +25 -0
  73. package/dist/components/NirField/NirField.d.ts +209 -271
  74. package/dist/components/NirField/locales.d.ts +10 -10
  75. package/dist/components/NirField/useNirValidation.d.ts +64 -0
  76. package/dist/components/NotificationBar/Notification/Notification.d.ts +3 -0
  77. package/dist/components/PasswordField/PasswordField.d.ts +9 -10
  78. package/dist/components/PeriodField/PeriodField.d.ts +1379 -1659
  79. package/dist/components/PhoneField/PhoneField.d.ts +90 -125
  80. package/dist/components/RangeField/RangeSlider/RangeSlider.d.ts +12 -12
  81. package/dist/components/SyBtnMenu/SyBtnMenu.d.ts +1 -1
  82. package/dist/components/SyHeading/SyHeading.a11y.test.d.ts +1 -0
  83. package/dist/components/SyHeading/SyHeading.d.ts +4 -2
  84. package/dist/components/SyHeading/SyHeading.test.d.ts +1 -0
  85. package/dist/components/SyTextArea/SyTextArea.d.ts +35 -15
  86. package/dist/components/SyTextArea/useDefaultValidationRules.d.ts +11 -0
  87. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +11 -8
  88. package/dist/components/Tables/SyTable/SyTable.d.ts +11 -8
  89. package/dist/components/Tables/common/SyTableFilter.d.ts +2 -3
  90. package/dist/components/Tables/common/SyTablePagination.d.ts +21 -23
  91. package/dist/components/Tables/common/filters/AutocompleteFilter.d.ts +120 -0
  92. package/dist/components/Tables/common/filters/locales.d.ts +0 -1
  93. package/dist/components/Tables/common/types.d.ts +19 -3
  94. package/dist/components/Tables/common/useClickableTableRow.d.ts +17 -0
  95. package/dist/components/Tables/common/usePagination.d.ts +3 -1
  96. package/dist/components/Tables/common/usePinnedColumns.d.ts +31 -0
  97. package/dist/components/Tables/common/useTableHeaders.d.ts +2 -0
  98. package/dist/components/Tables/common/useTableRowCheckboxAccessibility.d.ts +5 -0
  99. package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +6 -6
  100. package/dist/components/index.d.ts +1 -0
  101. package/dist/composables/date/useDatePickerAccessibility.d.ts +1 -1
  102. package/dist/composables/rules/useFieldValidation.d.ts +4 -4
  103. package/dist/composables/unifyValidation/useCustomValidation.d.ts +8 -0
  104. package/dist/composables/unifyValidation/useValidation.d.ts +102 -0
  105. package/dist/composables/unifyValidation/useVuetifyValidation.d.ts +18 -0
  106. package/dist/composables/useFormFieldErrorHandling.d.ts +2 -2
  107. package/dist/composables/validation/useFormValidation.d.ts +11 -2
  108. package/dist/composables/validation/useValidation.d.ts +15 -9
  109. package/dist/design-system-v3.d.ts +2 -0
  110. package/dist/design-system-v3.js +196 -194
  111. package/dist/design-system-v3.umd.cjs +1 -1066
  112. package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +5 -0
  113. package/dist/{main-CEl4J8_T.js → main-BtTqyn4z.js} +16983 -15576
  114. package/dist/main-C1e3eoxd.cjs +1067 -0
  115. package/dist/synapse.css +1 -0
  116. package/dist/tooth-11-D3sLWv2n.cjs +1 -0
  117. package/dist/tooth-12-CXrLuH03.cjs +1 -0
  118. package/dist/tooth-13-BSfo5fpT.cjs +1 -0
  119. package/dist/tooth-14-DMzulx0h.cjs +1 -0
  120. package/dist/tooth-15-BKRFVi-9.cjs +1 -0
  121. package/dist/tooth-16-CpuxAbuM.cjs +1 -0
  122. package/dist/tooth-17-BPoahUdg.cjs +1 -0
  123. package/dist/tooth-18-DhHJz8sy.cjs +1 -0
  124. package/dist/tooth-21-Dgd5hn_X.cjs +1 -0
  125. package/dist/tooth-22-C2Tn19sB.cjs +1 -0
  126. package/dist/tooth-23-C9uaaSGb.cjs +1 -0
  127. package/dist/tooth-24-BrK9UGpf.cjs +1 -0
  128. package/dist/tooth-25-CE_EfGNp.cjs +1 -0
  129. package/dist/tooth-26-Ctv4i9Fy.cjs +1 -0
  130. package/dist/tooth-27-C5J7JkWM.cjs +1 -0
  131. package/dist/tooth-28-Z9oWqjo0.cjs +1 -0
  132. package/dist/tooth-31-BrYqmkTi.cjs +1 -0
  133. package/dist/tooth-32-BNNR0oCZ.cjs +1 -0
  134. package/dist/tooth-33-DuxvqO2J.cjs +1 -0
  135. package/dist/tooth-34-BCSCXMB6.cjs +1 -0
  136. package/dist/tooth-35-BLUXkX88.cjs +1 -0
  137. package/dist/tooth-36-IrKHYqlA.cjs +1 -0
  138. package/dist/tooth-37-BYqpdMwo.cjs +1 -0
  139. package/dist/tooth-38-B_eNXXdu.cjs +1 -0
  140. package/dist/tooth-41-Ddva4Ot8.cjs +1 -0
  141. package/dist/tooth-42-szcDqlM0.cjs +1 -0
  142. package/dist/tooth-43-B3ka6rQm.cjs +1 -0
  143. package/dist/tooth-44-CazyQucj.cjs +1 -0
  144. package/dist/tooth-45-B4HQtc8n.cjs +1 -0
  145. package/dist/tooth-46-BPM40gbG.cjs +1 -0
  146. package/dist/tooth-47-Dvr20dlh.cjs +1 -0
  147. package/dist/tooth-48-Bd8ljGsF.cjs +1 -0
  148. package/dist/tooth-51-OBpwCOF3.cjs +1 -0
  149. package/dist/tooth-52-aKxyHcmq.cjs +1 -0
  150. package/dist/tooth-53-vCwJjTOc.cjs +1 -0
  151. package/dist/tooth-54-DsWu2iFy.cjs +1 -0
  152. package/dist/tooth-55-BxC1X2Dn.cjs +1 -0
  153. package/dist/tooth-61-BbLvxMQi.cjs +1 -0
  154. package/dist/tooth-62-CmTkWczP.cjs +1 -0
  155. package/dist/tooth-63-DI7l_2qI.cjs +1 -0
  156. package/dist/tooth-64-B21sOsJh.cjs +1 -0
  157. package/dist/tooth-65-D2ZC2VEr.cjs +1 -0
  158. package/dist/tooth-71-D473PPO5.cjs +1 -0
  159. package/dist/tooth-72-Drh1wnNu.cjs +1 -0
  160. package/dist/tooth-73-DzlwYI23.cjs +1 -0
  161. package/dist/tooth-74-8aGvcZPg.cjs +1 -0
  162. package/dist/tooth-75-BFK7At_r.cjs +1 -0
  163. package/dist/tooth-81-BZmR-I0M.cjs +1 -0
  164. package/dist/tooth-82-euVfUUZV.cjs +1 -0
  165. package/dist/tooth-83-KV010j64.cjs +1 -0
  166. package/dist/tooth-84-BBg1RjhZ.cjs +1 -0
  167. package/dist/tooth-85-Cr-kc1wM.cjs +1 -0
  168. package/dist/vuetifyConfig.js +561 -0
  169. package/dist/vuetifyConfig.umd.cjs +1 -0
  170. package/package.json +18 -6
  171. package/src/assets/apTokens.scss +2 -2
  172. package/src/assets/overrides/_btns.scss +2 -0
  173. package/src/assets/overrides/_forms.scss +9 -0
  174. package/src/assets/overrides/_icons.scss +41 -4
  175. package/src/assets/overrides/_tables.scss +19 -0
  176. package/src/assets/overrides/_typography.scss +0 -10
  177. package/src/components/Accordion/Accordion.mdx +23 -9
  178. package/src/components/Accordion/Accordion.stories.ts +153 -3
  179. package/src/components/Accordion/Accordion.vue +7 -6
  180. package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +40 -12
  181. package/src/components/Accordion/composables/useAccordionState.ts +3 -4
  182. package/src/components/Accordion/tests/accordion.spec.ts +131 -19
  183. package/src/components/Amelipro/AmeliproAutoCompleteField/__tests__/__snapshots__/AmeliproAutoCompleteField.spec.ts.snap +2 -2
  184. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/__tests__/__snapshots__/AmeliproHeaderBrandSection.spec.ts.snap +1 -1
  185. package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.mdx +3 -1
  186. package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.stories.ts +8 -0
  187. package/src/components/Amelipro/AmeliproTextArea/__tests__/__snapshots__/AmeliproTextArea.spec.ts.snap +2 -2
  188. package/src/components/BackBtn/accessibilite/Accessibility.mdx +62 -10
  189. package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +9 -3
  190. package/src/components/BackToTopBtn/accessibilite/Accessibility.mdx +86 -6
  191. package/src/components/Captcha/accessibilite/Accessibility.mdx +86 -8
  192. package/src/components/Captcha/tests/Captcha.spec.ts +0 -29
  193. package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +14 -122
  194. package/src/components/ChipList/ChipList.stories.ts +0 -15
  195. package/src/components/ChipList/ChipList.vue +5 -1
  196. package/src/components/ChipList/accessibilite/Accessibility.mdx +83 -10
  197. package/src/components/ChipList/tests/ChipList.a11y.spec.ts +41 -0
  198. package/src/components/Customs/Selects/SelectBtnField/accessibilite/Accessibility.mdx +124 -10
  199. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +379 -93
  200. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +162 -84
  201. package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibilite.stories.ts +40 -1
  202. package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibility.mdx +7 -1
  203. package/src/components/Customs/Selects/SyAutocomplete/locales.ts +5 -0
  204. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +96 -0
  205. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +377 -9
  206. package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +27 -13
  207. package/src/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.ts +9 -10
  208. package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.stories.ts +4 -4
  209. package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.vue +8 -9
  210. package/src/components/Customs/Selects/SyInputSelect/tests/SyInputSelect.spec.ts +10 -10
  211. package/src/components/Customs/Selects/SySelect/SySelect.vue +60 -14
  212. package/src/components/Customs/Selects/SySelect/locales.ts +1 -0
  213. package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +54 -0
  214. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +6 -9
  215. package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +10 -16
  216. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +16 -11
  217. package/src/components/Customs/SyCheckbox/accessibilite/Accessibility.mdx +35 -0
  218. package/src/components/Customs/SyCheckbox/tests/SyCheckbox.a11y.spec.ts +134 -2
  219. package/src/components/Customs/SyForm/SyForm.stories.ts +31 -5
  220. package/src/components/Customs/SyIcon/SyIcon.vue +1 -1
  221. package/src/components/Customs/SyIcon/tests/SyIcon.a11y.spec.ts +20 -0
  222. package/src/components/Customs/SyIconButton/SyIconButton.mdx +46 -0
  223. package/src/components/Customs/SyIconButton/SyIconButton.stories.ts +184 -0
  224. package/src/components/Customs/SyIconButton/SyIconButton.vue +38 -0
  225. package/src/components/Customs/SyIconButton/accessibilite/Accessibility.mdx +64 -0
  226. package/src/components/Customs/SyIconButton/tests/SyIconButton.a11y.spec.ts +87 -0
  227. package/src/components/Customs/SyIconButton/tests/SyIconButton.spec.ts +152 -0
  228. package/src/components/Customs/SyIconButton/tests/__snapshots__/SyIconButton.spec.ts.snap +61 -0
  229. package/src/components/Customs/SyPagination/SyPagination.vue +5 -5
  230. package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +4 -7
  231. package/src/components/Customs/SyTextField/SyTextField.mdx +1 -1
  232. package/src/components/Customs/SyTextField/SyTextField.stories.ts +29 -27
  233. package/src/components/Customs/SyTextField/SyTextField.vue +174 -159
  234. package/src/components/Customs/SyTextField/accessibilite/Accessibility.mdx +67 -9
  235. package/src/components/Customs/SyTextField/tests/SyTextField.a11y.spec.ts +47 -0
  236. package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +155 -10
  237. package/src/components/DataList/accessibilite/Accessibility.mdx +79 -11
  238. package/src/components/DataListGroup/accessibilite/Accessibility.mdx +80 -11
  239. package/src/components/DatePicker/CalendarMode/DatePicker.stories.ts +62 -58
  240. package/src/components/DatePicker/CalendarMode/DatePicker.vue +330 -223
  241. package/src/components/DatePicker/CalendarMode/accessibilite/Accessibility.mdx +82 -0
  242. package/src/components/DatePicker/CalendarMode/tests/DatePicker.a11y.spec.ts +141 -0
  243. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +2 -56
  244. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +195 -159
  245. package/src/components/DatePicker/ComplexDatePicker/accessibilite/Accessibility.mdx +76 -0
  246. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +10 -10
  247. package/src/components/DatePicker/DatePickerValidationExample/CalendarMode.stories.ts +8 -8
  248. package/src/components/DatePicker/DatePickerValidationExample/ComplexDatePicker.stories.ts +106 -8
  249. package/src/components/DatePicker/DatePickerValidationExample/DateTextInput.stories.ts +12 -11
  250. package/src/components/DatePicker/DatePickerValidationExample/MultiMode.stories.ts +12 -12
  251. package/src/components/DatePicker/DateTextInput/DateRange.stories.ts +0 -12
  252. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +63 -57
  253. package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +3 -0
  254. package/src/components/DatePicker/DateTextInput/accessibilite/Accessibility.mdx +66 -0
  255. package/src/components/DatePicker/DateTextInput/tests/DateTextInput.spec.ts +52 -1
  256. package/src/components/DatePicker/composables/index.ts +1 -0
  257. package/src/components/DatePicker/composables/tests/useCalendarKeyboardNavigation.spec.ts +109 -65
  258. package/src/components/DatePicker/composables/tests/useDatePickerFocusTrap.spec.ts +138 -0
  259. package/src/components/DatePicker/composables/tests/useDateValidation.spec.ts +74 -18
  260. package/src/components/DatePicker/composables/tests/useInputBlurHandler.spec.ts +39 -0
  261. package/src/components/DatePicker/composables/tests/useManualDateValidation.spec.ts +91 -0
  262. package/src/components/DatePicker/composables/useCalendarKeyboardNavigation.ts +442 -36
  263. package/src/components/DatePicker/composables/useDatePickerFocusTrap.ts +92 -0
  264. package/src/components/DatePicker/composables/useDateTextField.ts +7 -6
  265. package/src/components/DatePicker/composables/useDateValidation.ts +36 -35
  266. package/src/components/DatePicker/composables/useInputBlurHandler.ts +3 -3
  267. package/src/components/DatePicker/composables/useManualDateValidation.ts +6 -2
  268. package/src/components/DiacriticPicker/accessibilite/Accessibility.mdx +76 -8
  269. package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +25 -0
  270. package/src/components/ErrorPage/ErrorPage.stories.ts +113 -19
  271. package/src/components/ErrorPage/ErrorPage.vue +17 -2
  272. package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +17 -0
  273. package/src/components/ErrorPage/tests/ErrorPage.spec.ts +21 -1
  274. package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +0 -1
  275. package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +23 -0
  276. package/src/components/FileList/FileList.stories.ts +51 -1
  277. package/src/components/FileList/UploadItem/UploadItem.vue +13 -6
  278. package/src/components/FileList/UploadItem/locales.ts +3 -12
  279. package/src/components/FileList/accessibilite/Accessibility.mdx +3 -0
  280. package/src/components/FileUpload/FileUpload.vue +2 -1
  281. package/src/components/FileUpload/FileUploadContent.vue +2 -1
  282. package/src/components/FileUpload/tests/FileUpload.spec.ts +47 -0
  283. package/src/components/FileUpload/validateFiles.ts +5 -2
  284. package/src/components/FranceConnectBtn/accessibilite/Accessibility.mdx +62 -9
  285. package/src/components/HeaderBar/HeaderBar.stories.ts +14 -2
  286. package/src/components/HeaderBar/HeaderBar.vue +2 -1
  287. package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +2 -1
  288. package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +2 -1
  289. package/src/components/Logo/accessibilite/Accessibility.mdx +73 -11
  290. package/src/components/LogoBrandSection/accessibilite/Accessibility.mdx +85 -9
  291. package/src/components/LunarCalendar/accessibilite/Accessibility.mdx +74 -8
  292. package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +163 -0
  293. package/src/components/LunarCalendar/tests/LunarCalendar.spec.ts +3 -1
  294. package/src/components/LunarCalendar/useLunarCalendarValidation.ts +4 -5
  295. package/src/components/MaintenancePage/MaintenancePage.vue +1 -1
  296. package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +4 -5
  297. package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +0 -1
  298. package/src/components/MonthPicker/MonthPicker.mdx +35 -0
  299. package/src/components/MonthPicker/MonthPicker.stories.ts +527 -0
  300. package/src/components/MonthPicker/MonthPicker.vue +79 -0
  301. package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +89 -0
  302. package/src/components/MonthPicker/MonthPickerText/useTextField.ts +27 -0
  303. package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.vue +154 -0
  304. package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.ts +13 -0
  305. package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +137 -0
  306. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +60 -0
  307. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +149 -0
  308. package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +143 -0
  309. package/src/components/MonthPicker/MonthPickerVisual/useMonthGrid.ts +45 -0
  310. package/src/components/MonthPicker/MonthPickerVisual/useYearGrid.ts +45 -0
  311. package/src/components/MonthPicker/MonthPickerVisual/utils.ts +17 -0
  312. package/src/components/MonthPicker/accessibilite/Accessibility.mdx +59 -0
  313. package/src/components/MonthPicker/locales.ts +12 -0
  314. package/src/components/MonthPicker/tests/MonthPicker.a11y.spec.ts +71 -0
  315. package/src/components/MonthPicker/tests/MonthPicker.spec.ts +1249 -0
  316. package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +2545 -0
  317. package/src/components/MonthPicker/useMonthPickerValidation.ts +30 -0
  318. package/src/components/NirField/NirField.mdx +1 -2
  319. package/src/components/NirField/NirField.stories.ts +70 -6
  320. package/src/components/NirField/NirField.vue +64 -260
  321. package/src/components/NirField/accessibilite/Accessibility.mdx +2 -2
  322. package/src/components/NirField/locales.ts +1 -1
  323. package/src/components/NirField/tests/NirField.spec.ts +6 -0
  324. package/src/components/NirField/useNirValidation.ts +271 -0
  325. package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +2 -3
  326. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +22 -14
  327. package/src/components/NotificationBar/Notification/Notification.vue +3 -1
  328. package/src/components/NotificationBar/NotificationBar.stories.ts +154 -0
  329. package/src/components/NotificationBar/tests/NotificationBar.a11y.spec.ts +26 -0
  330. package/src/components/NotificationBar/tests/NotificationBar.spec.ts +60 -0
  331. package/src/components/PasswordField/PasswordField.stories.ts +4 -4
  332. package/src/components/PasswordField/PasswordField.vue +18 -24
  333. package/src/components/PasswordField/tests/PasswordField.spec.ts +6 -3
  334. package/src/components/PeriodField/PeriodField.stories.ts +4 -4
  335. package/src/components/PeriodField/PeriodField.vue +57 -57
  336. package/src/components/PeriodField/__tests__/PeriodField.async.spec.ts +32 -0
  337. package/src/components/PeriodField/accessibilite/Accessibility.mdx +68 -8
  338. package/src/components/PeriodField/tests/PeriodField.spec.ts +28 -2
  339. package/src/components/PhoneField/PhoneField.vue +5 -6
  340. package/src/components/PhoneField/tests/PhoneField.spec.ts +1 -0
  341. package/src/components/RangeField/RangeField.vue +6 -0
  342. package/src/components/RangeField/accessibilite/Accessibility.mdx +79 -11
  343. package/src/components/SkipLink/tests/SkipLink.a11y.spec.ts +23 -0
  344. package/src/components/StatusPage/StatusPage.stories.ts +118 -0
  345. package/src/components/StatusPage/StatusPage.vue +5 -3
  346. package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +22 -0
  347. package/src/components/StatusPage/tests/StatusPage.spec.ts +22 -0
  348. package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +22 -14
  349. package/src/components/SubHeader/tests/SubHeader.a11y.spec.ts +20 -0
  350. package/src/components/SyAlert/SyAlert.vue +1 -0
  351. package/src/components/SyAlert/accessibilite/Accessibility.mdx +79 -9
  352. package/src/components/SyAlert/tests/SyAlert.a11y.spec.ts +23 -0
  353. package/src/components/SyHeading/SyHeading.a11y.test.ts +149 -0
  354. package/src/components/SyHeading/SyHeading.test.ts +115 -0
  355. package/src/components/SyHeading/SyHeading.vue +5 -3
  356. package/src/components/SyTextArea/SyTextArea.stories.ts +138 -2
  357. package/src/components/SyTextArea/SyTextArea.vue +53 -23
  358. package/src/components/SyTextArea/accessibilite/Accessibility.mdx +80 -8
  359. package/src/components/SyTextArea/tests/SyTextArea.a11y.spec.ts +151 -0
  360. package/src/components/SyTextArea/tests/SyTextArea.spec.ts +126 -3
  361. package/src/components/SyTextArea/useDefaultValidationRules.ts +74 -0
  362. package/src/components/Tables/SyServerTable/SyServerTable.mdx +25 -0
  363. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +673 -1
  364. package/src/components/Tables/SyServerTable/SyServerTable.vue +148 -91
  365. package/src/components/Tables/SyServerTable/tests/SyServerTable.a11y.spec.ts +58 -0
  366. package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +122 -0
  367. package/src/components/Tables/SyTable/SyTable.mdx +25 -0
  368. package/src/components/Tables/SyTable/SyTable.stories.ts +452 -1
  369. package/src/components/Tables/SyTable/SyTable.vue +130 -56
  370. package/src/components/Tables/SyTable/tests/SyTable.a11y.spec.ts +57 -0
  371. package/src/components/Tables/SyTable/tests/SyTable.spec.ts +108 -0
  372. package/src/components/Tables/common/SyTableFilter.vue +22 -2
  373. package/src/components/Tables/common/TableHeader.vue +5 -1
  374. package/src/components/Tables/common/filters/AutocompleteFilter.vue +160 -0
  375. package/src/components/Tables/common/filters/NumberFilter.vue +1 -1
  376. package/src/components/Tables/common/filters/SelectFilter.vue +10 -11
  377. package/src/components/Tables/common/filters/TextFilter.vue +1 -1
  378. package/src/components/Tables/common/filters/getFilterComponent.ts +8 -1
  379. package/src/components/Tables/common/filters/locales.ts +0 -1
  380. package/src/components/Tables/common/filters/tests/AutocompleteFilter.a11y.spec.ts +110 -0
  381. package/src/components/Tables/common/filters/tests/AutocompleteFilter.spec.ts +203 -0
  382. package/src/components/Tables/common/filters/tests/SelectFilter.a11y.spec.ts +104 -0
  383. package/src/components/Tables/common/filters/tests/SelectFilter.spec.ts +152 -16
  384. package/src/components/Tables/common/tableFilterUtils.ts +3 -0
  385. package/src/components/Tables/common/tableStyles.scss +48 -4
  386. package/src/components/Tables/common/tests/filterByRange.spec.ts +2 -1
  387. package/src/components/Tables/common/types.ts +13 -4
  388. package/src/components/Tables/common/useClickableTableRow.ts +103 -0
  389. package/src/components/Tables/common/usePagination.ts +13 -0
  390. package/src/components/Tables/common/usePinnedColumns.ts +237 -0
  391. package/src/components/Tables/common/useTableHeaders.ts +3 -3
  392. package/src/components/Tables/common/useTableRowCheckboxAccessibility.ts +41 -0
  393. package/src/components/ToolbarContainer/tests/ToolbarContainer.a11y.spec.ts +126 -0
  394. package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +2 -2
  395. package/src/components/index.ts +1 -0
  396. package/src/composables/date/tests/useDatePickerAccessibility.spec.ts +2 -6
  397. package/src/composables/date/useDatePickerAccessibility.ts +42 -207
  398. package/src/composables/rules/tests/useFieldValidation.spec.ts +120 -120
  399. package/src/composables/rules/useFieldValidation.ts +34 -17
  400. package/src/composables/unifyValidation/tests/useCustomValidation.spec.ts +601 -0
  401. package/src/composables/unifyValidation/tests/useValidation.spec.ts +2048 -0
  402. package/src/composables/unifyValidation/tests/useVuetifyValidation.spec.ts +184 -0
  403. package/src/composables/unifyValidation/useCustomValidation.ts +95 -0
  404. package/src/composables/unifyValidation/useValidation.ts +190 -0
  405. package/src/composables/unifyValidation/useVuetifyValidation.ts +54 -0
  406. package/src/composables/useFormFieldErrorHandling.ts +15 -9
  407. package/src/composables/validation/tests/useFormValidation.spec.ts +14 -0
  408. package/src/composables/validation/tests/useValidation.spec.ts +116 -21
  409. package/src/composables/validation/useFormValidation.ts +20 -13
  410. package/src/composables/validation/useValidatable.ts +8 -1
  411. package/src/composables/validation/useValidation.ts +135 -99
  412. package/src/composantsVuetify/Introduction.mdx +48 -0
  413. package/src/composantsVuetify/VBtn/VBtn.mdx +72 -0
  414. package/src/composantsVuetify/VBtn/v-btn.stories.ts +121 -0
  415. package/src/composantsVuetify/VTooltip/VTooltip.mdx +32 -0
  416. package/src/composantsVuetify/VTooltip/v-tooltip.stories.ts +95 -0
  417. package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -1
  418. package/src/designTokens/tokens/cnam/cnamSemantic.ts +2 -2
  419. package/src/stories/Components/Components.stories.ts +74 -9
  420. package/src/stories/Demarrer/Accueil.stories.ts +3 -3
  421. package/src/stories/GuideDuDev/Amelipro.mdx +15 -0
  422. package/src/stories/GuideDuDev/Amelipro.stories.ts +209 -0
  423. package/src/stories/GuideDuDev/vuetifyOptions.mdx +3 -3
  424. package/dist/SelectFilter-BOYlF7rX.js +0 -136
  425. package/dist/style.css +0 -1
  426. package/src/components/DatePicker/Accessibilite.mdx +0 -14
@@ -1,4 +1,4 @@
1
- import { describe, it, expect } from 'vitest'
1
+ import { describe, it, expect, vi } from 'vitest'
2
2
  import { useValidation } from '../useValidation'
3
3
 
4
4
  describe('useValidation', () => {
@@ -13,7 +13,7 @@ describe('useValidation', () => {
13
13
  expect(validation.hasSuccess.value).toBe(false)
14
14
  })
15
15
 
16
- it('should handle basic validation rules', () => {
16
+ it('should handle basic validation rules', async () => {
17
17
  const validation = useValidation()
18
18
  const rules = [{
19
19
  type: 'required',
@@ -24,17 +24,17 @@ describe('useValidation', () => {
24
24
  }]
25
25
 
26
26
  // Test avec une valeur vide
27
- const emptyResult = validation.validateField('', rules)
27
+ const emptyResult = await validation.validateField('', rules)
28
28
  expect(emptyResult.hasError).toBe(true)
29
29
  expect(emptyResult.state.errors).toContain('Ce champ est requis')
30
30
 
31
31
  // Test avec une valeur valide
32
- const validResult = validation.validateField('test', rules)
32
+ const validResult = await validation.validateField('test', rules)
33
33
  expect(validResult.hasSuccess).toBe(true)
34
34
  expect(validResult.state.successes).toContain('Champ valide')
35
35
  })
36
36
 
37
- it('should handle warning rules', () => {
37
+ it('should handle warning rules', async () => {
38
38
  const validation = useValidation()
39
39
  const warningRules = [{
40
40
  type: 'custom',
@@ -46,17 +46,17 @@ describe('useValidation', () => {
46
46
  }]
47
47
 
48
48
  // Test avec une valeur courte
49
- const shortResult = validation.validateField('test', [], warningRules)
49
+ const shortResult = await validation.validateField('test', [], warningRules)
50
50
  expect(shortResult.hasWarning).toBe(true)
51
51
  expect(shortResult.state.warnings[0]).toContain('8 caractères')
52
52
 
53
53
  // Test avec une valeur valide
54
- const validResult = validation.validateField('test_long', [], warningRules)
54
+ const validResult = await validation.validateField('test_long', [], warningRules)
55
55
  expect(validResult.hasWarning).toBe(false)
56
56
  expect(validResult.state.warnings).toEqual([])
57
57
  })
58
58
 
59
- it('should handle multiple validation rules', () => {
59
+ it('should handle multiple validation rules', async () => {
60
60
  const validation = useValidation()
61
61
  const rules = [
62
62
  {
@@ -75,22 +75,22 @@ describe('useValidation', () => {
75
75
  ]
76
76
 
77
77
  // Test avec une valeur vide
78
- const emptyResult = validation.validateField('', rules)
78
+ const emptyResult = await validation.validateField('', rules)
79
79
  expect(emptyResult.hasError).toBe(true)
80
80
  expect(emptyResult.state.errors).toContain('Ce champ est requis')
81
81
 
82
82
  // Test avec une valeur trop courte
83
- const shortResult = validation.validateField('ab', rules)
83
+ const shortResult = await validation.validateField('ab', rules)
84
84
  expect(shortResult.hasError).toBe(true)
85
85
  expect(shortResult.state.errors).toContain('Minimum 3 caractères requis')
86
86
 
87
87
  // Test avec une valeur valide
88
- const validResult = validation.validateField('abc', rules)
88
+ const validResult = await validation.validateField('abc', rules)
89
89
  expect(validResult.hasError).toBe(false)
90
90
  expect(validResult.hasSuccess).toBe(true)
91
91
  })
92
92
 
93
- it('should respect showSuccessMessages option', () => {
93
+ it('should respect showSuccessMessages option', async () => {
94
94
  const validation = useValidation({ showSuccessMessages: false })
95
95
  const rules = [{
96
96
  type: 'required',
@@ -100,12 +100,12 @@ describe('useValidation', () => {
100
100
  },
101
101
  }]
102
102
 
103
- const result = validation.validateField('test', rules)
103
+ const result = await validation.validateField('test', rules)
104
104
  expect(result.hasSuccess).toBe(false)
105
105
  expect(result.state.successes).toEqual([])
106
106
  })
107
107
 
108
- it('should use fieldIdentifier in messages', () => {
108
+ it('should use fieldIdentifier in messages', async () => {
109
109
  const validation = useValidation({ fieldIdentifier: 'Email' })
110
110
  const rules = [{
111
111
  type: 'required',
@@ -114,11 +114,11 @@ describe('useValidation', () => {
114
114
  },
115
115
  }]
116
116
 
117
- const result = validation.validateField('', rules)
117
+ const result = await validation.validateField('', rules)
118
118
  expect(result.state.errors[0]).toContain('Email')
119
119
  })
120
120
 
121
- it('should clear validation state', () => {
121
+ it('should clear validation state', async () => {
122
122
  const validation = useValidation()
123
123
  const rules = [{
124
124
  type: 'required',
@@ -127,7 +127,7 @@ describe('useValidation', () => {
127
127
  },
128
128
  }]
129
129
 
130
- validation.validateField('', rules)
130
+ await validation.validateField('', rules)
131
131
  expect(validation.hasError.value).toBe(true)
132
132
 
133
133
  validation.clearValidation()
@@ -145,10 +145,105 @@ describe('useValidation', () => {
145
145
  },
146
146
  }]
147
147
 
148
- validation.validateField('', rules)
149
- expect(await validation.validateOnSubmit()).toBe(false)
148
+ await validation.validateField('', rules)
149
+ expect(validation.validateOnSubmit()).toBe(false)
150
150
 
151
- validation.validateField('test', rules)
152
- expect(await validation.validateOnSubmit()).toBe(true)
151
+ await validation.validateField('test', rules)
152
+ expect(validation.validateOnSubmit()).toBe(true)
153
+ })
154
+
155
+ describe('Handle thrown errors in async rules', () => {
156
+ it('should handle thrown error in async validation rules', async () => {
157
+ const validation = useValidation()
158
+ const rules = [{
159
+ type: 'custom',
160
+ options: {
161
+ validate: async () => {
162
+ throw new Error('Network error')
163
+ },
164
+ message: 'Erreur personnalisée',
165
+ },
166
+ }]
167
+
168
+ const result = await validation.validateField('test', rules)
169
+ expect(result.hasError).toBe(true)
170
+ expect(result.state.errors[0]).toBe('Erreur personnalisée')
171
+ })
172
+
173
+ it('should use thrown error message when no custom message is provided', async () => {
174
+ const validation = useValidation()
175
+ const rules = [{
176
+ type: 'custom',
177
+ options: {
178
+ validate: async () => {
179
+ throw new Error('Service unavailable')
180
+ },
181
+ },
182
+ }]
183
+
184
+ const result = await validation.validateField('test', rules)
185
+ expect(result.hasError).toBe(true)
186
+ expect(result.state.errors[0]).toBe('Service unavailable')
187
+ })
188
+
189
+ it('should handle thrown error in async warning rules', async () => {
190
+ const validation = useValidation()
191
+ const warningRules = [{
192
+ type: 'custom',
193
+ options: {
194
+ validate: async () => {
195
+ throw new Error('Warning service failed')
196
+ },
197
+ isWarning: true,
198
+ },
199
+ }]
200
+
201
+ const result = await validation.validateField('test', [], warningRules)
202
+ expect(result.hasWarning).toBe(true)
203
+ expect(result.state.warnings[0]).toBe('Warning service failed')
204
+ })
205
+ })
206
+
207
+ it('should discard a slow async validation when a newer one is triggered after', async () => {
208
+ vi.useFakeTimers()
209
+ const validation = useValidation()
210
+
211
+ // Slow rule: resolves after 100ms with an error
212
+ const slowRules = [{
213
+ type: 'custom',
214
+ options: {
215
+ validate: () => new Promise<boolean>(resolve => setTimeout(() => resolve(false), 100)),
216
+ message: 'Erreur lente',
217
+ },
218
+ }]
219
+
220
+ // Fast rule: resolves immediately with success
221
+ const fastRules = [{
222
+ type: 'custom',
223
+ options: {
224
+ validate: () => true,
225
+ successMessage: 'Validation rapide réussie',
226
+ },
227
+ }]
228
+
229
+ // Launch slow validation first, then fast validation immediately after
230
+ const slowPromise = validation.validateField('test', slowRules)
231
+ const fastResult = await validation.validateField('test', fastRules)
232
+
233
+ // Fast validation should have succeeded
234
+ expect(fastResult.hasError).toBe(false)
235
+ expect(fastResult.hasSuccess).toBe(true)
236
+ expect(fastResult.state.successes).toContain('Validation rapide réussie')
237
+
238
+ // Wait for the slow validation to resolve
239
+ vi.advanceTimersByTime(100)
240
+ await slowPromise
241
+
242
+ // The slow validation must NOT have overwritten the fast result
243
+ expect(validation.errors.value).toEqual([])
244
+ expect(validation.hasError.value).toBe(false)
245
+ expect(validation.successes.value).toContain('Validation rapide réussie')
246
+
247
+ vi.useRealTimers()
153
248
  })
154
249
  })
@@ -1,10 +1,13 @@
1
1
  import { provide, inject, ref, type InjectionKey, type Ref } from 'vue'
2
2
 
3
3
  // Type pour les composants pouvant être validés
4
- export interface ValidatableComponent {
4
+ export type ValidatableComponent = {
5
5
  validateOnSubmit: () => Promise<boolean> | boolean
6
6
  clearValidation?: () => void
7
7
  reset?: () => void
8
+ $props?: {
9
+ label?: string
10
+ }
8
11
  }
9
12
 
10
13
  // Clé d'injection pour le registre des composants validables
@@ -47,24 +50,28 @@ export function useFormValidation() {
47
50
  // Fonction pour nettoyer les validations de tous les composants enregistrés
48
51
  const clearAll = () => {
49
52
  if (validatableComponents.value.length === 0) return
50
- validatableComponents.value.forEach((component) => {
51
- try {
52
- component.clearValidation?.()
53
- }
54
- catch {
55
- // no-op: un composant peut ne pas implémenter clearValidation
53
+ validatableComponents.value.forEach((component: ValidatableComponent) => {
54
+ if (component.clearValidation) {
55
+ try {
56
+ component.clearValidation()
57
+ }
58
+ catch (error) {
59
+ console.warn('Error clearing validation for field: ' + (component?.$props?.label ?? 'unknown'), error)
60
+ }
56
61
  }
57
62
  })
58
63
  }
59
64
 
60
65
  const resetAll = () => {
61
66
  if (validatableComponents.value.length === 0) return
62
- validatableComponents.value.forEach((component) => {
63
- try {
64
- component.reset?.()
65
- }
66
- catch {
67
- // no-op: un composant peut ne pas implémenter reset
67
+ validatableComponents.value.forEach((component: ValidatableComponent) => {
68
+ if (component.reset) {
69
+ try {
70
+ component.reset()
71
+ }
72
+ catch (error) {
73
+ console.warn('Error resetting field: ' + (component?.$props?.label ?? 'unknown'), error)
74
+ }
68
75
  }
69
76
  })
70
77
  }
@@ -34,7 +34,14 @@ export function useValidatable(
34
34
  const instance = getCurrentInstance()
35
35
 
36
36
  // Keep a stable object reference for register/unregister symmetry
37
- const componentRef = { validateOnSubmit: validateMethod, clearValidation, reset }
37
+ const componentRef = {
38
+ validateOnSubmit: validateMethod,
39
+ clearValidation,
40
+ reset,
41
+ $props: {
42
+ label: typeof instance?.props?.label === 'string' ? instance.props.label : undefined,
43
+ },
44
+ }
38
45
 
39
46
  onMounted(() => {
40
47
  if (instance) {
@@ -1,18 +1,24 @@
1
1
  import { ref, computed } from 'vue'
2
- import { useFieldValidation, type RuleOptions } from '../rules/useFieldValidation'
2
+ import { useFieldValidation, type RuleOptions, type ValidationResult as FieldValidationResult } from '../rules/useFieldValidation'
3
3
 
4
- export type ValidationRule = {
5
- type: string
4
+ export type BuiltInRuleType = 'required' | 'email' | 'minLength' | 'maxLength'
5
+
6
+ interface CustomValidationRule {
7
+ type: 'custom'
8
+ options: RuleOptions & { validate: NonNullable<RuleOptions['validate']> }
9
+ }
10
+
11
+ interface StandardValidationRule {
12
+ type: BuiltInRuleType | ({} & string)
6
13
  options: RuleOptions
7
14
  }
8
15
 
16
+ export type ValidationRule = CustomValidationRule | StandardValidationRule
17
+
9
18
  export interface ValidationOptions {
10
19
  showSuccessMessages?: boolean
11
- fieldIdentifier?: string
12
- customRules?: ValidationRule[]
13
- warningRules?: ValidationRule[]
14
- successRules?: ValidationRule[]
15
20
  disableErrorHandling?: boolean
21
+ fieldIdentifier?: string
16
22
  }
17
23
 
18
24
  export interface ValidationState {
@@ -38,6 +44,8 @@ export function useValidation(options: ValidationOptions = { showSuccessMessages
38
44
  const warnings = ref<string[]>([])
39
45
  const successes = ref<string[]>([])
40
46
 
47
+ let currentValidationToken = 0
48
+
41
49
  const { generateRules } = useFieldValidation()
42
50
 
43
51
  const hasError = computed(() => errors.value.length > 0)
@@ -52,128 +60,156 @@ export function useValidation(options: ValidationOptions = { showSuccessMessages
52
60
  successes.value = []
53
61
  }
54
62
 
63
+ /**
64
+ * Resolves an array of rule results that may be sync or async.
65
+ * Returns the resolved array directly if all are sync, or a Promise if any are async.
66
+ */
67
+ const resolveRuleResults = (
68
+ results: (FieldValidationResult | Promise<FieldValidationResult>)[],
69
+ ): FieldValidationResult[] | Promise<FieldValidationResult[]> => {
70
+ if (results.every(r => !(r instanceof Promise))) return results as FieldValidationResult[]
71
+
72
+ const safePromises = results.map((r: FieldValidationResult | Promise<FieldValidationResult>) => {
73
+ if (!(r instanceof Promise)) return Promise.resolve(r)
74
+
75
+ return r.catch((err: unknown) => {
76
+ const message = err instanceof Error ? err.message : String(err)
77
+ return { error: message || 'Erreur de validation' } as FieldValidationResult
78
+ })
79
+ })
80
+
81
+ return Promise.all(safePromises)
82
+ }
83
+
84
+ /** Executes validation rules against a value, returning sync or async results. */
85
+ const executeRules = (
86
+ rules: ValidationRule[],
87
+ value: unknown,
88
+ extraOptions?: Record<string, boolean>,
89
+ ): FieldValidationResult[] | Promise<FieldValidationResult[]> => {
90
+ for (const rule of rules) {
91
+ if ('validator' in rule) {
92
+ console.error('[useValidation] "validator" en top level de ValidationRule n\'est plus supporté. Utilisez rule.options.validate à la place.')
93
+ }
94
+ }
95
+
96
+ const prepared = rules.map(rule => ({
97
+ type: rule.type,
98
+ options: { ...rule.options, ...extraOptions, ...(options.fieldIdentifier && !rule.options?.fieldIdentifier ? { fieldIdentifier: options.fieldIdentifier } : {}) },
99
+ }))
100
+ const fns = generateRules(prepared)
101
+ return resolveRuleResults(fns.map(fn => fn(value)))
102
+ }
103
+
104
+ /** Applies a callback to a sync or async value, discarding stale results via token. */
105
+ const thenOrSync = <T>(
106
+ value: T | Promise<T>,
107
+ token: number,
108
+ fn: (resolved: T) => ValidationResult | Promise<ValidationResult>,
109
+ ): ValidationResult | Promise<ValidationResult> => {
110
+ if (value instanceof Promise) {
111
+ return value.then(resolved =>
112
+ token !== currentValidationToken ? buildResult() : fn(resolved),
113
+ )
114
+ }
115
+ return fn(value)
116
+ }
117
+
118
+ const buildResult = (): ValidationResult => ({
119
+ hasError: hasError.value,
120
+ hasWarning: hasWarning.value,
121
+ hasSuccess: hasSuccess.value,
122
+ state: {
123
+ errors: errors.value,
124
+ warnings: warnings.value,
125
+ successes: successes.value,
126
+ },
127
+ })
128
+
129
+ /** Adds a default success message when no custom success rules are provided. */
130
+ const addDefaultSuccessMessage = (rules: ValidationRule[]) => {
131
+ const customSuccessMessage = rules.find(rule => rule.options?.successMessage)?.options.successMessage
132
+ if (customSuccessMessage) {
133
+ successes.value.push(customSuccessMessage)
134
+ }
135
+ else {
136
+ const defaultMessage = options.fieldIdentifier ? `Le champ ${options.fieldIdentifier} est valide.` : 'Champ valide'
137
+ successes.value.push(defaultMessage)
138
+ }
139
+ }
140
+
55
141
  const validateField = (
56
142
  value: unknown,
57
143
  rules: ValidationRule[] = [],
58
144
  warningRules: ValidationRule[] = [],
59
145
  successRules: ValidationRule[] = [],
60
- ): ValidationResult => {
146
+ ): ValidationResult | Promise<ValidationResult> => {
147
+ const token = ++currentValidationToken
61
148
  clearValidation()
62
149
 
63
- // Si la gestion des erreurs est désactivée, on retourne un résultat sans erreurs
64
- if (options.disableErrorHandling) {
65
- return {
66
- hasError: false,
67
- hasWarning: false,
68
- hasSuccess: false,
69
- state: {
70
- errors: [],
71
- warnings: [],
72
- successes: [],
73
- },
74
- }
75
- }
150
+ if (options.disableErrorHandling) return buildResult()
76
151
 
77
- // Validation des règles normales
78
- const normalRules = rules.map(rule => ({
79
- type: rule.type,
80
- options: {
81
- ...rule.options,
82
- fieldIdentifier: options.fieldIdentifier || rule.options.fieldIdentifier,
83
- },
84
- }))
152
+ const resolved = executeRules(rules, value)
85
153
 
86
- const validationRules = generateRules(normalRules)
87
- let hasValidationError = false
88
- validationRules.forEach((validationRule) => {
89
- const result = validationRule(value)
90
- if (result.error) {
91
- errors.value.push(result.error)
92
- hasValidationError = true
154
+ return thenOrSync(resolved, token, (ruleResults) => {
155
+ let hasValidationError = false
156
+ for (const result of ruleResults) {
157
+ if (result.error) {
158
+ errors.value.push(result.error)
159
+ hasValidationError = true
160
+ }
93
161
  }
94
- })
95
162
 
96
- // Si pas d'erreur, ajouter le message de succès ou un message par défaut
97
- // Mais seulement si aucun customSuccessRules n'est défini pour éviter la duplication
98
- if (!hasValidationError && value && options.showSuccessMessages !== false && (!successRules || successRules.length === 0)) {
99
- const customSuccessMessage = rules.find(rule => rule.options.successMessage)?.options.successMessage
100
- if (customSuccessMessage) {
101
- successes.value.push(customSuccessMessage)
163
+ if (!hasValidationError && value && options.showSuccessMessages !== false && successRules.length === 0) {
164
+ addDefaultSuccessMessage(rules)
102
165
  }
103
- else {
104
- const defaultMessage = options.fieldIdentifier ? `Le champ ${options.fieldIdentifier} est valide.` : 'Champ valide'
105
- successes.value.push(defaultMessage)
166
+
167
+ if (!hasValidationError && warningRules.length > 0) {
168
+ const warningResolved = executeRules(warningRules, value, { isWarning: true })
169
+ return thenOrSync(warningResolved, token, (warningResults) => {
170
+ for (const r of warningResults) {
171
+ if (r.warning) warnings.value.push(r.warning)
172
+ }
173
+ return runSuccessRules(hasValidationError, value, successRules, token)
174
+ })
106
175
  }
107
- }
108
176
 
109
- // Validation des règles d'avertissement
110
- if (!hasValidationError) {
111
- const warningValidationRules = generateRules(
112
- warningRules.map(rule => ({
113
- type: rule.type,
114
- options: {
115
- ...rule.options,
116
- isWarning: true,
117
- fieldIdentifier: options.fieldIdentifier || rule.options.fieldIdentifier,
118
- },
119
- })),
120
- )
177
+ return runSuccessRules(hasValidationError, value, successRules, token)
178
+ })
179
+ }
121
180
 
122
- warningValidationRules.forEach((validationRule) => {
123
- const result = validationRule(value)
124
- if (result.warning) {
125
- warnings.value.push(result.warning)
126
- }
127
- })
128
- }
181
+ /** Runs success rules after normal + warning rules. */
182
+ const runSuccessRules = (
183
+ hasValidationError: boolean,
184
+ value: unknown,
185
+ successRules: ValidationRule[],
186
+ token: number,
187
+ ): ValidationResult | Promise<ValidationResult> => {
188
+ if (hasValidationError || hasWarning.value || successRules.length === 0) return buildResult()
129
189
 
130
- // Validation des règles de succès
131
- if (!hasValidationError && !hasWarning.value) {
132
- const successValidationRules = generateRules(
133
- successRules.map(rule => ({
134
- type: rule.type,
135
- options: {
136
- ...rule.options,
137
- isSuccess: true,
138
- fieldIdentifier: options.fieldIdentifier || rule.options.fieldIdentifier,
139
- },
140
- })),
141
- )
190
+ const successResolved = executeRules(successRules, value, { isSuccess: true })
142
191
 
143
- successValidationRules.forEach((validationRule) => {
144
- const result = validationRule(value)
145
- if (result.success && options.showSuccessMessages !== false) {
146
- successes.value.push(result.success)
192
+ return thenOrSync(successResolved, token, (successResults) => {
193
+ for (const r of successResults) {
194
+ if (r.success && options.showSuccessMessages !== false) {
195
+ successes.value.push(r.success)
147
196
  }
148
- })
149
- }
150
-
151
- return {
152
- hasError: hasError.value,
153
- hasWarning: hasWarning.value,
154
- hasSuccess: hasSuccess.value,
155
- state: {
156
- errors: errors.value,
157
- warnings: warnings.value,
158
- successes: successes.value,
159
- },
160
- }
197
+ }
198
+ return buildResult()
199
+ })
161
200
  }
162
201
 
163
- const validateOnSubmit = async (): Promise<boolean> => {
202
+ const validateOnSubmit = (): boolean => {
164
203
  return !hasError.value
165
204
  }
166
205
 
167
206
  return {
168
- // États
169
207
  errors,
170
208
  warnings,
171
209
  successes,
172
210
  hasError,
173
211
  hasWarning,
174
212
  hasSuccess,
175
-
176
- // Méthodes
177
213
  validateField,
178
214
  validateOnSubmit,
179
215
  clearValidation,
@@ -0,0 +1,48 @@
1
+ import { Meta } from '@storybook/blocks'
2
+
3
+ <Meta title="Composants/Composants Vuetify/Introduction" />
4
+
5
+ <div className="header">
6
+ <h1>Composants Vuetify</h1>
7
+ Pour certains composants, nous avons fait le choix d'utiliser directement les composants natifs de Vuetify en leur appliquant un thème via les tokens du design system. Cela permet de bénéficier de toute la puissance et la flexibilité de Vuetify tout en respectant la charte graphique de chaque thème.
8
+ </div>
9
+
10
+ ## Pourquoi utiliser les composants Vuetify directement ?
11
+
12
+ Certains composants sont suffisamment couverts par Vuetify et ne nécessitent pas d'encapsulation supplémentaire. Dans ce cas, nous appliquons simplement les bonnes props Vuetify en combinaison avec les tokens de couleur de chaque thème.
13
+ Cela signifie que vous pouvez utiliser toute l'API Vuetify native sur ces composants, sans restriction.
14
+
15
+ ## Utilisation
16
+
17
+ Pour ces composants, il vous suffit d'utiliser directement le composant Vuetify avec les props adéquates.
18
+
19
+ ### Exemple avec `v-btn`
20
+
21
+ ```html
22
+ <!-- Bouton primaire -->
23
+ <v-btn color="primary">Button</v-btn>
24
+
25
+ <!-- Bouton outlined -->
26
+ <v-btn color="primary" variant="outlined">Button</v-btn>
27
+
28
+ <!-- Bouton tonal -->
29
+ <v-btn color="primary" variant="tonal">Button</v-btn>
30
+
31
+ <!-- Bouton texte -->
32
+ <v-btn color="primary" variant="text">Button</v-btn>
33
+
34
+ <!-- Bouton désactivé -->
35
+ <v-btn color="primary" disabled>Button</v-btn>
36
+ ```
37
+
38
+ ## Props Vuetify disponibles
39
+
40
+ Vous pouvez utiliser n'importe quelle prop reconnue par Vuetify sur ces composants. Par exemple, pour un bouton `v-btn` la liste complète des props est disponible sur la [documentation Vuetify](https://vuetifyjs.com/en/api/v-btn/#props) du composant.
41
+
42
+ ## Thèmes supportés
43
+
44
+ Pour le `v-btn` par exemple les couleurs `primary`, `secondary` et `tertiary` sont définies différemment selon le thème actif.
45
+
46
+ ## Conclusion
47
+
48
+ L'utilisation directe des composants Vuetify avec les thèmes du design system vous offre une flexibilité maximale. Vous bénéficiez de toute l'API Vuetify tout en respectant automatiquement la charte graphique du thème actif. Il vous suffit d'utiliser les bonnes valeurs pour obtenir un rendu cohérent avec le design system.