@cnamts/synapse 0.0.14-alpha → 0.0.16-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/components/CookiesSelection/CookiesSelection.d.ts +26 -26
- package/dist/components/Customs/SyInputSelect/SyInputSelect.d.ts +2 -2
- package/dist/components/Customs/SySelect/SySelect.d.ts +24 -12
- package/dist/components/Customs/SySelect/locales.d.ts +3 -0
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +1393 -3
- package/dist/components/DatePicker/DatePicker.d.ts +3532 -22
- package/dist/components/DatePicker/DateTextInput.d.ts +1408 -11
- package/dist/components/DialogBox/config.d.ts +1 -1
- package/dist/components/DownloadBtn/DownloadBtn.d.ts +2 -0
- package/dist/components/LangBtn/LangBtn.d.ts +467 -1
- package/dist/components/LangBtn/config.d.ts +1 -3
- package/dist/components/NirField/NirField.d.ts +2805 -15
- package/dist/components/PasswordField/PasswordField.d.ts +2 -2
- package/dist/components/PeriodField/PeriodField.d.ts +7345 -325
- package/dist/components/PhoneField/PhoneField.d.ts +3 -3
- package/dist/components/SelectBtnField/SelectBtnField.d.ts +1 -1
- package/dist/components/SkipLink/SkipLink.d.ts +3 -2
- package/dist/components/SyAlert/SyAlert.d.ts +72 -1
- package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +26 -26
- package/dist/components/UserMenuBtn/UserMenuBtn.d.ts +2 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/composables/date/useDateFormat.d.ts +2 -2
- package/dist/composables/date/useDateFormatDayjs.d.ts +23 -0
- package/dist/composables/date/useDateInitializationDayjs.d.ts +18 -0
- package/dist/design-system-v3.js +4314 -3987
- package/dist/design-system-v3.umd.cjs +1 -1
- package/dist/style.css +1 -1
- package/dist/vuetifyConfig.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/BackBtn/Accessibilite.stories.ts +4 -0
- package/src/components/BackBtn/BackBtn.vue +2 -1
- package/src/components/BackToTopBtn/Accessibilite.stories.ts +4 -0
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +78 -21
- package/src/components/BackToTopBtn/BackToTopBtn.vue +15 -0
- package/src/components/BackToTopBtn/config.ts +2 -2
- package/src/components/BackToTopBtn/tests/__snapshots__/BackToTopBtn.spec.ts.snap +4 -4
- package/src/components/CopyBtn/Accessibilite.stories.ts +4 -0
- package/src/components/Customs/SyBtnSelect/SyBtnSelect.stories.ts +2 -2
- package/src/components/Customs/SyBtnSelect/SyBtnSelect.vue +0 -1
- package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +3 -3
- package/src/components/Customs/SyInputSelect/SyInputSelect.vue +4 -4
- package/src/components/Customs/SySelect/SySelect.stories.ts +4 -0
- package/src/components/Customs/SySelect/SySelect.vue +75 -10
- package/src/components/Customs/SySelect/locales.ts +3 -0
- package/src/components/Customs/SySelect/tests/SySelect.spec.ts +24 -2
- package/src/components/Customs/SyTextField/Accessibilite.stories.ts +7 -0
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +14 -1
- package/src/components/Customs/SyTextField/SyTextField.vue +85 -20
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +795 -0
- package/src/components/DatePicker/DatePicker.stories.ts +432 -1
- package/src/components/DatePicker/DatePicker.vue +143 -76
- package/src/components/DatePicker/DatePickerValidation.mdx +338 -0
- package/src/components/DatePicker/DatePickerValidation.stories.ts +30 -0
- package/src/components/DatePicker/DateTextInput.vue +87 -135
- package/src/components/DatePicker/docExamples/DatePickerBidirectionalValidation.vue +282 -0
- package/src/components/DatePicker/docExamples/DatePickerValidationExamples.vue +535 -0
- package/src/components/DatePicker/tests/DatePicker.spec.ts +33 -32
- package/src/components/DatePicker/tests/DateTextInput.spec.ts +83 -35
- package/src/components/DialogBox/DialogBox.stories.ts +5 -2
- package/src/components/DialogBox/DialogBox.vue +1 -1
- package/src/components/DialogBox/config.ts +1 -1
- package/src/components/DownloadBtn/Accessibilite.stories.ts +4 -0
- package/src/components/DownloadBtn/DownloadBtn.stories.ts +17 -8
- package/src/components/DownloadBtn/DownloadBtn.vue +13 -6
- package/src/components/DownloadBtn/tests/__snapshots__/DownloadBtn.spec.ts.snap +0 -2
- package/src/components/FranceConnectBtn/Accessibilite.stories.ts +4 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +3 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +3 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/menu.scss +19 -0
- package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +12 -2
- package/src/components/LangBtn/Accessibilite.stories.ts +4 -0
- package/src/components/LangBtn/LangBtn.stories.ts +1 -4
- package/src/components/LangBtn/LangBtn.vue +68 -9
- package/src/components/LangBtn/config.ts +0 -1
- package/src/components/LangBtn/tests/LangBtn.spec.ts +30 -2
- package/src/components/PageContainer/Accessibilite.stories.ts +36 -23
- package/src/components/PaginatedTable/PaginatedTable.stories.ts +144 -18
- package/src/components/PasswordField/PasswordField.stories.ts +6 -6
- package/src/components/PasswordField/PasswordField.vue +3 -3
- package/src/components/PeriodField/PeriodField.vue +4 -4
- package/src/components/PhoneField/PhoneField.stories.ts +216 -24
- package/src/components/PhoneField/PhoneField.vue +32 -2
- package/src/components/PhoneField/tests/PhoneField.spec.ts +161 -14
- package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +2 -1
- package/src/components/RatingPicker/RatingPicker.stories.ts +1 -1
- package/src/components/SkipLink/Accessibilite.stories.ts +8 -0
- package/src/components/SkipLink/SkipLink.vue +11 -9
- package/src/components/SkipLink/tests/__snapshots__/skipLink.spec.ts.snap +7 -4
- package/src/components/SkipLink/tests/skipLink.spec.ts +120 -6
- package/src/components/SyAlert/Accessibilite.stories.ts +4 -0
- package/src/components/SyAlert/SyAlert.mdx +3 -7
- package/src/components/SyAlert/SyAlert.stories.ts +19 -12
- package/src/components/SyAlert/SyAlert.vue +88 -51
- package/src/components/SyAlert/tests/SyAlert.spec.ts +20 -2
- package/src/components/SyAlert/tests/__snapshots__/SyAlert.spec.ts.snap +83 -75
- package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +56 -0
- package/src/components/UserMenuBtn/UserMenuBtn.vue +4 -2
- package/src/components/UserMenuBtn/tests/UserMenuBtn.spec.ts +41 -0
- package/src/components/index.ts +2 -0
- package/src/composables/date/useDateFormat.ts +17 -1
- package/src/composables/date/useDateFormatDayjs.ts +84 -0
- package/src/composables/date/useDateInitializationDayjs.ts +133 -0
- package/src/composables/rules/useFieldValidation.ts +26 -3
- package/src/stories/Accessibilite/Avancement/Avancement.mdx +12 -0
- package/src/stories/Accessibilite/Avancement/Avancement.stories.ts +134 -0
- package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +1 -1
- package/src/stories/GuideDuDev/LesBreackingChanges.mdx +31 -2
- package/src/components/LangBtn/tests/Config.spec.ts +0 -24
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
|
|
2
|
+
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, type ComponentPublicInstance } from 'vue'
|
|
3
3
|
import SyTextField from '@/components/Customs/SyTextField/SyTextField.vue'
|
|
4
4
|
import DateTextInput from './DateTextInput.vue'
|
|
5
5
|
import { VDatePicker } from 'vuetify/components'
|
|
6
6
|
import { useValidation } from '@/composables/validation/useValidation'
|
|
7
|
-
import { useDateFormat } from '@/composables/date/
|
|
8
|
-
import { useDateInitialization, type DateValue, type DateInput } from '@/composables/date/
|
|
7
|
+
import { useDateFormat } from '@/composables/date/useDateFormatDayjs'
|
|
8
|
+
import { useDateInitialization, type DateValue, type DateInput } from '@/composables/date/useDateInitializationDayjs'
|
|
9
9
|
import { useDatePickerAccessibility } from '@/composables/date/useDatePickerAccessibility'
|
|
10
|
+
import dayjs from 'dayjs'
|
|
11
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat'
|
|
12
|
+
|
|
13
|
+
// Initialiser les plugins dayjs
|
|
14
|
+
dayjs.extend(customParseFormat)
|
|
10
15
|
|
|
11
16
|
const { parseDate, formatDate } = useDateFormat()
|
|
12
17
|
const { initializeSelectedDates } = useDateInitialization()
|
|
@@ -32,7 +37,7 @@
|
|
|
32
37
|
noIcon?: boolean
|
|
33
38
|
noCalendar?: boolean
|
|
34
39
|
isOutlined?: boolean
|
|
35
|
-
|
|
40
|
+
readonly?: boolean
|
|
36
41
|
width?: string
|
|
37
42
|
disableErrorHandling?: boolean
|
|
38
43
|
showSuccessMessages?: boolean
|
|
@@ -55,7 +60,7 @@
|
|
|
55
60
|
noIcon: false,
|
|
56
61
|
noCalendar: false,
|
|
57
62
|
isOutlined: true,
|
|
58
|
-
|
|
63
|
+
readonly: false,
|
|
59
64
|
width: '100%',
|
|
60
65
|
disableErrorHandling: false,
|
|
61
66
|
showSuccessMessages: true,
|
|
@@ -93,7 +98,7 @@
|
|
|
93
98
|
// Variable pour éviter les mises à jour récursives
|
|
94
99
|
const isUpdatingFromInternal = ref(false)
|
|
95
100
|
|
|
96
|
-
//
|
|
101
|
+
// Fonction pour valider les dates
|
|
97
102
|
const validateDates = (forceValidation = false) => {
|
|
98
103
|
if (props.noCalendar) {
|
|
99
104
|
// En mode no-calendar, on délègue la validation au DateTextInput
|
|
@@ -320,6 +325,13 @@
|
|
|
320
325
|
}
|
|
321
326
|
})
|
|
322
327
|
|
|
328
|
+
// Fonction pour mettre à jour displayFormattedDate quand le VDatePicker change
|
|
329
|
+
const updateDisplayFormattedDate = () => {
|
|
330
|
+
if (displayFormattedDateComputed.value) {
|
|
331
|
+
displayFormattedDate.value = displayFormattedDateComputed.value
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
323
335
|
const updateSelectedDates = (input: DateValue) => {
|
|
324
336
|
if (Array.isArray(input)) {
|
|
325
337
|
const dates = input
|
|
@@ -354,11 +366,7 @@
|
|
|
354
366
|
}
|
|
355
367
|
|
|
356
368
|
const todayInString = computed(() => {
|
|
357
|
-
return (
|
|
358
|
-
weekday: 'long',
|
|
359
|
-
month: 'long',
|
|
360
|
-
day: 'numeric',
|
|
361
|
-
})).replace(/\b\w/g, l => l.toUpperCase())
|
|
369
|
+
return dayjs().locale('fr').format('dddd D MMMM').replace(/\b\w/g, l => l.toUpperCase())
|
|
362
370
|
})
|
|
363
371
|
|
|
364
372
|
onMounted(() => {
|
|
@@ -377,7 +385,9 @@
|
|
|
377
385
|
document.removeEventListener('click', handleClickOutside)
|
|
378
386
|
})
|
|
379
387
|
|
|
380
|
-
const dateTextInputRef = ref()
|
|
388
|
+
const dateTextInputRef = ref<null | ComponentPublicInstance<typeof DateTextInput>>()
|
|
389
|
+
const dateCalendarTextInputRef = ref<null | ComponentPublicInstance<typeof SyTextField>>()
|
|
390
|
+
const datePickerRef = ref<null | ComponentPublicInstance<typeof VDatePicker>>()
|
|
381
391
|
|
|
382
392
|
const validateOnSubmit = () => {
|
|
383
393
|
if (props.noCalendar) {
|
|
@@ -389,19 +399,10 @@
|
|
|
389
399
|
return errors.value.length === 0
|
|
390
400
|
}
|
|
391
401
|
|
|
392
|
-
const showDatePicker = () => {
|
|
393
|
-
if (props.disabled || props.readOnly) return
|
|
394
|
-
|
|
395
|
-
isDatePickerVisible.value = true
|
|
396
|
-
|
|
397
|
-
// Mettre à jour l'accessibilité après l'ouverture du DatePicker
|
|
398
|
-
nextTick(() => {
|
|
399
|
-
updateAccessibility()
|
|
400
|
-
})
|
|
401
|
-
}
|
|
402
|
-
|
|
403
402
|
const openDatePicker = () => {
|
|
404
|
-
|
|
403
|
+
if (!isDatePickerVisible.value) {
|
|
404
|
+
toggleDatePicker()
|
|
405
|
+
}
|
|
405
406
|
}
|
|
406
407
|
|
|
407
408
|
type ViewMode = 'month' | 'year' | 'months' | undefined
|
|
@@ -409,6 +410,10 @@
|
|
|
409
410
|
// Variable pour suivre le mode d'affichage actuel du DatePicker
|
|
410
411
|
const currentViewMode = ref<ViewMode>(props.isBirthDate ? 'year' : 'month')
|
|
411
412
|
|
|
413
|
+
watch(() => props.isBirthDate, (newValue) => {
|
|
414
|
+
currentViewMode.value = newValue ? 'year' : 'month'
|
|
415
|
+
})
|
|
416
|
+
|
|
412
417
|
// Fonction pour gérer le changement de mode d'affichage
|
|
413
418
|
const handleViewModeUpdate = (newMode: ViewMode) => {
|
|
414
419
|
currentViewMode.value = newMode
|
|
@@ -430,11 +435,38 @@
|
|
|
430
435
|
}
|
|
431
436
|
}
|
|
432
437
|
|
|
433
|
-
|
|
438
|
+
const handleInputBlur = () => {
|
|
439
|
+
emit('blur')
|
|
440
|
+
validateDates(true)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
watch(isDatePickerVisible, async (isVisible) => {
|
|
434
444
|
if (!isVisible && props.isBirthDate) {
|
|
435
445
|
// Réinitialiser le mode d'affichage au type birthdate
|
|
436
446
|
currentViewMode.value = 'year'
|
|
437
447
|
}
|
|
448
|
+
|
|
449
|
+
if (isVisible) {
|
|
450
|
+
// set the focus on the date picker
|
|
451
|
+
await nextTick()
|
|
452
|
+
const firstButton = datePickerRef.value?.$el.querySelector('button')
|
|
453
|
+
if (firstButton) {
|
|
454
|
+
firstButton.focus()
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
// set the focus on the text input
|
|
459
|
+
// wait for VMenu to finish DOM updates & transition
|
|
460
|
+
setTimeout(() => {
|
|
461
|
+
requestAnimationFrame(() => {
|
|
462
|
+
const inputElement = dateCalendarTextInputRef.value?.$el?.querySelector('input')
|
|
463
|
+
if (inputElement) {
|
|
464
|
+
inputElement.focus()
|
|
465
|
+
isDatePickerVisible.value = false
|
|
466
|
+
}
|
|
467
|
+
})
|
|
468
|
+
}, 0)
|
|
469
|
+
}
|
|
438
470
|
})
|
|
439
471
|
|
|
440
472
|
const getIcon = () => {
|
|
@@ -502,6 +534,36 @@
|
|
|
502
534
|
}
|
|
503
535
|
}, { immediate: true })
|
|
504
536
|
|
|
537
|
+
const toggleDatePicker = () => {
|
|
538
|
+
if (props.disabled || props.readonly) return
|
|
539
|
+
|
|
540
|
+
isDatePickerVisible.value = !isDatePickerVisible.value
|
|
541
|
+
|
|
542
|
+
if (isDatePickerVisible.value) {
|
|
543
|
+
// Mettre à jour l'accessibilité après l'ouverture du DatePicker
|
|
544
|
+
nextTick(() => {
|
|
545
|
+
updateAccessibility()
|
|
546
|
+
})
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
emit('closed')
|
|
550
|
+
validateDates()
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const openDatePickerOnClick = () => {
|
|
555
|
+
openDatePicker()
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const openDatePickerOnFocus = () => {
|
|
559
|
+
openDatePicker()
|
|
560
|
+
emit('focus')
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const openDatePickerOnIconClick = () => {
|
|
564
|
+
toggleDatePicker()
|
|
565
|
+
}
|
|
566
|
+
|
|
505
567
|
defineExpose({
|
|
506
568
|
validateOnSubmit,
|
|
507
569
|
isDatePickerVisible,
|
|
@@ -532,7 +594,7 @@
|
|
|
532
594
|
:custom-rules="props.customRules"
|
|
533
595
|
:custom-warning-rules="props.customWarningRules"
|
|
534
596
|
:disabled="props.disabled"
|
|
535
|
-
:
|
|
597
|
+
:readonly="props.readonly"
|
|
536
598
|
:is-outlined="props.isOutlined"
|
|
537
599
|
:display-icon="props.displayIcon"
|
|
538
600
|
:display-append-icon="props.displayAppendIcon"
|
|
@@ -547,32 +609,6 @@
|
|
|
547
609
|
/>
|
|
548
610
|
</template>
|
|
549
611
|
<template v-else>
|
|
550
|
-
<SyTextField
|
|
551
|
-
v-model="displayFormattedDate"
|
|
552
|
-
:append-icon="displayIcon && displayAppendIcon ? 'calendar' : undefined"
|
|
553
|
-
:append-inner-icon="getIcon()"
|
|
554
|
-
:class="[getMessageClasses(), 'label-hidden-on-focus']"
|
|
555
|
-
:error-messages="errorMessages"
|
|
556
|
-
:warning-messages="warningMessages"
|
|
557
|
-
:success-messages="props.showSuccessMessages ? successMessages : []"
|
|
558
|
-
:disabled="props.disabled"
|
|
559
|
-
:read-only="true"
|
|
560
|
-
:label="props.placeholder"
|
|
561
|
-
:no-icon="props.noIcon"
|
|
562
|
-
:prepend-icon="displayIcon && !displayAppendIcon ? 'calendar' : undefined"
|
|
563
|
-
:variant-style="props.isOutlined ? 'outlined' : 'underlined'"
|
|
564
|
-
color="primary"
|
|
565
|
-
:show-success-messages="props.showSuccessMessages"
|
|
566
|
-
:bg-color="props.bgColor"
|
|
567
|
-
is-clearable
|
|
568
|
-
title="Date Picker"
|
|
569
|
-
@focus="openDatePicker"
|
|
570
|
-
@update:model-value="updateSelectedDates"
|
|
571
|
-
@prepend-icon-click="openDatePicker"
|
|
572
|
-
@append-icon-click="openDatePicker"
|
|
573
|
-
/>
|
|
574
|
-
</template>
|
|
575
|
-
<div>
|
|
576
612
|
<VMenu
|
|
577
613
|
v-if="!props.noCalendar"
|
|
578
614
|
v-model="isDatePickerVisible"
|
|
@@ -586,32 +622,63 @@
|
|
|
586
622
|
attach="body"
|
|
587
623
|
:offset="[-20, 5]"
|
|
588
624
|
>
|
|
589
|
-
<
|
|
590
|
-
<
|
|
591
|
-
v-
|
|
592
|
-
|
|
625
|
+
<template #activator="{ props: menuProps }">
|
|
626
|
+
<SyTextField
|
|
627
|
+
v-bind="menuProps"
|
|
628
|
+
ref="dateCalendarTextInputRef"
|
|
629
|
+
v-model="displayFormattedDate"
|
|
630
|
+
:append-icon="displayIcon && displayAppendIcon ? 'calendar' : undefined"
|
|
631
|
+
:append-inner-icon="getIcon()"
|
|
632
|
+
:class="[getMessageClasses(), 'label-hidden-on-focus']"
|
|
633
|
+
:error-messages="errorMessages"
|
|
634
|
+
:warning-messages="warningMessages"
|
|
635
|
+
:success-messages="props.showSuccessMessages ? successMessages : []"
|
|
636
|
+
:disabled="props.disabled"
|
|
637
|
+
:disable-click-button="false"
|
|
638
|
+
:readonly="true"
|
|
639
|
+
:label="props.placeholder"
|
|
640
|
+
:no-icon="props.noIcon"
|
|
641
|
+
:prepend-icon="displayIcon && !displayAppendIcon ? 'calendar' : undefined"
|
|
642
|
+
:variant-style="props.isOutlined ? 'outlined' : 'underlined'"
|
|
593
643
|
color="primary"
|
|
594
|
-
:
|
|
595
|
-
:
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
@
|
|
600
|
-
@
|
|
601
|
-
@update:
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
644
|
+
:show-success-messages="props.showSuccessMessages"
|
|
645
|
+
:bg-color="props.bgColor"
|
|
646
|
+
is-clearable
|
|
647
|
+
title="Date Picker"
|
|
648
|
+
@click="openDatePickerOnClick"
|
|
649
|
+
@focus="openDatePickerOnFocus"
|
|
650
|
+
@blur="handleInputBlur"
|
|
651
|
+
@update:model-value="updateSelectedDates"
|
|
652
|
+
@prepend-icon-click="openDatePickerOnIconClick"
|
|
653
|
+
@append-icon-click="openDatePickerOnIconClick"
|
|
654
|
+
/>
|
|
655
|
+
</template>
|
|
656
|
+
<VDatePicker
|
|
657
|
+
v-if="isDatePickerVisible && !props.noCalendar"
|
|
658
|
+
ref="datePickerRef"
|
|
659
|
+
v-model="selectedDates"
|
|
660
|
+
color="primary"
|
|
661
|
+
:first-day-of-week="1"
|
|
662
|
+
:multiple="props.displayRange ? 'range' : false"
|
|
663
|
+
:show-adjacent-months="true"
|
|
664
|
+
:show-week="props.showWeekNumber"
|
|
665
|
+
:view-mode="currentViewMode"
|
|
666
|
+
@update:view-mode="handleViewModeUpdate"
|
|
667
|
+
@update:year="handleYearUpdate"
|
|
668
|
+
@update:month="handleMonthUpdate"
|
|
669
|
+
@update:model-value="updateDisplayFormattedDate"
|
|
670
|
+
>
|
|
671
|
+
<template #title>
|
|
672
|
+
Sélectionnez une date
|
|
673
|
+
</template>
|
|
674
|
+
<template #header>
|
|
675
|
+
<h3 class="mx-auto my-auto ml-5 mb-4">
|
|
676
|
+
{{ todayInString }}
|
|
677
|
+
</h3>
|
|
678
|
+
</template>
|
|
679
|
+
</VDatePicker>
|
|
613
680
|
</VMenu>
|
|
614
|
-
</
|
|
681
|
+
</template>
|
|
615
682
|
</div>
|
|
616
683
|
</template>
|
|
617
684
|
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import {Meta, Canvas, Controls, Source} from '@storybook/blocks';
|
|
2
|
+
import * as ValidationStories from './DatePickerValidation.stories.ts';
|
|
3
|
+
|
|
4
|
+
<Meta of={ValidationStories}/>
|
|
5
|
+
|
|
6
|
+
# Documentations des règles de validation du DatePicker
|
|
7
|
+
|
|
8
|
+
Le composant DatePicker prend en charge plusieurs types de règles de validation qui permettent de contrôler les dates saisies par l'utilisateur. Cette documentation décrit toutes les règles disponibles et comment les utiliser.
|
|
9
|
+
|
|
10
|
+
> Pour en savoir plus sur le système global de gestion de validation, consultez la page <a href="/?path=/docs/guide-du-dev-utiliser-le-syst%C3%A8me-de-validation--docs">Utiliser le système de validation</a>.
|
|
11
|
+
|
|
12
|
+
## Exemples de validation
|
|
13
|
+
|
|
14
|
+
## Structure d'une règle de validation
|
|
15
|
+
|
|
16
|
+
Les règles de validation sont définies avec la structure suivante :
|
|
17
|
+
|
|
18
|
+
<Source
|
|
19
|
+
dark code={`
|
|
20
|
+
{
|
|
21
|
+
type: string, // Type de la règle (ex: 'notAfterToday')
|
|
22
|
+
options: {
|
|
23
|
+
message?: string, // Message d'erreur personnalisé
|
|
24
|
+
successMessage?: string, // Message de succès personnalisé
|
|
25
|
+
warningMessage?: string, // Message d'avertissement personnalisé
|
|
26
|
+
fieldIdentifier?: string, // Identifiant du champ pour les messages
|
|
27
|
+
// Autres options spécifiques au type de règle
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
`}/>
|
|
31
|
+
|
|
32
|
+
Ces règles peuvent être passées au DatePicker via les props `customRules` (pour les erreurs) ou `customWarningRules` (pour les avertissements).
|
|
33
|
+
|
|
34
|
+
## Types de règles disponibles
|
|
35
|
+
|
|
36
|
+
### 1. `required`
|
|
37
|
+
|
|
38
|
+
Vérifie que la date est renseignée.
|
|
39
|
+
|
|
40
|
+
<Source
|
|
41
|
+
dark code={`
|
|
42
|
+
<DatePicker
|
|
43
|
+
v-model="date"
|
|
44
|
+
:custom-rules="[{
|
|
45
|
+
type: 'required',
|
|
46
|
+
options: {
|
|
47
|
+
message: 'Vous devez sélectionner une date'
|
|
48
|
+
}
|
|
49
|
+
}]"
|
|
50
|
+
/>
|
|
51
|
+
`}/>
|
|
52
|
+
|
|
53
|
+
### 2. `notWeekend`
|
|
54
|
+
|
|
55
|
+
Vérifie que la date sélectionnée n'est pas un jour de weekend (samedi ou dimanche).
|
|
56
|
+
|
|
57
|
+
<Source
|
|
58
|
+
dark code={`
|
|
59
|
+
<DatePicker
|
|
60
|
+
v-model="date"
|
|
61
|
+
:custom-rules="[{
|
|
62
|
+
type: 'notWeekend',
|
|
63
|
+
options: {
|
|
64
|
+
message: 'La date ne peut pas être un weekend'
|
|
65
|
+
}
|
|
66
|
+
}]"
|
|
67
|
+
/>
|
|
68
|
+
`}/>
|
|
69
|
+
|
|
70
|
+
### 3. `notBeforeToday`
|
|
71
|
+
|
|
72
|
+
Vérifie que la date sélectionnée n'est pas antérieure à la date du jour.
|
|
73
|
+
|
|
74
|
+
<Source
|
|
75
|
+
dark code={`
|
|
76
|
+
<DatePicker
|
|
77
|
+
v-model="date"
|
|
78
|
+
:custom-rules="[{
|
|
79
|
+
type: 'notBeforeToday',
|
|
80
|
+
options: {
|
|
81
|
+
message: 'La date ne peut pas être antérieure à aujourd\'hui'
|
|
82
|
+
}
|
|
83
|
+
}]"
|
|
84
|
+
/>
|
|
85
|
+
`}/>
|
|
86
|
+
|
|
87
|
+
### 4. `notAfterToday`
|
|
88
|
+
|
|
89
|
+
Vérifie que la date sélectionnée n'est pas postérieure à la date du jour.
|
|
90
|
+
|
|
91
|
+
<Source
|
|
92
|
+
dark code={`
|
|
93
|
+
<DatePicker
|
|
94
|
+
v-model="date"
|
|
95
|
+
:custom-rules="[{
|
|
96
|
+
type: 'notAfterToday',
|
|
97
|
+
options: {
|
|
98
|
+
message: 'La date ne peut pas être postérieure à aujourd\'hui'
|
|
99
|
+
}
|
|
100
|
+
}]"
|
|
101
|
+
/>
|
|
102
|
+
`}/>
|
|
103
|
+
|
|
104
|
+
### 5. `notBeforeDate`
|
|
105
|
+
|
|
106
|
+
Vérifie que la date sélectionnée n'est pas antérieure à une date de référence.
|
|
107
|
+
|
|
108
|
+
<Source
|
|
109
|
+
dark code={`
|
|
110
|
+
<DatePicker
|
|
111
|
+
v-model="date"
|
|
112
|
+
:custom-rules="[{
|
|
113
|
+
type: 'notBeforeDate',
|
|
114
|
+
options: {
|
|
115
|
+
message: 'La date ne peut pas être antérieure au 01/01/2023',
|
|
116
|
+
date: '01/01/2023' // Date de référence au format DD/MM/YYYY
|
|
117
|
+
}
|
|
118
|
+
}]"
|
|
119
|
+
/>
|
|
120
|
+
`}/>
|
|
121
|
+
|
|
122
|
+
### 6. `notAfterDate`
|
|
123
|
+
|
|
124
|
+
Vérifie que la date sélectionnée n'est pas postérieure à une date de référence.
|
|
125
|
+
|
|
126
|
+
<Source
|
|
127
|
+
dark code={`
|
|
128
|
+
<DatePicker
|
|
129
|
+
v-model="date"
|
|
130
|
+
:custom-rules="[{
|
|
131
|
+
type: 'notAfterDate',
|
|
132
|
+
options: {
|
|
133
|
+
message: 'La date ne peut pas être postérieure au 31/12/2023',
|
|
134
|
+
date: '31/12/2023' // Date de référence au format DD/MM/YYYY
|
|
135
|
+
}
|
|
136
|
+
}]"
|
|
137
|
+
/>
|
|
138
|
+
`}/>
|
|
139
|
+
|
|
140
|
+
### 7. `dateExact`
|
|
141
|
+
|
|
142
|
+
Vérifie que la date sélectionnée est exactement égale à une date de référence.
|
|
143
|
+
|
|
144
|
+
<Source
|
|
145
|
+
dark code={`
|
|
146
|
+
<DatePicker
|
|
147
|
+
v-model="date"
|
|
148
|
+
:custom-rules="[{
|
|
149
|
+
type: 'dateExact',
|
|
150
|
+
options: {
|
|
151
|
+
message: 'La date doit être le 25/12/2023',
|
|
152
|
+
date: '25/12/2023' // Date de référence au format DD/MM/YYYY
|
|
153
|
+
}
|
|
154
|
+
}]"
|
|
155
|
+
/>
|
|
156
|
+
`}/>
|
|
157
|
+
|
|
158
|
+
### 8. `custom`
|
|
159
|
+
|
|
160
|
+
Permet de créer une règle de validation personnalisée avec une fonction de validation.
|
|
161
|
+
|
|
162
|
+
<Source
|
|
163
|
+
dark code={`
|
|
164
|
+
<DatePicker
|
|
165
|
+
v-model="date"
|
|
166
|
+
:custom-rules="[{
|
|
167
|
+
type: 'custom',
|
|
168
|
+
options: {
|
|
169
|
+
validate: (value) => {
|
|
170
|
+
// Si pas de valeur, c'est valide
|
|
171
|
+
if (!value) return true
|
|
172
|
+
// Convertir en chaîne si ce n'est pas déjà le cas
|
|
173
|
+
const dateStr = value.toString()
|
|
174
|
+
// Vérifier si c'est une Date et extraire l'année
|
|
175
|
+
if (value instanceof Date) {
|
|
176
|
+
return value.getFullYear() !== 2024
|
|
177
|
+
}
|
|
178
|
+
// Fallback sur la vérification de chaîne
|
|
179
|
+
return !dateStr.includes('2024')
|
|
180
|
+
},
|
|
181
|
+
message: 'Les dates en 2024 ne sont pas autorisées',
|
|
182
|
+
successMessage: 'Date valide (hors 2024)',
|
|
183
|
+
fieldIdentifier: 'date'
|
|
184
|
+
}
|
|
185
|
+
}]"
|
|
186
|
+
/>
|
|
187
|
+
`}/>
|
|
188
|
+
|
|
189
|
+
La fonction `validate` reçoit la valeur de la date (au format spécifié par la prop `format`) et doit retourner :
|
|
190
|
+
- `true` si la validation réussit
|
|
191
|
+
- `false` ou une chaîne (message d'erreur personnalisé) si la validation échoue
|
|
192
|
+
|
|
193
|
+
## Utilisation des règles d'avertissement
|
|
194
|
+
|
|
195
|
+
Toutes les règles ci-dessus peuvent également être utilisées comme règles d'avertissement avec la prop `customWarningRules`. Les avertissements n'empêchent pas la soumission du formulaire mais affichent un message en orange.
|
|
196
|
+
|
|
197
|
+
<Source
|
|
198
|
+
dark code={`
|
|
199
|
+
<DatePicker
|
|
200
|
+
v-model="date"
|
|
201
|
+
:custom-warning-rules="[{
|
|
202
|
+
type: 'notBeforeDate',
|
|
203
|
+
options: {
|
|
204
|
+
warningMessage: 'Attention : la date est antérieure à la date de référence',
|
|
205
|
+
date: '01/01/2024',
|
|
206
|
+
isWarning: true
|
|
207
|
+
}
|
|
208
|
+
}]"
|
|
209
|
+
/>
|
|
210
|
+
`}/>
|
|
211
|
+
|
|
212
|
+
## Combinaison de plusieurs règles
|
|
213
|
+
|
|
214
|
+
Vous pouvez combiner plusieurs règles de validation :
|
|
215
|
+
|
|
216
|
+
<Source
|
|
217
|
+
dark code={`
|
|
218
|
+
<DatePicker
|
|
219
|
+
v-model="date"
|
|
220
|
+
:custom-rules="[
|
|
221
|
+
{
|
|
222
|
+
type: 'required',
|
|
223
|
+
options: { message: 'La date est requise' }
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
type: 'notWeekend',
|
|
227
|
+
options: { message: 'La date ne peut pas être un weekend' }
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
type: 'notAfterToday',
|
|
231
|
+
options: { message: 'La date ne peut pas être dans le futur' }
|
|
232
|
+
}
|
|
233
|
+
]"
|
|
234
|
+
/>
|
|
235
|
+
`}/>
|
|
236
|
+
|
|
237
|
+
## Messages de succès
|
|
238
|
+
|
|
239
|
+
Vous pouvez personnaliser les messages de succès qui s'affichent lorsque la validation réussit :
|
|
240
|
+
|
|
241
|
+
<Source
|
|
242
|
+
dark code={`
|
|
243
|
+
<DatePicker
|
|
244
|
+
v-model="date"
|
|
245
|
+
:custom-rules="[{
|
|
246
|
+
type: 'notWeekend',
|
|
247
|
+
options: {
|
|
248
|
+
message: 'La date ne peut pas être un weekend',
|
|
249
|
+
successMessage: 'La date sélectionnée est valide (jour de semaine)'
|
|
250
|
+
}
|
|
251
|
+
}]"
|
|
252
|
+
:show-success-messages="true"
|
|
253
|
+
/>
|
|
254
|
+
`}/>
|
|
255
|
+
|
|
256
|
+
Pour afficher les messages de succès, la prop `showSuccessMessages` doit être définie à `true`.
|
|
257
|
+
|
|
258
|
+
## Désactivation de la gestion des erreurs
|
|
259
|
+
|
|
260
|
+
Si vous souhaitez effectuer la validation sans afficher les messages d'erreur, vous pouvez utiliser la prop `disableErrorHandling` :
|
|
261
|
+
|
|
262
|
+
<Source
|
|
263
|
+
dark code={`
|
|
264
|
+
<DatePicker
|
|
265
|
+
v-model="date"
|
|
266
|
+
:custom-rules="[{ type: 'required' }]"
|
|
267
|
+
:disable-error-handling="true"
|
|
268
|
+
/>
|
|
269
|
+
`}/>
|
|
270
|
+
|
|
271
|
+
Cette option est utile lorsque vous gérez la validation à un niveau supérieur, par exemple dans un formulaire parent.
|
|
272
|
+
|
|
273
|
+
## Règles présentes par défaut
|
|
274
|
+
|
|
275
|
+
Le composant DatePicker intègre certaines règles de validation par défaut, sans que vous ayez besoin de les spécifier via `customRules` :
|
|
276
|
+
|
|
277
|
+
### Validation du champ requis
|
|
278
|
+
|
|
279
|
+
Lorsque la prop `required` est définie à `true`, le DatePicker effectue automatiquement une validation pour s'assurer qu'une date est sélectionnée. Si aucune date n'est sélectionnée, le message d'erreur "La date est requise." est affiché.
|
|
280
|
+
|
|
281
|
+
<Source
|
|
282
|
+
dark code={`
|
|
283
|
+
<DatePicker
|
|
284
|
+
v-model="date"
|
|
285
|
+
required
|
|
286
|
+
/>
|
|
287
|
+
`}/>
|
|
288
|
+
|
|
289
|
+
### Validation du format de date
|
|
290
|
+
|
|
291
|
+
Le DatePicker vérifie automatiquement que la date saisie respecte le format spécifié par la prop `format` (par défaut `DD/MM/YYYY`). Cette validation est effectuée lorsque l'utilisateur saisit manuellement une date dans le champ de texte.
|
|
292
|
+
|
|
293
|
+
<Source
|
|
294
|
+
dark code={`
|
|
295
|
+
<DatePicker
|
|
296
|
+
v-model="date"
|
|
297
|
+
format="MM/DD/YYYY" <!-- Format personnalisé -->
|
|
298
|
+
/>
|
|
299
|
+
`}/>
|
|
300
|
+
|
|
301
|
+
### Validation de la plage de dates
|
|
302
|
+
|
|
303
|
+
Lorsque `displayRange` est à `true`, le DatePicker valide automatiquement que la plage de dates est cohérente (date de début antérieure à date de fin) lorsque deux dates sont sélectionnées.
|
|
304
|
+
|
|
305
|
+
<Source
|
|
306
|
+
dark code={`<DatePicker
|
|
307
|
+
v-model="dateRange"
|
|
308
|
+
display-range
|
|
309
|
+
/>
|
|
310
|
+
`}/>
|
|
311
|
+
|
|
312
|
+
## Interaction entre règles personnalisées et validations par défaut
|
|
313
|
+
|
|
314
|
+
Lorsque vous utilisez des règles personnalisées via `customRules` en combinaison avec des validations par défaut (comme `required`), il est important de comprendre comment ces règles interagissent :
|
|
315
|
+
|
|
316
|
+
### Ordre de priorité des validations
|
|
317
|
+
|
|
318
|
+
1. Les validations par défaut (comme `required`) sont exécutées en premier.
|
|
319
|
+
2. Si les validations par défaut réussissent, les règles personnalisées sont ensuite appliquées.
|
|
320
|
+
3. Les règles d'avertissement (`customWarningRules`) ne sont exécutées que si aucune erreur n'est détectée dans les étapes précédentes.
|
|
321
|
+
|
|
322
|
+
### Exemple d'interaction
|
|
323
|
+
|
|
324
|
+
<Source
|
|
325
|
+
dark code={`<DatePicker
|
|
326
|
+
v-model="date"
|
|
327
|
+
required
|
|
328
|
+
:custom-rules="[{
|
|
329
|
+
type: 'notAfterToday',
|
|
330
|
+
options: { message: 'La date ne peut pas être après aujourd\'hui' }
|
|
331
|
+
}]"
|
|
332
|
+
/>
|
|
333
|
+
`}/>
|
|
334
|
+
|
|
335
|
+
Dans cet exemple :
|
|
336
|
+
- Si aucune date n'est sélectionnée, la validation `required` échoue et le message "La date est requise." s'affiche.
|
|
337
|
+
- Si une date est sélectionnée mais qu'elle est postérieure à aujourd'hui, la règle personnalisée `notAfterToday` échoue et son message d'erreur s'affiche.
|
|
338
|
+
- Si une date est sélectionnée et qu'elle est antérieure ou égale à aujourd'hui, toutes les validations réussissent.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Meta, type StoryFn } from '@storybook/vue3'
|
|
2
|
+
import DatePickerValidationExamples from './docExamples/DatePickerValidationExamples.vue'
|
|
3
|
+
import DatePickerBidirectionalValidation from './docExamples/DatePickerBidirectionalValidation.vue'
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Composants/Formulaires/DatePicker/Validation',
|
|
7
|
+
component: DatePickerValidationExamples,
|
|
8
|
+
argTypes: {},
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: 'Exemples de validation pour le composant DatePicker.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
} as Meta
|
|
17
|
+
|
|
18
|
+
export const ValidationExamples: StoryFn = () => ({
|
|
19
|
+
components: {
|
|
20
|
+
DatePickerValidationExamples,
|
|
21
|
+
},
|
|
22
|
+
template: '<DatePickerValidationExamples />',
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
export const BidirectionalValidation: StoryFn = () => ({
|
|
26
|
+
components: {
|
|
27
|
+
DatePickerBidirectionalValidation,
|
|
28
|
+
},
|
|
29
|
+
template: '<DatePickerBidirectionalValidation />',
|
|
30
|
+
})
|