@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,1194 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { fn, userEvent, within } from '@storybook/test'
|
|
3
|
+
import { ref, watch } from 'vue'
|
|
4
|
+
import Captcha from '../Captcha.vue'
|
|
5
|
+
import { VBtn, VCard, VForm } from 'vuetify/components'
|
|
6
|
+
import SyForm from '../../Customs/SyForm/SyForm.vue'
|
|
7
|
+
import { getValidationDocumentation } from '@/composables/unifyValidation/documentationValidationProps'
|
|
8
|
+
|
|
9
|
+
const meta: Meta = {
|
|
10
|
+
title: 'Composants/Formulaires/Captcha/Validation',
|
|
11
|
+
component: Captcha,
|
|
12
|
+
argTypes: {
|
|
13
|
+
...getValidationDocumentation('string'),
|
|
14
|
+
},
|
|
15
|
+
parameters: {
|
|
16
|
+
layout: 'centered',
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: 'Exemples de validation pour le composant Captcha.',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
controls: { exclude: ['onUpdate:modelValue', 'onUpdate:type', 'onImageError', 'onAudioError', 'onCreationError'] },
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
'onUpdate:modelValue': fn(),
|
|
26
|
+
'onUpdate:type': fn(),
|
|
27
|
+
'onImageError': fn(),
|
|
28
|
+
'onAudioError': fn(),
|
|
29
|
+
'onCreationError': fn(),
|
|
30
|
+
'readonly': false,
|
|
31
|
+
'disabled': false,
|
|
32
|
+
'required': false,
|
|
33
|
+
'isValidateOnBlur': true,
|
|
34
|
+
'showSuccessMessages': true,
|
|
35
|
+
'disableErrorHandling': false,
|
|
36
|
+
'customRules': [],
|
|
37
|
+
'customWarningRules': [],
|
|
38
|
+
'customSuccessRules': [],
|
|
39
|
+
'errorMessages': null,
|
|
40
|
+
'warningMessages': null,
|
|
41
|
+
'successMessages': null,
|
|
42
|
+
'hasError': false,
|
|
43
|
+
'hasWarning': false,
|
|
44
|
+
'hasSuccess': false,
|
|
45
|
+
'useVuetifyValidation': false,
|
|
46
|
+
'maxErrors': 1,
|
|
47
|
+
'urlCreate': 'https://free.mockerapi.com/mock/0adac32b-e832-4553-aa7f-0011b7f35f0c',
|
|
48
|
+
'urlGetImage': '/captcha/captcha.png',
|
|
49
|
+
'urlGetAudio': '/captcha/captcha.mp3',
|
|
50
|
+
'type': 'image',
|
|
51
|
+
'modelValue': 'abc',
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default meta
|
|
56
|
+
type StoryArgs = {
|
|
57
|
+
modelValue?: string
|
|
58
|
+
} & Record<string, unknown>
|
|
59
|
+
|
|
60
|
+
type Story = StoryObj<StoryArgs>
|
|
61
|
+
|
|
62
|
+
export const WithError: Story = {
|
|
63
|
+
parameters: {
|
|
64
|
+
a11y: {
|
|
65
|
+
disable: true,
|
|
66
|
+
},
|
|
67
|
+
docs: {
|
|
68
|
+
description: {
|
|
69
|
+
story: 'Validation bloquante via `customRules` (message d\'erreur personnalisé).',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
sourceCode: [
|
|
73
|
+
{
|
|
74
|
+
name: 'Template',
|
|
75
|
+
code: `
|
|
76
|
+
<Captcha
|
|
77
|
+
v-model="modelValue"
|
|
78
|
+
required
|
|
79
|
+
:custom-rules="[
|
|
80
|
+
{
|
|
81
|
+
type: 'custom',
|
|
82
|
+
options: {
|
|
83
|
+
validate: (v) => (v as string).length >= 6,
|
|
84
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
85
|
+
successMessage: 'Le captcha contient au moins 6 caractères.'
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]"
|
|
89
|
+
/>
|
|
90
|
+
`,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'Script',
|
|
94
|
+
code: `
|
|
95
|
+
import { ref } from 'vue'
|
|
96
|
+
import { Captcha } from '@cnamts/synapse'
|
|
97
|
+
|
|
98
|
+
const modelValue = ref('ytq')
|
|
99
|
+
`,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
render: (args) => {
|
|
104
|
+
return {
|
|
105
|
+
components: { Captcha, VCard },
|
|
106
|
+
setup() {
|
|
107
|
+
const captchaValue = ref(args.modelValue)
|
|
108
|
+
watch(() => args.modelValue, () => {
|
|
109
|
+
captchaValue.value = args.modelValue
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
return { args, captchaValue }
|
|
113
|
+
},
|
|
114
|
+
template: `
|
|
115
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
116
|
+
<Captcha
|
|
117
|
+
v-bind="args"
|
|
118
|
+
v-model="captchaValue"
|
|
119
|
+
/>
|
|
120
|
+
</VCard>
|
|
121
|
+
`,
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
args: {
|
|
125
|
+
modelValue: 'ytq',
|
|
126
|
+
// Validation à la saisie pour que l'état (erreur/succès) se mette à jour
|
|
127
|
+
// immédiatement quand on modifie le champ, sans attendre le blur.
|
|
128
|
+
isValidateOnBlur: false,
|
|
129
|
+
customRules: [
|
|
130
|
+
{
|
|
131
|
+
type: 'custom',
|
|
132
|
+
options: {
|
|
133
|
+
validate: (v: unknown) => {
|
|
134
|
+
return (String(v || '')).length >= 6
|
|
135
|
+
},
|
|
136
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
137
|
+
successMessage: 'Le captcha contient au moins 6 caractères.',
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
play: async ({ canvasElement }) => {
|
|
143
|
+
const input = within(canvasElement).getByRole('textbox')
|
|
144
|
+
await userEvent.clear(input)
|
|
145
|
+
await userEvent.type(input, 'ytq')
|
|
146
|
+
input.blur()
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export const WithWarning: Story = {
|
|
151
|
+
...WithError,
|
|
152
|
+
parameters: {
|
|
153
|
+
a11y: {
|
|
154
|
+
disable: true,
|
|
155
|
+
},
|
|
156
|
+
docs: {
|
|
157
|
+
description: {
|
|
158
|
+
story: 'Validation non bloquante via `customWarningRules` (message d\'avertissement personnalisé).',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
sourceCode: [
|
|
162
|
+
{
|
|
163
|
+
name: 'Template',
|
|
164
|
+
code: `
|
|
165
|
+
<Captcha
|
|
166
|
+
v-model="modelValue"
|
|
167
|
+
required
|
|
168
|
+
:custom-warning-rules="[
|
|
169
|
+
{
|
|
170
|
+
type: 'custom',
|
|
171
|
+
options: {
|
|
172
|
+
validate: (v) => (String(v || '')).length >= 6,
|
|
173
|
+
warningMessage: 'Le captcha devrait idéalement contenir au moins 6 caractères.'
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
]"
|
|
177
|
+
/>
|
|
178
|
+
`,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'Script',
|
|
182
|
+
code: `
|
|
183
|
+
import { ref } from 'vue'
|
|
184
|
+
import { Captcha } from '@cnamts/synapse'
|
|
185
|
+
|
|
186
|
+
const modelValue = ref('ytq')
|
|
187
|
+
`,
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
args: {
|
|
192
|
+
...WithError.args,
|
|
193
|
+
customRules: [],
|
|
194
|
+
customWarningRules: [
|
|
195
|
+
{
|
|
196
|
+
type: 'custom',
|
|
197
|
+
options: {
|
|
198
|
+
validate: (v: unknown) => {
|
|
199
|
+
return (String(v || '')).length >= 6
|
|
200
|
+
},
|
|
201
|
+
warningMessage: 'Le captcha devrait idéalement contenir au moins 6 caractères.',
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export const WithSuccess: Story = {
|
|
209
|
+
...WithError,
|
|
210
|
+
parameters: {
|
|
211
|
+
a11y: {
|
|
212
|
+
disable: true,
|
|
213
|
+
},
|
|
214
|
+
docs: {
|
|
215
|
+
description: {
|
|
216
|
+
story: 'Validation de succès via `customSuccessRules` (message de succès personnalisé).',
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
sourceCode: [
|
|
220
|
+
{
|
|
221
|
+
name: 'Template',
|
|
222
|
+
code: `
|
|
223
|
+
<Captcha
|
|
224
|
+
v-model="modelValue"
|
|
225
|
+
required
|
|
226
|
+
:custom-rules="[
|
|
227
|
+
{
|
|
228
|
+
type: 'custom',
|
|
229
|
+
options: {
|
|
230
|
+
validate: (v) => (String(v || '')).length >= 6,
|
|
231
|
+
message: 'Le captcha doit contenir au moins 6 caractères.'
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
]"
|
|
235
|
+
:custom-success-rules="[
|
|
236
|
+
{
|
|
237
|
+
type: 'custom',
|
|
238
|
+
options: {
|
|
239
|
+
validate: (v) => (String(v || '')).length >= 6,
|
|
240
|
+
successMessage: 'Le captcha est correctement renseigné.'
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
]"
|
|
244
|
+
/>
|
|
245
|
+
`,
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: 'Script',
|
|
249
|
+
code: `
|
|
250
|
+
import { ref } from 'vue'
|
|
251
|
+
import { Captcha } from '@cnamts/synapse'
|
|
252
|
+
|
|
253
|
+
const modelValue = ref('ytqZNq')
|
|
254
|
+
`,
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
},
|
|
258
|
+
args: {
|
|
259
|
+
...WithError.args,
|
|
260
|
+
customRules: [
|
|
261
|
+
{
|
|
262
|
+
type: 'custom',
|
|
263
|
+
options: {
|
|
264
|
+
validate: (v: unknown) => (String(v || '')).length >= 6,
|
|
265
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
customSuccessRules: [
|
|
270
|
+
{
|
|
271
|
+
type: 'custom',
|
|
272
|
+
options: {
|
|
273
|
+
validate: (v: unknown) => (String(v || '')).length >= 6,
|
|
274
|
+
successMessage: 'Le captcha est correctement renseigné.',
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
play: async ({ canvasElement }) => {
|
|
280
|
+
const input = within(canvasElement).getByRole('textbox')
|
|
281
|
+
await userEvent.clear(input)
|
|
282
|
+
await userEvent.type(input, 'ytqZNq')
|
|
283
|
+
input.blur()
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export const ValidateOnInput: Story = {
|
|
288
|
+
parameters: {
|
|
289
|
+
a11y: {
|
|
290
|
+
disable: true,
|
|
291
|
+
},
|
|
292
|
+
docs: {
|
|
293
|
+
description: {
|
|
294
|
+
story: 'Validation déclenchée à chaque frappe via `isValidateOnBlur=false`.',
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
sourceCode: [
|
|
298
|
+
{
|
|
299
|
+
name: 'Template',
|
|
300
|
+
code: `
|
|
301
|
+
<Captcha
|
|
302
|
+
v-model="value"
|
|
303
|
+
required
|
|
304
|
+
:is-validate-on-blur="false"
|
|
305
|
+
:custom-rules="[
|
|
306
|
+
{
|
|
307
|
+
type: 'custom',
|
|
308
|
+
options: {
|
|
309
|
+
validate: (value) => String(value || '').length >= 6,
|
|
310
|
+
message: 'Le captcha doit contenir au moins 6 caractères.'
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
type: 'custom',
|
|
315
|
+
options: {
|
|
316
|
+
validate: async (value) => {
|
|
317
|
+
try {
|
|
318
|
+
const r = await verifyCaptcha()
|
|
319
|
+
return r.response.data.message === 'Success'
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
return false
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
message: 'Le captcha est incorrect',
|
|
326
|
+
successMessage: 'Le captcha est correct'
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
]"
|
|
330
|
+
/>
|
|
331
|
+
`,
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
name: 'Script',
|
|
335
|
+
code: `
|
|
336
|
+
import { ref } from 'vue'
|
|
337
|
+
import { Captcha } from '@cnamts/synapse'
|
|
338
|
+
|
|
339
|
+
const value = ref('abc')
|
|
340
|
+
|
|
341
|
+
const verifyCaptcha = () => {
|
|
342
|
+
// call the API to verify the captcha and return the response
|
|
343
|
+
}
|
|
344
|
+
`,
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
},
|
|
348
|
+
render: (args) => {
|
|
349
|
+
return {
|
|
350
|
+
components: { Captcha, VCard },
|
|
351
|
+
setup() {
|
|
352
|
+
const captchaValue = ref(args.modelValue)
|
|
353
|
+
watch(() => args.modelValue, () => {
|
|
354
|
+
captchaValue.value = args.modelValue
|
|
355
|
+
})
|
|
356
|
+
const verifyCaptcha = () => {
|
|
357
|
+
if (captchaValue.value === 'ytqZNq' || captchaValue.value === '941335') {
|
|
358
|
+
return Promise.resolve({ response: { data: { message: 'Success' } } })
|
|
359
|
+
}
|
|
360
|
+
return Promise.reject({ response: { data: { message: 'Le captcha est incorrect' } } })
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return { args, captchaValue, verifyCaptcha }
|
|
364
|
+
},
|
|
365
|
+
template: `
|
|
366
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
367
|
+
<p class="mb-4">La validation se déclenche à chaque modification de la valeur.</p>
|
|
368
|
+
<Captcha
|
|
369
|
+
v-bind="args"
|
|
370
|
+
v-model="captchaValue"
|
|
371
|
+
:is-validate-on-blur="false"
|
|
372
|
+
:custom-rules="[
|
|
373
|
+
{
|
|
374
|
+
type: 'custom',
|
|
375
|
+
options: {
|
|
376
|
+
validate: (value) => String(value || '').length >= 6,
|
|
377
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
type: 'custom',
|
|
382
|
+
options: {
|
|
383
|
+
validate: async (value) => {
|
|
384
|
+
try {
|
|
385
|
+
const r = await verifyCaptcha()
|
|
386
|
+
return r.response.data.message === 'Success'
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
return false
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
message: 'Le captcha est incorrect',
|
|
393
|
+
successMessage: 'Le captcha est correct',
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
]"
|
|
397
|
+
/>
|
|
398
|
+
</VCard>
|
|
399
|
+
`,
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
play: async ({ canvasElement }) => {
|
|
403
|
+
const input = within(canvasElement).getByRole('textbox')
|
|
404
|
+
await userEvent.clear(input)
|
|
405
|
+
// Saisie de la bonne réponse : la validation se met à jour à chaque frappe
|
|
406
|
+
// (erreur tant que < 6 caractères, puis succès une fois le bon captcha saisi).
|
|
407
|
+
await userEvent.type(input, 'ytqZNq')
|
|
408
|
+
},
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export const ExternalMessages: Story = {
|
|
412
|
+
parameters: {
|
|
413
|
+
a11y: {
|
|
414
|
+
disable: true,
|
|
415
|
+
},
|
|
416
|
+
docs: {
|
|
417
|
+
description: {
|
|
418
|
+
story: 'Messages injectés par le parent via `errorMessages`, `warningMessages` et `successMessages`.',
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
sourceCode: [
|
|
422
|
+
{
|
|
423
|
+
name: 'Template',
|
|
424
|
+
code: `
|
|
425
|
+
<VCard class="pa-8" max-width="400">
|
|
426
|
+
<Captcha
|
|
427
|
+
v-model="value"
|
|
428
|
+
:error-messages="errorMessages"
|
|
429
|
+
:warning-messages="warningMessages"
|
|
430
|
+
:success-messages="successMessages"
|
|
431
|
+
/>
|
|
432
|
+
<div class="mt-4 d-flex flex-wrap ga-2">
|
|
433
|
+
<VBtn @click="setError">Simuler une erreur</VBtn>
|
|
434
|
+
<VBtn @click="setWarning">Simuler un avertissement</VBtn>
|
|
435
|
+
<VBtn @click="setSuccess">Simuler un succès</VBtn>
|
|
436
|
+
<VBtn @click="reset">Réinitialiser</VBtn>
|
|
437
|
+
</div>
|
|
438
|
+
</VCard>
|
|
439
|
+
`,
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
render: args => ({
|
|
444
|
+
components: { Captcha, VBtn, VCard },
|
|
445
|
+
setup() {
|
|
446
|
+
const captchaValue = ref(args.modelValue)
|
|
447
|
+
watch(() => args.modelValue, (newValue) => {
|
|
448
|
+
captchaValue.value = newValue
|
|
449
|
+
})
|
|
450
|
+
const errorMessages = ref<string[] | null>(null)
|
|
451
|
+
const warningMessages = ref<string[] | null>(null)
|
|
452
|
+
const successMessages = ref<string[] | null>(null)
|
|
453
|
+
|
|
454
|
+
const verifyCaptcha = () => {
|
|
455
|
+
if (captchaValue.value === 'ytqZNq' || captchaValue.value === '941335') {
|
|
456
|
+
return Promise.resolve({ response: { data: { message: 'Success' } } })
|
|
457
|
+
}
|
|
458
|
+
return Promise.reject({ response: { data: { message: 'Le captcha est incorrect' } } })
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function setError() {
|
|
462
|
+
errorMessages.value = ['Ce captcha est déjà utilisé']
|
|
463
|
+
warningMessages.value = null
|
|
464
|
+
successMessages.value = null
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function setWarning() {
|
|
468
|
+
errorMessages.value = null
|
|
469
|
+
warningMessages.value = ['Ce captcha pourrait être plus lisible']
|
|
470
|
+
successMessages.value = null
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function setSuccess() {
|
|
474
|
+
errorMessages.value = null
|
|
475
|
+
warningMessages.value = null
|
|
476
|
+
successMessages.value = ['Captcha accepté']
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function reset() {
|
|
480
|
+
errorMessages.value = null
|
|
481
|
+
warningMessages.value = null
|
|
482
|
+
successMessages.value = null
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
return { args, captchaValue, errorMessages, warningMessages, successMessages, verifyCaptcha, setError, setWarning, setSuccess, reset }
|
|
486
|
+
},
|
|
487
|
+
template: `
|
|
488
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
489
|
+
<p class="mb-4">Les messages sont fournis directement par le parent sans déclencher de règle de validation.</p>
|
|
490
|
+
<Captcha
|
|
491
|
+
v-bind="args"
|
|
492
|
+
v-model="captchaValue"
|
|
493
|
+
:error-messages="errorMessages"
|
|
494
|
+
:warning-messages="warningMessages"
|
|
495
|
+
:success-messages="successMessages"
|
|
496
|
+
/>
|
|
497
|
+
</VCard>
|
|
498
|
+
<div class="mt-4 d-flex flex-wrap ga-2">
|
|
499
|
+
<VBtn color="error" @click="setError">Simuler une erreur</VBtn>
|
|
500
|
+
<VBtn color="warning" @click="setWarning">Simuler un avertissement</VBtn>
|
|
501
|
+
<VBtn color="success" @click="setSuccess">Simuler un succès</VBtn>
|
|
502
|
+
<VBtn color="black" @click="reset">Réinitialiser</VBtn>
|
|
503
|
+
</div>
|
|
504
|
+
`,
|
|
505
|
+
}),
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
export const DisableErrorHandling: Story = {
|
|
509
|
+
parameters: {
|
|
510
|
+
a11y: {
|
|
511
|
+
disable: true,
|
|
512
|
+
},
|
|
513
|
+
docs: {
|
|
514
|
+
description: {
|
|
515
|
+
story: 'Désactivation de la gestion des erreurs via `disableErrorHandling`.',
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
sourceCode: [
|
|
519
|
+
{
|
|
520
|
+
name: 'Template',
|
|
521
|
+
code: `<template>
|
|
522
|
+
<Captcha
|
|
523
|
+
v-model="value1"
|
|
524
|
+
required
|
|
525
|
+
:custom-rules="customRules"
|
|
526
|
+
/>
|
|
527
|
+
|
|
528
|
+
<Captcha
|
|
529
|
+
v-model="value2"
|
|
530
|
+
required
|
|
531
|
+
disable-error-handling
|
|
532
|
+
:custom-rules="customRules"
|
|
533
|
+
/>
|
|
534
|
+
</template>`,
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
name: 'Script',
|
|
538
|
+
code: `<script setup lang="ts">
|
|
539
|
+
import { ref } from 'vue'
|
|
540
|
+
import { Captcha } from '@cnamts/synapse'
|
|
541
|
+
const value1 = ref('')
|
|
542
|
+
const value2 = ref('')
|
|
543
|
+
|
|
544
|
+
const verifyCaptcha = (captchaValue: string | null) => {
|
|
545
|
+
// Simulate API call to verify captcha
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const customRules = [
|
|
549
|
+
{
|
|
550
|
+
type: 'custom',
|
|
551
|
+
options: {
|
|
552
|
+
validate: (value: string) => {
|
|
553
|
+
if (!value || value.trim().length === 0) {
|
|
554
|
+
return false
|
|
555
|
+
}
|
|
556
|
+
return true
|
|
557
|
+
},
|
|
558
|
+
message: 'Ce champ est requis.',
|
|
559
|
+
}
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
type: 'custom',
|
|
563
|
+
options: {
|
|
564
|
+
validate: async (value: string) => {
|
|
565
|
+
try {
|
|
566
|
+
const r = await verifyCaptcha(value)
|
|
567
|
+
return r.response.data.message === 'Success'
|
|
568
|
+
}
|
|
569
|
+
catch {
|
|
570
|
+
return false
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
message: 'Le captcha est incorrect.',
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
]
|
|
577
|
+
</script>`,
|
|
578
|
+
},
|
|
579
|
+
],
|
|
580
|
+
},
|
|
581
|
+
render: args => ({
|
|
582
|
+
components: { Captcha, VCard },
|
|
583
|
+
setup() {
|
|
584
|
+
const value1 = ref('')
|
|
585
|
+
const value2 = ref('')
|
|
586
|
+
|
|
587
|
+
const verifyCaptcha = (captchaValue: string | null) => {
|
|
588
|
+
if (captchaValue === 'ytqZNq' || captchaValue === '941335') {
|
|
589
|
+
return Promise.resolve({ response: { data: { message: 'Success' } } })
|
|
590
|
+
}
|
|
591
|
+
return Promise.reject({ response: { data: { message: 'Le captcha est incorrect' } } })
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
const customRules = [
|
|
595
|
+
{
|
|
596
|
+
type: 'custom',
|
|
597
|
+
options: {
|
|
598
|
+
validate: (value: string) => {
|
|
599
|
+
if (!value || value.trim().length === 0) {
|
|
600
|
+
return false
|
|
601
|
+
}
|
|
602
|
+
return true
|
|
603
|
+
},
|
|
604
|
+
message: 'Ce champ est requis.',
|
|
605
|
+
fieldIdentifier: 'captcha',
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
type: 'custom',
|
|
610
|
+
options: {
|
|
611
|
+
validate: async (value: string) => {
|
|
612
|
+
try {
|
|
613
|
+
const r = await verifyCaptcha(value)
|
|
614
|
+
return r.response.data.message === 'Success'
|
|
615
|
+
}
|
|
616
|
+
catch {
|
|
617
|
+
return false
|
|
618
|
+
}
|
|
619
|
+
},
|
|
620
|
+
message: 'Le captcha est incorrect.',
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
]
|
|
624
|
+
|
|
625
|
+
return { args, value1, value2, customRules }
|
|
626
|
+
},
|
|
627
|
+
template: `
|
|
628
|
+
<div>
|
|
629
|
+
<p class="mb-4">Cette démonstration compare un Captcha standard et un avec <code>disableErrorHandling=true</code>.</p>
|
|
630
|
+
|
|
631
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 64px; margin-bottom: 16px;">
|
|
632
|
+
<div>
|
|
633
|
+
<p class="text-subtitle-2 mb-2">Validation normale</p>
|
|
634
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
635
|
+
<Captcha
|
|
636
|
+
v-bind="args"
|
|
637
|
+
v-model="value1"
|
|
638
|
+
required
|
|
639
|
+
:custom-rules="customRules"
|
|
640
|
+
/>
|
|
641
|
+
</VCard>
|
|
642
|
+
</div>
|
|
643
|
+
|
|
644
|
+
<div>
|
|
645
|
+
<p class="text-subtitle-2 mb-2">Sans gestion d'erreurs</p>
|
|
646
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
647
|
+
<Captcha
|
|
648
|
+
v-bind="args"
|
|
649
|
+
v-model="value2"
|
|
650
|
+
required
|
|
651
|
+
disable-error-handling
|
|
652
|
+
:custom-rules="customRules"
|
|
653
|
+
/>
|
|
654
|
+
</VCard>
|
|
655
|
+
</div>
|
|
656
|
+
</div>
|
|
657
|
+
|
|
658
|
+
<div class="mt-4 text-body-2">
|
|
659
|
+
<p>Instructions :</p>
|
|
660
|
+
<ol>
|
|
661
|
+
<li class="ml-4">Cliquez dans un champ puis en dehors pour déclencher la validation</li>
|
|
662
|
+
<li class="ml-4">Le champ de gauche affichera une erreur requise, mais pas celui de droite</li>
|
|
663
|
+
</ol>
|
|
664
|
+
</div>
|
|
665
|
+
</div>
|
|
666
|
+
`,
|
|
667
|
+
}),
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export const SyFormValidation: Story = {
|
|
671
|
+
parameters: {
|
|
672
|
+
a11y: {
|
|
673
|
+
disable: true,
|
|
674
|
+
},
|
|
675
|
+
docs: {
|
|
676
|
+
description: {
|
|
677
|
+
story: 'Intégration avec `SyForm` pour soumettre un Captcha validé par règles personnalisées.',
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
sourceCode: [
|
|
681
|
+
{
|
|
682
|
+
name: 'Template',
|
|
683
|
+
code: `<template>
|
|
684
|
+
<SyForm @submit="handleSubmit">
|
|
685
|
+
<VCard class="pa-8" max-width="400">
|
|
686
|
+
<Captcha
|
|
687
|
+
v-model="value"
|
|
688
|
+
:custom-rules="customRules"
|
|
689
|
+
required
|
|
690
|
+
/>
|
|
691
|
+
<div class="mt-4">
|
|
692
|
+
<VBtn type="submit" color="primary">Valider</VBtn>
|
|
693
|
+
</div>
|
|
694
|
+
</VCard>
|
|
695
|
+
</SyForm>
|
|
696
|
+
</template>`,
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
name: 'Script',
|
|
700
|
+
code: `<script setup lang="ts">
|
|
701
|
+
import { ref } from 'vue'
|
|
702
|
+
import { Captcha, SyForm } from '@cnamts/synapse'
|
|
703
|
+
|
|
704
|
+
const value = ref('')
|
|
705
|
+
|
|
706
|
+
const verifyCaptcha = () => {
|
|
707
|
+
// Simulate API call to verify captcha
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
const customRules = [
|
|
711
|
+
{
|
|
712
|
+
type: 'custom',
|
|
713
|
+
options: {
|
|
714
|
+
validate: (value: string) => String(value || '').length >= 6,
|
|
715
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
716
|
+
fieldIdentifier: 'captcha',
|
|
717
|
+
},
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
type: 'custom',
|
|
721
|
+
options: {
|
|
722
|
+
validate: async (value: string) => {
|
|
723
|
+
try {
|
|
724
|
+
const r = await verifyCaptcha()
|
|
725
|
+
return r.response.data.message === 'Success'
|
|
726
|
+
}
|
|
727
|
+
catch {
|
|
728
|
+
return false
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
message: 'Le captcha est incorrect',
|
|
732
|
+
fieldIdentifier: 'captcha',
|
|
733
|
+
successMessage: 'Le captcha est correct',
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
]
|
|
737
|
+
|
|
738
|
+
function handleSubmit(e: { isValid: boolean }) {
|
|
739
|
+
alert(e.isValid ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
740
|
+
}
|
|
741
|
+
</script>`,
|
|
742
|
+
},
|
|
743
|
+
],
|
|
744
|
+
},
|
|
745
|
+
render: args => ({
|
|
746
|
+
components: { Captcha, VBtn, SyForm },
|
|
747
|
+
setup() {
|
|
748
|
+
const captchaValue = ref(args.modelValue)
|
|
749
|
+
watch(() => args.modelValue, (newValue) => {
|
|
750
|
+
captchaValue.value = newValue
|
|
751
|
+
})
|
|
752
|
+
|
|
753
|
+
const verifyCaptcha = () => {
|
|
754
|
+
if (captchaValue.value === 'ytqZNq' || captchaValue.value === '941335') {
|
|
755
|
+
return Promise.resolve({ response: { data: { message: 'Success' } } })
|
|
756
|
+
}
|
|
757
|
+
return Promise.reject({ response: { data: { message: 'Le captcha est incorrect' } } })
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const customRules = [
|
|
761
|
+
{
|
|
762
|
+
type: 'custom',
|
|
763
|
+
options: {
|
|
764
|
+
validate: (value: string) => String(value || '').length >= 6,
|
|
765
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
766
|
+
fieldIdentifier: 'captcha',
|
|
767
|
+
},
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
type: 'custom',
|
|
771
|
+
options: {
|
|
772
|
+
validate: async () => {
|
|
773
|
+
try {
|
|
774
|
+
const r = await verifyCaptcha()
|
|
775
|
+
return r.response.data.message === 'Success'
|
|
776
|
+
}
|
|
777
|
+
catch {
|
|
778
|
+
return false
|
|
779
|
+
}
|
|
780
|
+
},
|
|
781
|
+
message: 'Le captcha est incorrect',
|
|
782
|
+
fieldIdentifier: 'captcha',
|
|
783
|
+
successMessage: 'Le captcha est correct',
|
|
784
|
+
},
|
|
785
|
+
},
|
|
786
|
+
]
|
|
787
|
+
|
|
788
|
+
function handleSubmit(e: { isValid: boolean }) {
|
|
789
|
+
alert(e.isValid ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
return { args, captchaValue, customRules, handleSubmit }
|
|
793
|
+
},
|
|
794
|
+
template: `
|
|
795
|
+
<div>
|
|
796
|
+
<p class="mb-4">Il faut privilégier l'utilisation de <code>SyForm</code> pour bénéficier de l'intégration de validation.</p>
|
|
797
|
+
<SyForm @submit="handleSubmit">
|
|
798
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
799
|
+
<Captcha
|
|
800
|
+
v-bind="args"
|
|
801
|
+
v-model="captchaValue"
|
|
802
|
+
:custom-rules="customRules"
|
|
803
|
+
width="400px"
|
|
804
|
+
required
|
|
805
|
+
/>
|
|
806
|
+
<div class="mt-4">
|
|
807
|
+
<VBtn type="submit" color="primary">Valider</VBtn>
|
|
808
|
+
</div>
|
|
809
|
+
</VCard>
|
|
810
|
+
</SyForm>
|
|
811
|
+
</div>
|
|
812
|
+
`,
|
|
813
|
+
}),
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
export const VFormValidation: Story = {
|
|
817
|
+
parameters: {
|
|
818
|
+
a11y: {
|
|
819
|
+
disable: true,
|
|
820
|
+
},
|
|
821
|
+
docs: {
|
|
822
|
+
description: {
|
|
823
|
+
story: 'Validation déclenchée à la soumission du formulaire via l\'API exposée `validate()` du Captcha.',
|
|
824
|
+
},
|
|
825
|
+
},
|
|
826
|
+
sourceCode: [
|
|
827
|
+
{
|
|
828
|
+
name: 'Template',
|
|
829
|
+
code: `<template>
|
|
830
|
+
<VForm @submit.prevent="handleSubmit">
|
|
831
|
+
<VCard class="pa-8" max-width="400">
|
|
832
|
+
<Captcha
|
|
833
|
+
ref="captchaRef"
|
|
834
|
+
v-model="value"
|
|
835
|
+
required
|
|
836
|
+
:custom-rules="customRules"
|
|
837
|
+
/>
|
|
838
|
+
<VBtn type="submit" color="primary" class="mt-4">Valider</VBtn>
|
|
839
|
+
</VCard>
|
|
840
|
+
</VForm>
|
|
841
|
+
</template>`,
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
name: 'Script',
|
|
845
|
+
code: `<script setup lang="ts">
|
|
846
|
+
import { ref } from 'vue'
|
|
847
|
+
import { Captcha } from '@cnamts/synapse'
|
|
848
|
+
import { VBtn, VForm } from 'vuetify/components'
|
|
849
|
+
|
|
850
|
+
const value = ref('')
|
|
851
|
+
const captchaRef = ref()
|
|
852
|
+
|
|
853
|
+
const customRules = [
|
|
854
|
+
{
|
|
855
|
+
type: 'custom',
|
|
856
|
+
options: {
|
|
857
|
+
validate: (value: string) => String(value || '').length >= 6,
|
|
858
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
859
|
+
fieldIdentifier: 'captcha',
|
|
860
|
+
},
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
type: 'custom',
|
|
864
|
+
options: {
|
|
865
|
+
validate: async (value: string) => {
|
|
866
|
+
try {
|
|
867
|
+
const r = await verifyCaptcha()
|
|
868
|
+
return r.response.data.message === 'Success'
|
|
869
|
+
}
|
|
870
|
+
catch {
|
|
871
|
+
return false
|
|
872
|
+
}
|
|
873
|
+
},
|
|
874
|
+
message: 'Le captcha est incorrect',
|
|
875
|
+
successMessage: 'Le captcha est correct',
|
|
876
|
+
},
|
|
877
|
+
},
|
|
878
|
+
]
|
|
879
|
+
|
|
880
|
+
async function handleSubmit() {
|
|
881
|
+
if (captchaRef.value) {
|
|
882
|
+
const result = await captchaRef.value.validateOnSubmit()
|
|
883
|
+
alert(result ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
</script>`,
|
|
887
|
+
},
|
|
888
|
+
],
|
|
889
|
+
},
|
|
890
|
+
render: args => ({
|
|
891
|
+
components: { Captcha, VBtn, VForm },
|
|
892
|
+
setup() {
|
|
893
|
+
const value = ref(args.modelValue)
|
|
894
|
+
watch(() => args.modelValue, (newValue) => {
|
|
895
|
+
value.value = newValue
|
|
896
|
+
})
|
|
897
|
+
const captchaRef = ref()
|
|
898
|
+
|
|
899
|
+
const verifyCaptcha = () => {
|
|
900
|
+
if (value.value === 'ytqZNq' || value.value === '941335') {
|
|
901
|
+
return Promise.resolve({ response: { data: { message: 'Success' } } })
|
|
902
|
+
}
|
|
903
|
+
return Promise.reject({ response: { data: { message: 'Le captcha est incorrect' } } })
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
const customRules = [
|
|
907
|
+
{
|
|
908
|
+
type: 'custom',
|
|
909
|
+
options: {
|
|
910
|
+
validate: (captchaValue: string) => String(captchaValue || '').length >= 6,
|
|
911
|
+
message: 'Le captcha doit contenir au moins 6 caractères.',
|
|
912
|
+
fieldIdentifier: 'captcha',
|
|
913
|
+
},
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
type: 'custom',
|
|
917
|
+
options: {
|
|
918
|
+
validate: async () => {
|
|
919
|
+
try {
|
|
920
|
+
const r = await verifyCaptcha()
|
|
921
|
+
return r.response.data.message === 'Success'
|
|
922
|
+
}
|
|
923
|
+
catch {
|
|
924
|
+
return false
|
|
925
|
+
}
|
|
926
|
+
},
|
|
927
|
+
message: 'Le captcha est incorrect',
|
|
928
|
+
successMessage: 'Le captcha est correct',
|
|
929
|
+
fieldIdentifier: 'captcha',
|
|
930
|
+
},
|
|
931
|
+
},
|
|
932
|
+
]
|
|
933
|
+
|
|
934
|
+
async function handleSubmit() {
|
|
935
|
+
if (captchaRef.value) {
|
|
936
|
+
const result = await captchaRef.value.validateOnSubmit()
|
|
937
|
+
alert(result ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
return { args, value, captchaRef, customRules, handleSubmit }
|
|
942
|
+
},
|
|
943
|
+
template: `
|
|
944
|
+
<div>
|
|
945
|
+
<p class="mb-4">Il faut privilégier l'utilisation du composant SyForm pour déclencher la validation à la soumission.</p>
|
|
946
|
+
<VForm @submit.prevent="handleSubmit">
|
|
947
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
948
|
+
<Captcha
|
|
949
|
+
ref="captchaRef"
|
|
950
|
+
v-bind="args"
|
|
951
|
+
v-model="value"
|
|
952
|
+
:custom-rules="customRules"
|
|
953
|
+
required
|
|
954
|
+
width="400px"
|
|
955
|
+
/>
|
|
956
|
+
<VBtn type="submit" color="primary" class="mt-4">Valider</VBtn>
|
|
957
|
+
</VCard>
|
|
958
|
+
</VForm>
|
|
959
|
+
</div>
|
|
960
|
+
`,
|
|
961
|
+
}),
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
export const SyFormVuetifyValidation: Story = {
|
|
965
|
+
parameters: {
|
|
966
|
+
a11y: {
|
|
967
|
+
disable: true,
|
|
968
|
+
},
|
|
969
|
+
docs: {
|
|
970
|
+
description: {
|
|
971
|
+
story: 'Validation native Vuetify (`useVuetifyValidation=true` + `rules`) intégrée automatiquement à un `SyForm`.',
|
|
972
|
+
},
|
|
973
|
+
},
|
|
974
|
+
sourceCode: [
|
|
975
|
+
{
|
|
976
|
+
name: 'Template',
|
|
977
|
+
code: `<template>
|
|
978
|
+
<SyForm @submit="handleSubmit">
|
|
979
|
+
<VCard class="pa-8" max-width="400">
|
|
980
|
+
<Captcha
|
|
981
|
+
v-model="value"
|
|
982
|
+
:use-vuetify-validation="true"
|
|
983
|
+
:rules="rules"
|
|
984
|
+
required
|
|
985
|
+
/>
|
|
986
|
+
<div class="mt-4">
|
|
987
|
+
<VBtn type="submit" color="primary">Valider</VBtn>
|
|
988
|
+
</div>
|
|
989
|
+
</VCard>
|
|
990
|
+
</SyForm>
|
|
991
|
+
</template>`,
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
name: 'Script',
|
|
995
|
+
code: `<script setup lang="ts">
|
|
996
|
+
import { ref } from 'vue'
|
|
997
|
+
import { Captcha, SyForm } from '@cnamts/synapse'
|
|
998
|
+
|
|
999
|
+
const value = ref('')
|
|
1000
|
+
|
|
1001
|
+
const rules = [
|
|
1002
|
+
(value: string) => !!value || 'Ce champ est requis',
|
|
1003
|
+
(value: string) => String(value || '').length >= 6 || 'Le captcha doit contenir au moins 6 caractères',
|
|
1004
|
+
async () => {
|
|
1005
|
+
try {
|
|
1006
|
+
const r = await verifyCaptcha()
|
|
1007
|
+
return r.response.data.message === 'Success' || 'Le captcha est incorrect'
|
|
1008
|
+
}
|
|
1009
|
+
catch {
|
|
1010
|
+
return 'Le captcha est incorrect'
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
]
|
|
1014
|
+
|
|
1015
|
+
function handleSubmit(e: { isValid: boolean }) {
|
|
1016
|
+
alert(e.isValid ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
1017
|
+
}
|
|
1018
|
+
</script>`,
|
|
1019
|
+
},
|
|
1020
|
+
],
|
|
1021
|
+
},
|
|
1022
|
+
render: args => ({
|
|
1023
|
+
components: { Captcha, VBtn, SyForm },
|
|
1024
|
+
setup() {
|
|
1025
|
+
const captchaValue = ref(args.modelValue)
|
|
1026
|
+
watch(() => args.modelValue, (newValue) => {
|
|
1027
|
+
captchaValue.value = newValue
|
|
1028
|
+
})
|
|
1029
|
+
|
|
1030
|
+
const verifyCaptcha = () => {
|
|
1031
|
+
if (captchaValue.value === 'ytqZNq' || captchaValue.value === '941335') {
|
|
1032
|
+
return Promise.resolve({ response: { data: { message: 'Success' } } })
|
|
1033
|
+
}
|
|
1034
|
+
return Promise.reject({ response: { data: { message: 'Le captcha est incorrect' } } })
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
const rules = [
|
|
1038
|
+
(value: string) => !!value || 'Ce champ est requis',
|
|
1039
|
+
(value: string) => String(value || '').length >= 6 || 'Le captcha doit contenir au moins 6 caractères',
|
|
1040
|
+
async () => {
|
|
1041
|
+
try {
|
|
1042
|
+
const r = await verifyCaptcha()
|
|
1043
|
+
return r.response.data.message === 'Success' || 'Le captcha est incorrect'
|
|
1044
|
+
}
|
|
1045
|
+
catch {
|
|
1046
|
+
return 'Le captcha est incorrect'
|
|
1047
|
+
}
|
|
1048
|
+
},
|
|
1049
|
+
]
|
|
1050
|
+
|
|
1051
|
+
function handleSubmit(e: { isValid: boolean }) {
|
|
1052
|
+
alert(e.isValid ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
return { args, captchaValue, rules, handleSubmit }
|
|
1056
|
+
},
|
|
1057
|
+
template: `
|
|
1058
|
+
<div>
|
|
1059
|
+
<p class="mb-4">Validation Vuetify native intégrée au <code>SyForm</code> via <code>useVuetifyValidation</code>.</p>
|
|
1060
|
+
<SyForm @submit="handleSubmit">
|
|
1061
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
1062
|
+
<Captcha
|
|
1063
|
+
v-bind="args"
|
|
1064
|
+
v-model="captchaValue"
|
|
1065
|
+
:use-vuetify-validation="true"
|
|
1066
|
+
:rules="rules"
|
|
1067
|
+
width="400px"
|
|
1068
|
+
required
|
|
1069
|
+
/>
|
|
1070
|
+
<div class="mt-4">
|
|
1071
|
+
<VBtn type="submit" color="primary">Valider</VBtn>
|
|
1072
|
+
</div>
|
|
1073
|
+
</VCard>
|
|
1074
|
+
</SyForm>
|
|
1075
|
+
</div>
|
|
1076
|
+
`,
|
|
1077
|
+
}),
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
export const VFormVuetifyValidation: Story = {
|
|
1081
|
+
parameters: {
|
|
1082
|
+
a11y: {
|
|
1083
|
+
disable: true,
|
|
1084
|
+
},
|
|
1085
|
+
docs: {
|
|
1086
|
+
description: {
|
|
1087
|
+
story: 'Validation de style Vuetify avec `useVuetifyValidation=true` et des règles natives.',
|
|
1088
|
+
},
|
|
1089
|
+
},
|
|
1090
|
+
sourceCode: [
|
|
1091
|
+
{
|
|
1092
|
+
name: 'Template',
|
|
1093
|
+
code: `<template>
|
|
1094
|
+
<VForm @submit.prevent="handleSubmit">
|
|
1095
|
+
<VCard class="pa-8" max-width="400">
|
|
1096
|
+
<Captcha
|
|
1097
|
+
v-model="value"
|
|
1098
|
+
:use-vuetify-validation="true"
|
|
1099
|
+
:rules="rules"
|
|
1100
|
+
required
|
|
1101
|
+
/>
|
|
1102
|
+
<div class="mt-4">
|
|
1103
|
+
<VBtn type="submit" color="primary">Valider</VBtn>
|
|
1104
|
+
</div>
|
|
1105
|
+
</VCard>
|
|
1106
|
+
</VForm>
|
|
1107
|
+
</template>`,
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
name: 'Script',
|
|
1111
|
+
code: `<script setup lang="ts">
|
|
1112
|
+
import { ref } from 'vue'
|
|
1113
|
+
import { Captcha } from '@cnamts/synapse'
|
|
1114
|
+
|
|
1115
|
+
const value = ref('')
|
|
1116
|
+
|
|
1117
|
+
const rules = [
|
|
1118
|
+
(value: string) => !!value || 'Ce champ est requis',
|
|
1119
|
+
(value: string) => String(value || '').length >= 6 || 'Le captcha doit contenir au moins 6 caractères',
|
|
1120
|
+
async () => {
|
|
1121
|
+
try {
|
|
1122
|
+
const r = await verifyCaptcha()
|
|
1123
|
+
return r.response.data.message === 'Success' || 'Le captcha est incorrect'
|
|
1124
|
+
}
|
|
1125
|
+
catch {
|
|
1126
|
+
return 'Le captcha est incorrect'
|
|
1127
|
+
}
|
|
1128
|
+
},
|
|
1129
|
+
]
|
|
1130
|
+
|
|
1131
|
+
async function handleSubmit(e) {
|
|
1132
|
+
alert((await e).valid ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
1133
|
+
}
|
|
1134
|
+
</script>`,
|
|
1135
|
+
},
|
|
1136
|
+
],
|
|
1137
|
+
},
|
|
1138
|
+
render: args => ({
|
|
1139
|
+
components: { Captcha, VBtn, VForm },
|
|
1140
|
+
setup() {
|
|
1141
|
+
const captchaValue = ref(args.modelValue)
|
|
1142
|
+
watch(() => args.modelValue, (newValue) => {
|
|
1143
|
+
captchaValue.value = newValue
|
|
1144
|
+
})
|
|
1145
|
+
|
|
1146
|
+
const rules = [
|
|
1147
|
+
(value: string) => !!value || 'Ce champ est requis',
|
|
1148
|
+
(value: string) => String(value || '').length >= 6 || 'Le captcha doit contenir au moins 6 caractères',
|
|
1149
|
+
async () => {
|
|
1150
|
+
try {
|
|
1151
|
+
const r = await verifyCaptcha()
|
|
1152
|
+
return r.response.data.message === 'Success' || 'Le captcha est incorrect'
|
|
1153
|
+
}
|
|
1154
|
+
catch {
|
|
1155
|
+
return 'Le captcha est incorrect'
|
|
1156
|
+
}
|
|
1157
|
+
},
|
|
1158
|
+
]
|
|
1159
|
+
|
|
1160
|
+
const verifyCaptcha = () => {
|
|
1161
|
+
if (captchaValue.value === 'ytqZNq' || captchaValue.value === '941335') {
|
|
1162
|
+
return Promise.resolve({ response: { data: { message: 'Success' } } })
|
|
1163
|
+
}
|
|
1164
|
+
return Promise.reject({ response: { data: { message: 'Le captcha est incorrect' } } })
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
async function handleSubmit(e: Promise<{ valid: boolean }>) {
|
|
1168
|
+
const result = await e
|
|
1169
|
+
alert(result.valid ? 'Valeur valide !' : 'Veuillez corriger les erreurs.')
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
return { args, captchaValue, rules, handleSubmit }
|
|
1173
|
+
},
|
|
1174
|
+
template: `
|
|
1175
|
+
<div>
|
|
1176
|
+
<p class="mb-4">Les règles suivent le contrat Vuetify natif: <code>(value) => true | 'message'</code>.</p>
|
|
1177
|
+
<VForm @submit.prevent="handleSubmit">
|
|
1178
|
+
<VCard class="pa-8" max-width="400" min-width="400">
|
|
1179
|
+
<Captcha
|
|
1180
|
+
v-bind="args"
|
|
1181
|
+
v-model="captchaValue"
|
|
1182
|
+
:use-vuetify-validation="true"
|
|
1183
|
+
:rules="rules"
|
|
1184
|
+
width="400px"
|
|
1185
|
+
/>
|
|
1186
|
+
<div class="mt-4">
|
|
1187
|
+
<VBtn type="submit" color="primary">Valider</VBtn>
|
|
1188
|
+
</div>
|
|
1189
|
+
</VCard>
|
|
1190
|
+
</VForm>
|
|
1191
|
+
</div>
|
|
1192
|
+
`,
|
|
1193
|
+
}),
|
|
1194
|
+
}
|