@animus-ui/system 0.1.11 → 0.1.12

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.
Files changed (85) hide show
  1. package/README.md +124 -51
  2. package/dist/Animus.d.ts +1 -1
  3. package/dist/Animus.d.ts.map +1 -1
  4. package/dist/AnimusExtended.d.ts +1 -1
  5. package/dist/AnimusExtended.d.ts.map +1 -1
  6. package/dist/SystemBuilder.d.ts +184 -155
  7. package/dist/SystemBuilder.d.ts.map +1 -1
  8. package/dist/appearance/index.d.ts +0 -68
  9. package/dist/appearance/index.d.ts.map +1 -1
  10. package/dist/appearance/index.js +0 -91
  11. package/dist/assert-root-slot-C3Lp9MNJ.js +10 -0
  12. package/dist/asset.d.ts +4 -13
  13. package/dist/asset.d.ts.map +1 -1
  14. package/dist/bootstrap/createAppearanceBootstrap.d.ts +0 -57
  15. package/dist/bootstrap/createAppearanceBootstrap.d.ts.map +1 -1
  16. package/dist/bootstrap/index.d.ts.map +1 -1
  17. package/dist/bootstrap/index.js +4 -58
  18. package/dist/class-resolver.d.ts +2 -4
  19. package/dist/class-resolver.d.ts.map +1 -1
  20. package/dist/class-resolver.js +1 -1
  21. package/dist/compose.d.ts +2 -16
  22. package/dist/compose.d.ts.map +1 -1
  23. package/dist/compose.js +3 -17
  24. package/dist/composeWithContext.d.ts +4 -15
  25. package/dist/composeWithContext.d.ts.map +1 -1
  26. package/dist/composeWithContext.js +5 -16
  27. package/dist/conditions.d.ts +24 -141
  28. package/dist/conditions.d.ts.map +1 -1
  29. package/dist/{createClassResolver-BWyEQ5KZ.js → createClassResolver-EpwTL9Sa.js} +12 -113
  30. package/dist/{createComposedFamily-k5tTujGI.js → createComposedFamily-C4NovMcd.js} +11 -49
  31. package/dist/groups/index.js +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +318 -409
  35. package/dist/keyframes.d.ts +2 -23
  36. package/dist/keyframes.d.ts.map +1 -1
  37. package/dist/runtime/assert-root-slot.d.ts +2 -13
  38. package/dist/runtime/assert-root-slot.d.ts.map +1 -1
  39. package/dist/runtime/createClassResolver.d.ts +0 -8
  40. package/dist/runtime/createClassResolver.d.ts.map +1 -1
  41. package/dist/runtime/createComposedFamily.d.ts +2 -7
  42. package/dist/runtime/createComposedFamily.d.ts.map +1 -1
  43. package/dist/runtime/index.d.ts +0 -16
  44. package/dist/runtime/index.d.ts.map +1 -1
  45. package/dist/runtime/is-dev.d.ts +2 -42
  46. package/dist/runtime/is-dev.d.ts.map +1 -1
  47. package/dist/runtime/resolveClasses.d.ts +8 -33
  48. package/dist/runtime/resolveClasses.d.ts.map +1 -1
  49. package/dist/runtime/witness.d.ts +0 -8
  50. package/dist/runtime/witness.d.ts.map +1 -1
  51. package/dist/runtime-entry.d.ts +1 -6
  52. package/dist/runtime-entry.d.ts.map +1 -1
  53. package/dist/runtime-entry.js +2 -2
  54. package/dist/selectors.d.ts +6 -45
  55. package/dist/selectors.d.ts.map +1 -1
  56. package/dist/{size-CcVEGaen.js → size-C6jqxiQy.js} +7 -34
  57. package/dist/theme/createTheme.d.ts +26 -95
  58. package/dist/theme/createTheme.d.ts.map +1 -1
  59. package/dist/theme/flattenScale.d.ts +4 -10
  60. package/dist/theme/flattenScale.d.ts.map +1 -1
  61. package/dist/theme/resolveReferences.d.ts +7 -35
  62. package/dist/theme/resolveReferences.d.ts.map +1 -1
  63. package/dist/theme/serializeTokens.d.ts +0 -3
  64. package/dist/theme/serializeTokens.d.ts.map +1 -1
  65. package/dist/theme/types.d.ts +4 -26
  66. package/dist/theme/types.d.ts.map +1 -1
  67. package/dist/theme/utils.d.ts +1 -18
  68. package/dist/theme/utils.d.ts.map +1 -1
  69. package/dist/transforms/border.d.ts +1 -4
  70. package/dist/transforms/border.d.ts.map +1 -1
  71. package/dist/transforms/createTransform.d.ts +6 -31
  72. package/dist/transforms/createTransform.d.ts.map +1 -1
  73. package/dist/transforms/grid.d.ts +2 -12
  74. package/dist/transforms/grid.d.ts.map +1 -1
  75. package/dist/transforms/size.d.ts +2 -8
  76. package/dist/transforms/size.d.ts.map +1 -1
  77. package/dist/types/component.d.ts +9 -105
  78. package/dist/types/component.d.ts.map +1 -1
  79. package/dist/types/config.d.ts +12 -141
  80. package/dist/types/config.d.ts.map +1 -1
  81. package/dist/types/theme.d.ts +8 -165
  82. package/dist/types/theme.d.ts.map +1 -1
  83. package/dist/utils/deepMerge.d.ts.map +1 -1
  84. package/package.json +4 -4
  85. package/dist/assert-root-slot-B73sDJ1Q.js +0 -21
@@ -1,41 +1,8 @@
1
1
  //#region src/appearance/index.ts
2
- /**
3
- * Appearance record write path — the CLIENT half of the contract the generated
4
- * bootstrap reads (openspec: color-mode-bootstrap, "Appearance record
5
- * contract").
6
- *
7
- * This module is runtime application code: it ships in client bundles and owns
8
- * only the record WRITE path. It deliberately imports nothing from
9
- * `@animus-ui/system/bootstrap` — that subpath is build tooling, reaches
10
- * `node:crypto`, and must never enter an application bundle — so the two
11
- * modules re-state the key and shape they agree on, and the round-trip tests
12
- * pin the agreement (a record written here is restored by the generated
13
- * snippet).
14
- *
15
- * Record: `animus:appearance` → `{"v":1,"mode":…,"theme":…}`.
16
- *
17
- * Two axes share one record. A writer that changes ONE axis reads, modifies
18
- * and writes back, so fields it does not own (`theme`, plus anything a future
19
- * version adds) survive untouched.
20
- */
21
- /** The single versioned appearance record key. */
22
2
  const DEFAULT_STORAGE_KEY = "animus:appearance";
23
- /**
24
- * The CONTRACT's pre-record key. The generated bootstrap reads it once, only
25
- * when the record is absent, and never writes it — it may belong to another
26
- * app on this origin, so this module refuses to migrate (and therefore
27
- * delete) it. See {@link migrateLegacyModeKey}.
28
- */
29
3
  const CONTRACT_LEGACY_KEY = "color-mode";
30
- /** The only appearance-record version this module writes or read-modify-writes. */
31
4
  const RECORD_VERSION = 1;
32
- /**
33
- * Mode value meaning "follow the OS". It is never a declared mode and never
34
- * reaches `data-color-mode` — the OS is followed by the attribute's ABSENCE,
35
- * which the generated bootstrap restores when it reads this value.
36
- */
37
5
  const SYSTEM_MODE = "system";
38
- /** Applied when nothing is stored: OS-driven mode, default theme. */
39
6
  const DEFAULT_RECORD = {
40
7
  v: RECORD_VERSION,
41
8
  mode: SYSTEM_MODE,
@@ -49,25 +16,6 @@ function keyOf(options) {
49
16
  if (typeof key !== "string" || key === "") throw new Error("appearance: storageKey must be a non-empty string.");
50
17
  return key;
51
18
  }
52
- /**
53
- * Reads the stored record.
54
- *
55
- * READ FAILURE vs. ABSENT: a `getItem` that THROWS (blocked or partitioned
56
- * storage) — or no storage object at all — is reported as `absent`, not
57
- * `foreign`, deliberately. "Absent" here means "this code has no knowledge of
58
- * a stored record", and a store we cannot read at all is indistinguishable
59
- * from an empty one. The asymmetry is safe because the accompanying write is
60
- * wrapped in its own try/catch: a store that throws on read throws on write
61
- * too, so the `absent` classification can never actually clobber anything.
62
- * Only a store we CAN read and whose content we cannot interpret yields
63
- * `foreign`.
64
- *
65
- * A present-but-corrupt value (not JSON, not an object) is `absent`: it is
66
- * nobody's live state, so replacing it with a clean record is a repair. A
67
- * present record carrying an unrecognized `v` is `foreign`: that is a future
68
- * writer's data, and v1-shaped fields written over it would destroy fields
69
- * this version does not know exist.
70
- */
71
19
  function readRecord(storageKey) {
72
20
  let raw = null;
73
21
  try {
@@ -90,24 +38,6 @@ function readRecord(storageKey) {
90
38
  record
91
39
  };
92
40
  }
93
- /**
94
- * Persists the mode axis, preserving every field this call does not own
95
- * (`v`, `theme`, and any additional keys already in the record).
96
- *
97
- * Pass {@link SYSTEM_MODE} to persist "follow the OS" — the generated
98
- * bootstrap restores it as attribute absence. Applying the mode to the
99
- * document (setting or removing `data-color-mode`) stays the caller's job:
100
- * this module is storage-only and never touches the DOM.
101
- *
102
- * REFUSAL RULE: when the stored record carries a version this code does not
103
- * understand, NOTHING is written. Downgrading it to a v1 shape would drop
104
- * whatever fields the newer writer keeps there, and this axis is not worth
105
- * that. A caller that has already updated the attribute keeps the user's
106
- * choice for the session — only its persistence is skipped.
107
- *
108
- * Storage failures are likewise swallowed: persistence is a convenience, and
109
- * the attribute write that accompanies it has already taken effect.
110
- */
111
41
  function persistColorMode(mode, options) {
112
42
  const storageKey = keyOf(options);
113
43
  const outcome = readRecord(storageKey);
@@ -120,27 +50,6 @@ function persistColorMode(mode, options) {
120
50
  }));
121
51
  } catch {}
122
52
  }
123
- /**
124
- * One-shot migration of an application's OWN historical mode key into the
125
- * record.
126
- *
127
- * The generated bootstrap only knows the record and the contract's `color-mode`
128
- * key — an app that persisted under its own key before adopting the record
129
- * would silently drop every returning visitor's mode without this. Run it
130
- * post-paint from the app entry: the visit on which it migrates still paints
131
- * in the OS-resolved mode before correcting itself — one accepted flash, once
132
- * — and every later load restores pre-paint through the bootstrap.
133
- *
134
- * It writes only when there is nothing to lose (no record) and something worth
135
- * keeping (a value in `declaredModes`), then DELETES the old key so the
136
- * migration cannot run twice or resurrect a stale value. Deleting is
137
- * legitimate precisely because the key is the application's own; the
138
- * contract's `color-mode` key may belong to another app on this origin and is
139
- * refused, as is the record key itself.
140
- *
141
- * @returns the migrated mode name, so the caller can apply it to the document
142
- * for this one visit, or `null` when nothing was migrated.
143
- */
144
53
  function migrateLegacyModeKey(legacyKey, declaredModes, options) {
145
54
  const storageKey = keyOf(options);
146
55
  if (legacyKey === CONTRACT_LEGACY_KEY) throw new Error(`appearance: '${CONTRACT_LEGACY_KEY}' is the contract's shared legacy key — the generated bootstrap reads it read-only and it may belong to another app on this origin. Migrate only keys your application owns.`);
@@ -0,0 +1,10 @@
1
+ //#region src/runtime/assert-root-slot.ts
2
+ /**
3
+ * Without a Root slot a family has no cascade source: composed child rules
4
+ * inherit nothing and the context transport renders the empty default.
5
+ */
6
+ function assertRootSlot(slots, fnName) {
7
+ if (!Object.prototype.propertyIsEnumerable.call(slots, "Root")) throw new Error(`${fnName}(): No "Root" slot found. The root slot key must be exactly "Root" (PascalCase).`);
8
+ }
9
+ //#endregion
10
+ export { assertRootSlot as t };
package/dist/asset.d.ts CHANGED
@@ -1,24 +1,15 @@
1
1
  declare const ASSET_REF_BRAND: unique symbol;
2
2
  /**
3
- * A branded package-asset reference for `fontFaces[].src[].url`
4
- * (global-styles-system). The VALUE is the deterministic placeholder
5
- * `animus-asset:<specifier>` — a plain string, so it survives the QuickJS
6
- * sandbox's JSON serialization and the extraction emitter's byte-exact url
7
- * pass-through untouched. The HOST plugin substitutes the placeholder with
8
- * the bundler-resolved asset URL after extraction; the sandbox never
9
- * resolves anything.
3
+ * A plain string so it crosses the sandbox's JSON boundary untouched; the host
4
+ * plugin substitutes the placeholder with the bundler-resolved URL.
10
5
  */
11
6
  export type AssetRef = string & {
12
7
  readonly [ASSET_REF_BRAND]: true;
13
8
  };
14
- /** The reserved scheme marking an unsubstituted asset reference. */
15
9
  export declare const ASSET_PLACEHOLDER_PREFIX = "animus-asset:";
16
10
  /**
17
- * Reference a package-owned asset (e.g. a font file) by module specifier:
18
- * `asset('@acme/tokens/fonts/inter.woff2')`. Resolution — aliases, exports
19
- * maps, `base`, content hashing — belongs to the host bundler; this function
20
- * only brands the specifier into its placeholder form. A literal URL string
21
- * (`'/fonts/inter.woff2'`) remains the pass-through alternative.
11
+ * Brands the specifier only — aliases, exports maps and hashing belong to the
12
+ * host bundler. A literal URL string stays a valid alternative.
22
13
  */
23
14
  export declare function asset(specifier: string): AssetRef;
24
15
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../src/asset.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,eAAe,EAAE,OAAO,MAAM,CAAC;AAE7C;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAErE,oEAAoE;AACpE,eAAO,MAAM,wBAAwB,kBAAkB,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAEjD"}
1
+ {"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../src/asset.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,eAAe,EAAE,OAAO,MAAM,CAAC;AAE7C;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAErE,eAAO,MAAM,wBAAwB,kBAAkB,CAAC;AAExD;;;GAGG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAEjD"}
@@ -1,71 +1,14 @@
1
- /**
2
- * The slice of a built theme the generator reads: the declared mode names.
3
- * Structural on purpose — the generator reads mode KEYS only and never touches
4
- * the theme's pipeline wire (guardrail G5).
5
- */
6
1
  export interface AppearanceBootstrapTheme {
7
2
  manifest: {
8
- /** Mode name → resolved tokens. Only the KEYS are read. */
9
3
  modes?: Record<string, unknown>;
10
4
  };
11
5
  }
12
6
  export interface AppearanceBootstrapOptions {
13
- /** Overrides the record key. Defaults to `animus:appearance`. */
14
7
  storageKey?: string;
15
8
  }
16
9
  export interface AppearanceBootstrapArtifact {
17
- /** Dependency-free inline IIFE, safe to embed in a document head. */
18
10
  code: string;
19
- /**
20
- * `sha256-<base64>` — the CSP hash of `code`, ready for a `script-src`
21
- * source list.
22
- *
23
- * The source expression MUST be SINGLE-QUOTED in the header, exactly as
24
- * returned:
25
- *
26
- * ```
27
- * Content-Security-Policy: script-src 'sha256-<the artifact hash>'
28
- * ```
29
- *
30
- * Unquoted, it is parsed as a host source and silently fails to authorize
31
- * the script.
32
- *
33
- * Always derive the header from this field at build time — never hand-copy
34
- * it. Any theme edit that changes the declared mode names (or a changed
35
- * `storageKey`) changes `code` and therefore this hash; a stale literal in a
36
- * config file turns into a blocked script and a flash of the wrong mode.
37
- */
38
11
  cspHash: string;
39
12
  }
40
- /**
41
- * Builds the inline appearance-restoration script for a built theme.
42
- *
43
- * The generated snippet, before first paint:
44
- * 1. reads the appearance record from `storageKey`, falling back to the legacy
45
- * `color-mode` key ONLY when the record is absent (missing key, or an empty
46
- * string, which is not a record);
47
- * 2. accepts the record only at version `1` — a future or absent version is
48
- * treated as NO record, because an older snippet cannot interpret a newer
49
- * record and absence is the neutral fail-safe;
50
- * 3. sets `data-color-mode` when the resulting name is a declared mode;
51
- * 4. removes the attribute for `system`, no record, an unreadable store, or an
52
- * unknown mode — absence is how "follow the OS" is represented, so later OS
53
- * changes apply with no script running.
54
- *
55
- * The failure semantics are deliberately asymmetric:
56
- * - storage that THROWS on read (private browsing, blocked storage) means "no
57
- * knowledge", so the attribute is REMOVED and the media-query fallback takes
58
- * over; freezing a server-rendered mode would defeat that fallback;
59
- * - a record that is PRESENT but unparseable means "storage is telling us
60
- * something we cannot read", so the snippet exits leaving the server-rendered
61
- * markup exactly as it was.
62
- *
63
- * It never writes storage, never calls `matchMedia`, and ignores the record's
64
- * `theme` axis. Identical inputs always yield byte-identical output.
65
- *
66
- * @throws if the theme declares no color modes (a bootstrap without a mode
67
- * allowlist could not validate anything), declares the reserved name
68
- * `system`, or declares a blank mode name.
69
- */
70
13
  export declare function createAppearanceBootstrap(theme: AppearanceBootstrapTheme, options?: AppearanceBootstrapOptions): AppearanceBootstrapArtifact;
71
14
  //# sourceMappingURL=createAppearanceBootstrap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createAppearanceBootstrap.d.ts","sourceRoot":"","sources":["../../src/bootstrap/createAppearanceBootstrap.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE;QACR,2DAA2D;QAC3D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,2BAA2B;IAC1C,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,wBAAwB,EAC/B,OAAO,GAAE,0BAA+B,GACvC,2BAA2B,CAsE7B"}
1
+ {"version":3,"file":"createAppearanceBootstrap.d.ts","sourceRoot":"","sources":["../../src/bootstrap/createAppearanceBootstrap.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAyBD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,wBAAwB,EAC/B,OAAO,GAAE,0BAA+B,GACvC,2BAA2B,CAuD7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bootstrap/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bootstrap/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC"}
@@ -1,39 +1,15 @@
1
1
  import { createHash } from "node:crypto";
2
2
  //#region src/bootstrap/createAppearanceBootstrap.ts
3
- /**
4
- * Appearance bootstrap generator — build-tooling surface ONLY.
5
- *
6
- * This module is reachable exclusively from the `@animus-ui/system/bootstrap`
7
- * subpath. It is never imported by the component/runtime entries, so no part of
8
- * it (including the storage keys below) can reach an extracted application
9
- * bundle.
10
- */
11
- /** The single versioned appearance record key. */
12
3
  const DEFAULT_STORAGE_KEY = "animus:appearance";
13
- /**
14
- * Pre-record key read once, only when the record is absent. Never written —
15
- * migration is read-only by contract.
16
- */
17
4
  const LEGACY_STORAGE_KEY = "color-mode";
18
- /** The mode axis attribute. Its ABSENCE means "follow the OS" (D4). */
19
5
  const MODE_ATTRIBUTE = "data-color-mode";
20
- /**
21
- * Reserved mode name. `system` is modeled as attribute absence and can never be
22
- * a declared mode, so it must never enter the generated allowlist.
23
- */
24
6
  const RESERVED_MODE_NAME = "system";
25
- /** The only appearance-record version this generation of the snippet reads. */
26
7
  const RECORD_VERSION = 1;
27
8
  /**
28
- * Renders a string as a JS literal that is also safe inside an inline
29
- * `<script>` and inside a consumer's own string context:
30
- * - `<` is escaped, so an embedded value can never open a closing tag or an
31
- * HTML comment;
32
- * - U+2028/U+2029 are escaped, so `code` survives being nested in string
33
- * contexts that still treat them as line terminators.
34
- *
35
- * Character-wise on purpose: this file stays pure ASCII, so no invisible
36
- * separator can hide in it.
9
+ * Renders a JS string literal safe inside an inline `<script>`: `<` cannot open
10
+ * a closing tag, and U+2028/U+2029 survive nesting in string contexts. The loop
11
+ * compares code points rather than matching literal separators, so no invisible
12
+ * character has to appear in this source — keep it that way.
37
13
  */
38
14
  function inlineLiteral(value) {
39
15
  let out = "";
@@ -51,36 +27,6 @@ function inlineLiteral(value) {
51
27
  }
52
28
  return out;
53
29
  }
54
- /**
55
- * Builds the inline appearance-restoration script for a built theme.
56
- *
57
- * The generated snippet, before first paint:
58
- * 1. reads the appearance record from `storageKey`, falling back to the legacy
59
- * `color-mode` key ONLY when the record is absent (missing key, or an empty
60
- * string, which is not a record);
61
- * 2. accepts the record only at version `1` — a future or absent version is
62
- * treated as NO record, because an older snippet cannot interpret a newer
63
- * record and absence is the neutral fail-safe;
64
- * 3. sets `data-color-mode` when the resulting name is a declared mode;
65
- * 4. removes the attribute for `system`, no record, an unreadable store, or an
66
- * unknown mode — absence is how "follow the OS" is represented, so later OS
67
- * changes apply with no script running.
68
- *
69
- * The failure semantics are deliberately asymmetric:
70
- * - storage that THROWS on read (private browsing, blocked storage) means "no
71
- * knowledge", so the attribute is REMOVED and the media-query fallback takes
72
- * over; freezing a server-rendered mode would defeat that fallback;
73
- * - a record that is PRESENT but unparseable means "storage is telling us
74
- * something we cannot read", so the snippet exits leaving the server-rendered
75
- * markup exactly as it was.
76
- *
77
- * It never writes storage, never calls `matchMedia`, and ignores the record's
78
- * `theme` axis. Identical inputs always yield byte-identical output.
79
- *
80
- * @throws if the theme declares no color modes (a bootstrap without a mode
81
- * allowlist could not validate anything), declares the reserved name
82
- * `system`, or declares a blank mode name.
83
- */
84
30
  function createAppearanceBootstrap(theme, options = {}) {
85
31
  const { storageKey = DEFAULT_STORAGE_KEY } = options;
86
32
  if (typeof storageKey !== "string" || storageKey === "") throw new Error("createAppearanceBootstrap: storageKey must be a non-empty string.");
@@ -1,8 +1,6 @@
1
1
  /**
2
- * Framework-neutral runtime for `.asClass()` output.
3
- *
4
- * This entry intentionally excludes the React component runtime so non-React
5
- * consumers can install and bundle class resolvers without React.
2
+ * Excludes the React component runtime so non-React consumers can bundle
3
+ * class resolvers without installing React.
6
4
  */
7
5
  export { type ClassResolver, type ClassResolverAttributes, createClassResolver, } from './runtime/createClassResolver.js';
8
6
  //# sourceMappingURL=class-resolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"class-resolver.d.ts","sourceRoot":"","sources":["../src/class-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC5B,mBAAmB,GACpB,MAAM,kCAAkC,CAAC"}
1
+ {"version":3,"file":"class-resolver.d.ts","sourceRoot":"","sources":["../src/class-resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC5B,mBAAmB,GACpB,MAAM,kCAAkC,CAAC"}
@@ -1,2 +1,2 @@
1
- import { t as createClassResolver } from "./createClassResolver-BWyEQ5KZ.js";
1
+ import { t as createClassResolver } from "./createClassResolver-EpwTL9Sa.js";
2
2
  export { createClassResolver };
package/dist/compose.d.ts CHANGED
@@ -1,21 +1,7 @@
1
1
  import type { AnyBrandedComponent, ComposedFamily, SharedConfig } from './types/component';
2
2
  /**
3
- * Compose independently-authored Animus components into a sealed,
4
- * namespaced component family with shared variant propagation via
5
- * CSS cascade.
6
- *
7
- * - **Enforce**: TypeScript ensures shared keys exist on Root (the
8
- * cascade source). Non-Root slots that have the key consume it from
9
- * CSS inheritance; slots without the key are unaffected.
10
- * - **Wire**: The extraction pipeline emits composed variant CSS
11
- * rules — two per shared variant option per child (inheritance +
12
- * override) within @layer variants.
13
- * - **Seal**: Output components are plain ForwardRefExoticComponent —
14
- * no `.extend()`, no builder methods. One-way door from builder-land
15
- * to component-land.
16
- *
17
- * For React context propagation (portal-crossing), use
18
- * `composeWithContext` from `@animus-ui/system/compose-with-context`.
3
+ * Shared variants propagate through the CSS cascade, so a slot only inherits
4
+ * as a DOM descendant of Root; `composeWithContext` covers portaled children.
19
5
  */
20
6
  export declare function compose<Slots extends {
21
7
  Root: AnyBrandedComponent;
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,KAAK,SAAS;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAAG,MAAM,CAClD,MAAM,EACN,mBAAmB,CACpB,EACD,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,KAAK,CAAC,EAExC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAAC,KAAK,CAAC,CAoBvB"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,OAAO,CACrB,KAAK,SAAS;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAAG,MAAM,CAClD,MAAM,EACN,mBAAmB,CACpB,EACD,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,KAAK,CAAC,EAExC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAAC,KAAK,CAAC,CAoBvB"}
package/dist/compose.js CHANGED
@@ -1,23 +1,9 @@
1
- import { t as assertRootSlot } from "./assert-root-slot-B73sDJ1Q.js";
1
+ import { t as assertRootSlot } from "./assert-root-slot-C3Lp9MNJ.js";
2
2
  import { createElement, forwardRef } from "react";
3
3
  //#region src/compose.ts
4
4
  /**
5
- * Compose independently-authored Animus components into a sealed,
6
- * namespaced component family with shared variant propagation via
7
- * CSS cascade.
8
- *
9
- * - **Enforce**: TypeScript ensures shared keys exist on Root (the
10
- * cascade source). Non-Root slots that have the key consume it from
11
- * CSS inheritance; slots without the key are unaffected.
12
- * - **Wire**: The extraction pipeline emits composed variant CSS
13
- * rules — two per shared variant option per child (inheritance +
14
- * override) within @layer variants.
15
- * - **Seal**: Output components are plain ForwardRefExoticComponent —
16
- * no `.extend()`, no builder methods. One-way door from builder-land
17
- * to component-land.
18
- *
19
- * For React context propagation (portal-crossing), use
20
- * `composeWithContext` from `@animus-ui/system/compose-with-context`.
5
+ * Shared variants propagate through the CSS cascade, so a slot only inherits
6
+ * as a DOM descendant of Root; `composeWithContext` covers portaled children.
21
7
  */
22
8
  function compose(slots, options) {
23
9
  assertRootSlot(slots, "compose");
@@ -1,14 +1,8 @@
1
1
  import { type ForwardRefExoticComponent } from 'react';
2
2
  import type { AnyBrandedComponent, ComposedFamily, SharedConfig } from './types/component';
3
3
  /**
4
- * Compose components into a sealed family with shared variant propagation
5
- * via React context. Use this when children may be rendered in portals
6
- * or other React subtrees that escape the DOM hierarchy (where CSS
7
- * descendant selectors cannot reach).
8
- *
9
- * This function uses `createContext` and `useContext` — it is client-only.
10
- * For CSS-only propagation (RSC-safe), use `compose` from the barrel or
11
- * `@animus-ui/system/compose`.
4
+ * Context transport for shared variants, for children rendered in portals,
5
+ * where the CSS descendant selectors `compose` relies on cannot reach.
12
6
  */
13
7
  export declare function composeWithContext<Slots extends {
14
8
  Root: AnyBrandedComponent;
@@ -17,13 +11,8 @@ export declare function composeWithContext<Slots extends {
17
11
  name?: string;
18
12
  }): ComposedFamily<Slots>;
19
13
  /**
20
- * createComposedFamilyWithContext — extraction-time replacement for composeWithContext().
21
- *
22
- * The transform emitter replaces `composeWithContext({ Root, Body }, { shared, name })`
23
- * with `createComposedFamilyWithContext({ Root, Body }, { name, sharedKeys })`.
24
- *
25
- * Client-only: uses createContext and useContext. Files containing this function
26
- * receive a 'use client' directive from the transform emitter.
14
+ * The extraction emitter rewrites `composeWithContext()` calls to this form
15
+ * and adds the `'use client'` directive its context hooks require.
27
16
  */
28
17
  export declare function createComposedFamilyWithContext(slots: Record<string, ForwardRefExoticComponent<any>>, config: {
29
18
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"composeWithContext.d.ts","sourceRoot":"","sources":["../src/composeWithContext.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,yBAAyB,EAI/B,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,SAAS;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAAG,MAAM,CAClD,MAAM,EACN,mBAAmB,CACpB,EACD,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,KAAK,CAAC,EAExC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAAC,KAAK,CAAC,CA8DvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,EACrD,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAC7C,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,CAuDhD"}
1
+ {"version":3,"file":"composeWithContext.d.ts","sourceRoot":"","sources":["../src/composeWithContext.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,yBAAyB,EAI/B,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,SAAS;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAAG,MAAM,CAClD,MAAM,EACN,mBAAmB,CACpB,EACD,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,KAAK,CAAC,EAExC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAAC,KAAK,CAAC,CAuDvB;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,EACrD,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAC7C,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,CAkDhD"}
@@ -1,16 +1,10 @@
1
1
  "use client";
2
- import { t as assertRootSlot } from "./assert-root-slot-B73sDJ1Q.js";
2
+ import { t as assertRootSlot } from "./assert-root-slot-C3Lp9MNJ.js";
3
3
  import { createContext, createElement, forwardRef, useContext } from "react";
4
4
  //#region src/composeWithContext.ts
5
5
  /**
6
- * Compose components into a sealed family with shared variant propagation
7
- * via React context. Use this when children may be rendered in portals
8
- * or other React subtrees that escape the DOM hierarchy (where CSS
9
- * descendant selectors cannot reach).
10
- *
11
- * This function uses `createContext` and `useContext` — it is client-only.
12
- * For CSS-only propagation (RSC-safe), use `compose` from the barrel or
13
- * `@animus-ui/system/compose`.
6
+ * Context transport for shared variants, for children rendered in portals,
7
+ * where the CSS descendant selectors `compose` relies on cannot reach.
14
8
  */
15
9
  function composeWithContext(slots, options) {
16
10
  assertRootSlot(slots, "composeWithContext");
@@ -51,13 +45,8 @@ function composeWithContext(slots, options) {
51
45
  return result;
52
46
  }
53
47
  /**
54
- * createComposedFamilyWithContext — extraction-time replacement for composeWithContext().
55
- *
56
- * The transform emitter replaces `composeWithContext({ Root, Body }, { shared, name })`
57
- * with `createComposedFamilyWithContext({ Root, Body }, { name, sharedKeys })`.
58
- *
59
- * Client-only: uses createContext and useContext. Files containing this function
60
- * receive a 'use client' directive from the transform emitter.
48
+ * The extraction emitter rewrites `composeWithContext()` calls to this form
49
+ * and adds the `'use client'` directive its context hooks require.
61
50
  */
62
51
  function createComposedFamilyWithContext(slots, config) {
63
52
  assertRootSlot(slots, "createComposedFamilyWithContext");