origam 2.22.0 → 2.23.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,47 @@ This project follows [Semantic Versioning](https://semver.org).
18
18
 
19
19
  ## [Unreleased]
20
20
 
21
+ ## [2.23.0] - 2026-10-08
22
+
23
+ ### Added — `createOrigam({ code: { highlighter } })` : l'application fournit son highlighter
24
+
25
+ `OrigamCode` importait `shiki` par un **specificateur nu** que le navigateur ne sait pas resoudre. Mesure sur le build de production d'une application consommatrice, avec 2.21.0 : `Failed to resolve module specifier 'shiki'`, blocs de code non colorises, et un bloc `yaml` rendu **vide**. Declarer `shiki` en dependance de l'application ne suffisait pas.
26
+
27
+ ⛔ **Le `@vite-ignore` n'etait pas une negligence** : sans lui, Rollup suit le graphe jusqu'au chargeur WASM de shiki et emet un chunk virtuel invalide (`default` est un mot reserve, esbuild rejette). Le retirer aurait casse `packages/docs` (VitePress). L'option contourne les deux : si l'application fournit un highlighter, **le DS ne touche jamais a `shiki`** dans ce chemin — plus d'import, plus de specificateur nu, plus de chunk WASM.
28
+
29
+ `TShikiModule` n'exige que **`createHighlighter`**, pas la surface entiere de `shiki` : un module allege bati sur `shiki/core` + moteur regex JS fonctionne, et c'est ce qui evite la cause racine du contournement. Mesure du consommateur : **+65 Ko gzip contre +417 Ko** avec shiki complet.
30
+
31
+ ⚠️ **Non cassant** : sans l'option, le chemin par defaut est inchange ; `packages/docs` compile **sans aucune modification de sa part** (verifie, `exit 0`). Et le rattrapage vers le texte brut sur une langue non embarquee est **conserve deliberement** — c'est ce qui rend un highlighter partiel utilisable sans que la page casse.
32
+
33
+ ### Changed — ⚠️ RUPTURE : `IVariantProps` scinde en `IActionVariantProps` / `IInputVariantProps`
34
+
35
+ **14 composants acceptaient des valeurs de `variant` qui ne faisaient rien.** `IVariantProps` etait un mixin **partage** entre composants d'action et de saisie, exposant l'union des deux vocabulaires (10 valeurs) alors que chaque famille n'en implemente que la moitie. Mesure en navigateur reel, avec contrôle positif :
36
+
37
+ | famille | implemente | **inerte** |
38
+ |---|---|---|
39
+ | `OrigamBtn`, `OrigamBtnGroup`, `OrigamBtnToggle` | les 7 de `VARIANT` | **`underlined` `filled` `solo`** — byte-identiques a `flat` sur les 7 longhands |
40
+ | `OrigamField` + 9 descendants | les 5 de `VARIANT_INPUT` | **`text` `flat` `elevated` `tonal` `ghost`** — identiques entre eux |
41
+
42
+ `useVariant()` emet bien la classe `--variant-{valeur}` — il n'a aucune liste blanche — mais **aucune regle CSS ne la cible**.
43
+
44
+ ⚠️ **`outlined` et `plain` sont implementes des DEUX cotes**, avec un rendu different selon le composant. Ce chevauchement est **legitime** (deux patterns UI distincts partageant un nom) et ne change pas. Le defaut etait l'asymetrie, pas le recouvrement.
45
+
46
+ **`IVariantProps` est SUPPRIME** — mesure : zero consommateur hors des 14 composants, de son composable et de son test. `OrigamConfirmWrapper` recoit `IInputVariantProps` : son `variant` n'est qu'un defaut pousse vers les champs qu'il enveloppe.
47
+
48
+ **Ce que la restriction a revele** : `OrigamConfirmWrapper.story.vue` proposait `VARIANT_OPTIONS` (les 7 valeurs d'action) alors que ce composant pousse des defauts vers des **champs de formulaire** — faux en silence depuis la creation de la story.
49
+
50
+ **Cout de la rupture, mesure** : un consommateur qui passe `variant="solo"` a un `OrigamBtn` n'obtient **rien** aujourd'hui. La restriction transforme un silence en erreur de compilation, ce qui l'informe. La seule application cliente connue a audite ses deux etats : **zero occurrence**, et `git grep IVariantProps` y rend **0**.
51
+
52
+ Epingle par `packages/tests/TU/playground/variant-literal-union.spec.ts`, verifie **ROUGE sur le commit parent** (10/10) et **VERT apres** (7 et 5) — sur le descripteur resolu, pas sur le texte source.
53
+
54
+ ### Fixed — un test unitaire reconstruisait deux fois le programme TypeScript entier
55
+
56
+ `extractLiteralUnions()` appelle `createChecker()`, qui rebatit tout le programme de `packages/ds/tsconfig.json` depuis zero a chaque appel. Le test l'appelait **une fois par `it()`**, payant ce cout deux fois. Un seul appel partage dans un `beforeAll` suffit aux deux cas.
57
+
58
+ ⚠️ **Ce n'etait pas un defaut produit ni une particularite de Node 22**, et la mesure le montre : **3,73 s** isole, **54,6 s** sur le job CI Node 22 (un timeout), **36,0 s** sur le job Node 24 du **meme run** (vert, mais presque sans marge). Le facteur de 8 a 14 vient de la contention des workers Vitest sur un runner partage — Node 22 n'a pas cause l'echec, il l'a expose le premier.
59
+
60
+ ⚠️ **Ne figure pas dans le paquet publie** : le lot de fondation du playground (`packages/playground`, prive) n'affecte pas le tarball.
61
+
21
62
  ## [2.22.0] - 2026-10-07
22
63
 
23
64
  ### Added — `attach` sur `OrigamCommandPalette`, `OrigamSnackbarGroup` et `OrigamDrawer`
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.resetCodeHighlighterForTesting = resetCodeHighlighterForTesting;
7
7
  exports.useCode = useCode;
8
+ var _vue = require("vue");
8
9
  var _code = require("../../consts/Code/code.const.cjs");
9
10
  var _enums = require("../../enums/index.cjs");
10
11
  let _highlighterPromise = null;
@@ -33,11 +34,11 @@ function lruSet(key, value) {
33
34
  }
34
35
  _cache.set(key, value);
35
36
  }
36
- async function loadHighlighter() {
37
+ async function loadHighlighter(loader) {
37
38
  if (_highlighterUnavailable) return null;
38
39
  if (_highlighterPromise) return _highlighterPromise;
39
40
  _highlighterPromise = (async () => {
40
- const shiki = await Promise.resolve().then(() => require("shiki"));
41
+ const shiki = loader ? await loader() : await Promise.resolve().then(() => require("shiki"));
41
42
  const highlighter = await shiki.createHighlighter({
42
43
  themes: [_code.CODE_LIGHT_THEME, _code.CODE_DARK_THEME],
43
44
  langs: [..._code.SUPPORTED_LANGS]
@@ -50,7 +51,7 @@ async function loadHighlighter() {
50
51
  _highlighterPromise = null;
51
52
  if (!_unavailableWarned) {
52
53
  _unavailableWarned = true;
53
- console.warn("[origam] OrigamCode: `shiki` is not installed \u2014 rendering plain, unhighlighted code. Add `shiki` to your dependencies to enable syntax highlighting.", err);
54
+ console.warn(loader ? "[origam] OrigamCode: the `highlighter` supplied to `createOrigam({ code })` failed to load \u2014 rendering plain, unhighlighted code." : "[origam] OrigamCode: `shiki` is not installed \u2014 rendering plain, unhighlighted code. Add `shiki` to your dependencies to enable syntax highlighting.", err);
54
55
  }
55
56
  return null;
56
57
  });
@@ -64,12 +65,13 @@ function resolveLang(lang) {
64
65
  return _enums.CODE_LANG.PLAINTEXT;
65
66
  }
66
67
  function useCode() {
68
+ const highlighterLoader = (0, _vue.inject)(_code.ORIGAM_CODE_KEY)?.highlighter;
67
69
  async function highlight(code, lang) {
68
70
  const resolvedLang = resolveLang(lang);
69
71
  const key = makeCacheKey(code, resolvedLang);
70
72
  const cached = lruGet(key);
71
73
  if (cached !== void 0) return cached;
72
- const highlighter = await loadHighlighter();
74
+ const highlighter = await loadHighlighter(highlighterLoader);
73
75
  if (!highlighter) {
74
76
  const plain = escapeHtml(code);
75
77
  lruSet(key, plain);
@@ -97,7 +99,7 @@ function useCode() {
97
99
  return html;
98
100
  }
99
101
  async function prime() {
100
- await loadHighlighter();
102
+ await loadHighlighter(highlighterLoader);
101
103
  }
102
104
  function isReady() {
103
105
  return _highlighterReady;
@@ -1,6 +1,13 @@
1
1
  import type { IUseCodeReturn } from '../../interfaces/Code/code.interface';
2
2
  /**
3
3
  * Public hook — see `IUseCodeReturn` for the surface contract.
4
+ *
5
+ * `inject(ORIGAM_CODE_KEY)` below is called synchronously here, which is
6
+ * only valid while THIS function runs during a component's `setup()`
7
+ * (exactly how `OrigamCode.vue` calls it). `undefined` when no
8
+ * `createOrigam({ code })` ancestor provided one (or none was installed at
9
+ * all): `loadHighlighter()` then keeps its original `import('shiki')`
10
+ * behaviour, unchanged.
4
11
  */
5
12
  export declare function useCode(): IUseCodeReturn;
6
13
  /**
@@ -1,4 +1,5 @@
1
- import { CODE_CACHE_MAX_ENTRIES, CODE_DARK_THEME as DARK_THEME, CODE_LIGHT_THEME as LIGHT_THEME, SUPPORTED_LANGS } from "../../consts/Code/code.const.js";
1
+ import { inject } from "vue";
2
+ import { CODE_CACHE_MAX_ENTRIES, CODE_DARK_THEME as DARK_THEME, CODE_LIGHT_THEME as LIGHT_THEME, ORIGAM_CODE_KEY, SUPPORTED_LANGS } from "../../consts/Code/code.const.js";
2
3
  import { CODE_LANG } from "../../enums/index.js";
3
4
  let _highlighterPromise = null;
4
5
  let _highlighterReady = false;
@@ -26,11 +27,11 @@ function lruSet(key, value) {
26
27
  }
27
28
  _cache.set(key, value);
28
29
  }
29
- async function loadHighlighter() {
30
+ async function loadHighlighter(loader) {
30
31
  if (_highlighterUnavailable) return null;
31
32
  if (_highlighterPromise) return _highlighterPromise;
32
33
  _highlighterPromise = (async () => {
33
- const shiki = await import(
34
+ const shiki = loader ? await loader() : await import(
34
35
  /* @vite-ignore */
35
36
  "shiki"
36
37
  );
@@ -47,7 +48,7 @@ async function loadHighlighter() {
47
48
  if (!_unavailableWarned) {
48
49
  _unavailableWarned = true;
49
50
  console.warn(
50
- "[origam] OrigamCode: `shiki` is not installed \u2014 rendering plain, unhighlighted code. Add `shiki` to your dependencies to enable syntax highlighting.",
51
+ loader ? "[origam] OrigamCode: the `highlighter` supplied to `createOrigam({ code })` failed to load \u2014 rendering plain, unhighlighted code." : "[origam] OrigamCode: `shiki` is not installed \u2014 rendering plain, unhighlighted code. Add `shiki` to your dependencies to enable syntax highlighting.",
51
52
  err
52
53
  );
53
54
  }
@@ -65,12 +66,13 @@ function resolveLang(lang) {
65
66
  return CODE_LANG.PLAINTEXT;
66
67
  }
67
68
  export function useCode() {
69
+ const highlighterLoader = inject(ORIGAM_CODE_KEY)?.highlighter;
68
70
  async function highlight(code, lang) {
69
71
  const resolvedLang = resolveLang(lang);
70
72
  const key = makeCacheKey(code, resolvedLang);
71
73
  const cached = lruGet(key);
72
74
  if (cached !== void 0) return cached;
73
- const highlighter = await loadHighlighter();
75
+ const highlighter = await loadHighlighter(highlighterLoader);
74
76
  if (!highlighter) {
75
77
  const plain = escapeHtml(code);
76
78
  lruSet(key, plain);
@@ -92,7 +94,7 @@ export function useCode() {
92
94
  return html;
93
95
  }
94
96
  async function prime() {
95
- await loadHighlighter();
97
+ await loadHighlighter(highlighterLoader);
96
98
  }
97
99
  function isReady() {
98
100
  return _highlighterReady;
@@ -1,5 +1,3 @@
1
- import type { IVariantProps } from '../../interfaces/Commons/variant.interface';
2
- import type { TVariant, TVariantInput } from '../../types/Commons/variant.type';
3
1
  import { Ref } from 'vue';
4
2
  /*********************************************************
5
3
  * useVariant
@@ -10,7 +8,17 @@ import { Ref } from 'vue';
10
8
  * contrairement a `useDensity`/`useSize`, il n'y a pas de liste blanche
11
9
  * (`*_ARRAY`) a matcher : toute valeur non-nulle produit une classe, y
12
10
  * compris une variante que le composant ne connait pas.
11
+ *
12
+ * Le parametre props n'est plus type via l'ancien `IVariantProps` (mixin
13
+ * unique acceptant a tort `TVariant | TVariantInput` partout — scinde en
14
+ * `IActionVariantProps` / `IInputVariantProps`, cf. #1050). Un type
15
+ * structurel `{ variant?: string }` suffit ici : la fonction ne fait que
16
+ * lire `props.variant` et le stringifier, elle n'a jamais eu besoin de
17
+ * connaitre la liste de valeurs d'une famille precise — et les deux
18
+ * interfaces scindees (comme toute autre) lui restent assignables.
13
19
  ********************************************************/
14
- export declare function useVariant(props: IVariantProps | Ref<TVariant | TVariantInput | string | undefined>, name?: string): {
20
+ export declare function useVariant(props: {
21
+ variant?: string;
22
+ } | Ref<string | undefined>, name?: string): {
15
23
  variantClasses: import("vue").ComputedRef<string[]>;
16
24
  };
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.SUPPORTED_LANGS = exports.CODE_LIGHT_THEME = exports.CODE_DEFAULTS = exports.CODE_DARK_THEME = exports.CODE_CACHE_MAX_ENTRIES = void 0;
6
+ exports.SUPPORTED_LANGS = exports.ORIGAM_CODE_KEY = exports.CODE_LIGHT_THEME = exports.CODE_DEFAULTS = exports.CODE_DARK_THEME = exports.CODE_CACHE_MAX_ENTRIES = void 0;
7
7
  var _enums = require("../../enums/index.cjs");
8
8
  const SUPPORTED_LANGS = exports.SUPPORTED_LANGS = Object.freeze([_enums.CODE_LANG.PLAINTEXT, _enums.CODE_LANG.VUE, _enums.CODE_LANG.TS, _enums.CODE_LANG.JS, _enums.CODE_LANG.TSX, _enums.CODE_LANG.JSX, _enums.CODE_LANG.SCSS, _enums.CODE_LANG.CSS, _enums.CODE_LANG.JSON, _enums.CODE_LANG.BASH, _enums.CODE_LANG.HTML, _enums.CODE_LANG.XML, _enums.CODE_LANG.YAML, _enums.CODE_LANG.MD]);
9
9
  const CODE_CACHE_MAX_ENTRIES = exports.CODE_CACHE_MAX_ENTRIES = 64;
@@ -20,4 +20,5 @@ const CODE_DEFAULTS = exports.CODE_DEFAULTS = Object.freeze({
20
20
  * snackbar default so the visual rhythm stays consistent.
21
21
  */
22
22
  copyFeedbackDurationMs: 2e3
23
- });
23
+ });
24
+ const ORIGAM_CODE_KEY = exports.ORIGAM_CODE_KEY = /* @__PURE__ */Symbol.for("origam:code");
@@ -1,4 +1,6 @@
1
+ import type { InjectionKey } from 'vue';
1
2
  import { CODE_LANG } from '../../enums';
3
+ import type { ICodeOptions } from '../../interfaces/Code/code.interface';
2
4
  /**
3
5
  * Languages bundled with the default shiki highlighter. Keep this list and
4
6
  * the `langs` argument of `createHighlighter()` in lockstep — see
@@ -51,3 +53,15 @@ export declare const CODE_DEFAULTS: Readonly<{
51
53
  */
52
54
  readonly copyFeedbackDurationMs: 2000;
53
55
  }>;
56
+ /*********************************************************
57
+ * ORIGAM_CODE_KEY
58
+ *
59
+ * @description
60
+ * Provide/inject key for the `code` block of `createOrigam()`'s options
61
+ * (`ICodeOptions` — today just `highlighter`). `useCode()` reads it via
62
+ * `inject(ORIGAM_CODE_KEY)` — optional on purpose: an app that never calls
63
+ * `createOrigam({ code })`, or that never installs the plugin at all, gets
64
+ * `undefined` and `loadHighlighter()` falls back to the DS's own
65
+ * `import('shiki')` path unchanged. See `code.composable.ts`.
66
+ ********************************************************/
67
+ export declare const ORIGAM_CODE_KEY: InjectionKey<ICodeOptions>;
@@ -30,3 +30,4 @@ export const CODE_DEFAULTS = Object.freeze({
30
30
  */
31
31
  copyFeedbackDurationMs: 2e3
32
32
  });
33
+ export const ORIGAM_CODE_KEY = /* @__PURE__ */ Symbol.for("origam:code");
@@ -10,8 +10,8 @@ import type { IMarginProps } from '../Commons/margin.interface';
10
10
  import type { IPaddingProps } from '../Commons/padding.interface';
11
11
  import type { IRoundedProps } from '../Commons/rounded.interface';
12
12
  import type { ISizeProps } from '../Commons/size.interface';
13
- import type { IVariantProps } from '../Commons/variant.interface';
14
- export interface IBtnGroupProps extends ITagProps, ICommonsComponentProps, IRoundedProps, IBorderProps, IDensityProps, IElevationProps, IColorProps, IBgColorProps, IMarginProps, IPaddingProps, IHoverProps, IActiveProps, IVariantProps, ISizeProps {
13
+ import type { IActionVariantProps } from '../Commons/variant.interface';
14
+ export interface IBtnGroupProps extends ITagProps, ICommonsComponentProps, IRoundedProps, IBorderProps, IDensityProps, IElevationProps, IColorProps, IBgColorProps, IMarginProps, IPaddingProps, IHoverProps, IActiveProps, IActionVariantProps, ISizeProps {
15
15
  divided?: boolean;
16
16
  items?: Array<IBtnProps>;
17
17
  }
@@ -18,14 +18,14 @@ import type { IRippleProps } from '../Commons/ripple.interface';
18
18
  import type { IRoundedProps } from '../Commons/rounded.interface';
19
19
  import type { ISizeProps } from '../Commons/size.interface';
20
20
  import type { ITypographyProps } from '../Commons/typography.interface';
21
- import type { IVariantProps } from '../Commons/variant.interface';
21
+ import type { IActionVariantProps } from '../Commons/variant.interface';
22
22
  import type { TIcon } from '../../types/Icon/icon.type';
23
23
  import type { TStatus, TStatusPosition } from '../../types/Commons/status.type';
24
24
  /** Btn needs `status` / `statusIconPosition` from IStatusProps but its own
25
25
  * `icon` prop accepts `boolean | TIcon` (boolean = icon-only mode) which is
26
26
  * wider than `IIconProps.icon?: TIcon`. Pulling the two status props in
27
27
  * directly avoids the TS2430 incompatible-extends error. */
28
- export interface IBtnProps extends ICommonsComponentProps, IColorProps, IBgColorProps, IBorderProps, IDensityProps, IDimensionProps, IElevationProps, IRoundedProps, ITagProps, ISizeProps, ILinkProps, IRippleProps, ILoaderProps, IPositionProps, ILocationProps, IGroupItemProps, IPaddingProps, IMarginProps, IAdjacentProps, IHoverProps, IActiveProps, IVariantProps, Pick<ITypographyProps, 'fontSize' | 'fontWeight' | 'lineHeight' | 'letterSpacing'> {
28
+ export interface IBtnProps extends ICommonsComponentProps, IColorProps, IBgColorProps, IBorderProps, IDensityProps, IDimensionProps, IElevationProps, IRoundedProps, ITagProps, ISizeProps, ILinkProps, IRippleProps, ILoaderProps, IPositionProps, ILocationProps, IGroupItemProps, IPaddingProps, IMarginProps, IAdjacentProps, IHoverProps, IActiveProps, IActionVariantProps, Pick<ITypographyProps, 'fontSize' | 'fontWeight' | 'lineHeight' | 'letterSpacing'> {
29
29
  /** @deprecated Use `variant="flat"` instead. Kept for backward compat. */
30
30
  flat?: boolean;
31
31
  /** Pass `true` to activate icon-only mode; pass a `TIcon` value to set the icon. */
@@ -7,7 +7,7 @@ import type { IMarginProps } from '../Commons/margin.interface';
7
7
  import type { IPaddingProps } from '../Commons/padding.interface';
8
8
  import type { IRoundedProps } from '../Commons/rounded.interface';
9
9
  import type { ITypographyProps } from '../Commons/typography.interface';
10
- import type { TCodeLang } from '../../types/Code/code.type';
10
+ import type { TCodeLang, TShikiHighlighterLoader } from '../../types/Code/code.type';
11
11
  /**
12
12
  * Props for `<OrigamCode>` — a shiki-powered code block with line numbers,
13
13
  * line highlighting, copy button and theme awareness.
@@ -85,6 +85,38 @@ export interface ICodeProps extends ICommonsComponentProps, ITagProps, IBorderPr
85
85
  */
86
86
  prompt?: string;
87
87
  }
88
+ /*********************************************************
89
+ * ICodeOptions
90
+ *
91
+ * @description
92
+ * App-level config for `<OrigamCode>`, passed via `createOrigam({ code })`.
93
+ * Today it carries a single knob — `highlighter` — but it is its own
94
+ * interface (rather than a bare function on `IOrigamOptions`) so a future
95
+ * `OrigamCode`-wide setting (e.g. a default theme pair) has somewhere to
96
+ * land without another breaking shape change.
97
+ *
98
+ * @description
99
+ * `highlighter` supplies your own shiki-compatible module loader instead of
100
+ * the DS's default `import('shiki')` (see `code.composable.ts`'s
101
+ * `loadHighlighter()`). Absent (default) — `useCode()` keeps loading the
102
+ * full `shiki` package exactly as before, nothing changes for a consumer
103
+ * who does not set this. Supplied — the DS never touches `shiki` itself: no
104
+ * bare-specifier dynamic import, no `@vite-ignore`, no WASM-loader chunk in
105
+ * THIS path. Typical use: an app bundling `shiki/core` + a JS regex engine
106
+ * (no WASM loader, no oniguruma binary) to shrink the syntax-highlighting
107
+ * cost — any module exposing `createHighlighter` works, see `TShikiModule`.
108
+ *
109
+ * @description
110
+ * The loader is read once, synchronously, the first time `useCode()` is
111
+ * invoked inside a mounted `<OrigamCode>` — `useCode()` is a module-scoped
112
+ * singleton (one highlighter promise for the whole page), so the FIRST
113
+ * instance to resolve it wins for the lifetime of the page; later instances
114
+ * reuse that same highlighter regardless of their own `createOrigam()`
115
+ * ancestor.
116
+ ********************************************************/
117
+ export interface ICodeOptions {
118
+ highlighter?: TShikiHighlighterLoader;
119
+ }
88
120
  /** Emits fired by `<OrigamCode>` — copy-to-clipboard confirmation. */
89
121
  export interface ICodeEmits {
90
122
  (e: 'copy', code: string): void;
@@ -6,6 +6,7 @@ import type { IDisplayOptions } from './display.interface';
6
6
  import type { IGoToOptions } from './goTo.interface';
7
7
  import type { ILocaleOptions, IRtlOptions } from './locale.interface';
8
8
  import type { IOrigamTheme } from './theme.interface';
9
+ import type { ICodeOptions } from '../Code/code.interface';
9
10
  import { TIconOptions } from '../../types/Icon/icon.type';
10
11
  import { TOrigamPluginOptionsImport } from '../../types/Commons/commons.type';
11
12
  import { TSSROptions } from '../../types/Commons/display.type';
@@ -53,6 +54,7 @@ export interface IOrigamOptions {
53
54
  * injected. SSR-safe (injection is a no-op without `document`).
54
55
  */
55
56
  themes?: IOrigamTheme[];
57
+ code?: ICodeOptions;
56
58
  }
57
59
  export interface IOrigamPluginOptions {
58
60
  autoImport?: TOrigamPluginOptionsImport;
@@ -1,10 +1,32 @@
1
1
  import type { TVariant, TVariantInput } from '../../types/Commons/variant.type';
2
- /**
3
- * Mixin props for components that expose a visual variant. The union accepts
4
- * both action-style variants (`text/flat/elevated/tonal/outlined/plain`) and
5
- * input-style variants (`solo/filled/underlined/...`) so a single prop type
6
- * fits every consumer.
7
- */
8
- export interface IVariantProps {
9
- variant?: TVariant | TVariantInput;
2
+ /*********************************************************
3
+ * IActionVariantProps
4
+ *
5
+ * @description
6
+ * Mixin props for ACTION-style surfaces (Btn, BtnGroup, BtnToggle…) — the
7
+ * `VARIANT` enum taxonomy (`text/flat/elevated/tonal/outlined/plain/ghost`).
8
+ *
9
+ * @description
10
+ * Split from the former single `IVariantProps` (#1050 / ADR-005 follow-up):
11
+ * that mixin's union accepted BOTH this family's 7 values AND the input
12
+ * family's 5, so every one of the 14 consumers silently accepted 3-5 values
13
+ * it never implements (`underlined`/`filled`/`solo` here). Each family now
14
+ * only names the vocabulary it actually renders.
15
+ ********************************************************/
16
+ export interface IActionVariantProps {
17
+ variant?: TVariant;
18
+ }
19
+ /*********************************************************
20
+ * IInputVariantProps
21
+ *
22
+ * @description
23
+ * Mixin props for INPUT-style surfaces (Field and its descendants,
24
+ * ConfirmWrapper) — the `VARIANT_INPUT` enum taxonomy
25
+ * (`underlined/filled/solo/outlined/plain`).
26
+ *
27
+ * @description
28
+ * See `IActionVariantProps` above for why this was split out.
29
+ ********************************************************/
30
+ export interface IInputVariantProps {
31
+ variant?: TVariantInput;
10
32
  }
@@ -6,7 +6,7 @@ import type { IDirectionProps } from '../Commons/direction.interface';
6
6
  import type { IElevationProps } from '../Commons/elevation.interface';
7
7
  import type { IFocusProps } from '../Commons/focus.interface';
8
8
  import type { IRoundedProps } from '../Commons/rounded.interface';
9
- import type { IVariantProps } from '../Commons/variant.interface';
9
+ import type { IInputVariantProps } from '../Commons/variant.interface';
10
10
  /**
11
11
  * Props for `<OrigamConfirmWrapper>` — a "type-it-twice" form helper that
12
12
  * pairs a primary input with a confirmation input and lights up only when
@@ -15,8 +15,13 @@ import type { IVariantProps } from '../Commons/variant.interface';
15
15
  *
16
16
  * Inherits the standard form mixins so it slots into a Field/Form pipeline
17
17
  * alongside any other input control.
18
+ *
19
+ * `variant` is `IInputVariantProps` (not `IActionVariantProps`) — decided by
20
+ * the owner: ConfirmWrapper wraps form fields, so it only pushes a FIELD
21
+ * variant (`underlined/filled/solo/outlined/plain`), never an action-style
22
+ * one (#1050).
18
23
  */
19
- export interface IConfirmWrapperProps extends ICommonsComponentProps, IAdjacentProps, IDirectionProps, IColorProps, IDensityProps, IRoundedProps, IElevationProps, IVariantProps, IFocusProps {
24
+ export interface IConfirmWrapperProps extends ICommonsComponentProps, IAdjacentProps, IDirectionProps, IColorProps, IDensityProps, IRoundedProps, IElevationProps, IInputVariantProps, IFocusProps {
20
25
  modelValue?: any;
21
26
  confirm?: any;
22
27
  field?: string;
@@ -11,7 +11,7 @@ import type { ILoaderProps } from '../Commons/loader.interface';
11
11
  import type { IRoundedProps } from '../Commons/rounded.interface';
12
12
  import type { ISizeProps } from '../Commons/size.interface';
13
13
  import type { ITypographyProps } from '../Commons/typography.interface';
14
- import type { IVariantProps } from '../Commons/variant.interface';
14
+ import type { IInputVariantProps } from '../Commons/variant.interface';
15
15
  /*********************************************************
16
16
  * IFieldProps
17
17
  *
@@ -31,7 +31,7 @@ import type { IVariantProps } from '../Commons/variant.interface';
31
31
  * `--origam-field---border-*` token channel the three outline legs already
32
32
  * read, so the notch keeps opening under `--active` / `--focused`.
33
33
  ********************************************************/
34
- export interface IFieldProps extends ICommonsComponentProps, ILoaderProps, IColorProps, IBgColorProps, IAdjacentInnerProps, IBorderProps, IFocusProps, IDensityProps, ILabelProps, IActiveProps, IVariantProps, IRoundedProps, IElevationProps, ISizeProps, Pick<ITypographyProps, 'fontSize' | 'fontWeight' | 'lineHeight' | 'letterSpacing'> {
34
+ export interface IFieldProps extends ICommonsComponentProps, ILoaderProps, IColorProps, IBgColorProps, IAdjacentInnerProps, IBorderProps, IFocusProps, IDensityProps, ILabelProps, IActiveProps, IInputVariantProps, IRoundedProps, IElevationProps, ISizeProps, Pick<ITypographyProps, 'fontSize' | 'fontWeight' | 'lineHeight' | 'letterSpacing'> {
35
35
  centerAffix?: boolean;
36
36
  dirty?: boolean;
37
37
  disabled?: boolean;
@@ -2,9 +2,9 @@ import type { IAdjacentInnerEmits } from '../Commons/adjacent.interface';
2
2
  import type { IFocusEmits } from '../Commons/focus.interface';
3
3
  import type { IFieldProps, IFieldSlots } from '../Field/field.interface';
4
4
  import type { IInputEmits, IInputProps, IInputSlots } from '../Input/input.interface';
5
- import type { IVariantProps } from '../Commons/variant.interface';
5
+ import type { IInputVariantProps } from '../Commons/variant.interface';
6
6
  import type { TIcon } from '../../types/Icon/icon.type';
7
- export interface INumberFieldProps extends IFieldProps, IInputProps, IVariantProps {
7
+ export interface INumberFieldProps extends IFieldProps, IInputProps, IInputVariantProps {
8
8
  autofocus?: boolean;
9
9
  placeholder?: string;
10
10
  persistentPlaceholder?: boolean;
@@ -3,7 +3,7 @@ import type { ICommonsComponentEmits } from '../Commons/commons.interface';
3
3
  import type { IFocusEmits } from '../Commons/focus.interface';
4
4
  import type { IFieldProps, IFieldSlots } from '../Field/field.interface';
5
5
  import type { IInputProps, IInputSlots } from '../Input/input.interface';
6
- import type { IVariantProps } from '../Commons/variant.interface';
6
+ import type { IInputVariantProps } from '../Commons/variant.interface';
7
7
  import type { ITypographyProps } from '../Commons/typography.interface';
8
8
  import type { TOtpInputFieldType } from '../../types/OtpInputField/otp-input-field.type';
9
9
  /*********************************************************
@@ -43,7 +43,7 @@ import type { TOtpInputFieldType } from '../../types/OtpInputField/otp-input-fie
43
43
  * → `IAdjacentInnerProps`, reach `<origam-field>` via `fieldProps()`, and were
44
44
  * measured PRESENT in the same sweep.
45
45
  ********************************************************/
46
- export interface IOtpInputFieldProps extends Omit<IFieldProps, 'fontFamily' | 'fontWeight' | 'lineHeight' | 'letterSpacing'>, Omit<IInputProps, 'fontFamily' | 'fontWeight' | 'lineHeight' | 'letterSpacing' | 'prependIcon' | 'appendIcon' | 'prependAvatar' | 'appendAvatar' | 'prependAriaLabel' | 'appendAriaLabel'>, IVariantProps, Pick<ITypographyProps, 'fontSize'> {
46
+ export interface IOtpInputFieldProps extends Omit<IFieldProps, 'fontFamily' | 'fontWeight' | 'lineHeight' | 'letterSpacing'>, Omit<IInputProps, 'fontFamily' | 'fontWeight' | 'lineHeight' | 'letterSpacing' | 'prependIcon' | 'appendIcon' | 'prependAvatar' | 'appendAvatar' | 'prependAriaLabel' | 'appendAriaLabel'>, IInputVariantProps, Pick<ITypographyProps, 'fontSize'> {
47
47
  autofocus?: boolean;
48
48
  divider?: string;
49
49
  focusAll?: boolean;
@@ -61,6 +61,7 @@ function createOrigam(origam = {}) {
61
61
  const appScope = (0, _vue.effectScope)();
62
62
  app.onUnmount(() => appScope.stop());
63
63
  app.provide(_consts.ORIGAM_ICONS_KEY, icons);
64
+ app.provide(_consts.ORIGAM_CODE_KEY, options.code ?? {});
64
65
  app.provide(_consts.ORIGAM_DISPLAY_KEY, display);
65
66
  app.provide(_consts.ORIGAM_LOCALE_KEY, locale);
66
67
  app.provide(_consts.ORIGAM_DATE_OPTIONS_KEY, date.options);
@@ -12,6 +12,7 @@ import {
12
12
  } from "./composables/index.js";
13
13
  import {
14
14
  IN_BROWSER,
15
+ ORIGAM_CODE_KEY,
15
16
  ORIGAM_DATE_ADAPTER_KEY,
16
17
  ORIGAM_DATE_OPTIONS_KEY,
17
18
  ORIGAM_DEFAULTS_KEY,
@@ -79,6 +80,7 @@ export function createOrigam(origam = {}) {
79
80
  const appScope = effectScope();
80
81
  app.onUnmount(() => appScope.stop());
81
82
  app.provide(ORIGAM_ICONS_KEY, icons);
83
+ app.provide(ORIGAM_CODE_KEY, options.code ?? {});
82
84
  app.provide(ORIGAM_DISPLAY_KEY, display);
83
85
  app.provide(ORIGAM_LOCALE_KEY, locale);
84
86
  app.provide(ORIGAM_DATE_OPTIONS_KEY, date.options);
@@ -22,3 +22,32 @@ export type TShikiHighlighter = {
22
22
  defaultColor?: false | string;
23
23
  }) => string;
24
24
  };
25
+ /*********************************************************
26
+ * TShikiModule / TShikiHighlighterLoader
27
+ *
28
+ * @description
29
+ * `TShikiModule` is the slice of a shiki-COMPATIBLE MODULE that `useCode()`
30
+ * needs to build a highlighter — i.e. what `import('shiki')` (the DS's own
31
+ * default) or an app-supplied alternative must resolve to. Deliberately
32
+ * minimal, for the same reason `TShikiHighlighter` is: an app that wants to
33
+ * avoid shiki's WASM-loader chunk (see `code.composable.ts`'s
34
+ * `loadHighlighter()`) can hand `createOrigam({ code: { highlighter } })`
35
+ * a loader resolving to `shiki/core` + a regex engine — or any other
36
+ * module — as long as it exposes this one method. `shiki`'s own
37
+ * `createHighlighter` satisfies this type structurally; no cast needed on
38
+ * the consumer side.
39
+ *
40
+ * @description
41
+ * `TShikiHighlighterLoader` is the function shape an app passes as
42
+ * `createOrigam({ code: { highlighter } })` to supply that module instead
43
+ * of the DS's default `import('shiki')`. See `code.composable.ts`'s
44
+ * `loadHighlighter()` for how this branches the dynamic-import path, and
45
+ * `ICodeOptions` for the option itself.
46
+ ********************************************************/
47
+ export type TShikiModule = {
48
+ createHighlighter: (opts: {
49
+ themes: ReadonlyArray<string>;
50
+ langs: ReadonlyArray<string>;
51
+ }) => Promise<TShikiHighlighter>;
52
+ };
53
+ export type TShikiHighlighterLoader = () => Promise<TShikiModule>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "origam",
3
- "version": "2.22.0",
3
+ "version": "2.23.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": [