@cnamts/synapse 1.1.0 → 1.1.1
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-DXd4szWO.js → AutocompleteFilter-CGF33skz.js} +1 -1
- package/dist/{DateFilter-BD59Kgwf.js → DateFilter-D7-MsKtx.js} +1 -1
- package/dist/{NumberFilter-BSMZE7uw.js → NumberFilter-bjQPPfsj.js} +1 -1
- package/dist/{PeriodFilter-keUdSSk0.js → PeriodFilter-B3wJpK8-.js} +1 -1
- package/dist/{SelectFilter-Dhvvwazl.js → SelectFilter-BN6DbKAV.js} +1 -1
- package/dist/{TextFilter-CU8FpXz0.js → TextFilter-BffP0J2f.js} +1 -1
- package/dist/{apLightTheme2026-DbS7BPUf.js → apLightTheme2026-C4ygwMHC.js} +11 -11
- package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +6 -6
- package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +6 -6
- package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +6 -6
- package/dist/components/Captcha/Captcha.d.ts +27 -16
- package/dist/components/Captcha/CaptchaForm.d.ts +29 -3
- package/dist/components/Captcha/types.d.ts +14 -0
- package/dist/components/Captcha/useCaptchaValidation.d.ts +37 -0
- package/dist/components/Customs/Selects/SelectBtnField/SelectBtnField.d.ts +33 -13
- package/dist/components/Customs/Selects/SelectBtnField/composables/useSelectBtnFieldValidation.d.ts +23 -0
- package/dist/components/Customs/Selects/SyAutocomplete/composables/useSyAutocompleteValidation.d.ts +2 -2
- package/dist/components/Customs/Selects/SySelect/composables/useSySelectValidation.d.ts +2 -2
- package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +17 -48
- package/dist/components/Customs/SyCheckBoxGroup/composables/useSyCheckBoxGroupValidation.d.ts +29 -0
- package/dist/components/Customs/SyCheckBoxGroup/types.d.ts +46 -0
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +16 -51
- package/dist/components/Customs/SyCheckbox/composables/useSyCheckboxValidation.d.ts +27 -0
- package/dist/components/Customs/SyCheckbox/types.d.ts +49 -0
- package/dist/components/Customs/SyTextField/FieldState.d.ts +5 -0
- package/dist/components/Customs/SyTextField/useSyTextFieldValidation.d.ts +3 -3
- package/dist/components/DialogBox/DialogBox.d.ts +2 -0
- package/dist/components/DialogBox/locales.d.ts +1 -0
- package/dist/components/FilterSideBar/FilterSideBar.d.ts +4 -0
- package/dist/components/LunarCalendar/LunarCalendar.d.ts +43 -14
- package/dist/components/LunarCalendar/types.d.ts +35 -0
- package/dist/components/LunarCalendar/useLunarCalendarValidation.d.ts +11 -12
- package/dist/components/MonthPicker/MonthPicker.d.ts +72 -1747
- package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +21 -1733
- package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +5 -0
- package/dist/components/MonthPicker/locales.d.ts +1 -0
- package/dist/components/MonthPicker/types.d.ts +11 -0
- package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +37 -24
- package/dist/components/NirField/NirField.d.ts +6 -4
- package/dist/components/NirField/useNirValidation.d.ts +7 -5
- package/dist/components/PageContainer/PageContainer.d.ts +8 -0
- package/dist/components/PasswordField/PasswordField.d.ts +2 -2
- package/dist/components/PasswordField/usePasswordFieldValidation.d.ts +2 -2
- package/dist/components/PhoneField/PhoneField.d.ts +960 -1938
- package/dist/components/PhoneField/indicatifs.d.ts +715 -8
- package/dist/components/PhoneField/locales.d.ts +7 -0
- package/dist/components/PhoneField/types.d.ts +29 -0
- package/dist/components/PhoneField/usePhoneFieldValidation.d.ts +45 -0
- package/dist/components/PhoneField/usePhoneIndicatifs.d.ts +947 -0
- package/dist/components/SyTextArea/composables/useSyTextAreaValidation.d.ts +2 -2
- package/dist/composables/unifyValidation/documentationValidationProps.d.ts +1 -1
- package/dist/composables/unifyValidation/useValidation.d.ts +4 -5
- package/dist/design-system-v3.js +2 -2
- package/dist/designTokens/tokens/amelipro/apLightTheme.d.ts +10 -10
- package/dist/designTokens/tokens/baseTokens.d.ts +18 -18
- package/dist/designTokens/tokens/cnam/cnamLightTheme.d.ts +10 -10
- package/dist/designTokens/tokens/pa/paLightTheme.d.ts +10 -10
- package/dist/designTokens/tokens/semanticTokens.d.ts +14 -14
- package/dist/{main-D8ryUoS5.js → main-C4wAktOs.js} +13718 -12991
- package/dist/synapse.css +1 -1
- package/dist/vuetifyConfig.js +1 -1
- package/package.json +7 -7
- package/src/assets/compat/_legacy-tokens.scss +91 -0
- package/src/assets/overrides/_utilities.scss +23 -0
- package/src/components/Accordion/Accordion.stories.ts +121 -1
- package/src/components/BackBtn/BackBtn.mdx +1 -1
- package/src/components/BackToTopBtn/BackToTopBtn.mdx +0 -1
- package/src/components/Captcha/Captcha.stories.ts +134 -31
- package/src/components/Captcha/Captcha.vue +95 -28
- package/src/components/Captcha/CaptchaForm.vue +51 -22
- package/src/components/Captcha/tests/Captcha.focus.spec.ts +214 -0
- package/src/components/Captcha/tests/Captcha.spec.ts +233 -24
- package/src/components/Captcha/tests/CaptchaForm.spec.ts +82 -0
- package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +16 -42
- package/src/components/Captcha/types.ts +15 -0
- package/src/components/Captcha/useCaptchaValidation.ts +87 -0
- package/src/components/Captcha/validation/validation.stories.ts +1194 -0
- package/src/components/ChipList/ChipList.mdx +0 -1
- package/src/components/CollapsibleList/CollapsibleList.mdx +0 -1
- package/src/components/CookieBanner/CookieBanner.mdx +0 -1
- package/src/components/CopyBtn/CopyBtn.mdx +0 -1
- package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.stories.ts +123 -439
- package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.vue +147 -41
- package/src/components/Customs/Selects/SelectBtnField/Validation/Validation.stories.ts +600 -0
- package/src/components/Customs/Selects/SelectBtnField/composables/useSelectBtnFieldValidation.ts +87 -0
- package/src/components/Customs/Selects/SelectBtnField/tests/SelectBtnField.spec.ts +402 -33
- package/src/components/Customs/Selects/SelectBtnField/tests/__snapshots__/SelectBtnField.spec.ts.snap +52 -38
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +342 -162
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +77 -129
- package/src/components/Customs/SyCheckBoxGroup/Validation/Validation.stories.ts +1008 -0
- package/src/components/Customs/SyCheckBoxGroup/composables/useSyCheckBoxGroupValidation.ts +107 -0
- package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.spec.ts +180 -7
- package/src/components/Customs/SyCheckBoxGroup/types.ts +49 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +41 -161
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +71 -148
- package/src/components/Customs/SyCheckbox/Validation/Validation.stories.ts +654 -0
- package/src/components/Customs/SyCheckbox/composables/useSyCheckboxValidation.ts +105 -0
- package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +106 -0
- package/src/components/Customs/SyCheckbox/tests/useSyCheckboxValidation.spec.ts +98 -0
- package/src/components/Customs/SyCheckbox/types.ts +51 -0
- package/src/components/Customs/SyTextField/FieldState.vue +50 -0
- package/src/components/Customs/SyTextField/SyTextField.vue +12 -9
- package/src/components/Customs/SyTextField/useSyTextFieldValidation.ts +2 -11
- package/src/components/DataList/DataList.mdx +0 -1
- package/src/components/DataListGroup/DataListGroup.mdx +0 -1
- package/src/components/DiacriticPicker/DiacriticPicker.mdx +0 -1
- package/src/components/DialogBox/DialogBox.mdx +0 -1
- package/src/components/DialogBox/DialogBox.stories.ts +399 -4
- package/src/components/DialogBox/DialogBox.vue +20 -0
- package/src/components/DialogBox/locales.ts +1 -0
- package/src/components/DialogBox/tests/DialogBox.spec.ts +73 -0
- package/src/components/DialogBox/tests/DialogBox.visual.cy.ts +24 -0
- package/src/components/ErrorPage/ErrorPage.mdx +1 -1
- package/src/components/ExternalLinks/ExternalLinks.mdx +0 -1
- package/src/components/FileList/FileList.mdx +0 -1
- package/src/components/FilterInline/FilterInline.mdx +0 -1
- package/src/components/FilterSideBar/FilterSideBar.mdx +8 -1
- package/src/components/FilterSideBar/FilterSideBar.stories.ts +133 -1
- package/src/components/FilterSideBar/FilterSideBar.vue +19 -2
- package/src/components/FilterSideBar/tests/FilterSideBar.spec.ts +55 -0
- package/src/components/FooterBar/FooterBar.mdx +0 -1
- package/src/components/FranceConnectBtn/FranceConnectBtn.mdx +0 -1
- package/src/components/HeaderBar/HeaderBar.mdx +0 -1
- package/src/components/HeaderLoading/HeaderLoading.mdx +0 -1
- package/src/components/LangBtn/LangBtn.mdx +0 -1
- package/src/components/Logo/Logo.mdx +1 -1
- package/src/components/LunarCalendar/LunarCalendar.mdx +6 -9
- package/src/components/LunarCalendar/LunarCalendar.stories.ts +243 -46
- package/src/components/LunarCalendar/LunarCalendar.vue +61 -26
- package/src/components/LunarCalendar/Validation/Validation.stories.ts +717 -0
- package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +1 -1
- package/src/components/LunarCalendar/tests/LunarCalendar.spec.ts +197 -6
- package/src/components/LunarCalendar/tests/useLunarCalendarValidation.spec.ts +287 -0
- package/src/components/LunarCalendar/types.ts +39 -0
- package/src/components/LunarCalendar/useLunarCalendarValidation.ts +115 -39
- package/src/components/MonthPicker/MonthPicker.stories.ts +38 -281
- package/src/components/MonthPicker/MonthPicker.vue +66 -17
- package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +44 -20
- package/src/components/MonthPicker/MonthPickerText/useTextField.ts +5 -0
- package/src/components/MonthPicker/Validation/Validation.stories.ts +1117 -0
- package/src/components/MonthPicker/locales.ts +1 -0
- package/src/components/MonthPicker/tests/MonthPicker.spec.ts +353 -2
- package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +12 -8
- package/src/components/MonthPicker/types.ts +16 -0
- package/src/components/MonthPicker/useMonthPickerValidation.ts +64 -27
- package/src/components/NirField/NirField.mdx +120 -66
- package/src/components/NirField/NirField.stories.ts +216 -0
- package/src/components/NirField/useNirValidation.ts +16 -17
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +263 -245
- package/src/components/NotificationBar/NotificationBar.mdx +0 -1
- package/src/components/PageContainer/PageContainer.mdx +0 -1
- package/src/components/PageContainer/PageContainer.stories.ts +170 -2
- package/src/components/PageContainer/PageContainer.vue +63 -8
- package/src/components/PageContainer/tests/__snapshots__/PageContainer.spec.ts.snap +19 -11
- package/src/components/PaginatedTable/PaginatedTable.mdx +0 -1
- package/src/components/PeriodField/PeriodField.mdx +0 -1
- package/src/components/PhoneField/PhoneField.mdx +2 -3
- package/src/components/PhoneField/PhoneField.stories.ts +227 -410
- package/src/components/PhoneField/PhoneField.vue +204 -438
- package/src/components/PhoneField/indicatifs.ts +1 -1
- package/src/components/PhoneField/locales.ts +7 -0
- package/src/components/PhoneField/tests/PhoneField.a11y.spec.ts +0 -1
- package/src/components/PhoneField/tests/PhoneField.spec.ts +517 -220
- package/src/components/PhoneField/types.ts +30 -0
- package/src/components/PhoneField/usePhoneFieldValidation.ts +119 -0
- package/src/components/PhoneField/usePhoneIndicatifs.ts +89 -0
- package/src/components/PhoneField/validation/validation.stories.ts +717 -0
- package/src/components/RangeField/RangeField.mdx +0 -1
- package/src/components/RatingPicker/RatingPicker.mdx +0 -1
- package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +0 -1
- package/src/components/StatusPage/StatusPage.vue +1 -0
- package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +248 -230
- package/src/components/SubHeader/SubHeader.mdx +5 -6
- package/src/components/Tables/common/tests/SyTableFilter.spec.ts +11 -12
- package/src/components/UploadWorkflow/UploadWorkflow.mdx +0 -1
- package/src/components/UserMenuBtn/UserMenuBtn.mdx +0 -1
- package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +177 -0
- package/src/composables/unifyValidation/documentationValidationProps.ts +1 -1
- package/src/composables/unifyValidation/tests/useValidation.spec.ts +13 -1
- package/src/composables/unifyValidation/useValidation.ts +37 -33
- package/src/composantsVuetify/VCard/VCard.mdx +4 -0
- package/src/composantsVuetify/VCard/v-card.stories.ts +93 -1
- package/src/composantsVuetify/VCarousel/VCarousel.mdx +74 -0
- package/src/composantsVuetify/VCarousel/v-carousel.stories.ts +531 -0
- package/src/composantsVuetify/VNavigationDrawer/VNavgationDrawer.mdx +53 -0
- package/src/composantsVuetify/VNavigationDrawer/v-navigation-drawer.stories.ts +310 -0
- package/src/composantsVuetify/VSlideGroup/VSlideGroup.mdx +105 -0
- package/src/composantsVuetify/VSlideGroup/v-slide-group.stories.ts +463 -0
- package/src/designTokens/tokens/baseColors.ts +1 -1
- package/src/designTokens/tokens/baseTokens.ts +18 -18
- package/src/stories/Components/Components.stories.ts +34 -1
- package/src/stories/Demarrer/Releases.stories.ts +16 -2
- package/src/stories/DesignTokens/Arrondis.mdx +1 -1
- package/src/stories/DesignTokens/Correspondances.mdx +219 -0
- package/src/stories/DesignTokens/UtiliserLesTokens.mdx +235 -0
- package/src/stories/DesignTokens/colors.stories.ts +569 -569
- package/src/stories/GuideDuDev/Amelipro.stories.ts +335 -267
- package/dist/components/LunarCalendar/useLunarCalendarRules.d.ts +0 -5
- package/dist/components/PhoneField/tests/types.d.ts +0 -18
- package/src/components/LunarCalendar/tests/useLunarCalendarRules.spec.ts +0 -184
- package/src/components/LunarCalendar/useLunarCalendarRules.ts +0 -96
- package/src/components/PhoneField/tests/types.d.ts +0 -19
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { computed, ref, toRef, type ComputedRef, type Ref } from 'vue'
|
|
2
|
+
import { useValidation, type ValidationRule } from '@/composables/unifyValidation/useValidation'
|
|
3
|
+
import type { SyCheckboxValidationProps } from '../types'
|
|
4
|
+
|
|
5
|
+
export interface UseSyCheckboxValidationReturn {
|
|
6
|
+
validate: () => Promise<boolean>
|
|
7
|
+
validateOnSubmit: () => Promise<boolean>
|
|
8
|
+
clearValidation: () => void
|
|
9
|
+
errors: Ref<string[]>
|
|
10
|
+
warnings: Ref<string[]>
|
|
11
|
+
successes: Ref<string[]>
|
|
12
|
+
hasError: ComputedRef<boolean | undefined>
|
|
13
|
+
hasWarning: ComputedRef<boolean | undefined>
|
|
14
|
+
hasSuccess: ComputedRef<boolean | undefined>
|
|
15
|
+
defaultRules: ComputedRef<ValidationRule[]>
|
|
16
|
+
focused: Ref<boolean>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Composable de validation du composant SyCheckbox
|
|
21
|
+
*
|
|
22
|
+
* Version simplifiée du système unifié : pour une case à cocher, « required » signifie
|
|
23
|
+
* que la case doit être cochée (`value === true`). On utilise donc une règle `custom`
|
|
24
|
+
* plutôt que la règle `required` générique, qui considère `false` comme une valeur valide.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* const { validate, errors, hasError } = useSyCheckboxValidation(props, model, focused)
|
|
28
|
+
*/
|
|
29
|
+
export function useSyCheckboxValidation(
|
|
30
|
+
props: SyCheckboxValidationProps,
|
|
31
|
+
model: Ref<boolean | null>,
|
|
32
|
+
focused?: Ref<boolean>,
|
|
33
|
+
): UseSyCheckboxValidationReturn {
|
|
34
|
+
const focusedRef = focused !== undefined ? focused : ref(false)
|
|
35
|
+
|
|
36
|
+
// « required » pour une case = doit être cochée (true)
|
|
37
|
+
const defaultRules = computed<ValidationRule[]>(() =>
|
|
38
|
+
props.required
|
|
39
|
+
? [{
|
|
40
|
+
type: 'custom',
|
|
41
|
+
options: {
|
|
42
|
+
validate: (value: unknown) => value === true,
|
|
43
|
+
message: `Le champ ${props.label || 'ce champ'} est requis.`,
|
|
44
|
+
fieldIdentifier: props.label,
|
|
45
|
+
},
|
|
46
|
+
}]
|
|
47
|
+
: [],
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
// Vuetify ne gère pas les messages de succès : on les désactive en mode Vuetify
|
|
51
|
+
const effectiveShowSuccessMessages = computed(() =>
|
|
52
|
+
props.useVuetifyValidation ? false : (props.showSuccessMessages ?? false),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
const {
|
|
56
|
+
validate,
|
|
57
|
+
clearValidation,
|
|
58
|
+
errors,
|
|
59
|
+
warnings,
|
|
60
|
+
successes,
|
|
61
|
+
hasError,
|
|
62
|
+
hasWarning,
|
|
63
|
+
hasSuccess,
|
|
64
|
+
} = useValidation({
|
|
65
|
+
modelValue: model,
|
|
66
|
+
readonly: toRef(() => props.readonly ?? false),
|
|
67
|
+
disabled: toRef(() => props.disabled ?? false),
|
|
68
|
+
required: toRef(() => props.required ?? false),
|
|
69
|
+
isValidateOnBlur: toRef(() => props.isValidateOnBlur ?? false),
|
|
70
|
+
showSuccessMessages: effectiveShowSuccessMessages,
|
|
71
|
+
disableErrorHandling: toRef(() => props.disableErrorHandling ?? false),
|
|
72
|
+
useVuetifyValidation: toRef(() => props.useVuetifyValidation ?? false),
|
|
73
|
+
label: toRef(() => props.label ?? ''),
|
|
74
|
+
rules: toRef(() => props.rules),
|
|
75
|
+
customRules: computed(() => [...defaultRules.value, ...(props.customRules ?? [])]),
|
|
76
|
+
customWarningRules: toRef(() => props.customWarningRules ?? []),
|
|
77
|
+
customSuccessRules: toRef(() => props.customSuccessRules ?? []),
|
|
78
|
+
errorMessages: toRef(() => props.errorMessages ?? null),
|
|
79
|
+
warningMessages: toRef(() => props.warningMessages ?? null),
|
|
80
|
+
successMessages: toRef(() => props.successMessages ?? null),
|
|
81
|
+
hasErrorProp: toRef(() => props.hasError ?? false),
|
|
82
|
+
hasWarningProp: toRef(() => props.hasWarning ?? false),
|
|
83
|
+
hasSuccessProp: toRef(() => props.hasSuccess ?? false),
|
|
84
|
+
maxErrors: toRef(() => props.maxErrors ?? 1),
|
|
85
|
+
focused: focusedRef,
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const validateOnSubmit = async (): Promise<boolean> => {
|
|
89
|
+
return await validate()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
validate,
|
|
94
|
+
validateOnSubmit,
|
|
95
|
+
clearValidation,
|
|
96
|
+
errors,
|
|
97
|
+
warnings,
|
|
98
|
+
successes,
|
|
99
|
+
hasError,
|
|
100
|
+
hasWarning,
|
|
101
|
+
hasSuccess,
|
|
102
|
+
defaultRules,
|
|
103
|
+
focused: focusedRef,
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -178,4 +178,110 @@ describe('SyCheckbox', () => {
|
|
|
178
178
|
await wrapper.find('.v-checkbox').trigger('click')
|
|
179
179
|
expect(wrapper.emitted('update:modelValue')).toBeFalsy()
|
|
180
180
|
})
|
|
181
|
+
|
|
182
|
+
it('affiche le helpText quand aucun message de validation n\'est présent', () => {
|
|
183
|
+
const wrapper = mount(SyCheckbox, {
|
|
184
|
+
props: {
|
|
185
|
+
label: 'CGU',
|
|
186
|
+
helpText: 'Texte d\'aide',
|
|
187
|
+
},
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
const help = wrapper.find('.help-text-below')
|
|
191
|
+
expect(help.exists()).toBe(true)
|
|
192
|
+
expect(help.text()).toContain('Texte d\'aide')
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('masque le helpText et affiche l\'erreur quand la validation échoue', async () => {
|
|
196
|
+
const wrapper = mount(SyCheckbox, {
|
|
197
|
+
props: {
|
|
198
|
+
label: 'CGU',
|
|
199
|
+
helpText: 'Texte d\'aide',
|
|
200
|
+
required: true,
|
|
201
|
+
modelValue: false,
|
|
202
|
+
},
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
await wrapper.vm.validateOnSubmit()
|
|
206
|
+
await nextTick()
|
|
207
|
+
|
|
208
|
+
expect(wrapper.find('.help-text-below').exists()).toBe(false)
|
|
209
|
+
expect(wrapper.find('.v-messages').text()).toContain('CGU est requis')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('disableErrorHandling : aucune erreur affichée même si requis et décoché', async () => {
|
|
213
|
+
const wrapper = mount(SyCheckbox, {
|
|
214
|
+
props: {
|
|
215
|
+
label: 'CGU',
|
|
216
|
+
required: true,
|
|
217
|
+
disableErrorHandling: true,
|
|
218
|
+
modelValue: false,
|
|
219
|
+
},
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
const isValid = await wrapper.vm.validateOnSubmit()
|
|
223
|
+
await nextTick()
|
|
224
|
+
|
|
225
|
+
expect(isValid).toBe(true)
|
|
226
|
+
expect(wrapper.find('.error-field').exists()).toBe(false)
|
|
227
|
+
expect(wrapper.find('.v-messages__message').exists()).toBe(false)
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('affiche un message d\'avertissement via customWarningRules', async () => {
|
|
231
|
+
const wrapper = mount(SyCheckbox, {
|
|
232
|
+
props: {
|
|
233
|
+
label: 'CGU',
|
|
234
|
+
modelValue: false,
|
|
235
|
+
customWarningRules: [{
|
|
236
|
+
type: 'custom',
|
|
237
|
+
options: {
|
|
238
|
+
validate: (value: boolean) => value === true,
|
|
239
|
+
warningMessage: 'Avertissement de test',
|
|
240
|
+
},
|
|
241
|
+
}],
|
|
242
|
+
},
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
await wrapper.vm.validateOnSubmit()
|
|
246
|
+
await nextTick()
|
|
247
|
+
|
|
248
|
+
expect(wrapper.find('.warning-field').exists()).toBe(true)
|
|
249
|
+
expect(wrapper.find('.v-messages').text()).toContain('Avertissement de test')
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
it('affiche un message de succès via customSuccessRules et showSuccessMessages', async () => {
|
|
253
|
+
const wrapper = mount(SyCheckbox, {
|
|
254
|
+
props: {
|
|
255
|
+
label: 'CGU',
|
|
256
|
+
modelValue: true,
|
|
257
|
+
showSuccessMessages: true,
|
|
258
|
+
customSuccessRules: [{
|
|
259
|
+
type: 'custom',
|
|
260
|
+
options: {
|
|
261
|
+
validate: (value: boolean) => value === true,
|
|
262
|
+
successMessage: 'Succès de test',
|
|
263
|
+
},
|
|
264
|
+
}],
|
|
265
|
+
},
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
await wrapper.vm.validateOnSubmit()
|
|
269
|
+
await nextTick()
|
|
270
|
+
|
|
271
|
+
expect(wrapper.find('.success-field').exists()).toBe(true)
|
|
272
|
+
expect(wrapper.find('.v-messages').text()).toContain('Succès de test')
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('affiche les messages externes (errorMessages + hasError)', () => {
|
|
276
|
+
const wrapper = mount(SyCheckbox, {
|
|
277
|
+
props: {
|
|
278
|
+
label: 'CGU',
|
|
279
|
+
hasError: true,
|
|
280
|
+
errorMessages: ['Erreur externe'],
|
|
281
|
+
},
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
expect(wrapper.find('.error-field').exists()).toBe(true)
|
|
285
|
+
expect(wrapper.find('.v-messages').text()).toContain('Erreur externe')
|
|
286
|
+
})
|
|
181
287
|
})
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { defineComponent, ref, nextTick, type Ref } from 'vue'
|
|
3
|
+
import { mount } from '@vue/test-utils'
|
|
4
|
+
import { useSyCheckboxValidation, type UseSyCheckboxValidationReturn } from '../composables/useSyCheckboxValidation'
|
|
5
|
+
import type { SyCheckboxValidationProps } from '../types'
|
|
6
|
+
|
|
7
|
+
function createProps(overrides: Partial<SyCheckboxValidationProps> = {}): SyCheckboxValidationProps {
|
|
8
|
+
return {
|
|
9
|
+
label: 'Conditions générales',
|
|
10
|
+
required: false,
|
|
11
|
+
readonly: false,
|
|
12
|
+
disabled: false,
|
|
13
|
+
customRules: [],
|
|
14
|
+
customWarningRules: [],
|
|
15
|
+
customSuccessRules: [],
|
|
16
|
+
errorMessages: null,
|
|
17
|
+
warningMessages: null,
|
|
18
|
+
successMessages: null,
|
|
19
|
+
showSuccessMessages: false,
|
|
20
|
+
isValidateOnBlur: false,
|
|
21
|
+
...overrides,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Exécute le composable dans un contexte de setup (requis par les composables Vuetify internes)
|
|
26
|
+
function withValidation(props: SyCheckboxValidationProps, model: Ref<boolean | null>): UseSyCheckboxValidationReturn {
|
|
27
|
+
let result!: UseSyCheckboxValidationReturn
|
|
28
|
+
const Harness = defineComponent({
|
|
29
|
+
setup() {
|
|
30
|
+
result = useSyCheckboxValidation(props, model)
|
|
31
|
+
return () => null
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
mount(Harness)
|
|
35
|
+
return result
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('useSyCheckboxValidation', () => {
|
|
39
|
+
describe('required (la case doit être cochée)', () => {
|
|
40
|
+
it('échoue quand la case est décochée', async () => {
|
|
41
|
+
const model = ref<boolean | null>(false)
|
|
42
|
+
const { validate, errors, hasError } = withValidation(createProps({ required: true }), model)
|
|
43
|
+
|
|
44
|
+
expect(await validate()).toBe(false)
|
|
45
|
+
await nextTick()
|
|
46
|
+
expect(hasError.value).toBe(true)
|
|
47
|
+
expect(errors.value.join(' ')).toContain('Conditions générales est requis')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('réussit quand la case est cochée', async () => {
|
|
51
|
+
const model = ref<boolean | null>(true)
|
|
52
|
+
const { validate, hasError } = withValidation(createProps({ required: true }), model)
|
|
53
|
+
|
|
54
|
+
expect(await validate()).toBe(true)
|
|
55
|
+
await nextTick()
|
|
56
|
+
expect(hasError.value).toBeFalsy()
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('non requis : valide même décochée', async () => {
|
|
61
|
+
const model = ref<boolean | null>(false)
|
|
62
|
+
const { validate, hasError } = withValidation(createProps({ required: false }), model)
|
|
63
|
+
|
|
64
|
+
expect(await validate()).toBe(true)
|
|
65
|
+
expect(hasError.value).toBeFalsy()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('customRules : la case doit être cochée', async () => {
|
|
69
|
+
const model = ref<boolean | null>(false)
|
|
70
|
+
const { validate, errors } = withValidation(
|
|
71
|
+
createProps({
|
|
72
|
+
customRules: [{
|
|
73
|
+
type: 'custom',
|
|
74
|
+
options: {
|
|
75
|
+
validate: (value: unknown) => value === true,
|
|
76
|
+
message: 'Doit être coché',
|
|
77
|
+
},
|
|
78
|
+
}],
|
|
79
|
+
}),
|
|
80
|
+
model,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
expect(await validate()).toBe(false)
|
|
84
|
+
await nextTick()
|
|
85
|
+
expect(errors.value.join(' ')).toContain('Doit être coché')
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('disableErrorHandling : ne produit pas d\'erreur', async () => {
|
|
89
|
+
const model = ref<boolean | null>(false)
|
|
90
|
+
const { validate, hasError } = withValidation(
|
|
91
|
+
createProps({ required: true, disableErrorHandling: true }),
|
|
92
|
+
model,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
expect(await validate()).toBe(true)
|
|
96
|
+
expect(hasError.value).toBeFalsy()
|
|
97
|
+
})
|
|
98
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { FieldValidationProps, ValidationRule, VuetifyValidationRule } from '@/composables/unifyValidation/useValidation'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Props du composant SyCheckbox
|
|
5
|
+
*/
|
|
6
|
+
export interface SyCheckboxProps extends FieldValidationProps {
|
|
7
|
+
modelValue?: boolean | null
|
|
8
|
+
indeterminate?: boolean
|
|
9
|
+
label?: string
|
|
10
|
+
helpText?: string
|
|
11
|
+
ariaLabel?: string
|
|
12
|
+
ariaLabelledby?: string
|
|
13
|
+
title?: string
|
|
14
|
+
color?: string
|
|
15
|
+
hideDetails?: boolean | 'auto'
|
|
16
|
+
density?: 'default' | 'comfortable' | 'compact'
|
|
17
|
+
id?: string
|
|
18
|
+
name?: string
|
|
19
|
+
value?: unknown
|
|
20
|
+
trueValue?: unknown
|
|
21
|
+
falseValue?: unknown
|
|
22
|
+
controlsIds?: string[]
|
|
23
|
+
displayAsterisk?: boolean
|
|
24
|
+
decorative?: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Props de validation passées au composable dédié
|
|
29
|
+
*/
|
|
30
|
+
export interface SyCheckboxValidationProps extends FieldValidationProps {
|
|
31
|
+
modelValue?: boolean | null
|
|
32
|
+
required?: boolean
|
|
33
|
+
readonly?: boolean
|
|
34
|
+
disabled?: boolean
|
|
35
|
+
label?: string
|
|
36
|
+
customRules?: ValidationRule[]
|
|
37
|
+
customWarningRules?: ValidationRule[]
|
|
38
|
+
customSuccessRules?: ValidationRule[]
|
|
39
|
+
isValidateOnBlur?: boolean
|
|
40
|
+
showSuccessMessages?: boolean
|
|
41
|
+
useVuetifyValidation?: boolean
|
|
42
|
+
rules?: VuetifyValidationRule[]
|
|
43
|
+
errorMessages?: string[] | null
|
|
44
|
+
warningMessages?: string[] | null
|
|
45
|
+
successMessages?: string[] | null
|
|
46
|
+
hasError?: boolean
|
|
47
|
+
hasWarning?: boolean
|
|
48
|
+
hasSuccess?: boolean
|
|
49
|
+
maxErrors?: number
|
|
50
|
+
disableErrorHandling?: boolean
|
|
51
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { mdiAlertOutline, mdiCheck, mdiAlertCircle } from '@mdi/js'
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import SyIcon from '@/components/Customs/SyIcon/SyIcon.vue'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
state?: 'default' | 'error' | 'success' | 'warning'
|
|
8
|
+
}>()
|
|
9
|
+
|
|
10
|
+
const validationIcon = computed(() => {
|
|
11
|
+
if (props.state === 'error') return mdiAlertCircle
|
|
12
|
+
if (props.state === 'warning') return mdiAlertOutline
|
|
13
|
+
if (props.state === 'success') return mdiCheck
|
|
14
|
+
return null
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const className = computed(() => {
|
|
18
|
+
if (props.state === 'error') return 'error-icon'
|
|
19
|
+
if (props.state === 'warning') return 'warning-icon'
|
|
20
|
+
if (props.state === 'success') return 'success-icon'
|
|
21
|
+
return null
|
|
22
|
+
})
|
|
23
|
+
</script>
|
|
24
|
+
<template>
|
|
25
|
+
<SyIcon
|
|
26
|
+
v-if="validationIcon"
|
|
27
|
+
:icon="validationIcon"
|
|
28
|
+
:class="className"
|
|
29
|
+
class="field-state-icon"
|
|
30
|
+
decorative
|
|
31
|
+
/>
|
|
32
|
+
</template>
|
|
33
|
+
<style scoped lang="scss">
|
|
34
|
+
.field-state-icon :deep(.v-icon__svg) {
|
|
35
|
+
opacity: 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.success-icon :deep(.v-icon__svg) {
|
|
39
|
+
fill: rgb(var(--v-theme-onSuccessVariant)) !important;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.warning-icon :deep(.v-icon__svg) {
|
|
43
|
+
fill: rgb(var(--v-theme-onWarningVariant)) !important;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.error-icon :deep(.v-icon__svg) {
|
|
47
|
+
fill: rgb(var(--v-theme-error)) !important;
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { useNumberField } from './useNumberField'
|
|
23
23
|
import { locales as defaultLocales } from './locales'
|
|
24
24
|
import type { SyTextFieldProps } from './types'
|
|
25
|
+
import FieldState from './FieldState.vue'
|
|
25
26
|
|
|
26
27
|
const props = withDefaults(
|
|
27
28
|
defineProps<SyTextFieldProps>(),
|
|
@@ -157,7 +158,7 @@
|
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
const focused = ref(false)
|
|
160
|
-
const { validate, errors, warnings, successes, hasError, hasWarning, hasSuccess, iconColor, clearButtonColorClass,
|
|
161
|
+
const { validate, errors, warnings, successes, hasError, hasWarning, hasSuccess, iconColor, clearButtonColorClass, state, hasMessages } = useSyTextFieldValidation({
|
|
161
162
|
modelValue: model,
|
|
162
163
|
readonly: toRef(props, 'readonly'),
|
|
163
164
|
disabled: toRef(props, 'disabled'),
|
|
@@ -246,6 +247,10 @@
|
|
|
246
247
|
return
|
|
247
248
|
}
|
|
248
249
|
|
|
250
|
+
if (event.inputType === 'insertFromPaste') {
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
|
|
249
254
|
const hasDisallowed = props.type === 'number'
|
|
250
255
|
? hasDisallowedNumberCharacter(event.data)
|
|
251
256
|
: event.data.replace(TEL_ALLOWED_CHARACTERS_PATTERN, '') !== event.data
|
|
@@ -274,7 +279,7 @@
|
|
|
274
279
|
? isAllowedNumberCharacter(event.key)
|
|
275
280
|
: TEL_ALLOWED_SINGLE_CHARACTER_PATTERN.test(event.key)
|
|
276
281
|
|
|
277
|
-
if (!allowedNonCharacterKeys.includes(event.key) && event.key
|
|
282
|
+
if (!allowedNonCharacterKeys.includes(event.key) && event.key?.length === 1 && !isAllowedCharacter) {
|
|
278
283
|
event.preventDefault()
|
|
279
284
|
}
|
|
280
285
|
}
|
|
@@ -293,14 +298,13 @@
|
|
|
293
298
|
return isShouldDisplayAsterisk.value ? `${props.label} *` : props.label
|
|
294
299
|
})
|
|
295
300
|
|
|
296
|
-
// Détermine si le helpText doit être affiché
|
|
301
|
+
// Détermine si le helpText doit être affiché dans le composant VTextField ou en dessous
|
|
297
302
|
const showHelpTextAsMessage = computed(() => {
|
|
298
|
-
// Afficher à la position du message si pas de messages d'erreur
|
|
299
303
|
return props.helpText && !hasMessages.value
|
|
300
304
|
})
|
|
301
305
|
|
|
302
306
|
const showHelpTextBelow = computed(() => {
|
|
303
|
-
// Afficher en dessous si il y a des messages d'erreur ET
|
|
307
|
+
// Afficher en dessous si il y a des messages d'erreur ET hideDetails n'est pas activé
|
|
304
308
|
return props.helpText && hasMessages.value && !props.hideDetails
|
|
305
309
|
})
|
|
306
310
|
|
|
@@ -718,10 +722,9 @@
|
|
|
718
722
|
@keydown.enter.stop
|
|
719
723
|
@keydown.space.stop
|
|
720
724
|
/>
|
|
721
|
-
<
|
|
722
|
-
v-if="
|
|
723
|
-
:
|
|
724
|
-
:decorative="true"
|
|
725
|
+
<FieldState
|
|
726
|
+
v-if="!props.appendInnerIcon"
|
|
727
|
+
:state="state"
|
|
725
728
|
/>
|
|
726
729
|
<SyIcon
|
|
727
730
|
v-if="props.appendInnerIcon && !props.noIcon"
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { computed, type Ref } from 'vue'
|
|
2
2
|
import { useValidation } from '@/composables/unifyValidation/useValidation'
|
|
3
3
|
import type { ValidationRule as SyValidationRule, VuetifyValidationRule } from '@/composables/unifyValidation/useValidation'
|
|
4
|
-
import { mdiAlertOutline, mdiCheck, mdiAlertCircle } from '@mdi/js'
|
|
5
4
|
|
|
6
5
|
export function useSyTextFieldValidation(params: {
|
|
7
6
|
modelValue: Ref<string | number | null | undefined>
|
|
@@ -38,7 +37,7 @@ export function useSyTextFieldValidation(params: {
|
|
|
38
37
|
: [],
|
|
39
38
|
)
|
|
40
39
|
|
|
41
|
-
const { validate, errors, warnings, successes, hasError, hasWarning, hasSuccess, clearValidation } = useValidation({
|
|
40
|
+
const { validate, errors, warnings, successes, hasError, hasWarning, hasSuccess, state, clearValidation } = useValidation({
|
|
42
41
|
modelValue: params.modelValue,
|
|
43
42
|
readonly: params.readonly,
|
|
44
43
|
disabled: params.disabled,
|
|
@@ -75,15 +74,7 @@ export function useSyTextFieldValidation(params: {
|
|
|
75
74
|
// Le bouton clear garde toujours une couleur neutre, quel que soit l'état de validation
|
|
76
75
|
const clearButtonColorClass = computed(() => 'text-iconBase')
|
|
77
76
|
|
|
78
|
-
const validationIcon = computed(() => {
|
|
79
|
-
if (hasError.value) return mdiAlertCircle
|
|
80
|
-
if (hasWarning.value) return mdiAlertOutline
|
|
81
|
-
if (hasSuccess.value) return mdiCheck
|
|
82
|
-
return null
|
|
83
|
-
})
|
|
84
|
-
|
|
85
77
|
const hasMessages = computed(() => {
|
|
86
|
-
if (params.disableErrorHandling.value) return false
|
|
87
78
|
return (params.errorMessages.value?.length ?? 0) > 0 || hasError.value || hasWarning.value || (hasSuccess.value && params.showSuccessMessages.value)
|
|
88
79
|
})
|
|
89
80
|
|
|
@@ -96,8 +87,8 @@ export function useSyTextFieldValidation(params: {
|
|
|
96
87
|
hasSuccess,
|
|
97
88
|
iconColor,
|
|
98
89
|
clearButtonColorClass,
|
|
99
|
-
validationIcon,
|
|
100
90
|
hasMessages,
|
|
91
|
+
state,
|
|
101
92
|
validate,
|
|
102
93
|
clearValidation,
|
|
103
94
|
}
|