@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,107 @@
|
|
|
1
|
+
import { computed, ref, toRef, type ComputedRef, type Ref } from 'vue'
|
|
2
|
+
import { useValidation, type ValidationRule } from '@/composables/unifyValidation/useValidation'
|
|
3
|
+
import type { SyCheckBoxGroupValidationProps } from '../types'
|
|
4
|
+
|
|
5
|
+
export interface UseSyCheckBoxGroupValidationReturn {
|
|
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 pour gérer la validation du composant SyCheckBoxGroup
|
|
21
|
+
*
|
|
22
|
+
* Ce composable encapsule toute la logique de validation spécifique aux groupes de checkboxes :
|
|
23
|
+
* - Validation required avec message personnalisé (supporte les modes single et multiple)
|
|
24
|
+
* - Support des customRules, customWarningRules, customSuccessRules
|
|
25
|
+
* - Désactivation automatique des messages de succès en mode Vuetify
|
|
26
|
+
* - Intégration avec useValidation du design system
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const { validate, errors, hasError, defaultRules } = useSyCheckBoxGroupValidation(props, model)
|
|
30
|
+
*/
|
|
31
|
+
export function useSyCheckBoxGroupValidation(
|
|
32
|
+
props: SyCheckBoxGroupValidationProps,
|
|
33
|
+
model: Ref<(string | number) | (string | number)[] | null>,
|
|
34
|
+
focused?: Ref<boolean>,
|
|
35
|
+
): UseSyCheckBoxGroupValidationReturn {
|
|
36
|
+
// Utiliser la variable focused passée en paramètre, sinon en créer une locale
|
|
37
|
+
const focusedRef = focused !== undefined ? focused : ref(false)
|
|
38
|
+
|
|
39
|
+
// Construction des règles de validation par défaut (required)
|
|
40
|
+
const defaultRules = computed<ValidationRule[]>(() =>
|
|
41
|
+
props.required
|
|
42
|
+
? [{
|
|
43
|
+
type: 'required',
|
|
44
|
+
options: {
|
|
45
|
+
message: `Le champ ${props.fieldIdentifier || props.label || 'ce champ'} est requis.`,
|
|
46
|
+
fieldIdentifier: props.label,
|
|
47
|
+
},
|
|
48
|
+
}]
|
|
49
|
+
: [],
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
// Vuetify ne gère pas les messages de succès, on désactive automatiquement en mode Vuetify
|
|
53
|
+
const effectiveShowSuccessMessages = computed(() =>
|
|
54
|
+
props.useVuetifyValidation ? false : (props.showSuccessMessages ?? false),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
const {
|
|
58
|
+
validate,
|
|
59
|
+
clearValidation,
|
|
60
|
+
errors,
|
|
61
|
+
warnings,
|
|
62
|
+
successes,
|
|
63
|
+
hasError,
|
|
64
|
+
hasWarning,
|
|
65
|
+
hasSuccess,
|
|
66
|
+
} = useValidation({
|
|
67
|
+
modelValue: model,
|
|
68
|
+
readonly: toRef(() => props.readonly ?? false),
|
|
69
|
+
disabled: toRef(() => props.disabled ?? false),
|
|
70
|
+
required: toRef(() => props.required ?? false),
|
|
71
|
+
isValidateOnBlur: toRef(() => props.isValidateOnBlur ?? false),
|
|
72
|
+
showSuccessMessages: effectiveShowSuccessMessages,
|
|
73
|
+
disableErrorHandling: toRef(() => props.disableErrorHandling ?? false),
|
|
74
|
+
useVuetifyValidation: toRef(() => props.useVuetifyValidation ?? false),
|
|
75
|
+
label: toRef(() => props.label ?? ''),
|
|
76
|
+
rules: toRef(() => props.rules),
|
|
77
|
+
customRules: computed(() => [...defaultRules.value, ...(props.customRules || [])]),
|
|
78
|
+
customWarningRules: toRef(() => props.customWarningRules ?? []),
|
|
79
|
+
customSuccessRules: toRef(() => props.customSuccessRules ?? []),
|
|
80
|
+
errorMessages: toRef(() => props.errorMessages ?? null),
|
|
81
|
+
warningMessages: toRef(() => props.warningMessages ?? null),
|
|
82
|
+
successMessages: toRef(() => props.successMessages ?? null),
|
|
83
|
+
hasErrorProp: toRef(() => props.hasError ?? false),
|
|
84
|
+
hasWarningProp: toRef(() => props.hasWarning ?? false),
|
|
85
|
+
hasSuccessProp: toRef(() => props.hasSuccess ?? false),
|
|
86
|
+
maxErrors: toRef(() => props.maxErrors ?? 1),
|
|
87
|
+
focused: focusedRef,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const validateOnSubmit = async (): Promise<boolean> => {
|
|
91
|
+
return await validate()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
validate,
|
|
96
|
+
validateOnSubmit,
|
|
97
|
+
clearValidation,
|
|
98
|
+
errors,
|
|
99
|
+
warnings,
|
|
100
|
+
successes,
|
|
101
|
+
hasError,
|
|
102
|
+
hasWarning,
|
|
103
|
+
hasSuccess,
|
|
104
|
+
defaultRules,
|
|
105
|
+
focused: focusedRef,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -3,6 +3,7 @@ import SyCheckbox from '@/components/Customs/SyCheckbox/SyCheckbox.vue'
|
|
|
3
3
|
import { mount } from '@vue/test-utils'
|
|
4
4
|
import { describe, it, expect } from 'vitest'
|
|
5
5
|
import { nextTick } from 'vue'
|
|
6
|
+
import type { ValidationRule } from '@/composables/unifyValidation/useValidation'
|
|
6
7
|
|
|
7
8
|
describe('SyCheckBoxGroup', () => {
|
|
8
9
|
it('should render correctly', () => {
|
|
@@ -82,17 +83,17 @@ describe('SyCheckBoxGroup', () => {
|
|
|
82
83
|
},
|
|
83
84
|
})
|
|
84
85
|
|
|
85
|
-
await wrapper.vm.validateOnSubmit()
|
|
86
|
+
const isValidInitial = await wrapper.vm.validateOnSubmit()
|
|
86
87
|
await nextTick()
|
|
87
|
-
expect(
|
|
88
|
-
expect(wrapper.
|
|
88
|
+
expect(isValidInitial).toBe(false)
|
|
89
|
+
expect(wrapper.text()).toContain('est requis')
|
|
89
90
|
|
|
90
91
|
await wrapper.find('input').setValue(true)
|
|
91
92
|
|
|
92
|
-
await wrapper.vm.validateOnSubmit()
|
|
93
|
+
const isValidAfterSelection = await wrapper.vm.validateOnSubmit()
|
|
93
94
|
await nextTick()
|
|
94
95
|
|
|
95
|
-
expect(
|
|
96
|
+
expect(isValidAfterSelection).toBe(true)
|
|
96
97
|
expect(wrapper.props('modelValue')).toBe('X')
|
|
97
98
|
})
|
|
98
99
|
|
|
@@ -141,12 +142,184 @@ describe('SyCheckBoxGroup', () => {
|
|
|
141
142
|
|
|
142
143
|
const isValidInitial = await wrapper.vm.validateOnSubmit()
|
|
143
144
|
expect(isValidInitial).toBe(false)
|
|
144
|
-
|
|
145
|
+
// Vérifier que le message d'erreur de la règle required ou custom est affiché
|
|
146
|
+
expect(wrapper.text()).toContain('requis') // Le message required par défaut
|
|
145
147
|
|
|
146
148
|
await wrapper.setProps({ modelValue: 'OK' })
|
|
147
149
|
|
|
148
150
|
const isValidCorrect = await wrapper.vm.validateOnSubmit()
|
|
149
151
|
expect(isValidCorrect).toBe(true)
|
|
150
|
-
|
|
152
|
+
// Vérifier que le message d'erreur n'est plus présent
|
|
153
|
+
expect(wrapper.text()).not.toContain('requis')
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('should display asterisk when displayAsterisk is true and required', () => {
|
|
157
|
+
const wrapper = mount(SyCheckBoxGroup, {
|
|
158
|
+
props: {
|
|
159
|
+
label: 'Required Field',
|
|
160
|
+
required: true,
|
|
161
|
+
displayAsterisk: true,
|
|
162
|
+
options: [{ label: 'X', value: 'X', id: 'opt-x' }],
|
|
163
|
+
},
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
expect(wrapper.text()).toContain('Required Field *')
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('should not display asterisk when displayAsterisk is false', () => {
|
|
170
|
+
const wrapper = mount(SyCheckBoxGroup, {
|
|
171
|
+
props: {
|
|
172
|
+
label: 'Required Field',
|
|
173
|
+
required: true,
|
|
174
|
+
displayAsterisk: false,
|
|
175
|
+
options: [{ label: 'X', value: 'X', id: 'opt-x' }],
|
|
176
|
+
},
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
expect(wrapper.text()).not.toContain('Required Field *')
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('should handle external error messages', async () => {
|
|
183
|
+
const wrapper = mount(SyCheckBoxGroup, {
|
|
184
|
+
props: {
|
|
185
|
+
label: 'CheckBox Group',
|
|
186
|
+
options: [{ label: 'X', value: 'X', id: 'opt-x' }],
|
|
187
|
+
errorMessages: ['Erreur externe'],
|
|
188
|
+
},
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
await nextTick()
|
|
192
|
+
|
|
193
|
+
const errorMessages = wrapper.findAll('.v-messages__message')
|
|
194
|
+
expect(errorMessages.length).toBeGreaterThan(0)
|
|
195
|
+
expect(errorMessages[0]?.text()).toContain('Erreur externe')
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('should handle warning and success rules', async () => {
|
|
199
|
+
const warningRule: ValidationRule = {
|
|
200
|
+
type: 'custom',
|
|
201
|
+
options: {
|
|
202
|
+
validate: (value: unknown) => {
|
|
203
|
+
if (value !== 'A') {
|
|
204
|
+
return 'Vous devez sélectionner l\'option A'
|
|
205
|
+
}
|
|
206
|
+
return true
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const successRule: ValidationRule = {
|
|
212
|
+
type: 'custom',
|
|
213
|
+
options: {
|
|
214
|
+
validate: (value: unknown) => value === 'A',
|
|
215
|
+
successMessage: 'Option A sélectionnée',
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const wrapper = mount(SyCheckBoxGroup, {
|
|
220
|
+
props: {
|
|
221
|
+
'modelValue': null,
|
|
222
|
+
'customWarningRules': [warningRule],
|
|
223
|
+
'customSuccessRules': [successRule],
|
|
224
|
+
'showSuccessMessages': true,
|
|
225
|
+
'isValidateOnBlur': false,
|
|
226
|
+
'options': [
|
|
227
|
+
{ label: 'Option A', value: 'A', id: 'opt-a' },
|
|
228
|
+
{ label: 'Option B', value: 'B', id: 'opt-b' },
|
|
229
|
+
],
|
|
230
|
+
'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }),
|
|
231
|
+
},
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
// Sélectionner B devrait afficher un warning
|
|
235
|
+
await wrapper.setProps({ modelValue: 'B' })
|
|
236
|
+
await wrapper.vm.validateOnSubmit()
|
|
237
|
+
await nextTick()
|
|
238
|
+
|
|
239
|
+
expect(wrapper.text()).toContain('Vous devez sélectionner l\'option A')
|
|
240
|
+
|
|
241
|
+
// Sélectionner A devrait afficher un succès
|
|
242
|
+
await wrapper.setProps({ modelValue: 'A' })
|
|
243
|
+
await wrapper.vm.validateOnSubmit()
|
|
244
|
+
await nextTick()
|
|
245
|
+
|
|
246
|
+
expect(wrapper.text()).toContain('Option A sélectionnée')
|
|
247
|
+
|
|
248
|
+
const isValid = await wrapper.vm.validateOnSubmit()
|
|
249
|
+
expect(isValid).toBe(true)
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
it('should validate on selection change when isValidateOnBlur is false', async () => {
|
|
253
|
+
const wrapper = mount(SyCheckBoxGroup, {
|
|
254
|
+
props: {
|
|
255
|
+
'modelValue': null,
|
|
256
|
+
'required': true,
|
|
257
|
+
'isValidateOnBlur': false,
|
|
258
|
+
'options': [
|
|
259
|
+
{ label: 'Option A', value: 'A', id: 'opt-a' },
|
|
260
|
+
{ label: 'Option B', value: 'B', id: 'opt-b' },
|
|
261
|
+
],
|
|
262
|
+
'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }),
|
|
263
|
+
},
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
// Pas d'erreur au montage car pas de validation forcée
|
|
267
|
+
await nextTick()
|
|
268
|
+
|
|
269
|
+
// Sélectionner une option valide
|
|
270
|
+
await wrapper.setProps({ modelValue: 'A' })
|
|
271
|
+
await nextTick()
|
|
272
|
+
|
|
273
|
+
const isValid = await wrapper.vm.validateOnSubmit()
|
|
274
|
+
expect(isValid).toBe(true)
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
it('should handle useVuetifyValidation mode', async () => {
|
|
278
|
+
const wrapper = mount(SyCheckBoxGroup, {
|
|
279
|
+
props: {
|
|
280
|
+
'modelValue': null,
|
|
281
|
+
'required': true,
|
|
282
|
+
'useVuetifyValidation': true,
|
|
283
|
+
'rules': [(v: unknown) => !!v || 'Champ requis'],
|
|
284
|
+
'options': [
|
|
285
|
+
{ label: 'Option A', value: 'A', id: 'opt-a' },
|
|
286
|
+
],
|
|
287
|
+
'onUpdate:modelValue': e => wrapper.setProps({ modelValue: e }),
|
|
288
|
+
},
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
// Vérifier que la validation Vuetify est active
|
|
292
|
+
await nextTick()
|
|
293
|
+
const isValidInitial = await wrapper.vm.validateOnSubmit()
|
|
294
|
+
expect(isValidInitial).toBe(false)
|
|
295
|
+
expect(wrapper.text()).toContain('Champ requis')
|
|
296
|
+
|
|
297
|
+
// Sélectionner une option
|
|
298
|
+
await wrapper.setProps({ modelValue: 'A' })
|
|
299
|
+
const isValidAfter = await wrapper.vm.validateOnSubmit()
|
|
300
|
+
expect(isValidAfter).toBe(true)
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it('should expose checkErrorOnBlur method', async () => {
|
|
304
|
+
const wrapper = mount(SyCheckBoxGroup, {
|
|
305
|
+
props: {
|
|
306
|
+
modelValue: null,
|
|
307
|
+
required: true,
|
|
308
|
+
isValidateOnBlur: true,
|
|
309
|
+
options: [
|
|
310
|
+
{ label: 'Option A', value: 'A', id: 'opt-a' },
|
|
311
|
+
],
|
|
312
|
+
},
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
// Vérifier que la méthode est exposée
|
|
316
|
+
expect(typeof wrapper.vm.checkErrorOnBlur).toBe('function')
|
|
317
|
+
|
|
318
|
+
// Appeler la méthode (simule le blur)
|
|
319
|
+
await wrapper.vm.checkErrorOnBlur()
|
|
320
|
+
await nextTick()
|
|
321
|
+
|
|
322
|
+
// Devrait afficher l'erreur car champ vide
|
|
323
|
+
expect(wrapper.text()).toContain('requis')
|
|
151
324
|
})
|
|
152
325
|
})
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { FieldValidationProps, ValidationRule, VuetifyValidationRule } from '@/composables/unifyValidation/useValidation'
|
|
2
|
+
|
|
1
3
|
export type Option = {
|
|
2
4
|
label: string
|
|
3
5
|
value: string | number
|
|
@@ -8,3 +10,50 @@ export type Option = {
|
|
|
8
10
|
ariaLabel?: string
|
|
9
11
|
title?: string
|
|
10
12
|
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Props du composant SyCheckBoxGroup
|
|
16
|
+
*/
|
|
17
|
+
export interface SyCheckBoxGroupProps extends FieldValidationProps {
|
|
18
|
+
ariaLabel?: string
|
|
19
|
+
ariaLabelledby?: string
|
|
20
|
+
color?: string
|
|
21
|
+
density?: 'default' | 'comfortable' | 'compact'
|
|
22
|
+
displayAsterisk?: boolean
|
|
23
|
+
helpText?: string
|
|
24
|
+
hideDetails?: boolean | 'auto'
|
|
25
|
+
id?: string
|
|
26
|
+
label?: string
|
|
27
|
+
modelValue?: (string | number) | (string | number)[] | null
|
|
28
|
+
multiple?: boolean
|
|
29
|
+
name?: string
|
|
30
|
+
options?: Option[]
|
|
31
|
+
title?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Props de validation étendant FieldValidationProps du système unifié
|
|
36
|
+
*/
|
|
37
|
+
export interface SyCheckBoxGroupValidationProps extends FieldValidationProps {
|
|
38
|
+
modelValue?: (string | number) | (string | number)[] | null
|
|
39
|
+
multiple?: boolean
|
|
40
|
+
required?: boolean
|
|
41
|
+
readonly?: boolean
|
|
42
|
+
disabled?: boolean
|
|
43
|
+
customRules?: ValidationRule[]
|
|
44
|
+
customWarningRules?: ValidationRule[]
|
|
45
|
+
customSuccessRules?: ValidationRule[]
|
|
46
|
+
isValidateOnBlur?: boolean
|
|
47
|
+
showSuccessMessages?: boolean
|
|
48
|
+
useVuetifyValidation?: boolean
|
|
49
|
+
rules?: VuetifyValidationRule[]
|
|
50
|
+
errorMessages?: string[] | null
|
|
51
|
+
warningMessages?: string[] | null
|
|
52
|
+
successMessages?: string[] | null
|
|
53
|
+
hasError?: boolean
|
|
54
|
+
hasWarning?: boolean
|
|
55
|
+
hasSuccess?: boolean
|
|
56
|
+
maxErrors?: number
|
|
57
|
+
disableErrorHandling?: boolean
|
|
58
|
+
fieldIdentifier?: string
|
|
59
|
+
}
|
|
@@ -2,11 +2,7 @@ import type { Meta, StoryObj } from '@storybook/vue3'
|
|
|
2
2
|
import SyCheckbox from '@/components/Customs/SyCheckbox/SyCheckbox.vue'
|
|
3
3
|
import { ref, watch } from 'vue'
|
|
4
4
|
import { fn } from '@storybook/test'
|
|
5
|
-
|
|
6
|
-
// Interface pour typer correctement le composant SyCheckbox avec sa méthode validateOnSubmit
|
|
7
|
-
interface SyCheckboxInstance {
|
|
8
|
-
validateOnSubmit: () => Promise<boolean>
|
|
9
|
-
}
|
|
5
|
+
import { getValidationDocumentation } from '@/composables/unifyValidation/documentationValidationProps'
|
|
10
6
|
|
|
11
7
|
const meta = {
|
|
12
8
|
title: 'Composants/Formulaires/SyCheckbox',
|
|
@@ -26,11 +22,16 @@ const meta = {
|
|
|
26
22
|
},
|
|
27
23
|
},
|
|
28
24
|
argTypes: {
|
|
25
|
+
...getValidationDocumentation(),
|
|
29
26
|
modelValue: { control: 'boolean' },
|
|
30
27
|
label: {
|
|
31
28
|
description: 'Texte affiché comme label de la case à cocher',
|
|
32
29
|
control: 'text',
|
|
33
30
|
},
|
|
31
|
+
helpText: {
|
|
32
|
+
description: 'Texte d\'aide affiché sous la case (masqué quand un message de validation est présent)',
|
|
33
|
+
control: 'text',
|
|
34
|
+
},
|
|
34
35
|
color: {
|
|
35
36
|
control: 'select',
|
|
36
37
|
options: ['primary', 'success', 'error', 'warning'],
|
|
@@ -202,6 +203,41 @@ Cette case à cocher est dans un état indéterminé, généralement utilisé lo
|
|
|
202
203
|
},
|
|
203
204
|
}
|
|
204
205
|
|
|
206
|
+
export const HelpText: Story = {
|
|
207
|
+
args: {
|
|
208
|
+
...Default.args,
|
|
209
|
+
helpText: 'Cochez cette case pour accepter les conditions générales.',
|
|
210
|
+
},
|
|
211
|
+
render: args => ({
|
|
212
|
+
components: { SyCheckbox },
|
|
213
|
+
setup() {
|
|
214
|
+
const checked = ref(false)
|
|
215
|
+
return { args, checked }
|
|
216
|
+
},
|
|
217
|
+
template: `<SyCheckbox v-model="checked" v-bind="args" label="Case à cocher" />`,
|
|
218
|
+
}),
|
|
219
|
+
parameters: {
|
|
220
|
+
sourceCode: [
|
|
221
|
+
{
|
|
222
|
+
name: 'Template',
|
|
223
|
+
code: `<SyCheckbox
|
|
224
|
+
v-model="checked"
|
|
225
|
+
label="Case à cocher"
|
|
226
|
+
help-text="Cochez cette case pour accepter les conditions générales."
|
|
227
|
+
/>`,
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
docs: {
|
|
231
|
+
description: {
|
|
232
|
+
story: `
|
|
233
|
+
### Case à cocher avec texte d'aide
|
|
234
|
+
Un texte d'aide (\`helpText\`) s'affiche sous la case pour guider l'utilisateur, tant qu'aucun message de validation (erreur, avertissement, succès) n'est présent.
|
|
235
|
+
`,
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
}
|
|
240
|
+
|
|
205
241
|
export const WithControlsIds: Story = {
|
|
206
242
|
parameters: {
|
|
207
243
|
sourceCode: [
|
|
@@ -640,159 +676,3 @@ Le composant SyCheckbox peut être personnalisé avec différentes couleurs pour
|
|
|
640
676
|
`,
|
|
641
677
|
}),
|
|
642
678
|
}
|
|
643
|
-
|
|
644
|
-
export const FormValidation: Story = {
|
|
645
|
-
parameters: {
|
|
646
|
-
sourceCode: [
|
|
647
|
-
{
|
|
648
|
-
name: 'Template',
|
|
649
|
-
code: `
|
|
650
|
-
<template>
|
|
651
|
-
<form @submit.prevent="validateForm">
|
|
652
|
-
<h3>Validation avec règles personnalisées</h3>
|
|
653
|
-
<SyCheckbox
|
|
654
|
-
ref="checkbox"
|
|
655
|
-
v-model="checked"
|
|
656
|
-
label="J'accepte les conditions générales d'utilisation"
|
|
657
|
-
:custom-rules="rules"
|
|
658
|
-
validate-on-submit
|
|
659
|
-
/>
|
|
660
|
-
<h3>Validation avec la prop required</h3>
|
|
661
|
-
<SyCheckbox
|
|
662
|
-
ref="checkbox2"
|
|
663
|
-
v-model="checked2"
|
|
664
|
-
label="J'accepte les conditions générales d'utilisation"
|
|
665
|
-
display-asterisk
|
|
666
|
-
required
|
|
667
|
-
/>
|
|
668
|
-
<VBtn
|
|
669
|
-
type="submit"
|
|
670
|
-
color="primary"
|
|
671
|
-
class="mt-4"
|
|
672
|
-
>
|
|
673
|
-
Soumettre
|
|
674
|
-
</VBtn>
|
|
675
|
-
<p v-if="formSubmitted" style="margin-top: 16px; color: var(--v-success-base);">Formulaire soumis avec succès!</p>
|
|
676
|
-
</form>
|
|
677
|
-
</template>
|
|
678
|
-
|
|
679
|
-
<script setup lang="ts">
|
|
680
|
-
import { ref, watch } from 'vue'
|
|
681
|
-
|
|
682
|
-
const checkbox = ref<SyCheckboxInstance | null>(null)
|
|
683
|
-
const checkbox2 = ref<SyCheckboxInstance | null>(null)
|
|
684
|
-
const checked = ref(false)
|
|
685
|
-
const checked2 = ref(false)
|
|
686
|
-
const formSubmitted = ref(false)
|
|
687
|
-
const hasError = ref(false)
|
|
688
|
-
|
|
689
|
-
const rules = [
|
|
690
|
-
{
|
|
691
|
-
type: 'custom',
|
|
692
|
-
options: {
|
|
693
|
-
message: 'Cette case doit être cochée pour continuer.',
|
|
694
|
-
validate: (value: boolean) => value === true,
|
|
695
|
-
},
|
|
696
|
-
},
|
|
697
|
-
]
|
|
698
|
-
|
|
699
|
-
const validateForm = async (): Promise<void> => {
|
|
700
|
-
if (!checkbox.value || !checkbox2.value) return
|
|
701
|
-
hasError.value = true
|
|
702
|
-
const isValid = await checkbox.value.validateOnSubmit()
|
|
703
|
-
const isValid2 = await checkbox2.value.validateOnSubmit()
|
|
704
|
-
if (isValid && isValid2) {
|
|
705
|
-
formSubmitted.value = true
|
|
706
|
-
hasError.value = false
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
</script>`,
|
|
710
|
-
},
|
|
711
|
-
],
|
|
712
|
-
docs: {
|
|
713
|
-
description: {
|
|
714
|
-
story: `
|
|
715
|
-
### Case à cocher avec validation au moment de la soumission
|
|
716
|
-
Cette case à cocher utilise des règles de validation personnalisées et valide le formulaire lors de la soumission grâce à la propriété \`validateOnSubmit\`. Le bouton de soumission déclenche la validation et affiche un message de succès si la case est cochée.
|
|
717
|
-
`,
|
|
718
|
-
},
|
|
719
|
-
},
|
|
720
|
-
},
|
|
721
|
-
render: args => ({
|
|
722
|
-
components: { SyCheckbox },
|
|
723
|
-
setup() {
|
|
724
|
-
const checkbox = ref<SyCheckboxInstance | null>(null)
|
|
725
|
-
const checkbox2 = ref<SyCheckboxInstance | null>(null)
|
|
726
|
-
const checked = ref(false)
|
|
727
|
-
const checked2 = ref(false)
|
|
728
|
-
const formSubmitted = ref(false)
|
|
729
|
-
const hasError = ref(false)
|
|
730
|
-
|
|
731
|
-
// Revalider quand les valeurs changent
|
|
732
|
-
watch([checked, checked2], async () => {
|
|
733
|
-
if (hasError.value && checkbox.value && checkbox2.value) {
|
|
734
|
-
await checkbox.value.validateOnSubmit()
|
|
735
|
-
await checkbox2.value.validateOnSubmit()
|
|
736
|
-
}
|
|
737
|
-
})
|
|
738
|
-
|
|
739
|
-
const validateForm = async (): Promise<void> => {
|
|
740
|
-
if (!checkbox.value || !checkbox2.value) return
|
|
741
|
-
hasError.value = true
|
|
742
|
-
const isValid = await checkbox.value.validateOnSubmit()
|
|
743
|
-
const isValid2 = await checkbox2.value.validateOnSubmit()
|
|
744
|
-
if (isValid && isValid2) {
|
|
745
|
-
formSubmitted.value = true
|
|
746
|
-
hasError.value = false
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
return {
|
|
751
|
-
args,
|
|
752
|
-
checkbox,
|
|
753
|
-
checked,
|
|
754
|
-
checkbox2,
|
|
755
|
-
checked2,
|
|
756
|
-
formSubmitted,
|
|
757
|
-
hasError,
|
|
758
|
-
rules: [
|
|
759
|
-
{
|
|
760
|
-
type: 'custom',
|
|
761
|
-
options: {
|
|
762
|
-
message: 'Cette case doit être cochée pour continuer.',
|
|
763
|
-
validate: (value: boolean) => value === true,
|
|
764
|
-
},
|
|
765
|
-
},
|
|
766
|
-
],
|
|
767
|
-
validateForm,
|
|
768
|
-
}
|
|
769
|
-
},
|
|
770
|
-
template: `
|
|
771
|
-
<form @submit.prevent="validateForm">
|
|
772
|
-
<h3>Validation avec règles personnalisées</h3>
|
|
773
|
-
<SyCheckbox
|
|
774
|
-
ref="checkbox"
|
|
775
|
-
v-model="checked"
|
|
776
|
-
label="J'accepte les conditions générales d'utilisation"
|
|
777
|
-
:custom-rules="rules"
|
|
778
|
-
/>
|
|
779
|
-
<h3>Validation avec la prop required et display-asterisk</h3>
|
|
780
|
-
<SyCheckbox
|
|
781
|
-
ref="checkbox2"
|
|
782
|
-
v-model="checked2"
|
|
783
|
-
label="J'accepte les conditions générales d'utilisation"
|
|
784
|
-
required
|
|
785
|
-
display-asterisk
|
|
786
|
-
/>
|
|
787
|
-
<VBtn
|
|
788
|
-
type="submit"
|
|
789
|
-
color="primary"
|
|
790
|
-
class="mt-4"
|
|
791
|
-
>
|
|
792
|
-
Soumettre
|
|
793
|
-
</VBtn>
|
|
794
|
-
<p v-if="formSubmitted" style="margin-top: 16px; color: var(--v-success-base);">Formulaire soumis avec succès!</p>
|
|
795
|
-
</form>
|
|
796
|
-
`,
|
|
797
|
-
}),
|
|
798
|
-
}
|