origam 2.18.0 → 2.18.1

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/CHANGELOG.md CHANGED
@@ -16,6 +16,212 @@ This project follows [Semantic Versioning](https://semver.org).
16
16
 
17
17
  ---
18
18
 
19
+ ## [Unreleased]
20
+
21
+ Récolte de deux dépréciations posées "pour la prochaine majeure" avant que le
22
+ `CLAUDE.md` n'acte que `3.0.0` est réservé à la séparation en modules et que
23
+ les ruptures, elles, ne le sont pas — voir "Work priorities and versioning"
24
+ du `CLAUDE.md`. `origam` n'a aucun consommateur : les deux ruptures
25
+ ci-dessous partent en **mineure**, sans shim ni période de grâce.
26
+
27
+ ### ⚠️ BREAKING — `click:prepend` / `click:append` retirés d'`IBtnEmits` (#443, #577)
28
+
29
+ `<OrigamBtn>` n'émet plus `click:prepend` ni `click:append` — ni au niveau du
30
+ type, ni au niveau de l'exécution. `IBtnEmits` n'`extends` plus
31
+ `IAdjacentEmits`, et les `<span>` `origam-btn__prepend` / `__append` ne
32
+ portent plus de `@click` du tout : un clic souris dessus ne déclenche plus
33
+ rien.
34
+
35
+ **Pourquoi cette paire précisément, et pourquoi une suppression plutôt qu'un
36
+ correctif.** Les deux émissions n'ont jamais été atteignables au clavier :
37
+ l'événement partait d'un `<span>` descendant, alors qu'une activation clavier
38
+ synthétise son clic sur la RACINE du composant — l'écouteur posé sur le
39
+ descendant ne le voit jamais. Le correctif générique appliqué aux dix autres
40
+ consommateurs d'`useAdjacent` (promouvoir la zone en `role="button"` + arrêt
41
+ de tabulation) est **illégal** ici : `<OrigamBtn>` rend un `<button>` ou un
42
+ `<a>`, et le modèle de contenu HTML interdit à tous deux un descendant de
43
+ contenu interactif *et* tout descendant portant `tabindex`. Un
44
+ `<button type="button">` imbriqué y est tout aussi invalide. La forme était
45
+ fausse, pas seulement le balisage : un contrôle qui possède déjà une action
46
+ ne peut pas en héberger une seconde — deux actions sont deux boutons,
47
+ composés via `<origam-btn-group>`.
48
+
49
+ **Ce qui NE bouge PAS** : les slots `prepend` / `append` (`IBtnSlots extends
50
+ IAdjacentSlots`) restent intacts, ainsi que les props `prependIcon` /
51
+ `appendIcon` / `prependAvatar` / `appendAvatar` — un contenu décoratif ou
52
+ informationnel en prepend/append reste parfaitement légitime, seule
53
+ l'émission d'un clic disparaît.
54
+
55
+ **Preuve du comportement retiré** — A/B contre le commit parent, fonctionnel
56
+ et pas seulement typé : `packages/tests/TU/components/Btn/OrigamBtn.adjacent-emit-removed.spec.ts`
57
+ monte `<OrigamBtn>` avec un écouteur `onClick:prepend` / `onClick:append` et
58
+ déclenche un vrai `click` DOM sur la zone. Sur le commit parent, ce même test
59
+ appellerait l'écouteur (l'émission déclarée par `IAdjacentEmits` partait
60
+ encore) ; sur ce commit, l'écouteur n'est jamais invoqué — vérifié en
61
+ rejouant le fichier de spec avant/après le changement, pas seulement en le
62
+ lisant une fois vert.
63
+
64
+ Nettoyage induit : le helper `warnDeprecatedEmit` (`color.util.ts`) et la
65
+ constante `ADJACENT_EMIT_REPLACEMENT` (`consts/Btn/btn.const.ts`) sont
66
+ retirés — `<OrigamBtn>` était leur seul appelant, et le fichier `btn.const.ts`
67
+ devenu vide est supprimé.
68
+
69
+ **Migration.** Aucun consommateur interne (DS, marketing, stories, docs,
70
+ tests) n'utilisait `click:prepend` / `click:append` sur `<OrigamBtn>` —
71
+ balayage exhaustif, zéro résultat. Un consommateur externe qui les écoutait
72
+ doit remplacer l'action posée sur la zone prepend/append par un second
73
+ `<origam-btn>` dans un `<origam-btn-group>`.
74
+
75
+ ### ⚠️ BREAKING — `createOrigam()` nu n'installe plus le thème par défaut (#360)
76
+
77
+ `createOrigam()` préfixait inconditionnellement chaque install avec le thème
78
+ neutre interne `origamTheme` (`[...origamTheme, ...suppliedThemes]`) : même un
79
+ appel nu, ou un `themes: []` explicite, recevait quand même les variables CSS
80
+ et — surtout — les **props par défaut par composant** (ADR-005,
81
+ `components: { 'origam-avatar': { rounded: 'full' }, … }`) de ce thème. Une
82
+ application qui n'en voulait pas ne pouvait pas s'en défaire. Ce préfixage est
83
+ retiré : `createOrigam()` installe désormais exactement ce qu'on lui passe,
84
+ rien de plus.
85
+
86
+ **Ce qui change concrètement.** Sans `themes`/`theme` explicite,
87
+ `createOrigam()` n'injecte plus aucune variable `--origam-*` et le résolveur
88
+ de props par défaut (`installThemePropsResolver`, ADR-005) n'a plus rien à
89
+ résoudre — chaque composant retombe uniquement sur ses propres valeurs
90
+ `withDefaults()`. Concrètement : un `<origam-avatar>` sans prop `rounded`
91
+ explicite n'est plus automatiquement circulaire (`rounded="full"` venait du
92
+ thème, pas du composant).
93
+
94
+ **Le thème par défaut reste disponible, à la demande** — `origamTheme`,
95
+ exporté par `origam/themes` (déjà public avant cette rupture, aucun nouvel
96
+ export nécessaire) :
97
+
98
+ ```ts
99
+ // AVANT (2.x) — enregistrait implicitement le thème origam par défaut
100
+ import { createOrigam } from 'origam'
101
+ app.use(createOrigam())
102
+
103
+ // APRÈS — le thème par défaut est un choix explicite
104
+ import { createOrigam } from 'origam'
105
+ import { origamTheme } from 'origam/themes'
106
+ app.use(createOrigam({ themes: origamTheme }))
107
+ ```
108
+
109
+ **Rayon de souffle mesuré, corrigé dans le même lot** — quatre consommateurs
110
+ directs de `createOrigam()` nu trouvés par balayage exhaustif (DS, marketing,
111
+ stories, docs, tests) :
112
+ - `packages/ds/src/nuxt/module.ts` — le module Nuxt officiel. **Non cassé** :
113
+ son propre `DEFAULT_THEMES` (utilisé quand l'option `origam.themes` du
114
+ consommateur est omise) passe désormais `origamTheme` explicitement à
115
+ `createOrigam()`, préservant à l'identique le comportement de tout
116
+ consommateur Nuxt existant (marketing compris) qui ne configurait rien.
117
+ Seul un `createOrigam()` direct, hors module Nuxt, doit s'adapter.
118
+ - `packages/marketing/nuxt.config.ts` — configure `origam.themes`
119
+ explicitement (7 thèmes de marque + un thème `origam` renommé pour le
120
+ playground `/theming`), ce qui **contourne** le fallback du module. Le vrai
121
+ thème neutre non-nommé (celui que `activeDefaultsFor` fusionne toujours en
122
+ premier, avant la marque active) était fourni jusqu'ici par le préfixage
123
+ implicite de `createOrigam()` — invisible dans la config marketing. Il est
124
+ désormais listé explicitement, en premier, dans le tableau `themes`.
125
+ - `packages/stories/histoire.setup.ts` — Histoire (utilisé par les ~208
126
+ stories de composants) appelait `createOrigam()` nu ; sans correction,
127
+ chaque story aurait silencieusement perdu les props par défaut du thème
128
+ (avatars carrés au lieu de circulaires, etc.). Passe désormais
129
+ `{ themes: origamTheme }`.
130
+ - `packages/docs/.vitepress/theme/index.ts` — les démos de composants live de
131
+ la doc VitePress appelaient `createOrigam()` nu ; même correction.
132
+
133
+ Les échantillons de code montrés au consommateur (`installation.const.ts` /
134
+ `installation.vue` sur le marketing, `guide/usage.md` côté docs) sont mis à
135
+ jour pour montrer la forme correcte — un utilisateur copiant l'ancien
136
+ exemple aurait obtenu des composants non stylés selon le thème.
137
+
138
+ **Tests adaptés** (comptés avant correction, comme demandé) — 3 fichiers /
139
+ 5 assertions reposaient sur l'enregistrement implicite et ont été corrigés
140
+ pour installer `origamTheme` explicitement là où le test vérifie précisément
141
+ une valeur par défaut issue du thème, ou réécrits pour pinner le NOUVEAU
142
+ contrat plutôt que l'ancien :
143
+ - `theme-props-resolver.spec.ts` (2 assertions — `origam-radio`/`origam-text-field`
144
+ vs `origam-input` density) ;
145
+ - `installed-themes.composable.spec.ts` (describe block entier renommé
146
+ `origam baseline — explicit opt-in only (#360)`, 2 assertions corrigées et
147
+ 2 nouvelles ajoutées pour couvrir explicitement le nouveau contrat) ;
148
+ - `OrigamChip.spec.ts` (1 assertion — `components['origam-chip'].size`).
149
+
150
+ **Preuve fonctionnelle** (pas seulement structurelle) —
151
+ `packages/tests/TU/origam/createOrigam-bare-no-theme-360.spec.ts` monte un
152
+ vrai `<OrigamAvatar>` : sans thème, la classe `origam--rounded-full` est
153
+ absente ; avec `origamTheme` passé explicitement, elle est présente — la
154
+ même monteuse prouve donc que le harnais peut actionner la prop avant de
155
+ conclure qu'elle ne l'est plus par défaut.
156
+
157
+ ### Fixed
158
+
159
+ - **#871 — le mode sombre ne peignait qu'à moitié dans un sous-arbre thémé.**
160
+ Les feuilles de tokens portent ~1 761 déclarations **dérivées**
161
+ (`--origam-title---color: var(--origam-color__text---primary)`). Une custom
162
+ property est substituée **sur l'élément qui la déclare** ; ce qu'un
163
+ descendant hérite est la valeur DÉJÀ substituée. Le bloc sombre étant ancré
164
+ à la racine (`:root:not([data-theme])[data-mode="dark"]`), un sous-arbre
165
+ `<OrigamThemeProvider mode="dark">` basculait bien les ~60 tokens
166
+ sémantiques — le bloc runtime, lui, émet `[data-mode="dark"]` — mais laissait
167
+ les 1 761 dérivés **gelés** sur les valeurs claires de la racine. Motif
168
+ dominant mesuré : `rgb(10,10,10)` sur `rgb(10,10,10)`, texte et fond
169
+ identiques.
170
+
171
+ Les deux feuilles s'accrochent désormais aussi à l'axe `data-mode` :
172
+
173
+ ```css
174
+ :root, [data-theme="light"], [data-mode="light"] { /* clair */ }
175
+ [data-theme="dark"], [data-mode="dark"]:not([data-theme="light"]) { /* sombre */ }
176
+ ```
177
+
178
+ Rejoué sur 30 composants × 8 identités × 2 modes × 2 portées (racine ET
179
+ sous-arbre), soit **1 664 instances**, Chromium, contrôles positif et négatif
180
+ verts : **189 → 11 violations AA**, dont sombre **184 → 6** et clair
181
+ **5 → 5** (aucune régression). Les 11 restantes appartiennent toutes aux
182
+ palettes de marque de `packages/marketing`, aucune au DS. Harnais :
183
+ `pnpm -F @origam/tests audit:dark-contrast`.
184
+
185
+ - **#871 — `system-bar` et `tooltip` illisibles en sombre.** Les deux peignent
186
+ une surface sombre dans les DEUX modes (`neutral---700` / `neutral---800`)
187
+ et lisaient `text---inverse`, qui vaut blanc en clair et **encre** en
188
+ sombre : 1.91:1 et 1.31:1. `dark.css` lit maintenant `text---primary` ;
189
+ `light.css` est inchangé.
190
+
191
+ - **#871 — `bottom-nav` peignait une dalle claire dans une UI sombre.** Son
192
+ fond était épinglé à la primitive `neutral---200` (#e6e6e6) dans les deux
193
+ modes, sous un `text---primary` presque blanc (1.03:1). En sombre il passe
194
+ au token sémantique `surface---overlay`. Le clair est inchangé.
195
+
196
+ ### Changed — ⛔ RUPTURE (documentée, assumée)
197
+
198
+ - **Les feuilles de tokens ne sont plus ancrées à `:root`.** Un consommateur
199
+ qui avait contourné le gel ci-dessus en re-déclarant lui-même des variables
200
+ de composant dans un sous-arbre `[data-mode]` voit désormais la feuille les
201
+ déclarer aussi, en (0,1,0) côté clair et (0,2,0) côté sombre. Son bloc de
202
+ contournement doit donc être au moins aussi spécifique, ou être retiré.
203
+
204
+ Concrètement dans ce dépôt : `packages/marketing` embarque
205
+ `ORIGAM_COMPONENT_RESET_LIGHT/DARK` (`themes/origam-reset.generated.ts`),
206
+ une re-déclaration GÉNÉRÉE de ~2 700 variables de composant, écrite
207
+ exactement pour ce défaut. Elle est maintenant redondante — **elle n'a pas
208
+ été retirée ici**, faute de mesure sur le rendu du site.
209
+
210
+ Ce qui NE change pas : `data-theme="light" data-mode="dark"` reste clair
211
+ (l'axe marque gouverne quand les deux se contredisent, règle #807),
212
+ `data-mode="light"` sous un OS sombre reste clair (#794), et une marque
213
+ claire continue de gagner sur la feuille par l'ordre source.
214
+
215
+ ### Documentation
216
+
217
+ - `CLAUDE.md`, section *Multi-theme* : la note qui affirmait que le bloc
218
+ auto-mode ne porte que **11** déclarations est **fausse** — recompté en
219
+ parsant la feuille le 2026-09-22, les deux blocs en portent **2 731**
220
+ chacun. L'affirmation décrivait un état antérieur à #794 que plus rien ne
221
+ remesurait.
222
+
223
+ ---
224
+
19
225
  ## [2.18.0] - 2026-09-19
20
226
 
21
227
  80 commits depuis `v2.17.1`. L'essentiel est du **correctif** : des tokens qui