@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.
- package/dist/{AutocompleteFilter-D7qBuCAP.js → AutocompleteFilter-BPR-a55G.js} +1 -1
- package/dist/{DateFilter-BitMWrMU.js → DateFilter-CknrJWs2.js} +2 -2
- package/dist/{NumberFilter-BTLUxw0a.js → NumberFilter-DJ-yNlzv.js} +1 -1
- package/dist/{PeriodFilter-B5rUIPAC.js → PeriodFilter-CiB5Oa9Z.js} +1 -1
- package/dist/{SelectFilter-l4QnRcuk.js → SelectFilter-EiafX97M.js} +1 -1
- package/dist/{TextFilter-C9hj6Qrp.js → TextFilter-BzOmpdxj.js} +1 -1
- package/dist/{apLightTheme-DnIM24Lv.js → apLightTheme-DS0Uy44H.js} +20 -16
- package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +4 -2
- package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +60 -289
- package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +1 -0
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1 -0
- package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1 -0
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +2 -4
- package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +50 -49
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +29 -28
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +8 -8
- package/dist/components/DatePicker/composables/useDatePickerState.d.ts +3 -3
- package/dist/components/DatePicker/composables/useDateTextField.d.ts +2 -2
- package/dist/components/DatePicker/composables/useInputBlurHandler.d.ts +2 -2
- package/dist/components/DatePicker/types.d.ts +1 -2
- package/dist/components/LunarCalendar/useLunarCalendarValidation.d.ts +1 -0
- package/dist/components/MonthPicker/MonthPicker.d.ts +1 -1
- package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1 -1
- package/dist/components/NirField/NirField.d.ts +8 -4
- package/dist/components/NirField/useNirValidation.d.ts +6 -2
- package/dist/components/PeriodField/PeriodField.d.ts +102 -102
- package/dist/components/PhoneField/PhoneField.d.ts +11 -1
- package/dist/components/RangeField/RangeSlider/RangeSlider.d.ts +0 -3
- package/dist/components/RatingPicker/EmotionPicker/EmotionPicker.d.ts +3 -1
- package/dist/components/RatingPicker/NumberPicker/NumberPicker.d.ts +4 -3
- package/dist/components/RatingPicker/RatingPicker.d.ts +18 -5
- package/dist/components/RatingPicker/StarsPicker/StarsPicker.d.ts +3 -1
- package/dist/components/RatingPicker/tests/RatingPicker.a11y.spect.d.ts +1 -0
- package/dist/components/RatingPicker/useRatingFocus.d.ts +18 -0
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +4 -4
- package/dist/components/Tables/SyTable/SyTable.d.ts +4 -4
- package/dist/components/Tables/common/SyTablePagination.d.ts +152 -364
- package/dist/components/Tables/common/TableHeader.d.ts +1 -1
- package/dist/components/Tables/common/filters/DateFilter.d.ts +4 -4
- package/dist/composables/date/useDateInitializationDayjs.d.ts +3 -1
- package/dist/composables/unifyValidation/useCustomValidation.d.ts +3 -1
- package/dist/composables/unifyValidation/useValidation.d.ts +12 -6
- package/dist/composables/unifyValidation/useVuetifyValidation.d.ts +1 -1
- package/dist/composables/validation/useValidation.d.ts +1 -0
- package/dist/design-system-v3.js +2 -2
- package/dist/designTokens/tokens/amelipro/apLightTheme.d.ts +2 -0
- package/dist/designTokens/tokens/cnam/cnamLightTheme.d.ts +2 -0
- package/dist/{main-Cpx8Co6H.js → main-BsJ9ec3i.js} +9103 -9018
- package/dist/synapse.css +1 -1
- package/dist/vuetifyConfig.js +1 -1
- package/package.json +8 -7
- package/src/assets/overrides/_icons.scss +0 -13
- package/src/assets/overrides/_otp.scss +0 -1
- package/src/components/Accordion/Accordion.vue +2 -0
- package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +2 -1
- package/src/components/CookiesSelection/CookiesSelection.vue +2 -1
- package/src/components/CopyBtn/CopyBtn.vue +9 -0
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +1 -1
- package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +413 -96
- package/src/components/Customs/Selects/SySelect/SySelect.vue +270 -225
- package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +245 -6
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +3 -3
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +23 -2
- package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +23 -5
- package/src/components/Customs/SyTabs/SyTabs.stories.ts +5 -5
- package/src/components/Customs/SyTabs/config.ts +3 -3
- package/src/components/Customs/SyTextField/SyTextField.vue +31 -4
- package/src/components/DatePicker/CalendarMode/DatePicker.stories.ts +1 -1
- package/src/components/DatePicker/CalendarMode/DatePicker.vue +17 -14
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +1 -1
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +8 -7
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +1 -1
- package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.stories.ts +1 -1
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +57 -23
- package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +1 -1
- package/src/components/DatePicker/composables/useDatePickerState.ts +33 -14
- package/src/components/DatePicker/composables/useDateRangeInput.ts +2 -1
- package/src/components/DatePicker/composables/useDateSelection.ts +2 -1
- package/src/components/DatePicker/composables/useDateTextField.ts +2 -2
- package/src/components/DatePicker/composables/useInputBlurHandler.ts +2 -2
- package/src/components/DatePicker/types.ts +1 -2
- package/src/components/DialogBox/DialogBox.stories.ts +8 -8
- package/src/components/DialogBox/accessibilite/Accessibility.mdx +86 -22
- package/src/components/FilterSideBar/FilterSideBar.vue +2 -1
- package/src/components/LangBtn/LangBtn.vue +2 -1
- package/src/components/NotificationBar/Notification/Notification.vue +2 -2
- package/src/components/PaginatedTable/PaginatedTable.vue +1 -1
- package/src/components/PaginatedTable/Pagination.vue +1 -1
- package/src/components/PasswordField/PasswordField.vue +7 -3
- package/src/components/PhoneField/PhoneField.vue +4 -2
- package/src/components/RangeField/RangeSlider/RangeSlider.vue +11 -18
- package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +32 -48
- package/src/components/RatingPicker/EmotionPicker/tests/__snapshots__/EmotionPicker.spec.ts.snap +5 -0
- package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +48 -53
- package/src/components/RatingPicker/NumberPicker/tests/NumberPicker.spec.ts +2 -1
- package/src/components/RatingPicker/NumberPicker/tests/__snapshots__/NumberPicker.spec.ts.snap +40 -13
- package/src/components/RatingPicker/RatingPicker.stories.ts +65 -88
- package/src/components/RatingPicker/RatingPicker.vue +71 -15
- package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +28 -37
- package/src/components/RatingPicker/StarsPicker/tests/StarsPicker.spec.ts +1 -1
- package/src/components/RatingPicker/StarsPicker/tests/__snapshots__/StarsPicker.spec.ts.snap +5 -0
- package/src/components/RatingPicker/accessibilite/Accessibility.mdx +137 -9
- package/src/components/RatingPicker/tests/RatingPicker.a11y.spect.ts +123 -0
- package/src/components/RatingPicker/tests/RatingPicker.spec.ts +3 -2
- package/src/components/RatingPicker/tests/__snapshots__/RatingPicker.spec.ts.snap +40 -11
- package/src/components/RatingPicker/useRatingFocus.ts +97 -0
- package/src/components/SyTextArea/SyTextArea.vue +32 -1
- package/src/components/Tables/SyServerTable/SyServerTable.vue +1 -1
- package/src/components/Tables/SyTable/SyTable.vue +1 -1
- package/src/components/Tables/common/SyTableFilter.vue +4 -4
- package/src/components/Tables/common/SyTablePagination.vue +1 -0
- package/src/components/Tables/common/TableHeader.vue +1 -1
- package/src/components/Tables/common/filters/DateFilter.vue +2 -2
- package/src/composables/date/tests/useDateFormatDayjs.spec.ts +81 -0
- package/src/composables/date/tests/{useDateInitialization.spec.ts → useDateInitializationDayjs.spec.ts} +39 -3
- package/src/composables/date/useDateInitializationDayjs.ts +4 -1
- package/src/composables/unifyValidation/documentationValidationProps.ts +7 -7
- package/src/composables/unifyValidation/tests/useCustomValidation.spec.ts +2 -1
- package/src/composables/unifyValidation/tests/useValidation.spec.ts +22 -0
- package/src/composables/unifyValidation/useCustomValidation.ts +16 -4
- package/src/composables/unifyValidation/useValidation.ts +46 -15
- package/src/composables/unifyValidation/useVuetifyValidation.ts +2 -2
- package/src/composables/useFormFieldErrorHandling.ts +4 -1
- package/src/composables/validation/tests/useValidation.spec.ts +2 -2
- package/src/composables/validation/useValidation.ts +15 -3
- package/src/composantsVuetify/VCard/VCard.mdx +59 -0
- package/src/composantsVuetify/VCard/v-card.stories.ts +279 -0
- package/src/designTokens/tokens/amelipro/apColors2026.ts +1 -1
- package/src/designTokens/tokens/amelipro/apLightTheme.ts +3 -0
- package/src/designTokens/tokens/cnam/cnamLightTheme.ts +3 -0
- package/src/stories/Accessibilite/Aculturation/SensibilisationAccessibilite.mdx +61 -91
- package/src/stories/Accessibilite/AuditDesignSystem.mdx +5 -8
- package/src/stories/Accessibilite/AuditEtContreAudit/Exemptions-derogations.mdx +1 -1
- package/src/stories/Accessibilite/AuditEtContreAudit/Introduction.mdx +11 -8
- package/src/stories/Accessibilite/AuditEtContreAudit/RGAA.mdx +6 -7
- package/src/stories/Accessibilite/Introduction.mdx +30 -30
- package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +168 -78
- package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +13 -6
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +66 -45
- package/src/stories/Accessibilite/KitDePreAudit/Outils/LecteursDEcran.mdx +23 -49
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru/FauxPositifs.stories.ts +6 -0
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru/Utilisation.mdx +7 -19
- package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +18 -20
- package/src/stories/Components/Components.stories.ts +52 -3
- package/dist/AutocompleteFilter-Df9i5mAl.cjs +0 -1
- package/dist/DateFilter-BJD6FMev.cjs +0 -1
- package/dist/NumberFilter-DGCzCXzI.cjs +0 -1
- package/dist/PeriodFilter-DO_ecTZW.cjs +0 -1
- package/dist/SelectFilter-CGwcKWLm.cjs +0 -1
- package/dist/TextFilter-B8nf7xoK.cjs +0 -1
- package/dist/apLightTheme-CEK4iY3f.cjs +0 -1
- package/dist/composables/date/useDateFormat.d.ts +0 -26
- package/dist/composables/date/useDateInitialization.d.ts +0 -18
- package/dist/design-system-v3.umd.cjs +0 -1
- package/dist/main-ByDPHpae.cjs +0 -1067
- package/dist/tooth-11-D3sLWv2n.cjs +0 -1
- package/dist/tooth-12-CXrLuH03.cjs +0 -1
- package/dist/tooth-13-BSfo5fpT.cjs +0 -1
- package/dist/tooth-14-DMzulx0h.cjs +0 -1
- package/dist/tooth-15-BKRFVi-9.cjs +0 -1
- package/dist/tooth-16-CpuxAbuM.cjs +0 -1
- package/dist/tooth-17-BPoahUdg.cjs +0 -1
- package/dist/tooth-18-DhHJz8sy.cjs +0 -1
- package/dist/tooth-21-Dgd5hn_X.cjs +0 -1
- package/dist/tooth-22-C2Tn19sB.cjs +0 -1
- package/dist/tooth-23-C9uaaSGb.cjs +0 -1
- package/dist/tooth-24-BrK9UGpf.cjs +0 -1
- package/dist/tooth-25-CE_EfGNp.cjs +0 -1
- package/dist/tooth-26-Ctv4i9Fy.cjs +0 -1
- package/dist/tooth-27-C5J7JkWM.cjs +0 -1
- package/dist/tooth-28-Z9oWqjo0.cjs +0 -1
- package/dist/tooth-31-BrYqmkTi.cjs +0 -1
- package/dist/tooth-32-BNNR0oCZ.cjs +0 -1
- package/dist/tooth-33-DuxvqO2J.cjs +0 -1
- package/dist/tooth-34-BCSCXMB6.cjs +0 -1
- package/dist/tooth-35-BLUXkX88.cjs +0 -1
- package/dist/tooth-36-IrKHYqlA.cjs +0 -1
- package/dist/tooth-37-BYqpdMwo.cjs +0 -1
- package/dist/tooth-38-B_eNXXdu.cjs +0 -1
- package/dist/tooth-41-Ddva4Ot8.cjs +0 -1
- package/dist/tooth-42-szcDqlM0.cjs +0 -1
- package/dist/tooth-43-B3ka6rQm.cjs +0 -1
- package/dist/tooth-44-CazyQucj.cjs +0 -1
- package/dist/tooth-45-B4HQtc8n.cjs +0 -1
- package/dist/tooth-46-BPM40gbG.cjs +0 -1
- package/dist/tooth-47-Dvr20dlh.cjs +0 -1
- package/dist/tooth-48-Bd8ljGsF.cjs +0 -1
- package/dist/tooth-51-OBpwCOF3.cjs +0 -1
- package/dist/tooth-52-aKxyHcmq.cjs +0 -1
- package/dist/tooth-53-vCwJjTOc.cjs +0 -1
- package/dist/tooth-54-DsWu2iFy.cjs +0 -1
- package/dist/tooth-55-BxC1X2Dn.cjs +0 -1
- package/dist/tooth-61-BbLvxMQi.cjs +0 -1
- package/dist/tooth-62-CmTkWczP.cjs +0 -1
- package/dist/tooth-63-DI7l_2qI.cjs +0 -1
- package/dist/tooth-64-B21sOsJh.cjs +0 -1
- package/dist/tooth-65-D2ZC2VEr.cjs +0 -1
- package/dist/tooth-71-D473PPO5.cjs +0 -1
- package/dist/tooth-72-Drh1wnNu.cjs +0 -1
- package/dist/tooth-73-DzlwYI23.cjs +0 -1
- package/dist/tooth-74-8aGvcZPg.cjs +0 -1
- package/dist/tooth-75-BFK7At_r.cjs +0 -1
- package/dist/tooth-81-BZmR-I0M.cjs +0 -1
- package/dist/tooth-82-euVfUUZV.cjs +0 -1
- package/dist/tooth-83-KV010j64.cjs +0 -1
- package/dist/tooth-84-BBg1RjhZ.cjs +0 -1
- package/dist/tooth-85-Cr-kc1wM.cjs +0 -1
- package/dist/vuetifyConfig.umd.cjs +0 -1
- package/src/composables/date/tests/useDateFormat.spec.ts +0 -67
- package/src/composables/date/useDateFormat.ts +0 -110
- package/src/composables/date/useDateInitialization.ts +0 -92
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mount } from '@vue/test-utils'
|
|
2
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
3
3
|
import { VList } from 'vuetify/components'
|
|
4
|
+
import { nextTick } from 'vue'
|
|
4
5
|
import SySelect from '../SySelect.vue'
|
|
5
6
|
|
|
6
7
|
type ItemType = {
|
|
@@ -129,7 +130,7 @@ describe('SySelect.vue', () => {
|
|
|
129
130
|
it('renders error messages when provided', () => {
|
|
130
131
|
const errorMessages = ['Error 1']
|
|
131
132
|
const wrapper = mount(SySelect, {
|
|
132
|
-
props: { errorMessages,
|
|
133
|
+
props: { errorMessages, hideDetails: false },
|
|
133
134
|
attachTo: document.body,
|
|
134
135
|
})
|
|
135
136
|
const message = wrapper.find('.v-messages__message')
|
|
@@ -139,6 +140,99 @@ describe('SySelect.vue', () => {
|
|
|
139
140
|
wrapper.unmount()
|
|
140
141
|
})
|
|
141
142
|
|
|
143
|
+
describe('hideDetails', () => {
|
|
144
|
+
it('masque les messages de validation quand hideDetails est true', async () => {
|
|
145
|
+
const wrapper = mount(SySelect, {
|
|
146
|
+
props: {
|
|
147
|
+
errorMessages: ['Erreur de test'],
|
|
148
|
+
hideDetails: true,
|
|
149
|
+
},
|
|
150
|
+
attachTo: document.body,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
154
|
+
|
|
155
|
+
wrapper.unmount()
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('affiche les messages de validation quand hideDetails est false', async () => {
|
|
159
|
+
const wrapper = mount(SySelect, {
|
|
160
|
+
props: {
|
|
161
|
+
errorMessages: ['Erreur de test'],
|
|
162
|
+
hideDetails: false,
|
|
163
|
+
},
|
|
164
|
+
attachTo: document.body,
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
const message = wrapper.find('.v-messages__message')
|
|
168
|
+
expect(message.exists()).toBe(true)
|
|
169
|
+
expect(message.text()).toContain('Erreur de test')
|
|
170
|
+
|
|
171
|
+
wrapper.unmount()
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('affiche la zone de messages par défaut (hideDetails vaut false par défaut)', () => {
|
|
175
|
+
const wrapper = mount(SySelect, {
|
|
176
|
+
attachTo: document.body,
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
expect(wrapper.find('.v-messages').exists()).toBe(true)
|
|
180
|
+
|
|
181
|
+
wrapper.unmount()
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
it('n\'affiche pas le helpText en dessous du champ quand hideDetails est true et qu\'il y a des erreurs', () => {
|
|
185
|
+
const wrapper = mount(SySelect, {
|
|
186
|
+
props: {
|
|
187
|
+
helpText: 'Texte d\'aide',
|
|
188
|
+
errorMessages: ['Erreur de test'],
|
|
189
|
+
hideDetails: true,
|
|
190
|
+
},
|
|
191
|
+
attachTo: document.body,
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
expect(wrapper.find('.help-text-below').exists()).toBe(false)
|
|
195
|
+
|
|
196
|
+
wrapper.unmount()
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('affiche le helpText en dessous du champ quand hideDetails est false et qu\'il y a des erreurs', () => {
|
|
200
|
+
const wrapper = mount(SySelect, {
|
|
201
|
+
props: {
|
|
202
|
+
helpText: 'Texte d\'aide',
|
|
203
|
+
errorMessages: ['Erreur de test'],
|
|
204
|
+
hideDetails: false,
|
|
205
|
+
},
|
|
206
|
+
attachTo: document.body,
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
expect(wrapper.find('.help-text-below').exists()).toBe(true)
|
|
210
|
+
expect(wrapper.find('.help-text-below').text()).toContain('Texte d\'aide')
|
|
211
|
+
|
|
212
|
+
wrapper.unmount()
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it('keeps the label active when a validation error is displayed', async () => {
|
|
217
|
+
const wrapper = mount(SySelect, {
|
|
218
|
+
props: {
|
|
219
|
+
items: [{ text: 'Option 1', value: '1' }],
|
|
220
|
+
label: 'Option',
|
|
221
|
+
required: true,
|
|
222
|
+
},
|
|
223
|
+
attachTo: document.body,
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- exposed method is not part of the inferred public instance type
|
|
227
|
+
const isValid = await (wrapper.vm as any).validateOnSubmit()
|
|
228
|
+
await nextTick()
|
|
229
|
+
|
|
230
|
+
expect(isValid).toBe(false)
|
|
231
|
+
expect(wrapper.find('.v-field').classes()).toContain('v-field--active')
|
|
232
|
+
|
|
233
|
+
wrapper.unmount()
|
|
234
|
+
})
|
|
235
|
+
|
|
142
236
|
it('does not render error messages when not provided', () => {
|
|
143
237
|
const wrapper = mount(SySelect, {
|
|
144
238
|
attachTo: document.body,
|
|
@@ -522,25 +616,170 @@ describe('SySelect.vue', () => {
|
|
|
522
616
|
wrapper.unmount()
|
|
523
617
|
})
|
|
524
618
|
|
|
525
|
-
|
|
619
|
+
describe('disableErrorHandling', () => {
|
|
620
|
+
it('n\'affiche pas d\'erreur pour un champ requis sans valeur quand disableErrorHandling est true', async () => {
|
|
621
|
+
const wrapper = mount(SySelect, {
|
|
622
|
+
props: {
|
|
623
|
+
required: true,
|
|
624
|
+
label: 'Test Label',
|
|
625
|
+
modelValue: undefined,
|
|
626
|
+
disableErrorHandling: true,
|
|
627
|
+
},
|
|
628
|
+
attachTo: document.body,
|
|
629
|
+
})
|
|
630
|
+
|
|
631
|
+
await wrapper.find('.v-field').trigger('click')
|
|
632
|
+
await wrapper.vm.$nextTick()
|
|
633
|
+
await wrapper.find('.v-field').trigger('click')
|
|
634
|
+
await wrapper.vm.$nextTick()
|
|
635
|
+
|
|
636
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
637
|
+
const instance = wrapper.vm as any
|
|
638
|
+
expect(instance.hasError).toBe(false)
|
|
639
|
+
|
|
640
|
+
wrapper.unmount()
|
|
641
|
+
})
|
|
642
|
+
|
|
643
|
+
it('ignore les errorMessages quand disableErrorHandling est true', () => {
|
|
644
|
+
const wrapper = mount(SySelect, {
|
|
645
|
+
props: {
|
|
646
|
+
errorMessages: ['Erreur forcée'],
|
|
647
|
+
disableErrorHandling: true,
|
|
648
|
+
},
|
|
649
|
+
attachTo: document.body,
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
653
|
+
const instance = wrapper.vm as any
|
|
654
|
+
expect(instance.hasError).toBe(false)
|
|
655
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
656
|
+
|
|
657
|
+
wrapper.unmount()
|
|
658
|
+
})
|
|
659
|
+
|
|
660
|
+
it('n\'évalue pas les customRules quand disableErrorHandling est true', async () => {
|
|
661
|
+
const wrapper = mount(SySelect, {
|
|
662
|
+
props: {
|
|
663
|
+
modelValue: '1',
|
|
664
|
+
disableErrorHandling: true,
|
|
665
|
+
isValidateOnBlur: false,
|
|
666
|
+
customRules: [{
|
|
667
|
+
type: 'custom',
|
|
668
|
+
options: {
|
|
669
|
+
validate: () => false,
|
|
670
|
+
message: 'Toujours invalide',
|
|
671
|
+
},
|
|
672
|
+
}],
|
|
673
|
+
},
|
|
674
|
+
attachTo: document.body,
|
|
675
|
+
})
|
|
676
|
+
|
|
677
|
+
await wrapper.vm.$nextTick()
|
|
678
|
+
|
|
679
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
680
|
+
const instance = wrapper.vm as any
|
|
681
|
+
expect(instance.hasError).toBe(false)
|
|
682
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
683
|
+
|
|
684
|
+
wrapper.unmount()
|
|
685
|
+
})
|
|
686
|
+
|
|
687
|
+
it('affiche les erreurs normalement quand disableErrorHandling est false', async () => {
|
|
688
|
+
const wrapper = mount(SySelect, {
|
|
689
|
+
props: {
|
|
690
|
+
errorMessages: ['Erreur visible'],
|
|
691
|
+
disableErrorHandling: false,
|
|
692
|
+
},
|
|
693
|
+
attachTo: document.body,
|
|
694
|
+
})
|
|
695
|
+
|
|
696
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
697
|
+
const instance = wrapper.vm as any
|
|
698
|
+
expect(instance.hasError).toBe(true)
|
|
699
|
+
expect(wrapper.find('.v-messages__message').text()).toContain('Erreur visible')
|
|
700
|
+
|
|
701
|
+
wrapper.unmount()
|
|
702
|
+
})
|
|
703
|
+
})
|
|
704
|
+
|
|
705
|
+
it('valide immédiatement quand isValidateOnBlur est false', async () => {
|
|
526
706
|
const wrapper = mount(SySelect, {
|
|
527
707
|
props: {
|
|
528
|
-
|
|
708
|
+
items: [
|
|
709
|
+
{ text: 'Option 1', value: '1' },
|
|
710
|
+
{ text: 'Option 2', value: '2' },
|
|
711
|
+
],
|
|
529
712
|
label: 'Test Label',
|
|
530
713
|
modelValue: undefined,
|
|
531
|
-
|
|
714
|
+
isValidateOnBlur: false,
|
|
715
|
+
customRules: [{
|
|
716
|
+
type: 'custom',
|
|
717
|
+
options: {
|
|
718
|
+
validate: (value: unknown) => value === '2',
|
|
719
|
+
message: 'Test error message',
|
|
720
|
+
},
|
|
721
|
+
}],
|
|
532
722
|
},
|
|
533
723
|
attachTo: document.body,
|
|
534
724
|
})
|
|
535
725
|
|
|
726
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
727
|
+
const instance = wrapper.vm as any
|
|
728
|
+
expect(instance.hasError).toBe(false)
|
|
729
|
+
|
|
730
|
+
// Sélection de Option 1 via interaction utilisateur
|
|
536
731
|
await wrapper.find('.v-field').trigger('click')
|
|
537
732
|
await wrapper.vm.$nextTick()
|
|
733
|
+
await wrapper.findComponent(VList).findAll('.v-list-item').at(0)!.trigger('click')
|
|
734
|
+
await wrapper.setProps({ modelValue: '1' })
|
|
735
|
+
|
|
736
|
+
await vi.waitUntil(() => instance.hasError === true)
|
|
737
|
+
expect(wrapper.find('.v-messages').text()).toContain('Test error message')
|
|
738
|
+
|
|
739
|
+
// Sélection de Option 2 via interaction utilisateur
|
|
538
740
|
await wrapper.find('.v-field').trigger('click')
|
|
539
741
|
await wrapper.vm.$nextTick()
|
|
742
|
+
await wrapper.findComponent(VList).findAll('.v-list-item').at(1)!.trigger('click')
|
|
743
|
+
await wrapper.setProps({ modelValue: '2' })
|
|
744
|
+
|
|
745
|
+
await vi.waitUntil(() => instance.hasError === false)
|
|
746
|
+
expect(wrapper.find('.v-messages').text()).not.toContain('Test error message')
|
|
747
|
+
|
|
748
|
+
wrapper.unmount()
|
|
749
|
+
})
|
|
750
|
+
|
|
751
|
+
it('masque le message de succes mais conserve l\'etat de succes quand showSuccessMessages est false', async () => {
|
|
752
|
+
const wrapper = mount(SySelect, {
|
|
753
|
+
props: {
|
|
754
|
+
items: [
|
|
755
|
+
{ text: 'Option 1', value: '1' },
|
|
756
|
+
{ text: 'Option 2', value: '2' },
|
|
757
|
+
],
|
|
758
|
+
label: 'Test Label',
|
|
759
|
+
modelValue: undefined,
|
|
760
|
+
isValidateOnBlur: false,
|
|
761
|
+
showSuccessMessages: false,
|
|
762
|
+
customSuccessRules: [{
|
|
763
|
+
type: 'custom',
|
|
764
|
+
options: {
|
|
765
|
+
validate: (value: unknown) => value === '2',
|
|
766
|
+
successMessage: 'Test success message',
|
|
767
|
+
},
|
|
768
|
+
}],
|
|
769
|
+
},
|
|
770
|
+
attachTo: document.body,
|
|
771
|
+
})
|
|
540
772
|
|
|
541
773
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
542
774
|
const instance = wrapper.vm as any
|
|
543
|
-
expect(instance.
|
|
775
|
+
expect(instance.hasSuccess).toBe(false)
|
|
776
|
+
|
|
777
|
+
await wrapper.setProps({ modelValue: '2' })
|
|
778
|
+
|
|
779
|
+
await vi.waitUntil(() => instance.hasSuccess === true)
|
|
780
|
+
expect(wrapper.find('.success-field').exists()).toBe(true)
|
|
781
|
+
expect(wrapper.findAll('.v-messages__message')).toHaveLength(0)
|
|
782
|
+
expect(wrapper.text()).not.toContain('Test success message')
|
|
544
783
|
|
|
545
784
|
wrapper.unmount()
|
|
546
785
|
})
|
|
@@ -175,7 +175,7 @@
|
|
|
175
175
|
|
|
176
176
|
const errors = computed(() => validation.errors.value)
|
|
177
177
|
const warnings = computed(() => validation.warnings.value)
|
|
178
|
-
const
|
|
178
|
+
const displaySuccesses = computed(() => validation.displaySuccesses.value)
|
|
179
179
|
|
|
180
180
|
const labelId = computed(() => (props.id ? `${props.id}-label` : undefined))
|
|
181
181
|
const computedAriaLabelledby = computed(() => {
|
|
@@ -267,8 +267,8 @@
|
|
|
267
267
|
>
|
|
268
268
|
<VMessages
|
|
269
269
|
ref="messagesRef"
|
|
270
|
-
:active="hasError || hasWarning || (hasSuccess &&
|
|
271
|
-
:messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess
|
|
270
|
+
:active="hasError || hasWarning || (hasSuccess && displaySuccesses.length > 0)"
|
|
271
|
+
:messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess ? displaySuccesses : []))"
|
|
272
272
|
/>
|
|
273
273
|
</div>
|
|
274
274
|
|
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
|
|
205
205
|
const errors = computed(() => validation.errors.value)
|
|
206
206
|
const warnings = computed(() => validation.warnings.value)
|
|
207
|
-
const
|
|
207
|
+
const displaySuccesses = computed(() => validation.displaySuccesses.value)
|
|
208
208
|
|
|
209
209
|
const ariaChecked = computed(() => {
|
|
210
210
|
if (internalIndeterminate.value) return 'mixed'
|
|
@@ -347,6 +347,11 @@
|
|
|
347
347
|
:aria-labelledby="props.ariaLabelledby"
|
|
348
348
|
:title="props.title"
|
|
349
349
|
:color="props.color"
|
|
350
|
+
:class="{
|
|
351
|
+
'success-field': hasSuccess && !hasError && !hasWarning,
|
|
352
|
+
'warning-field': hasWarning && !hasError,
|
|
353
|
+
'error-field': hasError,
|
|
354
|
+
}"
|
|
350
355
|
:style="{ color: labelColor }"
|
|
351
356
|
:disabled="props.disabled"
|
|
352
357
|
:readonly="props.readonly"
|
|
@@ -354,7 +359,7 @@
|
|
|
354
359
|
:density="props.density"
|
|
355
360
|
:error="hasError"
|
|
356
361
|
:error-messages="errors"
|
|
357
|
-
:messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess
|
|
362
|
+
:messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess ? displaySuccesses : []))"
|
|
358
363
|
:indeterminate="internalIndeterminate"
|
|
359
364
|
:true-value="props.trueValue"
|
|
360
365
|
:false-value="props.falseValue"
|
|
@@ -387,6 +392,22 @@
|
|
|
387
392
|
</template>
|
|
388
393
|
|
|
389
394
|
<style scoped>
|
|
395
|
+
.success-field :deep(.v-messages__message) {
|
|
396
|
+
color: rgb(var(--v-theme-success)) !important;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.success-field :deep(.v-selection-control__input) {
|
|
400
|
+
color: rgb(var(--v-theme-success));
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.warning-field :deep(.v-messages__message) {
|
|
404
|
+
color: rgb(var(--v-theme-borderWarning)) !important;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.warning-field :deep(.v-selection-control__input) {
|
|
408
|
+
color: rgb(var(--v-theme-borderWarning));
|
|
409
|
+
}
|
|
410
|
+
|
|
390
411
|
:deep(.v-input--dirty .v-selection-control__input) {
|
|
391
412
|
color: v-bind('props.color');
|
|
392
413
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { computed, nextTick, onMounted, onUpdated, ref, watch } from 'vue'
|
|
4
4
|
import type { VRadioGroup } from 'vuetify/components'
|
|
5
|
+
import { VMessages } from 'vuetify/components'
|
|
5
6
|
import { useValidation, type ValidationRule } from '@/composables/validation/useValidation'
|
|
6
7
|
import { useValidatable } from '@/composables/validation/useValidatable'
|
|
7
8
|
import { locales } from './locales'
|
|
@@ -148,7 +149,7 @@
|
|
|
148
149
|
|
|
149
150
|
const errors = computed(() => validation.errors.value)
|
|
150
151
|
const warnings = computed(() => validation.warnings.value)
|
|
151
|
-
const
|
|
152
|
+
const displaySuccesses = computed(() => validation.displaySuccesses.value)
|
|
152
153
|
|
|
153
154
|
const getAriaChecked = (value: PropertyKey) => {
|
|
154
155
|
return model.value === value ? 'true' : 'false'
|
|
@@ -224,10 +225,6 @@
|
|
|
224
225
|
:error="hasError"
|
|
225
226
|
:error-messages="hasError ? errors : undefined"
|
|
226
227
|
:aria-describedby="messageId"
|
|
227
|
-
:messages="hasError ? errors :
|
|
228
|
-
hasWarning ? warnings :
|
|
229
|
-
(hasSuccess && props.showSuccessMessages ? successes : [])
|
|
230
|
-
"
|
|
231
228
|
>
|
|
232
229
|
<v-radio
|
|
233
230
|
v-for="opt in props.options"
|
|
@@ -258,14 +255,35 @@
|
|
|
258
255
|
{{ locales.labelledbyMessage }} <span v-if="props.label">{{ props.label + (props.displayAsterisk ? '*' : '')
|
|
259
256
|
}}</span>.
|
|
260
257
|
</span>
|
|
258
|
+
<template
|
|
259
|
+
v-if="!hasError && (hasWarning || hasSuccess)"
|
|
260
|
+
#details
|
|
261
|
+
>
|
|
262
|
+
<div class="v-input__details sy-radio-group__messages">
|
|
263
|
+
<VMessages
|
|
264
|
+
:active="hasWarning || (hasSuccess && displaySuccesses.length > 0)"
|
|
265
|
+
:messages="hasWarning ? warnings : displaySuccesses"
|
|
266
|
+
/>
|
|
267
|
+
</div>
|
|
268
|
+
</template>
|
|
261
269
|
</v-radio-group>
|
|
262
270
|
</template>
|
|
263
271
|
|
|
264
272
|
<style scoped>
|
|
273
|
+
:deep(.v-input__details) {
|
|
274
|
+
display: block !important;
|
|
275
|
+
padding-inline: 0 !important;
|
|
276
|
+
margin-top: -10px !important;
|
|
277
|
+
}
|
|
278
|
+
|
|
265
279
|
:deep(.v-selection-control--error .v-selection-control__input) {
|
|
266
280
|
color: rgb(var(--v-theme-error));
|
|
267
281
|
}
|
|
268
282
|
|
|
283
|
+
.sy-radio-group__messages {
|
|
284
|
+
align-items: flex-start;
|
|
285
|
+
}
|
|
286
|
+
|
|
269
287
|
.sb-show-main.sb-main-centered #storybook-root {
|
|
270
288
|
margin: none !important;
|
|
271
289
|
}
|
|
@@ -118,7 +118,7 @@ export const WithVModel: Story = {
|
|
|
118
118
|
Onglet actif: {{ activeTab }}
|
|
119
119
|
<button
|
|
120
120
|
class="ml-4 px-2 py-1 bg-primary text-white rounded"
|
|
121
|
-
@click="activeTab = activeTab === 'tab1' ? 'tab2' : 'tab1'"
|
|
121
|
+
@click="activeTab = activeTab === 'tab1' ? 'tab2' : activeTab === 'tab2' ? 'tab3' : 'tab1'"
|
|
122
122
|
>
|
|
123
123
|
Changer d'onglet
|
|
124
124
|
</button>
|
|
@@ -138,7 +138,7 @@ export const WithVModel: Story = {
|
|
|
138
138
|
Onglet actif: {{ activeTab }}
|
|
139
139
|
<button
|
|
140
140
|
class="ml-4 px-2 py-1 bg-primary text-white rounded"
|
|
141
|
-
@click="activeTab = activeTab === 'tab1' ? 'tab2' : 'tab1'"
|
|
141
|
+
@click="activeTab = activeTab === 'tab1' ? 'tab2' : activeTab === 'tab2' ? 'tab3' : 'tab1'"
|
|
142
142
|
>
|
|
143
143
|
Changer d'onglet
|
|
144
144
|
</button>
|
|
@@ -476,9 +476,9 @@ const items = [
|
|
|
476
476
|
export const NavigationMode: Story = {
|
|
477
477
|
args: {
|
|
478
478
|
items: [
|
|
479
|
-
{ label: 'Accueil', value: 'home', href: '
|
|
480
|
-
{ label: 'Profil', value: 'profile', href: '
|
|
481
|
-
{ label: 'Paramètres', value: 'settings', href: '
|
|
479
|
+
{ label: 'Accueil', value: 'home', href: 'javascript:void(0)' },
|
|
480
|
+
{ label: 'Profil', value: 'profile', href: 'javascript:void(0)' },
|
|
481
|
+
{ label: 'Paramètres', value: 'settings', href: 'javascript:void(0)' },
|
|
482
482
|
],
|
|
483
483
|
},
|
|
484
484
|
parameters: {
|
|
@@ -9,9 +9,9 @@ export const config = {
|
|
|
9
9
|
'show-arrows': true,
|
|
10
10
|
},
|
|
11
11
|
tab: {
|
|
12
|
-
'base-color': '
|
|
13
|
-
'active-color': '
|
|
14
|
-
'slider-color': '
|
|
12
|
+
'base-color': 'rgb(var(--v-theme-colorPrimary))',
|
|
13
|
+
'active-color': 'rgb(var(--v-theme-colorPrimary))',
|
|
14
|
+
'slider-color': 'rgb(var(--v-theme-colorPrimary))',
|
|
15
15
|
'ripple': false,
|
|
16
16
|
},
|
|
17
17
|
}
|
|
@@ -275,6 +275,13 @@
|
|
|
275
275
|
return 'rgba(0, 0, 0, 1)'
|
|
276
276
|
})
|
|
277
277
|
|
|
278
|
+
const clearButtonColorClass = computed(() => {
|
|
279
|
+
if (hasError.value) return 'error-field'
|
|
280
|
+
if (hasWarning.value) return 'warning-field'
|
|
281
|
+
if (hasSuccess.value) return 'success-field'
|
|
282
|
+
return 'text-iconBase'
|
|
283
|
+
})
|
|
284
|
+
|
|
278
285
|
const handlePrependIconClick = () => {
|
|
279
286
|
emit('prepend-icon-click')
|
|
280
287
|
}
|
|
@@ -346,7 +353,7 @@
|
|
|
346
353
|
const validationIcon = computed(() => {
|
|
347
354
|
if (hasError.value) return ICONS['error']
|
|
348
355
|
if (hasWarning.value) return ICONS['warning']
|
|
349
|
-
if (hasSuccess.value
|
|
356
|
+
if (hasSuccess.value) return ICONS['success']
|
|
350
357
|
return null
|
|
351
358
|
})
|
|
352
359
|
|
|
@@ -361,7 +368,7 @@
|
|
|
361
368
|
// Détermine s'il y a des messages d'erreur ou d'état
|
|
362
369
|
const hasMessages = computed(() => {
|
|
363
370
|
if (props.disableErrorHandling) return false
|
|
364
|
-
return (props.errorMessages?.length ?? 0) > 0 || hasError.value || hasWarning.value || hasSuccess.value
|
|
371
|
+
return (props.errorMessages?.length ?? 0) > 0 || hasError.value || hasWarning.value || (hasSuccess.value && props.showSuccessMessages)
|
|
365
372
|
})
|
|
366
373
|
|
|
367
374
|
// Détermine si le helpText doit être affiché à la position du message ou en dessous
|
|
@@ -634,7 +641,7 @@
|
|
|
634
641
|
:maxlength="props.maxlength"
|
|
635
642
|
:max-errors="props.maxErrors"
|
|
636
643
|
:max-width="props.maxWidth"
|
|
637
|
-
:messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess
|
|
644
|
+
:messages="hasError ? errors : (hasWarning ? warnings : (hasSuccess ? (props.showSuccessMessages ? successes : []) : messages))"
|
|
638
645
|
:min-width="props.minWidth"
|
|
639
646
|
:name="props.name"
|
|
640
647
|
:persistent-clear="props.displayPersistentClear"
|
|
@@ -778,7 +785,8 @@
|
|
|
778
785
|
<!-- Keyboard-focusable clear button -->
|
|
779
786
|
<VBtn
|
|
780
787
|
v-if="showClear"
|
|
781
|
-
class="v-btn v-btn--density-compact mr-1
|
|
788
|
+
class="v-btn v-btn--density-compact mr-1"
|
|
789
|
+
:class="clearButtonColorClass"
|
|
782
790
|
:aria-label="props.label ? `Vider ${props.label}` : 'Vider'"
|
|
783
791
|
:title="props.label ? `Vider ${props.label}` : 'Vider'"
|
|
784
792
|
:icon="mdiClose"
|
|
@@ -849,7 +857,11 @@
|
|
|
849
857
|
:deep(.v-field) {
|
|
850
858
|
color: rgb(var(--v-theme-borderWarning)) !important;
|
|
851
859
|
|
|
860
|
+
--v-medium-emphasis-opacity: 1;
|
|
861
|
+
|
|
852
862
|
.v-field__outline {
|
|
863
|
+
--v-field-border-opacity: 1;
|
|
864
|
+
|
|
853
865
|
color: rgb(var(--v-theme-borderWarning)) !important;
|
|
854
866
|
}
|
|
855
867
|
}
|
|
@@ -863,6 +875,13 @@
|
|
|
863
875
|
}
|
|
864
876
|
}
|
|
865
877
|
|
|
878
|
+
/* stylelint-disable-next-line selector-class-pattern */
|
|
879
|
+
.text-iconBase {
|
|
880
|
+
:deep(.v-icon__svg) {
|
|
881
|
+
fill: rgb(var(--v-theme-borderAccentPrimary)) !important;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
866
885
|
.error-field {
|
|
867
886
|
:deep(.v-input__details > .v-icon),
|
|
868
887
|
:deep(.v-input__prepend > .v-icon),
|
|
@@ -870,10 +889,16 @@
|
|
|
870
889
|
opacity: 1 !important;
|
|
871
890
|
}
|
|
872
891
|
|
|
892
|
+
:deep(.v-icon__svg) {
|
|
893
|
+
fill: rgb(var(--v-theme-textError)) !important;
|
|
894
|
+
}
|
|
895
|
+
|
|
873
896
|
:deep(.v-field) {
|
|
874
897
|
color: rgb(var(--v-theme-borderError)) !important;
|
|
875
898
|
|
|
876
899
|
.v-field__outline {
|
|
900
|
+
--v-field-border-opacity: 1;
|
|
901
|
+
|
|
877
902
|
color: rgb(var(--v-theme-borderError)) !important;
|
|
878
903
|
}
|
|
879
904
|
}
|
|
@@ -904,6 +929,8 @@
|
|
|
904
929
|
--v-medium-emphasis-opacity: 1;
|
|
905
930
|
|
|
906
931
|
.v-field__outline {
|
|
932
|
+
--v-field-border-opacity: 1;
|
|
933
|
+
|
|
907
934
|
color: rgb(var(--v-theme-borderSuccess)) !important;
|
|
908
935
|
}
|
|
909
936
|
}
|
|
@@ -172,7 +172,7 @@ const meta = {
|
|
|
172
172
|
},
|
|
173
173
|
'birthDate': {
|
|
174
174
|
control: 'boolean',
|
|
175
|
-
description: '
|
|
175
|
+
description: '⚠️ **DEPRECATED** — Utilisez `isBirthDate` à la place.',
|
|
176
176
|
defaultValue: false,
|
|
177
177
|
},
|
|
178
178
|
'isOutlined': {
|