feat(ui) : saisie clavier MalioDate + bouton « + » InputEmail + séparateurs InputAmount (#MUI-42) #68

Merged
tristan merged 38 commits from feature/MUI-42-fix-composants-apres-retour-erp into develop 2026-06-09 15:39:38 +00:00
Owner

Cette PR regroupe trois évolutions de la librairie (retours ERP).


1. MalioDate — saisie manuelle au clavier

Ajoute la saisie manuelle au clavier JJ/MM/AAAA sur MalioDate (opt-in via la prop editable), en plus de la sélection au calendrier.

  • CalendarField (interne) gagne un mode editable : input non readonly, masque maska ##/##/####, buffer local synchronisé sur la valeur, event commit au blur / à Entrée.
  • MalioDate parse le texte (parseDisplayToIso), valide les bornes (isDateInRange) et gère un état d'erreur interne fusionné avec la prop error du consommateur.
  • Le focus ouvre le popover ; la saisie invalide/hors bornes conserve le texte et affiche un message (invalidMessage, défaut Date invalide) ; la sélection au calendrier ou un changement externe de modelValue efface l'erreur.
  • Aucune régression : editable défaut false ; le reste de la famille Date (DateRange/DateTime/DateWeek) est inchangé.

Nouvelles props MalioDate : editable (boolean, défaut false), invalidMessage (string, défaut Date invalide).


2. MalioInputEmail — bouton « + » d'ajout

Ajoute à MalioInputEmail le même bouton « + » que MalioInputPhone : un bouton optionnel qui émet un event add (ex. pour ajouter dynamiquement un autre champ email).

  • Props addable (défaut false), addIconName (défaut mdi:plus), addButtonLabel (défaut Ajouter une adresse email) ; nouvel event add().
  • L'icône email étant à droite par défaut, une computed effectiveIconPosition la déplace automatiquement à gauche quand addable est actif, libérant la droite pour le bouton.
  • Le bouton respecte disabled/readonly (pas d'émission).
  • Aucune régression : addable défaut false ; la logique de sanitisation email (espaces, lowercase, caret) est intacte.

3. MalioInputAmount — séparateurs de milliers

Affiche les montants groupés à la française (1 234 567,89 : espace pour les milliers, virgule décimale), en temps réel pendant la saisie, tout en gardant une valeur émise propre.

  • La valeur émise (modelValue) reste une chaîne numérique propre : point décimal, sans espaces ('1234567.89'). Contrat consommateur inchangé.
  • Fonctions pures extraites dans composables/amountFormat.ts (normalizeAmount, formatGroupedAmount, helpers curseur) — testées en isolation.
  • À la frappe : parse → émission du modèle propre → reformatage groupé → repositionnement du curseur (comptage des caractères significatifs hors espaces).
  • maxLength borne désormais la longueur du modèle (le maxlength natif, qui compterait les espaces, est retiré).
  • Activé par défaut sur tous les MalioInputAmount ; format FR figé.

Spec et plan des trois features : docs/superpowers/specs/ et docs/superpowers/plans/.

Plan de test

  • npm run test -- Date.test.ts → 40 tests OK
  • npm run test -- InputEmail.test.ts → 52 tests OK
  • npm run test -- amountFormat.test.ts InputAmount.test.ts → 50 tests OK
  • npm run lint → 0 erreur
  • Vérif manuelle playground composant/date : saisie valide → ISO ; 32/13/2026 → texte conservé + rouge ; sélection calendrier efface l'erreur
  • Vérif manuelle playground composant/input/inputEmail : carte « Ajout dynamique » → le « + » ajoute un champ ; icône à gauche + bouton à droite
  • Vérif manuelle playground composant/input/inputAmount : carte « Grand montant » → 1234567 s'affiche 1 234 567 en live, modelValue émis 1234567 ; curseur cohérent

🤖 Generated with Claude Code

Cette PR regroupe **trois évolutions** de la librairie (retours ERP). --- ## 1. MalioDate — saisie manuelle au clavier Ajoute la **saisie manuelle au clavier** `JJ/MM/AAAA` sur `MalioDate` (opt-in via la prop `editable`), en plus de la sélection au calendrier. - `CalendarField` (interne) gagne un mode `editable` : input non `readonly`, masque maska `##/##/####`, buffer local synchronisé sur la valeur, event `commit` au blur / à Entrée. - `MalioDate` parse le texte (`parseDisplayToIso`), valide les bornes (`isDateInRange`) et gère un état d'erreur interne fusionné avec la prop `error` du consommateur. - Le focus ouvre le popover ; la saisie invalide/hors bornes conserve le texte et affiche un message (`invalidMessage`, défaut `Date invalide`) ; la sélection au calendrier ou un changement externe de `modelValue` efface l'erreur. - **Aucune régression** : `editable` défaut `false` ; le reste de la famille Date (DateRange/DateTime/DateWeek) est inchangé. Nouvelles props `MalioDate` : `editable` (boolean, défaut false), `invalidMessage` (string, défaut Date invalide). --- ## 2. MalioInputEmail — bouton « + » d'ajout Ajoute à `MalioInputEmail` le même bouton « + » que `MalioInputPhone` : un bouton optionnel qui émet un event `add` (ex. pour ajouter dynamiquement un autre champ email). - Props `addable` (défaut `false`), `addIconName` (défaut `mdi:plus`), `addButtonLabel` (défaut `Ajouter une adresse email`) ; nouvel event `add()`. - L'icône email étant à droite par défaut, une computed `effectiveIconPosition` la **déplace automatiquement à gauche** quand `addable` est actif, libérant la droite pour le bouton. - Le bouton respecte `disabled`/`readonly` (pas d'émission). - **Aucune régression** : `addable` défaut `false` ; la logique de sanitisation email (espaces, `lowercase`, caret) est intacte. --- ## 3. MalioInputAmount — séparateurs de milliers Affiche les montants groupés à la française (`1 234 567,89` : espace pour les milliers, virgule décimale), **en temps réel** pendant la saisie, tout en gardant une valeur émise propre. - La valeur émise (`modelValue`) reste une **chaîne numérique propre** : point décimal, sans espaces (`'1234567.89'`). Contrat consommateur inchangé. - Fonctions pures extraites dans `composables/amountFormat.ts` (`normalizeAmount`, `formatGroupedAmount`, helpers curseur) — testées en isolation. - À la frappe : parse → émission du modèle propre → reformatage groupé → repositionnement du curseur (comptage des caractères significatifs hors espaces). - `maxLength` borne désormais la **longueur du modèle** (le `maxlength` natif, qui compterait les espaces, est retiré). - **Activé par défaut** sur tous les `MalioInputAmount` ; format FR figé. --- Spec et plan des trois features : `docs/superpowers/specs/` et `docs/superpowers/plans/`. ## Plan de test - [x] `npm run test -- Date.test.ts` → 40 tests OK - [x] `npm run test -- InputEmail.test.ts` → 52 tests OK - [x] `npm run test -- amountFormat.test.ts InputAmount.test.ts` → 50 tests OK - [x] `npm run lint` → 0 erreur - [ ] Vérif manuelle playground `composant/date` : saisie valide → ISO ; `32/13/2026` → texte conservé + rouge ; sélection calendrier efface l'erreur - [ ] Vérif manuelle playground `composant/input/inputEmail` : carte « Ajout dynamique » → le « + » ajoute un champ ; icône à gauche + bouton à droite - [ ] Vérif manuelle playground `composant/input/inputAmount` : carte « Grand montant » → `1234567` s'affiche `1 234 567` en live, `modelValue` émis `1234567` ; curseur cohérent 🤖 Generated with [Claude Code](https://claude.com/claude-code)
tristan added 8 commits 2026-06-09 10:28:40 +00:00
tristan added 6 commits 2026-06-09 11:21:16 +00:00
tristan changed title from feat(date) : saisie manuelle au clavier sur MalioDate (#MUI-42) to feat(ui) : saisie manuelle MalioDate + bouton « + » d'ajout MalioInputEmail (#MUI-42) 2026-06-09 11:28:50 +00:00
tristan added 8 commits 2026-06-09 12:09:07 +00:00
tristan changed title from feat(ui) : saisie manuelle MalioDate + bouton « + » d'ajout MalioInputEmail (#MUI-42) to feat(ui) : saisie clavier MalioDate + bouton « + » InputEmail + séparateurs InputAmount (#MUI-42) 2026-06-09 12:12:16 +00:00
tristan added 1 commit 2026-06-09 12:59:29 +00:00
tristan added 15 commits 2026-06-09 15:38:52 +00:00
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Anneau outline m-primary affiché uniquement à la navigation clavier (Tab),
pas au clic souris. Composable partagé useKbdFocusRing (détection de modalité
clavier/souris) + utilitaire CSS .m-focus-ring-kbd. Le visuel existant
(grossissement, label flottant, bordure bleue) reste inchangé.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Anneau de focus clavier sur le champ (via useKbdFocusRing)
- Ouverture du sélecteur de fichier au clavier (Entrée / Espace)
- Nouveau prop `clearable` (défaut false) : croix `mdi:close` focusable
  (Entrée/Espace, anneau clavier) qui vide le champ et émet l'event `clear`
- Playground : carte de démonstration "Clearable"

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Anneau de focus clavier (clavier-only) ; quand la liste est ouverte,
  l'anneau entoure tout le bloc input + liste d'un seul tenant
  (utilitaires CSS .m-combo-ring-top / .m-combo-ring-bottom)
- Navigation clavier aux normes WAI-ARIA APG : scroll auto de l'option
  active dans la vue, ArrowUp ouvre sur la dernière option, Home/End,
  Tab ferme la liste

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Anneau de focus clavier (clavier-only) ; ouvert, l'anneau entoure
  bouton + liste d'un seul tenant, adapté au sens d'ouverture (haut/bas)
- Navigation clavier WAI-ARIA APG (manquait) : ouverture, flèches avec
  scroll auto de l'option active, Home/End, Entrée/Espace, Échap, Tab
- aria-activedescendant pour les lecteurs d'écran
- Le focus reste sur le bouton après sélection (plus de blur vers le body)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Anneau de focus clavier (clavier-only), combo bouton + liste selon le sens
- Navigation clavier WAI-ARIA APG : ouverture, flèches + scroll auto,
  Home/End, Entrée/Espace togglent (liste reste ouverte), Échap/Tab ferment
- Ligne "Tout sélectionner" intégrée à la navigation clavier (index -1)
- aria-activedescendant ; focus conservé sur le bouton
- Clic sur toute la ligne (li) coche/décoche, plus seulement sur le label

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remplace le halo focus-visible:ring-2 ring-m-primary/50 par l'anneau outline
standard (m-primary plein, offset 2px), cohérent avec les autres composants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`displayTag="true"` (string) déclenchait un warning de type Vue
(Expected Boolean, got String). Passage en `:display-tag="true"`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Couvre toute la famille date (Date, DateRange, DateTime, DateWeek) :
- Anneau de focus clavier (clavier-only) ; ouvert, l'anneau entoure
  champ + calendrier d'un seul tenant (combo)
- Entrée / Espace ouvrent/ferment le calendrier (mode non éditable),
  Échap ferme ; mode éditable inchangé
- Anneau sur la croix d'effacement

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- CHANGELOG : anneau de focus clavier standardisé, anneau combo, navigation
  APG (Select/SelectCheckbox/Autocomplete), clearable Upload, ouverture
  clavier Date, uniformisation Button/ButtonIcon, focus conservé Select
- COMPONENTS : note générale focus clavier + notes "Clavier" par composant,
  prop clearable et event clear d'InputUpload

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tristan merged commit 336cb9e315 into develop 2026-06-09 15:39:38 +00:00
tristan deleted branch feature/MUI-42-fix-composants-apres-retour-erp 2026-06-09 15:39:38 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MALIO-DEV/malio-layer-ui#68