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