@cnamts/synapse 1.0.25 → 1.0.26

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 (211) hide show
  1. package/dist/{AutocompleteFilter-D7qBuCAP.js → AutocompleteFilter-BPR-a55G.js} +1 -1
  2. package/dist/{DateFilter-BitMWrMU.js → DateFilter-CknrJWs2.js} +2 -2
  3. package/dist/{NumberFilter-BTLUxw0a.js → NumberFilter-DJ-yNlzv.js} +1 -1
  4. package/dist/{PeriodFilter-B5rUIPAC.js → PeriodFilter-CiB5Oa9Z.js} +1 -1
  5. package/dist/{SelectFilter-l4QnRcuk.js → SelectFilter-EiafX97M.js} +1 -1
  6. package/dist/{TextFilter-C9hj6Qrp.js → TextFilter-BzOmpdxj.js} +1 -1
  7. package/dist/{apLightTheme-DnIM24Lv.js → apLightTheme-DS0Uy44H.js} +20 -16
  8. package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +4 -2
  9. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +60 -289
  10. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +1 -0
  11. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1 -0
  12. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1 -0
  13. package/dist/components/Customs/SyTextField/SyTextField.d.ts +2 -4
  14. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +50 -49
  15. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +29 -28
  16. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +8 -8
  17. package/dist/components/DatePicker/composables/useDatePickerState.d.ts +3 -3
  18. package/dist/components/DatePicker/composables/useDateTextField.d.ts +2 -2
  19. package/dist/components/DatePicker/composables/useInputBlurHandler.d.ts +2 -2
  20. package/dist/components/DatePicker/types.d.ts +1 -2
  21. package/dist/components/LunarCalendar/useLunarCalendarValidation.d.ts +1 -0
  22. package/dist/components/MonthPicker/MonthPicker.d.ts +1 -1
  23. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1 -1
  24. package/dist/components/NirField/NirField.d.ts +8 -4
  25. package/dist/components/NirField/useNirValidation.d.ts +6 -2
  26. package/dist/components/PeriodField/PeriodField.d.ts +102 -102
  27. package/dist/components/PhoneField/PhoneField.d.ts +11 -1
  28. package/dist/components/RangeField/RangeSlider/RangeSlider.d.ts +0 -3
  29. package/dist/components/RatingPicker/EmotionPicker/EmotionPicker.d.ts +3 -1
  30. package/dist/components/RatingPicker/NumberPicker/NumberPicker.d.ts +4 -3
  31. package/dist/components/RatingPicker/RatingPicker.d.ts +18 -5
  32. package/dist/components/RatingPicker/StarsPicker/StarsPicker.d.ts +3 -1
  33. package/dist/components/RatingPicker/tests/RatingPicker.a11y.spect.d.ts +1 -0
  34. package/dist/components/RatingPicker/useRatingFocus.d.ts +18 -0
  35. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +4 -4
  36. package/dist/components/Tables/SyTable/SyTable.d.ts +4 -4
  37. package/dist/components/Tables/common/SyTablePagination.d.ts +152 -364
  38. package/dist/components/Tables/common/TableHeader.d.ts +1 -1
  39. package/dist/components/Tables/common/filters/DateFilter.d.ts +4 -4
  40. package/dist/composables/date/useDateInitializationDayjs.d.ts +3 -1
  41. package/dist/composables/unifyValidation/useCustomValidation.d.ts +3 -1
  42. package/dist/composables/unifyValidation/useValidation.d.ts +12 -6
  43. package/dist/composables/unifyValidation/useVuetifyValidation.d.ts +1 -1
  44. package/dist/composables/validation/useValidation.d.ts +1 -0
  45. package/dist/design-system-v3.js +2 -2
  46. package/dist/designTokens/tokens/amelipro/apLightTheme.d.ts +2 -0
  47. package/dist/designTokens/tokens/cnam/cnamLightTheme.d.ts +2 -0
  48. package/dist/{main-Cpx8Co6H.js → main-BsJ9ec3i.js} +9103 -9018
  49. package/dist/synapse.css +1 -1
  50. package/dist/vuetifyConfig.js +1 -1
  51. package/package.json +8 -7
  52. package/src/assets/overrides/_icons.scss +0 -13
  53. package/src/assets/overrides/_otp.scss +0 -1
  54. package/src/components/Accordion/Accordion.vue +2 -0
  55. package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +2 -1
  56. package/src/components/CookiesSelection/CookiesSelection.vue +2 -1
  57. package/src/components/CopyBtn/CopyBtn.vue +9 -0
  58. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +1 -1
  59. package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +413 -96
  60. package/src/components/Customs/Selects/SySelect/SySelect.vue +270 -225
  61. package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +245 -6
  62. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +3 -3
  63. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +23 -2
  64. package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +23 -5
  65. package/src/components/Customs/SyTabs/SyTabs.stories.ts +5 -5
  66. package/src/components/Customs/SyTabs/config.ts +3 -3
  67. package/src/components/Customs/SyTextField/SyTextField.vue +31 -4
  68. package/src/components/DatePicker/CalendarMode/DatePicker.stories.ts +1 -1
  69. package/src/components/DatePicker/CalendarMode/DatePicker.vue +17 -14
  70. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +1 -1
  71. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +8 -7
  72. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +1 -1
  73. package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.stories.ts +1 -1
  74. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +57 -23
  75. package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +1 -1
  76. package/src/components/DatePicker/composables/useDatePickerState.ts +33 -14
  77. package/src/components/DatePicker/composables/useDateRangeInput.ts +2 -1
  78. package/src/components/DatePicker/composables/useDateSelection.ts +2 -1
  79. package/src/components/DatePicker/composables/useDateTextField.ts +2 -2
  80. package/src/components/DatePicker/composables/useInputBlurHandler.ts +2 -2
  81. package/src/components/DatePicker/types.ts +1 -2
  82. package/src/components/DialogBox/DialogBox.stories.ts +8 -8
  83. package/src/components/DialogBox/accessibilite/Accessibility.mdx +86 -22
  84. package/src/components/FilterSideBar/FilterSideBar.vue +2 -1
  85. package/src/components/LangBtn/LangBtn.vue +2 -1
  86. package/src/components/NotificationBar/Notification/Notification.vue +2 -2
  87. package/src/components/PaginatedTable/PaginatedTable.vue +1 -1
  88. package/src/components/PaginatedTable/Pagination.vue +1 -1
  89. package/src/components/PasswordField/PasswordField.vue +7 -3
  90. package/src/components/PhoneField/PhoneField.vue +4 -2
  91. package/src/components/RangeField/RangeSlider/RangeSlider.vue +11 -18
  92. package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +32 -48
  93. package/src/components/RatingPicker/EmotionPicker/tests/__snapshots__/EmotionPicker.spec.ts.snap +5 -0
  94. package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +48 -53
  95. package/src/components/RatingPicker/NumberPicker/tests/NumberPicker.spec.ts +2 -1
  96. package/src/components/RatingPicker/NumberPicker/tests/__snapshots__/NumberPicker.spec.ts.snap +40 -13
  97. package/src/components/RatingPicker/RatingPicker.stories.ts +65 -88
  98. package/src/components/RatingPicker/RatingPicker.vue +71 -15
  99. package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +28 -37
  100. package/src/components/RatingPicker/StarsPicker/tests/StarsPicker.spec.ts +1 -1
  101. package/src/components/RatingPicker/StarsPicker/tests/__snapshots__/StarsPicker.spec.ts.snap +5 -0
  102. package/src/components/RatingPicker/accessibilite/Accessibility.mdx +137 -9
  103. package/src/components/RatingPicker/tests/RatingPicker.a11y.spect.ts +123 -0
  104. package/src/components/RatingPicker/tests/RatingPicker.spec.ts +3 -2
  105. package/src/components/RatingPicker/tests/__snapshots__/RatingPicker.spec.ts.snap +40 -11
  106. package/src/components/RatingPicker/useRatingFocus.ts +97 -0
  107. package/src/components/SyTextArea/SyTextArea.vue +32 -1
  108. package/src/components/Tables/SyServerTable/SyServerTable.vue +1 -1
  109. package/src/components/Tables/SyTable/SyTable.vue +1 -1
  110. package/src/components/Tables/common/SyTableFilter.vue +4 -4
  111. package/src/components/Tables/common/SyTablePagination.vue +1 -0
  112. package/src/components/Tables/common/TableHeader.vue +1 -1
  113. package/src/components/Tables/common/filters/DateFilter.vue +2 -2
  114. package/src/composables/date/tests/useDateFormatDayjs.spec.ts +81 -0
  115. package/src/composables/date/tests/{useDateInitialization.spec.ts → useDateInitializationDayjs.spec.ts} +39 -3
  116. package/src/composables/date/useDateInitializationDayjs.ts +4 -1
  117. package/src/composables/unifyValidation/documentationValidationProps.ts +7 -7
  118. package/src/composables/unifyValidation/tests/useCustomValidation.spec.ts +2 -1
  119. package/src/composables/unifyValidation/tests/useValidation.spec.ts +22 -0
  120. package/src/composables/unifyValidation/useCustomValidation.ts +16 -4
  121. package/src/composables/unifyValidation/useValidation.ts +46 -15
  122. package/src/composables/unifyValidation/useVuetifyValidation.ts +2 -2
  123. package/src/composables/useFormFieldErrorHandling.ts +4 -1
  124. package/src/composables/validation/tests/useValidation.spec.ts +2 -2
  125. package/src/composables/validation/useValidation.ts +15 -3
  126. package/src/composantsVuetify/VCard/VCard.mdx +59 -0
  127. package/src/composantsVuetify/VCard/v-card.stories.ts +279 -0
  128. package/src/designTokens/tokens/amelipro/apColors2026.ts +1 -1
  129. package/src/designTokens/tokens/amelipro/apLightTheme.ts +3 -0
  130. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +3 -0
  131. package/src/stories/Accessibilite/Aculturation/SensibilisationAccessibilite.mdx +61 -91
  132. package/src/stories/Accessibilite/AuditDesignSystem.mdx +5 -8
  133. package/src/stories/Accessibilite/AuditEtContreAudit/Exemptions-derogations.mdx +1 -1
  134. package/src/stories/Accessibilite/AuditEtContreAudit/Introduction.mdx +11 -8
  135. package/src/stories/Accessibilite/AuditEtContreAudit/RGAA.mdx +6 -7
  136. package/src/stories/Accessibilite/Introduction.mdx +30 -30
  137. package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +168 -78
  138. package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +13 -6
  139. package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +66 -45
  140. package/src/stories/Accessibilite/KitDePreAudit/Outils/LecteursDEcran.mdx +23 -49
  141. package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru/FauxPositifs.stories.ts +6 -0
  142. package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru/Utilisation.mdx +7 -19
  143. package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +18 -20
  144. package/src/stories/Components/Components.stories.ts +52 -3
  145. package/dist/AutocompleteFilter-Df9i5mAl.cjs +0 -1
  146. package/dist/DateFilter-BJD6FMev.cjs +0 -1
  147. package/dist/NumberFilter-DGCzCXzI.cjs +0 -1
  148. package/dist/PeriodFilter-DO_ecTZW.cjs +0 -1
  149. package/dist/SelectFilter-CGwcKWLm.cjs +0 -1
  150. package/dist/TextFilter-B8nf7xoK.cjs +0 -1
  151. package/dist/apLightTheme-CEK4iY3f.cjs +0 -1
  152. package/dist/composables/date/useDateFormat.d.ts +0 -26
  153. package/dist/composables/date/useDateInitialization.d.ts +0 -18
  154. package/dist/design-system-v3.umd.cjs +0 -1
  155. package/dist/main-ByDPHpae.cjs +0 -1067
  156. package/dist/tooth-11-D3sLWv2n.cjs +0 -1
  157. package/dist/tooth-12-CXrLuH03.cjs +0 -1
  158. package/dist/tooth-13-BSfo5fpT.cjs +0 -1
  159. package/dist/tooth-14-DMzulx0h.cjs +0 -1
  160. package/dist/tooth-15-BKRFVi-9.cjs +0 -1
  161. package/dist/tooth-16-CpuxAbuM.cjs +0 -1
  162. package/dist/tooth-17-BPoahUdg.cjs +0 -1
  163. package/dist/tooth-18-DhHJz8sy.cjs +0 -1
  164. package/dist/tooth-21-Dgd5hn_X.cjs +0 -1
  165. package/dist/tooth-22-C2Tn19sB.cjs +0 -1
  166. package/dist/tooth-23-C9uaaSGb.cjs +0 -1
  167. package/dist/tooth-24-BrK9UGpf.cjs +0 -1
  168. package/dist/tooth-25-CE_EfGNp.cjs +0 -1
  169. package/dist/tooth-26-Ctv4i9Fy.cjs +0 -1
  170. package/dist/tooth-27-C5J7JkWM.cjs +0 -1
  171. package/dist/tooth-28-Z9oWqjo0.cjs +0 -1
  172. package/dist/tooth-31-BrYqmkTi.cjs +0 -1
  173. package/dist/tooth-32-BNNR0oCZ.cjs +0 -1
  174. package/dist/tooth-33-DuxvqO2J.cjs +0 -1
  175. package/dist/tooth-34-BCSCXMB6.cjs +0 -1
  176. package/dist/tooth-35-BLUXkX88.cjs +0 -1
  177. package/dist/tooth-36-IrKHYqlA.cjs +0 -1
  178. package/dist/tooth-37-BYqpdMwo.cjs +0 -1
  179. package/dist/tooth-38-B_eNXXdu.cjs +0 -1
  180. package/dist/tooth-41-Ddva4Ot8.cjs +0 -1
  181. package/dist/tooth-42-szcDqlM0.cjs +0 -1
  182. package/dist/tooth-43-B3ka6rQm.cjs +0 -1
  183. package/dist/tooth-44-CazyQucj.cjs +0 -1
  184. package/dist/tooth-45-B4HQtc8n.cjs +0 -1
  185. package/dist/tooth-46-BPM40gbG.cjs +0 -1
  186. package/dist/tooth-47-Dvr20dlh.cjs +0 -1
  187. package/dist/tooth-48-Bd8ljGsF.cjs +0 -1
  188. package/dist/tooth-51-OBpwCOF3.cjs +0 -1
  189. package/dist/tooth-52-aKxyHcmq.cjs +0 -1
  190. package/dist/tooth-53-vCwJjTOc.cjs +0 -1
  191. package/dist/tooth-54-DsWu2iFy.cjs +0 -1
  192. package/dist/tooth-55-BxC1X2Dn.cjs +0 -1
  193. package/dist/tooth-61-BbLvxMQi.cjs +0 -1
  194. package/dist/tooth-62-CmTkWczP.cjs +0 -1
  195. package/dist/tooth-63-DI7l_2qI.cjs +0 -1
  196. package/dist/tooth-64-B21sOsJh.cjs +0 -1
  197. package/dist/tooth-65-D2ZC2VEr.cjs +0 -1
  198. package/dist/tooth-71-D473PPO5.cjs +0 -1
  199. package/dist/tooth-72-Drh1wnNu.cjs +0 -1
  200. package/dist/tooth-73-DzlwYI23.cjs +0 -1
  201. package/dist/tooth-74-8aGvcZPg.cjs +0 -1
  202. package/dist/tooth-75-BFK7At_r.cjs +0 -1
  203. package/dist/tooth-81-BZmR-I0M.cjs +0 -1
  204. package/dist/tooth-82-euVfUUZV.cjs +0 -1
  205. package/dist/tooth-83-KV010j64.cjs +0 -1
  206. package/dist/tooth-84-BBg1RjhZ.cjs +0 -1
  207. package/dist/tooth-85-Cr-kc1wM.cjs +0 -1
  208. package/dist/vuetifyConfig.umd.cjs +0 -1
  209. package/src/composables/date/tests/useDateFormat.spec.ts +0 -67
  210. package/src/composables/date/useDateFormat.ts +0 -110
  211. package/src/composables/date/useDateInitialization.ts +0 -92
@@ -3,7 +3,6 @@
3
3
  exports[`RatingPicker > renders correctly 1`] = `
4
4
  <div class="sy-rating-picker">
5
5
  <fieldset class="sy-number-picker">
6
- <legend class="d-sr-only"></legend>
7
6
  <legend class="
8
7
  mb-6
9
8
  text-h6
@@ -19,7 +18,7 @@ exports[`RatingPicker > renders correctly 1`] = `
19
18
  role="radiogroup"
20
19
  >
21
20
  <div
22
- aria-label="Note de 1 sur 10."
21
+ aria-checked="false"
23
22
  class="
24
23
  pa-0
25
24
  sy-number-picker__item
@@ -29,9 +28,12 @@ exports[`RatingPicker > renders correctly 1`] = `
29
28
  tabindex="0"
30
29
  >
31
30
  1
31
+ <span class="d-sr-only">
32
+ Note de 1 sur 10.
33
+ </span>
32
34
  </div>
33
35
  <div
34
- aria-label="Note de 2 sur 10."
36
+ aria-checked="false"
35
37
  class="
36
38
  pa-0
37
39
  sy-number-picker__item
@@ -41,9 +43,12 @@ exports[`RatingPicker > renders correctly 1`] = `
41
43
  tabindex="-1"
42
44
  >
43
45
  2
46
+ <span class="d-sr-only">
47
+ Note de 2 sur 10.
48
+ </span>
44
49
  </div>
45
50
  <div
46
- aria-label="Note de 3 sur 10."
51
+ aria-checked="false"
47
52
  class="
48
53
  pa-0
49
54
  sy-number-picker__item
@@ -53,9 +58,12 @@ exports[`RatingPicker > renders correctly 1`] = `
53
58
  tabindex="-1"
54
59
  >
55
60
  3
61
+ <span class="d-sr-only">
62
+ Note de 3 sur 10.
63
+ </span>
56
64
  </div>
57
65
  <div
58
- aria-label="Note de 4 sur 10."
66
+ aria-checked="false"
59
67
  class="
60
68
  pa-0
61
69
  sy-number-picker__item
@@ -65,9 +73,12 @@ exports[`RatingPicker > renders correctly 1`] = `
65
73
  tabindex="-1"
66
74
  >
67
75
  4
76
+ <span class="d-sr-only">
77
+ Note de 4 sur 10.
78
+ </span>
68
79
  </div>
69
80
  <div
70
- aria-label="Note de 5 sur 10."
81
+ aria-checked="false"
71
82
  class="
72
83
  pa-0
73
84
  sy-number-picker__item
@@ -77,9 +88,12 @@ exports[`RatingPicker > renders correctly 1`] = `
77
88
  tabindex="-1"
78
89
  >
79
90
  5
91
+ <span class="d-sr-only">
92
+ Note de 5 sur 10.
93
+ </span>
80
94
  </div>
81
95
  <div
82
- aria-label="Note de 6 sur 10."
96
+ aria-checked="false"
83
97
  class="
84
98
  pa-0
85
99
  sy-number-picker__item
@@ -89,9 +103,12 @@ exports[`RatingPicker > renders correctly 1`] = `
89
103
  tabindex="-1"
90
104
  >
91
105
  6
106
+ <span class="d-sr-only">
107
+ Note de 6 sur 10.
108
+ </span>
92
109
  </div>
93
110
  <div
94
- aria-label="Note de 7 sur 10."
111
+ aria-checked="false"
95
112
  class="
96
113
  pa-0
97
114
  sy-number-picker__item
@@ -101,9 +118,12 @@ exports[`RatingPicker > renders correctly 1`] = `
101
118
  tabindex="-1"
102
119
  >
103
120
  7
121
+ <span class="d-sr-only">
122
+ Note de 7 sur 10.
123
+ </span>
104
124
  </div>
105
125
  <div
106
- aria-label="Note de 8 sur 10."
126
+ aria-checked="false"
107
127
  class="
108
128
  pa-0
109
129
  sy-number-picker__item
@@ -113,9 +133,12 @@ exports[`RatingPicker > renders correctly 1`] = `
113
133
  tabindex="-1"
114
134
  >
115
135
  8
136
+ <span class="d-sr-only">
137
+ Note de 8 sur 10.
138
+ </span>
116
139
  </div>
117
140
  <div
118
- aria-label="Note de 9 sur 10."
141
+ aria-checked="false"
119
142
  class="
120
143
  pa-0
121
144
  sy-number-picker__item
@@ -125,9 +148,12 @@ exports[`RatingPicker > renders correctly 1`] = `
125
148
  tabindex="-1"
126
149
  >
127
150
  9
151
+ <span class="d-sr-only">
152
+ Note de 9 sur 10.
153
+ </span>
128
154
  </div>
129
155
  <div
130
- aria-label="Note de 10 sur 10."
156
+ aria-checked="false"
131
157
  class="
132
158
  pa-0
133
159
  sy-number-picker__item
@@ -137,6 +163,9 @@ exports[`RatingPicker > renders correctly 1`] = `
137
163
  tabindex="-1"
138
164
  >
139
165
  10
166
+ <span class="d-sr-only">
167
+ Note de 10 sur 10.
168
+ </span>
140
169
  </div>
141
170
  </div>
142
171
  <!-- v-if -->
@@ -0,0 +1,97 @@
1
+ import { nextTick, ref, watch, type Ref } from 'vue'
2
+
3
+ type SelectValueFn = (value: number) => void
4
+
5
+ interface UseRatingFocusOptions {
6
+ length: Ref<number>
7
+ modelValue: Ref<number>
8
+ selectValue: SelectValueFn
9
+ wrap?: boolean
10
+ }
11
+
12
+ export function useRatingFocus({
13
+ length,
14
+ modelValue,
15
+ selectValue,
16
+ wrap = true,
17
+ }: UseRatingFocusOptions) {
18
+ const ratingElement = ref<HTMLElement[]>([])
19
+
20
+ function setFocus(index: number) {
21
+ ratingElement.value.forEach((el, i) => {
22
+ if (!el) return
23
+ el.setAttribute('tabindex', i === index ? '0' : '-1')
24
+ })
25
+
26
+ ratingElement.value[index]?.focus()
27
+ }
28
+
29
+ function getCurrentIndex() {
30
+ if (modelValue.value >= 1 && modelValue.value <= length.value) {
31
+ return modelValue.value - 1
32
+ }
33
+ return 0
34
+ }
35
+
36
+ function initFocus() {
37
+ setFocus(getCurrentIndex())
38
+ }
39
+
40
+ function selectAndFocus(index: number) {
41
+ const value = index + 1
42
+ selectValue(value)
43
+ nextTick(() => setFocus(index))
44
+ }
45
+
46
+ function focusNextElement(index: number) {
47
+ let nextIndex = index + 1
48
+
49
+ if (wrap) {
50
+ if (nextIndex >= length.value) {
51
+ nextIndex = 0
52
+ }
53
+ }
54
+ else {
55
+ nextIndex = Math.min(nextIndex, length.value - 1)
56
+ }
57
+
58
+ setFocus(nextIndex)
59
+ }
60
+
61
+ function focusPrevElement(index: number) {
62
+ let prevIndex = index - 1
63
+
64
+ if (wrap) {
65
+ if (prevIndex < 0) {
66
+ prevIndex = length.value - 1
67
+ }
68
+ }
69
+ else {
70
+ prevIndex = Math.max(prevIndex, 0)
71
+ }
72
+
73
+ setFocus(prevIndex)
74
+ }
75
+
76
+ function focus() {
77
+ nextTick(() => {
78
+ setFocus(getCurrentIndex())
79
+ })
80
+ }
81
+
82
+ watch(modelValue, () => {
83
+ nextTick(() => {
84
+ setFocus(getCurrentIndex())
85
+ })
86
+ })
87
+
88
+ return {
89
+ ratingElement,
90
+ setFocus,
91
+ initFocus,
92
+ selectAndFocus,
93
+ focusNextElement,
94
+ focusPrevElement,
95
+ focus,
96
+ }
97
+ }
@@ -143,7 +143,12 @@
143
143
  :bg-color="props.bgColor"
144
144
  :error="hasError"
145
145
  :error-messages="errors"
146
- :messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess && props.showSuccessMessages ? successes : []))"
146
+ :class="{
147
+ 'success-field': hasSuccess && !hasError && !hasWarning,
148
+ 'warning-field': hasWarning && !hasError,
149
+ 'error-field': hasError,
150
+ }"
151
+ :messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess ? successes : []))"
147
152
  :max-errors="props.maxErrors"
148
153
  :disabled="props.disabled"
149
154
  :readonly="props.readonly"
@@ -157,3 +162,29 @@
157
162
  @update:focused="(e: boolean) => { focused = e; if (!e) execBlurChange() }"
158
163
  />
159
164
  </template>
165
+
166
+ <style lang="scss" scoped>
167
+ .success-field {
168
+ :deep(.v-field__outline) {
169
+ --v-field-border-opacity: 1;
170
+
171
+ color: rgb(var(--v-theme-success));
172
+ }
173
+
174
+ :deep(.v-messages__message) {
175
+ color: rgb(var(--v-theme-success));
176
+ }
177
+ }
178
+
179
+ .warning-field {
180
+ :deep(.v-field__outline) {
181
+ --v-field-border-opacity: 1;
182
+
183
+ color: rgb(var(--v-theme-borderWarning));
184
+ }
185
+
186
+ :deep(.v-messages__message) {
187
+ color: rgb(var(--v-theme-borderWarning));
188
+ }
189
+ }
190
+ </style>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, onMounted, provide, ref, toRef, useAttrs, watch } from 'vue'
3
- import type { VDataTableServer } from 'vuetify/components'
3
+ import type { VDataTableServer } from 'vuetify/components/VDataTable'
4
4
  import SyCheckbox from '@/components/Customs/SyCheckbox/SyCheckbox.vue'
5
5
  import SyTableFilter from '../common/SyTableFilter.vue'
6
6
  import TableHeader from '../common/TableHeader.vue'
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, onMounted, provide, ref, toRef, useAttrs, watch } from 'vue'
3
- import type { VDataTable } from 'vuetify/components'
3
+ import type { VDataTable } from 'vuetify/components/VDataTable'
4
4
  import SyCheckbox from '@/components/Customs/SyCheckbox/SyCheckbox.vue'
5
5
  import SyTableFilter from '../common/SyTableFilter.vue'
6
6
  import TableHeader from '../common/TableHeader.vue'
@@ -2,7 +2,7 @@
2
2
  import { ref, watch, provide, computed } from 'vue'
3
3
  import type { FilterOption, TableColumnHeader } from './types'
4
4
  import { filterItems } from './tableFilterUtils'
5
- import type { DateValue } from '@/composables/date/useDateInitializationDayjs'
5
+ import type { DateModelValue } from '@/composables/date/useDateInitializationDayjs'
6
6
  import getFilterComponent from './filters/getFilterComponent'
7
7
 
8
8
  const props = defineProps({
@@ -59,7 +59,7 @@
59
59
  const filtersMap = ref<{
60
60
  text: Record<string, string>
61
61
  number: Record<string, number>
62
- date: Record<string, DateValue>
62
+ date: Record<string, DateModelValue>
63
63
  period: Record<string, { from: string | null, to: string | null }>
64
64
  select: Record<string, string | number | Record<string, unknown> | undefined>
65
65
  autocomplete: Record<string, string | number | Record<string, unknown> | Array<string | number | Record<string, unknown>> | undefined>
@@ -93,7 +93,7 @@
93
93
  filtersMap.value.number[key] = value as number
94
94
  break
95
95
  case 'date':
96
- filtersMap.value.date[key] = value as DateValue
96
+ filtersMap.value.date[key] = value as DateModelValue
97
97
  break
98
98
  case 'period':
99
99
  if (value && typeof value === 'object' && 'from' in value && 'to' in value) {
@@ -184,7 +184,7 @@
184
184
  filtersMap.value.select[key] = value as string | number | Record<string, unknown> | undefined
185
185
  }
186
186
  else if (header.filterType === 'date') {
187
- filtersMap.value.date[key] = value as DateValue
187
+ filtersMap.value.date[key] = value as DateModelValue
188
188
  }
189
189
  else if (header.filterType === 'period') {
190
190
  filtersMap.value.period[key] = value as { from: string | null, to: string | null }
@@ -211,6 +211,7 @@
211
211
  :items="formatedItemsPerPageOptions"
212
212
  hide-details
213
213
  hide-messages
214
+ disable-error-handling
214
215
  density="compact"
215
216
  class="rows-per-page-select"
216
217
  :aria-label="locales.pagination.itemsPerPageText"
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, nextTick, onMounted, ref, inject, watch, type Ref, onUnmounted } from 'vue'
3
- import type { VDataTable, VDataTableServer } from 'vuetify/components'
3
+ import type { VDataTable, VDataTableServer } from 'vuetify/components/VDataTable'
4
4
  import { locales } from './locales'
5
5
  import SyIcon from '@/components/Customs/SyIcon/SyIcon.vue'
6
6
 
@@ -2,7 +2,7 @@
2
2
  import { computed } from 'vue'
3
3
  import type { FilterOption, TableColumnHeader } from '../types'
4
4
  import DatePicker from '@/components/DatePicker/CalendarMode/DatePicker.vue'
5
- import type { DateValue } from '@/composables/date/useDateInitializationDayjs'
5
+ import type { DateModelValue } from '@/composables/date/useDateInitializationDayjs'
6
6
  import { useDateFormat } from '@/composables/date/useDateFormatDayjs'
7
7
  const { parseDate } = useDateFormat()
8
8
 
@@ -16,7 +16,7 @@
16
16
  default: () => [],
17
17
  },
18
18
  filterValue: {
19
- type: [String, Date, Object, null] as unknown as () => DateValue,
19
+ type: [String, Date, Object, null] as unknown as () => DateModelValue,
20
20
  default: null,
21
21
  },
22
22
  inputConfig: {
@@ -2,7 +2,88 @@ import { describe, it, expect } from 'vitest'
2
2
  import { formatDate, parseDate } from '../useDateFormatDayjs'
3
3
 
4
4
  describe('useDateFormatDayjs', () => {
5
+ describe('formatDate', () => {
6
+ it('formats a Date object to string according to the specified format', () => {
7
+ const date = new Date(2023, 0, 15) // 15 janvier 2023
8
+ expect(formatDate(date, 'DD/MM/YYYY')).toBe('15/01/2023')
9
+ expect(formatDate(date, 'YYYY-MM-DD')).toBe('2023-01-15')
10
+ })
11
+
12
+ it('returns empty string when date is null or undefined', () => {
13
+ expect(formatDate(null as unknown as Date, 'DD/MM/YYYY')).toBe('')
14
+ expect(formatDate(undefined as unknown as Date, 'DD/MM/YYYY')).toBe('')
15
+ })
16
+
17
+ it('handles different date formats correctly', () => {
18
+ const date = new Date(2023, 11, 31) // 31 décembre 2023
19
+ expect(formatDate(date, 'DD/MM/YYYY')).toBe('31/12/2023')
20
+ expect(formatDate(date, 'YYYY-MM-DD')).toBe('2023-12-31')
21
+ })
22
+
23
+ it('handles custom separators correctly', () => {
24
+ const date = new Date(2023, 0, 15) // 15 janvier 2023
25
+ expect(formatDate(date, 'DD.MM.YYYY')).toBe('15.01.2023')
26
+ expect(formatDate(date, 'DD-MM-YYYY')).toBe('15-01-2023')
27
+ expect(formatDate(date, 'YYYY/MM/DD')).toBe('2023/01/15')
28
+ })
29
+ })
30
+
5
31
  describe('parseDate', () => {
32
+ it('parses a date string to a Date object according to the specified format', () => {
33
+ const dateStr = '15/01/2023'
34
+ const date = parseDate(dateStr, 'DD/MM/YYYY')
35
+ expect(date).toBeInstanceOf(Date)
36
+ expect(date?.getFullYear()).toBe(2023)
37
+ expect(date?.getMonth()).toBe(0) // Janvier = 0
38
+ expect(date?.getDate()).toBe(15)
39
+ })
40
+
41
+ it('returns null for invalid date strings', () => {
42
+ expect(parseDate('invalid', 'DD/MM/YYYY')).toBeNull()
43
+ expect(parseDate('31/02/2023', 'DD/MM/YYYY')).toBeNull() // 31 février n'existe pas
44
+ })
45
+
46
+ it('handles different date formats correctly', () => {
47
+ expect(parseDate('2023-01-15', 'YYYY-MM-DD')?.getDate()).toBe(15)
48
+ expect(parseDate('15.01.2023', 'DD.MM.YYYY')?.getDate()).toBe(15)
49
+ })
50
+
51
+ it('returns null when input is null or empty', () => {
52
+ expect(parseDate(null, 'DD/MM/YYYY')).toBeNull()
53
+ expect(parseDate('', 'DD/MM/YYYY')).toBeNull()
54
+ })
55
+
56
+ it('handles leap years correctly', () => {
57
+ // 2020 était une année bissextile
58
+ expect(parseDate('29/02/2020', 'DD/MM/YYYY')).not.toBeNull()
59
+ // 2023 n'est pas une année bissextile
60
+ expect(parseDate('29/02/2023', 'DD/MM/YYYY')).toBeNull()
61
+ })
62
+
63
+ it('returns the Date object as-is when input is already a Date', () => {
64
+ const original = new Date(2023, 5, 15, 10, 30)
65
+ const result = parseDate(original, 'DD/MM/YYYY')
66
+ expect(result).toBe(original) // même référence
67
+ })
68
+
69
+ it('creates dates at midnight (00:00:00.000)', () => {
70
+ const date = parseDate('15/01/2023', 'DD/MM/YYYY')!
71
+ expect(date.getHours()).toBe(0)
72
+ expect(date.getMinutes()).toBe(0)
73
+ expect(date.getSeconds()).toBe(0)
74
+ expect(date.getMilliseconds()).toBe(0)
75
+ })
76
+
77
+ it('roundtrip: parseDate then formatDate preserves the same calendar day', () => {
78
+ const formats = ['DD/MM/YYYY', 'YYYY-MM-DD', 'DD.MM.YYYY']
79
+ const inputs = ['01/01/2023', '2023-06-30', '31.12.2020']
80
+ formats.forEach((fmt, i) => {
81
+ const parsed = parseDate(inputs[i]!, fmt)
82
+ expect(parsed).not.toBeNull()
83
+ expect(formatDate(parsed, fmt)).toBe(inputs[i])
84
+ })
85
+ })
86
+
6
87
  it('keeps the same calendar day when formatting back in a negative timezone (UTC-4)', () => {
7
88
  const previousTz = process.env.TZ
8
89
  process.env.TZ = 'America/Guadeloupe'
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
2
- import { initializeSelectedDates, type DateInput } from '../useDateInitialization'
2
+ import { initializeSelectedDates, type DateInput } from '../useDateInitializationDayjs'
3
3
 
4
- describe('useDateInitialization', () => {
4
+ describe('useDateInitializationDayjs', () => {
5
5
  describe('initializeSelectedDates', () => {
6
6
  it('returns null when modelValue is null or undefined', () => {
7
7
  expect(initializeSelectedDates(null, 'DD/MM/YYYY')).toBeNull()
@@ -70,7 +70,7 @@ describe('useDateInitialization', () => {
70
70
  expect(result1).toBeInstanceOf(Date)
71
71
  expect((result1 as Date).getDate()).toBe(15)
72
72
 
73
- // Date au format d'affichage quand le format de retour est différen
73
+ // Date au format d'affichage quand le format de retour est différent
74
74
  const result2 = initializeSelectedDates('15/01/2023', 'DD/MM/YYYY', 'YYYY-MM-DD')
75
75
  expect(result2).toBeInstanceOf(Date)
76
76
  expect((result2 as Date).getDate()).toBe(15)
@@ -97,6 +97,42 @@ describe('useDateInitialization', () => {
97
97
  })
98
98
  })
99
99
 
100
+ it('creates dates at midnight (00:00:00.000)', () => {
101
+ const result = initializeSelectedDates('15/06/2023', 'DD/MM/YYYY') as Date
102
+ expect(result.getHours()).toBe(0)
103
+ expect(result.getMinutes()).toBe(0)
104
+ expect(result.getSeconds()).toBe(0)
105
+ expect(result.getMilliseconds()).toBe(0)
106
+ })
107
+
108
+ it('creates dates at midnight for arrays too', () => {
109
+ const result = initializeSelectedDates(['01/03/2023', '15/03/2023'], 'DD/MM/YYYY') as Date[]
110
+ result.forEach((date) => {
111
+ expect(date.getHours()).toBe(0)
112
+ expect(date.getMinutes()).toBe(0)
113
+ expect(date.getSeconds()).toBe(0)
114
+ })
115
+ })
116
+
117
+ it('handles range array with different return format', () => {
118
+ const result = initializeSelectedDates(['2023-01-10', '2023-01-20'], 'DD/MM/YYYY', 'YYYY-MM-DD')
119
+ expect(Array.isArray(result)).toBe(true)
120
+ const dates = result as Date[]
121
+ expect(dates).toHaveLength(2)
122
+ expect(dates[0]?.getDate()).toBe(10)
123
+ expect(dates[1]?.getDate()).toBe(20)
124
+ })
125
+
126
+ it('accepts a range where both dates are equal', () => {
127
+ const result = initializeSelectedDates(['15/01/2023', '15/01/2023'], 'DD/MM/YYYY')
128
+ expect(Array.isArray(result)).toBe(true)
129
+ expect(result).toHaveLength(2)
130
+ })
131
+
132
+ it('returns null for empty string input', () => {
133
+ expect(initializeSelectedDates('', 'DD/MM/YYYY')).toBeNull()
134
+ })
135
+
100
136
  it('returns null for object input', () => {
101
137
  const result = initializeSelectedDates({}, 'DD/MM/YYYY')
102
138
  expect(result).toBeNull()
@@ -14,7 +14,10 @@ dayjs.extend(timezone)
14
14
  dayjs.locale('fr')
15
15
 
16
16
  // Types
17
- export type DateValue = string | [string, string] | null
17
+ export type DateModelValue = string | [string, string] | null
18
+
19
+ /** @deprecated Utilisez DateModelValue à la place */
20
+ export type DateValue = DateModelValue
18
21
  export type DateInput = string | string[] | null | object
19
22
 
20
23
  /**
@@ -59,7 +59,7 @@ export function getValidationDocumentation(type: 'date' | 'number' | 'string' |
59
59
  },
60
60
  },
61
61
  showSuccessMessages: {
62
- description: 'Affiche les messages de succès lorsque la validation est réussie.',
62
+ description: 'Affiche les messages de succès lorsque la validation est réussie. Si la prop est à `false` cela cache uniquement les messages texte, l\'état visuel reste actif.',
63
63
  control: 'boolean',
64
64
  table: {
65
65
  type: { summary: 'boolean' },
@@ -107,7 +107,7 @@ export function getValidationDocumentation(type: 'date' | 'number' | 'string' |
107
107
  },
108
108
  },
109
109
  customRules: {
110
- description: 'Les règles de validation personnalisées à appliquer au champ.',
110
+ description: 'Les règles de validation personnalisées d\'erreur (bloquantes) à appliquer au champ. Elles sont évaluées à partir de la valeur du champ.',
111
111
  control: 'object',
112
112
  table: {
113
113
  type: {
@@ -127,7 +127,7 @@ export function getValidationDocumentation(type: 'date' | 'number' | 'string' |
127
127
  },
128
128
  },
129
129
  customWarningRules: {
130
- description: 'Les règles de validation personnalisées pour les avertissements à appliquer au champ.',
130
+ description: 'Les règles de validation personnalisées d\'avertissement (non bloquantes) à appliquer au champ. Elles sont évaluées à partir de la valeur du champ.',
131
131
  control: 'object',
132
132
  table: {
133
133
  type: {
@@ -147,7 +147,7 @@ export function getValidationDocumentation(type: 'date' | 'number' | 'string' |
147
147
  },
148
148
  },
149
149
  customSuccessRules: {
150
- description: 'Les règles de validation personnalisées pour les succès à appliquer au champ.',
150
+ description: 'Les règles de validation personnalisées de succès à appliquer au champ. Elles sont évaluées à partir de la valeur du champ.',
151
151
  control: 'object',
152
152
  table: {
153
153
  type: {
@@ -167,7 +167,7 @@ export function getValidationDocumentation(type: 'date' | 'number' | 'string' |
167
167
  },
168
168
  },
169
169
  errorMessages: {
170
- description: 'Permet de forcer des messages d\'erreur spécifiques.',
170
+ description: 'Permet d\'injecter des messages d\'erreur depuis le parent. Aucun calcul de validation n\'est exécuté.',
171
171
  control: 'object',
172
172
  table: {
173
173
  type: { summary: 'array<string>' },
@@ -175,7 +175,7 @@ export function getValidationDocumentation(type: 'date' | 'number' | 'string' |
175
175
  },
176
176
  },
177
177
  warningMessages: {
178
- description: 'Permet de forcer des messages d\'avertissement spécifiques.',
178
+ description: 'Permet d\'injecter des messages d\'avertissement depuis le parent. Aucun calcul de validation n\'est exécuté.',
179
179
  control: 'object',
180
180
  table: {
181
181
  type: { summary: 'array<string>' },
@@ -183,7 +183,7 @@ export function getValidationDocumentation(type: 'date' | 'number' | 'string' |
183
183
  },
184
184
  },
185
185
  successMessages: {
186
- description: 'Permet de forcer des messages de succès spécifiques.',
186
+ description: 'Permet d\'injecter des messages de succès depuis le parent. Aucun calcul de validation n\'est exécuté.',
187
187
  control: 'object',
188
188
  table: {
189
189
  type: { summary: 'array<string>' },
@@ -468,7 +468,8 @@ describe('useCustomValidation', () => {
468
468
  args.disableErrorHandling,
469
469
  ),
470
470
  )
471
- await result.validate()
471
+ const validationResult = await result.validate()
472
+ expect(validationResult.hasSuccess).toBe(true)
472
473
  expect(args.successes.value).toEqual([])
473
474
  })
474
475
 
@@ -1490,6 +1490,7 @@ describe('useValidation (unifyValidation)', () => {
1490
1490
  const { result } = withSetup(() => useValidation(params as Parameters<typeof useValidation>[0]))
1491
1491
 
1492
1492
  await result.validate()
1493
+ expect(result.hasSuccess.value).toBe(true)
1493
1494
  expect(result.successes.value).toContain('Succès externe')
1494
1495
  })
1495
1496
 
@@ -1510,9 +1511,30 @@ describe('useValidation (unifyValidation)', () => {
1510
1511
  const { result } = withSetup(() => useValidation(params as Parameters<typeof useValidation>[0]))
1511
1512
 
1512
1513
  await result.validate()
1514
+ expect(result.hasSuccess.value).toBe(true)
1513
1515
  expect(result.successes.value).not.toContain('Succès interne')
1514
1516
  expect(result.successes.value).toContain('Succès externe')
1515
1517
  })
1518
+
1519
+ it('keeps hasSuccess true when inner success messages are hidden', async () => {
1520
+ const params = makeParams({
1521
+ modelValue: ref('ok'),
1522
+ showSuccessMessages: ref(false),
1523
+ customRules: ref([]),
1524
+ customSuccessRules: ref([{
1525
+ type: 'custom',
1526
+ options: {
1527
+ validate: (value: unknown) => value === 'ok',
1528
+ successMessage: 'Succès interne',
1529
+ },
1530
+ }]),
1531
+ })
1532
+ const { result } = withSetup(() => useValidation(params as Parameters<typeof useValidation>[0]))
1533
+
1534
+ await result.validate()
1535
+ expect(result.hasSuccess.value).toBe(true)
1536
+ expect(result.successes.value).toEqual([])
1537
+ })
1516
1538
  })
1517
1539
 
1518
1540
  describe('rules concurrences', () => {