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.
@@ -64,10 +64,41 @@
64
64
  * que soit `prefers-color-scheme`) tandis que le bloc média ne s'active que
65
65
  * si NI `data-theme` NI `data-mode` ne sont posés. Ne pas les fusionner.
66
66
  *
67
- * ⛔ Le deuxième bloc (media query, "AUTO mode") reste volontairement un
68
- * SOUS-ENSEMBLE de 11 déclarations, pas une copie complète des 2731 du bloc
69
- * 1 — c'est un fait préexistant à #807, non réévalué ici, et hors périmètre
70
- * de ce ticket.
67
+ * ⚠️ Cette phrase disait « le deuxième bloc reste volontairement un
68
+ * SOUS-ENSEMBLE de 11 déclarations ». C'est FAUX depuis #794 : recompté le
69
+ * 2026-09-22 en parsant la feuille, les deux blocs portent **2731
70
+ * déclarations chacun**. La note décrivait un état antérieur que plus rien ne
71
+ * remesurait.
72
+ *
73
+ * ── #871 — POURQUOI `[data-mode="dark"]` REMPLACE `:root:not([data-theme])…` ─
74
+ * Le sélecteur précédent, `:root:not([data-theme])[data-mode="dark"]`, était
75
+ * ancré à la RACINE. Or les ~1 761 déclarations DÉRIVÉES de ce bloc
76
+ * (`--origam-title---color: var(--origam-color__text---primary)`) ne se
77
+ * ré-évaluent QUE sur un élément que le sélecteur matche : ailleurs, la
78
+ * valeur héritée est déjà SUBSTITUÉE. Un sous-arbre
79
+ * `<OrigamThemeProvider mode="dark">` — avec ou sans marque —
80
+ * basculait donc bien les ~60 tokens sémantiques (bloc runtime
81
+ * `[data-mode="dark"]` / `[data-theme="X"][data-mode="dark"]`) mais gardait
82
+ * les 1 761 dérivés GELÉS sur les valeurs CLAIRES de la racine. D'où le motif
83
+ * dominant de #871 : `rgb(10,10,10)` sur `rgb(10,10,10)`, texte et fond
84
+ * identiques.
85
+ *
86
+ * `[data-mode="dark"]` matche aussi bien la racine que n'importe quel
87
+ * sous-arbre, et subsume donc l'ancien sélecteur (une racine sans
88
+ * `data-theme` portant `data-mode="dark"` le matche).
89
+ *
90
+ * ⛔ Le `:not([data-theme="light"])` n'est PAS décoratif : il préserve la
91
+ * règle de #807 — « la marque gouverne dès qu'elle est posée » — pour la
92
+ * seule combinaison où les deux axes se contredisent,
93
+ * `data-theme="light" data-mode="dark"`, épinglée par le contrôle négatif de
94
+ * `packages/tests/e2e/tokens-prefers-color-scheme.spec.ts`.
95
+ *
96
+ * ⛔ Spécificité (0,2,0). Elle doit rester ≥ celle de `light.css`
97
+ * (`:root` / `[data-theme="light"]` / `[data-mode="light"]`, toutes (0,1,0))
98
+ * et ≤ celle du bloc runtime d'une marque sombre
99
+ * (`[data-theme="X"][data-mode="dark"]`, (0,2,0), injecté plus tard donc
100
+ * gagnant à égalité). Monter ou descendre ce sélecteur casse l'un des deux
101
+ * côtés.
71
102
  *
72
103
  * ⛔ The two blocks carry the SAME declarations, and this file is BYTE-IDENTICAL
73
104
  * to its twin — the whole file, header included. The pair is
@@ -103,9 +134,46 @@
103
134
  *
104
135
  * Mesure, témoins et non-régression :
105
136
  * `packages/tests/e2e/token-intent-contrast.spec.ts`.
137
+ *
138
+ * ── #871 — SURFACE QUI NE BASCULE PAS × PREMIER PLAN QUI BASCULE ───────────
139
+ * Deuxième famille de défauts trouvée en rejouant le chiffrage, INDÉPENDANTE
140
+ * du mécanisme de sélecteur ci-dessus : elle se voit aussi bien en theming
141
+ * RACINE qu'en sous-arbre.
142
+ *
143
+ * `--origam-color__text---inverse` est défini comme l'opposé de
144
+ * `text---primary` : blanc en clair, encre en sombre. Posé sur une surface
145
+ * qui, elle, est épinglée à une PRIMITIVE (donc identique dans les deux
146
+ * modes), il est correct en clair et illisible en sombre :
147
+ *
148
+ * system-bar fond neutral-700 (#404040) · fg text---inverse → 1.91:1
149
+ * tooltip fond neutral-800 (#262626) · fg text---inverse → 1.31:1
150
+ *
151
+ * Le correctif se fait DANS CETTE FEUILLE UNIQUEMENT : `text---primary`, qui
152
+ * est clair en sombre par définition, sur une surface sombre. `light.css`
153
+ * n'est pas touché et garde `text---inverse`, qui y vaut blanc.
154
+ *
155
+ * ⛔ Premier essai, ÉCARTÉ PAR LA MESURE : passer les deux feuilles à
156
+ * `text---onColor`. Blanc dans les deux modes pour l'identité native, donc
157
+ * NO-OP apparent en clair — sauf qu'une marque est libre de redéfinir
158
+ * `onColor`, et `cartoon` le pose à `#3a2a2e` (brun foncé). Le « no-op » a
159
+ * mesuré **+2 violations en mode CLAIR** (system-bar cartoon, 1.31:1). La
160
+ * leçon vaut au-delà de ce ticket : sur cette famille, un token sémantique
161
+ * n'est jamais « le même dans les deux modes » — seules les 8 identités
162
+ * mesurées le disent.
163
+ *
164
+ * Symétriquement, `--origam-bottom-nav---background` était épinglé à
165
+ * `neutral---200` (#e6e6e6) dans les DEUX modes : une dalle claire au milieu
166
+ * d'une UI sombre, avec un `text---primary` presque blanc par-dessus
167
+ * (1.03:1). Il passe au token sémantique `surface---overlay`, qui bascule.
168
+ * Le bloc clair n'est pas touché.
169
+ *
170
+ * ⚠️ Non traité ici : `video__controls`, `video--error`, `audio__cover-label`,
171
+ * `media-scrubber__tooltip`, `media-volume-control__tooltip` sont eux aussi
172
+ * épinglés à une primitive neutre sombre — mais leur premier plan ne bascule
173
+ * pas, donc aucun d'eux n'est ressorti de la mesure. Non vérifié un par un.
106
174
  */
107
175
  [data-theme="dark"],
108
- :root:not([data-theme])[data-mode="dark"] {
176
+ [data-mode="dark"]:not([data-theme="light"]) {
109
177
  --origam-color__surface---default: var(--origam-color__neutral---950);
110
178
  --origam-color__surface---raised: var(--origam-color__neutral---900);
111
179
  --origam-color__surface---overlay: var(--origam-color__neutral---800);
@@ -675,7 +743,7 @@
675
743
  --origam-bottom-nav---density: 0px;
676
744
  --origam-bottom-nav---max-width: 100%;
677
745
  --origam-bottom-nav---height: var(--origam-space---12);
678
- --origam-bottom-nav---background: var(--origam-color__neutral---200);
746
+ --origam-bottom-nav---background: var(--origam-color__surface---overlay);
679
747
  --origam-bottom-nav---color: var(--origam-color__text---primary);
680
748
  --origam-bottom-nav---box-shadow: var(--origam-shadow---none);
681
749
  --origam-bottom-nav---padding-block-start: var(--origam-space---2);
@@ -945,7 +1013,7 @@
945
1013
  --origam-system-bar---height-window: 32px;
946
1014
  --origam-system-bar---padding-inline: var(--origam-space---2);
947
1015
  --origam-system-bar---background: var(--origam-color__neutral---700);
948
- --origam-system-bar---color: var(--origam-color__text---inverse);
1016
+ --origam-system-bar---color: var(--origam-color__text---primary);
949
1017
  --origam-system-bar---font-size: var(--origam-font__size---sm);
950
1018
  --origam-system-bar---font-weight: var(--origam-font__weight---regular);
951
1019
  --origam-system-bar---letter-spacing: var(--origam-font__letterSpacing---wide);
@@ -1463,7 +1531,7 @@
1463
1531
  --origam-menu---offset-left: var(--origam-space---0);
1464
1532
  --origam-menu---offset-right: var(--origam-space---0);
1465
1533
  --origam-tooltip---background-color: var(--origam-color__neutral---800);
1466
- --origam-tooltip---color: var(--origam-color__text---inverse);
1534
+ --origam-tooltip---color: var(--origam-color__text---primary);
1467
1535
  --origam-tooltip---backdrop-filter: none;
1468
1536
  --origam-tooltip---font-size: var(--origam-font__size---sm);
1469
1537
  --origam-tooltip---font-weight: var(--origam-font__weight---medium);
@@ -3411,7 +3479,7 @@
3411
3479
  --origam-bottom-nav---density: 0px;
3412
3480
  --origam-bottom-nav---max-width: 100%;
3413
3481
  --origam-bottom-nav---height: var(--origam-space---12);
3414
- --origam-bottom-nav---background: var(--origam-color__neutral---200);
3482
+ --origam-bottom-nav---background: var(--origam-color__surface---overlay);
3415
3483
  --origam-bottom-nav---color: var(--origam-color__text---primary);
3416
3484
  --origam-bottom-nav---box-shadow: var(--origam-shadow---none);
3417
3485
  --origam-bottom-nav---padding-block-start: var(--origam-space---2);
@@ -3681,7 +3749,7 @@
3681
3749
  --origam-system-bar---height-window: 32px;
3682
3750
  --origam-system-bar---padding-inline: var(--origam-space---2);
3683
3751
  --origam-system-bar---background: var(--origam-color__neutral---700);
3684
- --origam-system-bar---color: var(--origam-color__text---inverse);
3752
+ --origam-system-bar---color: var(--origam-color__text---primary);
3685
3753
  --origam-system-bar---font-size: var(--origam-font__size---sm);
3686
3754
  --origam-system-bar---font-weight: var(--origam-font__weight---regular);
3687
3755
  --origam-system-bar---letter-spacing: var(--origam-font__letterSpacing---wide);
@@ -4199,7 +4267,7 @@
4199
4267
  --origam-menu---offset-left: var(--origam-space---0);
4200
4268
  --origam-menu---offset-right: var(--origam-space---0);
4201
4269
  --origam-tooltip---background-color: var(--origam-color__neutral---800);
4202
- --origam-tooltip---color: var(--origam-color__text---inverse);
4270
+ --origam-tooltip---color: var(--origam-color__text---primary);
4203
4271
  --origam-tooltip---backdrop-filter: none;
4204
4272
  --origam-tooltip---font-size: var(--origam-font__size---sm);
4205
4273
  --origam-tooltip---font-weight: var(--origam-font__weight---medium);
@@ -30,9 +30,40 @@
30
30
  * palette primitive (son `blue---600` vaut `#1d4ed8`, soit le 700 de
31
31
  * Tailwind). La valeur est celle de `origam.theme.ts`, ce qui ferme du même
32
32
  * coup la divergence feuille ↔ thème que #793 suit.
33
+ *
34
+ * ── #871 — POURQUOI `[data-mode="light"]` DANS LA LISTE ────────────────────
35
+ * Les ~1 792 déclarations DÉRIVÉES de ce bloc — la forme
36
+ * `--origam-title---color: var(--origam-color__text---primary)` —
37
+ * ne se ré-évaluent QUE sur un élément que ce sélecteur matche. Sur tout autre
38
+ * élément, la valeur héritée est déjà SUBSTITUÉE — c'est la sémantique des
39
+ * custom properties, pas un bug : `--a: var(--b)` posé à `:root`, `--b`
40
+ * réécrit sur un enfant, et `--a` garde sur l'enfant la valeur calculée à la
41
+ * racine.
42
+ *
43
+ * Sans `[data-mode="light"]`, un sous-arbre `<OrigamThemeProvider mode="light">`
44
+ * à l'intérieur d'une page sombre gardait donc les 1 792 dérivés GELÉS sur les
45
+ * valeurs sombres de la racine. C'est le pendant clair du défaut mesuré en
46
+ * sombre par #871.
47
+ *
48
+ * ⛔ SPÉCIFICITÉ (0,1,0), VOLONTAIREMENT. Le bloc runtime d'une marque claire
49
+ * (`applyThemes()` sérialise `[data-theme="cartoon"]` sans `data-mode`) est
50
+ * lui aussi (0,1,0) et est injecté dans `<head>` APRÈS cette feuille : à
51
+ * égalité, l'ordre source tranche et la marque gagne. Monter ce sélecteur à
52
+ * (0,2,0) (p. ex. `[data-mode="light"]:not([data-theme="dark"])`) le ferait
53
+ * perdre, et cette feuille repeindrait par-dessus chaque marque claire.
54
+ *
55
+ * ── #871 — `system-bar` / `tooltip` : RIEN NE CHANGE ICI ──────────────────
56
+ * Ces deux composants peignent une surface SOMBRE dans les deux modes
57
+ * (`neutral---700` / `neutral---800`) et lisent `text---inverse`, qui vaut
58
+ * blanc EN CLAIR — correct, donc inchangé. C'est en SOMBRE que le même token
59
+ * vaut de l'encre et rend le texte illisible ; le correctif est donc dans
60
+ * `dark.css` seul. Voir son en-tête, y compris la piste écartée (passer les
61
+ * DEUX feuilles à `text---onColor`, qui a mesuré +2 violations en clair sur
62
+ * la marque `cartoon`).
33
63
  */
34
64
  :root,
35
- [data-theme="light"] {
65
+ [data-theme="light"],
66
+ [data-mode="light"] {
36
67
  --origam-color__surface---default: var(--origam-color__neutral---0);
37
68
  --origam-color__surface---raised: var(--origam-color__neutral---0);
38
69
  --origam-color__surface---overlay: var(--origam-color__neutral---100);
@@ -64,10 +64,41 @@
64
64
  * que soit `prefers-color-scheme`) tandis que le bloc média ne s'active que
65
65
  * si NI `data-theme` NI `data-mode` ne sont posés. Ne pas les fusionner.
66
66
  *
67
- * ⛔ Le deuxième bloc (media query, "AUTO mode") reste volontairement un
68
- * SOUS-ENSEMBLE de 11 déclarations, pas une copie complète des 2731 du bloc
69
- * 1 — c'est un fait préexistant à #807, non réévalué ici, et hors périmètre
70
- * de ce ticket.
67
+ * ⚠️ Cette phrase disait « le deuxième bloc reste volontairement un
68
+ * SOUS-ENSEMBLE de 11 déclarations ». C'est FAUX depuis #794 : recompté le
69
+ * 2026-09-22 en parsant la feuille, les deux blocs portent **2731
70
+ * déclarations chacun**. La note décrivait un état antérieur que plus rien ne
71
+ * remesurait.
72
+ *
73
+ * ── #871 — POURQUOI `[data-mode="dark"]` REMPLACE `:root:not([data-theme])…` ─
74
+ * Le sélecteur précédent, `:root:not([data-theme])[data-mode="dark"]`, était
75
+ * ancré à la RACINE. Or les ~1 761 déclarations DÉRIVÉES de ce bloc
76
+ * (`--origam-title---color: var(--origam-color__text---primary)`) ne se
77
+ * ré-évaluent QUE sur un élément que le sélecteur matche : ailleurs, la
78
+ * valeur héritée est déjà SUBSTITUÉE. Un sous-arbre
79
+ * `<OrigamThemeProvider mode="dark">` — avec ou sans marque —
80
+ * basculait donc bien les ~60 tokens sémantiques (bloc runtime
81
+ * `[data-mode="dark"]` / `[data-theme="X"][data-mode="dark"]`) mais gardait
82
+ * les 1 761 dérivés GELÉS sur les valeurs CLAIRES de la racine. D'où le motif
83
+ * dominant de #871 : `rgb(10,10,10)` sur `rgb(10,10,10)`, texte et fond
84
+ * identiques.
85
+ *
86
+ * `[data-mode="dark"]` matche aussi bien la racine que n'importe quel
87
+ * sous-arbre, et subsume donc l'ancien sélecteur (une racine sans
88
+ * `data-theme` portant `data-mode="dark"` le matche).
89
+ *
90
+ * ⛔ Le `:not([data-theme="light"])` n'est PAS décoratif : il préserve la
91
+ * règle de #807 — « la marque gouverne dès qu'elle est posée » — pour la
92
+ * seule combinaison où les deux axes se contredisent,
93
+ * `data-theme="light" data-mode="dark"`, épinglée par le contrôle négatif de
94
+ * `packages/tests/e2e/tokens-prefers-color-scheme.spec.ts`.
95
+ *
96
+ * ⛔ Spécificité (0,2,0). Elle doit rester ≥ celle de `light.css`
97
+ * (`:root` / `[data-theme="light"]` / `[data-mode="light"]`, toutes (0,1,0))
98
+ * et ≤ celle du bloc runtime d'une marque sombre
99
+ * (`[data-theme="X"][data-mode="dark"]`, (0,2,0), injecté plus tard donc
100
+ * gagnant à égalité). Monter ou descendre ce sélecteur casse l'un des deux
101
+ * côtés.
71
102
  *
72
103
  * ⛔ The two blocks carry the SAME declarations, and this file is BYTE-IDENTICAL
73
104
  * to its twin — the whole file, header included. The pair is
@@ -103,9 +134,46 @@
103
134
  *
104
135
  * Mesure, témoins et non-régression :
105
136
  * `packages/tests/e2e/token-intent-contrast.spec.ts`.
137
+ *
138
+ * ── #871 — SURFACE QUI NE BASCULE PAS × PREMIER PLAN QUI BASCULE ───────────
139
+ * Deuxième famille de défauts trouvée en rejouant le chiffrage, INDÉPENDANTE
140
+ * du mécanisme de sélecteur ci-dessus : elle se voit aussi bien en theming
141
+ * RACINE qu'en sous-arbre.
142
+ *
143
+ * `--origam-color__text---inverse` est défini comme l'opposé de
144
+ * `text---primary` : blanc en clair, encre en sombre. Posé sur une surface
145
+ * qui, elle, est épinglée à une PRIMITIVE (donc identique dans les deux
146
+ * modes), il est correct en clair et illisible en sombre :
147
+ *
148
+ * system-bar fond neutral-700 (#404040) · fg text---inverse → 1.91:1
149
+ * tooltip fond neutral-800 (#262626) · fg text---inverse → 1.31:1
150
+ *
151
+ * Le correctif se fait DANS CETTE FEUILLE UNIQUEMENT : `text---primary`, qui
152
+ * est clair en sombre par définition, sur une surface sombre. `light.css`
153
+ * n'est pas touché et garde `text---inverse`, qui y vaut blanc.
154
+ *
155
+ * ⛔ Premier essai, ÉCARTÉ PAR LA MESURE : passer les deux feuilles à
156
+ * `text---onColor`. Blanc dans les deux modes pour l'identité native, donc
157
+ * NO-OP apparent en clair — sauf qu'une marque est libre de redéfinir
158
+ * `onColor`, et `cartoon` le pose à `#3a2a2e` (brun foncé). Le « no-op » a
159
+ * mesuré **+2 violations en mode CLAIR** (system-bar cartoon, 1.31:1). La
160
+ * leçon vaut au-delà de ce ticket : sur cette famille, un token sémantique
161
+ * n'est jamais « le même dans les deux modes » — seules les 8 identités
162
+ * mesurées le disent.
163
+ *
164
+ * Symétriquement, `--origam-bottom-nav---background` était épinglé à
165
+ * `neutral---200` (#e6e6e6) dans les DEUX modes : une dalle claire au milieu
166
+ * d'une UI sombre, avec un `text---primary` presque blanc par-dessus
167
+ * (1.03:1). Il passe au token sémantique `surface---overlay`, qui bascule.
168
+ * Le bloc clair n'est pas touché.
169
+ *
170
+ * ⚠️ Non traité ici : `video__controls`, `video--error`, `audio__cover-label`,
171
+ * `media-scrubber__tooltip`, `media-volume-control__tooltip` sont eux aussi
172
+ * épinglés à une primitive neutre sombre — mais leur premier plan ne bascule
173
+ * pas, donc aucun d'eux n'est ressorti de la mesure. Non vérifié un par un.
106
174
  */
107
175
  [data-theme="dark"],
108
- :root:not([data-theme])[data-mode="dark"] {
176
+ [data-mode="dark"]:not([data-theme="light"]) {
109
177
  --origam-color__surface---default: var(--origam-color__neutral---950);
110
178
  --origam-color__surface---raised: var(--origam-color__neutral---900);
111
179
  --origam-color__surface---overlay: var(--origam-color__neutral---800);
@@ -675,7 +743,7 @@
675
743
  --origam-bottom-nav---density: 0px;
676
744
  --origam-bottom-nav---max-width: 100%;
677
745
  --origam-bottom-nav---height: var(--origam-space---12);
678
- --origam-bottom-nav---background: var(--origam-color__neutral---200);
746
+ --origam-bottom-nav---background: var(--origam-color__surface---overlay);
679
747
  --origam-bottom-nav---color: var(--origam-color__text---primary);
680
748
  --origam-bottom-nav---box-shadow: var(--origam-shadow---none);
681
749
  --origam-bottom-nav---padding-block-start: var(--origam-space---2);
@@ -945,7 +1013,7 @@
945
1013
  --origam-system-bar---height-window: 32px;
946
1014
  --origam-system-bar---padding-inline: var(--origam-space---2);
947
1015
  --origam-system-bar---background: var(--origam-color__neutral---700);
948
- --origam-system-bar---color: var(--origam-color__text---inverse);
1016
+ --origam-system-bar---color: var(--origam-color__text---primary);
949
1017
  --origam-system-bar---font-size: var(--origam-font__size---sm);
950
1018
  --origam-system-bar---font-weight: var(--origam-font__weight---regular);
951
1019
  --origam-system-bar---letter-spacing: var(--origam-font__letterSpacing---wide);
@@ -1463,7 +1531,7 @@
1463
1531
  --origam-menu---offset-left: var(--origam-space---0);
1464
1532
  --origam-menu---offset-right: var(--origam-space---0);
1465
1533
  --origam-tooltip---background-color: var(--origam-color__neutral---800);
1466
- --origam-tooltip---color: var(--origam-color__text---inverse);
1534
+ --origam-tooltip---color: var(--origam-color__text---primary);
1467
1535
  --origam-tooltip---backdrop-filter: none;
1468
1536
  --origam-tooltip---font-size: var(--origam-font__size---sm);
1469
1537
  --origam-tooltip---font-weight: var(--origam-font__weight---medium);
@@ -3411,7 +3479,7 @@
3411
3479
  --origam-bottom-nav---density: 0px;
3412
3480
  --origam-bottom-nav---max-width: 100%;
3413
3481
  --origam-bottom-nav---height: var(--origam-space---12);
3414
- --origam-bottom-nav---background: var(--origam-color__neutral---200);
3482
+ --origam-bottom-nav---background: var(--origam-color__surface---overlay);
3415
3483
  --origam-bottom-nav---color: var(--origam-color__text---primary);
3416
3484
  --origam-bottom-nav---box-shadow: var(--origam-shadow---none);
3417
3485
  --origam-bottom-nav---padding-block-start: var(--origam-space---2);
@@ -3681,7 +3749,7 @@
3681
3749
  --origam-system-bar---height-window: 32px;
3682
3750
  --origam-system-bar---padding-inline: var(--origam-space---2);
3683
3751
  --origam-system-bar---background: var(--origam-color__neutral---700);
3684
- --origam-system-bar---color: var(--origam-color__text---inverse);
3752
+ --origam-system-bar---color: var(--origam-color__text---primary);
3685
3753
  --origam-system-bar---font-size: var(--origam-font__size---sm);
3686
3754
  --origam-system-bar---font-weight: var(--origam-font__weight---regular);
3687
3755
  --origam-system-bar---letter-spacing: var(--origam-font__letterSpacing---wide);
@@ -4199,7 +4267,7 @@
4199
4267
  --origam-menu---offset-left: var(--origam-space---0);
4200
4268
  --origam-menu---offset-right: var(--origam-space---0);
4201
4269
  --origam-tooltip---background-color: var(--origam-color__neutral---800);
4202
- --origam-tooltip---color: var(--origam-color__text---inverse);
4270
+ --origam-tooltip---color: var(--origam-color__text---primary);
4203
4271
  --origam-tooltip---backdrop-filter: none;
4204
4272
  --origam-tooltip---font-size: var(--origam-font__size---sm);
4205
4273
  --origam-tooltip---font-weight: var(--origam-font__weight---medium);
@@ -30,9 +30,40 @@
30
30
  * palette primitive (son `blue---600` vaut `#1d4ed8`, soit le 700 de
31
31
  * Tailwind). La valeur est celle de `origam.theme.ts`, ce qui ferme du même
32
32
  * coup la divergence feuille ↔ thème que #793 suit.
33
+ *
34
+ * ── #871 — POURQUOI `[data-mode="light"]` DANS LA LISTE ────────────────────
35
+ * Les ~1 792 déclarations DÉRIVÉES de ce bloc — la forme
36
+ * `--origam-title---color: var(--origam-color__text---primary)` —
37
+ * ne se ré-évaluent QUE sur un élément que ce sélecteur matche. Sur tout autre
38
+ * élément, la valeur héritée est déjà SUBSTITUÉE — c'est la sémantique des
39
+ * custom properties, pas un bug : `--a: var(--b)` posé à `:root`, `--b`
40
+ * réécrit sur un enfant, et `--a` garde sur l'enfant la valeur calculée à la
41
+ * racine.
42
+ *
43
+ * Sans `[data-mode="light"]`, un sous-arbre `<OrigamThemeProvider mode="light">`
44
+ * à l'intérieur d'une page sombre gardait donc les 1 792 dérivés GELÉS sur les
45
+ * valeurs sombres de la racine. C'est le pendant clair du défaut mesuré en
46
+ * sombre par #871.
47
+ *
48
+ * ⛔ SPÉCIFICITÉ (0,1,0), VOLONTAIREMENT. Le bloc runtime d'une marque claire
49
+ * (`applyThemes()` sérialise `[data-theme="cartoon"]` sans `data-mode`) est
50
+ * lui aussi (0,1,0) et est injecté dans `<head>` APRÈS cette feuille : à
51
+ * égalité, l'ordre source tranche et la marque gagne. Monter ce sélecteur à
52
+ * (0,2,0) (p. ex. `[data-mode="light"]:not([data-theme="dark"])`) le ferait
53
+ * perdre, et cette feuille repeindrait par-dessus chaque marque claire.
54
+ *
55
+ * ── #871 — `system-bar` / `tooltip` : RIEN NE CHANGE ICI ──────────────────
56
+ * Ces deux composants peignent une surface SOMBRE dans les deux modes
57
+ * (`neutral---700` / `neutral---800`) et lisent `text---inverse`, qui vaut
58
+ * blanc EN CLAIR — correct, donc inchangé. C'est en SOMBRE que le même token
59
+ * vaut de l'encre et rend le texte illisible ; le correctif est donc dans
60
+ * `dark.css` seul. Voir son en-tête, y compris la piste écartée (passer les
61
+ * DEUX feuilles à `text---onColor`, qui a mesuré +2 violations en clair sur
62
+ * la marque `cartoon`).
33
63
  */
34
64
  :root,
35
- [data-theme="light"] {
65
+ [data-theme="light"],
66
+ [data-mode="light"] {
36
67
  --origam-color__surface---default: var(--origam-color__neutral---0);
37
68
  --origam-color__surface---raised: var(--origam-color__neutral---0);
38
69
  --origam-color__surface---overlay: var(--origam-color__neutral---100);
@@ -62,7 +62,6 @@
62
62
  v-if="hasPrepend"
63
63
  key="prepend"
64
64
  class="origam-btn__prepend"
65
- @click="handleClickPrepend"
66
65
  >
67
66
  <slot name="prepend">
68
67
  <origam-avatar
@@ -101,7 +100,6 @@
101
100
  v-if="hasAppend"
102
101
  key="append"
103
102
  class="origam-btn__append"
104
- @click="handleClickAppend"
105
103
  >
106
104
  <slot name="append">
107
105
  <origam-avatar
@@ -125,7 +123,7 @@
125
123
  </template>
126
124
 
127
125
  <script lang="ts" setup>
128
- import { computed, onMounted, ref, StyleValue, toRef, useAttrs, useSlots, watchEffect } from "vue";
126
+ import { computed, ref, StyleValue, toRef, useAttrs, useSlots, watchEffect } from "vue";
129
127
  import OrigamAvatar from "../Avatar/OrigamAvatar.vue";
130
128
  import OrigamIcon from "../Icon/OrigamIcon.vue";
131
129
  import OrigamLoader from "../Loader/OrigamLoader.vue";
@@ -149,8 +147,6 @@ import { useStyle } from "../../composables/Commons/style.composable";
149
147
  import { useTypography } from "../../composables/Commons/typography.composable";
150
148
  import { useVariant } from "../../composables/Commons/variant.composable";
151
149
  import { warnMissingNativeControlName } from "../../utils/Commons/a11y.util";
152
- import { warnDeprecatedEmit } from "../../utils/Commons/color.util";
153
- import { ADJACENT_EMIT_REPLACEMENT } from "../../consts/Btn/btn.const";
154
150
  import { ORIGAM_BTN_TOGGLE_KEY } from "../../consts/Btn/btn-toggle.const";
155
151
  import vContrast from "../../directives/Contrast/contrast.directive";
156
152
  import vRipple from "../../directives/Ripple/ripple.directive";
@@ -248,7 +244,7 @@ const props = defineProps({
248
244
  letterSpacing: { type: null, required: false }
249
245
  });
250
246
  const colorLocked = computed(() => props.color ? "true" : void 0);
251
- defineEmits(["click:append", "click:prepend", "group:selected"]);
247
+ defineEmits(["group:selected"]);
252
248
  defineSlots();
253
249
  const { filterProps } = useProps(props);
254
250
  const origamProgressRef = ref();
@@ -312,17 +308,9 @@ const {
312
308
  } = useStateEffect(props, isHover, isActive, hoverState, activeState, isDisabled, toRef(props, "flat"));
313
309
  const { variantClasses } = useVariant(props);
314
310
  const {
315
- onClickPrepend: handleClickPrepend,
316
- onClickAppend: handleClickAppend,
317
- isPrependClickable,
318
- isAppendClickable,
319
311
  hasAppend,
320
312
  hasPrepend
321
313
  } = useAdjacent(props, prependIcon, appendIcon);
322
- onMounted(() => {
323
- if (isPrependClickable.value) warnDeprecatedEmit("OrigamBtn", "click:prepend", ADJACENT_EMIT_REPLACEMENT);
324
- if (isAppendClickable.value) warnDeprecatedEmit("OrigamBtn", "click:append", ADJACENT_EMIT_REPLACEMENT);
325
- });
326
314
  const handleClick = (e) => {
327
315
  if (isDisabled.value || link.isLink.value && (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0 || attrs.target === "_blank")) return;
328
316
  link.navigate?.(e);
@@ -1,5 +1,5 @@
1
1
  import type { IActiveProps } from '../Commons/active.interface';
2
- import type { IAdjacentEmits, IAdjacentProps, IAdjacentSlots } from '../Commons/adjacent.interface';
2
+ import type { IAdjacentProps, IAdjacentSlots } from '../Commons/adjacent.interface';
3
3
  import type { IBorderProps } from '../Commons/border.interface';
4
4
  import type { IBgColorProps, IColorProps } from '../Commons/color.interface';
5
5
  import type { ICommonsComponentProps, ITagProps } from '../Commons/commons.interface';
@@ -40,12 +40,12 @@ export interface IBtnProps extends ICommonsComponentProps, IColorProps, IBgColor
40
40
  /**
41
41
  * Emit signatures for `<OrigamBtn>`.
42
42
  *
43
- * ⛔ DEPRECATED SURFACE (#443) — `click:prepend` / `click:append`, inherited
44
- * from {@link IAdjacentEmits}, are **deprecated and will be removed in
45
- * v3.0.0**. They still fire for now so no consumer breaks silently, and
46
- * `<OrigamBtn>` warns once per emit in dev builds.
43
+ * ⛔ REMOVED SURFACE (#443, #577) — `click:prepend` / `click:append` used to
44
+ * be inherited from `IAdjacentEmits`. They are GONE, not merely typed
45
+ * away: `<OrigamBtn>` no longer relays a click from the prepend/append zone
46
+ * at all (see `OrigamBtn.vue`, the spans carry no `@click` any more).
47
47
  *
48
- * They were never reachable by keyboard: the emit is bound to the
48
+ * They were never reachable by keyboard: the emit was bound to the
49
49
  * `origam-btn__prepend` / `origam-btn__append` `<span>`, while a keyboard
50
50
  * activation synthesises its click on the component ROOT, which never
51
51
  * reaches a descendant listener. The fix `useAdjacent` applies on the other
@@ -55,11 +55,8 @@ export interface IBtnProps extends ICommonsComponentProps, IColorProps, IBgColor
55
55
  *
56
56
  * Two actions are two buttons: compose them with `<origam-btn-group>`. The
57
57
  * `prepend` / `append` SLOTS are unaffected — see {@link IBtnSlots}.
58
- *
59
- * @deprecated The inherited `click:prepend` / `click:append` only. Drop
60
- * `IAdjacentEmits` from this interface in v3.0.0.
61
58
  */
62
- export interface IBtnEmits extends IAdjacentEmits, IGroupEmits {
59
+ export interface IBtnEmits extends IGroupEmits {
63
60
  }
64
61
  /** Slot signatures for `<OrigamBtn>`. */
65
62
  export interface IBtnSlots extends IAdjacentSlots {
@@ -7,10 +7,11 @@ Object.defineProperty(exports, "__esModule", {
7
7
  var _nodeFs = require("node:fs");
8
8
  var _nodePath = require("node:path");
9
9
  var _kit = require("@nuxt/kit");
10
+ var _origam = require("../themes/origam.theme.cjs");
10
11
  const MODULE_NAME = "origam-nuxt";
11
12
  const CONFIG_KEY = "origam";
12
13
  const NUXT_COMPOSABLES_BLOCKLIST = /* @__PURE__ */new Set(["useRoute", "useRouter", "useLink", "useHydration"]);
13
- const DEFAULT_THEMES = [];
14
+ const DEFAULT_THEMES = _origam.origamTheme;
14
15
  const DEFAULT_MODES = ["light", "dark"];
15
16
  const DEFAULTS = {
16
17
  themes: DEFAULT_THEMES,
@@ -1,6 +1,7 @@
1
1
  import { readdirSync, readFileSync, statSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { addComponentsDir, addImports, addPlugin, createResolver, defineNuxtModule } from "@nuxt/kit";
4
+ import { origamTheme } from "../themes/origam.theme.js";
4
5
  const MODULE_NAME = "origam-nuxt";
5
6
  const CONFIG_KEY = "origam";
6
7
  const NUXT_COMPOSABLES_BLOCKLIST = /* @__PURE__ */ new Set([
@@ -9,7 +10,7 @@ const NUXT_COMPOSABLES_BLOCKLIST = /* @__PURE__ */ new Set([
9
10
  "useLink",
10
11
  "useHydration"
11
12
  ]);
12
- const DEFAULT_THEMES = [];
13
+ const DEFAULT_THEMES = origamTheme;
13
14
  const DEFAULT_MODES = ["light", "dark"];
14
15
  const DEFAULTS = {
15
16
  themes: DEFAULT_THEMES,
@@ -11,7 +11,6 @@ var _consts = require("./consts/index.cjs");
11
11
  var origamDirectives = _interopRequireWildcard(require("./directives/index.cjs"));
12
12
  var _contrast = require("./directives/Contrast/contrast.directive.cjs");
13
13
  var _utils = require("./utils/index.cjs");
14
- var _origam = require("./themes/origam.theme.cjs");
15
14
  require("@mdi/font/css/materialdesignicons.css");
16
15
  var _vue = require("vue");
17
16
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -28,7 +27,7 @@ function createOrigam(origam = {}) {
28
27
  directives = origamDirectives
29
28
  } = options;
30
29
  const suppliedThemes = [...(options.theme ? [options.theme] : []), ...(options.themes ?? [])];
31
- const allThemes = [..._origam.origamTheme, ...suppliedThemes];
30
+ const allThemes = [...suppliedThemes];
32
31
  const installedThemes = (0, _utils.installedThemesFromList)(allThemes);
33
32
  const defaultsRef = (0, _composables.createDefaults)({});
34
33
  defaultsRef.value = activeDefaultsFor(allThemes, allThemes[0]?.name ?? "", void 0);
@@ -24,7 +24,6 @@ import {
24
24
  import * as origamDirectives from "./directives/index.js";
25
25
  import { setContrastConfig } from "./directives/Contrast/contrast.directive.js";
26
26
  import { applyThemes, installedThemesFromList, mergeDeep } from "./utils/index.js";
27
- import { origamTheme } from "./themes/origam.theme.js";
28
27
  import "@mdi/font/css/materialdesignicons.css";
29
28
  import { defineComponent, effectScope, nextTick, reactive } from "vue";
30
29
  export function createOrigam(origam = {}) {
@@ -39,7 +38,7 @@ export function createOrigam(origam = {}) {
39
38
  ...options.theme ? [options.theme] : [],
40
39
  ...options.themes ?? []
41
40
  ];
42
- const allThemes = [...origamTheme, ...suppliedThemes];
41
+ const allThemes = [...suppliedThemes];
43
42
  const installedThemes = installedThemesFromList(allThemes);
44
43
  const defaultsRef = createDefaults({});
45
44
  defaultsRef.value = activeDefaultsFor(allThemes, allThemes[0]?.name ?? "", void 0);
@@ -3,9 +3,9 @@
3
3
  *
4
4
  * @description
5
5
  * ⛔ issues #747 / #653 / #660. Same once-per-key, `import.meta.env.DEV`-gated
6
- * shape as `warnUnsupportedProp` / `warnDeprecatedEmit` (`color.util.ts`), but
7
- * filed here rather than grown as a fifth warning inside a colour utility —
8
- * these two say nothing about colour.
6
+ * shape as `warnUnsupportedProp` (`color.util.ts`), but filed here rather
7
+ * than grown as a fifth warning inside a colour utility — these two say
8
+ * nothing about colour.
9
9
  *
10
10
  * Both warnings are SILENT in production builds. They exist to tell the
11
11
  * developer what to add, at the moment they can still add it; shipping the
@@ -40,7 +40,6 @@ exports.rawBgExprWithState = rawBgExprWithState;
40
40
  exports.toHex = toHex;
41
41
  exports.tokenForegroundForIntent = tokenForegroundForIntent;
42
42
  exports.tokenStylesForIntent = tokenStylesForIntent;
43
- exports.warnDeprecatedEmit = warnDeprecatedEmit;
44
43
  exports.warnDeprecatedProp = warnDeprecatedProp;
45
44
  exports.warnLegacyColor = warnLegacyColor;
46
45
  exports.warnUnsupportedProp = warnUnsupportedProp;
@@ -431,13 +430,4 @@ function warnUnsupportedProp(component, prop, reason) {
431
430
  if (_warnedUnsupportedPropKeys.has(key)) return;
432
431
  _warnedUnsupportedPropKeys.add(key);
433
432
  console.warn(`[origam] <${component}> prop "${prop}" has no effect on this component: ${reason}`);
434
- }
435
- const _warnedDeprecatedEmitKeys = /* @__PURE__ */new Set();
436
- function warnDeprecatedEmit(component, emit, replacement, removalVersion = "v3.0.0") {
437
- if (typeof console === "undefined") return;
438
- if (!process.env?.DEV) return;
439
- const key = `${component}::${emit}`;
440
- if (_warnedDeprecatedEmitKeys.has(key)) return;
441
- _warnedDeprecatedEmitKeys.add(key);
442
- console.warn(`[origam] <${component}> emit "${emit}" is deprecated and will be removed in ${removalVersion}. ${replacement}`);
443
433
  }
@@ -492,26 +492,3 @@ export declare function warnDeprecatedProp(component: string, oldProp: string, n
492
492
  * bullishColor/bearishColor").
493
493
  ********************************************************/
494
494
  export declare function warnUnsupportedProp(component: string, prop: string, reason: string): void;
495
- /*********************************************************
496
- * warnDeprecatedEmit
497
- *
498
- * @description
499
- * Warn (once per component / emit, dev builds only) that the consumer
500
- * attached a listener to an emit scheduled for removal. The emit KEEPS
501
- * FIRING until the removal version — this announces the break instead of
502
- * shipping it. `replacement` should name what to do instead, not merely
503
- * say the emit is going away. Same once-per-key cache as the three
504
- * warnings above, but for a public EMIT rather than a prop.
505
- *
506
- * @description
507
- * First use case: `click:prepend` / `click:append` on `<OrigamBtn>` (#443).
508
- * Those two were reachable by MOUSE ONLY — the emit is bound to a
509
- * descendant span, while keyboard activation synthesises its click on the
510
- * button root. The `role="button"` + tab-stop remedy `useAdjacent` applies
511
- * on the other ten consumers is ILLEGAL here: Btn's root is a
512
- * `<button>`/`<a>`, whose content model forbids both an interactive
513
- * descendant and any descendant carrying `tabindex`. A control that already
514
- * owns one action cannot host a second — two actions are two buttons
515
- * (`origam-btn-group`).
516
- ********************************************************/
517
- export declare function warnDeprecatedEmit(component: string, emit: string, replacement: string, removalVersion?: string): void;
@@ -343,14 +343,3 @@ export function warnUnsupportedProp(component, prop, reason) {
343
343
  `[origam] <${component}> prop "${prop}" has no effect on this component: ${reason}`
344
344
  );
345
345
  }
346
- const _warnedDeprecatedEmitKeys = /* @__PURE__ */ new Set();
347
- export function warnDeprecatedEmit(component, emit, replacement, removalVersion = "v3.0.0") {
348
- if (typeof console === "undefined") return;
349
- if (!import.meta.env?.DEV) return;
350
- const key = `${component}::${emit}`;
351
- if (_warnedDeprecatedEmitKeys.has(key)) return;
352
- _warnedDeprecatedEmitKeys.add(key);
353
- console.warn(
354
- `[origam] <${component}> emit "${emit}" is deprecated and will be removed in ${removalVersion}. ${replacement}`
355
- );
356
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "origam",
3
- "version": "2.18.0",
3
+ "version": "2.18.1",
4
4
  "type": "module",
5
5
  "description": "origam — a Vue 3 design system with multi-theme design tokens, CSS-first components and TypeScript types.",
6
6
  "keywords": [
@@ -1,7 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.ADJACENT_EMIT_REPLACEMENT = void 0;
7
- const ADJACENT_EMIT_REPLACEMENT = exports.ADJACENT_EMIT_REPLACEMENT = "It was never reachable by keyboard (the emit fires from a descendant span, and keyboard activation targets the button root), and Btn cannot be given a focusable sub-control because <button>/<a> forbid interactive descendants. Use two buttons in an <origam-btn-group> instead. The prepend/append slots themselves are unaffected.";