@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,6 +1,7 @@
1
1
  import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2
2
  import { mount, flushPromises } from '@vue/test-utils'
3
- import { VMenu } from 'vuetify/components'
3
+ import { defineComponent, ref } from 'vue'
4
+ import { VCheckbox, VDivider, VListItem, VListItemTitle, VMenu } from 'vuetify/components'
4
5
 
5
6
  import SyAutocomplete from '../SyAutocomplete.vue'
6
7
  import SyTextField from '@/components/Customs/SyTextField/SyTextField.vue'
@@ -776,4 +777,763 @@ describe('SyAutocomplete', () => {
776
777
  expect(wrapper.find('.v-messages').exists()).toBe(false)
777
778
  })
778
779
  })
780
+
781
+ describe('validation', () => {
782
+ it('validateOnSubmit returns false and shows error when required field is empty', async () => {
783
+ wrapper.unmount()
784
+ wrapper = mount(SyAutocomplete, {
785
+ props: {
786
+ modelValue: null,
787
+ items,
788
+ label: 'Champ requis',
789
+ textKey: 'text',
790
+ valueKey: 'value',
791
+ required: true,
792
+ },
793
+ })
794
+ const result = await wrapper.vm.validateOnSubmit()
795
+ await flushPromises()
796
+ await wrapper.vm.$nextTick()
797
+ expect(result).toBe(false)
798
+ expect(wrapper.find('.v-messages').text()).toContain('requis')
799
+ })
800
+
801
+ it('validateOnSubmit returns true when required field has a value', async () => {
802
+ wrapper.unmount()
803
+ wrapper = mount(SyAutocomplete, {
804
+ props: {
805
+ modelValue: '1',
806
+ items,
807
+ label: 'Champ valide',
808
+ textKey: 'text',
809
+ valueKey: 'value',
810
+ required: true,
811
+ },
812
+ })
813
+ const result = await wrapper.vm.validateOnSubmit()
814
+ await flushPromises()
815
+ await wrapper.vm.$nextTick()
816
+ expect(result).toBe(true)
817
+ })
818
+
819
+ it('clearValidation removes displayed errors', async () => {
820
+ wrapper.unmount()
821
+ wrapper = mount(SyAutocomplete, {
822
+ props: {
823
+ modelValue: null,
824
+ items,
825
+ label: 'Test clearValidation',
826
+ textKey: 'text',
827
+ valueKey: 'value',
828
+ required: true,
829
+ },
830
+ })
831
+ await wrapper.vm.validateOnSubmit()
832
+ await flushPromises()
833
+ await wrapper.vm.$nextTick()
834
+ expect(wrapper.find('.v-messages').text()).toContain('requis')
835
+
836
+ wrapper.vm.clearValidation()
837
+ await wrapper.vm.$nextTick()
838
+ expect(wrapper.find('.v-messages').text()).not.toContain('requis')
839
+ })
840
+
841
+ it('disableErrorHandling suppresses validation — validateOnSubmit always returns true', async () => {
842
+ wrapper.unmount()
843
+ wrapper = mount(SyAutocomplete, {
844
+ props: {
845
+ modelValue: null,
846
+ items,
847
+ label: 'Test disableErrorHandling',
848
+ textKey: 'text',
849
+ valueKey: 'value',
850
+ required: true,
851
+ disableErrorHandling: true,
852
+ },
853
+ })
854
+ const result = await wrapper.vm.validateOnSubmit()
855
+ await flushPromises()
856
+ await wrapper.vm.$nextTick()
857
+ expect(result).toBe(true)
858
+ expect(wrapper.find('.v-messages').text()).not.toContain('requis')
859
+ })
860
+
861
+ it('validates only on blur when isValidateOnBlur is true', async () => {
862
+ wrapper.unmount()
863
+ const failingRule = {
864
+ type: 'custom',
865
+ options: { validate: () => false, message: 'Erreur isValidateOnBlur' },
866
+ }
867
+ wrapper = mount(SyAutocomplete, {
868
+ props: {
869
+ modelValue: '1',
870
+ items,
871
+ label: 'Test isValidateOnBlur',
872
+ textKey: 'text',
873
+ valueKey: 'value',
874
+ isValidateOnBlur: true,
875
+ customRules: [failingRule],
876
+ },
877
+ })
878
+
879
+ // Force interaction, puis réinitialisation pour repartir d'un état propre
880
+ await wrapper.vm.validateOnSubmit()
881
+ await flushPromises()
882
+ await wrapper.vm.$nextTick()
883
+ wrapper.vm.clearValidation()
884
+ await wrapper.vm.$nextTick()
885
+
886
+ // Changer modelValue ne doit PAS déclencher la validation (isValidateOnBlur: true)
887
+ await wrapper.setProps({ modelValue: '2' })
888
+ await flushPromises()
889
+ await wrapper.vm.$nextTick()
890
+ expect(wrapper.find('.v-messages').text()).not.toContain('Erreur isValidateOnBlur')
891
+
892
+ // Le blur déclenche la validation
893
+ wrapper.vm.checkErrorOnBlur()
894
+ await flushPromises()
895
+ await wrapper.vm.$nextTick()
896
+ expect(wrapper.find('.v-messages').text()).toContain('Erreur isValidateOnBlur')
897
+ })
898
+
899
+ it('displays warning from customWarningRules', async () => {
900
+ wrapper.unmount()
901
+ const warningRule = {
902
+ type: 'custom',
903
+ options: { validate: () => false, warningMessage: 'Avertissement test' },
904
+ }
905
+ wrapper = mount(SyAutocomplete, {
906
+ props: {
907
+ modelValue: '1',
908
+ items,
909
+ label: 'Test warning',
910
+ textKey: 'text',
911
+ valueKey: 'value',
912
+ customWarningRules: [warningRule],
913
+ },
914
+ })
915
+ await wrapper.vm.validateOnSubmit()
916
+ await flushPromises()
917
+ await wrapper.vm.$nextTick()
918
+ expect(wrapper.find('.v-messages').text()).toContain('Avertissement test')
919
+ })
920
+
921
+ it('displays success message from customSuccessRules', async () => {
922
+ wrapper.unmount()
923
+ const successRule = {
924
+ type: 'custom',
925
+ options: { validate: () => true, successMessage: 'Succès test' },
926
+ }
927
+ wrapper = mount(SyAutocomplete, {
928
+ props: {
929
+ modelValue: '1',
930
+ items,
931
+ label: 'Test success',
932
+ textKey: 'text',
933
+ valueKey: 'value',
934
+ customSuccessRules: [successRule],
935
+ },
936
+ })
937
+ await wrapper.vm.validateOnSubmit()
938
+ await flushPromises()
939
+ await wrapper.vm.$nextTick()
940
+ expect(wrapper.find('.v-messages').text()).toContain('Succès test')
941
+ })
942
+
943
+ it('hides success message text when showSuccessMessages is false', async () => {
944
+ wrapper.unmount()
945
+ const successRule = {
946
+ type: 'custom',
947
+ options: { validate: () => true, successMessage: 'Succès test' },
948
+ }
949
+ wrapper = mount(SyAutocomplete, {
950
+ props: {
951
+ modelValue: '1',
952
+ items,
953
+ label: 'Test showSuccessMessages false',
954
+ textKey: 'text',
955
+ valueKey: 'value',
956
+ customSuccessRules: [successRule],
957
+ showSuccessMessages: false,
958
+ },
959
+ })
960
+ await wrapper.vm.validateOnSubmit()
961
+ await flushPromises()
962
+ await wrapper.vm.$nextTick()
963
+ expect(wrapper.find('.v-messages').text()).not.toContain('Succès test')
964
+ })
965
+
966
+ it('forces error state on SyTextField when hasError prop is true', async () => {
967
+ wrapper.unmount()
968
+ wrapper = mount(SyAutocomplete, {
969
+ props: {
970
+ modelValue: '1',
971
+ items,
972
+ label: 'Test hasError prop',
973
+ textKey: 'text',
974
+ valueKey: 'value',
975
+ hasError: true,
976
+ },
977
+ })
978
+ await wrapper.vm.validateOnSubmit()
979
+ await wrapper.vm.$nextTick()
980
+ expect(wrapper.findComponent(SyTextField).props('hasError')).toBe(true)
981
+ })
982
+
983
+ it('forces warning state on SyTextField when hasWarning prop is true', async () => {
984
+ wrapper.unmount()
985
+ wrapper = mount(SyAutocomplete, {
986
+ props: {
987
+ modelValue: '1',
988
+ items,
989
+ label: 'Test hasWarning prop',
990
+ textKey: 'text',
991
+ valueKey: 'value',
992
+ hasWarning: true,
993
+ },
994
+ })
995
+ await wrapper.vm.validateOnSubmit()
996
+ await wrapper.vm.$nextTick()
997
+ expect(wrapper.findComponent(SyTextField).props('hasWarning')).toBe(true)
998
+ })
999
+
1000
+ it('forces success state on SyTextField when hasSuccess prop is true', async () => {
1001
+ wrapper.unmount()
1002
+ wrapper = mount(SyAutocomplete, {
1003
+ props: {
1004
+ modelValue: '1',
1005
+ items,
1006
+ label: 'Test hasSuccess prop',
1007
+ textKey: 'text',
1008
+ valueKey: 'value',
1009
+ hasSuccess: true,
1010
+ },
1011
+ })
1012
+ await wrapper.vm.validateOnSubmit()
1013
+ await wrapper.vm.$nextTick()
1014
+ expect(wrapper.findComponent(SyTextField).props('hasSuccess')).toBe(true)
1015
+ })
1016
+
1017
+ it('displays errorMessages injected by the parent', async () => {
1018
+ wrapper.unmount()
1019
+ wrapper = mount(SyAutocomplete, {
1020
+ props: {
1021
+ modelValue: null,
1022
+ items,
1023
+ label: 'Test errorMessages',
1024
+ textKey: 'text',
1025
+ valueKey: 'value',
1026
+ errorMessages: ['Erreur externe'],
1027
+ },
1028
+ })
1029
+ await wrapper.vm.validateOnSubmit()
1030
+ await flushPromises()
1031
+ await wrapper.vm.$nextTick()
1032
+ expect(wrapper.find('.v-messages').text()).toContain('Erreur externe')
1033
+ })
1034
+
1035
+ it('displays warningMessages injected by the parent', async () => {
1036
+ wrapper.unmount()
1037
+ wrapper = mount(SyAutocomplete, {
1038
+ props: {
1039
+ modelValue: null,
1040
+ items,
1041
+ label: 'Test warningMessages',
1042
+ textKey: 'text',
1043
+ valueKey: 'value',
1044
+ warningMessages: ['Avertissement externe'],
1045
+ },
1046
+ })
1047
+ await wrapper.vm.validateOnSubmit()
1048
+ await flushPromises()
1049
+ await wrapper.vm.$nextTick()
1050
+ expect(wrapper.find('.v-messages').text()).toContain('Avertissement externe')
1051
+ })
1052
+
1053
+ it('displays successMessages injected by the parent', async () => {
1054
+ wrapper.unmount()
1055
+ wrapper = mount(SyAutocomplete, {
1056
+ props: {
1057
+ modelValue: null,
1058
+ items,
1059
+ label: 'Test successMessages',
1060
+ textKey: 'text',
1061
+ valueKey: 'value',
1062
+ successMessages: ['Succès externe'],
1063
+ },
1064
+ })
1065
+ await wrapper.vm.validateOnSubmit()
1066
+ await flushPromises()
1067
+ await wrapper.vm.$nextTick()
1068
+ expect(wrapper.find('.v-messages').text()).toContain('Succès externe')
1069
+ })
1070
+ })
1071
+
1072
+ describe('slot prepend-item', () => {
1073
+ it('reçoit le focus en premier à l\'ouverture du menu', async () => {
1074
+ wrapper.unmount()
1075
+ wrapper = mount(SyAutocomplete, {
1076
+ props: {
1077
+ modelValue: null,
1078
+ items,
1079
+ label: 'Test prepend focus',
1080
+ textKey: 'text',
1081
+ valueKey: 'value',
1082
+ menuId,
1083
+ },
1084
+ slots: {
1085
+ 'prepend-item': '<li class="v-list-item prepend-item-btn">Tous</li>',
1086
+ },
1087
+ attachTo: document.body,
1088
+ })
1089
+
1090
+ const input = wrapper.find('input')
1091
+ await input.trigger('click')
1092
+ await flushPromises()
1093
+ await wrapper.vm.$nextTick()
1094
+ await wrapper.vm.$nextTick()
1095
+ await wrapper.vm.$nextTick()
1096
+
1097
+ const prependEl = document.body.querySelector('.prepend-item-btn')
1098
+ expect(prependEl?.classList.contains('keyboard-focused')).toBe(true)
1099
+ })
1100
+
1101
+ it('ArrowDown depuis le prepend va au premier item', async () => {
1102
+ wrapper.unmount()
1103
+ wrapper = mount(SyAutocomplete, {
1104
+ props: {
1105
+ modelValue: null,
1106
+ items,
1107
+ label: 'Test prepend arrow',
1108
+ textKey: 'text',
1109
+ valueKey: 'value',
1110
+ menuId,
1111
+ },
1112
+ slots: {
1113
+ 'prepend-item': '<li class="v-list-item prepend-item-btn">Tous</li>',
1114
+ },
1115
+ attachTo: document.body,
1116
+ })
1117
+
1118
+ const input = wrapper.find('input')
1119
+ await input.trigger('click')
1120
+ await flushPromises()
1121
+ await wrapper.vm.$nextTick()
1122
+ await wrapper.vm.$nextTick()
1123
+ await wrapper.vm.$nextTick()
1124
+
1125
+ const inputEl = document.getElementById(`${menuId}-input`) as HTMLInputElement
1126
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
1127
+ await flushPromises()
1128
+ await wrapper.vm.$nextTick()
1129
+
1130
+ const firstOption = document.body.querySelector(`#${menuId}-option-0`)
1131
+ expect(firstOption?.classList.contains('keyboard-focused')).toBe(true)
1132
+ expect(document.body.querySelector('.prepend-item-btn')?.classList.contains('keyboard-focused')).toBe(false)
1133
+ })
1134
+
1135
+ it('ArrowUp depuis le premier item revient au prepend', async () => {
1136
+ wrapper.unmount()
1137
+ wrapper = mount(SyAutocomplete, {
1138
+ props: {
1139
+ modelValue: null,
1140
+ items,
1141
+ label: 'Test prepend arrow up',
1142
+ textKey: 'text',
1143
+ valueKey: 'value',
1144
+ menuId,
1145
+ },
1146
+ slots: {
1147
+ 'prepend-item': '<li class="v-list-item prepend-item-btn">Tous</li>',
1148
+ },
1149
+ attachTo: document.body,
1150
+ })
1151
+
1152
+ const input = wrapper.find('input')
1153
+ await input.trigger('click')
1154
+ await flushPromises()
1155
+ await wrapper.vm.$nextTick()
1156
+ await wrapper.vm.$nextTick()
1157
+ await wrapper.vm.$nextTick()
1158
+
1159
+ const inputEl = document.getElementById(`${menuId}-input`) as HTMLInputElement
1160
+
1161
+ // ArrowDown → premier item
1162
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
1163
+ await flushPromises()
1164
+ await wrapper.vm.$nextTick()
1165
+
1166
+ // ArrowUp → retour au prepend
1167
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp', bubbles: true }))
1168
+ await flushPromises()
1169
+ await wrapper.vm.$nextTick()
1170
+ await wrapper.vm.$nextTick()
1171
+
1172
+ expect(document.body.querySelector('.prepend-item-btn')?.classList.contains('keyboard-focused')).toBe(true)
1173
+ })
1174
+
1175
+ it('Enter sur le prepend déclenche un click sur l\'élément', async () => {
1176
+ wrapper.unmount()
1177
+ let clicked = false
1178
+ wrapper = mount(SyAutocomplete, {
1179
+ props: {
1180
+ modelValue: null,
1181
+ items,
1182
+ label: 'Test prepend enter',
1183
+ textKey: 'text',
1184
+ valueKey: 'value',
1185
+ menuId,
1186
+ },
1187
+ slots: {
1188
+ 'prepend-item': `<li class="v-list-item prepend-item-btn">Tous</li>`,
1189
+ },
1190
+ attachTo: document.body,
1191
+ })
1192
+
1193
+ // Ajouter un listener click sur le bouton après montage
1194
+ const input = wrapper.find('input')
1195
+ await input.trigger('click')
1196
+ await flushPromises()
1197
+ await wrapper.vm.$nextTick()
1198
+ await wrapper.vm.$nextTick()
1199
+
1200
+ const prependEl = document.body.querySelector('.prepend-item-btn')
1201
+ prependEl?.addEventListener('click', () => {
1202
+ clicked = true
1203
+ })
1204
+
1205
+ const inputEl = document.getElementById(`${menuId}-input`) as HTMLInputElement
1206
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))
1207
+ await flushPromises()
1208
+ await wrapper.vm.$nextTick()
1209
+
1210
+ expect(clicked).toBe(true)
1211
+ })
1212
+
1213
+ it('Enter sur un VListItem du slot prepend-item active son @click', async () => {
1214
+ wrapper.unmount()
1215
+
1216
+ const HostComponent = defineComponent({
1217
+ components: { SyAutocomplete, VCheckbox, VDivider, VListItem, VListItemTitle },
1218
+ setup() {
1219
+ const selectedValues = ref<string[]>([])
1220
+ const toggleAll = () => {
1221
+ selectedValues.value = selectedValues.value.length === items.length
1222
+ ? []
1223
+ : items.map(item => item.value as string)
1224
+ }
1225
+
1226
+ return {
1227
+ items,
1228
+ menuId,
1229
+ selectedValues,
1230
+ toggleAll,
1231
+ }
1232
+ },
1233
+ template: `
1234
+ <SyAutocomplete
1235
+ v-model="selectedValues"
1236
+ :items="items"
1237
+ label="Test prepend enter on VListItem"
1238
+ text-key="text"
1239
+ value-key="value"
1240
+ :menu-id="menuId"
1241
+ multiple
1242
+ >
1243
+ <template #prepend-item>
1244
+ <VListItem
1245
+ class="prepend-item-btn"
1246
+ @mousedown.prevent
1247
+ @click="toggleAll"
1248
+ >
1249
+ <template #prepend>
1250
+ <VCheckbox
1251
+ :model-value="selectedValues.length === items.length"
1252
+ :indeterminate="selectedValues.length > 0 && selectedValues.length < items.length"
1253
+ density="compact"
1254
+ hide-details
1255
+ color="primary"
1256
+ class="mt-0 pt-0 mr-1"
1257
+ />
1258
+ </template>
1259
+ <VListItemTitle>Tous</VListItemTitle>
1260
+ </VListItem>
1261
+ <VDivider />
1262
+ </template>
1263
+ </SyAutocomplete>
1264
+ `,
1265
+ })
1266
+
1267
+ const hostWrapper = mount(HostComponent, {
1268
+ attachTo: document.body,
1269
+ })
1270
+
1271
+ const input = hostWrapper.find('input')
1272
+ await input.trigger('click')
1273
+ await flushPromises()
1274
+ await hostWrapper.vm.$nextTick()
1275
+ await hostWrapper.vm.$nextTick()
1276
+
1277
+ const inputEl = document.getElementById(`${menuId}-input`) as HTMLInputElement
1278
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))
1279
+ await flushPromises()
1280
+ await hostWrapper.vm.$nextTick()
1281
+
1282
+ expect((hostWrapper.vm as { selectedValues: string[] }).selectedValues).toEqual(['1', '2', '3'])
1283
+
1284
+ hostWrapper.unmount()
1285
+ })
1286
+
1287
+ it('rend le contenu du slot dans le listbox', async () => {
1288
+ wrapper.unmount()
1289
+ wrapper = mount(SyAutocomplete, {
1290
+ props: {
1291
+ modelValue: null,
1292
+ items,
1293
+ label: 'Test prepend-item',
1294
+ textKey: 'text',
1295
+ valueKey: 'value',
1296
+ menuId,
1297
+ },
1298
+ slots: {
1299
+ 'prepend-item': '<button class="prepend-item-btn">Tous</button>',
1300
+ },
1301
+ attachTo: document.body,
1302
+ })
1303
+
1304
+ const input = wrapper.find('input')
1305
+ await input.trigger('click')
1306
+ await flushPromises()
1307
+ await wrapper.vm.$nextTick()
1308
+ expect(isMenuOverlayActive()).toBe(true)
1309
+
1310
+ // Le slot est dans le listbox
1311
+ const listbox = document.body.querySelector(`#${menuId}`)
1312
+ expect(listbox!.querySelector('.prepend-item-btn')).not.toBeNull()
1313
+
1314
+ // Il n'y a pas de container prepend séparé
1315
+ expect(document.body.querySelector(`#${menuId}-prepend`)).toBeNull()
1316
+ })
1317
+
1318
+ it('n\'affiche pas le contenu du slot quand le menu est fermé', async () => {
1319
+ wrapper.unmount()
1320
+ wrapper = mount(SyAutocomplete, {
1321
+ props: {
1322
+ modelValue: null,
1323
+ items,
1324
+ label: 'Test prepend-item fermé',
1325
+ textKey: 'text',
1326
+ valueKey: 'value',
1327
+ menuId,
1328
+ },
1329
+ slots: {
1330
+ 'prepend-item': '<button class="prepend-item-btn">Tous</button>',
1331
+ },
1332
+ attachTo: document.body,
1333
+ })
1334
+
1335
+ expect(isMenuOverlayActive()).toBe(false)
1336
+ expect(document.body.querySelector('.prepend-item-btn')).toBeNull()
1337
+ })
1338
+ })
1339
+
1340
+ it('does not open menu when readonly', async () => {
1341
+ wrapper.unmount()
1342
+ wrapper = mount(SyAutocomplete, {
1343
+ props: {
1344
+ modelValue: null,
1345
+ items,
1346
+ label: 'Test readonly',
1347
+ textKey: 'text',
1348
+ valueKey: 'value',
1349
+ readonly: true,
1350
+ menuId,
1351
+ },
1352
+ attachTo: document.body,
1353
+ })
1354
+ const input = wrapper.find('input')
1355
+ await input.trigger('click')
1356
+ await flushPromises()
1357
+ await wrapper.vm.$nextTick()
1358
+ expect(isMenuOverlayActive()).toBe(false)
1359
+ })
1360
+
1361
+ it('emits full object when returnObject is true', async () => {
1362
+ wrapper.unmount()
1363
+ wrapper = mount(SyAutocomplete, {
1364
+ props: {
1365
+ modelValue: null,
1366
+ items,
1367
+ label: 'Test returnObject true',
1368
+ textKey: 'text',
1369
+ valueKey: 'value',
1370
+ returnObject: true,
1371
+ },
1372
+ })
1373
+ wrapper.vm.selectItem(items[0])
1374
+ await wrapper.vm.$nextTick()
1375
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy()
1376
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([items[0]])
1377
+ })
1378
+
1379
+ it('emits value key when returnObject is false', async () => {
1380
+ wrapper.vm.selectItem(items[0])
1381
+ await wrapper.vm.$nextTick()
1382
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['1'])
1383
+ })
1384
+
1385
+ it('shows custom noDataText when list is empty', async () => {
1386
+ wrapper.unmount()
1387
+ wrapper = mount(SyAutocomplete, {
1388
+ props: {
1389
+ modelValue: null,
1390
+ items: [],
1391
+ label: 'Test noDataText',
1392
+ textKey: 'text',
1393
+ valueKey: 'value',
1394
+ noDataText: 'Pas de résultats disponibles',
1395
+ menuId,
1396
+ },
1397
+ attachTo: document.body,
1398
+ })
1399
+ const input = wrapper.find('input')
1400
+ await input.trigger('click')
1401
+ await flushPromises()
1402
+ await wrapper.vm.$nextTick()
1403
+ const listItems = document.body.querySelectorAll(`#${menuId} .v-list-item`)
1404
+ const texts = Array.from(listItems).map(el => el.textContent?.trim())
1405
+ expect(texts.some(t => t?.includes('Pas de résultats disponibles'))).toBe(true)
1406
+ })
1407
+
1408
+ describe('filter and search', () => {
1409
+ it('filters items client-side based on input', async () => {
1410
+ const input = wrapper.find('input')
1411
+ await input.trigger('click')
1412
+ await flushPromises()
1413
+ await wrapper.vm.$nextTick()
1414
+
1415
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', 'Option 1')
1416
+ await flushPromises()
1417
+ await wrapper.vm.$nextTick()
1418
+
1419
+ const listItems = document.body.querySelectorAll(`#${menuId} .v-list-item`)
1420
+ expect(listItems).toHaveLength(1)
1421
+ expect(listItems[0]!.textContent?.trim()).toContain('Option 1')
1422
+ })
1423
+
1424
+ it('shows all items when filter is disabled', async () => {
1425
+ wrapper.unmount()
1426
+ wrapper = mount(SyAutocomplete, {
1427
+ props: {
1428
+ modelValue: null,
1429
+ items,
1430
+ label: 'Test filter false',
1431
+ textKey: 'text',
1432
+ valueKey: 'value',
1433
+ filter: false,
1434
+ menuId,
1435
+ },
1436
+ attachTo: document.body,
1437
+ })
1438
+ const input = wrapper.find('input')
1439
+ await input.trigger('click')
1440
+ await flushPromises()
1441
+ await wrapper.vm.$nextTick()
1442
+
1443
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', 'Option 1')
1444
+ await flushPromises()
1445
+ await wrapper.vm.$nextTick()
1446
+
1447
+ const listItems = document.body.querySelectorAll(`#${menuId} .v-list-item`)
1448
+ expect(listItems).toHaveLength(3)
1449
+ })
1450
+
1451
+ it('filters using plainTextKey instead of textKey when provided', async () => {
1452
+ wrapper.unmount()
1453
+ const specialItems = [
1454
+ { text: '★ Alpha', plain: 'Alpha', value: 'alpha' },
1455
+ { text: '★ Beta', plain: 'Beta', value: 'beta' },
1456
+ ]
1457
+ wrapper = mount(SyAutocomplete, {
1458
+ props: {
1459
+ modelValue: null,
1460
+ items: specialItems,
1461
+ label: 'Test plainTextKey',
1462
+ textKey: 'text',
1463
+ valueKey: 'value',
1464
+ plainTextKey: 'plain',
1465
+ menuId,
1466
+ },
1467
+ attachTo: document.body,
1468
+ })
1469
+
1470
+ // '★' est dans textKey mais pas dans plainTextKey → aucun résultat
1471
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', '★')
1472
+ await flushPromises()
1473
+ await wrapper.vm.$nextTick()
1474
+ const noResults = document.body.querySelectorAll(`#${menuId} [role="option"]`)
1475
+ expect(noResults).toHaveLength(0)
1476
+
1477
+ // 'Alpha' est dans plainTextKey → 1 résultat
1478
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', 'Alpha')
1479
+ await flushPromises()
1480
+ await wrapper.vm.$nextTick()
1481
+ const oneResult = document.body.querySelectorAll(`#${menuId} [role="option"]`)
1482
+ expect(oneResult).toHaveLength(1)
1483
+ })
1484
+
1485
+ it('emits search event after debounce delay', async () => {
1486
+ wrapper.unmount()
1487
+ wrapper = mount(SyAutocomplete, {
1488
+ props: {
1489
+ modelValue: null,
1490
+ items,
1491
+ label: 'Test search event',
1492
+ textKey: 'text',
1493
+ valueKey: 'value',
1494
+ debounce: 0,
1495
+ menuId,
1496
+ },
1497
+ attachTo: document.body,
1498
+ })
1499
+ // syncSearchFromValue() sets suppressMenuOpen=true on mount; first input clears the flag
1500
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', 'clear-suppress')
1501
+ await wrapper.vm.$nextTick()
1502
+ await flushPromises()
1503
+ // Second input actually triggers the search event
1504
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', 'test')
1505
+ await wrapper.vm.$nextTick()
1506
+ await flushPromises()
1507
+ const emitted = wrapper.emitted('search')
1508
+ expect(emitted).toBeTruthy()
1509
+ expect(emitted?.[emitted.length - 1]).toEqual(['test'])
1510
+ })
1511
+
1512
+ it('respects custom debounce delay', async () => {
1513
+ wrapper.unmount()
1514
+ wrapper = mount(SyAutocomplete, {
1515
+ props: {
1516
+ modelValue: null,
1517
+ items,
1518
+ label: 'Test debounce',
1519
+ textKey: 'text',
1520
+ valueKey: 'value',
1521
+ debounce: 50,
1522
+ menuId,
1523
+ },
1524
+ attachTo: document.body,
1525
+ })
1526
+ // First input clears the suppressMenuOpen flag set during initialization
1527
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', 'clear-suppress')
1528
+ await wrapper.vm.$nextTick()
1529
+ // Second input triggers debounced search
1530
+ wrapper.findComponent(SyTextField).vm.$emit('update:modelValue', 'query')
1531
+ await wrapper.vm.$nextTick()
1532
+ // Before debounce expires: pas encore émis
1533
+ expect(wrapper.emitted('search')).toBeFalsy()
1534
+ // After debounce: émis
1535
+ await new Promise(resolve => setTimeout(resolve, 60))
1536
+ expect(wrapper.emitted('search')).toBeTruthy()
1537
+ })
1538
+ })
779
1539
  })