# Changelog
Liste des évolutions de la librairie Malio layer UI
## [0.0.0]
### Parameters
### Added
* [#333] Création d'un composant text
* [#337] Création d'un composant select
* [#362] Création d'un composant checkbox
* [#363] Création d'un composant amount
* [#364] Création d'un composant button radio
* [#365] Création d'un composant number
* [#366] Création d'un composant select checkbox
* [#407] Création d'un composant time
* Création d'un composant textarea
* [#MUI-8] Création d'un composant mot de passe
* [#MUI-9] Création d'un composant upload
* [#MUI-14] Création d'un composant bouton icône
* [#MUI-11] Création d'un composant navigation par onglets
* [#MUI-20] Création d'un composant sidebar
* [#MUI-23] Revoir la config couleur tailwind
* [#MUI-10] Création d'un composant bouton
* [#MUI-2] Faire un MCP pour la librairie de composant
* [#MUI-15] Création d'un composant drawer
* [#MUI-22] Création d'un composant datatable
* [#MUI-27] Création d'un composant sélection de site
* Création d'un composant rich text (TipTap) avec sortie markdown / HTML
* [#MUI-30] Création d'un composant email
* [#MUI-31] Création d'un composant téléphone
* [#MUI-32] Création d'un composant saisie assistée (autocomplete)
* [#MUI-34] Revoir le système de playground
* [#MUI-33] Développer le composant Datepicker
* [#MUI-33] Création du composant DateTime (date + heure, sélecteur d'heure natif intérimaire)
* [#MUI-36] Création d'un composant modal (dialogue centré, focus-trap, scroll-lock, footer fixe)
* [#MUI-37] Création d'un composant accordéon
* [#MUI-39] Création d'un sélecteur d'heure à molettes (MalioTimePicker) ; DateTime rebranché dessus (remplace l'input time natif intérimaire)
* InputAutocomplete : prop `localFilter` pour le filtrage côté client des listes statiques (case-insensitive `label.includes(query)`), sans avoir à brancher `@search`
* InputTextArea : la scrollbar passe en primary (bleu) au focus, comme la liste du Select
* Token Tailwind partagé `w-m-btn-action` (150px) exposé via `tailwind.config.ts` + CSS var `--m-btn-action-width` dans `malio.css` — utilisable côté consommateur pour les boutons d'action (``), themable en redéfinissant la CSS var
* [#MUI-41] Prop `required` cohérente + astérisque rouge dans le label sur la famille formulaire (Select, SelectCheckbox, InputUpload, InputRichText gagnent la prop)
* [#MUI-41] InputEmail : sanitisation à la saisie (suppression des espaces, option `lowercase`)
* [#MUI-42] MalioDate : saisie clavier `JJ/MM/AAAA` optionnelle (prop `editable`, masque maska, validation au blur, message `invalidMessage`)
* InputEmail : bouton `+` d'ajout optionnel (prop `addable`, event `add`), calqué sur InputPhone ; l'icône email passe à gauche quand le bouton est actif
* InputAmount : affichage groupé des milliers à la française (`1 234 567,89`) en temps réel ; `modelValue` reste propre (`'1234567.89'`) ; `maxLength` borne la longueur du modèle
* [#MUI-42] Anneau de focus clavier standardisé (`outline` 2px `m-primary`, offset 2px) affiché **uniquement** à la navigation clavier (jamais au clic souris), sur l'ensemble des champs et contrôles : inputs (Text, Email, Password, Phone, Amount, Number + boutons ±, Upload, TextArea, Autocomplete), Select, SelectCheckbox, famille Date (Date, DateRange, DateTime, DateWeek), Button, ButtonIcon. Mécanique : composable `useKbdFocusRing` (détection de modalité clavier/souris) + utilitaires CSS `.m-focus-ring` (éléments à `:focus-visible` natif) et `.m-focus-ring-kbd` (champs texte, où `:focus-visible` se déclenche aussi à la souris)
* [#MUI-42] Anneau « combo » : quand un dropdown / calendrier est ouvert (Autocomplete, Select, SelectCheckbox, Date), l'anneau entoure le champ **et** la liste / le calendrier d'un seul tenant, adapté au sens d'ouverture (utilitaires `.m-combo-ring-top` / `.m-combo-ring-bottom`)
* [#MUI-42] Navigation clavier WAI-ARIA APG sur les listes déroulantes : Select et SelectCheckbox gagnent la navigation (flèches, Home/End, Entrée/Espace, Échap, Tab — absente jusque-là), avec scroll automatique de l'option active et `aria-activedescendant` ; InputAutocomplete complété (scroll auto, ArrowUp ouvre sur la dernière option, Home/End, Tab ferme)
* [#MUI-42] SelectCheckbox : la ligne « Tout sélectionner » est intégrée à la navigation clavier ; le clic sur toute la ligne d'option (et plus seulement le label) coche/décoche
* [#MUI-42] InputUpload : prop `clearable` (croix `mdi:close` focusable qui vide le champ + event `clear`) et ouverture du sélecteur de fichier au clavier (Entrée / Espace)
* [#MUI-42] Famille Date : ouverture du calendrier au clavier (Entrée / Espace), fermeture par Échap
* [#MUI-43] MalioDate : event `update:valid` (booléen) exposant l'état de validité de la saisie (`false` sur date malformée ou hors `min`/`max`, qui n'émet pas `modelValue`) — permet au parent de bloquer le submit ; la validité ne couvre pas `required` (champ vide = valide)
* [#MUI-43] MalioDateTime : saisie clavier `JJ/MM/AAAA HH:MM` optionnelle (prop `editable`, masque maska, `invalidMessage`) + même event `update:valid` que MalioDate (mêmes règles, émis dès le montage). Nouveau parseur `parseDisplayToIsoDateTime`.
* [#MUI-43] Famille Date editable (MalioDate, MalioDateTime) : gabarit fantôme progressif — le format (`JJ/MM/AAAA` / `JJ/MM/AAAA HH:MM`) s'affiche en gris et se remplit au fil de la saisie (tapé en noir, reste en gris) ; séparateurs (`/`, espace, `:`) posés automatiquement dès qu'un groupe est complet (maska `eager`). CalendarField : prop `placeholderTemplate` (le masque maska en est dérivé), remplace l'ancienne mécanique de masque codé en dur.
* [#MUI-43] CalendarField : la croix d'effacement réinitialise désormais la saisie clavier même après une date invalide (le `v-model` restant `null`, le champ se vidait pas).
* [#MUI-44] MalioDate / MalioDateTime : event `update:rawValue` (string) exposant la saisie brute sur un canal séparé pour la validation back-autoritative — saisie invalide (non parsable ou hors `min`/`max`) → texte trimmé tel que tapé, saisie valide/vide + clear + sélection au calendrier → `''`. `modelValue` reste `string` ISO `| null` (la saisie invalide n'y transite jamais) ; le parent construit son payload via `valid ? modelValue : rawValue`.
* [#MUI-45] MalioDate : prop `markedDates` (`Record<"YYYY-MM-DD", 'success' | 'danger'>`) appliquant un fond tokenisé par jour dans la grille (générique, fourni par le consommateur ; précédence sélection/`today` > variante marquée > défaut) + event `month-change` (`{ month: 0-11, year }`) émis à l'ouverture du popover et à chaque navigation de mois. Sert l'écran *Heures* de SIRH (jours validés en vert, chargement du mois visible à la volée).
### Changed
* Cohérence du mode **`disabled`** sur toute la famille formulaire (calqué sur InputText : texte + label grisés, `cursor-not-allowed`, aucune affordance interactive). Concrètement, quand `disabled` : le **bouton « + »** d'ajout disparaît (InputPhone, InputEmail), l'**œil** de révélation disparaît (InputPassword), le **chevron** disparaît (Select, SelectCheckbox, InputAutocomplete), la **croix d'effacement** reste masquée (date, upload, time), le **label** passe en `text-m-muted` (Select, SelectCheckbox, famille Date via CalendarField, TimePicker), et les **tags** du SelectCheckbox + la valeur du Select passent en gris. (InputText, InputAmount, InputNumber, InputTextArea, InputRichText, Checkbox, RadioButton, InputUpload étaient déjà conformes.)
* TabList : le nombre d'onglets visibles en mode fenêtré s'**adapte automatiquement à la largeur réelle** (mesure via `ResizeObserver` + ligne de mesure cachée), au lieu d'un `maxVisibleTabs` fixe qui pouvait faire déborder les onglets sur les chevrons. Les chevrons restent fixés aux bords et le nombre affiché est choisi pour que les onglets tiennent (pas de chevauchement ni de rognage). `maxVisibleTabs` devient un **plafond optionnel**. Calcul isolé dans une fonction pure testable (`tabFit.ts`, basée sur les largeurs réelles des onglets). Sans layout (SSR), repli sur le plafond / tous les onglets. **Breaking** : la prop `maxWidth` est supprimée (la barre utilise désormais toute la largeur disponible au lieu d'être plafonnée à 1100px).
* TabList : au **survol** d'un onglet inactif, on applique désormais le même style que l'onglet actif — texte `m-primary` plein + barre soulignée `m-primary` (`hover:after:*`) — au lieu du discret `text-m-primary/70`, pour bien marquer la cible.
* Sidebar : états visuels des liens de navigation — **survol** : highlight pleine largeur entièrement porté par le `
` (fond `m-primary` à 10 % + texte `m-primary` + semi-bold, `hover:bg-m-primary/10 hover:text-m-primary hover:font-semibold`, espacement `pt-1 pb-1`). La couleur de base (`text-black`) est aussi sur le `` et le `` ne fige plus sa couleur (il hérite) : sinon, sur les bandes `pt-1`/`pb-1` situées hors du ``, le fond devenait bleu mais le texte restait noir. **Lien actif** : texte `m-primary` + semi-bold, sans fond (`active-class="!text-m-primary font-semibold"` ; `!important` car `active-class` est hors `twMerge`).
* DataTable : libellés de pagination en français — `Préc.` / `Suiv.` (étaient `Prev` / `Next`) ; aria-labels déjà en français inchangés.
* MalioButton : dimensions par défaut `w-[180px]` / `h-[38px]` (étaient `w-[200px]` / `h-[40px]`).
* DataTable : tailles par défaut revues — texte header `16px` (était `20px`), texte body `14px` (était `18px`), sélecteur de lignes et boutons de pagination (Prev / numéros / Next) alignés à `30px` de haut, padding de `12px` entre le bas du tableau et la barre de pagination, texte header et body passés en noir (`text-black`, étaient `text-m-primary`).
* Select : nouvelle prop `fieldClass` pour surcharger les classes du field (notamment la hauteur `h-[40px]` jusqu'ici codée en dur) ; utilisée par le DataTable pour passer le sélecteur de perPage à `30px`.
* [#MUI-35] Refonte du composant drawer : slots `#header`/`#footer`, prop `side` (droite/gauche), `dismissable`, `closeOnEscape`, classes d'override, focus-trap, scroll-lock et fermeture au clavier. **Breaking** : la prop `title` est remplacée par le slot `#header`.
* [#MUI-42] Button / ButtonIcon : l'anneau de focus passe du halo `ring-2 ring-m-primary/50` à l'anneau standard `.m-focus-ring` (outline plein, offset 2px), pour l'homogénéité avec les autres composants.
### Fixed
* Sidebar : le **lien actif** reste actif sur les **sous-routes** (match par préfixe via `useRoute().path` au lieu de l'`active-class` de NuxtLink qui dépendait de l'imbrication des routes) — ex. `/supplier` reste surligné sur `/supplier/1/edit`. Nouvelle option `exact: true` par item pour forcer le match strict.
* Famille Date (CalendarField) : le **clic sur le picto calendrier** ouvre désormais le popover (le `` en overlay absolu interceptait le clic sans le traiter, et ne le laissait pas retomber sur l'input). Couvre Date, DateTime, DateRange, DateWeek. La croix d'effacement conserve son comportement (efface sans ouvrir).
* Famille Date editable (MalioDate, MalioDateTime) : la saisie clavier est désormais **bornée par champ** sur le premier **et** le second chiffre (jour `01-31`, mois `01-12`, heure `00-23`, minute `00-59`) — une valeur hors plage (`99/99/9999`, un jour `33`, un mois `19`…) ne peut plus être tapée (auparavant saisissable puis rejetée a posteriori par la validation). Les impossibilités calendaires fines (`31/02`, 29/02 non bissextile, hors `min`/`max`) restent captées par la validation. Implémenté via `buildBoundedMask(template)` (CalendarField) : un `preProcess` maska valide chaque champ progressivement (un chiffre n'est accepté que s'il reste une complétion valide dans la plage) ; il distingue le mois des minutes (même lettre `M`) selon la présence d'heures dans le gabarit.
* DataTable : pagination réalignée verticalement après l'introduction du `min-h-[1rem]` du Select — la barre pagination passe en `items-center`, et le MalioSelect du sélecteur de perPage est encapsulé dans un wrapper `h-12` qui borne sa taille flex à la hauteur du field (le slot vide déborde invisiblement en dessous). Span « Lignes : » et boutons Prev/Page/Next sont désormais centrés exactement sur le field (y=24)
* Drawer : le slot `#footer` est désormais rendu hors de la zone scrollable (épinglé en bas, comme la modal) ; seul le body défile et la scrollbar ne s'étend plus derrière le footer
* Hauteur des boutons de pagination du datatable alignée sur le select (40px)
* Distribution de `tailwind.config.ts` aux projets consommateurs avec paths `content` absolus
* Espace réservé (`min-h-[1rem]`) pour le paragraphe hint/error/success de 15 composants (Input*, Select*, Time*, CalendarField, Checkbox) — l'apparition d'une erreur ne décale plus les cellules voisines dans une grille
* InputPhone : la croix `+` (add button) suit la même cascade d'état que les autres icônes du champ (muted / primary en focus / black quand rempli / danger / success) au lieu d'être figée en primary
* Select / SelectCheckbox : le chevron suit l'état du champ (muted par défaut, primary à l'ouverture, black avec une option sélectionnée, danger / success en cas d'erreur ou succès) au lieu de `text-current`
* InputTextArea : composant single-root (était multi-root) — le wrapper du message ne prend plus sa propre cellule de grille, `row-span-2` fonctionne à nouveau
* Label désactivé en `text-m-muted` (gris des bordures) au lieu de `text-black/60` sur les inputs à floating-label (InputText, Email, Password, Amount, Phone, Upload, Autocomplete, TextArea, RichText)
* InputAutocomplete : suppression de 4 sources de saut visuel au focus / ouverture (extra translate label, padding `grow-height:focus`, `focus:pl-[11px]`, `!border-b-0` remplacé par `!border-b-transparent`)
* Select / SelectCheckbox : mêmes correctifs anti-saut (suppression du padding `grow-height:focus` et remplacement de `!border-b-0` / `!border-t-0` par leurs variantes `transparent`)
* MalioButton : largeur par défaut alignée sur `w-[200px]` (au lieu de `w-[240px]`) pour correspondre au sizing des formulaires de l'app
* [#MUI-42] RadioButton : ajout d'un focus visible au clavier (`outline` 2px `m-primary`, offset 2px) — l'input en `appearance-none` n'avait aucun indicateur de focus, seul l'`outline: auto 1px` du navigateur restait, quasi invisible. La navigation native (Tab entre groupes, flèches dans le groupe) reste inchangée
* [#MUI-42] Checkbox : ajout d'un focus visible au clavier sur la case (`outline` 2px `m-primary`, offset 2px) — l'input réel est masqué (`clip-path`), aucun indicateur n'apparaissait à la tabulation
* [#MUI-42] Select : le focus reste sur le bouton après sélection (un `blur()` renvoyait le focus au `body`, cassant la tabulation clavier — un Tab repartait du haut de page)