feat(ui) : MalioDate/DateTime — event update:rawValue pour validation back-autoritative (#MUI-44)

Expose la saisie brute invalide sur un canal séparé (`@update:rawValue`),
sans la faire transiter par `modelValue` (qui reste ISO|null). Émis à chaque
commit : saisie invalide (non parsable ou hors min/max) → texte trimmé tel que
tapé ; saisie valide/vide, clear, sélection au calendrier → ''. Le parent
construit son payload via `valid ? modelValue : rawValue`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-12 09:19:19 +02:00
parent 86e8a84535
commit 6c78d511a8
6 changed files with 137 additions and 3 deletions
+9
View File
@@ -90,6 +90,10 @@ const props = withDefaults(
const emit = defineEmits<{
(e: 'update:modelValue', value: string | null): void
(e: 'update:valid', value: boolean): void
// Canal séparé pour la saisie invalide (validation back-autoritative) : texte brut
// tel que tapé sur saisie non parsable/hors plage, '' sinon. Ne JAMAIS transiter
// par modelValue, qui doit rester ISO|null pour l'affichage et le round-trip.
(e: 'update:rawValue', value: string): void
}>()
const displayValue = computed(() => formatIsoToDisplay(props.modelValue ?? null))
@@ -108,25 +112,30 @@ const onCommit = (text: string) => {
const trimmed = text.trim()
if (trimmed === '') {
setError('')
emit('update:rawValue', '')
emit('update:modelValue', null)
return
}
const iso = parseDisplayToIso(trimmed)
if (iso && isDateInRange(iso, props.min, props.max)) {
setError('')
emit('update:rawValue', '')
emit('update:modelValue', iso)
return
}
setError(props.invalidMessage)
emit('update:rawValue', trimmed)
}
const onClear = () => {
setError('')
emit('update:rawValue', '')
emit('update:modelValue', null)
}
const onSelect = (iso: string, close: () => void) => {
setError('')
emit('update:rawValue', '')
emit('update:modelValue', iso)
close()
}