@cnamts/synapse 0.0.5-alpha → 0.0.7-alpha
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/design-system-v3.d.ts +487 -415
- package/dist/design-system-v3.js +2954 -2203
- package/dist/design-system-v3.umd.cjs +6 -6
- package/dist/style.css +1 -1
- package/package.json +17 -17
- package/src/assets/settings.scss +3 -0
- package/src/assets/tokens.scss +16 -16
- package/src/components/BackBtn/AccessibiliteItems.ts +0 -30
- package/src/components/BackBtn/BackBtn.mdx +1 -1
- package/src/components/BackBtn/BackBtn.stories.ts +12 -9
- package/src/components/BackBtn/BackBtn.vue +0 -1
- package/src/components/BackToTopBtn/AccessibiliteItems.ts +0 -30
- package/src/components/BackToTopBtn/BackToTopBtn.mdx +1 -1
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +3 -3
- package/src/components/CollapsibleList/Accessibilite.stories.ts +4 -0
- package/src/components/CollapsibleList/AccessibiliteItems.ts +55 -62
- package/src/components/CollapsibleList/CollapsibleList.stories.ts +1 -1
- package/src/components/CookieBanner/Accessibilite.stories.ts +219 -0
- package/src/components/CookieBanner/AccessibiliteItems.ts +356 -0
- package/src/components/CookieBanner/CookieBanner.mdx +219 -0
- package/src/components/CookieBanner/CookieBanner.stories.ts +680 -0
- package/src/components/CookieBanner/CookieBanner.vue +225 -0
- package/src/components/CookieBanner/config.ts +38 -0
- package/src/components/CookieBanner/locales.ts +12 -0
- package/src/components/CookieBanner/tests/CookieBanner.spec.ts +129 -0
- package/src/components/CookieBanner/tests/__snapshots__/CookieBanner.spec.ts.snap +197 -0
- package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +123 -0
- package/src/components/CookiesSelection/CookiesInformation/locales.ts +21 -0
- package/src/components/CookiesSelection/CookiesInformation/tests/CookiesInformation.spec.ts +121 -0
- package/src/components/CookiesSelection/CookiesSelection.vue +127 -0
- package/src/components/CookiesSelection/CookiesTable/CookiesTable.vue +47 -0
- package/src/components/CookiesSelection/CookiesTable/headers.ts +14 -0
- package/src/components/CookiesSelection/CookiesTable/tests/CookiesTable.spec.ts +30 -0
- package/src/components/CookiesSelection/CookiesTable/tests/__snapshots__/CookiesTable.spec.ts.snap +3 -0
- package/src/components/CookiesSelection/locales.ts +10 -0
- package/src/components/CookiesSelection/tests/CookiesSelection.spec.ts +184 -0
- package/src/components/CookiesSelection/tests/__snapshots__/CookiesSelection.spec.ts.snap +192 -0
- package/src/components/CookiesSelection/types.ts +15 -0
- package/src/components/CopyBtn/AccessibiliteItems.ts +0 -30
- package/src/components/CopyBtn/CopyBtn.mdx +1 -1
- package/src/components/CopyBtn/CopyBtn.stories.ts +9 -6
- package/src/components/CopyBtn/CopyBtn.vue +0 -1
- package/src/components/Customs/SyBtnSelect/Accessibilite.mdx +14 -0
- package/src/components/Customs/SyBtnSelect/Accessibilite.stories.ts +193 -0
- package/src/components/Customs/SyBtnSelect/AccessibiliteItems.ts +139 -0
- package/src/components/Customs/SyBtnSelect/SyBtnSelect.mdx +3 -2
- package/src/components/Customs/SyBtnSelect/SyBtnSelect.stories.ts +30 -14
- package/src/components/Customs/SyBtnSelect/SyBtnSelect.vue +21 -13
- package/src/components/Customs/SyBtnSelect/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/Customs/SyInputSelect/Accessibilite.mdx +14 -0
- package/src/components/Customs/SyInputSelect/Accessibilite.stories.ts +166 -0
- package/src/components/Customs/SyInputSelect/AccessibiliteItems.ts +96 -0
- package/src/components/Customs/SyInputSelect/SyInputSelect.mdx +7 -3
- package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +24 -65
- package/src/components/Customs/SyInputSelect/SyInputSelect.vue +36 -4
- package/src/components/Customs/SyInputSelect/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/Customs/SySelect/Accessibilite.mdx +14 -0
- package/src/components/Customs/SySelect/Accessibilite.stories.ts +217 -0
- package/src/components/Customs/SySelect/AccessibiliteItems.ts +173 -0
- package/src/components/Customs/SySelect/SySelect.mdx +4 -4
- package/src/components/Customs/SySelect/SySelect.stories.ts +4 -60
- package/src/components/Customs/SySelect/SySelect.vue +35 -8
- package/src/components/Customs/SySelect/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/Customs/SyTextField/Accessibilite.mdx +14 -0
- package/src/components/Customs/SyTextField/Accessibilite.stories.ts +224 -0
- package/src/components/Customs/SyTextField/AccessibiliteItems.ts +198 -0
- package/src/components/Customs/SyTextField/SyTextField.mdx +1 -1
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +118 -7
- package/src/components/Customs/SyTextField/SyTextField.vue +27 -7
- package/src/components/Customs/SyTextField/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/Customs/SyTextField/tests/__snapshots__/SyTextField.spec.ts.snap +2 -1
- package/src/components/DataList/Accessibilite.mdx +14 -0
- package/src/components/DataList/Accessibilite.stories.ts +166 -0
- package/src/components/DataList/AccessibiliteItems.ts +47 -0
- package/src/components/DataList/DataList.mdx +1 -1
- package/src/components/DataList/DataList.stories.ts +10 -10
- package/src/components/DataList/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/DataListGroup/Accessibilite.mdx +14 -0
- package/src/components/DataListGroup/Accessibilite.stories.ts +225 -0
- package/src/components/DataListGroup/AccessibiliteItems.ts +79 -0
- package/src/components/DataListGroup/DataListGroup.mdx +1 -1
- package/src/components/DataListGroup/DataListGroup.stories.ts +7 -7
- package/src/components/DataListGroup/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/DialogBox/Accessibilite.mdx +14 -0
- package/src/components/DialogBox/Accessibilite.stories.ts +189 -0
- package/src/components/DialogBox/AccessibiliteItems.ts +167 -0
- package/src/components/DialogBox/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/DownloadBtn/AccessibiliteItems.ts +1 -31
- package/src/components/DownloadBtn/DownloadBtn.mdx +5 -6
- package/src/components/DownloadBtn/DownloadBtn.stories.ts +25 -26
- package/src/components/ErrorPage/Accessibilite.mdx +14 -0
- package/src/components/ErrorPage/Accessibilite.stories.ts +189 -0
- package/src/components/ErrorPage/AccessibiliteItems.ts +205 -0
- package/src/components/ErrorPage/ErrorPage.vue +1 -1
- package/src/components/ErrorPage/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +4 -4
- package/src/components/FooterBar/Accessibilite.mdx +14 -0
- package/src/components/FooterBar/Accessibilite.stories.ts +223 -0
- package/src/components/FooterBar/AccessibiliteItems.ts +257 -0
- package/src/components/FooterBar/FooterBar.mdx +2 -2
- package/src/components/FooterBar/FooterBar.stories.ts +14 -14
- package/src/components/FooterBar/FooterBar.vue +86 -75
- package/src/components/FooterBar/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/FooterBar/tests/__snapshots__/FooterBar.spec.ts.snap +22 -20
- package/src/components/FranceConnectBtn/AccessibiliteItems.ts +0 -30
- package/src/components/FranceConnectBtn/FranceConnectBtn.mdx +1 -1
- package/src/components/FranceConnectBtn/FranceConnectBtn.stories.ts +5 -4
- package/src/components/HeaderBar/Accessibilite.mdx +14 -0
- package/src/components/HeaderBar/Accessibilite.stories.ts +223 -0
- package/src/components/HeaderBar/AccessibiliteItems.ts +194 -0
- package/src/components/HeaderBar/HeaderBar.stories.ts +19 -12
- package/src/components/HeaderBar/HeaderBar.vue +9 -12
- package/src/components/HeaderBar/HeaderBurgerMenu/Accessibilite.mdx +14 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/Accessibilite.stories.ts +223 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/AccessibiliteItems.ts +174 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.vue +1 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/HeaderBar/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/HeaderBar/tests/__snapshots__/HeaderBar.spec.ts.snap +1 -1
- package/src/components/HeaderLoading/Accessibilite.mdx +14 -0
- package/src/components/HeaderLoading/Accessibilite.stories.ts +167 -0
- package/src/components/HeaderLoading/AccessibiliteItems.ts +29 -0
- package/src/components/HeaderLoading/HeaderLoading.mdx +1 -1
- package/src/components/HeaderLoading/HeaderLoading.stories.ts +1 -1
- package/src/components/HeaderLoading/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.stories.ts +104 -32
- package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +35 -33
- package/src/components/HeaderToolbar/Accessibilite.mdx +14 -0
- package/src/components/HeaderToolbar/Accessibilite.stories.ts +203 -0
- package/src/components/HeaderToolbar/AccessibiliteItems.ts +200 -0
- package/src/components/HeaderToolbar/HeaderToolbar.mdx +1 -1
- package/src/components/HeaderToolbar/HeaderToolbar.stories.ts +2 -2
- package/src/components/HeaderToolbar/HeaderToolbar.vue +24 -1
- package/src/components/HeaderToolbar/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/LangBtn/Accessibilite.stories.ts +3 -1
- package/src/components/LangBtn/AccessibiliteItems.ts +0 -31
- package/src/components/LangBtn/LangBtn.mdx +1 -1
- package/src/components/LangBtn/LangBtn.stories.ts +4 -4
- package/src/components/LangBtn/LangBtn.vue +3 -2
- package/src/components/Logo/Accessibilite.mdx +14 -0
- package/src/components/Logo/Accessibilite.stories.ts +223 -0
- package/src/components/Logo/AccessibiliteItems.ts +155 -0
- package/src/components/Logo/Logo.mdx +1 -1
- package/src/components/Logo/Logo.stories.ts +8 -8
- package/src/components/Logo/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/LogoBrandSection/Accessibilite.mdx +14 -0
- package/src/components/LogoBrandSection/Accessibilite.stories.ts +223 -0
- package/src/components/LogoBrandSection/AccessibiliteItems.ts +194 -0
- package/src/components/LogoBrandSection/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/MaintenancePage/Accessibilite.mdx +14 -0
- package/src/components/MaintenancePage/Accessibilite.stories.ts +189 -0
- package/src/components/MaintenancePage/AccessibiliteItems.ts +173 -0
- package/src/components/MaintenancePage/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/NirField/Accessibilite.mdx +14 -0
- package/src/components/NirField/Accessibilite.stories.ts +214 -0
- package/src/components/NirField/AccessibiliteItems.ts +243 -0
- package/src/components/NirField/NirField.mdx +213 -0
- package/src/components/NirField/NirField.stories.ts +412 -0
- package/src/components/NirField/NirField.vue +453 -0
- package/src/components/NirField/config.ts +16 -0
- package/src/components/NirField/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/NirField/locales.ts +12 -0
- package/src/components/NirField/nirValidation.ts +42 -0
- package/src/components/NirField/tests/NirField.spec.ts +120 -0
- package/src/components/NotFoundPage/Accessibilite.mdx +14 -0
- package/src/components/NotFoundPage/Accessibilite.stories.ts +190 -0
- package/src/components/NotFoundPage/AccessibiliteItems.ts +205 -0
- package/src/components/NotFoundPage/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +4 -4
- package/src/components/NotificationBar/AccessibiliteItems.ts +0 -30
- package/src/components/NotificationBar/NotificationBar.mdx +1 -1
- package/src/components/PageContainer/PageContainer.mdx +1 -1
- package/src/components/PageContainer/PageContainer.stories.ts +9 -9
- package/src/components/PageContainer/PageContainer.vue +24 -18
- package/src/components/PageContainer/tests/PageContainer.spec.ts +2 -2
- package/src/components/PageContainer/tests/__snapshots__/PageContainer.spec.ts.snap +2 -2
- package/src/components/PhoneField/Accessibilite.mdx +14 -0
- package/src/components/PhoneField/Accessibilite.stories.ts +216 -0
- package/src/components/PhoneField/AccessibiliteItems.ts +238 -0
- package/src/components/PhoneField/PhoneField.mdx +1 -1
- package/src/components/PhoneField/PhoneField.stories.ts +2 -2
- package/src/components/PhoneField/PhoneField.vue +0 -1
- package/src/components/PhoneField/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/SkipLink/Accessibilite.stories.ts +1 -1
- package/src/components/SkipLink/SkipLink.stories.ts +2 -2
- package/src/components/SocialMediaLinks/Accessibilite.mdx +14 -0
- package/src/components/SocialMediaLinks/Accessibilite.stories.ts +170 -0
- package/src/components/SocialMediaLinks/AccessibiliteItems.ts +160 -0
- package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +1 -1
- package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +1 -1
- package/src/components/SocialMediaLinks/SocialMediaLinks.vue +7 -1
- package/src/components/SocialMediaLinks/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/SocialMediaLinks/tests/__snapshots__/SocialMediaLinks.spec.ts.snap +2 -2
- package/src/components/SubHeader/Accessibilite.mdx +14 -0
- package/src/components/SubHeader/Accessibilite.stories.ts +166 -0
- package/src/components/SubHeader/AccessibiliteItems.ts +146 -0
- package/src/components/SubHeader/SubHeader.mdx +1 -1
- package/src/components/SubHeader/SubHeader.stories.ts +17 -14
- package/src/components/SubHeader/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/SyAlert/Accessibilite.mdx +14 -0
- package/src/components/{Alert → SyAlert}/Accessibilite.stories.ts +1 -1
- package/src/components/{Alert → SyAlert}/AccessibiliteItems.ts +2 -32
- package/src/components/{Alert/Alert.mdx → SyAlert/SyAlert.mdx} +9 -9
- package/src/components/{Alert/Alert.stories.ts → SyAlert/SyAlert.stories.ts} +22 -22
- package/src/components/{Alert/Alert.vue → SyAlert/SyAlert.vue} +7 -0
- package/src/components/SyAlert/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/{Alert/tests/Alert.spec.ts → SyAlert/tests/SyAlert.spec.ts} +5 -5
- package/src/components/{Alert/tests/__snapshots__/Alert.spec.ts.snap → SyAlert/tests/__snapshots__/SyAlert.spec.ts.snap} +2 -2
- package/src/components/UserMenuBtn/Accessibilite.mdx +14 -0
- package/src/components/UserMenuBtn/Accessibilite.stories.ts +189 -0
- package/src/components/UserMenuBtn/AccessibiliteItems.ts +155 -0
- package/src/components/UserMenuBtn/UserMenuBtn.mdx +17 -17
- package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +121 -19
- package/src/components/UserMenuBtn/UserMenuBtn.vue +25 -29
- package/src/components/UserMenuBtn/config.ts +1 -1
- package/src/components/UserMenuBtn/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/index.ts +11 -4
- package/src/composables/rules/tests/useFieldValidation.spec.ts +60 -58
- package/src/composables/rules/useFieldValidation.ts +65 -28
- package/src/main.ts +1 -0
- package/src/stories/GuideDuDev/CommentUtiliserLesRules.mdx +67 -79
- package/src/stories/GuideDuDev/components.stories.ts +5 -5
- package/src/stories/GuideDuDev/moduleDeNotification.mdx +1 -1
- package/src/stories/Guidelines/Vuetify/Vuetify.mdx +11 -0
- package/src/stories/Guidelines/Vuetify/Vuetify.stories.ts +138 -0
- package/src/stories/Guidelines/Vuetify/VuetifyItems.ts +350 -0
- /package/src/components/{Alert → CookieBanner}/Accessibilite.mdx +0 -0
- /package/src/components/{Alert → CookieBanner}/constants/ExpertiseLevelEnum.ts +0 -0
- /package/src/components/{Alert → SyAlert}/locales.ts +0 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref, watch, computed, nextTick } from 'vue'
|
|
3
|
+
import { useFieldValidation } from '@/composables/rules/useFieldValidation'
|
|
4
|
+
import { vMaska } from 'maska/vue'
|
|
5
|
+
import { checkNIR, isNIRKeyValid } from './nirValidation'
|
|
6
|
+
import useCustomizableOptions, { type CustomizableOptions } from '@/composables/useCustomizableOptions'
|
|
7
|
+
import SyTextField from '../Customs/SyTextField/SyTextField.vue'
|
|
8
|
+
import { mdiInformationOutline } from '@mdi/js'
|
|
9
|
+
import { locales } from './locales'
|
|
10
|
+
import defaultOptions from './config'
|
|
11
|
+
|
|
12
|
+
type Rule = (value: string) => { error?: string, success?: string }
|
|
13
|
+
|
|
14
|
+
const props = withDefaults(defineProps<CustomizableOptions & {
|
|
15
|
+
modelValue?: string | undefined
|
|
16
|
+
outlined?: boolean
|
|
17
|
+
required?: boolean
|
|
18
|
+
nirTooltip?: string
|
|
19
|
+
keyTooltip?: string
|
|
20
|
+
numberLabel?: string
|
|
21
|
+
keyLabel?: string
|
|
22
|
+
displayKey?: boolean
|
|
23
|
+
showSuccessMessages?: boolean
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
25
|
+
customNumberRules?: any
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
27
|
+
customKeyRules?: any
|
|
28
|
+
}>(), {
|
|
29
|
+
modelValue: undefined,
|
|
30
|
+
outlined: true,
|
|
31
|
+
required: false,
|
|
32
|
+
nirTooltip: undefined,
|
|
33
|
+
keyTooltip: undefined,
|
|
34
|
+
numberLabel: 'Numéro de sécurité sociale',
|
|
35
|
+
keyLabel: 'Clé',
|
|
36
|
+
displayKey: true,
|
|
37
|
+
showSuccessMessages: false,
|
|
38
|
+
customNumberRules: [],
|
|
39
|
+
customKeyRules: [],
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const emit = defineEmits(['update:modelValue'])
|
|
43
|
+
const options = useCustomizableOptions(defaultOptions, props)
|
|
44
|
+
const infoIcon = mdiInformationOutline
|
|
45
|
+
|
|
46
|
+
// Champs
|
|
47
|
+
const numberValue = ref('')
|
|
48
|
+
const keyValue = ref('')
|
|
49
|
+
const keyDeleted = ref(false)
|
|
50
|
+
|
|
51
|
+
// Refs pour les champs
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
53
|
+
const keyField = ref<any | null>(null)
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
55
|
+
const numberField = ref<any | null>(null)
|
|
56
|
+
|
|
57
|
+
const unmaskedNumberValue = computed(() => numberValue.value.replace(/\s/g, ''))
|
|
58
|
+
|
|
59
|
+
watch(() => props.modelValue, async (value) => {
|
|
60
|
+
numberValue.value = value?.slice(0, 13) ?? ''
|
|
61
|
+
keyValue.value = value?.slice(13, 15) ?? ''
|
|
62
|
+
}, { immediate: true })
|
|
63
|
+
|
|
64
|
+
// Etats d’erreur/succès
|
|
65
|
+
const errors = ref<string[]>([])
|
|
66
|
+
const successes = ref<string[]>([])
|
|
67
|
+
|
|
68
|
+
// Flags de validation
|
|
69
|
+
const isValidating = ref(false)
|
|
70
|
+
|
|
71
|
+
// Masques
|
|
72
|
+
const numberMask = {
|
|
73
|
+
mask: '# ## ## #C ### ###',
|
|
74
|
+
preProcess: (value: string) => value.toUpperCase(),
|
|
75
|
+
tokens: {
|
|
76
|
+
C: {
|
|
77
|
+
pattern: /[0-9AB]/,
|
|
78
|
+
transform: (char: string) => char.toUpperCase(),
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
const keyMask = { mask: '##' }
|
|
83
|
+
|
|
84
|
+
// Règles de validation par défaut
|
|
85
|
+
const { generateRules } = useFieldValidation()
|
|
86
|
+
|
|
87
|
+
const defaultNumberRules = [
|
|
88
|
+
{
|
|
89
|
+
type: 'exactLength',
|
|
90
|
+
options: { length: 13, message: locales.errorLengthNumber(13), ignoreSpace: true, fieldIdentifier: 'numéro' },
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: 'custom',
|
|
94
|
+
options: {
|
|
95
|
+
validate: checkNIR,
|
|
96
|
+
message: 'Le numéro de sécurité sociale est invalide.',
|
|
97
|
+
successMessage: 'Le numéro de sécurité sociale est valide.',
|
|
98
|
+
fieldIdentifier: 'numéro',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
...(props.required
|
|
102
|
+
? [{
|
|
103
|
+
type: 'required',
|
|
104
|
+
options: { message: 'Le numéro de sécurité sociale est requis.', fieldIdentifier: 'numéro' },
|
|
105
|
+
}]
|
|
106
|
+
: []),
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
const defaultKeyRules = [
|
|
110
|
+
{
|
|
111
|
+
type: 'exactLength',
|
|
112
|
+
options: { length: 2, message: locales.errorLengthKey(2), ignoreSpace: true, fieldIdentifier: 'clé' },
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: 'custom',
|
|
116
|
+
options: {
|
|
117
|
+
validate: () => isNIRKeyValid(`${numberValue.value}${keyValue.value}`),
|
|
118
|
+
message: 'La clé du numéro de sécurité sociale est invalide.',
|
|
119
|
+
successMessage: 'Le champ clé est valide.',
|
|
120
|
+
fieldIdentifier: 'clé',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
...(props.required
|
|
124
|
+
? [{
|
|
125
|
+
type: 'required',
|
|
126
|
+
options: { message: 'La clé est requise.', fieldIdentifier: 'clé' },
|
|
127
|
+
}]
|
|
128
|
+
: []),
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
// Computed pour statut des champs
|
|
132
|
+
const fieldIdentifierNumber = defaultNumberRules[0]?.options?.fieldIdentifier
|
|
133
|
+
const fieldIdentifierKey = defaultKeyRules[0]?.options?.fieldIdentifier
|
|
134
|
+
|
|
135
|
+
const hasNumberErrors = computed(() => errors.value.some(error => error.includes(fieldIdentifierNumber)))
|
|
136
|
+
const hasKeyErrors = computed(() => errors.value.some(error => error.includes(fieldIdentifierKey)))
|
|
137
|
+
const hasNumberSuccess = computed(() => successes.value.some(success => success.includes(fieldIdentifierNumber)))
|
|
138
|
+
const hasKeySuccess = computed(() => successes.value.some(success => success.includes(fieldIdentifierKey)))
|
|
139
|
+
|
|
140
|
+
// Génération des règles finales
|
|
141
|
+
const numberRules = props.customNumberRules?.length
|
|
142
|
+
? generateRules(props.customNumberRules)
|
|
143
|
+
: generateRules(defaultNumberRules)
|
|
144
|
+
|
|
145
|
+
const keyRules = props.displayKey
|
|
146
|
+
? (props.customKeyRules?.length
|
|
147
|
+
? generateRules(props.customKeyRules)
|
|
148
|
+
: generateRules(defaultKeyRules))
|
|
149
|
+
: []
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Valide une liste de règles sur une valeur et met à jour les tableaux d'erreurs et de succès.
|
|
153
|
+
* @param value Valeur du champ à valider
|
|
154
|
+
* @param rules Ensemble de règles
|
|
155
|
+
*/
|
|
156
|
+
function validateFieldSet(value: string, rules: Rule[]) {
|
|
157
|
+
rules.forEach((rule) => {
|
|
158
|
+
const { error, success } = rule(value)
|
|
159
|
+
if (error) errors.value.push(error)
|
|
160
|
+
if (success && success !== 'Le champ est valide.') successes.value.push(success)
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Valide les champs numéro et clé (si activée).
|
|
166
|
+
* @param onBlur Si true, la validation est lancée suite à un blur, sinon validation continue
|
|
167
|
+
*/
|
|
168
|
+
function validateFields(onBlur = false) {
|
|
169
|
+
errors.value = []
|
|
170
|
+
successes.value = []
|
|
171
|
+
|
|
172
|
+
const shouldValidateNumber = onBlur || isValidating.value || numberValue.value.length === 18
|
|
173
|
+
const shouldValidateKey = props.displayKey && (onBlur || isValidating.value || keyValue.value.length === 2)
|
|
174
|
+
|
|
175
|
+
if (shouldValidateNumber) {
|
|
176
|
+
validateFieldSet(numberValue.value, numberRules)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (shouldValidateKey) {
|
|
180
|
+
validateFieldSet(keyValue.value, keyRules)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Unicité des succès
|
|
184
|
+
successes.value = Array.from(new Set(successes.value))
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Compteurs
|
|
188
|
+
const numberCounter = computed(() => {
|
|
189
|
+
const length = numberValue.value.replace(/\s/g, '').length
|
|
190
|
+
return `${Math.min(length, 13)}/13`
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
const keyCounter = computed(() => {
|
|
194
|
+
const length = keyValue.value.replace(/\s/g, '').length
|
|
195
|
+
return `${Math.min(length, 2)}/2`
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
watch([unmaskedNumberValue, keyValue], () => {
|
|
199
|
+
validateFields()
|
|
200
|
+
if (unmaskedNumberValue.value + keyValue.value !== props.modelValue) {
|
|
201
|
+
emit('update:modelValue', `${unmaskedNumberValue.value}${keyValue.value}`)
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
watch(keyValue, (newValue, oldValue) => {
|
|
206
|
+
keyDeleted.value = !!(!newValue && oldValue)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
watch(numberValue, () => {
|
|
210
|
+
if (unmaskedNumberValue.value.length < 13) {
|
|
211
|
+
keyDeleted.value = false
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
// Déplacement du focus sur la clé quand le numéro est rempli
|
|
216
|
+
const focusElement = computed(() => {
|
|
217
|
+
if (props.displayKey && numberValue.value.length === 18) {
|
|
218
|
+
if (!keyDeleted.value) {
|
|
219
|
+
return keyField.value?.$el?.querySelector('input')
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
return numberField.value?.$el?.querySelector('input')
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return null
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
watch(focusElement, (newEl) => {
|
|
229
|
+
nextTick(() => {
|
|
230
|
+
newEl?.focus()
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
function validateOnSubmit() {
|
|
235
|
+
isValidating.value = true
|
|
236
|
+
validateFields()
|
|
237
|
+
return errors.value.length === 0
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
defineExpose({
|
|
241
|
+
validateOnSubmit,
|
|
242
|
+
})
|
|
243
|
+
</script>
|
|
244
|
+
|
|
245
|
+
<template>
|
|
246
|
+
<div class="d-flex align-start">
|
|
247
|
+
<v-input
|
|
248
|
+
ref="vInput"
|
|
249
|
+
:class="{
|
|
250
|
+
'v-messages__message--success': successes.length > 0 && props.showSuccessMessages,
|
|
251
|
+
'v-messages__message--error': errors.length > 0
|
|
252
|
+
}"
|
|
253
|
+
:error-messages="errors"
|
|
254
|
+
:label="numberLabel"
|
|
255
|
+
:max-errors="3"
|
|
256
|
+
:messages="props.showSuccessMessages ? successes : []"
|
|
257
|
+
:model-value="[numberValue, keyValue]"
|
|
258
|
+
class="vd-nir-field__fields-wrapper multi-line"
|
|
259
|
+
validate-on="blur lazy"
|
|
260
|
+
>
|
|
261
|
+
<VTooltip v-if="nirTooltip">
|
|
262
|
+
<template #activator="{ props: iconProps }">
|
|
263
|
+
<VIcon
|
|
264
|
+
class="vd-tooltip-icon mt-4 mr-4"
|
|
265
|
+
v-bind="{ ...iconProps, ...options.tooltip }"
|
|
266
|
+
>
|
|
267
|
+
{{ infoIcon }}
|
|
268
|
+
</VIcon>
|
|
269
|
+
</template>
|
|
270
|
+
<slot name="nirTooltip">
|
|
271
|
+
{{ nirTooltip }}
|
|
272
|
+
</slot>
|
|
273
|
+
</VTooltip>
|
|
274
|
+
<SyTextField
|
|
275
|
+
ref="numberField"
|
|
276
|
+
v-model="numberValue"
|
|
277
|
+
v-maska="numberMask"
|
|
278
|
+
:append-inner-icon="hasNumberErrors ? 'error' : (hasNumberSuccess ? 'success' : undefined)"
|
|
279
|
+
:aria-errormessage="hasNumberErrors ? 'number-field-errors' : undefined"
|
|
280
|
+
:aria-invalid="hasNumberErrors"
|
|
281
|
+
:aria-required="required"
|
|
282
|
+
:color="hasNumberErrors ? 'error' : 'primary'"
|
|
283
|
+
:error="hasNumberErrors"
|
|
284
|
+
:hint="locales.numberHint"
|
|
285
|
+
:label="numberLabel"
|
|
286
|
+
:variant="outlined ? 'outlined' : 'underlined'"
|
|
287
|
+
class="vd-number-field"
|
|
288
|
+
title="nirField"
|
|
289
|
+
@blur="validateFields(true)"
|
|
290
|
+
>
|
|
291
|
+
<template #details>
|
|
292
|
+
<span class="custom-counter">
|
|
293
|
+
{{ numberCounter }}
|
|
294
|
+
</span>
|
|
295
|
+
</template>
|
|
296
|
+
</SyTextField>
|
|
297
|
+
|
|
298
|
+
<template v-if="displayKey">
|
|
299
|
+
<SyTextField
|
|
300
|
+
ref="keyField"
|
|
301
|
+
v-model="keyValue"
|
|
302
|
+
v-maska="keyMask"
|
|
303
|
+
:append-inner-icon="hasKeyErrors ? 'error' : (hasKeySuccess ? 'success' : undefined)"
|
|
304
|
+
:aria-errormessage="hasKeyErrors ? 'key-field-errors' : undefined"
|
|
305
|
+
:aria-invalid="hasKeyErrors"
|
|
306
|
+
:aria-required="required"
|
|
307
|
+
:color="hasKeyErrors ? 'error' : 'primary'"
|
|
308
|
+
:error="hasKeyErrors"
|
|
309
|
+
:hint="locales.keyHint"
|
|
310
|
+
:label="keyLabel"
|
|
311
|
+
:variant="outlined ? 'outlined' : 'underlined'"
|
|
312
|
+
class="vd-key-field"
|
|
313
|
+
title="nirKeyField"
|
|
314
|
+
@blur="validateFields(true)"
|
|
315
|
+
>
|
|
316
|
+
<template #details>
|
|
317
|
+
<span class="custom-counter">
|
|
318
|
+
{{ keyCounter }}
|
|
319
|
+
</span>
|
|
320
|
+
</template>
|
|
321
|
+
</SyTextField>
|
|
322
|
+
|
|
323
|
+
<VTooltip v-if="keyTooltip">
|
|
324
|
+
<template #activator="{ props: iconProps }">
|
|
325
|
+
<VIcon
|
|
326
|
+
class="vd-tooltip-icon mt-4 ml-4"
|
|
327
|
+
v-bind="{ ...iconProps, ...options.icon }"
|
|
328
|
+
>
|
|
329
|
+
{{ infoIcon }}
|
|
330
|
+
</VIcon>
|
|
331
|
+
</template>
|
|
332
|
+
<slot name="keyTooltip">
|
|
333
|
+
{{ keyTooltip }}
|
|
334
|
+
</slot>
|
|
335
|
+
</VTooltip>
|
|
336
|
+
</template>
|
|
337
|
+
</v-input>
|
|
338
|
+
</div>
|
|
339
|
+
</template>
|
|
340
|
+
|
|
341
|
+
<style lang="scss" scoped>
|
|
342
|
+
@use '@/assets/tokens.scss';
|
|
343
|
+
|
|
344
|
+
.v-messages__message--success {
|
|
345
|
+
color: tokens.$colors-border-success !important;
|
|
346
|
+
|
|
347
|
+
.v-field--active & {
|
|
348
|
+
color: tokens.$colors-border-success !important;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.v-messages__message--error {
|
|
353
|
+
color: tokens.$colors-border-error;
|
|
354
|
+
|
|
355
|
+
.v-field--active & {
|
|
356
|
+
color: tokens.$colors-border-error;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
:deep(.v-field.v-field--active .v-label.v-field-label--floating) {
|
|
361
|
+
opacity: 1;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.multi-line {
|
|
365
|
+
white-space: pre-line !important;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.vd-number-field {
|
|
369
|
+
max-width: 296px;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.vd-key-field {
|
|
373
|
+
width: 104px;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.custom-counter {
|
|
377
|
+
color: rgba(0, 0, 0, 0.54);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.vd-nir-field :deep(.v-input__append-inner),
|
|
381
|
+
.vd-tooltip-icon {
|
|
382
|
+
flex: none;
|
|
383
|
+
color: rgba(0, 0, 0, 0.54);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
:deep(.v-overlay__content) {
|
|
387
|
+
background: rgba(84, 88, 89, 0.95) !important;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.vd-key-field {
|
|
391
|
+
flex: none;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.vd-nir-field--outlined :deep(.v-messages.error--text) {
|
|
395
|
+
padding: 6px;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.vd-nir-field {
|
|
399
|
+
container-name: nirFieldwrapper;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
:deep(.v-input__append) {
|
|
403
|
+
margin-inline-start: 0 !important;
|
|
404
|
+
}
|
|
405
|
+
:deep(.vd-number-field > .v-input__prepend) {
|
|
406
|
+
margin-right: 0 !important;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
:deep(.vd-key-field > .v-input__prepend) {
|
|
410
|
+
@media screen and (max-width: 360px) {
|
|
411
|
+
margin-inline-end: 0 !important;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
:deep(.v-text-field .v-input__details) {
|
|
416
|
+
padding-inline-start: 0 !important;
|
|
417
|
+
padding-inline-end: 0 !important;
|
|
418
|
+
flex: none !important;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
:deep(.v-text-field .v-input__details .v-messages) {
|
|
422
|
+
color: rgba(0, 0, 0, 1) !important;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
@mixin responsive-nir-wrapper {
|
|
426
|
+
.vd-nir-field__fields-wrapper :deep(> .v-input__control) {
|
|
427
|
+
justify-content: start;
|
|
428
|
+
flex-wrap: wrap;
|
|
429
|
+
gap: 4px;
|
|
430
|
+
margin-bottom: 4px;
|
|
431
|
+
|
|
432
|
+
.vd-number-field {
|
|
433
|
+
flex: 100% 0 0;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
@container nirFieldwrapper (max-width: 300px) {
|
|
439
|
+
@include responsive-nir-wrapper;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
@media screen and (max-width: 360px) {
|
|
443
|
+
@include responsive-nir-wrapper;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.v-text-field .v-input__append-inner {
|
|
447
|
+
padding-left: 0 !important;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
:deep(.v-text-field > .v-input__control > .v-input__slot > .v-text-field__slot) {
|
|
451
|
+
width: min-content !important;
|
|
452
|
+
}
|
|
453
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const locales = {
|
|
2
|
+
errorRequiredNumber: 'Le numéro de sécurité sociale est requis.',
|
|
3
|
+
errorLengthNumber: (length: number) => `Le numéro de sécurité sociale doit contenir ${length} caractères.`,
|
|
4
|
+
errorInvalidFormat: 'Le format du numéro de sécurité sociale est invalide.',
|
|
5
|
+
errorRequiredKey: 'La clé du numéro de sécurité sociale est requise.',
|
|
6
|
+
errorLengthKey: (length: number) => `La clé du numéro de sécurité sociale doit contenir ${length} caractères.`,
|
|
7
|
+
errorInvalidKey: 'La clé du numéro de sécurité sociale est invalide.',
|
|
8
|
+
numberLabel: 'Numéro de sécurité sociale',
|
|
9
|
+
numberHint: '13 caractères',
|
|
10
|
+
keyLabel: 'Clé',
|
|
11
|
+
keyHint: '2 chiffres',
|
|
12
|
+
} as const
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const NUMBER_LENGTH = 13
|
|
2
|
+
export const KEY_LENGTH = 2
|
|
3
|
+
|
|
4
|
+
export function checkNIR(nir: string): boolean {
|
|
5
|
+
nir = nir.replace(/\s+/g, '').toUpperCase()
|
|
6
|
+
|
|
7
|
+
const nirRegex = new RegExp(
|
|
8
|
+
'^'
|
|
9
|
+
+ '(?<sexe>[1-4]|7|8)'
|
|
10
|
+
+ '(?<anneeNaissance>\\d{2})'
|
|
11
|
+
+ '(?<moisNaissance>0[1-9]|1[0-2]|2[0-9]|3[0-9]|4[0-2])'
|
|
12
|
+
+ '(?<departementNaissance>\\d{2}|2A|2B|96|97\\d|98\\d)'
|
|
13
|
+
+ '(?<communeNaissance>\\d{3})'
|
|
14
|
+
+ '(?<rangInscription>\\d{3})'
|
|
15
|
+
+ '(?<cle>[0-9]{2})?'
|
|
16
|
+
+ '$',
|
|
17
|
+
'i',
|
|
18
|
+
)
|
|
19
|
+
return nirRegex.test(nir)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function computeNIRKey(nir: string): string {
|
|
23
|
+
nir = nir.replace(/\s+/g, '').toUpperCase()
|
|
24
|
+
|
|
25
|
+
let nirNumberPart = nir.substring(0, 13)
|
|
26
|
+
|
|
27
|
+
nirNumberPart = nirNumberPart.replace('2A', '19').replace('2B', '18')
|
|
28
|
+
|
|
29
|
+
const nirNumber = BigInt(nirNumberPart)
|
|
30
|
+
|
|
31
|
+
const key = 97n - (nirNumber % 97n)
|
|
32
|
+
|
|
33
|
+
return key.toString().padStart(2, '0')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isNIRKeyValid(nir: string): boolean {
|
|
37
|
+
nir = nir.replace(/\s+/g, '').toUpperCase()
|
|
38
|
+
|
|
39
|
+
const providedKey = nir.substring(13, 15)
|
|
40
|
+
const computedKey = computeNIRKey(nir)
|
|
41
|
+
return providedKey === computedKey
|
|
42
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils'
|
|
2
|
+
import NirField from '../NirField.vue'
|
|
3
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
4
|
+
import { createVuetify } from 'vuetify'
|
|
5
|
+
|
|
6
|
+
const vuetify = createVuetify()
|
|
7
|
+
|
|
8
|
+
describe('NirField.vue', () => {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
10
|
+
let wrapper: any
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
wrapper = mount(NirField, {
|
|
14
|
+
global: {
|
|
15
|
+
plugins: [vuetify],
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
modelValue: '',
|
|
19
|
+
required: true,
|
|
20
|
+
showSuccessMessages: true,
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('renders correctly', () => {
|
|
26
|
+
expect(wrapper.exists()).toBe(true)
|
|
27
|
+
expect(wrapper.find('.vd-number-field').exists()).toBe(true)
|
|
28
|
+
expect(wrapper.find('.vd-key-field').exists()).toBe(true)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('displays error message for invalid NIR length', async () => {
|
|
32
|
+
const numberField = wrapper.find('.vd-number-field input')
|
|
33
|
+
await numberField.setValue('123') // Invalid length
|
|
34
|
+
await numberField.trigger('blur')
|
|
35
|
+
expect(wrapper.find('.v-messages__message').text()).toContain('Le numéro de sécurité sociale doit contenir 13 caractères.')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('validates the NIR field successfully', async () => {
|
|
39
|
+
const numberField = wrapper.find('.vd-number-field input')
|
|
40
|
+
await numberField.setValue('2940375120005') // Valid NIR length
|
|
41
|
+
expect(wrapper.find('.v-messages__message--success').exists()).toBe(true)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('displays error message for invalid key length', async () => {
|
|
45
|
+
const numberField = wrapper.find('.vd-number-field input')
|
|
46
|
+
await numberField.setValue('2940375120005') // Valid NIR length
|
|
47
|
+
const keyField = wrapper.find('.vd-key-field input')
|
|
48
|
+
await keyField.setValue('1') // Invalid length
|
|
49
|
+
await keyField.trigger('blur')
|
|
50
|
+
expect(wrapper.find('.v-messages__message').text()).toContain('La clé du numéro de sécurité sociale doit contenir 2 caractères.')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('validates the key field successfully', async () => {
|
|
54
|
+
const numberField = wrapper.find('.vd-number-field input')
|
|
55
|
+
const keyField = wrapper.find('.vd-key-field input')
|
|
56
|
+
await numberField.setValue('2940375120005')
|
|
57
|
+
await keyField.setValue('91')
|
|
58
|
+
expect(wrapper.find('.v-messages__message--success').exists()).toBe(true)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('hides the key field when displayKey is false', async () => {
|
|
62
|
+
await wrapper.setProps({ displayKey: false })
|
|
63
|
+
expect(wrapper.find('.vd-key-field').exists()).toBe(false)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('calls validateOnSubmit and returns true if no errors', async () => {
|
|
67
|
+
const numberField = wrapper.find('.vd-number-field input')
|
|
68
|
+
const keyField = wrapper.find('.vd-key-field input')
|
|
69
|
+
|
|
70
|
+
await numberField.setValue('2940375120005')
|
|
71
|
+
await keyField.setValue('91')
|
|
72
|
+
|
|
73
|
+
await wrapper.vm.$nextTick()
|
|
74
|
+
|
|
75
|
+
wrapper.vm.validateFields()
|
|
76
|
+
|
|
77
|
+
const isValid = wrapper.vm.validateOnSubmit()
|
|
78
|
+
|
|
79
|
+
expect(isValid).toBe(true)
|
|
80
|
+
expect(wrapper.vm.errors.length).toBe(0)
|
|
81
|
+
})
|
|
82
|
+
it('applies custom key rules when provided', async () => {
|
|
83
|
+
const customKeyRules = [
|
|
84
|
+
{
|
|
85
|
+
type: 'custom',
|
|
86
|
+
options: {
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
|
|
88
|
+
validate: (value: any) => value === '91',
|
|
89
|
+
message: 'Custom key validation failed.',
|
|
90
|
+
successMessage: 'Custom key validation passed.',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
wrapper = mount(NirField, {
|
|
96
|
+
global: {
|
|
97
|
+
plugins: [vuetify],
|
|
98
|
+
},
|
|
99
|
+
props: {
|
|
100
|
+
modelValue: '',
|
|
101
|
+
required: true,
|
|
102
|
+
customKeyRules,
|
|
103
|
+
},
|
|
104
|
+
})
|
|
105
|
+
const numberField = wrapper.find('.vd-number-field input')
|
|
106
|
+
const keyField = wrapper.find('.vd-key-field input')
|
|
107
|
+
await numberField.setValue('2940375120005')
|
|
108
|
+
await keyField.setValue('91')
|
|
109
|
+
|
|
110
|
+
await wrapper.vm.$nextTick()
|
|
111
|
+
|
|
112
|
+
expect(wrapper.vm.errors.length).toBe(0)
|
|
113
|
+
expect(wrapper.vm.successes).toContain('Custom key validation passed.')
|
|
114
|
+
|
|
115
|
+
await keyField.setValue('11')
|
|
116
|
+
await wrapper.vm.$nextTick()
|
|
117
|
+
|
|
118
|
+
expect(wrapper.vm.errors).toContain('Custom key validation failed.')
|
|
119
|
+
})
|
|
120
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Meta, Story } from '@storybook/addon-docs';
|
|
2
|
+
import * as AccessStories from './Accessibilite.stories.ts';
|
|
3
|
+
|
|
4
|
+
<Meta of={AccessStories} />
|
|
5
|
+
|
|
6
|
+
Accessibilité
|
|
7
|
+
=============
|
|
8
|
+
<Story of={AccessStories.Legende} />
|
|
9
|
+
<br />
|
|
10
|
+
|
|
11
|
+
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
<Story of={AccessStories.AccessibilitePanel} />
|
|
14
|
+
<br />
|