zyzz 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -19
- package/dist/Config.d.ts +16 -167
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js +7 -246
- package/dist/Config.js.map +1 -1
- package/dist/Style.d.ts +15 -12
- package/dist/Style.d.ts.map +1 -1
- package/dist/Style.js +51 -26
- package/dist/Style.js.map +1 -1
- package/dist/Vars.d.ts +114 -0
- package/dist/Vars.d.ts.map +1 -0
- package/dist/Vars.js +42 -0
- package/dist/Vars.js.map +1 -0
- package/dist/compiler/Graph.js +11 -8
- package/dist/compiler/Graph.js.map +1 -1
- package/dist/compiler/Native.d.ts +5 -5
- package/dist/compiler/Native.d.ts.map +1 -1
- package/dist/compiler/Native.js +21 -21
- package/dist/compiler/Native.js.map +1 -1
- package/dist/compiler/Source.d.ts +8 -6
- package/dist/compiler/Source.d.ts.map +1 -1
- package/dist/compiler/Source.js +47 -14
- package/dist/compiler/Source.js.map +1 -1
- package/dist/compiler/Transform.d.ts +1 -1
- package/dist/compiler/Transform.d.ts.map +1 -1
- package/dist/compiler/Transform.js +58 -22
- package/dist/compiler/Transform.js.map +1 -1
- package/dist/compiler/internal/Compositions.d.ts +5 -0
- package/dist/compiler/internal/Compositions.d.ts.map +1 -1
- package/dist/compiler/internal/Compositions.js +22 -3
- package/dist/compiler/internal/Compositions.js.map +1 -1
- package/dist/compiler/internal/Configurations.d.ts.map +1 -1
- package/dist/compiler/internal/Configurations.js +73 -12
- package/dist/compiler/internal/Configurations.js.map +1 -1
- package/dist/compiler/internal/Contract.d.ts +1 -1
- package/dist/compiler/internal/Contract.d.ts.map +1 -1
- package/dist/compiler/internal/Contract.js +155 -13
- package/dist/compiler/internal/Contract.js.map +1 -1
- package/dist/compiler/internal/Contributions.js +1 -1
- package/dist/compiler/internal/Contributions.js.map +1 -1
- package/dist/compiler/internal/Dynamic.js +1 -1
- package/dist/compiler/internal/Dynamic.js.map +1 -1
- package/dist/compiler/internal/Expression.d.ts +3 -0
- package/dist/compiler/internal/Expression.d.ts.map +1 -1
- package/dist/compiler/internal/Expression.js +21 -0
- package/dist/compiler/internal/Expression.js.map +1 -1
- package/dist/compiler/internal/Identifiers.d.ts +1 -1
- package/dist/compiler/internal/Identifiers.d.ts.map +1 -1
- package/dist/compiler/internal/Identifiers.js +2 -2
- package/dist/compiler/internal/Identifiers.js.map +1 -1
- package/dist/compiler/internal/NativeBindings.d.ts +1 -1
- package/dist/compiler/internal/NativeBindings.d.ts.map +1 -1
- package/dist/compiler/internal/NativeBindings.js +3 -3
- package/dist/compiler/internal/NativeBindings.js.map +1 -1
- package/dist/compiler/internal/PackedStyles.d.ts +1 -1
- package/dist/compiler/internal/PackedStyles.d.ts.map +1 -1
- package/dist/compiler/internal/PackedStyles.js +15 -25
- package/dist/compiler/internal/PackedStyles.js.map +1 -1
- package/dist/compiler/internal/Recipes.js +1 -1
- package/dist/compiler/internal/Recipes.js.map +1 -1
- package/dist/compiler/internal/Selectors.js +1 -1
- package/dist/compiler/internal/Selectors.js.map +1 -1
- package/dist/compiler/internal/Themes.d.ts +12 -3
- package/dist/compiler/internal/Themes.d.ts.map +1 -1
- package/dist/compiler/internal/Themes.js +192 -52
- package/dist/compiler/internal/Themes.js.map +1 -1
- package/dist/compiler/internal/{Variables.d.ts → Vars.d.ts} +1 -1
- package/dist/compiler/internal/Vars.d.ts.map +1 -0
- package/dist/compiler/internal/{Variables.js → Vars.js} +3 -3
- package/dist/compiler/internal/Vars.js.map +1 -0
- package/dist/default.d.ts +147 -2562
- package/dist/default.d.ts.map +1 -1
- package/dist/default.js +85 -80
- package/dist/default.js.map +2 -2
- package/dist/default.js.zyzz.json +1 -1
- package/dist/esbuild/index.d.ts +3 -0
- package/dist/esbuild/index.d.ts.map +1 -0
- package/dist/esbuild/index.js +5 -0
- package/dist/esbuild/index.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/Authoring.d.ts +1 -1
- package/dist/internal/Authoring.d.ts.map +1 -1
- package/dist/internal/Authoring.js +4 -4
- package/dist/internal/Authoring.js.map +1 -1
- package/dist/internal/Binding.d.ts +1 -1
- package/dist/internal/Binding.d.ts.map +1 -1
- package/dist/internal/Completion.d.ts +19 -0
- package/dist/internal/Completion.d.ts.map +1 -0
- package/dist/internal/Completion.js +2 -0
- package/dist/internal/Completion.js.map +1 -0
- package/dist/internal/Condition.d.ts +3 -1
- package/dist/internal/Condition.d.ts.map +1 -1
- package/dist/internal/Condition.js.map +1 -1
- package/dist/internal/Configuration.d.ts +248 -0
- package/dist/internal/Configuration.d.ts.map +1 -0
- package/dist/internal/Configuration.js +343 -0
- package/dist/internal/Configuration.js.map +1 -0
- package/dist/{Theme.d.ts → internal/Theme.d.ts} +15 -13
- package/dist/internal/Theme.d.ts.map +1 -0
- package/dist/{Theme.js → internal/Theme.js} +39 -12
- package/dist/internal/Theme.js.map +1 -0
- package/dist/internal/Token.d.ts +46 -16
- package/dist/internal/Token.d.ts.map +1 -1
- package/dist/internal/Token.js +89 -5
- package/dist/internal/Token.js.map +1 -1
- package/dist/internal/Typography.d.ts +13 -5
- package/dist/internal/Typography.d.ts.map +1 -1
- package/dist/internal/Typography.js +42 -6
- package/dist/internal/Typography.js.map +1 -1
- package/dist/internal/Value.d.ts +6 -1
- package/dist/internal/Value.d.ts.map +1 -1
- package/dist/internal/Value.js.map +1 -1
- package/dist/internal/VariableSets.d.ts +20 -0
- package/dist/internal/VariableSets.d.ts.map +1 -0
- package/dist/internal/VariableSets.js +317 -0
- package/dist/internal/VariableSets.js.map +1 -0
- package/dist/next/loader.js +15 -5
- package/dist/next/loader.js.map +1 -1
- package/dist/node/Host.d.ts.map +1 -1
- package/dist/node/Host.js +1 -1
- package/dist/node/Host.js.map +1 -1
- package/dist/react-native/Host.d.ts +2 -2
- package/dist/react-native/Host.d.ts.map +1 -1
- package/dist/react-native/Host.js +4 -4
- package/dist/react-native/Host.js.map +1 -1
- package/dist/react-native/StyleSheet.d.ts +9 -8
- package/dist/react-native/StyleSheet.d.ts.map +1 -1
- package/dist/react-native/StyleSheet.js +29 -23
- package/dist/react-native/StyleSheet.js.map +1 -1
- package/dist/react-native/Variants.d.ts +3 -3
- package/dist/react-native/Variants.d.ts.map +1 -1
- package/dist/react-native/Variants.js +2 -2
- package/dist/react-native/react.d.ts +1 -1
- package/dist/react-native/react.d.ts.map +1 -1
- package/dist/react-native/react.js +5 -5
- package/dist/react-native/react.js.map +1 -1
- package/dist/rollup/index.d.ts +3 -0
- package/dist/rollup/index.d.ts.map +1 -0
- package/dist/rollup/index.js +5 -0
- package/dist/rollup/index.js.map +1 -0
- package/dist/runtime/Appearance.d.ts +7 -7
- package/dist/runtime/Appearance.d.ts.map +1 -1
- package/dist/runtime/Appearance.js +15 -15
- package/dist/runtime/Appearance.js.map +1 -1
- package/dist/runtime/Dynamic.d.ts.map +1 -1
- package/dist/runtime/Dynamic.js +4 -1
- package/dist/runtime/Dynamic.js.map +1 -1
- package/dist/runtime/NativeContext.d.ts +4 -4
- package/dist/runtime/NativeContext.d.ts.map +1 -1
- package/dist/runtime/NativeContext.js +5 -5
- package/dist/runtime/NativeContext.js.map +1 -1
- package/dist/runtime/NativeDynamic.d.ts +1 -1
- package/dist/runtime/NativeDynamic.d.ts.map +1 -1
- package/dist/runtime/NativeDynamic.js.map +1 -1
- package/dist/runtime/Props.d.ts +1 -1
- package/dist/runtime/Props.js +3 -3
- package/dist/runtime/Props.js.map +1 -1
- package/dist/runtime/Selection.d.ts +14 -10
- package/dist/runtime/Selection.d.ts.map +1 -1
- package/dist/runtime/Selection.js +19 -18
- package/dist/runtime/Selection.js.map +1 -1
- package/dist/styleFunction.d.ts +14 -14
- package/dist/styleFunction.d.ts.map +1 -1
- package/dist/styleFunction.js.map +1 -1
- package/dist/unplugin/index.d.ts +20 -0
- package/dist/unplugin/index.d.ts.map +1 -0
- package/dist/unplugin/index.js +498 -0
- package/dist/unplugin/index.js.map +1 -0
- package/dist/variants.d.ts +3 -3
- package/dist/variants.d.ts.map +1 -1
- package/dist/variants.js.map +1 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +6 -3
- package/dist/vite/index.js.map +1 -1
- package/dist/web/Css.d.ts +4 -3
- package/dist/web/Css.d.ts.map +1 -1
- package/dist/web/Css.js +4 -4
- package/dist/web/Css.js.map +1 -1
- package/dist/web/internal/Themes.d.ts +3 -2
- package/dist/web/internal/Themes.d.ts.map +1 -1
- package/dist/web/internal/Themes.js +42 -6
- package/dist/web/internal/Themes.js.map +1 -1
- package/dist/webpack/index.d.ts +3 -0
- package/dist/webpack/index.d.ts.map +1 -0
- package/dist/webpack/index.js +5 -0
- package/dist/webpack/index.js.map +1 -0
- package/package.json +23 -2
- package/src/Config.ts +43 -685
- package/src/Style.ts +97 -34
- package/src/Vars.ts +299 -0
- package/src/compiler/Graph.ts +14 -9
- package/src/compiler/Native.ts +29 -32
- package/src/compiler/Source.ts +59 -21
- package/src/compiler/Transform.ts +73 -23
- package/src/compiler/internal/Compositions.ts +36 -3
- package/src/compiler/internal/Configurations.ts +83 -11
- package/src/compiler/internal/Contract.ts +207 -15
- package/src/compiler/internal/Contributions.ts +1 -1
- package/src/compiler/internal/Dynamic.ts +1 -1
- package/src/compiler/internal/Expression.ts +26 -0
- package/src/compiler/internal/Identifiers.ts +2 -1
- package/src/compiler/internal/NativeBindings.ts +3 -3
- package/src/compiler/internal/PackedStyles.ts +22 -26
- package/src/compiler/internal/Recipes.ts +1 -1
- package/src/compiler/internal/Selectors.ts +1 -1
- package/src/compiler/internal/Themes.ts +266 -57
- package/src/compiler/internal/{Variables.ts → Vars.ts} +2 -2
- package/src/default.ts +173 -154
- package/src/esbuild/index.ts +5 -0
- package/src/index.ts +4 -4
- package/src/internal/Authoring.ts +5 -7
- package/src/internal/Binding.ts +1 -1
- package/src/internal/Completion.ts +42 -0
- package/src/internal/Condition.ts +31 -1
- package/src/internal/Configuration.ts +970 -0
- package/src/{Theme.ts → internal/Theme.ts} +75 -20
- package/src/internal/Token.ts +258 -85
- package/src/internal/Typography.ts +71 -16
- package/src/internal/Value.ts +45 -26
- package/src/internal/VariableSets.ts +458 -0
- package/src/next/loader.ts +19 -5
- package/src/node/Host.ts +1 -2
- package/src/react-native/Host.ts +6 -6
- package/src/react-native/StyleSheet.ts +49 -42
- package/src/react-native/Variants.ts +3 -3
- package/src/react-native/react.ts +6 -6
- package/src/rollup/index.ts +5 -0
- package/src/runtime/Appearance.ts +20 -20
- package/src/runtime/Dynamic.ts +4 -1
- package/src/runtime/NativeContext.ts +8 -8
- package/src/runtime/NativeDynamic.ts +2 -4
- package/src/runtime/Props.ts +3 -3
- package/src/runtime/Selection.ts +44 -33
- package/src/styleFunction.ts +22 -19
- package/src/unplugin/index.ts +600 -0
- package/src/variants.ts +7 -5
- package/src/vite/index.ts +5 -4
- package/src/web/Css.ts +10 -7
- package/src/web/internal/Themes.ts +52 -9
- package/src/webpack/index.ts +5 -0
- package/dist/Theme.d.ts.map +0 -1
- package/dist/Theme.js.map +0 -1
- package/dist/compiler/internal/Variables.d.ts.map +0 -1
- package/dist/compiler/internal/Variables.js.map +0 -1
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
* Defines typed token contracts and compatible immutable theme overrides.
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
|
-
import { MissingTransformError, style } from '
|
|
6
|
-
import * as Authoring from './
|
|
7
|
-
import * as Identity from './
|
|
8
|
-
import { variants } from '
|
|
9
|
-
import type * as Binding from './
|
|
10
|
-
import type * as Literal from './
|
|
11
|
-
import * as Query from './
|
|
12
|
-
import * as Token from './
|
|
13
|
-
import * as Typography from './
|
|
14
|
-
import type * as Value from './
|
|
15
|
-
import type * as Style from '
|
|
5
|
+
import { MissingTransformError, style } from '../styleFunction.js'
|
|
6
|
+
import * as Authoring from './Authoring.js'
|
|
7
|
+
import * as Identity from './Identity.js'
|
|
8
|
+
import { variants } from '../variants.js'
|
|
9
|
+
import type * as Binding from './Binding.js'
|
|
10
|
+
import type * as Literal from './Literal.js'
|
|
11
|
+
import * as Query from './Query.js'
|
|
12
|
+
import * as Token from './Token.js'
|
|
13
|
+
import * as Typography from './Typography.js'
|
|
14
|
+
import type * as Value from './Value.js'
|
|
15
|
+
import type * as Style from '../Style.js'
|
|
16
|
+
import * as Condition from './Condition.js'
|
|
16
17
|
|
|
17
18
|
/** Complete color-scheme pair or a shared color. */
|
|
18
19
|
export type Color =
|
|
@@ -96,7 +97,7 @@ export type Definition<
|
|
|
96
97
|
/** Token-aware single-element recipe authoring. */
|
|
97
98
|
readonly variants: boundVariants
|
|
98
99
|
/** Web variable references; source templates retain their identity and fallback. */
|
|
99
|
-
readonly vars: Token.
|
|
100
|
+
readonly vars: Token.Vars<References<tokens>>
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
/**
|
|
@@ -128,6 +129,8 @@ export function extend<
|
|
|
128
129
|
data.contract,
|
|
129
130
|
data.values,
|
|
130
131
|
data.queries,
|
|
132
|
+
undefined,
|
|
133
|
+
data.paths,
|
|
131
134
|
) as unknown as Definition<tokens, boundStyle, boundVariants>
|
|
132
135
|
}
|
|
133
136
|
|
|
@@ -218,6 +221,7 @@ type ReferenceTree<
|
|
|
218
221
|
type Scalar<group> = group extends
|
|
219
222
|
| 'spacing'
|
|
220
223
|
| 'borderRadius'
|
|
224
|
+
| 'borderWidth'
|
|
221
225
|
| 'margin'
|
|
222
226
|
| 'padding'
|
|
223
227
|
? Literal.Length
|
|
@@ -242,6 +246,10 @@ export type Tokens = {
|
|
|
242
246
|
readonly borderColor?: Palette<Color> | undefined
|
|
243
247
|
/** Nonnegative corner radii. */
|
|
244
248
|
readonly borderRadius?: Palette<Literal.Length> | undefined
|
|
249
|
+
/** Nonnegative widths for physical and logical border declarations. */
|
|
250
|
+
readonly borderWidth?:
|
|
251
|
+
| Palette<Exclude<Literal.Length, `${number}%`>>
|
|
252
|
+
| undefined
|
|
245
253
|
/** Compile-time viewport width thresholds. */
|
|
246
254
|
readonly breakpoints?: Readonly<Record<string, Query.Length>> | undefined
|
|
247
255
|
/** Shared colors available to every supported color property. */
|
|
@@ -288,6 +296,7 @@ function build(
|
|
|
288
296
|
base?: Readonly<Record<string, Token.Value>>,
|
|
289
297
|
baseQueries?: Query.Metadata,
|
|
290
298
|
scope?: string,
|
|
299
|
+
basePaths?: Readonly<Record<string, readonly string[]>>,
|
|
291
300
|
) {
|
|
292
301
|
const values: Record<string, Token.Value> = Object.assign(
|
|
293
302
|
Object.create(null),
|
|
@@ -306,6 +315,9 @@ function build(
|
|
|
306
315
|
) as Record<string, string>,
|
|
307
316
|
}
|
|
308
317
|
|
|
318
|
+
const paths: Record<string, readonly string[]> = { ...basePaths }
|
|
319
|
+
const conditions: (readonly string[])[] = []
|
|
320
|
+
|
|
309
321
|
let hasQueries = !!baseQueries
|
|
310
322
|
const active = new Set<object>()
|
|
311
323
|
|
|
@@ -315,6 +327,8 @@ function build(
|
|
|
315
327
|
path: readonly string[],
|
|
316
328
|
) {
|
|
317
329
|
const key = path.join('.')
|
|
330
|
+
if (path.some((part) => part.startsWith('@')))
|
|
331
|
+
paths[key] = Object.freeze([...path])
|
|
318
332
|
const scalar = typeof value === 'string' || typeof value === 'number'
|
|
319
333
|
if (group === 'typography' && scalar)
|
|
320
334
|
throw new InvalidError(
|
|
@@ -374,6 +388,24 @@ function build(
|
|
|
374
388
|
|
|
375
389
|
for (const [name, child] of entries!) {
|
|
376
390
|
const next = [...path, name]
|
|
391
|
+
if (group === 'typography' && name.startsWith('@')) {
|
|
392
|
+
if (!Typography.condition(name))
|
|
393
|
+
throw new InvalidError(
|
|
394
|
+
next,
|
|
395
|
+
'Typography conditions must be media or container queries.',
|
|
396
|
+
)
|
|
397
|
+
conditions.push(next)
|
|
398
|
+
}
|
|
399
|
+
if (
|
|
400
|
+
group === 'typography' &&
|
|
401
|
+
path.some((part) => part.startsWith('@')) &&
|
|
402
|
+
!Typography.condition(name) &&
|
|
403
|
+
!Typography.properties.includes(name as Typography.Property)
|
|
404
|
+
)
|
|
405
|
+
throw new InvalidError(
|
|
406
|
+
next,
|
|
407
|
+
'Typography query blocks accept only typography fields and queries.',
|
|
408
|
+
)
|
|
377
409
|
if (
|
|
378
410
|
base &&
|
|
379
411
|
!Object.keys(base).some(
|
|
@@ -482,6 +514,7 @@ function build(
|
|
|
482
514
|
'backgroundColor',
|
|
483
515
|
'borderColor',
|
|
484
516
|
'borderRadius',
|
|
517
|
+
'borderWidth',
|
|
485
518
|
'color',
|
|
486
519
|
'margin',
|
|
487
520
|
'padding',
|
|
@@ -510,7 +543,8 @@ function build(
|
|
|
510
543
|
for (const [name, value] of entries) {
|
|
511
544
|
if (
|
|
512
545
|
group === 'typography' &&
|
|
513
|
-
Typography.properties.includes(name as Typography.Property)
|
|
546
|
+
(Typography.properties.includes(name as Typography.Property) ||
|
|
547
|
+
name.startsWith('@'))
|
|
514
548
|
)
|
|
515
549
|
throw new InvalidError(
|
|
516
550
|
[group, name],
|
|
@@ -520,12 +554,20 @@ function build(
|
|
|
520
554
|
}
|
|
521
555
|
}
|
|
522
556
|
|
|
557
|
+
for (const path of conditions) {
|
|
558
|
+
try {
|
|
559
|
+
Condition.normalize(Query.resolve(path.at(-1)!, queries))
|
|
560
|
+
} catch (error) {
|
|
561
|
+
throw new InvalidError(path, (error as Error).message)
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
523
565
|
type Tree = { [key: string]: Tree | Token.Reference }
|
|
524
566
|
|
|
525
567
|
const tokens: Tree = Object.create(null)
|
|
526
568
|
|
|
527
569
|
for (const [path, value] of Object.entries(values)) {
|
|
528
|
-
const parts = path.split('.')
|
|
570
|
+
const parts = paths[path] ?? path.split('.')
|
|
529
571
|
let tree = tokens
|
|
530
572
|
|
|
531
573
|
for (const part of parts.slice(0, -1))
|
|
@@ -577,6 +619,7 @@ function build(
|
|
|
577
619
|
{
|
|
578
620
|
value: Object.freeze({
|
|
579
621
|
contract,
|
|
622
|
+
...(Object.keys(paths).length ? { paths: Object.freeze(paths) } : {}),
|
|
580
623
|
values: Object.freeze(values),
|
|
581
624
|
...(hasQueries
|
|
582
625
|
? {
|
|
@@ -627,7 +670,8 @@ function record(
|
|
|
627
670
|
if (
|
|
628
671
|
typeof key !== 'string' ||
|
|
629
672
|
!key ||
|
|
630
|
-
key.includes('.')
|
|
673
|
+
(key.includes('.') &&
|
|
674
|
+
!(path[0] === 'typography' && Typography.condition(key))) ||
|
|
631
675
|
!descriptor.enumerable ||
|
|
632
676
|
!('value' in descriptor)
|
|
633
677
|
)
|
|
@@ -694,7 +738,7 @@ type ValidPalette<palette, group> = palette extends undefined
|
|
|
694
738
|
[key in keyof palette]: key extends `${string}!${string}`
|
|
695
739
|
? never
|
|
696
740
|
: group extends 'typography'
|
|
697
|
-
? key extends Typography.Property
|
|
741
|
+
? key extends Typography.Property | `@${string}`
|
|
698
742
|
? never
|
|
699
743
|
: ValidTree<palette[key], group>
|
|
700
744
|
: ValidTree<palette[key], group>
|
|
@@ -767,11 +811,22 @@ type ValidTree<tree, group> = tree extends string | number
|
|
|
767
811
|
[key in keyof tree]: key extends `${string}!${string}`
|
|
768
812
|
? never
|
|
769
813
|
: group extends 'typography'
|
|
770
|
-
? key extends
|
|
771
|
-
?
|
|
772
|
-
? ValidTree<tree[key],
|
|
814
|
+
? key extends `@${string}`
|
|
815
|
+
? key extends Typography.Condition
|
|
816
|
+
? ValidTree<tree[key], group> &
|
|
817
|
+
Record<
|
|
818
|
+
Exclude<
|
|
819
|
+
keyof tree[key],
|
|
820
|
+
Typography.Property | Typography.Condition
|
|
821
|
+
>,
|
|
822
|
+
never
|
|
823
|
+
>
|
|
773
824
|
: never
|
|
774
|
-
:
|
|
825
|
+
: key extends Typography.Property
|
|
826
|
+
? tree[key] extends string | number
|
|
827
|
+
? ValidTree<tree[key], key>
|
|
828
|
+
: never
|
|
829
|
+
: ValidTree<tree[key], group>
|
|
775
830
|
: ValidTree<tree[key], group>
|
|
776
831
|
}
|
|
777
832
|
: group extends 'color' | 'backgroundColor' | 'borderColor' | 'textColor'
|
package/src/internal/Token.ts
CHANGED
|
@@ -2,19 +2,28 @@
|
|
|
2
2
|
* Carries portable theme references and enforces their property domains.
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
|
-
import
|
|
5
|
+
import * as Binding from './Binding.js'
|
|
6
6
|
import type * as Query from './Query.js'
|
|
7
7
|
import type * as Shorthands from './Shorthands.js'
|
|
8
|
-
import type * as Theme from '
|
|
8
|
+
import type * as Theme from './Theme.js'
|
|
9
|
+
import type * as ValueSyntax from './Value.js'
|
|
10
|
+
import type * as VariableSets from '../Vars.js'
|
|
9
11
|
import * as Literal from './Literal.js'
|
|
12
|
+
import * as VariableData from './VariableSets.js'
|
|
10
13
|
|
|
11
14
|
/** Checks a reference's property domain. */
|
|
12
15
|
export function accepts(
|
|
13
16
|
group: Group,
|
|
14
17
|
property: keyof Literal.Properties,
|
|
15
18
|
): boolean {
|
|
19
|
+
if (property.startsWith('--')) return true
|
|
20
|
+
if (group === 'number' || group === 'string') return false
|
|
16
21
|
if (group === 'color') return Literal.rule(property)?.kind === 'color'
|
|
17
22
|
if (group === 'borderColor') return /^border.*Color$/.test(property)
|
|
23
|
+
if (group === 'borderWidth')
|
|
24
|
+
return /^border(?:Block|Inline)?(?:Start|End|Top|Right|Bottom|Left)?Width$/.test(
|
|
25
|
+
property,
|
|
26
|
+
)
|
|
18
27
|
if (group === 'borderRadius') return /^border.*Radius$/.test(property)
|
|
19
28
|
if (group === 'textColor') return property === 'color'
|
|
20
29
|
|
|
@@ -57,6 +66,50 @@ export function accepts(
|
|
|
57
66
|
return group === property
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
/** Checks explicit variable values independently of shorthand category mappings. */
|
|
70
|
+
export function acceptsReference(
|
|
71
|
+
reference: Reference,
|
|
72
|
+
property: keyof Literal.Properties,
|
|
73
|
+
): boolean {
|
|
74
|
+
if (!reference.contract.variableSet) return accepts(reference.group, property)
|
|
75
|
+
if (property.startsWith('--')) return true
|
|
76
|
+
function check(value: Value): boolean {
|
|
77
|
+
if (is(value)) return acceptsReference(value, property)
|
|
78
|
+
if (typeof value === 'object') return Object.values(value).every(check)
|
|
79
|
+
if (typeof value === 'number') {
|
|
80
|
+
const rule = Literal.rule(property)
|
|
81
|
+
if (rule?.kind === 'number')
|
|
82
|
+
return (
|
|
83
|
+
value >= rule.min &&
|
|
84
|
+
value <= rule.max &&
|
|
85
|
+
(!rule.integer || Number.isInteger(value))
|
|
86
|
+
)
|
|
87
|
+
return value === 0 && Binding.accepts('length', property)
|
|
88
|
+
}
|
|
89
|
+
if (reference.group === 'color') return Binding.accepts('color', property)
|
|
90
|
+
if (reference.group === 'spacing')
|
|
91
|
+
return (
|
|
92
|
+
(Literal.rule(property)?.kind === 'compound' &&
|
|
93
|
+
accepts('spacing', property)) ||
|
|
94
|
+
Binding.accepts(
|
|
95
|
+
value.endsWith('%')
|
|
96
|
+
? value.startsWith('-')
|
|
97
|
+
? 'signedPercentage'
|
|
98
|
+
: 'percentage'
|
|
99
|
+
: value.startsWith('-')
|
|
100
|
+
? 'signedLength'
|
|
101
|
+
: 'length',
|
|
102
|
+
property,
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
return (
|
|
106
|
+
Literal.isLiteral(property, value) ||
|
|
107
|
+
Literal.rule(property)?.kind === 'compound'
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
return check(reference.value)
|
|
111
|
+
}
|
|
112
|
+
|
|
60
113
|
/** Rebinds validated scalar references to a explicitly owned contract identity. */
|
|
61
114
|
export function bind<tokens extends Theme.Tokens>(
|
|
62
115
|
original: Theme.Definition<tokens>,
|
|
@@ -64,6 +117,9 @@ export function bind<tokens extends Theme.Tokens>(
|
|
|
64
117
|
): Theme.Definition<tokens> {
|
|
65
118
|
type Tree = { [key: string]: Reference | Tree }
|
|
66
119
|
|
|
120
|
+
const metadata = original[definition]
|
|
121
|
+
const values = VariableData.rebind(metadata, contract)
|
|
122
|
+
|
|
67
123
|
function rebind(tree: Theme.References<Theme.Tokens>): Tree {
|
|
68
124
|
return Object.freeze(
|
|
69
125
|
Object.fromEntries(
|
|
@@ -74,7 +130,7 @@ export function bind<tokens extends Theme.Tokens>(
|
|
|
74
130
|
contract,
|
|
75
131
|
group: value.group,
|
|
76
132
|
path: value.path,
|
|
77
|
-
value: value.
|
|
133
|
+
value: values[value.path]!,
|
|
78
134
|
})
|
|
79
135
|
: rebind(value as Theme.References<Theme.Tokens>),
|
|
80
136
|
]),
|
|
@@ -96,7 +152,7 @@ export function bind<tokens extends Theme.Tokens>(
|
|
|
96
152
|
vars: variables(tokens),
|
|
97
153
|
},
|
|
98
154
|
definition,
|
|
99
|
-
{ value: Object.freeze({ ...
|
|
155
|
+
{ value: Object.freeze({ ...metadata, contract, values }) },
|
|
100
156
|
),
|
|
101
157
|
) as Theme.Definition<tokens>
|
|
102
158
|
}
|
|
@@ -106,8 +162,14 @@ export const complete = Symbol('zyzz.contract.complete')
|
|
|
106
162
|
|
|
107
163
|
/** Opaque data shared by a definition and its compatible extensions. */
|
|
108
164
|
export type Contract = {
|
|
165
|
+
/** Whether values belong to independent variables rather than fixed theme categories. */
|
|
166
|
+
readonly variableSet?: boolean | undefined
|
|
167
|
+
/** Configuration-local category-to-property mappings. */
|
|
168
|
+
readonly mappings?: VariableSets.Mappings | false | undefined
|
|
109
169
|
/** Web emission mode retained by configuration-bound theme handles. */
|
|
110
170
|
readonly cssOutput?: 'atomic' | 'grouped' | undefined
|
|
171
|
+
/** Fallback layer for declarations without an explicit layer. */
|
|
172
|
+
readonly defaultLayer?: string | undefined
|
|
111
173
|
/** Configuration-local property aliases, inherited by bound handles. */
|
|
112
174
|
readonly shorthands?: Shorthands.Map | undefined
|
|
113
175
|
readonly [complete]?: boolean | undefined
|
|
@@ -153,23 +215,24 @@ export function compose(
|
|
|
153
215
|
export const web = Symbol('zyzz.web.variable')
|
|
154
216
|
|
|
155
217
|
/** Web reference with the original token domain. */
|
|
156
|
-
export type Variable<group extends Group = Group> =
|
|
157
|
-
|
|
158
|
-
|
|
218
|
+
export type Variable<group extends Group = Group> = `var(--${string})` &
|
|
219
|
+
Reference<group> & {
|
|
220
|
+
readonly [web]: true
|
|
221
|
+
}
|
|
159
222
|
|
|
160
223
|
/** Replaces portable scalar leaves with web-only references. */
|
|
161
|
-
export type
|
|
224
|
+
export type Vars<tree> =
|
|
162
225
|
tree extends Reference<infer group>
|
|
163
226
|
? Variable<group>
|
|
164
|
-
: { readonly [key in keyof tree]:
|
|
227
|
+
: { readonly [key in keyof tree]: Vars<tree[key]> }
|
|
165
228
|
|
|
166
229
|
/** Creates web-only reference leaves without changing contract identities. */
|
|
167
|
-
export function variables<tree>(tree: tree):
|
|
230
|
+
export function variables<tree>(tree: tree): Vars<tree> {
|
|
168
231
|
if (is(tree))
|
|
169
232
|
return Object.freeze({
|
|
170
233
|
...tree,
|
|
171
234
|
[web]: true as const,
|
|
172
|
-
}) as unknown as
|
|
235
|
+
}) as unknown as Vars<tree>
|
|
173
236
|
|
|
174
237
|
return Object.freeze(
|
|
175
238
|
Object.fromEntries(
|
|
@@ -178,7 +241,7 @@ export function variables<tree>(tree: tree): Variables<tree> {
|
|
|
178
241
|
variables(value),
|
|
179
242
|
]),
|
|
180
243
|
),
|
|
181
|
-
) as
|
|
244
|
+
) as Vars<tree>
|
|
182
245
|
}
|
|
183
246
|
|
|
184
247
|
/** Internal definition metadata; never enumerable consumer output. */
|
|
@@ -186,9 +249,12 @@ export const definition = Symbol('zyzz.theme')
|
|
|
186
249
|
|
|
187
250
|
/** Supported scalar token groups. */
|
|
188
251
|
export type Group =
|
|
252
|
+
| 'number'
|
|
253
|
+
| 'string'
|
|
189
254
|
| 'backgroundColor'
|
|
190
255
|
| 'borderColor'
|
|
191
256
|
| 'borderRadius'
|
|
257
|
+
| 'borderWidth'
|
|
192
258
|
| 'color'
|
|
193
259
|
| 'margin'
|
|
194
260
|
| 'padding'
|
|
@@ -223,19 +289,53 @@ export function is(value: unknown): value is Reference {
|
|
|
223
289
|
|
|
224
290
|
/** Immutable theme data carried directly by each definition. */
|
|
225
291
|
export type Metadata = {
|
|
292
|
+
/** Original segments for typography paths containing query punctuation. */
|
|
293
|
+
readonly paths?: Readonly<Record<string, readonly string[]>> | undefined
|
|
226
294
|
readonly queries?: Query.Metadata | undefined
|
|
227
295
|
readonly contract: Contract
|
|
228
296
|
readonly values: Readonly<Record<string, Value>>
|
|
229
297
|
}
|
|
230
298
|
|
|
231
|
-
/**
|
|
232
|
-
export
|
|
233
|
-
[group in Extract<keyof tokens, Group>]: property extends Properties<group>
|
|
234
|
-
? Paths<NonNullable<tokens[group]>>
|
|
235
|
-
: never
|
|
236
|
-
}[Extract<keyof tokens, Group>]
|
|
299
|
+
/** Literal domain carried by explicit variable references during type checking. */
|
|
300
|
+
export const scalar = Symbol('zyzz.variable.scalar')
|
|
237
301
|
|
|
238
|
-
|
|
302
|
+
/** Inferred shorthand names whose leaves belong to a property domain. */
|
|
303
|
+
export type Names<
|
|
304
|
+
tokens,
|
|
305
|
+
property extends keyof Literal.Properties,
|
|
306
|
+
> = tokens extends {
|
|
307
|
+
readonly '~vars': { values: infer values; mappings: infer mappings }
|
|
308
|
+
}
|
|
309
|
+
? mappings extends false
|
|
310
|
+
? Paths<
|
|
311
|
+
Omit<values, 'breakpoints' | 'containers' | 'containerNames'>,
|
|
312
|
+
property
|
|
313
|
+
>
|
|
314
|
+
: {
|
|
315
|
+
[category in keyof values]: category extends keyof mappings
|
|
316
|
+
? mappings[category] extends readonly unknown[]
|
|
317
|
+
? property extends mappings[category][number]
|
|
318
|
+
? Paths<values[category], property>
|
|
319
|
+
: never
|
|
320
|
+
: never
|
|
321
|
+
: category extends Group
|
|
322
|
+
? property extends Properties<category>
|
|
323
|
+
? Paths<values[category], property>
|
|
324
|
+
: never
|
|
325
|
+
: never
|
|
326
|
+
}[keyof values]
|
|
327
|
+
: {
|
|
328
|
+
[group in Extract<
|
|
329
|
+
keyof tokens,
|
|
330
|
+
Group
|
|
331
|
+
>]: property extends Properties<group>
|
|
332
|
+
? Paths<NonNullable<tokens[group]>>
|
|
333
|
+
: never
|
|
334
|
+
}[Extract<keyof tokens, Group>]
|
|
335
|
+
|
|
336
|
+
type Paths<tree, property extends keyof Literal.Properties = never> = [
|
|
337
|
+
tree,
|
|
338
|
+
] extends [never]
|
|
239
339
|
? never
|
|
240
340
|
: string extends keyof tree
|
|
241
341
|
? string
|
|
@@ -243,72 +343,95 @@ type Paths<tree> = [tree] extends [never]
|
|
|
243
343
|
[key in Extract<keyof tree, number | string>]: NonNullable<
|
|
244
344
|
tree[key]
|
|
245
345
|
> extends Value
|
|
246
|
-
?
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
346
|
+
? [property] extends [never]
|
|
347
|
+
? PathKey<key>
|
|
348
|
+
: VariableSets.Scalar<
|
|
349
|
+
NonNullable<tree[key]>
|
|
350
|
+
> extends Literal.Properties[property] &
|
|
351
|
+
ValueSyntax.Checked<
|
|
352
|
+
Record<
|
|
353
|
+
property,
|
|
354
|
+
VariableSets.Scalar<NonNullable<tree[key]>>
|
|
355
|
+
>
|
|
356
|
+
>[property]
|
|
357
|
+
? PathKey<key>
|
|
358
|
+
: never
|
|
359
|
+
: `${key}.${Paths<NonNullable<tree[key]>, property>}`
|
|
255
360
|
}[Extract<keyof tree, number | string>]
|
|
256
361
|
|
|
362
|
+
type PathKey<key extends number | string> =
|
|
363
|
+
| key
|
|
364
|
+
| `${key}`
|
|
365
|
+
| (key extends `${infer numericKey extends number}`
|
|
366
|
+
? `${numericKey}` extends key
|
|
367
|
+
? numericKey
|
|
368
|
+
: never
|
|
369
|
+
: never)
|
|
370
|
+
|
|
257
371
|
/** Property domains accepted by each token group. */
|
|
258
|
-
export type Properties<group extends Group> =
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
| `blockSize`
|
|
267
|
-
| `bottom`
|
|
268
|
-
| `columnGap`
|
|
269
|
-
| `flexBasis`
|
|
270
|
-
| `gap`
|
|
271
|
-
| `height`
|
|
272
|
-
| `inlineSize`
|
|
273
|
-
| `inset${string}`
|
|
274
|
-
| `left`
|
|
275
|
-
| Exclude<
|
|
276
|
-
Extract<keyof Literal.Properties, `margin${string}`>,
|
|
277
|
-
'marginTrim'
|
|
278
|
-
>
|
|
279
|
-
| `maxBlockSize`
|
|
280
|
-
| `maxHeight`
|
|
281
|
-
| `maxInlineSize`
|
|
282
|
-
| `maxWidth`
|
|
283
|
-
| `minBlockSize`
|
|
284
|
-
| `minHeight`
|
|
285
|
-
| `minInlineSize`
|
|
286
|
-
| `minWidth`
|
|
287
|
-
| `padding${string}`
|
|
288
|
-
| `right`
|
|
289
|
-
| `rowGap`
|
|
290
|
-
| `scrollPadding${string}`
|
|
291
|
-
| `textDecorationThickness`
|
|
292
|
-
| `textIndent`
|
|
293
|
-
| `textUnderlineOffset`
|
|
294
|
-
| `top`
|
|
295
|
-
| `width`
|
|
372
|
+
export type Properties<group extends Group> = `--${string}` | Property<group>
|
|
373
|
+
|
|
374
|
+
type Property<group extends Group> = group extends 'number' | 'string'
|
|
375
|
+
? never
|
|
376
|
+
: group extends 'margin' | 'padding'
|
|
377
|
+
? Exclude<
|
|
378
|
+
Extract<keyof Literal.Properties, `${group}${string}`>,
|
|
379
|
+
'marginTrim'
|
|
296
380
|
>
|
|
297
|
-
: group extends '
|
|
298
|
-
?
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
381
|
+
: group extends 'spacing'
|
|
382
|
+
? Extract<
|
|
383
|
+
keyof Literal.Properties,
|
|
384
|
+
| `blockSize`
|
|
385
|
+
| `bottom`
|
|
386
|
+
| `columnGap`
|
|
387
|
+
| `flexBasis`
|
|
388
|
+
| `gap`
|
|
389
|
+
| `height`
|
|
390
|
+
| `inlineSize`
|
|
391
|
+
| `inset${string}`
|
|
392
|
+
| `left`
|
|
393
|
+
| Exclude<
|
|
394
|
+
Extract<keyof Literal.Properties, `margin${string}`>,
|
|
395
|
+
'marginTrim'
|
|
396
|
+
>
|
|
397
|
+
| `maxBlockSize`
|
|
398
|
+
| `maxHeight`
|
|
399
|
+
| `maxInlineSize`
|
|
400
|
+
| `maxWidth`
|
|
401
|
+
| `minBlockSize`
|
|
402
|
+
| `minHeight`
|
|
403
|
+
| `minInlineSize`
|
|
404
|
+
| `minWidth`
|
|
405
|
+
| `padding${string}`
|
|
406
|
+
| `right`
|
|
407
|
+
| `rowGap`
|
|
408
|
+
| `scrollPadding${string}`
|
|
409
|
+
| `textDecorationThickness`
|
|
410
|
+
| `textIndent`
|
|
411
|
+
| `textUnderlineOffset`
|
|
412
|
+
| `top`
|
|
413
|
+
| `width`
|
|
414
|
+
>
|
|
415
|
+
: group extends 'textColor'
|
|
416
|
+
? 'color'
|
|
417
|
+
: group extends 'color'
|
|
418
|
+
? {
|
|
419
|
+
[property in keyof typeof Literal.rules]: (typeof Literal.rules)[property] extends {
|
|
420
|
+
kind: 'color'
|
|
421
|
+
}
|
|
422
|
+
? property
|
|
423
|
+
: never
|
|
424
|
+
}[keyof typeof Literal.rules]
|
|
425
|
+
: group extends 'borderColor'
|
|
426
|
+
? Extract<keyof Literal.Properties, `border${string}Color`>
|
|
427
|
+
: group extends 'borderWidth'
|
|
428
|
+
? Exclude<
|
|
429
|
+
Extract<keyof Literal.Properties, `border${string}Width`>,
|
|
430
|
+
'borderImageWidth'
|
|
431
|
+
>
|
|
432
|
+
: group extends 'borderRadius'
|
|
433
|
+
? Extract<keyof Literal.Properties, `border${string}Radius`>
|
|
434
|
+
: group
|
|
312
435
|
|
|
313
436
|
/** Immutable portable reference retaining its defining fallback. */
|
|
314
437
|
export type Reference<group extends Group = Group> = {
|
|
@@ -333,11 +456,11 @@ export function resolve(value: unknown, options: resolve.Options): unknown {
|
|
|
333
456
|
?.value as Metadata | undefined
|
|
334
457
|
if (!data) throw new Error('Expected a theme definition.')
|
|
335
458
|
|
|
336
|
-
|
|
337
|
-
for (const group of [
|
|
459
|
+
const groups = [
|
|
338
460
|
'backgroundColor',
|
|
339
461
|
'borderColor',
|
|
340
462
|
'borderRadius',
|
|
463
|
+
'borderWidth',
|
|
341
464
|
'margin',
|
|
342
465
|
'padding',
|
|
343
466
|
'spacing',
|
|
@@ -348,7 +471,49 @@ export function resolve(value: unknown, options: resolve.Options): unknown {
|
|
|
348
471
|
'lineHeight',
|
|
349
472
|
'textColor',
|
|
350
473
|
'color',
|
|
351
|
-
] as const
|
|
474
|
+
] as const
|
|
475
|
+
|
|
476
|
+
if (data.contract.variableSet) {
|
|
477
|
+
for (const [path, entry] of Object.entries(data.values).sort(
|
|
478
|
+
([left], [right]) =>
|
|
479
|
+
groups.indexOf(left.split('.')[0] as (typeof groups)[number]) -
|
|
480
|
+
groups.indexOf(right.split('.')[0] as (typeof groups)[number]),
|
|
481
|
+
)) {
|
|
482
|
+
const [category, ...parts] = path.split('.')
|
|
483
|
+
const mappings = data.contract.mappings
|
|
484
|
+
const mapped = mappings === false ? undefined : mappings?.[category!]
|
|
485
|
+
if (
|
|
486
|
+
mappings === false
|
|
487
|
+
? path !== String(value)
|
|
488
|
+
: parts.join('.') !== String(value) ||
|
|
489
|
+
!(mapped
|
|
490
|
+
? mapped.includes(options.property)
|
|
491
|
+
: accepts(category as Group, options.property))
|
|
492
|
+
)
|
|
493
|
+
continue
|
|
494
|
+
return create({
|
|
495
|
+
contract: data.contract,
|
|
496
|
+
group: (() => {
|
|
497
|
+
let leaf: unknown = Object.getOwnPropertyDescriptor(
|
|
498
|
+
options.theme,
|
|
499
|
+
'tokens',
|
|
500
|
+
)?.value
|
|
501
|
+
for (const key of path.split('.'))
|
|
502
|
+
leaf =
|
|
503
|
+
leaf && typeof leaf === 'object'
|
|
504
|
+
? Object.getOwnPropertyDescriptor(leaf, key)?.value
|
|
505
|
+
: undefined
|
|
506
|
+
return is(leaf) ? leaf.group : (category as Group)
|
|
507
|
+
})(),
|
|
508
|
+
path,
|
|
509
|
+
value: entry,
|
|
510
|
+
})
|
|
511
|
+
}
|
|
512
|
+
return value
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Specific groups precede shared colors regardless of authored group order.
|
|
516
|
+
for (const group of groups) {
|
|
352
517
|
if (!accepts(group, options.property)) continue
|
|
353
518
|
|
|
354
519
|
const path = `${group}.${value}`
|
|
@@ -377,4 +542,12 @@ export declare namespace resolve {
|
|
|
377
542
|
export type Value =
|
|
378
543
|
| number
|
|
379
544
|
| string
|
|
380
|
-
|
|
|
545
|
+
| Reference
|
|
546
|
+
| { readonly dark: Value; readonly light: Value }
|
|
547
|
+
| Conditions
|
|
548
|
+
|
|
549
|
+
/** Ordered conditional values with an unconditional fallback. */
|
|
550
|
+
export type Conditions = {
|
|
551
|
+
readonly default: Value
|
|
552
|
+
readonly [query: `@media ${string}`]: Value
|
|
553
|
+
}
|