zyzz 0.0.19 → 0.0.20
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 +9 -9
- package/dist/Config.d.ts +1 -0
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js.map +1 -1
- package/dist/Vars.d.ts +22 -15
- package/dist/Vars.d.ts.map +1 -1
- package/dist/Vars.js +26 -0
- package/dist/Vars.js.map +1 -1
- package/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/compiler/Source.d.ts.map +1 -1
- package/dist/compiler/Source.js +3 -0
- package/dist/compiler/Source.js.map +1 -1
- package/dist/compiler/internal/Configurations.d.ts.map +1 -1
- package/dist/compiler/internal/Configurations.js +3 -0
- package/dist/compiler/internal/Configurations.js.map +1 -1
- package/dist/compiler/internal/Contract.d.ts.map +1 -1
- package/dist/compiler/internal/Contract.js +30 -4
- package/dist/compiler/internal/Contract.js.map +1 -1
- package/dist/compiler/internal/Themes.d.ts.map +1 -1
- package/dist/compiler/internal/Themes.js +83 -23
- package/dist/compiler/internal/Themes.js.map +1 -1
- package/dist/default.d.ts +7 -11
- package/dist/default.d.ts.map +1 -1
- package/dist/default.js +4 -5
- package/dist/default.js.map +2 -2
- package/dist/default.js.zyzz.json +1 -1
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/Token.d.ts +11 -2
- package/dist/internal/Token.d.ts.map +1 -1
- package/dist/internal/Token.js +2 -0
- package/dist/internal/Token.js.map +1 -1
- package/dist/internal/VariableSets.d.ts.map +1 -1
- package/dist/internal/VariableSets.js +18 -1
- package/dist/internal/VariableSets.js.map +1 -1
- package/dist/node/Host.d.ts +2 -0
- package/dist/node/Host.d.ts.map +1 -1
- package/dist/node/Host.js +7 -0
- package/dist/node/Host.js.map +1 -1
- package/dist/react-native/StyleSheet.js +2 -0
- package/dist/react-native/StyleSheet.js.map +1 -1
- package/dist/runtime/Composition.d.ts +1 -1
- package/dist/runtime/ConditionalRecipe.d.ts +1 -1
- package/dist/runtime/PayloadRecipe.d.ts +1 -1
- package/dist/runtime/Recipe.d.ts +1 -1
- package/dist/styleFunction.d.ts +1 -1
- package/dist/styleFunction.d.ts.map +1 -1
- package/dist/styleFunction.js.map +1 -1
- package/dist/variants.d.ts +14 -6
- package/dist/variants.d.ts.map +1 -1
- package/dist/variants.js.map +1 -1
- package/dist/vite/index.d.ts +2 -0
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +75 -30
- package/dist/vite/index.js.map +1 -1
- package/dist/web/internal/Themes.d.ts.map +1 -1
- package/dist/web/internal/Themes.js +4 -0
- package/dist/web/internal/Themes.js.map +1 -1
- package/package.json +1 -1
- package/src/Config.ts +5 -0
- package/src/Vars.ts +88 -29
- package/src/cli/index.ts +5 -0
- package/src/compiler/Source.ts +3 -0
- package/src/compiler/internal/Configurations.ts +3 -0
- package/src/compiler/internal/Contract.ts +47 -4
- package/src/compiler/internal/Themes.ts +109 -34
- package/src/default.ts +8 -10
- package/src/index.ts +15 -0
- package/src/internal/Authoring.ts +1 -1
- package/src/internal/Token.ts +39 -11
- package/src/internal/VariableSets.ts +25 -1
- package/src/node/Host.ts +19 -0
- package/src/react-native/StyleSheet.ts +6 -0
- package/src/styleFunction.ts +1 -3
- package/src/variants.ts +38 -16
- package/src/vite/index.ts +94 -33
- package/src/web/internal/Themes.ts +4 -0
|
@@ -26,7 +26,7 @@ export function read(
|
|
|
26
26
|
if (
|
|
27
27
|
![
|
|
28
28
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
|
29
|
-
22, 23, 24, 25, 26, 27, 28,
|
|
29
|
+
22, 23, 24, 25, 26, 27, 28, 29,
|
|
30
30
|
].includes(data.version as number)
|
|
31
31
|
)
|
|
32
32
|
throw new Error('Unsupported Zyzz contract version.')
|
|
@@ -69,6 +69,26 @@ export function read(
|
|
|
69
69
|
decode(value),
|
|
70
70
|
]),
|
|
71
71
|
)
|
|
72
|
+
if (Object.hasOwn(fields, '$composition')) {
|
|
73
|
+
if ((data.version as number) < 29)
|
|
74
|
+
throw new Error(
|
|
75
|
+
'Composed variables require contract version 29 or later.',
|
|
76
|
+
)
|
|
77
|
+
const composition = record(fields.$composition)
|
|
78
|
+
if (
|
|
79
|
+
(composition.group !== 'color' && composition.group !== 'spacing') ||
|
|
80
|
+
!Array.isArray(composition.parts)
|
|
81
|
+
)
|
|
82
|
+
throw new Error('Invalid packed variable composition.')
|
|
83
|
+
return Vars.compose(
|
|
84
|
+
composition.group,
|
|
85
|
+
composition.parts.map(decode) as readonly (
|
|
86
|
+
| string
|
|
87
|
+
| number
|
|
88
|
+
| Vars.Reference
|
|
89
|
+
)[],
|
|
90
|
+
)
|
|
91
|
+
}
|
|
72
92
|
if (Object.hasOwn(fields, '$variable')) {
|
|
73
93
|
const reference = record(fields.$variable)
|
|
74
94
|
const identity = string(reference.identity)
|
|
@@ -294,7 +314,7 @@ export function read(
|
|
|
294
314
|
if (
|
|
295
315
|
![
|
|
296
316
|
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
|
|
297
|
-
27, 28,
|
|
317
|
+
27, 28, 29,
|
|
298
318
|
].includes(data.version as number) ||
|
|
299
319
|
![
|
|
300
320
|
'cssFunction',
|
|
@@ -590,7 +610,8 @@ function tokens(tree: Theme.References<Theme.Tokens>): Record<string, unknown> {
|
|
|
590
610
|
}
|
|
591
611
|
|
|
592
612
|
function type(value: unknown): string {
|
|
593
|
-
if (Token.is(value)
|
|
613
|
+
if (Token.is(value) || Token.isExpression(value))
|
|
614
|
+
return Configurations.type(value)
|
|
594
615
|
if (Array.isArray(value)) return `readonly [${value.map(type).join(',')}]`
|
|
595
616
|
if (!value || typeof value !== 'object') return JSON.stringify(value)
|
|
596
617
|
|
|
@@ -727,6 +748,22 @@ export function write(
|
|
|
727
748
|
]),
|
|
728
749
|
),
|
|
729
750
|
version: (() => {
|
|
751
|
+
function composed(value: unknown): boolean {
|
|
752
|
+
if (Token.isExpression(value)) return true
|
|
753
|
+
if (Token.is(value)) return composed(value.value)
|
|
754
|
+
return (
|
|
755
|
+
!!value &&
|
|
756
|
+
typeof value === 'object' &&
|
|
757
|
+
Object.values(value).some(composed)
|
|
758
|
+
)
|
|
759
|
+
}
|
|
760
|
+
if (
|
|
761
|
+
Object.values(themes).some((theme) =>
|
|
762
|
+
composed(theme[Token.definition].values),
|
|
763
|
+
)
|
|
764
|
+
)
|
|
765
|
+
return 29
|
|
766
|
+
|
|
730
767
|
if (
|
|
731
768
|
Object.values(themes).some(
|
|
732
769
|
(theme) =>
|
|
@@ -1031,6 +1068,10 @@ function extended(signature: NonNullable<Themes.Call['function']>): boolean {
|
|
|
1031
1068
|
}
|
|
1032
1069
|
|
|
1033
1070
|
function encode(value: unknown): unknown {
|
|
1071
|
+
if (Token.isExpression(value) && 'group' in value)
|
|
1072
|
+
return {
|
|
1073
|
+
$composition: { group: value.group, parts: value.parts.map(encode) },
|
|
1074
|
+
}
|
|
1034
1075
|
if (Token.is(value))
|
|
1035
1076
|
return {
|
|
1036
1077
|
$variable: {
|
|
@@ -1044,7 +1085,9 @@ function encode(value: unknown): unknown {
|
|
|
1044
1085
|
const fields = Object.fromEntries(
|
|
1045
1086
|
Object.entries(value).map(([key, value]) => [key, encode(value)]),
|
|
1046
1087
|
)
|
|
1047
|
-
return Object.hasOwn(fields, '$
|
|
1088
|
+
return Object.hasOwn(fields, '$composition') ||
|
|
1089
|
+
Object.hasOwn(fields, '$variable') ||
|
|
1090
|
+
Object.hasOwn(fields, '$object')
|
|
1048
1091
|
? { $object: fields }
|
|
1049
1092
|
: fields
|
|
1050
1093
|
}
|
|
@@ -144,6 +144,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
144
144
|
const imports = new Set<number>()
|
|
145
145
|
const variableImports = new Set<number>()
|
|
146
146
|
const configImports = new Set<number>()
|
|
147
|
+
const factoryImports = new Map<number, 'create' | 'define' | 'extend'>()
|
|
147
148
|
const configs = new Map<string, Link>()
|
|
148
149
|
const configBindings = new Map<number, Link>()
|
|
149
150
|
const factoryReferences = new Set<number>()
|
|
@@ -188,11 +189,31 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
188
189
|
: specifier.imported.value) === 'Config'
|
|
189
190
|
)
|
|
190
191
|
configImports.add(specifier.start)
|
|
192
|
+
else if (
|
|
193
|
+
specifier.type === 'ImportSpecifier' &&
|
|
194
|
+
specifier.importKind !== 'type' &&
|
|
195
|
+
['defineConfig', 'defineVars', 'extendVars'].includes(
|
|
196
|
+
specifier.imported.type === 'Identifier'
|
|
197
|
+
? specifier.imported.name
|
|
198
|
+
: specifier.imported.value,
|
|
199
|
+
)
|
|
200
|
+
) {
|
|
201
|
+
const name =
|
|
202
|
+
specifier.imported.type === 'Identifier'
|
|
203
|
+
? specifier.imported.name
|
|
204
|
+
: specifier.imported.value
|
|
205
|
+
if (name === 'defineConfig')
|
|
206
|
+
factoryImports.set(specifier.start, 'create')
|
|
207
|
+
else if (name === 'defineVars')
|
|
208
|
+
factoryImports.set(specifier.start, 'define')
|
|
209
|
+
else factoryImports.set(specifier.start, 'extend')
|
|
210
|
+
}
|
|
191
211
|
}
|
|
192
212
|
|
|
193
213
|
if (
|
|
194
214
|
!imports.size &&
|
|
195
215
|
!configImports.size &&
|
|
216
|
+
!factoryImports.size &&
|
|
196
217
|
!Object.keys(options.links ?? {}).length
|
|
197
218
|
)
|
|
198
219
|
return undefined
|
|
@@ -251,6 +272,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
251
272
|
|
|
252
273
|
const namespaces = new Set<string>()
|
|
253
274
|
const configNamespaces = new Set<string>()
|
|
275
|
+
const factoryFunctions = new Map<string, 'create' | 'define' | 'extend'>()
|
|
254
276
|
const variableNamespaces = new Set<string>()
|
|
255
277
|
for (const node of program.body)
|
|
256
278
|
if (node.type === 'ImportDeclaration')
|
|
@@ -264,6 +286,11 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
264
286
|
if (imports.has(specifier.start)) namespaces.add(specifier.local.name)
|
|
265
287
|
else if (configImports.has(specifier.start))
|
|
266
288
|
configNamespaces.add(specifier.local.name)
|
|
289
|
+
else if (factoryImports.has(specifier.start))
|
|
290
|
+
factoryFunctions.set(
|
|
291
|
+
specifier.local.name,
|
|
292
|
+
factoryImports.get(specifier.start)!,
|
|
293
|
+
)
|
|
267
294
|
|
|
268
295
|
function resolve(node: Ast.Node): Link | undefined {
|
|
269
296
|
if (node.type === 'Identifier') {
|
|
@@ -426,6 +453,35 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
426
453
|
if (node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression')
|
|
427
454
|
return data(node.expression, derived)
|
|
428
455
|
|
|
456
|
+
if (node.type === 'CallExpression' && !node.optional) {
|
|
457
|
+
const callee = node.callee
|
|
458
|
+
if (
|
|
459
|
+
callee.type === 'MemberExpression' &&
|
|
460
|
+
!callee.computed &&
|
|
461
|
+
!callee.optional &&
|
|
462
|
+
callee.object.type === 'Identifier' &&
|
|
463
|
+
variableNamespaces.has(callee.object.name) &&
|
|
464
|
+
derived?.name !== callee.object.name &&
|
|
465
|
+
callee.property.type === 'Identifier' &&
|
|
466
|
+
callee.property.name === 'compose'
|
|
467
|
+
) {
|
|
468
|
+
if (node.arguments.length !== 2)
|
|
469
|
+
return fail(
|
|
470
|
+
'Vars.compose requires a literal domain and parts array.',
|
|
471
|
+
node,
|
|
472
|
+
)
|
|
473
|
+
const group = data(node.arguments[0]!, derived)
|
|
474
|
+
const parts = data(node.arguments[1]!, derived)
|
|
475
|
+
if ((group !== 'color' && group !== 'spacing') || !Array.isArray(parts))
|
|
476
|
+
return fail(
|
|
477
|
+
'Vars.compose requires a literal domain and parts array.',
|
|
478
|
+
node,
|
|
479
|
+
)
|
|
480
|
+
factoryReferences.add(callee.start)
|
|
481
|
+
return Vars.compose(group, parts)
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
429
485
|
if (
|
|
430
486
|
node.type === 'Literal' &&
|
|
431
487
|
(typeof node.value === 'string' || typeof node.value === 'number')
|
|
@@ -536,37 +592,52 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
536
592
|
registerAlias({ declaration, statement, variable })
|
|
537
593
|
|
|
538
594
|
const expression = variable.init
|
|
539
|
-
if (
|
|
540
|
-
expression?.type !== 'CallExpression' ||
|
|
541
|
-
expression.callee.type !== 'MemberExpression' ||
|
|
542
|
-
expression.callee.object.type !== 'Identifier' ||
|
|
543
|
-
(!namespaces.has(expression.callee.object.name) &&
|
|
544
|
-
!configNamespaces.has(expression.callee.object.name))
|
|
545
|
-
)
|
|
546
|
-
continue
|
|
595
|
+
if (expression?.type !== 'CallExpression' || expression.optional) continue
|
|
547
596
|
|
|
548
597
|
const member = expression.callee
|
|
598
|
+
const directFactory =
|
|
599
|
+
member.type === 'Identifier'
|
|
600
|
+
? factoryFunctions.get(member.name)
|
|
601
|
+
: undefined
|
|
549
602
|
if (
|
|
550
|
-
|
|
551
|
-
member.
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
603
|
+
!directFactory &&
|
|
604
|
+
(member.type !== 'MemberExpression' ||
|
|
605
|
+
member.object.type !== 'Identifier' ||
|
|
606
|
+
(!namespaces.has(member.object.name) &&
|
|
607
|
+
!configNamespaces.has(member.object.name)) ||
|
|
608
|
+
member.computed ||
|
|
609
|
+
member.optional ||
|
|
610
|
+
member.property.type !== 'Identifier' ||
|
|
611
|
+
!(
|
|
612
|
+
configNamespaces.has(member.object.name)
|
|
613
|
+
? ['create']
|
|
614
|
+
: ['define', 'extend']
|
|
615
|
+
).includes(member.property.name))
|
|
559
616
|
)
|
|
560
617
|
continue
|
|
561
618
|
|
|
619
|
+
const config =
|
|
620
|
+
directFactory === 'create' ||
|
|
621
|
+
(member.type === 'MemberExpression' &&
|
|
622
|
+
member.object.type === 'Identifier' &&
|
|
623
|
+
configNamespaces.has(member.object.name))
|
|
624
|
+
const method =
|
|
625
|
+
member.type === 'MemberExpression' &&
|
|
626
|
+
member.property.type === 'Identifier'
|
|
627
|
+
? member.property.name
|
|
628
|
+
: directFactory
|
|
629
|
+
const variableSet =
|
|
630
|
+
directFactory === 'define' ||
|
|
631
|
+
directFactory === 'extend' ||
|
|
632
|
+
(member.type === 'MemberExpression' &&
|
|
633
|
+
member.object.type === 'Identifier' &&
|
|
634
|
+
variableNamespaces.has(member.object.name))
|
|
635
|
+
|
|
562
636
|
if (
|
|
563
637
|
(statement.type === 'ExportNamedDeclaration' && !options.linked) ||
|
|
564
638
|
declaration.kind !== 'const' ||
|
|
565
639
|
(variable.id.type !== 'Identifier' &&
|
|
566
|
-
!(
|
|
567
|
-
configNamespaces.has(expression.callee.object.name) &&
|
|
568
|
-
variable.id.type === 'ObjectPattern'
|
|
569
|
-
))
|
|
640
|
+
!(config && variable.id.type === 'ObjectPattern'))
|
|
570
641
|
)
|
|
571
642
|
fail(
|
|
572
643
|
'Define local themes with a module-level const; exported themes require source linking.',
|
|
@@ -601,10 +672,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
601
672
|
fail('Configuration destructuring requires a binding.', variable)
|
|
602
673
|
|
|
603
674
|
let name = `${options.namespace}-${binding}`
|
|
604
|
-
if (
|
|
605
|
-
!configNamespaces.has(expression.callee.object.name) &&
|
|
606
|
-
member.property.name === 'define'
|
|
607
|
-
) {
|
|
675
|
+
if (!config && method === 'define') {
|
|
608
676
|
const argument = expression.arguments[1]
|
|
609
677
|
const callback = argument && Expression.unwrap(argument)
|
|
610
678
|
const id = Identifiers.explicit(
|
|
@@ -617,7 +685,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
617
685
|
if (id !== undefined) name = Identity.requireId(id, 'Vars.define')
|
|
618
686
|
}
|
|
619
687
|
|
|
620
|
-
if (
|
|
688
|
+
if (config) {
|
|
621
689
|
try {
|
|
622
690
|
const link = Configurations.collect({
|
|
623
691
|
data,
|
|
@@ -772,7 +840,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
772
840
|
let output: Call['output']
|
|
773
841
|
|
|
774
842
|
try {
|
|
775
|
-
if (
|
|
843
|
+
if (method === 'define') {
|
|
776
844
|
if (
|
|
777
845
|
expression.arguments.length < 1 ||
|
|
778
846
|
expression.arguments.length > 3
|
|
@@ -786,9 +854,6 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
786
854
|
|
|
787
855
|
tokenType = type(expression.arguments[0]!)
|
|
788
856
|
|
|
789
|
-
const variableSet = variableNamespaces.has(
|
|
790
|
-
expression.callee.object.name,
|
|
791
|
-
)
|
|
792
857
|
const argument = expression.arguments[1]
|
|
793
858
|
const callback = argument && Expression.unwrap(argument)
|
|
794
859
|
if (
|
|
@@ -860,7 +925,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
860
925
|
)
|
|
861
926
|
|
|
862
927
|
factoryReferences.add(base!.start)
|
|
863
|
-
definition =
|
|
928
|
+
definition = variableSet
|
|
864
929
|
? VariableSets.theme(
|
|
865
930
|
Vars.extend(
|
|
866
931
|
VariableSets.from(themes[parent.name]![Token.definition]),
|
|
@@ -892,7 +957,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
892
957
|
}
|
|
893
958
|
|
|
894
959
|
const call = Object.freeze({
|
|
895
|
-
...(
|
|
960
|
+
...(variableSet
|
|
896
961
|
? {
|
|
897
962
|
variableSet: true,
|
|
898
963
|
directVariables: true,
|
|
@@ -1286,12 +1351,22 @@ export function collect(program: Ast.Program, options: collect.Options) {
|
|
|
1286
1351
|
|
|
1287
1352
|
if (
|
|
1288
1353
|
binding?.type === 'Import' &&
|
|
1289
|
-
(imports.has(binding.node.start) ||
|
|
1354
|
+
(imports.has(binding.node.start) ||
|
|
1355
|
+
configImports.has(binding.node.start) ||
|
|
1356
|
+
factoryImports.has(binding.node.start))
|
|
1290
1357
|
) {
|
|
1358
|
+
if (
|
|
1359
|
+
factoryImports.has(binding.node.start) &&
|
|
1360
|
+
parent.type === 'CallExpression' &&
|
|
1361
|
+
factories.has(parent.start)
|
|
1362
|
+
)
|
|
1363
|
+
return true
|
|
1364
|
+
|
|
1291
1365
|
if (
|
|
1292
1366
|
parent.type === 'MemberExpression' &&
|
|
1293
1367
|
grandparent?.type === 'CallExpression' &&
|
|
1294
|
-
factories.has(grandparent.start)
|
|
1368
|
+
(factories.has(grandparent.start) ||
|
|
1369
|
+
factoryReferences.has(parent.start))
|
|
1295
1370
|
)
|
|
1296
1371
|
return true
|
|
1297
1372
|
|
package/src/default.ts
CHANGED
|
@@ -80,8 +80,8 @@ export const tokens = {
|
|
|
80
80
|
1000: { dark: '#fef3dc', light: '#4e2009' },
|
|
81
81
|
},
|
|
82
82
|
background: {
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
primary: { dark: '#000', light: '#fafafa' },
|
|
84
|
+
surface: { dark: '#0a0a0a', light: '#fff' },
|
|
85
85
|
},
|
|
86
86
|
black: '#000',
|
|
87
87
|
blue: {
|
|
@@ -169,7 +169,6 @@ export const tokens = {
|
|
|
169
169
|
900: { dark: '#ff6166', light: '#cb2a2f' },
|
|
170
170
|
1000: { dark: '#feecee', light: '#391417' },
|
|
171
171
|
},
|
|
172
|
-
surface: { dark: '#0a0a0a', light: '#fff' },
|
|
173
172
|
teal: {
|
|
174
173
|
100: { dark: '#04201b', light: '#eefcf9' },
|
|
175
174
|
200: { dark: '#062822', light: '#e5faf6' },
|
|
@@ -428,14 +427,14 @@ export const tokens = {
|
|
|
428
427
|
fontSize: '20px',
|
|
429
428
|
fontWeight: 400,
|
|
430
429
|
letterSpacing: '0px',
|
|
431
|
-
lineHeight: '
|
|
430
|
+
lineHeight: '28px',
|
|
432
431
|
strong: {
|
|
433
432
|
fontFamily:
|
|
434
433
|
'Geist, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
|
|
435
434
|
fontSize: '20px',
|
|
436
435
|
fontWeight: 550,
|
|
437
436
|
letterSpacing: '0px',
|
|
438
|
-
lineHeight: '
|
|
437
|
+
lineHeight: '28px',
|
|
439
438
|
},
|
|
440
439
|
},
|
|
441
440
|
'24': {
|
|
@@ -722,8 +721,8 @@ const config = Config.create({
|
|
|
722
721
|
1000: { dark: '#fef3dc', light: '#4e2009' },
|
|
723
722
|
},
|
|
724
723
|
background: {
|
|
725
|
-
|
|
726
|
-
|
|
724
|
+
primary: { dark: '#000', light: '#fafafa' },
|
|
725
|
+
surface: { dark: '#0a0a0a', light: '#fff' },
|
|
727
726
|
},
|
|
728
727
|
black: '#000',
|
|
729
728
|
blue: {
|
|
@@ -811,7 +810,6 @@ const config = Config.create({
|
|
|
811
810
|
900: { dark: '#ff6166', light: '#cb2a2f' },
|
|
812
811
|
1000: { dark: '#feecee', light: '#391417' },
|
|
813
812
|
},
|
|
814
|
-
surface: { dark: '#0a0a0a', light: '#fff' },
|
|
815
813
|
teal: {
|
|
816
814
|
100: { dark: '#04201b', light: '#eefcf9' },
|
|
817
815
|
200: { dark: '#062822', light: '#e5faf6' },
|
|
@@ -1070,14 +1068,14 @@ const config = Config.create({
|
|
|
1070
1068
|
fontSize: '20px',
|
|
1071
1069
|
fontWeight: 400,
|
|
1072
1070
|
letterSpacing: '0px',
|
|
1073
|
-
lineHeight: '
|
|
1071
|
+
lineHeight: '28px',
|
|
1074
1072
|
strong: {
|
|
1075
1073
|
fontFamily:
|
|
1076
1074
|
'Geist, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
|
|
1077
1075
|
fontSize: '20px',
|
|
1078
1076
|
fontWeight: 550,
|
|
1079
1077
|
letterSpacing: '0px',
|
|
1080
|
-
lineHeight: '
|
|
1078
|
+
lineHeight: '28px',
|
|
1081
1079
|
},
|
|
1082
1080
|
},
|
|
1083
1081
|
'24': {
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,21 @@ export * as Config from './Config.js'
|
|
|
8
8
|
export { style } from './styleFunction.js'
|
|
9
9
|
/** Ordered composition of applied styling props. */
|
|
10
10
|
export { cx } from './cx.js'
|
|
11
|
+
/**
|
|
12
|
+
* Creates isolated authoring with optional vars and named alternatives.
|
|
13
|
+
* @alias Config.create
|
|
14
|
+
*/
|
|
15
|
+
export { create as defineConfig } from './Config.js'
|
|
16
|
+
/**
|
|
17
|
+
* Creates immutable typed variable sets without emitting CSS.
|
|
18
|
+
* @alias Vars.define
|
|
19
|
+
*/
|
|
20
|
+
export { define as defineVars } from './Vars.js'
|
|
21
|
+
/**
|
|
22
|
+
* Overrides variable values while preserving their shared contract.
|
|
23
|
+
* @alias Vars.extend
|
|
24
|
+
*/
|
|
25
|
+
export { extend as extendVars } from './Vars.js'
|
|
11
26
|
/** Inferred component inputs from callable style definitions. */
|
|
12
27
|
export type * as Props from './Props.js'
|
|
13
28
|
/** Typed literal style definitions and validation diagnostics. */
|
|
@@ -157,7 +157,7 @@ export function variants(
|
|
|
157
157
|
return (values: Record<string, unknown> & style.Options = {}) => {
|
|
158
158
|
const result = { ...props(values as style.Options) } as {
|
|
159
159
|
className: string
|
|
160
|
-
style?: style.Props['style']
|
|
160
|
+
style?: NonNullable<style.Props['style']>
|
|
161
161
|
[key: `data-${string}`]: string | undefined
|
|
162
162
|
}
|
|
163
163
|
const bindings: Record<string, string | number> = {}
|
package/src/internal/Token.ts
CHANGED
|
@@ -262,6 +262,11 @@ export function acceptsReference(
|
|
|
262
262
|
if (property.startsWith('--')) return true
|
|
263
263
|
function check(value: Value): boolean {
|
|
264
264
|
if (is(value)) return acceptsReference(value, property)
|
|
265
|
+
if (isExpression(value))
|
|
266
|
+
return Binding.accepts(
|
|
267
|
+
value.group === 'color' ? 'color' : 'length',
|
|
268
|
+
property,
|
|
269
|
+
)
|
|
265
270
|
if (typeof value === 'object') return Object.values(value).every(check)
|
|
266
271
|
if (typeof value === 'number') {
|
|
267
272
|
const rule = Literal.rule(property)
|
|
@@ -403,6 +408,18 @@ export type Expression = {
|
|
|
403
408
|
readonly parts: readonly (string | Reference | Binding.Reference)[]
|
|
404
409
|
}
|
|
405
410
|
|
|
411
|
+
/** A composed variable value with an explicit scalar domain. */
|
|
412
|
+
export type Composition<
|
|
413
|
+
group extends 'color' | 'spacing' = 'color' | 'spacing',
|
|
414
|
+
> = {
|
|
415
|
+
/** Structured expression discriminator. */
|
|
416
|
+
readonly [expression]: true
|
|
417
|
+
/** Domain retained by variable references and compatible overrides. */
|
|
418
|
+
readonly group: group
|
|
419
|
+
/** CSS text and references to portable variable values. */
|
|
420
|
+
readonly parts: readonly (string | Reference)[]
|
|
421
|
+
}
|
|
422
|
+
|
|
406
423
|
/** Identifies structured web expressions independently of literal CSS text. */
|
|
407
424
|
export const expression = Symbol('zyzz.expression')
|
|
408
425
|
|
|
@@ -558,17 +575,27 @@ type Paths<tree, property extends keyof Literal.Properties = never> = [
|
|
|
558
575
|
> extends Value
|
|
559
576
|
? [property] extends [never]
|
|
560
577
|
? PathKey<key>
|
|
561
|
-
: VariableSets.Scalar<
|
|
562
|
-
|
|
563
|
-
>
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
578
|
+
: Literal.Color extends VariableSets.Scalar<NonNullable<tree[key]>>
|
|
579
|
+
? property extends Properties<'color'>
|
|
580
|
+
? PathKey<key>
|
|
581
|
+
: never
|
|
582
|
+
: Literal.Length extends VariableSets.Scalar<
|
|
583
|
+
NonNullable<tree[key]>
|
|
584
|
+
>
|
|
585
|
+
? Binding.Property<'length', property> extends never
|
|
586
|
+
? never
|
|
587
|
+
: PathKey<key>
|
|
588
|
+
: VariableSets.Scalar<
|
|
589
|
+
NonNullable<tree[key]>
|
|
590
|
+
> extends Literal.Properties[property] &
|
|
591
|
+
ValueSyntax.Checked<
|
|
592
|
+
Record<
|
|
593
|
+
property,
|
|
594
|
+
VariableSets.Scalar<NonNullable<tree[key]>>
|
|
595
|
+
>
|
|
596
|
+
>[property]
|
|
597
|
+
? PathKey<key>
|
|
598
|
+
: never
|
|
572
599
|
: `${key}.${Paths<NonNullable<tree[key]>, property>}`
|
|
573
600
|
}[Extract<keyof tree, number | string>]
|
|
574
601
|
|
|
@@ -794,6 +821,7 @@ export type Value =
|
|
|
794
821
|
| number
|
|
795
822
|
| string
|
|
796
823
|
| Reference
|
|
824
|
+
| Composition
|
|
797
825
|
| { readonly dark: Value; readonly light: Value }
|
|
798
826
|
| Conditions
|
|
799
827
|
|
|
@@ -75,6 +75,7 @@ export function build(
|
|
|
75
75
|
typeof input === 'string' ||
|
|
76
76
|
typeof input === 'number' ||
|
|
77
77
|
Token.is(input) ||
|
|
78
|
+
Token.isExpression(input) ||
|
|
78
79
|
(path.length > 0 &&
|
|
79
80
|
input &&
|
|
80
81
|
typeof input === 'object' &&
|
|
@@ -244,6 +245,17 @@ function read(
|
|
|
244
245
|
active = new Set<object>(),
|
|
245
246
|
): Token.Value {
|
|
246
247
|
if (Token.is(input)) return input
|
|
248
|
+
if (Token.isExpression(input)) {
|
|
249
|
+
if (
|
|
250
|
+
!('group' in input) ||
|
|
251
|
+
(input.group !== 'color' && input.group !== 'spacing')
|
|
252
|
+
)
|
|
253
|
+
throw new Vars.InvalidError(path, 'Expected a composed variable value.')
|
|
254
|
+
return Vars.compose(
|
|
255
|
+
input.group,
|
|
256
|
+
input.parts as readonly (string | Token.Reference)[],
|
|
257
|
+
)
|
|
258
|
+
}
|
|
247
259
|
if (typeof input === 'number' && Number.isFinite(input)) return input
|
|
248
260
|
if (typeof input === 'string' && input.trim() && !/[;{}]/.test(input))
|
|
249
261
|
return input
|
|
@@ -307,7 +319,7 @@ function read(
|
|
|
307
319
|
|
|
308
320
|
/** Infers the shared declaration domain after following defaults and references. */
|
|
309
321
|
export function domain(value: Token.Value): Token.Group {
|
|
310
|
-
if (Token.is(value)) return value.group
|
|
322
|
+
if (Token.is(value) || Token.isExpression(value)) return value.group
|
|
311
323
|
if (typeof value === 'object')
|
|
312
324
|
return 'default' in value ? domain(value.default) : 'color'
|
|
313
325
|
if (
|
|
@@ -383,6 +395,7 @@ export function merge(
|
|
|
383
395
|
typeof entry !== 'object' ||
|
|
384
396
|
Array.isArray(entry) ||
|
|
385
397
|
Token.is(entry) ||
|
|
398
|
+
Token.isExpression(entry) ||
|
|
386
399
|
'default' in entry ||
|
|
387
400
|
('light' in entry && 'dark' in entry) ||
|
|
388
401
|
(Object.keys(entry).length <= 2 &&
|
|
@@ -424,6 +437,17 @@ export function rebind(
|
|
|
424
437
|
value: visit(value.path),
|
|
425
438
|
})
|
|
426
439
|
}
|
|
440
|
+
if (Token.isExpression(value))
|
|
441
|
+
return Vars.compose(
|
|
442
|
+
value.group,
|
|
443
|
+
value.parts.map((part) => {
|
|
444
|
+
if (typeof part === 'string') return part
|
|
445
|
+
const reference = resolve(part)
|
|
446
|
+
if (!Token.is(reference))
|
|
447
|
+
throw new Vars.InvalidError([], 'Expected a variable reference.')
|
|
448
|
+
return reference
|
|
449
|
+
}),
|
|
450
|
+
)
|
|
427
451
|
if (typeof value !== 'object') return value
|
|
428
452
|
|
|
429
453
|
return Object.freeze(
|
package/src/node/Host.ts
CHANGED
|
@@ -49,6 +49,14 @@ export async function create(options: create.Options): Promise<Runtime> {
|
|
|
49
49
|
targets: { ...options.css?.targets },
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
const externals = [...(options.external ?? [])]
|
|
53
|
+
if (
|
|
54
|
+
externals.some((pattern) => !pattern || pattern.slice(0, -1).includes('*'))
|
|
55
|
+
)
|
|
56
|
+
throw new Error(
|
|
57
|
+
'External imports require exact names or a trailing * prefix.',
|
|
58
|
+
)
|
|
59
|
+
|
|
52
60
|
const native = options.native
|
|
53
61
|
? Object.freeze({
|
|
54
62
|
...options.native,
|
|
@@ -404,6 +412,15 @@ export async function create(options: create.Options): Promise<Runtime> {
|
|
|
404
412
|
(!specifier.startsWith('#') && specifier.includes('#'))
|
|
405
413
|
)
|
|
406
414
|
continue
|
|
415
|
+
if (
|
|
416
|
+
externals.some((pattern) =>
|
|
417
|
+
pattern.endsWith('*')
|
|
418
|
+
? specifier.startsWith(pattern.slice(0, -1))
|
|
419
|
+
: specifier === pattern,
|
|
420
|
+
)
|
|
421
|
+
)
|
|
422
|
+
continue
|
|
423
|
+
|
|
407
424
|
try {
|
|
408
425
|
if (specifier.startsWith('.')) {
|
|
409
426
|
const target = Relative.resolve({ moduleId, modules, specifier })
|
|
@@ -951,6 +968,8 @@ export declare namespace create {
|
|
|
951
968
|
readonly targets?: Readonly<LightningCss.Targets> | undefined
|
|
952
969
|
}
|
|
953
970
|
| undefined
|
|
971
|
+
/** Imports left for downstream tooling. Matches exact names or prefixes ending in *. */
|
|
972
|
+
readonly external?: readonly string[] | undefined
|
|
954
973
|
/** Native context captured at creation. Emits modules and maps without CSS or web initialization. */
|
|
955
974
|
readonly native?: Graph.compile.Options['native']
|
|
956
975
|
/** Output directory exclusively locked until close; may be nested under root. Defaults to `dist`. */
|
|
@@ -785,6 +785,12 @@ function resolve(
|
|
|
785
785
|
resolved = resolved.value
|
|
786
786
|
continue
|
|
787
787
|
}
|
|
788
|
+
if (Token.isExpression(resolved))
|
|
789
|
+
fail(
|
|
790
|
+
'unsupported_feature',
|
|
791
|
+
'Composed variables require a web target.',
|
|
792
|
+
path,
|
|
793
|
+
)
|
|
788
794
|
if ('default' in resolved)
|
|
789
795
|
fail(
|
|
790
796
|
'unsupported_feature',
|
package/src/styleFunction.ts
CHANGED
|
@@ -114,9 +114,7 @@ export declare namespace style {
|
|
|
114
114
|
/** Compiled and supplied class names. */
|
|
115
115
|
readonly className: string
|
|
116
116
|
/** Supplied inline styling overrides when present. */
|
|
117
|
-
readonly style?:
|
|
118
|
-
| Readonly<Record<string, string | number | undefined>>
|
|
119
|
-
| undefined
|
|
117
|
+
readonly style?: Readonly<Record<string, string | number | undefined>>
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
/** Callable definition; source rewriting supplies its implementation. */
|