@cnamts/synapse 1.0.26 → 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 (253) hide show
  1. package/dist/{AutocompleteFilter-BPR-a55G.js → AutocompleteFilter-C9eLKyW8.js} +3 -3
  2. package/dist/{DateFilter-CknrJWs2.js → DateFilter-y-GLkAkn.js} +8 -8
  3. package/dist/{NumberFilter-DJ-yNlzv.js → NumberFilter-DN6hIBS7.js} +1 -1
  4. package/dist/{PeriodFilter-CiB5Oa9Z.js → PeriodFilter-MoUUp9qS.js} +1 -1
  5. package/dist/{SelectFilter-EiafX97M.js → SelectFilter-bCbrdLmu.js} +1 -1
  6. package/dist/{TextFilter-BzOmpdxj.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 -353
  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 +9 -10
  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 +3 -3
  16. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +3 -3
  17. package/dist/components/Customs/SyIconButton/SyIconButton.d.ts +18 -0
  18. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +20 -38
  19. package/dist/components/Customs/SyRadioGroup/composables/useSyRadioGroupValidation.d.ts +50 -0
  20. package/dist/components/Customs/SyTextField/SyTextField.d.ts +6 -6
  21. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +147 -136
  22. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +62 -54
  23. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +27 -24
  24. package/dist/components/DatePicker/composables/index.d.ts +1 -0
  25. package/dist/components/DatePicker/composables/useDatePickerValidationBridge.d.ts +51 -0
  26. package/dist/components/MonthPicker/MonthPicker.d.ts +23 -23
  27. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +23 -23
  28. package/dist/components/NirField/NirField.d.ts +56 -56
  29. package/dist/components/PasswordField/PasswordField.d.ts +3 -3
  30. package/dist/components/PeriodField/PeriodField.d.ts +236 -212
  31. package/dist/components/PhoneField/PhoneField.d.ts +23 -23
  32. package/dist/components/SyTextArea/SyTextArea.d.ts +25 -15
  33. package/dist/components/SyTextArea/composables/useSyTextAreaValidation.d.ts +20 -0
  34. package/dist/components/SyTextArea/locales.d.ts +1 -0
  35. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +1 -0
  36. package/dist/components/Tables/SyTable/SyTable.d.ts +1 -0
  37. package/dist/components/Tables/common/SyTablePagination.d.ts +25 -25
  38. package/dist/components/Tables/common/types.d.ts +2 -0
  39. package/dist/components/index.d.ts +1 -0
  40. package/dist/composables/unifyValidation/documentationValidationProps.d.ts +160 -160
  41. package/dist/composables/unifyValidation/useValidation.d.ts +16 -14
  42. package/dist/design-system-v3.js +81 -80
  43. package/dist/designTokens/tokens/amelipro/apContextual.d.ts +6 -6
  44. package/dist/designTokens/tokens/amelipro/apDarkTheme.d.ts +3 -1
  45. package/dist/designTokens/tokens/amelipro/apLightTheme.d.ts +53 -100
  46. package/dist/designTokens/tokens/baseContextualTokens.d.ts +0 -6
  47. package/dist/designTokens/tokens/baseTokens.d.ts +232 -0
  48. package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +6 -6
  49. package/dist/designTokens/tokens/cnam/cnamDarkTheme.d.ts +1 -1
  50. package/dist/designTokens/tokens/cnam/cnamLightTheme.d.ts +57 -101
  51. package/dist/designTokens/tokens/pa/paContextual.d.ts +0 -6
  52. package/dist/designTokens/tokens/pa/paDarkTheme.d.ts +1 -1
  53. package/dist/designTokens/tokens/pa/paLightTheme.d.ts +53 -97
  54. package/dist/designTokens/tokens/pa/paSemantic.d.ts +1 -0
  55. package/dist/designTokens/tokens/semanticTokens.d.ts +112 -0
  56. package/dist/main-CI6Q9nmO.js +39234 -0
  57. package/dist/synapse.css +1 -1
  58. package/dist/vuetifyConfig.js +208 -72
  59. package/package.json +4 -2
  60. package/src/assets/overrides/_icons.scss +5 -4
  61. package/src/assets/overrides/_otp.scss +4 -4
  62. package/src/assets/overrides/_typography.scss +2 -1
  63. package/src/assets/overrides/_utilities.scss +1 -42
  64. package/src/components/ChipList/ChipList.vue +30 -18
  65. package/src/components/ChipList/tests/chipList.spec.ts +4 -4
  66. package/src/components/CopyBtn/CopyBtn.vue +2 -2
  67. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.stories.ts +4 -0
  68. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.vue +7 -6
  69. package/src/components/Customs/Selects/SelectBtnField/tests/SelectBtnField.spec.ts +223 -0
  70. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +283 -351
  71. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +182 -218
  72. package/src/components/Customs/Selects/SyAutocomplete/composables/useSyAutocompleteValidation.ts +101 -0
  73. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +761 -1
  74. package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +3 -1
  75. package/src/components/Customs/Selects/SyAutocomplete/utils/useKeyboardHandler.ts +79 -5
  76. package/src/components/Customs/Selects/SyAutocomplete/validation/Validation.stories.ts +1029 -0
  77. package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +9 -491
  78. package/src/components/Customs/Selects/SySelect/SySelect.vue +46 -79
  79. package/src/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.ts +3 -0
  80. package/src/components/Customs/Selects/SySelect/composables/useSySelectValidation.ts +64 -0
  81. package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +196 -0
  82. package/src/components/Customs/Selects/SySelect/validation/Validation.stories.ts +1026 -0
  83. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +18 -7
  84. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +2 -2
  85. package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +8 -8
  86. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +8 -8
  87. package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +1 -1
  88. package/src/components/Customs/SyIcon/accessibilite/Accessibility.mdx +0 -6
  89. package/src/components/Customs/SyIcon/utils/tests/iconUtils.spec.ts +107 -0
  90. package/src/components/Customs/SyRadioGroup/SyRadioGroup.mdx +2 -2
  91. package/src/components/Customs/SyRadioGroup/SyRadioGroup.stories.ts +395 -200
  92. package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +82 -127
  93. package/src/components/Customs/SyRadioGroup/composables/useSyRadioGroupValidation.ts +127 -0
  94. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.a11y.spec.ts +93 -1
  95. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.spec.ts +146 -9
  96. package/src/components/Customs/SyRadioGroup/tests/SyRadioGroup.visual.cy.ts +165 -0
  97. package/src/components/Customs/SyRadioGroup/validation/Validation.stories.ts +773 -0
  98. package/src/components/Customs/SyTabs/config.ts +3 -3
  99. package/src/components/Customs/SyTabs/tests/SyTabs.spec.ts +265 -0
  100. package/src/components/Customs/SyTabs/tests/useTabTransition.spec.ts +188 -0
  101. package/src/components/Customs/SyTextField/SyTextField.stories.ts +10 -29
  102. package/src/components/Customs/SyTextField/SyTextField.vue +23 -15
  103. package/src/components/DataList/DataList.stories.ts +1 -1
  104. package/src/components/DataListItem/tests/DataListItem.spec.ts +3 -1
  105. package/src/components/DatePicker/CalendarMode/DatePicker.vue +37 -142
  106. package/src/components/DatePicker/CalendarMode/tests/DatePicker.coverage.spec.ts +156 -0
  107. package/src/components/DatePicker/CalendarMode/tests/DatePicker.spec.ts +495 -4
  108. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +47 -66
  109. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +206 -0
  110. package/src/components/DatePicker/ComplexDatePicker/tests/bridge-integration.regression.spec.ts +210 -0
  111. package/src/components/DatePicker/ComplexDatePicker/tests/calendar-navigation.regression.spec.ts +214 -0
  112. package/src/components/DatePicker/ComplexDatePicker/tests/validation-cross.regression.spec.ts +194 -0
  113. package/src/components/DatePicker/ComplexDatePicker/tests/validation-success-messages.regression.spec.ts +83 -0
  114. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +129 -54
  115. package/src/components/DatePicker/DateTextInput/tests/DateTextInput.spec.ts +320 -0
  116. package/src/components/DatePicker/composables/index.ts +1 -0
  117. package/src/components/DatePicker/composables/tests/useCalendarKeyboardNavigation.spec.ts +360 -0
  118. package/src/components/DatePicker/composables/tests/useDatePickerValidationBridge.spec.ts +129 -0
  119. package/src/components/DatePicker/composables/useDatePickerValidationBridge.ts +205 -0
  120. package/src/components/DatePicker/docExamples/BidirectionalComplexValidation.vue +1 -1
  121. package/src/components/DatePicker/docExamples/DatePickerBidirectionalValidation.vue +1 -1
  122. package/src/components/DatePicker/tests/exposed-methods.coverage.spec.ts +75 -0
  123. package/src/components/DialogBox/DialogBox.vue +1 -1
  124. package/src/components/FileList/UploadItem/UploadItem.vue +4 -4
  125. package/src/components/FileUpload/FileUpload.vue +2 -2
  126. package/src/components/FileUpload/FileUploadContent.vue +1 -1
  127. package/src/components/FilterInline/FilterInline.mdx +2 -2
  128. package/src/components/FilterSideBar/FilterSideBar.stories.ts +1 -1
  129. package/src/components/FilterSideBar/FilterSideBar.vue +2 -2
  130. package/src/components/FooterBar/FooterBar.vue +7 -7
  131. package/src/components/FranceConnectBtn/FranceConnectBtn.vue +1 -1
  132. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +2 -2
  133. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +7 -7
  134. package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +2 -2
  135. package/src/components/HeaderLoading/tests/HeaderLoading.spec.ts +87 -8
  136. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +3 -3
  137. package/src/components/HeaderNavigationBar/HorizontalNavbar/tests/HorizontalNavbar.spec.ts +589 -0
  138. package/src/components/HeaderToolbar/tests/HeaderToolBar.spec.ts +153 -1
  139. package/src/components/HeaderToolbar/tests/useMobileRightMenu.spec.ts +258 -0
  140. package/src/components/LogoBrandSection/tests/LogoBrandSection.spec.ts +2 -2
  141. package/src/components/LogoBrandSection/tests/__snapshots__/LogoBrandSection.spec.ts.snap +1 -1
  142. package/src/components/LunarCalendar/tests/useLunarCalendarRules.spec.ts +184 -0
  143. package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +3 -3
  144. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +1 -1
  145. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +2 -2
  146. package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +1 -1
  147. package/src/components/NirField/NirField.vue +3 -3
  148. package/src/components/NotificationBar/Notification/Notification.vue +12 -12
  149. package/src/components/NotificationBar/NotificationBar.stories.ts +8 -8
  150. package/src/components/PaginatedTable/Pagination.vue +2 -2
  151. package/src/components/PasswordField/PasswordField.vue +8 -8
  152. package/src/components/PasswordField/tests/PasswordField.spec.ts +3 -3
  153. package/src/components/RangeField/RangeSlider/RangeSlider.vue +2 -2
  154. package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +1 -1
  155. package/src/components/StatusPage/tests/StatusPage.spec.ts +149 -0
  156. package/src/components/SubHeader/SubHeader.vue +1 -1
  157. package/src/components/SyAlert/SyAlert.vue +23 -23
  158. package/src/components/SyTextArea/SyTextArea.stories.ts +177 -131
  159. package/src/components/SyTextArea/SyTextArea.vue +235 -83
  160. package/src/components/SyTextArea/composables/useSyTextAreaValidation.ts +81 -0
  161. package/src/components/SyTextArea/locales.ts +1 -0
  162. package/src/components/SyTextArea/tests/SyTextArea.spec.ts +449 -1
  163. package/src/components/SyTextArea/useDefaultValidationRules.ts +2 -7
  164. package/src/components/SyTextArea/validation/Validation.stories.ts +856 -0
  165. package/src/components/TableToolbar/TableToolbar.vue +6 -6
  166. package/src/components/TableToolbar/accessibilite/Accessibility.mdx +81 -7
  167. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +163 -0
  168. package/src/components/Tables/SyServerTable/SyServerTable.vue +2 -1
  169. package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +67 -0
  170. package/src/components/Tables/SyTable/SyTable.stories.ts +94 -0
  171. package/src/components/Tables/SyTable/SyTable.vue +2 -1
  172. package/src/components/Tables/SyTable/tests/SyTable.spec.ts +64 -0
  173. package/src/components/Tables/common/TableHeader.vue +2 -2
  174. package/src/components/Tables/common/filters/logics/tests/NumberFilterLogic.spec.ts +176 -0
  175. package/src/components/Tables/common/filters/logics/tests/SelectFilterLogic.spec.ts +111 -0
  176. package/src/components/Tables/common/tableStyles.scss +6 -6
  177. package/src/components/Tables/common/types.ts +2 -0
  178. package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +2 -0
  179. package/src/components/index.ts +1 -0
  180. package/src/composables/date/tests/useDateFormatDayjs.spec.ts +31 -0
  181. package/src/composables/date/tests/useHolidayDay.spec.ts +109 -0
  182. package/src/composables/rules/tests/useFieldValidation.spec.ts +374 -0
  183. package/src/composables/tests/useError.spec.ts +30 -0
  184. package/src/composables/tests/useFormFieldErrorHandling.spec.ts +234 -0
  185. package/src/composables/unifyValidation/documentationValidationProps.ts +5 -5
  186. package/src/composables/unifyValidation/tests/documentationValidationProps.spec.ts +177 -0
  187. package/src/composables/unifyValidation/tests/useCustomValidation.spec.ts +30 -0
  188. package/src/composables/unifyValidation/tests/useValidation.spec.ts +6 -2
  189. package/src/composables/unifyValidation/useCustomValidation.ts +19 -9
  190. package/src/composables/unifyValidation/useValidation.ts +18 -21
  191. package/src/composables/useFilterable/useFilterable.spec.ts +42 -0
  192. package/src/composables/useFilterable/useFilterable.ts +11 -7
  193. package/src/composables/useFormFieldErrorHandling.ts +2 -2
  194. package/src/composantsVuetify/VBtn/VBtn.mdx +9 -39
  195. package/src/composantsVuetify/VBtn/v-btn.stories.ts +26 -86
  196. package/src/designTokens/tokens/amelipro/apContextual.ts +6 -0
  197. package/src/designTokens/tokens/amelipro/apDarkTheme.ts +2 -2
  198. package/src/designTokens/tokens/amelipro/apLightTheme.ts +72 -103
  199. package/src/designTokens/tokens/amelipro/apSemantic.ts +1 -1
  200. package/src/designTokens/tokens/baseContextualTokens.ts +1 -6
  201. package/src/designTokens/tokens/baseTokens.ts +232 -0
  202. package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -0
  203. package/src/designTokens/tokens/cnam/cnamDarkTheme.ts +2 -2
  204. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +76 -104
  205. package/src/designTokens/tokens/pa/paDarkTheme.ts +2 -2
  206. package/src/designTokens/tokens/pa/paLightTheme.ts +73 -99
  207. package/src/designTokens/tokens/pa/paSemantic.ts +2 -0
  208. package/src/designTokens/tokens/semanticTokens.ts +114 -0
  209. package/src/stories/Components/Components.stories.ts +7 -3
  210. package/src/stories/DesignTokens/ColorIntegrationExample.vue +2 -3
  211. package/src/stories/DesignTokens/Colors.mdx +6 -8
  212. package/src/stories/DesignTokens/colors.stories.ts +244 -1081
  213. package/src/utils/amelipro/toKebabCase/tests/toKebabCase.spec.ts +52 -0
  214. package/src/utils/formatNir/tests/formatNir.spec.ts +34 -0
  215. package/src/utils/tests/insertAt.spec.ts +44 -0
  216. package/dist/apLightTheme-DS0Uy44H.js +0 -954
  217. package/dist/components/RatingPicker/tests/RatingPicker.a11y.spect.d.ts +0 -1
  218. package/dist/main-BsJ9ec3i.js +0 -38954
  219. package/src/components/BackBtn/tests/__snapshots__/back-btn-custom-bg.snap.png +0 -0
  220. package/src/components/BackBtn/tests/__snapshots__/back-btn-dark-mode.snap.png +0 -0
  221. package/src/components/BackBtn/tests/__snapshots__/back-btn-default.snap.png +0 -0
  222. package/src/components/BackBtn/tests/__snapshots__/back-btn-no-icon.snap.png +0 -0
  223. package/src/components/DatePicker/CalendarMode/tests/DatePicker.events.spec.ts +0 -178
  224. package/src/components/DialogBox/tests/__snapshots__/dialog-box-custom-texts.snap.png +0 -0
  225. package/src/components/DialogBox/tests/__snapshots__/dialog-box-default.snap.png +0 -0
  226. package/src/components/DialogBox/tests/__snapshots__/dialog-box-no-actions.snap.png +0 -0
  227. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated-submenu-open.snap.png +0 -0
  228. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/header-burger-menu-generated.snap.png +0 -0
  229. package/src/components/HeaderBar/tests/__snapshots__/header-bar-custom-width.snap.png +0 -0
  230. package/src/components/HeaderBar/tests/__snapshots__/header-bar-default.snap.png +0 -0
  231. package/src/components/HeaderBar/tests/__snapshots__/header-bar-no-sticky.snap.png +0 -0
  232. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-prepend.snap.png +0 -0
  233. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-side.snap.png +0 -0
  234. package/src/components/HeaderBar/tests/__snapshots__/header-bar-with-subtitle.snap.png +0 -0
  235. package/src/components/Logo/tests/__snapshots__/logo-avatar.snap.png +0 -0
  236. package/src/components/Logo/tests/__snapshots__/logo-dark.snap.png +0 -0
  237. package/src/components/Logo/tests/__snapshots__/logo-default.snap.png +0 -0
  238. package/src/components/Logo/tests/__snapshots__/logo-no-organism.snap.png +0 -0
  239. package/src/components/Logo/tests/__snapshots__/logo-no-signature.snap.png +0 -0
  240. package/src/components/Logo/tests/__snapshots__/logo-risque-pro.snap.png +0 -0
  241. package/src/components/RangeField/tests/__snapshots__/range-field-custom-bg.snap.png +0 -0
  242. package/src/components/RangeField/tests/__snapshots__/range-field-custom-range.snap.png +0 -0
  243. package/src/components/RangeField/tests/__snapshots__/range-field-default.snap.png +0 -0
  244. package/src/components/RangeField/tests/__snapshots__/range-field-step.snap.png +0 -0
  245. package/src/components/RangeField/tests/__snapshots__/range-field-with-label.snap.png +0 -0
  246. package/src/components/SyAlert/tests/__snapshots__/sy-alert-closable.snap.png +0 -0
  247. package/src/components/SyAlert/tests/__snapshots__/sy-alert-error.snap.png +0 -0
  248. package/src/components/SyAlert/tests/__snapshots__/sy-alert-info.snap.png +0 -0
  249. package/src/components/SyAlert/tests/__snapshots__/sy-alert-success.snap.png +0 -0
  250. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-outlined.snap.png +0 -0
  251. package/src/components/SyAlert/tests/__snapshots__/sy-alert-variant-tonal.snap.png +0 -0
  252. package/src/components/SyAlert/tests/__snapshots__/sy-alert-warning.snap.png +0 -0
  253. /package/src/components/RatingPicker/tests/{RatingPicker.a11y.spect.ts → RatingPicker.a11y.spec.ts} +0 -0
@@ -1,5 +1,8 @@
1
- import { it, describe, expect } from 'vitest'
1
+ import { it, describe, expect, vi } from 'vitest'
2
2
  import { flushPromises, mount } from '@vue/test-utils'
3
+ import { ref } from 'vue'
4
+ import SyForm from '../../Customs/SyForm/SyForm.vue'
5
+ import SyIcon from '../../Customs/SyIcon/SyIcon.vue'
3
6
  import SyTextArea from '../SyTextArea.vue'
4
7
 
5
8
  describe('SyTextArea', () => {
@@ -324,4 +327,449 @@ describe('SyTextArea', () => {
324
327
 
325
328
  expect(wrapper.text()).toContain('Succès personnalisé')
326
329
  })
330
+
331
+ it('validates only on blur when isValidateOnBlur is true', async () => {
332
+ const wrapper = mount(SyTextArea, {
333
+ props: {
334
+ modelValue: '',
335
+ label: 'Description des symptomes',
336
+ isValidateOnBlur: true,
337
+ customRules: [
338
+ {
339
+ type: 'custom',
340
+ options: {
341
+ validate: (value: string) => value !== 'interdit',
342
+ message: 'Erreur isValidateOnBlur',
343
+ },
344
+ },
345
+ ],
346
+ },
347
+ })
348
+
349
+ const textarea = wrapper.find('textarea')
350
+ await textarea.trigger('focus')
351
+ await textarea.setValue('interdit')
352
+ await flushPromises()
353
+
354
+ expect(wrapper.text()).not.toContain('Erreur isValidateOnBlur')
355
+
356
+ await textarea.trigger('blur')
357
+ await flushPromises()
358
+
359
+ expect(wrapper.text()).toContain('Erreur isValidateOnBlur')
360
+ })
361
+
362
+ it('keeps success visual state but hides success text when showSuccessMessages is false', async () => {
363
+ const wrapper = mount(SyTextArea, {
364
+ props: {
365
+ modelValue: '',
366
+ label: 'Description des symptomes',
367
+ isValidateOnBlur: false,
368
+ showSuccessMessages: false,
369
+ customSuccessRules: [
370
+ {
371
+ type: 'custom',
372
+ options: {
373
+ successMessage: 'Succès masqué',
374
+ validate: () => true,
375
+ },
376
+ },
377
+ ],
378
+ },
379
+ })
380
+
381
+ const textarea = wrapper.find('textarea')
382
+ await textarea.trigger('focus')
383
+ await textarea.setValue('valeur')
384
+ await textarea.trigger('blur')
385
+ await flushPromises()
386
+
387
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
388
+ expect((wrapper.vm as any).hasSuccess).toBe(true)
389
+ expect(wrapper.find('.success-field').exists()).toBe(true)
390
+ expect(wrapper.find('.sy-textarea__state-icon').exists()).toBe(true)
391
+ expect(wrapper.findComponent(SyIcon).props('color')).toBe('onSuccessVariant')
392
+ expect(wrapper.text()).not.toContain('Succès masqué')
393
+ })
394
+
395
+ it('applies warning visual state and warning icon when warning rules fail', async () => {
396
+ const wrapper = mount(SyTextArea, {
397
+ props: {
398
+ modelValue: '',
399
+ label: 'Description des symptomes',
400
+ isValidateOnBlur: false,
401
+ customWarningRules: [
402
+ {
403
+ type: 'custom',
404
+ options: {
405
+ warningMessage: 'Avertissement visuel',
406
+ validate: () => false,
407
+ },
408
+ },
409
+ ],
410
+ },
411
+ })
412
+
413
+ const textarea = wrapper.find('textarea')
414
+ await textarea.trigger('focus')
415
+ await textarea.setValue('valeur')
416
+ await textarea.trigger('blur')
417
+ await flushPromises()
418
+
419
+ expect(wrapper.find('.warning-field').exists()).toBe(true)
420
+ expect(wrapper.find('.sy-textarea__state-icon').exists()).toBe(true)
421
+ expect(wrapper.findComponent(SyIcon).props('color')).toBe('onWarningVariant')
422
+ })
423
+
424
+ it('applies error visual state and error icon when validation fails', async () => {
425
+ const wrapper = mount(SyTextArea, {
426
+ props: {
427
+ modelValue: '',
428
+ label: 'Description des symptomes',
429
+ required: true,
430
+ },
431
+ })
432
+
433
+ const textarea = wrapper.find('textarea')
434
+ await textarea.trigger('focus')
435
+ await textarea.trigger('blur')
436
+ await flushPromises()
437
+
438
+ expect(wrapper.find('.error-field').exists()).toBe(true)
439
+ expect(wrapper.find('.sy-textarea__state-icon').exists()).toBe(true)
440
+ expect(wrapper.findComponent(SyIcon).props('color')).toBe('error')
441
+ })
442
+
443
+ describe('Affichage de l\'astérisque', () => {
444
+ it('affiche l\'astérisque quand displayAsterisk et required sont true', () => {
445
+ const wrapper = mount(SyTextArea, {
446
+ props: {
447
+ modelValue: '',
448
+ label: 'Test Label',
449
+ displayAsterisk: true,
450
+ required: true,
451
+ },
452
+ })
453
+
454
+ expect(wrapper.html()).toContain('Test Label *')
455
+ })
456
+
457
+ it('n\'affiche pas l\'astérisque quand displayAsterisk est false', () => {
458
+ const wrapper = mount(SyTextArea, {
459
+ props: {
460
+ modelValue: '',
461
+ label: 'Test Label',
462
+ displayAsterisk: false,
463
+ required: true,
464
+ },
465
+ })
466
+
467
+ expect(wrapper.html()).not.toContain('Test Label *')
468
+ expect(wrapper.html()).toContain('Test Label')
469
+ })
470
+
471
+ it('n\'affiche pas l\'astérisque quand required est false', () => {
472
+ const wrapper = mount(SyTextArea, {
473
+ props: {
474
+ modelValue: '',
475
+ label: 'Test Label',
476
+ displayAsterisk: true,
477
+ required: false,
478
+ },
479
+ })
480
+
481
+ expect(wrapper.html()).not.toContain('Test Label *')
482
+ })
483
+ })
484
+
485
+ describe('helpText', () => {
486
+ it('affiche le helpText quand aucun message de validation n\'est présent', () => {
487
+ const wrapper = mount(SyTextArea, {
488
+ props: {
489
+ modelValue: '',
490
+ label: 'Description',
491
+ helpText: 'Texte d\'aide',
492
+ },
493
+ })
494
+
495
+ expect(wrapper.text()).toContain('Texte d\'aide')
496
+ })
497
+
498
+ it('masque le helpText quand des erreurs sont présentes', async () => {
499
+ const wrapper = mount(SyTextArea, {
500
+ props: {
501
+ modelValue: '',
502
+ label: 'Description',
503
+ helpText: 'Texte d\'aide',
504
+ required: true,
505
+ },
506
+ })
507
+
508
+ const textarea = wrapper.find('textarea')
509
+ await textarea.trigger('focus')
510
+ await textarea.trigger('blur')
511
+
512
+ expect(wrapper.text()).not.toContain('Texte d\'aide')
513
+ expect(wrapper.text()).toContain('Ce champ est requis')
514
+ })
515
+ })
516
+
517
+ describe('hideDetails', () => {
518
+ it('masque la zone des messages quand hideDetails est true et qu\'il n\'y a pas de messages', () => {
519
+ const wrapper = mount(SyTextArea, {
520
+ props: {
521
+ modelValue: '',
522
+ label: 'Description',
523
+ hideDetails: true,
524
+ },
525
+ })
526
+
527
+ expect(wrapper.find('.v-messages').exists()).toBe(false)
528
+ })
529
+
530
+ it('affiche la zone des messages quand hideDetails est true mais qu\'il y a des erreurs', async () => {
531
+ const wrapper = mount(SyTextArea, {
532
+ props: {
533
+ modelValue: '',
534
+ label: 'Description',
535
+ hideDetails: true,
536
+ required: true,
537
+ },
538
+ })
539
+
540
+ const textarea = wrapper.find('textarea')
541
+ await textarea.trigger('focus')
542
+ await textarea.trigger('blur')
543
+
544
+ expect(wrapper.find('.v-messages').exists()).toBe(true)
545
+ expect(wrapper.text()).toContain('Ce champ est requis')
546
+ })
547
+
548
+ it('affiche la zone des messages par défaut (hideDetails vaut false)', () => {
549
+ const wrapper = mount(SyTextArea, {
550
+ props: {
551
+ modelValue: '',
552
+ label: 'Description',
553
+ },
554
+ })
555
+
556
+ expect(wrapper.find('.v-messages').exists()).toBe(true)
557
+ })
558
+ })
559
+
560
+ describe('clearable', () => {
561
+ it('affiche le bouton de suppression quand clearable est true et qu\'une valeur est saisie', () => {
562
+ const wrapper = mount(SyTextArea, {
563
+ props: {
564
+ modelValue: 'contenu',
565
+ label: 'Description',
566
+ clearable: true,
567
+ },
568
+ attachTo: document.body,
569
+ })
570
+
571
+ expect(wrapper.find('.sy-textarea__clear-button').exists()).toBe(true)
572
+
573
+ wrapper.unmount()
574
+ })
575
+
576
+ it('n\'affiche pas le bouton de suppression quand clearable est false', () => {
577
+ const wrapper = mount(SyTextArea, {
578
+ props: {
579
+ modelValue: 'contenu',
580
+ label: 'Description',
581
+ clearable: false,
582
+ },
583
+ attachTo: document.body,
584
+ })
585
+
586
+ expect(wrapper.find('.sy-textarea__clear-button').exists()).toBe(false)
587
+
588
+ wrapper.unmount()
589
+ })
590
+
591
+ it('vide le champ au clic sur le bouton de suppression', async () => {
592
+ const wrapper = mount(SyTextArea, {
593
+ props: {
594
+ modelValue: 'contenu',
595
+ label: 'Description',
596
+ clearable: true,
597
+ },
598
+ attachTo: document.body,
599
+ })
600
+
601
+ const clearButton = wrapper.find('.sy-textarea__clear-button')
602
+ await clearButton.trigger('click')
603
+ await flushPromises()
604
+
605
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy()
606
+ const emittedValues = wrapper.emitted('update:modelValue') as string[][]
607
+ expect(emittedValues[emittedValues.length - 1]).toEqual([''])
608
+
609
+ wrapper.unmount()
610
+ })
611
+ })
612
+
613
+ describe('disableErrorHandling', () => {
614
+ it('n\'affiche pas d\'erreur pour un champ requis sans valeur quand disableErrorHandling est true', async () => {
615
+ const wrapper = mount(SyTextArea, {
616
+ props: {
617
+ modelValue: '',
618
+ label: 'Description',
619
+ required: true,
620
+ disableErrorHandling: true,
621
+ },
622
+ })
623
+
624
+ const textarea = wrapper.find('textarea')
625
+ await textarea.trigger('focus')
626
+ await textarea.trigger('blur')
627
+
628
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
629
+ expect((wrapper.vm as any).hasError).toBe(false)
630
+ expect(wrapper.text()).not.toContain('Ce champ est requis')
631
+ })
632
+
633
+ it('affiche les erreurs normalement quand disableErrorHandling est false', async () => {
634
+ const wrapper = mount(SyTextArea, {
635
+ props: {
636
+ modelValue: '',
637
+ label: 'Description',
638
+ required: true,
639
+ disableErrorHandling: false,
640
+ },
641
+ })
642
+
643
+ const textarea = wrapper.find('textarea')
644
+ await textarea.trigger('focus')
645
+ await textarea.trigger('blur')
646
+
647
+ expect(wrapper.text()).toContain('Ce champ est requis')
648
+ })
649
+ })
650
+
651
+ describe('validateOnSubmit / clearValidation', () => {
652
+ it('validateOnSubmit retourne true quand le champ est valide', async () => {
653
+ const wrapper = mount(SyTextArea, {
654
+ props: {
655
+ modelValue: 'valeur',
656
+ label: 'Description',
657
+ required: true,
658
+ },
659
+ })
660
+
661
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
662
+ const isValid = await (wrapper.vm as any).validateOnSubmit()
663
+ await flushPromises()
664
+
665
+ expect(isValid).toBe(true)
666
+ })
667
+
668
+ it('validateOnSubmit retourne false quand le champ est invalide', async () => {
669
+ const wrapper = mount(SyTextArea, {
670
+ props: {
671
+ modelValue: '',
672
+ label: 'Description',
673
+ isValidateOnBlur: false,
674
+ customRules: [{
675
+ type: 'custom',
676
+ options: {
677
+ validate: (value: string) => value.length <= 5,
678
+ message: 'Valeur trop longue.',
679
+ },
680
+ }],
681
+ },
682
+ })
683
+
684
+ const textarea = wrapper.find('textarea')
685
+ await textarea.trigger('focus')
686
+ await textarea.setValue('valeur trop longue')
687
+ await textarea.trigger('blur')
688
+ await flushPromises()
689
+
690
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
691
+ const isValid = await (wrapper.vm as any).validateOnSubmit()
692
+ await flushPromises()
693
+
694
+ expect(isValid).toBe(false)
695
+ expect(wrapper.text()).toContain('Valeur trop longue.')
696
+ })
697
+
698
+ it('validateOnSubmit retourne false quand un champ requis est vide', async () => {
699
+ const wrapper = mount(SyTextArea, {
700
+ props: {
701
+ modelValue: '',
702
+ label: 'Description',
703
+ required: true,
704
+ },
705
+ })
706
+
707
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
708
+ const isValid = await (wrapper.vm as any).validateOnSubmit()
709
+ await flushPromises()
710
+
711
+ expect(isValid).toBe(false)
712
+ expect(wrapper.text()).toContain('Ce champ est requis')
713
+ })
714
+
715
+ it('clearValidation remet l\'état d\'erreur à zéro', async () => {
716
+ const wrapper = mount(SyTextArea, {
717
+ props: {
718
+ modelValue: '',
719
+ label: 'Description',
720
+ isValidateOnBlur: false,
721
+ customRules: [{
722
+ type: 'custom',
723
+ options: {
724
+ validate: (value: string) => value.length <= 5,
725
+ message: 'Valeur trop longue.',
726
+ },
727
+ }],
728
+ },
729
+ })
730
+
731
+ const textarea = wrapper.find('textarea')
732
+ await textarea.trigger('focus')
733
+ await textarea.setValue('valeur trop longue')
734
+ await textarea.trigger('blur')
735
+ await flushPromises()
736
+
737
+ expect(wrapper.text()).toContain('Valeur trop longue.')
738
+
739
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
740
+ const instance = wrapper.vm as any
741
+ instance.clearValidation()
742
+ await flushPromises()
743
+ expect(wrapper.find('.v-messages__message').exists()).toBe(false)
744
+ })
745
+ })
746
+
747
+ describe('SyForm integration', () => {
748
+ it('valide un champ requis vide lors de la soumission sans interaction préalable', async () => {
749
+ const onSubmit = vi.fn()
750
+ const wrapper = mount({
751
+ components: { SyForm, SyTextArea },
752
+ setup() {
753
+ const value = ref('')
754
+ return { onSubmit, value }
755
+ },
756
+ template: `
757
+ <SyForm @submit="onSubmit">
758
+ <SyTextArea
759
+ v-model="value"
760
+ label="Description"
761
+ required
762
+ />
763
+ <button type="submit">Soumettre</button>
764
+ </SyForm>
765
+ `,
766
+ })
767
+
768
+ await wrapper.find('form').trigger('submit')
769
+ await flushPromises()
770
+
771
+ expect(onSubmit).toHaveBeenCalledWith({ isValid: false })
772
+ expect(wrapper.text()).toContain('Ce champ est requis')
773
+ })
774
+ })
327
775
  })
@@ -40,14 +40,9 @@ export function useDefaultValidationRules(params: {
40
40
 
41
41
  if (params.required.value) {
42
42
  rules.push({
43
- type: 'custom',
43
+ type: 'required',
44
44
  options: {
45
- validate: (value: string) => {
46
- if (!params.hasInteracted.value) {
47
- return true
48
- }
49
- return !!value || locales.required
50
- },
45
+ message: locales.required,
51
46
  },
52
47
  })
53
48
  }