origam 2.26.1 → 2.27.0

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
@@ -18,6 +18,37 @@ This project follows [Semantic Versioning](https://semver.org).
18
18
 
19
19
  ## [Unreleased]
20
20
 
21
+ ## [2.27.0] - 2026-10-15
22
+
23
+ ### Removed — `OrigamSkeleton` : les gabarits `card` et `list-item` (BREAKING, #1073 lot 3, #1083)
24
+
25
+ Decision 4 de #1073. Les deux gabarits composites figes disparaissent ; il ne reste que les quatre primitives `text`, `rectangular`, `circular`, `pill`. Rupture assumee (pre-1.0, aucun consommateur externe), livree dans un minor.
26
+
27
+ Retire :
28
+
29
+ - `SKELETON_VARIANT.CARD` et `SKELETON_VARIANT.LIST_ITEM`, donc `TSkeletonVariant` ne vaut plus que `'text' | 'rectangular' | 'circular' | 'pill'` ;
30
+ - les classes `.origam-skeleton-wrapper`, `.origam-skeleton-wrapper--card`, `.origam-skeleton-wrapper--list-item` et `.origam-skeleton__lines`, ainsi que leurs regles scoped. Aucun token n'est retire : `--origam-skeleton---gap` reste lu par `OrigamSkeletonGroup`.
31
+
32
+ Les consommateurs internes avaient deja migre : `OrigamCard` (#1089, lot 2b) et `wireframe.vue` (#1084, lot 2c) ne passent plus par ces gabarits.
33
+
34
+ Migration : `<origam-skeleton variant="card" />` et `variant="list-item"` rendaient un `<div class="origam-skeleton-wrapper--…">` de primitives. On compose maintenant ces primitives soi-meme dans un `OrigamSkeletonGroup`, qui porte l'unique annonce `role="status"` de la zone et la meme horloge d'animation :
35
+
36
+ ```vue
37
+ <origam-skeleton-group>
38
+ <origam-skeleton variant="circular" />
39
+ <origam-skeleton variant="text" width="60%" />
40
+ <origam-skeleton variant="text" width="40%" />
41
+ </origam-skeleton-group>
42
+ ```
43
+
44
+ Un `variant="card"` ou `"list-item"` restant n'est plus type (erreur `vue-tsc`) ; a l'execution la classe `origam-skeleton--card` / `--list-item` n'a plus aucune regle CSS associee : il n'y a plus de gabarit.
45
+
46
+ ## [2.26.2] - 2026-10-15
47
+
48
+ ### Fixed — un theme sans `name` avec `mode` l'emporte sur la palette integree du meme mode (#1102)
49
+
50
+ `themeSelector({ mode: 'dark' })` emettait `[data-mode="dark"]` (0,1,0) face a `[data-mode="dark"]:not([data-theme="light"])` (0,2,0) de `dark.css` : le theme sombre sans nom perdait sur `theme=dark/mode=dark`, `mode=dark` seul et `theme=site/mode=dark` (mesure Chromium : `--origam-color__action--primary---bg` restait a `#7c3aed`). Il peignait aussi sombre sous `data-theme="light" data-mode="dark"` par egalite d'ordre source (regle #807 violee). Le selecteur est desormais `html[data-mode="…"]` (dark : `(0,2,1)`, `:not([data-theme="light"])` conserve ; light : `(0,1,1)`), independant de l'ordre d'injection, et reste sous les blocs `:root:root[data-theme]` des marques nommees. Le doc `theme.interface.ts` (« scoped to `:root` ») est corrige. Spec : `unnamed-theme-specificity.spec.ts`.
51
+
21
52
  ## [2.26.1] - 2026-10-14
22
53
 
23
54
  ### Fixed — `warnLegacyColor` : dev uniquement, et plus d'avertissement pour `var()` / `color-mix()` (#1099)
@@ -3,54 +3,6 @@
3
3
  <slot/>
4
4
  </template>
5
5
 
6
- <div
7
- v-else-if="isListItem"
8
- :id="id"
9
- :class="skeletonContainerClasses"
10
- :style="skeletonContainerStyles"
11
- v-bind="{ ...a11yAttrs, ...$attrs }"
12
- >
13
- <div
14
- :class="skeletonCircularClasses"
15
- aria-hidden="true"
16
- />
17
- <div class="origam-skeleton__lines">
18
- <div
19
- :class="skeletonTextClasses"
20
- aria-hidden="true"
21
- />
22
- <div
23
- :class="skeletonTextClasses"
24
- aria-hidden="true"
25
- />
26
- </div>
27
- </div>
28
-
29
- <div
30
- v-else-if="isCard"
31
- :id="id"
32
- :class="skeletonContainerClasses"
33
- :style="skeletonContainerStyles"
34
- v-bind="{ ...a11yAttrs, ...$attrs }"
35
- >
36
- <div
37
- :class="skeletonRectangularClasses"
38
- aria-hidden="true"
39
- />
40
- <div
41
- :class="skeletonTextClasses"
42
- aria-hidden="true"
43
- />
44
- <div
45
- :class="skeletonTextClasses"
46
- aria-hidden="true"
47
- />
48
- <div
49
- :class="skeletonTextClasses"
50
- aria-hidden="true"
51
- />
52
- </div>
53
-
54
6
  <div
55
7
  v-else
56
8
  :id="id"
@@ -68,7 +20,7 @@ import { useProps } from "../../composables/Commons/props.composable";
68
20
  import { useRounded } from "../../composables/Commons/rounded.composable";
69
21
  import { useSize } from "../../composables/Commons/size.composable";
70
22
  import { ORIGAM_SKELETON_GROUP_KEY } from "../../consts/Skeleton/skeleton.const";
71
- import { SKELETON_ANIMATION, SKELETON_VARIANT } from "../../enums/Skeleton/skeleton.enum";
23
+ import { SKELETON_ANIMATION } from "../../enums/Skeleton/skeleton.enum";
72
24
  import { getSkeletonHostClasses } from "../../utils/Skeleton/skeleton.util";
73
25
  import { computed, inject, toRef } from "vue";
74
26
  defineOptions({ inheritAttrs: false });
@@ -119,30 +71,7 @@ const a11yAttrs = computed(() => {
119
71
  "aria-label": skeletonAriaLabel.value
120
72
  };
121
73
  });
122
- const isListItem = computed(() => props.variant === SKELETON_VARIANT.LIST_ITEM);
123
- const isCard = computed(() => props.variant === SKELETON_VARIANT.CARD);
124
74
  const animationClasses = computed(() => getSkeletonHostClasses(animation.value));
125
- const skeletonCircularClasses = computed(() => [
126
- "origam-skeleton",
127
- "origam-skeleton--circular",
128
- animationClasses.value
129
- ]);
130
- const skeletonTextClasses = computed(() => [
131
- "origam-skeleton",
132
- "origam-skeleton--text",
133
- animationClasses.value
134
- ]);
135
- const skeletonRectangularClasses = computed(() => [
136
- "origam-skeleton",
137
- "origam-skeleton--rectangular",
138
- animationClasses.value
139
- ]);
140
- const skeletonContainerClasses = computed(() => [
141
- "origam-skeleton-wrapper",
142
- `origam-skeleton-wrapper--${props.variant}`,
143
- props.class
144
- ]);
145
- const skeletonContainerStyles = computed(() => [props.style]);
146
75
  const skeletonClasses = computed(() => [
147
76
  "origam-skeleton",
148
77
  `origam-skeleton--${props.variant}`,
@@ -195,54 +124,4 @@ defineExpose({
195
124
  border-radius: var(--origam-skeleton---border-radius-pill);
196
125
  }
197
126
  }
198
-
199
- .origam-skeleton-wrapper {
200
- &--list-item {
201
- display: flex;
202
- gap: var(--origam-skeleton---gap, 12px);
203
- align-items: center;
204
-
205
- > .origam-skeleton__lines {
206
- flex: 1;
207
- display: flex;
208
- flex-direction: column;
209
- gap: 6px;
210
-
211
- > .origam-skeleton:nth-child(1) {
212
- width: 60%;
213
- }
214
-
215
- > .origam-skeleton:nth-child(2) {
216
- width: 40%;
217
- opacity: 0.7;
218
- }
219
- }
220
- }
221
-
222
- &--card {
223
- display: flex;
224
- flex-direction: column;
225
-
226
- > .origam-skeleton:nth-child(1) {
227
- height: 80px;
228
- margin-bottom: 10px;
229
- }
230
-
231
- > .origam-skeleton:nth-child(2) {
232
- width: 70%;
233
- margin-bottom: 6px;
234
- }
235
-
236
- > .origam-skeleton:nth-child(3) {
237
- width: 90%;
238
- margin-bottom: 4px;
239
- opacity: 0.7;
240
- }
241
-
242
- > .origam-skeleton:nth-child(4) {
243
- width: 50%;
244
- opacity: 0.7;
245
- }
246
- }
247
- }
248
127
  </style>
@@ -9,8 +9,6 @@ var SKELETON_VARIANT = exports.SKELETON_VARIANT = /* @__PURE__ */(SKELETON_VARIA
9
9
  SKELETON_VARIANT2["RECTANGULAR"] = "rectangular";
10
10
  SKELETON_VARIANT2["CIRCULAR"] = "circular";
11
11
  SKELETON_VARIANT2["PILL"] = "pill";
12
- SKELETON_VARIANT2["CARD"] = "card";
13
- SKELETON_VARIANT2["LIST_ITEM"] = "list-item";
14
12
  return SKELETON_VARIANT2;
15
13
  })(SKELETON_VARIANT || {});
16
14
  var SKELETON_ANIMATION = exports.SKELETON_ANIMATION = /* @__PURE__ */(SKELETON_ANIMATION2 => {
@@ -4,16 +4,13 @@
4
4
  * @description
5
5
  * Shape presets for `<OrigamSkeleton>`. `text`, `rectangular`, `circular`
6
6
  * and `pill` are the PRIMITIVES — the bricks a component assembles to mimic
7
- * its own anatomy. `card` and `list-item` are fixed composite templates kept
8
- * until the components that consume them have moved to primitives.
7
+ * its own anatomy, inside an `<OrigamSkeletonGroup>`.
9
8
  ********************************************************/
10
9
  export declare enum SKELETON_VARIANT {
11
10
  TEXT = "text",
12
11
  RECTANGULAR = "rectangular",
13
12
  CIRCULAR = "circular",
14
- PILL = "pill",
15
- CARD = "card",
16
- LIST_ITEM = "list-item"
13
+ PILL = "pill"
17
14
  }
18
15
  /*********************************************************
19
16
  * SKELETON_ANIMATION
@@ -3,8 +3,6 @@ export var SKELETON_VARIANT = /* @__PURE__ */ ((SKELETON_VARIANT2) => {
3
3
  SKELETON_VARIANT2["RECTANGULAR"] = "rectangular";
4
4
  SKELETON_VARIANT2["CIRCULAR"] = "circular";
5
5
  SKELETON_VARIANT2["PILL"] = "pill";
6
- SKELETON_VARIANT2["CARD"] = "card";
7
- SKELETON_VARIANT2["LIST_ITEM"] = "list-item";
8
6
  return SKELETON_VARIANT2;
9
7
  })(SKELETON_VARIANT || {});
10
8
  export var SKELETON_ANIMATION = /* @__PURE__ */ ((SKELETON_ANIMATION2) => {
@@ -21,8 +21,11 @@ export interface IOrigamThemeSingletonState {
21
21
  /**
22
22
  * Runtime theme object ingested by `createOrigam({ themes })`. At install time
23
23
  * the DS resolves it to a block of `--origam-*` CSS variables injected into
24
- * `<head>`, scoped to `:root` (or `[data-theme="<name>"]` when `name` is set,
25
- * optionally narrowed by `[data-mode]` when `mode` is set).
24
+ * `<head>`, scoped by `name` / `mode` (see `themeSelector`):
25
+ * no `name` and no `mode` → `:root`; no `name` but a `mode` → `html[data-mode]`
26
+ * (plus a bare `[data-mode]` twin for sub-trees), specific enough to beat the
27
+ * built-in palette of that mode and still lose to every named brand (#1102);
28
+ * a `name` → `[data-theme="<name>"]`, optionally narrowed by `[data-mode]`.
26
29
  *
27
30
  * ## A theme has exactly THREE authoring surfaces
28
31
  *
@@ -74,7 +74,11 @@ function themeSelector(theme) {
74
74
  const hasName = typeof theme.name === "string" && theme.name.length > 0;
75
75
  const hasMode = theme.mode === "light" || theme.mode === "dark";
76
76
  if (!hasName && !hasMode) return ":root";
77
- if (!hasName) return `[data-mode="${theme.mode}"]`;
77
+ if (!hasName) {
78
+ const root = theme.mode === "dark" ? 'html[data-mode="dark"]:not([data-theme="light"])' : 'html[data-mode="light"]';
79
+ const subtree = theme.mode === "dark" ? '[data-mode="dark"]:not([data-theme]):not([data-theme="light"])' : '[data-mode="light"]:not([data-theme])';
80
+ return `${root}, ${subtree}`;
81
+ }
78
82
  const modeAttr = hasMode ? `[data-mode="${theme.mode}"]` : "";
79
83
  const attrs = `[data-theme="${theme.name}"]${modeAttr}`;
80
84
  return `:root:root${attrs}, ${attrs}`;
@@ -27,7 +27,8 @@ export declare function resolveThemeVars(theme: IOrigamTheme): TThemeVars;
27
27
  * Compute the CSS selector a theme block targets, from its `name` / `mode`:
28
28
  * - neither → `:root`
29
29
  * - name only → `[data-theme="<name>"]`
30
- * - mode only → `[data-mode="<mode>"]`
30
+ * - mode only → `html[data-mode="<mode>"], [data-mode="<mode>"]:not([data-theme])`
31
+ * (dark adds `:not([data-theme="light"])`, see #1102)
31
32
  * - name + mode → `[data-theme="<name>"][data-mode="<mode>"]`
32
33
  *
33
34
  * A `mode` of `'auto'` is treated as "no mode scoping".
@@ -55,7 +55,11 @@ export function themeSelector(theme) {
55
55
  const hasName = typeof theme.name === "string" && theme.name.length > 0;
56
56
  const hasMode = theme.mode === "light" || theme.mode === "dark";
57
57
  if (!hasName && !hasMode) return ":root";
58
- if (!hasName) return `[data-mode="${theme.mode}"]`;
58
+ if (!hasName) {
59
+ const root = theme.mode === "dark" ? 'html[data-mode="dark"]:not([data-theme="light"])' : 'html[data-mode="light"]';
60
+ const subtree = theme.mode === "dark" ? '[data-mode="dark"]:not([data-theme]):not([data-theme="light"])' : '[data-mode="light"]:not([data-theme])';
61
+ return `${root}, ${subtree}`;
62
+ }
59
63
  const modeAttr = hasMode ? `[data-mode="${theme.mode}"]` : "";
60
64
  const attrs = `[data-theme="${theme.name}"]${modeAttr}`;
61
65
  return `:root:root${attrs}, ${attrs}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "origam",
3
- "version": "2.26.1",
3
+ "version": "2.27.0",
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": [