@pitlane/theme 0.2.0 → 0.3.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.
@@ -0,0 +1,572 @@
1
+ import { createSchema, fail } from "remix/data-schema";
2
+ //#region src/tokens.ts
3
+ /**
4
+ * The error {@link createTheme} throws for every structural failure:
5
+ * one problem, one sentence.
6
+ *
7
+ * | Failure | Message shape |
8
+ * | --- | --- |
9
+ * | No schema entry | `"space.md" has no schema entry` |
10
+ * | Unknown reference | `"color.bg" references unknown token "color.nope"` |
11
+ * | Reference type mismatch | `"color.bg" references "space.md" of type "dimension" where "color" is required` |
12
+ * | Reference to an untyped token | `"color.bg" references untyped token "animate.spin"` |
13
+ * | Reference cycle | `Reference cycle: color.a → color.b → color.a` |
14
+ * | Variable collision | `Tokens "a.b" and "a-b" both produce the CSS variable --a-b` |
15
+ * | Reserved characters | `Token or group name "a.b" contains characters reserved by references (".", "{", "}")` |
16
+ * | Empty identifier | `Token path segment "!!" produces an empty CSS identifier` |
17
+ * | Unknown mode token | `Mode "dark" overrides unknown token "color.nope"` |
18
+ *
19
+ * Bad token *values* raise `ValidationError` from `remix/data-schema`
20
+ * instead, because there may be several and each carries its own path.
21
+ *
22
+ * @see {@link createTheme}
23
+ */
24
+ var ThemeError = class extends Error {
25
+ name = "ThemeError";
26
+ };
27
+ const VAR_RE = /^var\((--[a-z0-9-]+)\)$/;
28
+ const EMBEDDED_VAR_RE = /var\((--[a-z0-9-]+)\)/g;
29
+ /**
30
+ * Rejects a value carrying a `{path.to.token}` reference. Braces are never
31
+ * valid in a CSS value, so one can only be a reference left behind from the
32
+ * format this package used before 0.3.0, and passing it through would put
33
+ * `{color.white}` in the stylesheet where a color belongs.
34
+ *
35
+ * @internal
36
+ */
37
+ function assertNoStringReference(value, key) {
38
+ if (typeof value !== "string" || !value.includes("{")) return;
39
+ let match = /\{([^{}]+)\}/.exec(value);
40
+ if (match === null) return;
41
+ throw new ThemeError(`"${key}" contains the reference "{${match[1]}}", which is no longer a value. Reference a token by property access in an extend layer: .extend(base => ({ tokens: { … base.${match[1]} … } }))`);
42
+ }
43
+ /**
44
+ * The token a whole-value `var()` reference names, or `null` when the value is
45
+ * not one. A reference is written as a property access on the layer below, and
46
+ * an accessor leaf is a `var()` string, so this is what a reference looks like
47
+ * by the time the compiler sees it.
48
+ *
49
+ * @internal
50
+ */
51
+ function referenceTarget(value) {
52
+ if (typeof value !== "string") return null;
53
+ let match = VAR_RE.exec(value);
54
+ return match ? match[1] : null;
55
+ }
56
+ /**
57
+ * Every `var()` a value mentions, including inside a larger string. A composite
58
+ * is authored as CSS text, so a reference interpolated into a shadow or a
59
+ * transition shows up here rather than as the whole value.
60
+ *
61
+ * @internal
62
+ */
63
+ function mentionedVarNames(value) {
64
+ if (typeof value !== "string" || !value.includes("var(")) return [];
65
+ return [...value.matchAll(EMBEDDED_VAR_RE)].map((match) => match[1]);
66
+ }
67
+ /**
68
+ * Kebab-cases one path segment for a CSS variable name. Throws when
69
+ * the segment reduces to an empty identifier.
70
+ *
71
+ * @internal
72
+ */
73
+ function kebabSegment(segment) {
74
+ let kebab = segment.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
75
+ if (!kebab) throw new ThemeError(`Token path segment "${segment}" produces an empty CSS identifier`);
76
+ return kebab;
77
+ }
78
+ /**
79
+ * Walks the token tree and the schema tree together, in document
80
+ * order, into one list of tagged entries. Rejects a token with no
81
+ * schema entry, a reserved character in a name, and two tokens whose
82
+ * paths collide after kebab-casing.
83
+ *
84
+ * @internal
85
+ */
86
+ function collectTokens(tokens, schema) {
87
+ let entries = [];
88
+ walk(tokens, schema, void 0, [], entries, /* @__PURE__ */ new Map());
89
+ linkVarReferences(entries);
90
+ return entries;
91
+ }
92
+ /**
93
+ * Links a whole-value `var()` to the token it names, so it is type-checked,
94
+ * resolvable by `raw`, and visible to `select`. The link is a second pass
95
+ * because a layer may reference a token declared after it.
96
+ *
97
+ * A `var()` naming something this theme does not declare is left alone: it may
98
+ * be a custom property the application defines elsewhere.
99
+ */
100
+ function linkVarReferences(entries) {
101
+ let byVarName = new Map(entries.map((entry) => [entry.varName, entry]));
102
+ for (let entry of entries) {
103
+ if (entry.kind !== "typed" || entry.aliasOf !== void 0) continue;
104
+ if (typeof entry.value !== "string") continue;
105
+ let varName = referenceTarget(entry.value);
106
+ if (varName === null) continue;
107
+ let target = byVarName.get(varName);
108
+ if (target !== void 0) entry.aliasOf = target.key;
109
+ }
110
+ }
111
+ function walk(node, schema, inherited, path, out, varNames) {
112
+ for (let [key, value] of Object.entries(node)) {
113
+ let childPath = [...path, key];
114
+ let childKey = childPath.join(".");
115
+ if (/[.{}]/.test(key)) throw new ThemeError(`Token or group name "${childKey}" contains characters reserved by references (".", "{", "}")`);
116
+ let child = childSchema(schema, key);
117
+ let own = selfSchema(child) ?? inherited;
118
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
119
+ walk(value, child, own, childPath, out, varNames);
120
+ continue;
121
+ }
122
+ if (own === void 0) throw new ThemeError(`"${childKey}" has no schema entry`);
123
+ assertNoStringReference(value, childKey);
124
+ let varName = `--${childPath.map(kebabSegment).join("-")}`;
125
+ let existing = varNames.get(varName);
126
+ if (existing !== void 0) throw new ThemeError(`Tokens "${existing}" and "${childKey}" both produce the CSS variable ${varName}`);
127
+ varNames.set(varName, childKey);
128
+ let common = {
129
+ key: childKey,
130
+ path: childPath,
131
+ varName
132
+ };
133
+ let tag = own[TAG];
134
+ if (tag === "any") out.push({
135
+ kind: "untyped",
136
+ ...common,
137
+ value: String(value)
138
+ });
139
+ else if (tag === "scale") out.push({
140
+ kind: "scale",
141
+ ...common,
142
+ value
143
+ });
144
+ else out.push({
145
+ kind: "typed",
146
+ ...common,
147
+ type: tag,
148
+ value
149
+ });
150
+ }
151
+ }
152
+ //#endregion
153
+ //#region src/serialize.ts
154
+ const FONT_WEIGHT_KEYWORDS = {
155
+ thin: 100,
156
+ hairline: 100,
157
+ "extra-light": 200,
158
+ "ultra-light": 200,
159
+ light: 300,
160
+ normal: 400,
161
+ regular: 400,
162
+ book: 400,
163
+ medium: 500,
164
+ "semi-bold": 600,
165
+ "demi-bold": 600,
166
+ bold: 700,
167
+ "extra-bold": 800,
168
+ "ultra-bold": 800,
169
+ black: 900,
170
+ heavy: 900,
171
+ "extra-black": 950,
172
+ "ultra-black": 950
173
+ };
174
+ const COLOR_FUNCTIONS = {
175
+ hsl: {
176
+ fn: "hsl",
177
+ percents: [1, 2]
178
+ },
179
+ hwb: {
180
+ fn: "hwb",
181
+ percents: [1, 2]
182
+ },
183
+ lab: { fn: "lab" },
184
+ lch: { fn: "lch" },
185
+ oklab: { fn: "oklab" },
186
+ oklch: { fn: "oklch" }
187
+ };
188
+ const COLOR_SPACES = /* @__PURE__ */ new Set([
189
+ "srgb",
190
+ "srgb-linear",
191
+ "display-p3",
192
+ "a98-rgb",
193
+ "prophoto-rgb",
194
+ "rec2020",
195
+ "xyz-d65",
196
+ "xyz-d50"
197
+ ]);
198
+ const STROKE_KEYWORDS = /* @__PURE__ */ new Set([
199
+ "solid",
200
+ "dashed",
201
+ "dotted",
202
+ "double",
203
+ "groove",
204
+ "ridge",
205
+ "outset",
206
+ "inset"
207
+ ]);
208
+ function serializeValue(type, value, ctx, key) {
209
+ switch (type) {
210
+ case "color": return serializeColor(value, key);
211
+ case "dimension": return serializeMeasure(value, ["px", "rem"], key);
212
+ case "duration": return serializeMeasure(value, ["ms", "s"], key);
213
+ case "fontFamily": return serializeFontFamily(value, key);
214
+ case "fontWeight": return serializeFontWeight(value, key);
215
+ case "number": return serializeNumber(value, key);
216
+ case "cubicBezier": return serializeCubicBezier(value, key);
217
+ case "shadow": return serializeShadow(value, ctx, key);
218
+ case "border": return serializeBorder(value, ctx, key);
219
+ case "transition": return serializeTransition(value, ctx, key);
220
+ case "gradient": return serializeGradient(value, ctx, key);
221
+ case "strokeStyle": return serializeStrokeStyle(value, key);
222
+ }
223
+ }
224
+ function field(type, value, ctx, key) {
225
+ return serializeValue(type, value, ctx, key);
226
+ }
227
+ function invalid(key, type, value) {
228
+ return new ThemeError(`"${key}" has an invalid ${type} value: ${JSON.stringify(value)}`);
229
+ }
230
+ function serializeColor(value, key) {
231
+ if (typeof value === "string") return value;
232
+ if (typeof value !== "object" || value === null) throw invalid(key, "color", value);
233
+ let { colorSpace, components, alpha, hex } = value;
234
+ if (typeof hex === "string") return hex;
235
+ if (typeof colorSpace !== "string" || !Array.isArray(components)) throw invalid(key, "color", value);
236
+ let parts = components.map((component) => component === "none" ? "none" : serializeComponent(component, key));
237
+ let alphaPart = alpha === void 0 ? "" : ` / ${serializeComponent(alpha, key)}`;
238
+ let fn = COLOR_FUNCTIONS[colorSpace];
239
+ if (fn) {
240
+ let printed = parts.map((part, index) => fn.percents?.includes(index) && part !== "none" ? `${part}%` : part);
241
+ return `${fn.fn}(${printed.join(" ")}${alphaPart})`;
242
+ }
243
+ if (COLOR_SPACES.has(colorSpace)) return `color(${colorSpace} ${parts.join(" ")}${alphaPart})`;
244
+ throw new ThemeError(`"${key}" has unknown colorSpace "${colorSpace}"`);
245
+ }
246
+ function serializeComponent(value, key) {
247
+ if (typeof value !== "number" || !Number.isFinite(value)) throw invalid(key, "color component", value);
248
+ return String(value);
249
+ }
250
+ function serializeMeasure(value, units, key) {
251
+ if (typeof value === "string") return value;
252
+ if (typeof value === "object" && value !== null) {
253
+ let { value: amount, unit } = value;
254
+ if (typeof amount === "number" && typeof unit === "string" && units.includes(unit)) return `${amount}${unit}`;
255
+ }
256
+ throw invalid(key, `dimension/duration (${units.join("|")})`, value);
257
+ }
258
+ function serializeFontFamily(value, key) {
259
+ if (typeof value === "string") return value;
260
+ let names = Array.isArray(value) ? value : [value];
261
+ if (names.length === 0) throw invalid(key, "fontFamily", value);
262
+ return names.map((name) => {
263
+ if (typeof name !== "string") throw invalid(key, "fontFamily", value);
264
+ return /^[a-zA-Z][a-zA-Z-]*$/.test(name) ? name : `"${name.replaceAll("\"", "\\\"")}"`;
265
+ }).join(", ");
266
+ }
267
+ function serializeFontWeight(value, key) {
268
+ if (typeof value === "number") {
269
+ if (value >= 1 && value <= 1e3) return String(value);
270
+ throw invalid(key, "fontWeight", value);
271
+ }
272
+ if (typeof value === "string") {
273
+ let mapped = FONT_WEIGHT_KEYWORDS[value];
274
+ if (mapped !== void 0) return String(mapped);
275
+ throw new ThemeError(`"${key}" has unknown fontWeight keyword "${value}"`);
276
+ }
277
+ throw invalid(key, "fontWeight", value);
278
+ }
279
+ function serializeNumber(value, key) {
280
+ if (typeof value === "string") return value;
281
+ if (typeof value !== "number" || !Number.isFinite(value)) throw invalid(key, "number", value);
282
+ return String(value);
283
+ }
284
+ function serializeCubicBezier(value, key) {
285
+ if (typeof value === "string") return value;
286
+ if (!Array.isArray(value) || value.length !== 4) throw invalid(key, "cubicBezier", value);
287
+ return `cubic-bezier(${value.map((part) => serializeComponent(part, key)).join(", ")})`;
288
+ }
289
+ function serializeShadow(value, ctx, key) {
290
+ if (typeof value === "string") return value;
291
+ return (Array.isArray(value) ? value : [value]).map((shadow) => {
292
+ if (typeof shadow !== "object" || shadow === null) throw invalid(key, "shadow", value);
293
+ let { color, offsetX, offsetY, blur, spread, inset } = shadow;
294
+ let parts = [
295
+ field("dimension", offsetX, ctx, key),
296
+ field("dimension", offsetY, ctx, key),
297
+ blur === void 0 ? "0" : field("dimension", blur, ctx, key),
298
+ spread === void 0 ? "0" : field("dimension", spread, ctx, key),
299
+ field("color", color, ctx, key)
300
+ ];
301
+ return `${inset === true ? "inset " : ""}${parts.join(" ")}`;
302
+ }).join(", ");
303
+ }
304
+ function serializeBorder(value, ctx, key) {
305
+ if (typeof value === "string") return value;
306
+ if (typeof value !== "object" || value === null) throw invalid(key, "border", value);
307
+ let { color, width, style } = value;
308
+ return `${field("dimension", width, ctx, key)} ${field("strokeStyle", style, ctx, key)} ${field("color", color, ctx, key)}`;
309
+ }
310
+ function serializeTransition(value, ctx, key) {
311
+ if (typeof value === "string") return value;
312
+ if (typeof value !== "object" || value === null) throw invalid(key, "transition", value);
313
+ let { duration, timingFunction, delay } = value;
314
+ let delayPart = delay === void 0 ? "0s" : field("duration", delay, ctx, key);
315
+ return `${field("duration", duration, ctx, key)} ${field("cubicBezier", timingFunction, ctx, key)} ${delayPart}`;
316
+ }
317
+ function serializeGradient(value, ctx, key) {
318
+ if (typeof value === "string") return value;
319
+ if (!Array.isArray(value)) throw invalid(key, "gradient", value);
320
+ return value.map((stop) => {
321
+ if (typeof stop !== "object" || stop === null) throw invalid(key, "gradient", value);
322
+ let { color, position } = stop;
323
+ if (typeof position !== "number") throw invalid(key, "gradient stop position", position);
324
+ return `${field("color", color, ctx, key)} ${Number((position * 100).toFixed(4))}%`;
325
+ }).join(", ");
326
+ }
327
+ function serializeStrokeStyle(value, key) {
328
+ if (typeof value === "string") {
329
+ if (STROKE_KEYWORDS.has(value)) return value;
330
+ throw new ThemeError(`"${key}" has unknown strokeStyle keyword "${value}"`);
331
+ }
332
+ if (typeof value === "object" && value !== null) return "dashed";
333
+ throw invalid(key, "strokeStyle", value);
334
+ }
335
+ //#endregion
336
+ //#region src/schema.ts
337
+ /** @internal */
338
+ const TAG = Symbol.for("pitlane.theme.tag");
339
+ /** @internal */
340
+ const SELF = Symbol.for("pitlane.theme.self");
341
+ const NO_REFS = { varRefFor(key) {
342
+ return `var(--${key.replaceAll(".", "-")})`;
343
+ } };
344
+ /**
345
+ * Standard Schema path segments may be objects, so stringify each one
346
+ * rather than relying on `Array#join`.
347
+ *
348
+ * @internal
349
+ */
350
+ function pathKey(path) {
351
+ return path.map((segment) => typeof segment === "object" && segment !== null && "key" in segment ? String(segment.key) : String(segment)).join(".");
352
+ }
353
+ function tokenSchema(tag) {
354
+ let schema = createSchema((value, context) => {
355
+ let key = pathKey(context.path);
356
+ if (tag === "any") {
357
+ if (typeof value === "string" || typeof value === "number") return { value: String(value) };
358
+ return fail(`"${key}" must be a string or a number`, context.path);
359
+ }
360
+ try {
361
+ return { value: serializeValue(tag === "scale" ? "dimension" : tag, value, NO_REFS, key) };
362
+ } catch (error) {
363
+ return fail(error.message, context.path);
364
+ }
365
+ });
366
+ return Object.assign(schema, { [TAG]: tag });
367
+ }
368
+ /**
369
+ * A `color` token. Accepts any CSS color, including `light-dark()`,
370
+ * `color-mix()`, and `currentColor`, plus DTCG's structured form.
371
+ *
372
+ * @returns A schema declaring the `color` token type
373
+ *
374
+ * @example
375
+ * ```ts
376
+ * let schema = { color: s.color() };
377
+ * let tokens = { color: { white: "#fff", page: lightDark("#fff", "#111") } };
378
+ * ```
379
+ */
380
+ function color() {
381
+ return tokenSchema("color");
382
+ }
383
+ /**
384
+ * A `dimension` token. Accepts any CSS length, including `clamp()`,
385
+ * `calc()`, `%`, and `em`.
386
+ *
387
+ * @returns A schema declaring the `dimension` token type
388
+ */
389
+ function dimension() {
390
+ return tokenSchema("dimension");
391
+ }
392
+ /**
393
+ * A `duration` token. Accepts `ms`, `s`, and `calc()`.
394
+ *
395
+ * @returns A schema declaring the `duration` token type
396
+ */
397
+ function duration() {
398
+ return tokenSchema("duration");
399
+ }
400
+ /**
401
+ * A `number` token. Accepts a finite number, which is what unitless
402
+ * CSS values such as `line-height` and `opacity` take.
403
+ *
404
+ * @returns A schema declaring the `number` token type
405
+ */
406
+ function number() {
407
+ return tokenSchema("number");
408
+ }
409
+ /**
410
+ * A `cubicBezier` token, named for the CSS property it feeds. Accepts
411
+ * a four-number tuple or `cubic-bezier(…)` text.
412
+ *
413
+ * @returns A schema declaring the `cubicBezier` token type
414
+ */
415
+ function easing() {
416
+ return tokenSchema("cubicBezier");
417
+ }
418
+ /**
419
+ * A `shadow` token. Accepts CSS shadow text, `inset` included.
420
+ *
421
+ * @returns A schema declaring the `shadow` token type
422
+ */
423
+ function shadow() {
424
+ return tokenSchema("shadow");
425
+ }
426
+ /**
427
+ * A `border` token. Accepts CSS border shorthand text.
428
+ *
429
+ * @returns A schema declaring the `border` token type
430
+ */
431
+ function border() {
432
+ return tokenSchema("border");
433
+ }
434
+ /**
435
+ * A `transition` token. Accepts CSS transition shorthand text.
436
+ *
437
+ * @returns A schema declaring the `transition` token type
438
+ */
439
+ function transition() {
440
+ return tokenSchema("transition");
441
+ }
442
+ /**
443
+ * A `gradient` token. Accepts CSS gradient function text.
444
+ *
445
+ * @returns A schema declaring the `gradient` token type
446
+ */
447
+ function gradient() {
448
+ return tokenSchema("gradient");
449
+ }
450
+ /**
451
+ * A `strokeStyle` token, named for the CSS value it holds. Accepts a
452
+ * line-style keyword.
453
+ *
454
+ * @returns A schema declaring the `strokeStyle` token type
455
+ */
456
+ function stroke() {
457
+ return tokenSchema("strokeStyle");
458
+ }
459
+ /**
460
+ * The two font token types, grouped because they share a prefix.
461
+ *
462
+ * `font.family()` accepts a font stack, as a string or an array of
463
+ * names; an array joins with commas and quotes what needs quoting.
464
+ * `font.weight()` accepts 1 to 1000 or one of DTCG's nineteen
465
+ * keywords, and emits the number.
466
+ *
467
+ * @example
468
+ * ```ts
469
+ * let schema = { font: s.font.family(), weight: s.font.weight() };
470
+ * let tokens = { font: { sans: ["Inter var", "system-ui"] }, weight: { bold: 700 } };
471
+ * ```
472
+ */
473
+ let font = {
474
+ family: () => tokenSchema("fontFamily"),
475
+ weight: () => tokenSchema("fontWeight")
476
+ };
477
+ /**
478
+ * A dimension token whose accessor leaf is a multiplier rather than a
479
+ * value. The token emits its own custom property; the accessor leaf is
480
+ * callable, and carries the base itself as `.token`.
481
+ *
482
+ * This is Tailwind's `--spacing`: one base that the whole scale
483
+ * multiplies, with no named steps.
484
+ *
485
+ * @returns A schema declaring a scale token
486
+ *
487
+ * @example
488
+ * ```ts
489
+ * let theme = createTheme({
490
+ * schema: { spacing: s.scale() },
491
+ * tokens: { spacing: "0.25rem" },
492
+ * });
493
+ *
494
+ * theme.token.spacing(4); // "calc(var(--spacing) * 4)"
495
+ * theme.token.spacing.token; // "var(--spacing)"
496
+ * ```
497
+ */
498
+ function scale() {
499
+ return tokenSchema("scale");
500
+ }
501
+ /**
502
+ * A token with no type. Its value is emitted verbatim and its accessor
503
+ * leaf brands as a plain `string`, which the open-grammar CSS
504
+ * properties accept and the token-mapped longhands still reject.
505
+ *
506
+ * This exists for CSS values with no DTCG type, such as
507
+ * `spin 1s linear infinite` and `16 / 9`. An untyped token may not be
508
+ * the target of a typed token's reference, because there is no type to
509
+ * check against.
510
+ *
511
+ * @returns A schema declaring an untyped token
512
+ */
513
+ function any() {
514
+ return tokenSchema("any");
515
+ }
516
+ /**
517
+ * A node that is itself typed and also carries per-child overrides.
518
+ * `self` applies to that node and to every descendant without its own
519
+ * entry; each key in `children` overrides it from there down.
520
+ *
521
+ * The self schema rides on a symbol key, so no token name is reserved:
522
+ * a token named `default` can carry its own type.
523
+ *
524
+ * @param self - The schema for this node and its unlabelled descendants
525
+ * @param children - Per-child schema overrides
526
+ * @returns A schema group
527
+ *
528
+ * @example
529
+ * ```ts
530
+ * let schema = {
531
+ * control: s.group(s.dimension(), { color: s.color(), opacity: s.number() }),
532
+ * };
533
+ * // control.height.sm is a dimension; control.color.border is a color.
534
+ * ```
535
+ */
536
+ function group(self, children) {
537
+ return {
538
+ ...children,
539
+ [SELF]: self
540
+ };
541
+ }
542
+ /**
543
+ * True when a node declares a token type rather than grouping others.
544
+ *
545
+ * @internal
546
+ */
547
+ function isTokenSchema(node) {
548
+ return typeof node === "object" && node !== null && TAG in node;
549
+ }
550
+ /**
551
+ * The schema a node declares for itself and its unlabelled children,
552
+ * or `undefined` when it only groups.
553
+ *
554
+ * @internal
555
+ */
556
+ function selfSchema(node) {
557
+ if (isTokenSchema(node)) return node;
558
+ if (typeof node === "object" && node !== null && SELF in node) return node[SELF];
559
+ }
560
+ /**
561
+ * The schema node for one child key, or `undefined` when the parent
562
+ * declares nothing for it.
563
+ *
564
+ * @internal
565
+ */
566
+ function childSchema(node, key) {
567
+ if (typeof node !== "object" || node === null || isTokenSchema(node)) return void 0;
568
+ if (!Object.hasOwn(node, key)) return void 0;
569
+ return node[key];
570
+ }
571
+ //#endregion
572
+ export { assertNoStringReference as C, referenceTarget as D, mentionedVarNames as E, ThemeError as S, kebabSegment as T, selfSchema as _, childSchema as a, transition as b, duration as c, gradient as d, group as f, scale as g, pathKey as h, border as i, easing as l, number as m, TAG as n, color as o, isTokenSchema as p, any as r, dimension as s, SELF as t, font as u, shadow as v, collectTokens as w, serializeValue as x, stroke as y };
@@ -0,0 +1,2 @@
1
+ import { C as stroke, S as shadow, _ as isTokenSchema, a as TAG, b as scale, c as border, d as dimension, f as duration, g as group, h as gradient, i as SchemaTag, l as childSchema, m as font, n as SchemaGroup, o as TokenSchema, p as easing, r as SchemaNode, s as any, t as SELF, u as color, v as number, w as transition, x as selfSchema, y as pathKey } from "./schema-CRP607Pg.mjs";
2
+ export { SELF, SchemaGroup, SchemaNode, SchemaTag, TAG, TokenSchema, any, border, childSchema, color, dimension, duration, easing, font, gradient, group, isTokenSchema, number, pathKey, scale, selfSchema, shadow, stroke, transition };
@@ -0,0 +1,2 @@
1
+ import { _ as selfSchema, a as childSchema, b as transition, c as duration, d as gradient, f as group, g as scale, h as pathKey, i as border, l as easing, m as number, n as TAG, o as color, p as isTokenSchema, r as any, s as dimension, t as SELF, u as font, v as shadow, y as stroke } from "./schema-JmfNnMzr.mjs";
2
+ export { SELF, TAG, any, border, childSchema, color, dimension, duration, easing, font, gradient, group, isTokenSchema, number, pathKey, scale, selfSchema, shadow, stroke, transition };