@cnamts/synapse 1.0.25 → 1.0.27

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 (393) hide show
  1. package/dist/{AutocompleteFilter-D7qBuCAP.js → AutocompleteFilter-C9eLKyW8.js} +3 -3
  2. package/dist/{DateFilter-BitMWrMU.js → DateFilter-y-GLkAkn.js} +9 -9
  3. package/dist/{NumberFilter-BTLUxw0a.js → NumberFilter-DN6hIBS7.js} +1 -1
  4. package/dist/{PeriodFilter-B5rUIPAC.js → PeriodFilter-MoUUp9qS.js} +1 -1
  5. package/dist/{SelectFilter-l4QnRcuk.js → SelectFilter-bCbrdLmu.js} +1 -1
  6. package/dist/{TextFilter-C9hj6Qrp.js → TextFilter-CvjgEaoM.js} +4 -4
  7. package/dist/apLightTheme2026-ug4Y23ns.js +611 -0
  8. package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +2369 -351
  9. package/dist/components/Customs/Selects/SyAutocomplete/composables/useSyAutocompleteValidation.d.ts +18 -0
  10. package/dist/components/Customs/Selects/SyAutocomplete/utils/ariaManager.d.ts +1 -1
  11. package/dist/components/Customs/Selects/SyAutocomplete/utils/useKeyboardHandler.d.ts +3 -1
  12. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +58 -288
  13. package/dist/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.d.ts +1 -0
  14. package/dist/components/Customs/Selects/SySelect/composables/useSySelectValidation.d.ts +15 -0
  15. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +4 -3
  16. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +4 -3
  17. package/dist/components/Customs/SyIconButton/SyIconButton.d.ts +18 -0
  18. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +20 -37
  19. package/dist/components/Customs/SyRadioGroup/composables/useSyRadioGroupValidation.d.ts +50 -0
  20. package/dist/components/Customs/SyTextField/SyTextField.d.ts +8 -10
  21. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +197 -185
  22. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +91 -82
  23. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +35 -32
  24. package/dist/components/DatePicker/composables/index.d.ts +1 -0
  25. package/dist/components/DatePicker/composables/useDatePickerState.d.ts +3 -3
  26. package/dist/components/DatePicker/composables/useDatePickerValidationBridge.d.ts +51 -0
  27. package/dist/components/DatePicker/composables/useDateTextField.d.ts +2 -2
  28. package/dist/components/DatePicker/composables/useInputBlurHandler.d.ts +2 -2
  29. package/dist/components/DatePicker/types.d.ts +1 -2
  30. package/dist/components/LunarCalendar/useLunarCalendarValidation.d.ts +1 -0
  31. package/dist/components/MonthPicker/MonthPicker.d.ts +24 -24
  32. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +24 -24
  33. package/dist/components/NirField/NirField.d.ts +64 -60
  34. package/dist/components/NirField/useNirValidation.d.ts +6 -2
  35. package/dist/components/PasswordField/PasswordField.d.ts +3 -3
  36. package/dist/components/PeriodField/PeriodField.d.ts +338 -314
  37. package/dist/components/PhoneField/PhoneField.d.ts +34 -24
  38. package/dist/components/RangeField/RangeSlider/RangeSlider.d.ts +0 -3
  39. package/dist/components/RatingPicker/EmotionPicker/EmotionPicker.d.ts +3 -1
  40. package/dist/components/RatingPicker/NumberPicker/NumberPicker.d.ts +4 -3
  41. package/dist/components/RatingPicker/RatingPicker.d.ts +18 -5
  42. package/dist/components/RatingPicker/StarsPicker/StarsPicker.d.ts +3 -1
  43. package/dist/components/RatingPicker/useRatingFocus.d.ts +18 -0
  44. package/dist/components/SyTextArea/SyTextArea.d.ts +25 -15
  45. package/dist/components/SyTextArea/composables/useSyTextAreaValidation.d.ts +20 -0
  46. package/dist/components/SyTextArea/locales.d.ts +1 -0
  47. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +5 -4
  48. package/dist/components/Tables/SyTable/SyTable.d.ts +5 -4
  49. package/dist/components/Tables/common/SyTablePagination.d.ts +152 -364
  50. package/dist/components/Tables/common/TableHeader.d.ts +1 -1
  51. package/dist/components/Tables/common/filters/DateFilter.d.ts +4 -4
  52. package/dist/components/Tables/common/types.d.ts +2 -0
  53. package/dist/components/index.d.ts +1 -0
  54. package/dist/composables/date/useDateInitializationDayjs.d.ts +3 -1
  55. package/dist/composables/unifyValidation/documentationValidationProps.d.ts +160 -160
  56. package/dist/composables/unifyValidation/useCustomValidation.d.ts +3 -1
  57. package/dist/composables/unifyValidation/useValidation.d.ts +27 -19
  58. package/dist/composables/unifyValidation/useVuetifyValidation.d.ts +1 -1
  59. package/dist/composables/validation/useValidation.d.ts +1 -0
  60. package/dist/design-system-v3.js +81 -80
  61. package/dist/designTokens/tokens/amelipro/apContextual.d.ts +6 -6
  62. package/dist/designTokens/tokens/amelipro/apDarkTheme.d.ts +3 -1
  63. package/dist/designTokens/tokens/amelipro/apLightTheme.d.ts +53 -98
  64. package/dist/designTokens/tokens/baseContextualTokens.d.ts +0 -6
  65. package/dist/designTokens/tokens/baseTokens.d.ts +232 -0
  66. package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +6 -6
  67. package/dist/designTokens/tokens/cnam/cnamDarkTheme.d.ts +1 -1
  68. package/dist/designTokens/tokens/cnam/cnamLightTheme.d.ts +57 -99
  69. package/dist/designTokens/tokens/pa/paContextual.d.ts +0 -6
  70. package/dist/designTokens/tokens/pa/paDarkTheme.d.ts +1 -1
  71. package/dist/designTokens/tokens/pa/paLightTheme.d.ts +53 -97
  72. package/dist/designTokens/tokens/pa/paSemantic.d.ts +1 -0
  73. package/dist/designTokens/tokens/semanticTokens.d.ts +112 -0
  74. package/dist/{main-Cpx8Co6H.js → main-CI6Q9nmO.js} +13843 -13478
  75. package/dist/synapse.css +1 -1
  76. package/dist/vuetifyConfig.js +208 -72
  77. package/package.json +10 -7
  78. package/src/assets/overrides/_icons.scss +5 -17
  79. package/src/assets/overrides/_otp.scss +4 -5
  80. package/src/assets/overrides/_typography.scss +2 -1
  81. package/src/assets/overrides/_utilities.scss +1 -42
  82. package/src/components/Accordion/Accordion.vue +2 -0
  83. package/src/components/ChipList/ChipList.vue +30 -18
  84. package/src/components/ChipList/tests/chipList.spec.ts +4 -4
  85. package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +2 -1
  86. package/src/components/CookiesSelection/CookiesSelection.vue +2 -1
  87. package/src/components/CopyBtn/CopyBtn.vue +9 -0
  88. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.stories.ts +4 -0
  89. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.vue +7 -6
  90. package/src/components/Customs/Selects/SelectBtnField/tests/SelectBtnField.spec.ts +223 -0
  91. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +283 -351
  92. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +183 -219
  93. package/src/components/Customs/Selects/SyAutocomplete/composables/useSyAutocompleteValidation.ts +101 -0
  94. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +761 -1
  95. package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +3 -1
  96. package/src/components/Customs/Selects/SyAutocomplete/utils/useKeyboardHandler.ts +79 -5
  97. package/src/components/Customs/Selects/SyAutocomplete/validation/Validation.stories.ts +1029 -0
  98. package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +52 -217
  99. package/src/components/Customs/Selects/SySelect/SySelect.vue +248 -236
  100. package/src/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.ts +3 -0
  101. package/src/components/Customs/Selects/SySelect/composables/useSySelectValidation.ts +64 -0
  102. package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +440 -5
  103. package/src/components/Customs/Selects/SySelect/validation/Validation.stories.ts +1026 -0
  104. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +18 -7
  105. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +5 -5
  106. package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +8 -8
  107. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +27 -6
  108. package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +1 -1
  109. package/src/components/Customs/SyIcon/accessibilite/Accessibility.mdx +0 -6
  110. package/src/components/Customs/SyIcon/utils/tests/iconUtils.spec.ts +107 -0
  111. package/src/components/Customs/SyRadioGroup/SyRadioGroup.mdx +2 -2
  112. package/src/components/Customs/SyRadioGroup/SyRadioGroup.stories.ts +395 -200
  113. package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +100 -127
  114. package/src/components/Customs/SyRadioGroup/composables/useSyRadioGroupValidation.ts +127 -0
  115. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.a11y.spec.ts +93 -1
  116. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.spec.ts +146 -9
  117. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.visual.cy.ts +165 -0
  118. package/src/components/Customs/SyRadioGroup/validation/Validation.stories.ts +773 -0
  119. package/src/components/Customs/SyTabs/SyTabs.stories.ts +5 -5
  120. package/src/components/Customs/SyTabs/config.ts +3 -3
  121. package/src/components/Customs/SyTabs/tests/SyTabs.spec.ts +265 -0
  122. package/src/components/Customs/SyTabs/tests/useTabTransition.spec.ts +188 -0
  123. package/src/components/Customs/SyTextField/SyTextField.stories.ts +10 -29
  124. package/src/components/Customs/SyTextField/SyTextField.vue +52 -17
  125. package/src/components/DataList/DataList.stories.ts +1 -1
  126. package/src/components/DataListItem/tests/DataListItem.spec.ts +3 -1
  127. package/src/components/DatePicker/CalendarMode/DatePicker.stories.ts +1 -1
  128. package/src/components/DatePicker/CalendarMode/DatePicker.vue +52 -154
  129. package/src/components/DatePicker/CalendarMode/tests/DatePicker.coverage.spec.ts +156 -0
  130. package/src/components/DatePicker/CalendarMode/tests/DatePicker.spec.ts +495 -4
  131. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +1 -1
  132. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +55 -73
  133. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +207 -1
  134. package/src/components/DatePicker/ComplexDatePicker/tests/bridge-integration.regression.spec.ts +210 -0
  135. package/src/components/DatePicker/ComplexDatePicker/tests/calendar-navigation.regression.spec.ts +214 -0
  136. package/src/components/DatePicker/ComplexDatePicker/tests/validation-cross.regression.spec.ts +194 -0
  137. package/src/components/DatePicker/ComplexDatePicker/tests/validation-success-messages.regression.spec.ts +83 -0
  138. package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.stories.ts +1 -1
  139. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +169 -60
  140. package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +1 -1
  141. package/src/components/DatePicker/DateTextInput/tests/DateTextInput.spec.ts +320 -0
  142. package/src/components/DatePicker/composables/index.ts +1 -0
  143. package/src/components/DatePicker/composables/tests/useCalendarKeyboardNavigation.spec.ts +360 -0
  144. package/src/components/DatePicker/composables/tests/useDatePickerValidationBridge.spec.ts +129 -0
  145. package/src/components/DatePicker/composables/useDatePickerState.ts +33 -14
  146. package/src/components/DatePicker/composables/useDatePickerValidationBridge.ts +205 -0
  147. package/src/components/DatePicker/composables/useDateRangeInput.ts +2 -1
  148. package/src/components/DatePicker/composables/useDateSelection.ts +2 -1
  149. package/src/components/DatePicker/composables/useDateTextField.ts +2 -2
  150. package/src/components/DatePicker/composables/useInputBlurHandler.ts +2 -2
  151. package/src/components/DatePicker/docExamples/BidirectionalComplexValidation.vue +1 -1
  152. package/src/components/DatePicker/docExamples/DatePickerBidirectionalValidation.vue +1 -1
  153. package/src/components/DatePicker/tests/exposed-methods.coverage.spec.ts +75 -0
  154. package/src/components/DatePicker/types.ts +1 -2
  155. package/src/components/DialogBox/DialogBox.stories.ts +8 -8
  156. package/src/components/DialogBox/DialogBox.vue +1 -1
  157. package/src/components/DialogBox/accessibilite/Accessibility.mdx +86 -22
  158. package/src/components/FileList/UploadItem/UploadItem.vue +4 -4
  159. package/src/components/FileUpload/FileUpload.vue +2 -2
  160. package/src/components/FileUpload/FileUploadContent.vue +1 -1
  161. package/src/components/FilterInline/FilterInline.mdx +2 -2
  162. package/src/components/FilterSideBar/FilterSideBar.stories.ts +1 -1
  163. package/src/components/FilterSideBar/FilterSideBar.vue +4 -3
  164. package/src/components/FooterBar/FooterBar.vue +7 -7
  165. package/src/components/FranceConnectBtn/FranceConnectBtn.vue +1 -1
  166. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +2 -2
  167. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +7 -7
  168. package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +2 -2
  169. package/src/components/HeaderLoading/tests/HeaderLoading.spec.ts +87 -8
  170. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +3 -3
  171. package/src/components/HeaderNavigationBar/HorizontalNavbar/tests/HorizontalNavbar.spec.ts +589 -0
  172. package/src/components/HeaderToolbar/tests/HeaderToolBar.spec.ts +153 -1
  173. package/src/components/HeaderToolbar/tests/useMobileRightMenu.spec.ts +258 -0
  174. package/src/components/LangBtn/LangBtn.vue +2 -1
  175. package/src/components/LogoBrandSection/tests/LogoBrandSection.spec.ts +2 -2
  176. package/src/components/LogoBrandSection/tests/__snapshots__/LogoBrandSection.spec.ts.snap +1 -1
  177. package/src/components/LunarCalendar/tests/useLunarCalendarRules.spec.ts +184 -0
  178. package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +3 -3
  179. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +1 -1
  180. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +2 -2
  181. package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +1 -1
  182. package/src/components/NirField/NirField.vue +3 -3
  183. package/src/components/NotificationBar/Notification/Notification.vue +12 -12
  184. package/src/components/NotificationBar/NotificationBar.stories.ts +8 -8
  185. package/src/components/PaginatedTable/PaginatedTable.vue +1 -1
  186. package/src/components/PaginatedTable/Pagination.vue +3 -3
  187. package/src/components/PasswordField/PasswordField.vue +15 -11
  188. package/src/components/PasswordField/tests/PasswordField.spec.ts +3 -3
  189. package/src/components/PhoneField/PhoneField.vue +4 -2
  190. package/src/components/RangeField/RangeSlider/RangeSlider.vue +11 -18
  191. package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +1 -1
  192. package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +32 -48
  193. package/src/components/RatingPicker/EmotionPicker/tests/__snapshots__/EmotionPicker.spec.ts.snap +5 -0
  194. package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +48 -53
  195. package/src/components/RatingPicker/NumberPicker/tests/NumberPicker.spec.ts +2 -1
  196. package/src/components/RatingPicker/NumberPicker/tests/__snapshots__/NumberPicker.spec.ts.snap +40 -13
  197. package/src/components/RatingPicker/RatingPicker.stories.ts +65 -88
  198. package/src/components/RatingPicker/RatingPicker.vue +71 -15
  199. package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +28 -37
  200. package/src/components/RatingPicker/StarsPicker/tests/StarsPicker.spec.ts +1 -1
  201. package/src/components/RatingPicker/StarsPicker/tests/__snapshots__/StarsPicker.spec.ts.snap +5 -0
  202. package/src/components/RatingPicker/accessibilite/Accessibility.mdx +137 -9
  203. package/src/components/RatingPicker/tests/RatingPicker.a11y.spec.ts +123 -0
  204. package/src/components/RatingPicker/tests/RatingPicker.spec.ts +3 -2
  205. package/src/components/RatingPicker/tests/__snapshots__/RatingPicker.spec.ts.snap +40 -11
  206. package/src/components/RatingPicker/useRatingFocus.ts +97 -0
  207. package/src/components/StatusPage/tests/StatusPage.spec.ts +149 -0
  208. package/src/components/SubHeader/SubHeader.vue +1 -1
  209. package/src/components/SyAlert/SyAlert.vue +23 -23
  210. package/src/components/SyTextArea/SyTextArea.stories.ts +177 -131
  211. package/src/components/SyTextArea/SyTextArea.vue +257 -74
  212. package/src/components/SyTextArea/composables/useSyTextAreaValidation.ts +81 -0
  213. package/src/components/SyTextArea/locales.ts +1 -0
  214. package/src/components/SyTextArea/tests/SyTextArea.spec.ts +449 -1
  215. package/src/components/SyTextArea/useDefaultValidationRules.ts +2 -7
  216. package/src/components/SyTextArea/validation/Validation.stories.ts +856 -0
  217. package/src/components/TableToolbar/TableToolbar.vue +6 -6
  218. package/src/components/TableToolbar/accessibilite/Accessibility.mdx +81 -7
  219. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +163 -0
  220. package/src/components/Tables/SyServerTable/SyServerTable.vue +3 -2
  221. package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +67 -0
  222. package/src/components/Tables/SyTable/SyTable.stories.ts +94 -0
  223. package/src/components/Tables/SyTable/SyTable.vue +3 -2
  224. package/src/components/Tables/SyTable/tests/SyTable.spec.ts +64 -0
  225. package/src/components/Tables/common/SyTableFilter.vue +4 -4
  226. package/src/components/Tables/common/SyTablePagination.vue +1 -0
  227. package/src/components/Tables/common/TableHeader.vue +3 -3
  228. package/src/components/Tables/common/filters/DateFilter.vue +2 -2
  229. package/src/components/Tables/common/filters/logics/tests/NumberFilterLogic.spec.ts +176 -0
  230. package/src/components/Tables/common/filters/logics/tests/SelectFilterLogic.spec.ts +111 -0
  231. package/src/components/Tables/common/tableStyles.scss +6 -6
  232. package/src/components/Tables/common/types.ts +2 -0
  233. package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +2 -0
  234. package/src/components/index.ts +1 -0
  235. package/src/composables/date/tests/useDateFormatDayjs.spec.ts +112 -0
  236. package/src/composables/date/tests/{useDateInitialization.spec.ts → useDateInitializationDayjs.spec.ts} +39 -3
  237. package/src/composables/date/tests/useHolidayDay.spec.ts +109 -0
  238. package/src/composables/date/useDateInitializationDayjs.ts +4 -1
  239. package/src/composables/rules/tests/useFieldValidation.spec.ts +374 -0
  240. package/src/composables/tests/useError.spec.ts +30 -0
  241. package/src/composables/tests/useFormFieldErrorHandling.spec.ts +234 -0
  242. package/src/composables/unifyValidation/documentationValidationProps.ts +12 -12
  243. package/src/composables/unifyValidation/tests/documentationValidationProps.spec.ts +177 -0
  244. package/src/composables/unifyValidation/tests/useCustomValidation.spec.ts +32 -1
  245. package/src/composables/unifyValidation/tests/useValidation.spec.ts +28 -2
  246. package/src/composables/unifyValidation/useCustomValidation.ts +34 -12
  247. package/src/composables/unifyValidation/useValidation.ts +55 -27
  248. package/src/composables/unifyValidation/useVuetifyValidation.ts +2 -2
  249. package/src/composables/useFilterable/useFilterable.spec.ts +42 -0
  250. package/src/composables/useFilterable/useFilterable.ts +11 -7
  251. package/src/composables/useFormFieldErrorHandling.ts +6 -3
  252. package/src/composables/validation/tests/useValidation.spec.ts +2 -2
  253. package/src/composables/validation/useValidation.ts +15 -3
  254. package/src/composantsVuetify/VBtn/VBtn.mdx +9 -39
  255. package/src/composantsVuetify/VBtn/v-btn.stories.ts +26 -86
  256. package/src/composantsVuetify/VCard/VCard.mdx +59 -0
  257. package/src/composantsVuetify/VCard/v-card.stories.ts +279 -0
  258. package/src/designTokens/tokens/amelipro/apColors2026.ts +1 -1
  259. package/src/designTokens/tokens/amelipro/apContextual.ts +6 -0
  260. package/src/designTokens/tokens/amelipro/apDarkTheme.ts +2 -2
  261. package/src/designTokens/tokens/amelipro/apLightTheme.ts +72 -100
  262. package/src/designTokens/tokens/amelipro/apSemantic.ts +1 -1
  263. package/src/designTokens/tokens/baseContextualTokens.ts +1 -6
  264. package/src/designTokens/tokens/baseTokens.ts +232 -0
  265. package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -0
  266. package/src/designTokens/tokens/cnam/cnamDarkTheme.ts +2 -2
  267. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +76 -101
  268. package/src/designTokens/tokens/pa/paDarkTheme.ts +2 -2
  269. package/src/designTokens/tokens/pa/paLightTheme.ts +73 -99
  270. package/src/designTokens/tokens/pa/paSemantic.ts +2 -0
  271. package/src/designTokens/tokens/semanticTokens.ts +114 -0
  272. package/src/stories/Accessibilite/Aculturation/SensibilisationAccessibilite.mdx +61 -91
  273. package/src/stories/Accessibilite/AuditDesignSystem.mdx +5 -8
  274. package/src/stories/Accessibilite/AuditEtContreAudit/Exemptions-derogations.mdx +1 -1
  275. package/src/stories/Accessibilite/AuditEtContreAudit/Introduction.mdx +11 -8
  276. package/src/stories/Accessibilite/AuditEtContreAudit/RGAA.mdx +6 -7
  277. package/src/stories/Accessibilite/Introduction.mdx +30 -30
  278. package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +168 -78
  279. package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +13 -6
  280. package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +66 -45
  281. package/src/stories/Accessibilite/KitDePreAudit/Outils/LecteursDEcran.mdx +23 -49
  282. package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru/FauxPositifs.stories.ts +6 -0
  283. package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru/Utilisation.mdx +7 -19
  284. package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +18 -20
  285. package/src/stories/Components/Components.stories.ts +59 -6
  286. package/src/stories/DesignTokens/ColorIntegrationExample.vue +2 -3
  287. package/src/stories/DesignTokens/Colors.mdx +6 -8
  288. package/src/stories/DesignTokens/colors.stories.ts +244 -1081
  289. package/src/utils/amelipro/toKebabCase/tests/toKebabCase.spec.ts +52 -0
  290. package/src/utils/formatNir/tests/formatNir.spec.ts +34 -0
  291. package/src/utils/tests/insertAt.spec.ts +44 -0
  292. package/dist/AutocompleteFilter-Df9i5mAl.cjs +0 -1
  293. package/dist/DateFilter-BJD6FMev.cjs +0 -1
  294. package/dist/NumberFilter-DGCzCXzI.cjs +0 -1
  295. package/dist/PeriodFilter-DO_ecTZW.cjs +0 -1
  296. package/dist/SelectFilter-CGwcKWLm.cjs +0 -1
  297. package/dist/TextFilter-B8nf7xoK.cjs +0 -1
  298. package/dist/apLightTheme-CEK4iY3f.cjs +0 -1
  299. package/dist/apLightTheme-DnIM24Lv.js +0 -950
  300. package/dist/composables/date/useDateFormat.d.ts +0 -26
  301. package/dist/composables/date/useDateInitialization.d.ts +0 -18
  302. package/dist/design-system-v3.umd.cjs +0 -1
  303. package/dist/main-ByDPHpae.cjs +0 -1067
  304. package/dist/tooth-11-D3sLWv2n.cjs +0 -1
  305. package/dist/tooth-12-CXrLuH03.cjs +0 -1
  306. package/dist/tooth-13-BSfo5fpT.cjs +0 -1
  307. package/dist/tooth-14-DMzulx0h.cjs +0 -1
  308. package/dist/tooth-15-BKRFVi-9.cjs +0 -1
  309. package/dist/tooth-16-CpuxAbuM.cjs +0 -1
  310. package/dist/tooth-17-BPoahUdg.cjs +0 -1
  311. package/dist/tooth-18-DhHJz8sy.cjs +0 -1
  312. package/dist/tooth-21-Dgd5hn_X.cjs +0 -1
  313. package/dist/tooth-22-C2Tn19sB.cjs +0 -1
  314. package/dist/tooth-23-C9uaaSGb.cjs +0 -1
  315. package/dist/tooth-24-BrK9UGpf.cjs +0 -1
  316. package/dist/tooth-25-CE_EfGNp.cjs +0 -1
  317. package/dist/tooth-26-Ctv4i9Fy.cjs +0 -1
  318. package/dist/tooth-27-C5J7JkWM.cjs +0 -1
  319. package/dist/tooth-28-Z9oWqjo0.cjs +0 -1
  320. package/dist/tooth-31-BrYqmkTi.cjs +0 -1
  321. package/dist/tooth-32-BNNR0oCZ.cjs +0 -1
  322. package/dist/tooth-33-DuxvqO2J.cjs +0 -1
  323. package/dist/tooth-34-BCSCXMB6.cjs +0 -1
  324. package/dist/tooth-35-BLUXkX88.cjs +0 -1
  325. package/dist/tooth-36-IrKHYqlA.cjs +0 -1
  326. package/dist/tooth-37-BYqpdMwo.cjs +0 -1
  327. package/dist/tooth-38-B_eNXXdu.cjs +0 -1
  328. package/dist/tooth-41-Ddva4Ot8.cjs +0 -1
  329. package/dist/tooth-42-szcDqlM0.cjs +0 -1
  330. package/dist/tooth-43-B3ka6rQm.cjs +0 -1
  331. package/dist/tooth-44-CazyQucj.cjs +0 -1
  332. package/dist/tooth-45-B4HQtc8n.cjs +0 -1
  333. package/dist/tooth-46-BPM40gbG.cjs +0 -1
  334. package/dist/tooth-47-Dvr20dlh.cjs +0 -1
  335. package/dist/tooth-48-Bd8ljGsF.cjs +0 -1
  336. package/dist/tooth-51-OBpwCOF3.cjs +0 -1
  337. package/dist/tooth-52-aKxyHcmq.cjs +0 -1
  338. package/dist/tooth-53-vCwJjTOc.cjs +0 -1
  339. package/dist/tooth-54-DsWu2iFy.cjs +0 -1
  340. package/dist/tooth-55-BxC1X2Dn.cjs +0 -1
  341. package/dist/tooth-61-BbLvxMQi.cjs +0 -1
  342. package/dist/tooth-62-CmTkWczP.cjs +0 -1
  343. package/dist/tooth-63-DI7l_2qI.cjs +0 -1
  344. package/dist/tooth-64-B21sOsJh.cjs +0 -1
  345. package/dist/tooth-65-D2ZC2VEr.cjs +0 -1
  346. package/dist/tooth-71-D473PPO5.cjs +0 -1
  347. package/dist/tooth-72-Drh1wnNu.cjs +0 -1
  348. package/dist/tooth-73-DzlwYI23.cjs +0 -1
  349. package/dist/tooth-74-8aGvcZPg.cjs +0 -1
  350. package/dist/tooth-75-BFK7At_r.cjs +0 -1
  351. package/dist/tooth-81-BZmR-I0M.cjs +0 -1
  352. package/dist/tooth-82-euVfUUZV.cjs +0 -1
  353. package/dist/tooth-83-KV010j64.cjs +0 -1
  354. package/dist/tooth-84-BBg1RjhZ.cjs +0 -1
  355. package/dist/tooth-85-Cr-kc1wM.cjs +0 -1
  356. package/dist/vuetifyConfig.umd.cjs +0 -1
  357. package/src/components/BackBtn/tests/__snapshots__/back-btn-custom-bg.snap.png +0 -0
  358. package/src/components/BackBtn/tests/__snapshots__/back-btn-dark-mode.snap.png +0 -0
  359. package/src/components/BackBtn/tests/__snapshots__/back-btn-default.snap.png +0 -0
  360. package/src/components/BackBtn/tests/__snapshots__/back-btn-no-icon.snap.png +0 -0
  361. package/src/components/DatePicker/CalendarMode/tests/DatePicker.events.spec.ts +0 -178
  362. package/src/components/DialogBox/tests/__snapshots__/dialog-box-custom-texts.snap.png +0 -0
  363. package/src/components/DialogBox/tests/__snapshots__/dialog-box-default.snap.png +0 -0
  364. package/src/components/DialogBox/tests/__snapshots__/dialog-box-no-actions.snap.png +0 -0
  365. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated-submenu-open.snap.png +0 -0
  366. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated.snap.png +0 -0
  367. package/src/components/HeaderBar/tests/__snapshots__/header-bar-custom-width.snap.png +0 -0
  368. package/src/components/HeaderBar/tests/__snapshots__/header-bar-default.snap.png +0 -0
  369. package/src/components/HeaderBar/tests/__snapshots__/header-bar-no-sticky.snap.png +0 -0
  370. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-prepend.snap.png +0 -0
  371. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-side.snap.png +0 -0
  372. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-subtitle.snap.png +0 -0
  373. package/src/components/Logo/tests/__snapshots__/logo-avatar.snap.png +0 -0
  374. package/src/components/Logo/tests/__snapshots__/logo-dark.snap.png +0 -0
  375. package/src/components/Logo/tests/__snapshots__/logo-default.snap.png +0 -0
  376. package/src/components/Logo/tests/__snapshots__/logo-no-organism.snap.png +0 -0
  377. package/src/components/Logo/tests/__snapshots__/logo-no-signature.snap.png +0 -0
  378. package/src/components/Logo/tests/__snapshots__/logo-risque-pro.snap.png +0 -0
  379. package/src/components/RangeField/tests/__snapshots__/range-field-custom-bg.snap.png +0 -0
  380. package/src/components/RangeField/tests/__snapshots__/range-field-custom-range.snap.png +0 -0
  381. package/src/components/RangeField/tests/__snapshots__/range-field-default.snap.png +0 -0
  382. package/src/components/RangeField/tests/__snapshots__/range-field-step.snap.png +0 -0
  383. package/src/components/RangeField/tests/__snapshots__/range-field-with-label.snap.png +0 -0
  384. package/src/components/SyAlert/tests/__snapshots__/sy-alert-closable.snap.png +0 -0
  385. package/src/components/SyAlert/tests/__snapshots__/sy-alert-error.snap.png +0 -0
  386. package/src/components/SyAlert/tests/__snapshots__/sy-alert-info.snap.png +0 -0
  387. package/src/components/SyAlert/tests/__snapshots__/sy-alert-success.snap.png +0 -0
  388. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-outlined.snap.png +0 -0
  389. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-tonal.snap.png +0 -0
  390. package/src/components/SyAlert/tests/__snapshots__/sy-alert-warning.snap.png +0 -0
  391. package/src/composables/date/tests/useDateFormat.spec.ts +0 -67
  392. package/src/composables/date/useDateFormat.ts +0 -110
  393. package/src/composables/date/useDateInitialization.ts +0 -92
@@ -1,176 +1,85 @@
1
1
  <script setup lang="ts">
2
- import { computed, nextTick, onMounted, ref, watch, type PropType } from 'vue'
3
- import { VMenu, VList, VListItem, VListItemTitle, VChip } from 'vuetify/components'
2
+ import { computed, nextTick, onMounted, ref, useSlots, watch } from 'vue'
4
3
  import { mdiChevronDown, mdiCloseCircle } from '@mdi/js'
5
4
  import SyTextField from '@/components/Customs/SyTextField/SyTextField.vue'
6
5
  import SyIcon from '@/components/Customs/SyIcon/SyIcon.vue'
7
6
  import SyCheckbox from '@/components/Customs/SyCheckbox/SyCheckbox.vue'
8
7
  import { ariaManager } from './utils/ariaManager'
9
- import { useFormFieldErrorHandling } from '@/composables/useFormFieldErrorHandling'
10
- import { type ValidationRule } from '@/composables/validation/useValidation'
8
+ import { validationPropsDefaults, type FieldValidationProps } from '@/composables/unifyValidation/useValidation'
11
9
  import type { ItemType, SelectValue, SelectArray } from './types'
12
10
  import { useItemUtils } from './utils/useItemUtils'
13
11
  import { useSelectionLogic } from './utils/useSelectionLogic'
14
12
  import { useSyAutocompleteKeyboard } from './utils/useKeyboardHandler'
13
+ import { useSyAutocompleteValidation } from './composables/useSyAutocompleteValidation'
15
14
  import { locales } from './locales'
16
15
 
17
- const props = defineProps({
18
- bgColor: {
19
- type: String,
20
- default: 'white',
21
- },
22
- chips: {
23
- type: Boolean,
24
- default: false,
25
- },
26
- clearable: {
27
- type: Boolean,
28
- default: false,
29
- },
30
- customRules: {
31
- type: Array as PropType<ValidationRule[]>,
32
- default: () => [],
33
- },
34
- customSuccessRules: {
35
- type: Array as PropType<ValidationRule[]>,
36
- default: () => [],
37
- },
38
- customWarningRules: {
39
- type: Array as PropType<ValidationRule[]>,
40
- default: () => [],
41
- },
42
- debounce: {
43
- type: Number,
44
- default: 200,
45
- },
46
- density: {
47
- type: String as PropType<'default' | 'comfortable' | 'compact' | undefined>,
48
- default: 'default',
49
- },
50
- disableErrorHandling: {
51
- type: Boolean,
52
- default: false,
53
- },
54
- displayAsterisk: {
55
- type: Boolean,
56
- default: false,
57
- },
58
- errorMessages: {
59
- type: Array as PropType<string[] | null>,
60
- default: null,
61
- },
62
- filter: {
63
- type: Boolean,
64
- default: true,
65
- },
66
- hasError: {
67
- type: Boolean,
68
- default: false,
69
- },
70
- hasSuccess: {
71
- type: Boolean,
72
- default: false,
73
- },
74
- hasWarning: {
75
- type: Boolean,
76
- default: false,
77
- },
78
- hideDetails: {
79
- type: Boolean,
80
- default: false,
81
- },
82
- hideNoData: {
83
- type: Boolean,
84
- default: false,
85
- },
86
- isValidateOnBlur: {
87
- type: Boolean,
88
- default: false,
89
- },
90
- items: {
91
- type: Array as PropType<ItemType[]>,
92
- default: () => [],
93
- },
94
- label: {
95
- type: String,
96
- default: 'Rechercher',
97
- },
98
- loading: {
99
- type: Boolean,
100
- default: false,
101
- },
102
- menuId: {
103
- type: String,
104
- default: 'sy-autocomplete-menu',
105
- },
106
- modelValue: {
107
- type: [Object, String, Number, Array, null] as PropType<SelectValue | SelectArray>,
108
- default: null,
109
- },
110
- multiple: {
111
- type: Boolean,
112
- default: false,
113
- },
114
- noDataText: {
115
- type: String,
116
- default: locales.noData,
117
- },
118
- placeholder: {
119
- type: String,
120
- default: '',
121
- },
122
- plainTextKey: {
123
- type: String,
124
- default: '',
125
- },
126
- disabled: {
127
- type: Boolean,
128
- default: false,
129
- },
130
- readonly: {
131
- type: Boolean,
132
- default: false,
133
- },
134
- required: {
135
- type: Boolean,
136
- default: false,
137
- },
138
- returnObject: {
139
- type: Boolean,
140
- default: false,
141
- },
142
- showSuccessMessages: {
143
- type: Boolean,
144
- default: true,
145
- },
146
- successMessages: {
147
- type: Array as PropType<string[] | null>,
148
- default: null,
149
- },
150
- selectionText: {
151
- type: Function as PropType<(selected: SelectArray) => string>,
152
- default: undefined,
153
- },
154
- textKey: {
155
- type: String,
156
- default: 'text',
157
- },
158
- valueKey: {
159
- type: String,
160
- default: 'value',
161
- },
162
- warningMessages: {
163
- type: Array as PropType<string[] | null>,
164
- default: null,
165
- },
166
- })
16
+ interface SyAutocompleteProps {
17
+ bgColor?: string
18
+ chips?: boolean
19
+ clearable?: boolean
20
+ debounce?: number
21
+ density?: 'default' | 'comfortable' | 'compact' | undefined
22
+ displayAsterisk?: boolean
23
+ filter?: boolean
24
+ hideDetails?: boolean
25
+ hideNoData?: boolean
26
+ items?: ItemType[]
27
+ label?: string
28
+ loading?: boolean
29
+ menuId?: string
30
+ modelValue?: SelectValue | SelectArray
31
+ multiple?: boolean
32
+ noDataText?: string
33
+ placeholder?: string
34
+ plainTextKey?: string
35
+ helpText?: string
36
+ returnObject?: boolean
37
+ selectionText?: (selected: SelectArray) => string
38
+ textKey?: string
39
+ valueKey?: string
40
+ }
41
+
42
+ const props = withDefaults(
43
+ defineProps<SyAutocompleteProps & FieldValidationProps>(),
44
+ {
45
+ bgColor: 'white',
46
+ chips: false,
47
+ clearable: false,
48
+ debounce: 200,
49
+ density: 'default',
50
+ displayAsterisk: false,
51
+ filter: true,
52
+ hideDetails: false,
53
+ hideNoData: false,
54
+ items: () => [],
55
+ label: 'Rechercher',
56
+ loading: false,
57
+ menuId: 'sy-autocomplete-menu',
58
+ modelValue: null,
59
+ multiple: false,
60
+ noDataText: locales.noData,
61
+ helpText: '',
62
+ selectionText: undefined,
63
+ placeholder: '',
64
+ plainTextKey: '',
65
+ returnObject: false,
66
+ textKey: 'text',
67
+ valueKey: 'value',
68
+ ...validationPropsDefaults,
69
+ // Diverge du défaut global (true) : modelValue ne change que lors d'une sélection (pas à chaque frappe),
70
+ // donc valider sur ce changement donne un retour immédiat après sélection sans erreurs prématurées pendant la saisie.
71
+ isValidateOnBlur: false,
72
+ },
73
+ )
167
74
 
168
75
  const emit = defineEmits(['update:modelValue', 'search'])
169
76
 
77
+ const slots = useSlots()
78
+ const hasPrependItem = computed(() => !!slots['prepend-item'])
79
+
170
80
  const isOpen = ref(false)
171
81
  const search = ref('')
172
82
  const selected = ref<SelectValue | SelectArray>(props.modelValue as SelectValue | SelectArray)
173
- const hasInteracted = ref(false)
174
83
  const suppressNextInput = ref(false)
175
84
  const suppressMenuOpen = ref(false)
176
85
  type SyTextFieldInstance = InstanceType<typeof SyTextField> & { $refs?: { input?: HTMLInputElement } }
@@ -180,7 +89,21 @@
180
89
  const optionIdPrefixed = computed(() => `${uniqueMenuId.value}-option`)
181
90
  const activeDescendantId = ref('')
182
91
 
183
- const errorHandling = useFormFieldErrorHandling(props, selected)
92
+ const {
93
+ focused,
94
+ hasInteracted,
95
+ markInteracted,
96
+ clearValidation,
97
+ validateOnSubmit,
98
+ validateOnBlur,
99
+ displayErrors,
100
+ displayWarnings,
101
+ displaySuccesses,
102
+ displayHasError,
103
+ displayHasWarning,
104
+ displayHasSuccess,
105
+ validationIcon,
106
+ } = useSyAutocompleteValidation(props)
184
107
 
185
108
  const formattedItems = computed(() => props.items.map((item) => {
186
109
  if (typeof item === 'string') {
@@ -223,12 +146,11 @@
223
146
  })
224
147
  })
225
148
 
226
- const markInteracted = () => {
227
- hasInteracted.value = true
228
- }
229
-
230
149
  const selectItem = (item: ItemType | string | number | null | undefined) => {
231
150
  markInteracted()
151
+ if (item === null || item === undefined) {
152
+ clearValidation()
153
+ }
232
154
  updateValue(item ?? null)
233
155
  if (props.multiple) {
234
156
  suppressNextInput.value = true
@@ -258,13 +180,12 @@
258
180
 
259
181
  focusInput(textFieldRef)
260
182
 
261
- if (!props.filter) return
262
-
263
183
  if (debounceHandle) {
264
184
  clearTimeout(debounceHandle)
265
185
  }
266
186
 
267
187
  debounceHandle = setTimeout(() => {
188
+ emit('search', search.value)
268
189
  }, props.debounce)
269
190
  })
270
191
 
@@ -316,7 +237,7 @@
316
237
  : index
317
238
  }
318
239
 
319
- const { focusInput, keyboardActiveId, handleTabKey } = useSyAutocompleteKeyboard({
240
+ const { focusInput, focusPrepend, keyboardActiveId, handleTabKey } = useSyAutocompleteKeyboard({
320
241
  multiple: props.multiple,
321
242
  chips: props.chips,
322
243
  }, {
@@ -328,6 +249,7 @@
328
249
  filteredItems,
329
250
  uniqueMenuId,
330
251
  focusListItem: false,
252
+ hasPrependItem,
331
253
  })
332
254
 
333
255
  watch(keyboardActiveId, (val) => {
@@ -344,41 +266,6 @@
344
266
  return (textFieldRef.value?.$el as HTMLElement | undefined)?.querySelector('.v-field') ?? undefined
345
267
  })
346
268
 
347
- const shouldDisableErrorHandling = computed(() => props.disableErrorHandling)
348
-
349
- const externalErrors = computed(() => props.errorMessages || [])
350
- const displayErrors = computed(() => {
351
- if (shouldDisableErrorHandling.value) return []
352
- return externalErrors.value.length > 0
353
- ? externalErrors.value
354
- : (hasInteracted.value ? errorHandling.errors.value : [])
355
- })
356
- const displayWarnings = computed(() => {
357
- if (shouldDisableErrorHandling.value) return []
358
- return hasInteracted.value ? errorHandling.warnings.value : []
359
- })
360
- const displaySuccesses = computed(() => {
361
- if (shouldDisableErrorHandling.value) return []
362
- return hasInteracted.value ? errorHandling.successes.value : []
363
- })
364
- const displayHasError = computed(() => {
365
- if (shouldDisableErrorHandling.value) return false
366
- return externalErrors.value.length > 0 || (hasInteracted.value && errorHandling.hasError.value)
367
- })
368
- const displayHasWarning = computed(() => {
369
- if (shouldDisableErrorHandling.value) return false
370
- return hasInteracted.value && errorHandling.hasWarning.value
371
- })
372
- const displayHasSuccess = computed(() => {
373
- if (shouldDisableErrorHandling.value) return false
374
- return hasInteracted.value && errorHandling.hasSuccess.value
375
- })
376
-
377
- const validateOnSubmit = () => {
378
- markInteracted()
379
- return errorHandling.validateOnSubmit()
380
- }
381
-
382
269
  const checkErrorOnBlur = (event?: FocusEvent) => {
383
270
  const relatedTarget = event?.relatedTarget as HTMLElement | null | undefined
384
271
  if (relatedTarget?.closest('.sy-autocomplete__chip') || relatedTarget?.closest('.sy-autocomplete__clear-button')) {
@@ -388,8 +275,7 @@
388
275
  })
389
276
  return
390
277
  }
391
- markInteracted()
392
- return errorHandling.checkErrorOnBlur()
278
+ validateOnBlur()
393
279
  }
394
280
 
395
281
  const getInputValue = (value: string | Event): string | null => {
@@ -419,13 +305,13 @@
419
305
  updateValue(null)
420
306
  }
421
307
 
422
- emit('search', inputValue)
423
308
  openAndFocus()
424
309
  }
425
310
 
426
311
  const openAndFocus = () => {
427
312
  if (props.disabled || props.readonly) return
428
313
  markInteracted()
314
+ focused.value = true
429
315
  isOpen.value = true
430
316
  focusInput(textFieldRef)
431
317
  }
@@ -443,12 +329,12 @@
443
329
 
444
330
  onMounted(() => {
445
331
  syncSearchFromValue()
446
- ariaManager.setupAriaAttributesForAutocomplete(textFieldRef, isOpen, uniqueMenuId.value, activeDescendantId, props.loading, props.label)
332
+ ariaManager.setupAriaAttributesForAutocomplete(textFieldRef, isOpen, uniqueMenuId.value, activeDescendantId, props.loading, props.label, props.required, displayHasError.value)
447
333
  focusInput(textFieldRef, true)
448
334
  })
449
335
 
450
- watch([isOpen, activeDescendantId, () => props.loading], () => {
451
- ariaManager.setupAriaAttributesForAutocomplete(textFieldRef, isOpen, uniqueMenuId.value, activeDescendantId, props.loading, props.label)
336
+ watch([isOpen, activeDescendantId, () => props.loading, displayHasError, () => props.required], () => {
337
+ ariaManager.setupAriaAttributesForAutocomplete(textFieldRef, isOpen, uniqueMenuId.value, activeDescendantId, props.loading, props.label, props.required, displayHasError.value)
452
338
  }, { flush: 'post' })
453
339
 
454
340
  watch(isOpen, (open) => {
@@ -457,9 +343,17 @@
457
343
  }
458
344
  })
459
345
 
346
+ // flush: 'post' + rAF: Vuetify uses requestAnimationFrame (requestNewFrame) for overlay rendering,
347
+ // so nextTick/setTimeout(0) fire before the listbox is in the DOM.
348
+ watch(isOpen, (open) => {
349
+ if (open && hasPrependItem.value) {
350
+ requestAnimationFrame(() => focusPrepend())
351
+ }
352
+ }, { flush: 'post' })
353
+
460
354
  defineExpose({
461
- validation: errorHandling.validation,
462
355
  validateOnSubmit,
356
+ clearValidation,
463
357
  checkErrorOnBlur,
464
358
  isOpen,
465
359
  selectItem,
@@ -504,10 +398,12 @@
504
398
  :has-error="displayHasError"
505
399
  :has-warning="displayHasWarning"
506
400
  :has-success="displayHasSuccess"
401
+ :show-success-messages="showSuccessMessages"
507
402
  :required="required"
508
403
  :display-asterisk="required && displayAsterisk"
509
404
  :disable-error-handling="disableErrorHandling"
510
405
  :loading="loading"
406
+ :help-text="helpText"
511
407
  :are-details-hidden="hideDetails"
512
408
  :aria-label="hasInlineSelections ? label : undefined"
513
409
  @click="openAndFocus"
@@ -516,10 +412,19 @@
516
412
  @keydown.tab="handleTabKey"
517
413
  >
518
414
  <template #append-inner>
415
+ <SyIcon
416
+ v-if="validationIcon"
417
+ class="mr-6"
418
+ :color="displayHasError ? 'error' : (displayHasWarning ? 'warning' : 'success')"
419
+ :icon="validationIcon"
420
+ role="presentation"
421
+ :decorative="true"
422
+ />
519
423
  <button
520
424
  v-if="clearable && hasSelectionToClear"
521
425
  type="button"
522
426
  class="sy-autocomplete__clear-button"
427
+ :class="{ 'sy-autocomplete__clear-button--with-icon': validationIcon }"
523
428
  :aria-label="locales.clearSelection"
524
429
  @click.stop.prevent="selectItem(null)"
525
430
  >
@@ -581,6 +486,7 @@
581
486
  tabindex="-1"
582
487
  @click.stop
583
488
  >
489
+ <slot name="prepend-item" />
584
490
  <template v-if="filteredItems.length === 0 && !hideNoData && !loading">
585
491
  <VListItem
586
492
  :title="noDataText"
@@ -603,16 +509,18 @@
603
509
  v-if="multiple"
604
510
  #prepend
605
511
  >
606
- <SyCheckbox
607
- :model-value="isItemSelected(item)"
608
- density="compact"
609
- hide-details
610
- color="primary"
611
- class="mt-0 pt-0 mr-1"
612
- :title="getItemText(item) as string"
613
- :aria-label="getItemText(item) as string"
614
- @mousedown.stop.prevent="() => selectItem(item)"
615
- />
512
+ <div
513
+ aria-hidden="true"
514
+ inert
515
+ >
516
+ <SyCheckbox
517
+ :model-value="isItemSelected(item)"
518
+ density="compact"
519
+ hide-details
520
+ color="primary"
521
+ class="mt-0 pt-0 mr-1"
522
+ />
523
+ </div>
616
524
  </template>
617
525
  <VListItemTitle>
618
526
  {{ getItemText(item) }}
@@ -649,7 +557,13 @@
649
557
  border: 0;
650
558
  }
651
559
 
560
+ .v-icon.arrow {
561
+ position: absolute;
562
+ right: 10px;
563
+ }
564
+
652
565
  .sy-autocomplete__clear-button {
566
+ position: absolute;
653
567
  background: transparent;
654
568
  border: none;
655
569
  padding: 0;
@@ -657,10 +571,22 @@
657
571
  display: flex;
658
572
  align-items: center;
659
573
  justify-content: center;
574
+ top: 50%;
575
+ transform: translateY(-50%);
576
+ right: 42px;
577
+
578
+ &--with-icon {
579
+ right: 62px;
580
+ }
581
+
582
+ .v-icon {
583
+ position: static;
584
+ }
660
585
  }
661
586
 
662
587
  .sy-autocomplete__clear-icon {
663
- color: rgb(var(--v-theme-iconBase));
588
+ color: rgb(var(--v-theme-primary)) !important;
589
+ opacity: var(--v-medium-emphasis-opacity) !important;
664
590
  }
665
591
 
666
592
  .sy-autocomplete__chip {
@@ -724,12 +650,50 @@ li:hover {
724
650
  }
725
651
 
726
652
  /* Ensure focus styles match selection styles for keyboard navigation (align with SySelect) */
653
+
654
+ /* :deep() is required for keyboard-focused so the style applies to slot content (prepend-item),
655
+ which carries the parent's scoped attribute, not SyAutocomplete's. */
727
656
  .v-list-item:focus-visible,
728
- .v-list-item.keyboard-focused,
729
- li:focus-visible,
730
- li.keyboard-focused {
657
+ li:focus-visible {
731
658
  outline: 2px solid rgb(var(--v-theme-borderAccentPrimary));
732
659
  outline-offset: -2px;
733
660
  background-color: rgb(0 0 0 / 8%);
734
661
  }
662
+
663
+ :deep(.v-list-item.keyboard-focused),
664
+ :deep(li.keyboard-focused) {
665
+ outline: 2px solid rgb(var(--v-theme-borderAccentPrimary));
666
+ outline-offset: -2px;
667
+ background-color: rgb(0 0 0 / 8%);
668
+ }
669
+
670
+ :deep(.error-field .v-icon.arrow),
671
+ :deep(.error-field .v-icon.arrow .v-icon__svg) {
672
+ color: rgb(var(--v-theme-iconSubdued)) !important;
673
+ fill: rgb(var(--v-theme-iconSubdued)) !important;
674
+ }
675
+
676
+ :deep(.error-field .sy-autocomplete__clear-icon .v-icon__svg) {
677
+ fill: rgb(var(--v-theme-iconBase)) !important;
678
+ }
679
+
680
+ :deep(.warning-field .v-icon.arrow),
681
+ :deep(.warning-field .v-icon.arrow .v-icon__svg) {
682
+ color: rgb(var(--v-theme-iconBase)) !important;
683
+ fill: rgb(var(--v-theme-iconBase)) !important;
684
+ }
685
+
686
+ :deep(.warning-field .sy-autocomplete__clear-icon .v-icon__svg) {
687
+ fill: rgb(var(--v-theme-iconBase)) !important;
688
+ }
689
+
690
+ :deep(.success-field .v-icon.arrow),
691
+ :deep(.success-field .v-icon.arrow .v-icon__svg) {
692
+ color: rgb(var(--v-theme-iconBase)) !important;
693
+ fill: rgb(var(--v-theme-iconBase)) !important;
694
+ }
695
+
696
+ :deep(.success-field .sy-autocomplete__clear-icon .v-icon__svg) {
697
+ fill: rgb(var(--v-theme-iconBase)) !important;
698
+ }
735
699
  </style>
@@ -0,0 +1,101 @@
1
+ import { computed, ref, toRef, watch } from 'vue'
2
+ import type { Ref } from 'vue'
3
+ import type { ValidationRule as VuetifyValidationRule } from 'vuetify'
4
+ import { mdiAlertCircle, mdiAlertOutline, mdiCheck } from '@mdi/js'
5
+ import { type ValidationRule } from '@/composables/validation/useValidation'
6
+ import { useValidation, type FieldValidationProps } from '@/composables/unifyValidation/useValidation'
7
+ import { useValidatable } from '@/composables/validation/useValidatable'
8
+
9
+ export function useSyAutocompleteValidation(props: FieldValidationProps) {
10
+ const hasInteracted = ref(false)
11
+ const focused = ref(false)
12
+
13
+ const defaultRules = computed<ValidationRule[]>(() =>
14
+ props.required
15
+ ? [{
16
+ type: 'required',
17
+ options: {
18
+ message: `Le champ ${props.label || 'ce champ'} est requis.`,
19
+ fieldIdentifier: props.label,
20
+ },
21
+ }]
22
+ : [],
23
+ )
24
+
25
+ const { validate, clearValidation, errors, warnings, successes, hasError, hasWarning, hasSuccess } = useValidation({
26
+ modelValue: toRef(props, 'modelValue') as Ref<unknown>,
27
+ readonly: toRef(props, 'readonly') as Ref<boolean>,
28
+ disabled: toRef(props, 'disabled') as Ref<boolean>,
29
+ required: toRef(props, 'required') as Ref<boolean>,
30
+ isValidateOnBlur: toRef(props, 'isValidateOnBlur') as Ref<boolean>,
31
+ showSuccessMessages: toRef(props, 'showSuccessMessages') as Ref<boolean>,
32
+ disableErrorHandling: toRef(props, 'disableErrorHandling') as Ref<boolean>,
33
+ useVuetifyValidation: toRef(props, 'useVuetifyValidation') as Ref<boolean>,
34
+ label: toRef(props, 'label') as Ref<string | undefined>,
35
+ rules: toRef(props, 'rules') as Ref<VuetifyValidationRule[] | undefined>,
36
+ customRules: computed(() => [...defaultRules.value, ...(props.customRules ?? [])]),
37
+ customWarningRules: toRef(props, 'customWarningRules') as Ref<ValidationRule[]>,
38
+ customSuccessRules: toRef(props, 'customSuccessRules') as Ref<ValidationRule[]>,
39
+ errorMessages: toRef(props, 'errorMessages') as Ref<string[] | null | undefined>,
40
+ warningMessages: toRef(props, 'warningMessages') as Ref<string[] | null | undefined>,
41
+ successMessages: toRef(props, 'successMessages') as Ref<string[] | null | undefined>,
42
+ hasErrorProp: toRef(props, 'hasError') as Ref<boolean>,
43
+ hasWarningProp: toRef(props, 'hasWarning') as Ref<boolean>,
44
+ hasSuccessProp: toRef(props, 'hasSuccess') as Ref<boolean>,
45
+ maxErrors: toRef(props, 'maxErrors') as Ref<number>,
46
+ focused,
47
+ })
48
+
49
+ watch([errors, warnings, successes], ([e, w, s]) => {
50
+ if (e.length > 0 || w.length > 0 || s.length > 0) hasInteracted.value = true
51
+ })
52
+
53
+ const markInteracted = () => {
54
+ hasInteracted.value = true
55
+ }
56
+
57
+ const displayErrors = computed(() => hasInteracted.value ? errors.value : [])
58
+ const displayWarnings = computed(() => hasInteracted.value ? warnings.value : [])
59
+ const displaySuccesses = computed(() => hasInteracted.value ? successes.value : [])
60
+ const displayHasError = computed(() => hasInteracted.value && hasError.value)
61
+ const displayHasWarning = computed(() => hasInteracted.value && hasWarning.value)
62
+ const displayHasSuccess = computed(() => hasInteracted.value && hasSuccess.value)
63
+
64
+ const validationIcon = computed(() => {
65
+ if (props.useVuetifyValidation) return null
66
+ if (displayHasError.value) return mdiAlertCircle
67
+ if (displayHasWarning.value) return mdiAlertOutline
68
+ if (displayHasSuccess.value) return mdiCheck
69
+ return null
70
+ })
71
+
72
+ const validateOnSubmit = async () => {
73
+ markInteracted()
74
+ return await validate()
75
+ }
76
+
77
+ const validateOnBlur = () => {
78
+ markInteracted()
79
+ focused.value = false
80
+ validate()
81
+ }
82
+
83
+ useValidatable(validateOnSubmit, clearValidation)
84
+
85
+ return {
86
+ focused,
87
+ hasInteracted,
88
+ markInteracted,
89
+ validate,
90
+ clearValidation,
91
+ validateOnSubmit,
92
+ validateOnBlur,
93
+ displayErrors,
94
+ displayWarnings,
95
+ displaySuccesses,
96
+ displayHasError,
97
+ displayHasWarning,
98
+ displayHasSuccess,
99
+ validationIcon,
100
+ }
101
+ }