@ui0/theme 0.0.0-stage → 0.1.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.
Files changed (148) hide show
  1. package/README.md +113 -2
  2. package/dist/backdrop.module.css +1 -0
  3. package/dist/backdrop.scss +7 -0
  4. package/dist/color.inject.module.css +7 -0
  5. package/dist/color.module.css +3 -0
  6. package/dist/color.scss +84 -0
  7. package/dist/components/index.d.ts +4 -0
  8. package/dist/components/index.d.ts.map +1 -0
  9. package/dist/components/index.js +53 -0
  10. package/dist/components/style.css +1 -0
  11. package/dist/components/theme-provider.keys.d.ts +4 -0
  12. package/dist/components/theme-provider.keys.d.ts.map +1 -0
  13. package/dist/components/theme-provider.module.css +1 -0
  14. package/dist/components/theme-provider.types.d.ts +18 -0
  15. package/dist/components/theme-provider.types.d.ts.map +1 -0
  16. package/dist/components/theme-provider.vue.d.ts +19 -0
  17. package/dist/config.default.d.mts +4 -0
  18. package/dist/config.default.d.mts.map +1 -0
  19. package/dist/config.default.mjs +73 -0
  20. package/dist/config.default.mjs.map +1 -0
  21. package/dist/disabled.inject.module.css +5 -0
  22. package/dist/disabled.module.css +1 -0
  23. package/dist/disabled.scss +3 -0
  24. package/dist/display.module.css +2 -0
  25. package/dist/display.scss +63 -0
  26. package/dist/duration.scss +17 -0
  27. package/dist/elevation.module.css +33 -0
  28. package/dist/elevation.scss +46 -0
  29. package/dist/generate-BPYE5ALG.mjs +1037 -0
  30. package/dist/generate-BPYE5ALG.mjs.map +1 -0
  31. package/dist/generator/cli.d.mts +1 -0
  32. package/dist/generator/cli.mjs +103 -0
  33. package/dist/generator/cli.mjs.map +1 -0
  34. package/dist/generator/vite.d.mts +18 -0
  35. package/dist/generator/vite.d.mts.map +1 -0
  36. package/dist/generator/vite.mjs +117 -0
  37. package/dist/generator/vite.mjs.map +1 -0
  38. package/dist/index.d.mts +339 -0
  39. package/dist/index.d.mts.map +1 -0
  40. package/dist/index.mjs +909 -0
  41. package/dist/index.mjs.map +1 -0
  42. package/dist/is.scss +185 -0
  43. package/dist/load-config-64q6nzFy.mjs +48 -0
  44. package/dist/load-config-64q6nzFy.mjs.map +1 -0
  45. package/dist/ripple.scss +57 -0
  46. package/dist/round.inject.module.css +92 -0
  47. package/dist/round.module.css +14 -0
  48. package/dist/round.scss +90 -0
  49. package/dist/size.inject.module.css +50 -0
  50. package/dist/size.module.css +13 -0
  51. package/dist/size.scss +28 -0
  52. package/dist/theme.scss +16 -0
  53. package/dist/typography.inject.module.css +81 -0
  54. package/dist/typography.module.css +32 -0
  55. package/dist/typography.scss +21 -0
  56. package/dist/util.scss +78 -0
  57. package/dist/vars.scss +0 -0
  58. package/package.json +96 -4
  59. package/src/contracts/backdrop/backdrop.contract.ts +44 -0
  60. package/src/contracts/backdrop/backdrop.generator.ts +82 -0
  61. package/src/contracts/backdrop/backdrop.keys.ts +7 -0
  62. package/src/contracts/backdrop/backdrop.module.css +3 -0
  63. package/src/contracts/backdrop/backdrop.scss +7 -0
  64. package/src/contracts/backdrop/backdrop.types.ts +45 -0
  65. package/src/contracts/backdrop/index.ts +21 -0
  66. package/src/contracts/color/color.contract.spec.ts +75 -0
  67. package/src/contracts/color/color.contract.ts +97 -0
  68. package/src/contracts/color/color.generator.spec.ts +73 -0
  69. package/src/contracts/color/color.generator.ts +122 -0
  70. package/src/contracts/color/color.gradient.spec.ts +32 -0
  71. package/src/contracts/color/color.gradient.ts +52 -0
  72. package/src/contracts/color/color.inject.module.css +5 -0
  73. package/src/contracts/color/color.keys.ts +7 -0
  74. package/src/contracts/color/color.module.css +5 -0
  75. package/src/contracts/color/color.scss +84 -0
  76. package/src/contracts/color/color.serialize.spec.ts +57 -0
  77. package/src/contracts/color/color.serialize.ts +35 -0
  78. package/src/contracts/color/color.token.spec.ts +57 -0
  79. package/src/contracts/color/color.token.ts +89 -0
  80. package/src/contracts/color/color.types.ts +82 -0
  81. package/src/contracts/color/index.md +87 -0
  82. package/src/contracts/color/index.ts +25 -0
  83. package/src/contracts/contract.ts +115 -0
  84. package/src/contracts/disabled/disabled.contract.ts +32 -0
  85. package/src/contracts/disabled/disabled.generator.ts +32 -0
  86. package/src/contracts/disabled/disabled.inject.module.css +5 -0
  87. package/src/contracts/disabled/disabled.keys.ts +6 -0
  88. package/src/contracts/disabled/disabled.module.css +3 -0
  89. package/src/contracts/disabled/disabled.scss +3 -0
  90. package/src/contracts/disabled/disabled.types.ts +19 -0
  91. package/src/contracts/disabled/index.ts +21 -0
  92. package/src/contracts/display/display.contract.ts +41 -0
  93. package/src/contracts/display/display.generator.ts +57 -0
  94. package/src/contracts/display/display.instance.ts +173 -0
  95. package/src/contracts/display/display.keys.ts +9 -0
  96. package/src/contracts/display/display.module.css +4 -0
  97. package/src/contracts/display/display.scss +63 -0
  98. package/src/contracts/display/display.types.ts +75 -0
  99. package/src/contracts/display/index.ts +27 -0
  100. package/src/contracts/elevation/elevation.contract.ts +37 -0
  101. package/src/contracts/elevation/elevation.generator.ts +71 -0
  102. package/src/contracts/elevation/elevation.keys.ts +6 -0
  103. package/src/contracts/elevation/elevation.module.css +35 -0
  104. package/src/contracts/elevation/elevation.scss +46 -0
  105. package/src/contracts/elevation/elevation.types.ts +21 -0
  106. package/src/contracts/elevation/index.ts +20 -0
  107. package/src/contracts/generator.ts +38 -0
  108. package/src/contracts/index.md +48 -0
  109. package/src/contracts/index.ts +37 -0
  110. package/src/contracts/round/index.ts +21 -0
  111. package/src/contracts/round/round.contract.ts +75 -0
  112. package/src/contracts/round/round.generator.ts +33 -0
  113. package/src/contracts/round/round.inject.module.scss +36 -0
  114. package/src/contracts/round/round.keys.ts +7 -0
  115. package/src/contracts/round/round.module.css +16 -0
  116. package/src/contracts/round/round.scss +90 -0
  117. package/src/contracts/round/round.types.ts +44 -0
  118. package/src/contracts/size/index.ts +22 -0
  119. package/src/contracts/size/size.contract.ts +98 -0
  120. package/src/contracts/size/size.generator.spec.ts +101 -0
  121. package/src/contracts/size/size.generator.ts +51 -0
  122. package/src/contracts/size/size.inject.module.scss +12 -0
  123. package/src/contracts/size/size.keys.ts +8 -0
  124. package/src/contracts/size/size.module.css +15 -0
  125. package/src/contracts/size/size.scss +28 -0
  126. package/src/contracts/size/size.types.ts +63 -0
  127. package/src/contracts/size/units.scss +17 -0
  128. package/src/contracts/style/index.ts +11 -0
  129. package/src/contracts/style/style.generator.ts +36 -0
  130. package/src/contracts/style/style.key.ts +4 -0
  131. package/src/contracts/style/style.types.ts +16 -0
  132. package/src/contracts/typography/index.ts +26 -0
  133. package/src/contracts/typography/typography.contract.ts +52 -0
  134. package/src/contracts/typography/typography.generator.spec.ts +48 -0
  135. package/src/contracts/typography/typography.generator.ts +44 -0
  136. package/src/contracts/typography/typography.inject.module.css +54 -0
  137. package/src/contracts/typography/typography.keys.ts +12 -0
  138. package/src/contracts/typography/typography.module.css +36 -0
  139. package/src/contracts/typography/typography.scss +21 -0
  140. package/src/contracts/typography/typography.types.ts +90 -0
  141. package/src/generator/theme.default.css +657 -0
  142. package/src/styles/duration.scss +17 -0
  143. package/src/styles/index.md +18 -0
  144. package/src/styles/is.scss +185 -0
  145. package/src/styles/ripple.scss +57 -0
  146. package/src/styles/theme.scss +16 -0
  147. package/src/styles/util.scss +78 -0
  148. package/src/styles/vars.scss +0 -0
@@ -0,0 +1,1037 @@
1
+ import config from "./config.default.mjs";
2
+ import { SPACES, blend, darken, isArray, isLiteralColor, isNumberish, isString, lighten, sha256hex, toRgb, toUnits, tryToUnits } from "@ui0/util";
3
+ // src/types.ts
4
+ function schemesOf(preset) {
5
+ return preset;
6
+ }
7
+ // src/generator/base.ts
8
+ /**
9
+ * The base `body` reset every theme ships: margin 0 and the base font size.
10
+ * Themed colors stay on the themed subtrees - the body itself stays neutral.
11
+ *
12
+ * @returns the `body {...}` rule
13
+ */
14
+ function generateBaseCss() {
15
+ return "body {\n margin: 0;\n font-size: 1rem;\n}";
16
+ }
17
+ /** marker attribute of the injected base-reset <style> element */
18
+ const BASE_STYLE_ATTR = "data-ui0-theme-base";
19
+ /**
20
+ * Inject the base body reset into a document, idempotently - a second call
21
+ * finds the previously created `<style>` and returns it untouched.
22
+ *
23
+ * @param doc - the document to inject into (defaults to the global one)
24
+ * @returns the style element carrying the reset
25
+ */
26
+ function ensureThemeBaseStyle(doc = document) {
27
+ const selector = `style[${BASE_STYLE_ATTR}]`;
28
+ const existing = doc.head.querySelector(selector);
29
+ if (existing) return existing;
30
+ const el = doc.createElement("style");
31
+ el.setAttribute(BASE_STYLE_ATTR, "");
32
+ el.textContent = generateBaseCss();
33
+ doc.head.appendChild(el);
34
+ return el;
35
+ }
36
+ // src/contracts/backdrop/backdrop.module.css.ui0-map
37
+ var backdrop_module_css_default = { "backdrop": "ba_d486" };
38
+ // src/contracts/backdrop/backdrop.generator.ts
39
+ /** fallback value per function when the config omits the value */
40
+ const DEFAULTS = {
41
+ blur: "4px",
42
+ brightness: "0.5",
43
+ contrast: "0.5",
44
+ "drop-shadow": "0 4px 8px rgba(0, 0, 0, 0.5)",
45
+ grayscale: "1",
46
+ "hue-rotate": "90deg",
47
+ invert: "1",
48
+ opacity: "0.5",
49
+ saturate: "0.5",
50
+ sepia: "1"
51
+ };
52
+ const backdropGenerator = (ctx) => {
53
+ const { hash } = ctx;
54
+ const config = ctx.config.backdrop;
55
+ const backdropSettings = ctx.settings.backdrop;
56
+ const fnSettings = backdropSettings === false ? {} : backdropSettings ?? {};
57
+ const fromConfig = config ? Object.keys(config) : ["blur"];
58
+ const enabled = [.../* @__PURE__ */ new Set([...fromConfig, ...Object.keys(fnSettings).filter((fn) => fnSettings[fn])])].filter((fn) => fnSettings[fn] !== false);
59
+ function vars() {
60
+ const backdrop = {};
61
+ for (const fn of enabled) backdrop[fn] = `${config?.[fn] ?? DEFAULTS[fn]}`;
62
+ return { backdrop };
63
+ }
64
+ console.log("hash", backdrop_module_css_default.backdrop);
65
+ return {
66
+ namespace: "bd",
67
+ vars: (scheme) => scheme ? {} : vars(),
68
+ css: () => {
69
+ return `.${backdrop_module_css_default.backdrop} {\n backdrop-filter: var(--0-backdrop);\n -webkit-backdrop-filter: var(--0-backdrop);\n will-change: backdrop-filter;\n}`;
70
+ },
71
+ class: () => ({ ...backdrop_module_css_default }),
72
+ styles: () => ({})
73
+ };
74
+ };
75
+ // src/generator/pool.ts
76
+ const DEFAULT_RAMP_TYPES = ["l", "d"];
77
+ /** Read the per-color options out of a pool entry's 3rd tuple element. */
78
+ function colorOptions(raw) {
79
+ const opt = Array.isArray(raw) ? raw[2] : void 0;
80
+ if (Array.isArray(opt)) return {
81
+ ramps: opt,
82
+ space: "hsl"
83
+ };
84
+ if (opt && typeof opt === "object") return {
85
+ ramps: opt.ramps || [],
86
+ space: opt.space || "hsl"
87
+ };
88
+ return {
89
+ ramps: [],
90
+ space: "hsl"
91
+ };
92
+ }
93
+ /**
94
+ * The ramp types a pool entry wants generated: the defaults (l/d) plus any
95
+ * extras (c/s) from its options, deduped, order-stable.
96
+ *
97
+ * @param raw - the pool entry to read options from
98
+ * @returns the ramp types to emit for this entry
99
+ */
100
+ function requestedRampTypes(raw) {
101
+ return [.../* @__PURE__ */ new Set([...DEFAULT_RAMP_TYPES, ...colorOptions(raw).ramps])];
102
+ }
103
+ /** merge a scheme's pool over the base pool (scheme wins per entry) */
104
+ function buildPool(base, scheme) {
105
+ return {
106
+ ...base,
107
+ ...scheme
108
+ };
109
+ }
110
+ /**
111
+ * Resolve a whole color pool into base RGB triples plus per-color ramps.
112
+ *
113
+ * Entries may be literals (`'#fff'`, `'rgb(...)'`, named), aliases (`'brand'`),
114
+ * ramp-step references (`'brand-l2'`) or blend expressions
115
+ * (`[['#0d654e', '#000', 50], 3]`); cycles (background referencing a ramp
116
+ * that needs background's lightness) are broken by resolving only what each
117
+ * step needs - ramp arrays are built lazily and cached per (color, type).
118
+ *
119
+ * @param pool - the pool slice of an appearance config
120
+ * @returns resolved base colors and the generated ramps
121
+ * @throws on circular references and unknown color names
122
+ */
123
+ function resolvePool(pool) {
124
+ const resolvedBase = {};
125
+ const resolvedRampArrays = {};
126
+ const resolvingBase = /* @__PURE__ */ new Set();
127
+ /** Resolve any reference form to an RGB triple (literal / ramp step / alias). */
128
+ function resolveRef(ref) {
129
+ if (isLiteralColor(ref)) return toRgb(ref);
130
+ const m = ref.match(/^(.+)-([ldcs])(\d+)$/);
131
+ if (m) {
132
+ const [, refName, type, stepStr] = m;
133
+ return getRampArray(refName, type)[Number(stepStr) - 1];
134
+ }
135
+ resolveBase(ref);
136
+ return resolvedBase[ref];
137
+ }
138
+ /** Resolve a non-string entry: a [color, steps] tuple or a blend expression. */
139
+ function resolveExpr(expr) {
140
+ if (Array.isArray(expr[0])) {
141
+ const [c1, c2, depth] = expr[0];
142
+ return {
143
+ base: blend(typeof c1 === "string" ? resolveRef(c1) : c1, typeof c2 === "string" ? resolveRef(c2) : c2, depth),
144
+ steps: expr[1]
145
+ };
146
+ }
147
+ return {
148
+ base: resolveRef(expr[0]),
149
+ steps: expr[1]
150
+ };
151
+ }
152
+ /**
153
+ * Resolve ONLY the base value - never needs the scheme's background lightness,
154
+ * so it can be called while resolving background itself without a cycle.
155
+ */
156
+ function resolveBase(name) {
157
+ if (name in resolvedBase) return;
158
+ if (resolvingBase.has(name)) throw new Error(`circular color reference: ${name}`);
159
+ resolvingBase.add(name);
160
+ const raw = pool[name];
161
+ if (raw === void 0) throw new Error(`unknown color reference: ${name}`);
162
+ resolvedBase[name] = typeof raw === "string" ? resolveRef(raw) : resolveExpr(raw).base;
163
+ resolvingBase.delete(name);
164
+ }
165
+ /**
166
+ * The background's lightness, read in the SAME space as the color being
167
+ * ramped, so the "which side of 50" comparison stays apples-to-apples.
168
+ */
169
+ function baseLightness(space) {
170
+ resolveBase("background");
171
+ return SPACES[space].lightnessOf(resolvedBase.background);
172
+ }
173
+ /** Build (and cache) one color's ramp of one type, lazily. */
174
+ function getRampArray(name, type) {
175
+ resolvedRampArrays[name] = resolvedRampArrays[name] || {};
176
+ const cached = resolvedRampArrays[name][type];
177
+ if (cached) return cached;
178
+ resolveBase(name);
179
+ const raw = pool[name];
180
+ const steps = raw[1];
181
+ const base = resolvedBase[name];
182
+ const { space } = colorOptions(raw);
183
+ let arr;
184
+ if (type === "l") arr = Array.from({ length: steps }, (_, i) => lighten(base, i + 1, steps, space));
185
+ else if (type === "d") arr = Array.from({ length: steps }, (_, i) => darken(base, i + 1, steps, space));
186
+ else {
187
+ const bg = name === "background" ? SPACES[space].lightnessOf(base) : baseLightness(space);
188
+ arr = type === "c" ? Array.from({ length: steps }, (_, i) => bg < 50 ? lighten(base, i + 1, steps, space) : darken(base, i + 1, steps, space)) : Array.from({ length: steps }, (_, i) => bg < 50 ? darken(base, i + 1, steps, space) : lighten(base, i + 1, steps, space));
189
+ }
190
+ resolvedRampArrays[name][type] = arr;
191
+ return arr;
192
+ }
193
+ for (const name of Object.keys(pool)) {
194
+ resolveBase(name);
195
+ if (typeof pool[name] !== "string") for (const type of requestedRampTypes(pool[name])) getRampArray(name, type);
196
+ }
197
+ return {
198
+ base: resolvedBase,
199
+ ramps: resolvedRampArrays
200
+ };
201
+ }
202
+ // src/contracts/color/color.token.ts
203
+ const ColorSchemeValues = ["light", "dark"];
204
+ const ColorPseudoValues = [
205
+ "hover",
206
+ "active",
207
+ "focus"
208
+ ];
209
+ const SPACE = /\s+/;
210
+ /** parse a `<ref>[@pct]` tail into ref + opacity (0..1) */
211
+ function parseRef(raw) {
212
+ const at = raw.lastIndexOf("@");
213
+ if (at === -1) return { ref: raw };
214
+ const ref = raw.slice(0, at);
215
+ const pct = raw.slice(at + 1);
216
+ if (!ref || !isNumberish(pct)) throw new Error(`ui0 color: invalid ref "${raw}" (expected name[@pct])`);
217
+ const n = Number(pct);
218
+ if (n < 0 || n > 100) throw new Error(`ui0 color: opacity ${pct} out of 0..100 in "${raw}"`);
219
+ return {
220
+ ref,
221
+ opacity: n / 100
222
+ };
223
+ }
224
+ function parseToken(raw) {
225
+ const segments = raw.split(":");
226
+ const out = { ref: "" };
227
+ while (segments.length > 1) {
228
+ const head = segments[0];
229
+ if (ColorSchemeValues.includes(head)) out.scheme = head;
230
+ else if (ColorPseudoValues.includes(head)) out.pseudo = head;
231
+ else throw new Error(`ui0 color: unknown prefix "${head}" in "${raw}" (expected light|dark|hover|active|focus)`);
232
+ segments.shift();
233
+ }
234
+ Object.assign(out, parseRef(segments[0]));
235
+ if (!out.ref) throw new Error(`ui0 color: missing color ref in "${raw}"`);
236
+ return out;
237
+ }
238
+ /** parse a color/fill prop value into tokens (one per layer) */
239
+ function parseColorProp(value) {
240
+ const raws = (isString(value) ? value.split(SPACE) : isArray(value) ? value : []).map((x) => String(x).trim()).filter(Boolean);
241
+ const tokens = [];
242
+ let sawPair = false;
243
+ let sawNamedScheme = false;
244
+ for (const raw of raws) if (raw.includes("/")) {
245
+ const pair = raw.split("/");
246
+ if (pair.length !== 2 || !pair[0] || !pair[1]) throw new Error(`ui0 color: "${raw}" is not a light/dark pair (spell single-scheme as dark:ref)`);
247
+ if (pair[0].includes(":") || pair[1].includes(":")) throw new Error(`ui0 color: "${raw}" - pair segments must be plain refs (name[-ramp][@pct]); prefixed parts need the named form: light:<ref> [pseudo:]<ref>`);
248
+ tokens.push({
249
+ scheme: "light",
250
+ ...parseRef(pair[0])
251
+ });
252
+ tokens.push({
253
+ scheme: "dark",
254
+ ...parseRef(pair[1])
255
+ });
256
+ sawPair = true;
257
+ } else {
258
+ const token = parseToken(raw);
259
+ if (token.scheme) sawNamedScheme = true;
260
+ tokens.push(token);
261
+ }
262
+ if (sawPair && sawNamedScheme) throw new Error("ui0 color: a positional `a/b` pair cannot mix with light:/dark: prefixes in one prop");
263
+ return tokens;
264
+ }
265
+ // src/contracts/color/color.inject.module.css.ui0-inject
266
+ var color_inject_module_css_default = ".co_ca8c { /* slot marker */ }\n.fi_8a2f { /* slot marker */ }\n.gr_9658 { /* slot marker */ }";
267
+ // src/contracts/color/color.module.css.ui0-map
268
+ var color_module_css_default = {
269
+ "colored": "co_ca8c",
270
+ "filled": "fi_8a2f",
271
+ "gradiented": "gr_9658"
272
+ };
273
+ // src/contracts/color/color.generator.ts
274
+ function channels(rgb) {
275
+ return rgb.map((v) => Math.round(v)).join(" ");
276
+ }
277
+ const PSEUDOS = [void 0, ...ColorPseudoValues];
278
+ const GATINGS = [{
279
+ prefix: "",
280
+ selector: ""
281
+ }, ...ColorSchemeValues.map((s) => ({
282
+ prefix: `${s}-`,
283
+ selector: `.theme_${s} `
284
+ }))];
285
+ const SLOTS = ["c", "f"];
286
+ const colorGenerator = (ctx) => {
287
+ const { config, hash } = ctx;
288
+ function vars() {
289
+ const pool = config.color;
290
+ const merged = buildPool(pool, void 0);
291
+ if (!Object.keys(merged).length) return {};
292
+ const { base, ramps } = resolvePool(merged);
293
+ const c = {};
294
+ for (const [name, rgb] of Object.entries(base)) {
295
+ c[`${name}-v`] = channels(rgb);
296
+ const ramp = ramps[name];
297
+ if (!ramp) continue;
298
+ for (const [type, steps] of Object.entries(ramp)) steps?.forEach((rgbStep, i) => {
299
+ c[`${name}-${type}${i + 1}-v`] = channels(rgbStep);
300
+ });
301
+ }
302
+ if ("foreground" in base) c["cur-v"] = "var(--0-c-foreground-v)";
303
+ c.cur = "rgb(var(--0-c-cur-v, var(--0-c-foreground-v)) / var(--0-c-o, 1))";
304
+ const f = {};
305
+ if ("background" in base) f["cur-v"] = "var(--0-c-background-v)";
306
+ f.cur = "rgb(var(--0-f-cur-v, var(--0-c-background-v)) / var(--0-f-o, 1))";
307
+ return {
308
+ c,
309
+ f
310
+ };
311
+ }
312
+ function css() {
313
+ const pool = config.color;
314
+ const names = Object.keys(buildPool(pool, void 0));
315
+ if (!names.length) return color_inject_module_css_default;
316
+ const lines = [];
317
+ for (const { prefix, selector } of GATINGS) for (const pseudo of PSEUDOS) {
318
+ const pseudoPrefix = pseudo ? `${pseudo}-` : "";
319
+ const pseudoSuffix = pseudo ? `:${pseudo}` : "";
320
+ for (const name of names) for (const slot of SLOTS) {
321
+ const cls = `${prefix}${pseudoPrefix}${slot}-${name}`;
322
+ const ns = slot === "c" ? "--0-c" : "--0-f";
323
+ lines.push(`${selector}.${hash(cls)}${pseudoSuffix} { ${ns}-cur-v: var(--0-c-${name}-v); }`);
324
+ }
325
+ }
326
+ return `${color_inject_module_css_default}\n${lines.join("\n")}`;
327
+ }
328
+ function classes() {
329
+ const out = { ...color_module_css_default };
330
+ const pool = config.color;
331
+ const names = Object.keys(buildPool(pool, void 0));
332
+ for (const { prefix } of GATINGS) for (const pseudo of PSEUDOS) {
333
+ const pseudoPrefix = pseudo ? `${pseudo}-` : "";
334
+ for (const name of names) for (const slot of SLOTS) out[`${prefix}${pseudoPrefix}${slot}-${name}`] = hash(`${prefix}${pseudoPrefix}${slot}-${name}`);
335
+ }
336
+ return out;
337
+ }
338
+ return {
339
+ namespace: "c",
340
+ vars: (scheme) => scheme ? {} : vars(),
341
+ css,
342
+ class: classes,
343
+ styles: () => ({})
344
+ };
345
+ };
346
+ // src/contracts/disabled/disabled.inject.module.css.ui0-inject
347
+ var disabled_inject_module_css_default = ".di_17eb {\n opacity: var(--0-dis-o, 0.5);\n}";
348
+ // src/contracts/disabled/disabled.module.css.ui0-map
349
+ var disabled_module_css_default = { "disabled": "di_17eb" };
350
+ // src/contracts/disabled/disabled.generator.ts
351
+ const disabledGenerator = (ctx) => {
352
+ const { config } = ctx;
353
+ function vars() {
354
+ const disabled = config.disabled;
355
+ if (disabled?.opacity === void 0) return {};
356
+ return { dis: { o: disabled.opacity } };
357
+ }
358
+ return {
359
+ namespace: "dis",
360
+ vars: (scheme) => scheme ? {} : vars(),
361
+ css: () => disabled_inject_module_css_default,
362
+ class: () => ({ ...disabled_module_css_default }),
363
+ styles: () => ({})
364
+ };
365
+ };
366
+ // src/contracts/display/display.module.css.ui0-map
367
+ var display_module_css_default = {
368
+ "displayed": "di_e228",
369
+ "displayNormal": "di_bf77"
370
+ };
371
+ // src/contracts/display/display.generator.ts
372
+ const displayGenerator = (ctx) => {
373
+ const { config } = ctx;
374
+ function vars() {
375
+ const display = config.display;
376
+ if (display?.base === void 0) return {};
377
+ return { display: { base: display.base } };
378
+ }
379
+ return {
380
+ namespace: "d",
381
+ vars: (scheme) => scheme ? {} : vars(),
382
+ css: () => `.${display_module_css_default.displayed} { /* point the component slot at the theme var */ }`,
383
+ localScss: () => {
384
+ const brp = ctx.settings.display?.breakpoints;
385
+ const out = {};
386
+ if (brp) Object.keys(brp).forEach((k) => {
387
+ out[`$${k}`] = toUnits(brp[k]);
388
+ });
389
+ return out;
390
+ },
391
+ class: () => ({ ...display_module_css_default }),
392
+ styles: () => {
393
+ const brp = ctx.settings.display?.breakpoints;
394
+ const out = {};
395
+ if (brp) Object.keys(brp).forEach((k) => {
396
+ out[`--0-display-${k}`] = toUnits(brp[k]);
397
+ });
398
+ return out;
399
+ }
400
+ };
401
+ };
402
+ // src/contracts/elevation/elevation.module.css.ui0-map
403
+ var elevation_module_css_default = {
404
+ "elv": "el_b4e0",
405
+ "elv1": "el_5e0f",
406
+ "elv1n": "el_5995",
407
+ "elv2": "el_fb8f",
408
+ "elv2n": "el_af23",
409
+ "elv3": "el_8867",
410
+ "elv3n": "el_6c3d",
411
+ "elv4": "el_4d5e",
412
+ "elv4n": "el_a211",
413
+ "elv5": "el_1ab1",
414
+ "elv5n": "el_2df9",
415
+ "elv6": "el_56bd",
416
+ "elv6n": "el_b036",
417
+ "elv7": "el_61ea",
418
+ "elv7n": "el_8003",
419
+ "elv8": "el_8924",
420
+ "elv8n": "el_7bc0",
421
+ "elv9": "el_1bb1",
422
+ "elv9n": "el_734f",
423
+ "elv10": "el_40d4",
424
+ "elv10n": "el_ef94",
425
+ "elv11": "el_a016",
426
+ "elv11n": "el_fcd8",
427
+ "elv12": "el_1c39",
428
+ "elv12n": "el_ba0c",
429
+ "elv13": "el_5602",
430
+ "elv13n": "el_d306",
431
+ "elv14": "el_3f15",
432
+ "elv14n": "el_ece8",
433
+ "elv15": "el_3130",
434
+ "elv15n": "el_5599",
435
+ "elv16": "el_c651",
436
+ "elv16n": "el_f2d2"
437
+ };
438
+ // src/contracts/elevation/elevation.generator.ts
439
+ const BASE_CLASS_BODY = ` box-shadow:
440
+ 0 0 0 1px rgba(255 255 255 / .1),
441
+ var(--0-elv-i, ) 0px 1px 1px rgba(var(--0-elv-c, 0 0 0) / 0.1),
442
+ var(--0-elv-i, ) var(--0-elv-x1, 0px) var(--0-elv-y1, 0px) rgba(var(--0-elv-c, 0 0 0) / 0.095),
443
+ var(--0-elv-i, ) var(--0-elv-x2, 0px) var(--0-elv-y2, 0px) rgba(var(--0-elv-c, 0 0 0) / 0.13);`;
444
+ const elevationGenerator = (ctx) => {
445
+ const { config, hash } = ctx;
446
+ const steps = config.elevation?.steps ?? 16;
447
+ function vars() {
448
+ return { elv: {
449
+ x1: "1px",
450
+ y1: "calc(var(--0-elv-x1) * 3)",
451
+ x2: "calc(var(--0-elv-x1) * 1.5)",
452
+ y2: "calc(var(--0-elv-x1) * 1.5)"
453
+ } };
454
+ }
455
+ function stepVars(i, inset) {
456
+ const lines = [` --0-elv-x1: ${i}px;`];
457
+ if (inset) lines.push(" --0-elv-i: inset;");
458
+ return lines.join("\n");
459
+ }
460
+ function css() {
461
+ const lines = [`.${elevation_module_css_default.elv} {\n${BASE_CLASS_BODY}\n}`];
462
+ for (let i = 1; i <= steps; i++) {
463
+ lines.push(`.${hash(`elv${i}`)} {\n${stepVars(i, false)}\n}`);
464
+ lines.push(`.${hash(`elv${i}n`)} {\n${stepVars(i, true)}\n}`);
465
+ }
466
+ return lines.join("\n");
467
+ }
468
+ function classes() {
469
+ const out = { ...elevation_module_css_default };
470
+ for (let i = 1; i <= steps; i++) {
471
+ out[`elv${i}`] = hash(`elv${i}`);
472
+ out[`elv${i}n`] = hash(`elv${i}n`);
473
+ }
474
+ return out;
475
+ }
476
+ return {
477
+ namespace: "e",
478
+ vars,
479
+ css,
480
+ class: classes,
481
+ styles: () => ({})
482
+ };
483
+ };
484
+ // src/contracts/round/round.inject.module.scss.ui0-inject
485
+ var round_inject_module_scss_default = ".rF_7ee9 {\n --0-r-tl: var(--0c-r-full, var(--0-r-full));\n --0-r-tr: var(--0c-r-full, var(--0-r-full));\n --0-r-bl: var(--0c-r-full, var(--0-r-full));\n --0-r-br: var(--0c-r-full, var(--0-r-full));\n}\n\n.rS_e0da {\n --0-r-tl: var(--0c-r-smooth, var(--0-r-smooth));\n --0-r-tr: var(--0c-r-smooth, var(--0-r-smooth));\n --0-r-bl: var(--0c-r-smooth, var(--0-r-smooth));\n --0-r-br: var(--0c-r-smooth, var(--0-r-smooth));\n}\n\n.rB_2f08 {\n --0-r-tl: var(--0c-r-basic, var(--0-r-basic));\n --0-r-tr: var(--0c-r-basic, var(--0-r-basic));\n --0-r-bl: var(--0c-r-basic, var(--0-r-basic));\n --0-r-br: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.rH_7415 {\n --0-r-tl: var(--0c-r-hard, var(--0-r-hard));\n --0-r-tr: var(--0c-r-hard, var(--0-r-hard));\n --0-r-bl: var(--0c-r-hard, var(--0-r-hard));\n --0-r-br: var(--0c-r-hard, var(--0-r-hard));\n}\n\n.rN_2296 {\n --0-r-tl: var(--0c-r-none, var(--0-r-none));\n --0-r-tr: var(--0c-r-none, var(--0-r-none));\n --0-r-bl: var(--0c-r-none, var(--0-r-none));\n --0-r-br: var(--0c-r-none, var(--0-r-none));\n}\n\n.ro_0102 {\n --0-r-tl: var(--0c-r-basic, var(--0-r-basic));\n --0-r-tr: var(--0c-r-basic, var(--0-r-basic));\n --0-r-bl: var(--0c-r-basic, var(--0-r-basic));\n --0-r-br: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.rl_52df {\n --0-r-tl: var(--0c-r-basic, var(--0-r-basic));\n --0-r-bl: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.rr_597c {\n --0-r-tr: var(--0c-r-basic, var(--0-r-basic));\n --0-r-br: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.rt_cdff {\n --0-r-tl: var(--0c-r-basic, var(--0-r-basic));\n --0-r-tr: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.rb_64f2 {\n --0-r-bl: var(--0c-r-basic, var(--0-r-basic));\n --0-r-br: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.tl_e660 {\n --0-r-tl: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.tr_7817 {\n --0-r-tr: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.bl_29d9 {\n --0-r-bl: var(--0c-r-basic, var(--0-r-basic));\n}\n\n.br_8850 {\n --0-r-br: var(--0c-r-basic, var(--0-r-basic));\n}";
486
+ // src/contracts/round/round.module.css.ui0-map
487
+ var round_module_css_default = {
488
+ "rounded": "ro_0102",
489
+ "rBasic": "rB_2f08",
490
+ "rSmooth": "rS_e0da",
491
+ "rHard": "rH_7415",
492
+ "rNone": "rN_2296",
493
+ "rFull": "rF_7ee9",
494
+ "rl": "rl_52df",
495
+ "rr": "rr_597c",
496
+ "rt": "rt_cdff",
497
+ "rb": "rb_64f2",
498
+ "br": "br_8850",
499
+ "bl": "bl_29d9",
500
+ "tl": "tl_e660",
501
+ "tr": "tr_7817"
502
+ };
503
+ // src/contracts/round/round.generator.ts
504
+ const roundGenerator = () => {
505
+ return {
506
+ namespace: "r",
507
+ vars: () => ({}),
508
+ css: () => round_inject_module_scss_default,
509
+ class: () => ({ ...round_module_css_default }),
510
+ styles: () => ({
511
+ "--0-r-base": "4px",
512
+ "--0-r-tl": "0px",
513
+ "--0-r-tr": "0px",
514
+ "--0-r-bl": "0px",
515
+ "--0-r-basic": "calc(var(--0-s-m, 42px) * var(--0-s-density, 1))",
516
+ "--0-r-br": "0px"
517
+ })
518
+ };
519
+ };
520
+ // src/generator/scales.ts
521
+ const SCALE_RATIO = 1.2;
522
+ const SCALE_STEPS = [
523
+ "xxxs",
524
+ "xxs",
525
+ "xs",
526
+ "s",
527
+ "m",
528
+ "l",
529
+ "xl",
530
+ "xxl",
531
+ "xxxl"
532
+ ];
533
+ /** The step -> value map of one geometric scale. */
534
+ function scaleValues(base, ratio) {
535
+ const out = {};
536
+ for (const step of SCALE_STEPS) out[step] = base * ratio ** (SCALE_STEPS.indexOf(step) - SCALE_STEPS.indexOf("m"));
537
+ return out;
538
+ }
539
+ /**
540
+ * Expand a single base value into the xxxs..xxxl scale with PURE step names
541
+ * (no `--0-` prefix - the caller assigns the namespace).
542
+ *
543
+ * Three scales use this: `fs` (text font-size), `s` (control heights - a
544
+ * component's `size` prop picks a step) and `sc` (a control's child heights).
545
+ * An unparseable value (e.g. 'inherit') emits only the `m` step verbatim.
546
+ *
547
+ * @param value - the base value (the "m" step)
548
+ * @param ratio - the geometric ratio between steps
549
+ * @returns the pure step -> value map
550
+ */
551
+ function renderScale(value, ratio = SCALE_RATIO) {
552
+ const m = String(value).match(/^([\d.]+)([a-z%]*)$/i);
553
+ if (!m) return { m: value };
554
+ const base = parseFloat(m[1]);
555
+ const unit = m[2] || "px";
556
+ const round = (n) => unit === "px" ? Math.round(n) : Math.round(n * 1e3) / 1e3;
557
+ const values = scaleValues(base, ratio);
558
+ return Object.fromEntries(SCALE_STEPS.map((step) => [step, `${round(values[step])}${unit}`]));
559
+ }
560
+ /**
561
+ * The global unit scales, emitted on the theme so they ALWAYS exist - a
562
+ * component that doesn't opt into the `sizeable()` mixin simply inherits
563
+ * them. Each is a calc() off the theme's own base vars (same formula the
564
+ * SCSS `sizeable()` mixin uses locally, so a component can re-derive the
565
+ * control units under its own `size`):
566
+ *
567
+ * `--0-u{1..8}` <- `--0-u-base` (spacing / typography)
568
+ * `--0-uc{1..8}` <- `--0-s-m` x density / 14 (control units)
569
+ * `--0-ucc{1..4}` <- `--0-sc-m` x density / 10 (control-child units)
570
+ *
571
+ * @param ns - the namespace step 1 lands in (only used for the calc refs to
572
+ * `--0-<ns>-1`)
573
+ * @param first - the value of the `1` step (usually a calc off the base)
574
+ * @param count - how many steps to emit
575
+ * @returns the pure step -> value map
576
+ */
577
+ function renderUnits(ns, first, count) {
578
+ const out = { 1: first };
579
+ for (let i = 2; i <= count; i++) out[i] = `calc(var(--0-${ns}1) * ${i})`;
580
+ return out;
581
+ }
582
+ // src/contracts/size/size.inject.module.scss.ui0-inject
583
+ var size_inject_module_scss_default = ".si_bce5 {\n --0-s: var(--0-s-xxxs);\n}\n\n.si_87d4 {\n --0-s: var(--0-s-xxs);\n}\n\n.si_0820 {\n --0-s: var(--0-s-xs);\n}\n\n.si_9329 {\n --0-s: var(--0-s-s);\n}\n\n.si_96e7 {\n --0-s: var(--0-s-m);\n}\n\n.si_05f9 {\n --0-s: var(--0-s-l);\n}\n\n.si_81de {\n --0-s: var(--0-s-xl);\n}\n\n.si_d16b {\n --0-s: var(--0-s-xxl);\n}\n\n.si_5136 {\n --0-s: var(--0-s-xxxl);\n}\n\n.si_e681 {\n --0-s: var(--0-s-custom);\n}";
584
+ // src/contracts/size/size.module.css.ui0-map
585
+ var size_module_css_default = {
586
+ "sizeXl": "si_81de",
587
+ "sizeM": "si_96e7",
588
+ "sizeXs": "si_0820",
589
+ "sizeS": "si_9329",
590
+ "sizeL": "si_05f9",
591
+ "sizeXxs": "si_87d4",
592
+ "sizeXxxs": "si_bce5",
593
+ "sizeXxxl": "si_5136",
594
+ "sizeXxl": "si_d16b",
595
+ "sizeCustom": "si_e681",
596
+ "sized": "si_3f5b",
597
+ "child": "ch_ddc9",
598
+ "fontSizing": "fo_5e6f"
599
+ };
600
+ // src/contracts/size/size.generator.ts
601
+ const CONTROL_UNIT_DIVIDER = 14;
602
+ const CONTROL_CHILD_UNIT_DIVIDER = 10;
603
+ const sizeGenerator = (ctx) => {
604
+ const { config } = ctx;
605
+ function vars() {
606
+ const out = {};
607
+ const size = config.size;
608
+ if (size?.control !== void 0) {
609
+ out.s = renderScale(size.control, SCALE_RATIO);
610
+ out.uc = renderUnits("uc", `calc(var(--0-s-m) * var(--0-s-density, 1) / ${CONTROL_UNIT_DIVIDER})`, 8);
611
+ }
612
+ if (size?.child !== void 0) {
613
+ out.sc = renderScale(size.child);
614
+ out.ucc = renderUnits("ucc", `calc(var(--0-sc-m) * var(--0-s-density, 1) / ${CONTROL_CHILD_UNIT_DIVIDER})`, 4);
615
+ }
616
+ if (size?.control !== void 0 || size?.child !== void 0) out.s = {
617
+ ...out.s,
618
+ density: 1
619
+ };
620
+ return out;
621
+ }
622
+ return {
623
+ namespace: "s",
624
+ vars: (scheme) => scheme ? {} : vars(),
625
+ css: () => size_inject_module_scss_default,
626
+ class: () => ({ ...size_module_css_default }),
627
+ styles: () => ({})
628
+ };
629
+ };
630
+ // src/contracts/style/style.generator.ts
631
+ const styleGenerator = (ctx) => {
632
+ const { config } = ctx;
633
+ function vars() {
634
+ const style = config.style;
635
+ if (!style?.vars) return {};
636
+ return { style: Object.fromEntries(Object.entries(style.vars)) };
637
+ }
638
+ function styles() {
639
+ const style = config.style;
640
+ if (!style?.raw) return {};
641
+ return { ...style.raw };
642
+ }
643
+ return {
644
+ namespace: "style",
645
+ vars: (scheme) => scheme ? {} : vars(),
646
+ css: () => "",
647
+ class: () => ({}),
648
+ styles: (scheme) => scheme ? {} : styles()
649
+ };
650
+ };
651
+ // src/contracts/typography/typography.inject.module.css.ui0-inject
652
+ var typography_inject_module_css_default = ".fw_f5d2 { font-weight: 100 }\n.fw_25c0 { font-weight: 200 }\n.fw_de2b { font-weight: 300 }\n.fw_a02f { font-weight: 400 }\n.fw_c057 { font-weight: 500 }\n.fw_aee5 { font-weight: 600 }\n.fw_3207 { font-weight: 700 }\n.fw_d808 { font-weight: 800 }\n.fw_bb66 { font-weight: 900 }\n\n.tt_c60d { text-transform: uppercase }\n.tt_56d5 { text-transform: lowercase }\n.tt_ce2a { text-transform: capitalize }\n.tt_1ff4 { text-transform: none }\n.tt_59a5 { text-transform: full-width }\n.tt_50f0 { text-transform: full-size-kana }\n\n.ta_c49e { text-align: start }\n.ta_e1d2 { text-align: end }\n.ta_d725 { text-align: center }\n.ta_3342 { text-align: left }\n.ta_e5b8 { text-align: right }\n.ta_010c { text-align: justify }\n.ta_0241 { text-align: match-parent }\n\n.to_a88e { text-orientation: mixed }\n.to_4919 { text-orientation: sideways }\n.to_2640 { text-orientation: sideways-right }\n.to_de51 { text-orientation: use-glyph-orientation }\n.to_35e5 { text-orientation: upright }\n\n.tw_83bf { text-wrap: nowrap }\n.tw_d03a { text-wrap: wrap }\n.tw_4fdb { text-wrap: balance }\n.tw_f5a3 { text-wrap: pretty }\n.tw_698e { text-wrap: stable }\nh1, h2, h3, h4, h5, h6 {\n --0-typo-step: 0.25rem; /* шаг (длина) */\n font-size: calc(var(--0-typo-h-fs, var(--0-typo-fs, 1rem)) + var(--0-typo-step) * var(--0-typo-x));\n line-height: calc(1 + 1 / var(--0-typo-x));\n\n}\nh1 { --0-typo-x: 6; }\nh2 { --0-typo-x: 5; }\nh3 { --0-typo-x: 4; }\nh4 { --0-typo-x: 3; }\nh5 { --0-typo-x: 2; }\nh6 { --0-typo-x: 1; }";
653
+ // src/contracts/typography/typography.module.css.ui0-map
654
+ var typography_module_css_default = {
655
+ "fw100": "fw_f5d2",
656
+ "fw200": "fw_25c0",
657
+ "fw300": "fw_de2b",
658
+ "fw400": "fw_a02f",
659
+ "fw500": "fw_c057",
660
+ "fw600": "fw_aee5",
661
+ "fw700": "fw_3207",
662
+ "fw800": "fw_d808",
663
+ "fw900": "fw_bb66",
664
+ "tt-uppercase": "tt_c60d",
665
+ "tt-lowercase": "tt_56d5",
666
+ "tt-capitalize": "tt_ce2a",
667
+ "tt-none": "tt_1ff4",
668
+ "tt-full": "tt_59a5",
669
+ "tt-full-size-kana": "tt_50f0",
670
+ "ta-center": "ta_d725",
671
+ "ta-end": "ta_e1d2",
672
+ "ta-justify": "ta_010c",
673
+ "ta-left": "ta_3342",
674
+ "ta-match-parent": "ta_0241",
675
+ "ta-right": "ta_e5b8",
676
+ "ta-start": "ta_c49e",
677
+ "to-mixed": "to_a88e",
678
+ "to-sideways": "to_4919",
679
+ "to-sideways-right": "to_2640",
680
+ "to-use-glyph-orientation": "to_de51",
681
+ "to-upright": "to_35e5",
682
+ "tw-nowrap": "tw_83bf",
683
+ "tw-wrap": "tw_d03a",
684
+ "tw-balance": "tw_4fdb",
685
+ "tw-pretty": "tw_f5a3",
686
+ "tw-stable": "tw_698e"
687
+ };
688
+ // src/contracts/typography/typography.generator.ts
689
+ const typographyGenerator = (ctx) => {
690
+ function vars() {
691
+ if (ctx.settings.typography) {
692
+ const { headingRatio, fontSizeHeading, fontSize } = ctx.settings.typography;
693
+ return { typo: {
694
+ fs: tryToUnits(fontSize),
695
+ "h-ratio": headingRatio,
696
+ "h-fs": toUnits(fontSizeHeading) || tryToUnits(fontSize)
697
+ } };
698
+ }
699
+ return {};
700
+ }
701
+ return {
702
+ namespace: "t",
703
+ vars: (scheme) => scheme ? {} : vars(),
704
+ css: () => typography_inject_module_css_default,
705
+ class: () => ({ ...typography_module_css_default }),
706
+ styles: () => ({})
707
+ };
708
+ };
709
+ // src/generator.ts
710
+ const contractGenerators = {
711
+ size: sizeGenerator,
712
+ color: colorGenerator,
713
+ round: roundGenerator,
714
+ backdrop: backdropGenerator,
715
+ elevation: elevationGenerator,
716
+ disabled: disabledGenerator,
717
+ display: displayGenerator,
718
+ typography: typographyGenerator,
719
+ style: styleGenerator
720
+ };
721
+ // src/generator/hash.ts
722
+ /** deterministic scoped name for a class-registry entry: xx_<sha256(name):4> */
723
+ function hashClassName(name) {
724
+ const hash = sha256hex(name).slice(0, 4);
725
+ return `${name.slice(0, 2)}_${hash}`;
726
+ }
727
+ // src/generator/contracts.ts
728
+ /**
729
+ * Run every registered contract factory against one resolved appearance
730
+ * config. See {@link ContractGeneratorResult} for the collected shape.
731
+ *
732
+ * @param presetName - the preset being generated (goes into the context)
733
+ * @param config - the resolved appearance config (extends flattened, base
734
+ * merged under the scheme)
735
+ * @param hash - class-name hasher; defaults to the distiller-lockstep hasher
736
+ * @param settings - the consumer's contract settings (ThemePluginConfig.contracts)
737
+ * @param factories - the registry to run; defaults to the built-in
738
+ * {@link contractGenerators} - external contract packages merge their own
739
+ * default-exported factories in and pass the merged map
740
+ */
741
+ function runContractGenerators(presetName, config, hash = hashClassName, settings = {}, factories = contractGenerators) {
742
+ const ctx = {
743
+ presetName,
744
+ config,
745
+ settings,
746
+ hash
747
+ };
748
+ const generators = {};
749
+ const themeVars = {};
750
+ const themeStyles = {};
751
+ const themeBlocks = [];
752
+ const schemeVars = {
753
+ default: {},
754
+ dark: {},
755
+ light: {}
756
+ };
757
+ const schemeStyles = {
758
+ default: {},
759
+ dark: {},
760
+ light: {}
761
+ };
762
+ const contractCss = {};
763
+ const contractLocalScss = {};
764
+ for (const [name, factory] of Object.entries(factories)) {
765
+ if (settings[name] === false) continue;
766
+ const generator = factory(ctx);
767
+ generators[name] = generator;
768
+ const vars = flattenVars(generator.vars());
769
+ const styles = generator.styles();
770
+ Object.assign(themeVars, vars);
771
+ Object.assign(themeStyles, styles);
772
+ themeBlocks.push({
773
+ contract: name,
774
+ vars,
775
+ styles
776
+ });
777
+ for (const scheme of [
778
+ "default",
779
+ "dark",
780
+ "light"
781
+ ]) {
782
+ Object.assign(schemeVars[scheme], flattenVars(generator.vars(scheme)));
783
+ Object.assign(schemeStyles[scheme], generator.styles(scheme));
784
+ }
785
+ const css = generator.css();
786
+ if (css) contractCss[name] = css;
787
+ const localScss = generator.localScss?.();
788
+ if (localScss && Object.keys(localScss).length) contractLocalScss[name] = localScss;
789
+ }
790
+ return {
791
+ generators,
792
+ themeStyles,
793
+ themeVars,
794
+ themeBlocks,
795
+ schemeVars,
796
+ schemeStyles,
797
+ contractCss,
798
+ contractLocalScss
799
+ };
800
+ }
801
+ /**
802
+ * Expand a generator's namespaced pure vars into the flat global form:
803
+ * `{ s: { m: '32px' } }` -> `{ '--0-s-m': '32px' }`. Numeric keys join the
804
+ * namespace directly (`{ uc: { 1: x } }` -> `--0-uc1`) - the unit-scale
805
+ * convention; every other key takes a dash (`--0-<ns>-<name>`).
806
+ */
807
+ function flattenVars(namespaced) {
808
+ const out = {};
809
+ for (const [ns, list] of Object.entries(namespaced)) for (const [k, v] of Object.entries(list)) out[/^\d/.test(k) ? `--0-${ns}${k}` : `--0-${ns}-${k}`] = v;
810
+ return out;
811
+ }
812
+ // src/generator/theme-def.ts
813
+ /** Type guard: a plain record (not an array, not null) - deepMerge recurses
814
+ * into these and overwrites anything else. */
815
+ function isPlainObject(v) {
816
+ return typeof v === "object" && v !== null && !Array.isArray(v);
817
+ }
818
+ /**
819
+ * Deep-merge `from` over `to` and return a new object.
820
+ *
821
+ * Nested plain objects merge key by key; anything else (scalars, arrays,
822
+ * class instances, mismatched types) is replaced wholesale - `from` wins.
823
+ * Neither input is mutated.
824
+ *
825
+ * @param to - the base object (weakest)
826
+ * @param from - the object merged on top (strongest)
827
+ * @returns the merged object
828
+ */
829
+ function deepMerge(to, from) {
830
+ const result = { ...to };
831
+ for (const key in from) if (key in to && isPlainObject(to[key]) && isPlainObject(from[key])) result[key] = deepMerge(to[key], from[key]);
832
+ else result[key] = from[key];
833
+ return result;
834
+ }
835
+ /**
836
+ * Resolve one preset into a self-complete preset, flattening its `extends`
837
+ * chain: the extended preset is merged UNDER this preset's own appearance
838
+ * configs. Results are memoized in `cache` - pass the same cache across a
839
+ * whole generation run so shared ancestors resolve once.
840
+ *
841
+ * @param presets - the preset map to resolve against
842
+ * @param name - the preset to resolve
843
+ * @param cache - per-run memo of already-resolved presets
844
+ * @returns the flattened preset
845
+ * @throws when `name` (or a preset in its `extends` chain) is undeclared
846
+ */
847
+ function resolvePreset(presets, name, cache) {
848
+ if (cache[name]) return cache[name];
849
+ const raw = presets[name];
850
+ if (!raw) throw new Error(`unknown theme preset: ${name}`);
851
+ const resolved = raw.extends ? deepMerge(resolvePreset(presets, raw.extends, cache), raw) : raw;
852
+ cache[name] = resolved;
853
+ return resolved;
854
+ }
855
+ // src/generator/generate.ts
856
+ /**
857
+ * Merge the built-in default preset UNDER every preset of the consumer's
858
+ * config (weakest -> strongest: built-in default <- the preset itself), so
859
+ * any setting a preset omits falls back to the default. The default preset
860
+ * itself is always present; an empty consumer config gets exactly the
861
+ * built-in default. Contract settings follow the same rule - the built-in
862
+ * `contracts` map sits under the consumer's one (deep-merged per contract).
863
+ */
864
+ function withDefaults(config$1 = {
865
+ default: config.default,
866
+ contracts: {},
867
+ presets: {}
868
+ }) {
869
+ const base = config.presets[config.default];
870
+ if (!base) return config$1;
871
+ const presets = config$1.presets ?? {};
872
+ const keys = /* @__PURE__ */ new Set([...Object.keys(config.presets), ...Object.keys(presets)]);
873
+ const out = {
874
+ default: keys.has(config$1.default) ? config$1.default : config.default,
875
+ contracts: deepMerge(config.contracts ?? {}, config$1.contracts ?? {}),
876
+ presets: {}
877
+ };
878
+ for (const key of keys) {
879
+ const preset = presets[key] ?? config.presets[key];
880
+ out.presets[key] = preset ? deepMerge(base, preset) : structuredClone(base);
881
+ }
882
+ return out;
883
+ }
884
+ /**
885
+ * Generate the theme for a resolved config: one base block per preset
886
+ * (`.theme-{preset}`) plus a scheme block per declared appearance
887
+ * (`.theme_{scheme}`, re-declaring the full merged config), and every
888
+ * contract's setter classes, deduped across presets, inside `@layer theme`.
889
+ *
890
+ * @param config - a config already passed through {@link withDefaults}
891
+ * @param emitPresets - which presets get a css block. Defaults to every
892
+ * preset of `config`; pass the consumer's own preset names to keep the
893
+ * built-in default out of the emitted css while it still back-fills the
894
+ * consumer's presets with fallback values
895
+ * @returns the assembled theme css and the per-contract css/scss pieces
896
+ */
897
+ function generateThemeArtifacts(config, emitPresets) {
898
+ const cache = {};
899
+ const contractCss = /* @__PURE__ */ new Map();
900
+ const localScss = /* @__PURE__ */ new Map();
901
+ let css = "";
902
+ for (const presetName of emitPresets ?? Object.keys(config.presets)) {
903
+ const preset = resolvePreset(config.presets, presetName, cache);
904
+ const base = runContractGenerators(presetName, schemesOf(preset).default, void 0, config.contracts);
905
+ collectContractPieces(contractCss, base.contractCss);
906
+ collectContractPieces(localScss, base.contractLocalScss);
907
+ css += emitThemeBlocks(`.theme-${presetName}`, base.themeBlocks);
908
+ const baseBlocks = new Map(base.themeBlocks.map((b) => [b.contract, b]));
909
+ for (const scheme of ["dark", "light"]) {
910
+ const schemeConf = schemesOf(preset)[scheme];
911
+ if (!schemeConf) continue;
912
+ const run = runContractGenerators(presetName, deepMerge(schemesOf(preset).default, schemeConf), void 0, config.contracts);
913
+ collectContractPieces(contractCss, run.contractCss);
914
+ collectContractPieces(localScss, run.contractLocalScss);
915
+ const selector = `.theme-${presetName}.theme_${scheme}`;
916
+ css += `${selector} {\n color-scheme: ${scheme};\n}\n`;
917
+ for (const block of run.themeBlocks) {
918
+ const baseBlock = baseBlocks.get(block.contract);
919
+ css += emitThemeBlocks(selector, [{
920
+ contract: block.contract,
921
+ vars: diffList(baseBlock?.vars ?? {}, block.vars),
922
+ styles: diffList(baseBlock?.styles ?? {}, block.styles)
923
+ }]);
924
+ }
925
+ const additions = [...declLines(run.schemeVars[scheme]), ...declLines(run.schemeStyles[scheme])];
926
+ if (additions.length) css += `${selector} {\n /* ${scheme} additions */\n${additions.join("\n")}\n}\n`;
927
+ }
928
+ }
929
+ const contractBody = [...contractCss.values()].join("\n");
930
+ return {
931
+ themeCss: `@layer theme, ui0;\n@layer theme {\n${`${generateBaseCss()}\n${css}${contractBody ? contractBody + "\n" : ""}`}}\n`,
932
+ contractCss: Object.fromEntries(contractCss),
933
+ localScss: Object.fromEntries(localScss)
934
+ };
935
+ }
936
+ /**
937
+ * Generate the complete theme CSS for a resolved config - the single-string
938
+ * form of {@link generateThemeArtifacts}. Pass the result through
939
+ * `withDefaults` first unless the config is already self-complete.
940
+ *
941
+ * @param config - a config already passed through {@link withDefaults}
942
+ * @param emitPresets - which presets get a css block (see
943
+ * {@link generateThemeArtifacts})
944
+ * @returns the theme css (preset + scheme blocks + setter classes)
945
+ */
946
+ function generateThemeCss(config, emitPresets) {
947
+ return generateThemeArtifacts(config, emitPresets).themeCss;
948
+ }
949
+ /**
950
+ * Merge a run's per-contract pieces into the cross-preset dedupe map - the
951
+ * first preset to emit a contract's setters/scss wins (they are
952
+ * config-independent).
953
+ */
954
+ function collectContractPieces(map, pieces) {
955
+ for (const [name, body] of Object.entries(pieces)) if (!map.has(name)) map.set(name, body);
956
+ }
957
+ /**
958
+ * VarList/StyleList -> theme-block declaration lines. Keys pass through
959
+ * verbatim (css custom properties keep their exact spelling); values are
960
+ * interpolated as authored - numbers print bare (`--0-dis-o: 1;`).
961
+ */
962
+ function declLines(list) {
963
+ return Object.entries(list).map(([k, v]) => ` ${k}: ${v};`);
964
+ }
965
+ /**
966
+ * Emit one theme block per contract that produced declarations: the same
967
+ * selector repeated, each block carrying a `/* <contract> *\/` comment, so
968
+ * the generated css reads per-contract and a disabled (or silent) contract
969
+ * simply has no block. Contracts with nothing to declare are skipped.
970
+ */
971
+ function emitThemeBlocks(selector, blocks) {
972
+ let out = "";
973
+ for (const block of blocks) {
974
+ const decls = [...declLines(block.vars), ...declLines(block.styles)];
975
+ if (!decls.length) continue;
976
+ out += `${selector} {\n /* ${block.contract} */\n${decls.join("\n")}\n}\n`;
977
+ }
978
+ return out;
979
+ }
980
+ /**
981
+ * The entries of `next` whose value differs from `prev`. Scheme blocks only
982
+ * re-declare what actually changes against the base block - everything else
983
+ * inherits, so an unchanged scheme adds no declarations at all.
984
+ */
985
+ function diffList(prev, next) {
986
+ const out = {};
987
+ for (const [k, v] of Object.entries(next)) if (prev[k] !== v) out[k] = v;
988
+ return out;
989
+ }
990
+ /**
991
+ * Generate a .d.ts that augments the global Ui0Theme* registries so the
992
+ * editor can suggest what exists: Ui0ThemeNames (presets for ThemeProvider),
993
+ * Ui0ThemeSchemeNames (appearances), Ui0ThemeColorNames (pool refs incl.
994
+ * ramp steps, unioned across every emitted preset and scheme). Pass
995
+ * withDefaults(config).
996
+ *
997
+ * @param config - a config already passed through {@link withDefaults}
998
+ * @param emitPresets - which presets contribute names (see
999
+ * {@link generateThemeArtifacts}); defaults to every preset of `config`
1000
+ */
1001
+ function generateThemeTypes(config, emitPresets) {
1002
+ const names = emitPresets ?? Object.keys(config.presets);
1003
+ const schemes = /* @__PURE__ */ new Set();
1004
+ const colors = /* @__PURE__ */ new Set();
1005
+ const cache = {};
1006
+ for (const presetName of names) {
1007
+ const appearances = schemesOf(resolvePreset(config.presets, presetName, cache));
1008
+ const base = appearances.default;
1009
+ for (const [scheme, appearance] of Object.entries(appearances)) {
1010
+ if (scheme !== "default") schemes.add(scheme);
1011
+ const pool = deepMerge(base, appearance).color;
1012
+ if (!pool) continue;
1013
+ const { base: poolBase, ramps } = resolvePool(buildPool(pool, void 0));
1014
+ for (const name of Object.keys(poolBase)) {
1015
+ colors.add(name);
1016
+ const ramp = ramps[name];
1017
+ if (!ramp) continue;
1018
+ for (const [type, steps] of Object.entries(ramp)) steps?.forEach((_, i) => colors.add(`${name}-${type}${i + 1}`));
1019
+ }
1020
+ }
1021
+ }
1022
+ const registry = (name, keys) => ` interface ${name} {\n${[...keys].sort().map((k) => ` '${k}': true`).join("\n")}\n }`;
1023
+ return `// GENERATED by @ui0/theme — do not edit
1024
+ declare global {
1025
+ interface Ui0ThemeNames {
1026
+ ${names.map((k) => ` '${k}': true`).join("\n")}
1027
+ }
1028
+ ${registry("Ui0ThemeSchemeNames", schemes)}
1029
+ ${registry("Ui0ThemeColorNames", colors)}
1030
+ }
1031
+
1032
+ export {}
1033
+ `;
1034
+ }
1035
+ export { schemesOf as S, parseRef as _, deepMerge as a, backdrop_module_css_default as b, contractGenerators as c, round_module_css_default as d, elevation_module_css_default as f, parseColorProp as g, color_module_css_default as h, withDefaults as i, typography_module_css_default as l, disabled_module_css_default as m, generateThemeCss as n, resolvePreset as o, display_module_css_default as p, generateThemeTypes as r, hashClassName as s, generateThemeArtifacts as t, size_module_css_default as u, buildPool as v, ensureThemeBaseStyle as x, resolvePool as y };
1036
+
1037
+ //# sourceMappingURL=generate-BPYE5ALG.mjs.map