fix(date) : borne le 2e chiffre par champ (jour 1-31, mois 1-12, heure 0-23, minute 0-59)

Le bornage par tokens ne contraignait que le 1er chiffre (positionnel, sans
mémoire du chiffre précédent) : 33 (jour) ou 19 (mois) restaient tapables.

Remplacé par un preProcess maska qui valide chaque champ progressivement : un
chiffre n'est accepté que s'il existe encore une complétion dans [min, max].
Borne donc le 1er ET le 2e chiffre ; les impossibilités calendaires fines
(31/02, 29/02 non bissextile, hors min/max) restent captées par la validation.

Tests d'intégration : 32/13 (désormais non tapable) remplacé par 31/02 comme
date « champs valides mais inexistante » ; garde sur l'exemple métier 33/19.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-18 16:35:25 +02:00
parent 428f30aabe
commit 4a933da19e
7 changed files with 159 additions and 113 deletions
@@ -191,14 +191,14 @@ const generatedId = useId()
const root = ref<HTMLElement | null>(null)
const draft = ref(props.displayValue)
// Le masque maska est dérivé du gabarit : chaque lettre devient un slot chiffre,
// le premier chiffre de chaque champ est borné (jour 0-3, mois 0-1, heure 0-2,
// minute 0-5) pour empêcher la frappe de valeurs absurdes (ex. 99/99/9999).
// eager : pose les séparateurs (/, espace, :) dès qu'un groupe est complet.
// Le masque maska est dérivé du gabarit : masque structurel pour le formatage,
// + preProcess qui borne la saisie (1er ET 2e chiffre : jour 1-31, mois 1-12,
// heure 0-23, minute 0-59) afin qu'une valeur impossible (99/99/9999, 33, mois 19…)
// ne puisse pas être tapée. eager : pose les séparateurs dès qu'un groupe est complet.
const maskaOptions = computed<MaskInputOptions>(() => {
if (!props.editable) return {eager: false}
const {mask, tokens} = buildBoundedMask(props.placeholderTemplate)
return {mask, tokens, eager: true}
const {mask, preProcess} = buildBoundedMask(props.placeholderTemplate)
return {mask, preProcess, eager: true}
})
const inputReadonly = computed(() => !props.editable || props.readonly || props.disabled)