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.
Files changed (247) hide show
  1. package/README.md +34 -19
  2. package/dist/Config.d.ts +16 -167
  3. package/dist/Config.d.ts.map +1 -1
  4. package/dist/Config.js +7 -246
  5. package/dist/Config.js.map +1 -1
  6. package/dist/Style.d.ts +15 -12
  7. package/dist/Style.d.ts.map +1 -1
  8. package/dist/Style.js +51 -26
  9. package/dist/Style.js.map +1 -1
  10. package/dist/Vars.d.ts +114 -0
  11. package/dist/Vars.d.ts.map +1 -0
  12. package/dist/Vars.js +42 -0
  13. package/dist/Vars.js.map +1 -0
  14. package/dist/compiler/Graph.js +11 -8
  15. package/dist/compiler/Graph.js.map +1 -1
  16. package/dist/compiler/Native.d.ts +5 -5
  17. package/dist/compiler/Native.d.ts.map +1 -1
  18. package/dist/compiler/Native.js +21 -21
  19. package/dist/compiler/Native.js.map +1 -1
  20. package/dist/compiler/Source.d.ts +8 -6
  21. package/dist/compiler/Source.d.ts.map +1 -1
  22. package/dist/compiler/Source.js +47 -14
  23. package/dist/compiler/Source.js.map +1 -1
  24. package/dist/compiler/Transform.d.ts +1 -1
  25. package/dist/compiler/Transform.d.ts.map +1 -1
  26. package/dist/compiler/Transform.js +58 -22
  27. package/dist/compiler/Transform.js.map +1 -1
  28. package/dist/compiler/internal/Compositions.d.ts +5 -0
  29. package/dist/compiler/internal/Compositions.d.ts.map +1 -1
  30. package/dist/compiler/internal/Compositions.js +22 -3
  31. package/dist/compiler/internal/Compositions.js.map +1 -1
  32. package/dist/compiler/internal/Configurations.d.ts.map +1 -1
  33. package/dist/compiler/internal/Configurations.js +73 -12
  34. package/dist/compiler/internal/Configurations.js.map +1 -1
  35. package/dist/compiler/internal/Contract.d.ts +1 -1
  36. package/dist/compiler/internal/Contract.d.ts.map +1 -1
  37. package/dist/compiler/internal/Contract.js +155 -13
  38. package/dist/compiler/internal/Contract.js.map +1 -1
  39. package/dist/compiler/internal/Contributions.js +1 -1
  40. package/dist/compiler/internal/Contributions.js.map +1 -1
  41. package/dist/compiler/internal/Dynamic.js +1 -1
  42. package/dist/compiler/internal/Dynamic.js.map +1 -1
  43. package/dist/compiler/internal/Expression.d.ts +3 -0
  44. package/dist/compiler/internal/Expression.d.ts.map +1 -1
  45. package/dist/compiler/internal/Expression.js +21 -0
  46. package/dist/compiler/internal/Expression.js.map +1 -1
  47. package/dist/compiler/internal/Identifiers.d.ts +1 -1
  48. package/dist/compiler/internal/Identifiers.d.ts.map +1 -1
  49. package/dist/compiler/internal/Identifiers.js +2 -2
  50. package/dist/compiler/internal/Identifiers.js.map +1 -1
  51. package/dist/compiler/internal/NativeBindings.d.ts +1 -1
  52. package/dist/compiler/internal/NativeBindings.d.ts.map +1 -1
  53. package/dist/compiler/internal/NativeBindings.js +3 -3
  54. package/dist/compiler/internal/NativeBindings.js.map +1 -1
  55. package/dist/compiler/internal/PackedStyles.d.ts +1 -1
  56. package/dist/compiler/internal/PackedStyles.d.ts.map +1 -1
  57. package/dist/compiler/internal/PackedStyles.js +15 -25
  58. package/dist/compiler/internal/PackedStyles.js.map +1 -1
  59. package/dist/compiler/internal/Recipes.js +1 -1
  60. package/dist/compiler/internal/Recipes.js.map +1 -1
  61. package/dist/compiler/internal/Selectors.js +1 -1
  62. package/dist/compiler/internal/Selectors.js.map +1 -1
  63. package/dist/compiler/internal/Themes.d.ts +12 -3
  64. package/dist/compiler/internal/Themes.d.ts.map +1 -1
  65. package/dist/compiler/internal/Themes.js +192 -52
  66. package/dist/compiler/internal/Themes.js.map +1 -1
  67. package/dist/compiler/internal/{Variables.d.ts → Vars.d.ts} +1 -1
  68. package/dist/compiler/internal/Vars.d.ts.map +1 -0
  69. package/dist/compiler/internal/{Variables.js → Vars.js} +3 -3
  70. package/dist/compiler/internal/Vars.js.map +1 -0
  71. package/dist/default.d.ts +147 -2562
  72. package/dist/default.d.ts.map +1 -1
  73. package/dist/default.js +85 -80
  74. package/dist/default.js.map +2 -2
  75. package/dist/default.js.zyzz.json +1 -1
  76. package/dist/esbuild/index.d.ts +3 -0
  77. package/dist/esbuild/index.d.ts.map +1 -0
  78. package/dist/esbuild/index.js +5 -0
  79. package/dist/esbuild/index.js.map +1 -0
  80. package/dist/index.d.ts +4 -4
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +4 -4
  83. package/dist/index.js.map +1 -1
  84. package/dist/internal/Authoring.d.ts +1 -1
  85. package/dist/internal/Authoring.d.ts.map +1 -1
  86. package/dist/internal/Authoring.js +4 -4
  87. package/dist/internal/Authoring.js.map +1 -1
  88. package/dist/internal/Binding.d.ts +1 -1
  89. package/dist/internal/Binding.d.ts.map +1 -1
  90. package/dist/internal/Completion.d.ts +19 -0
  91. package/dist/internal/Completion.d.ts.map +1 -0
  92. package/dist/internal/Completion.js +2 -0
  93. package/dist/internal/Completion.js.map +1 -0
  94. package/dist/internal/Condition.d.ts +3 -1
  95. package/dist/internal/Condition.d.ts.map +1 -1
  96. package/dist/internal/Condition.js.map +1 -1
  97. package/dist/internal/Configuration.d.ts +248 -0
  98. package/dist/internal/Configuration.d.ts.map +1 -0
  99. package/dist/internal/Configuration.js +343 -0
  100. package/dist/internal/Configuration.js.map +1 -0
  101. package/dist/{Theme.d.ts → internal/Theme.d.ts} +15 -13
  102. package/dist/internal/Theme.d.ts.map +1 -0
  103. package/dist/{Theme.js → internal/Theme.js} +39 -12
  104. package/dist/internal/Theme.js.map +1 -0
  105. package/dist/internal/Token.d.ts +46 -16
  106. package/dist/internal/Token.d.ts.map +1 -1
  107. package/dist/internal/Token.js +89 -5
  108. package/dist/internal/Token.js.map +1 -1
  109. package/dist/internal/Typography.d.ts +13 -5
  110. package/dist/internal/Typography.d.ts.map +1 -1
  111. package/dist/internal/Typography.js +42 -6
  112. package/dist/internal/Typography.js.map +1 -1
  113. package/dist/internal/Value.d.ts +6 -1
  114. package/dist/internal/Value.d.ts.map +1 -1
  115. package/dist/internal/Value.js.map +1 -1
  116. package/dist/internal/VariableSets.d.ts +20 -0
  117. package/dist/internal/VariableSets.d.ts.map +1 -0
  118. package/dist/internal/VariableSets.js +317 -0
  119. package/dist/internal/VariableSets.js.map +1 -0
  120. package/dist/next/loader.js +15 -5
  121. package/dist/next/loader.js.map +1 -1
  122. package/dist/node/Host.d.ts.map +1 -1
  123. package/dist/node/Host.js +1 -1
  124. package/dist/node/Host.js.map +1 -1
  125. package/dist/react-native/Host.d.ts +2 -2
  126. package/dist/react-native/Host.d.ts.map +1 -1
  127. package/dist/react-native/Host.js +4 -4
  128. package/dist/react-native/Host.js.map +1 -1
  129. package/dist/react-native/StyleSheet.d.ts +9 -8
  130. package/dist/react-native/StyleSheet.d.ts.map +1 -1
  131. package/dist/react-native/StyleSheet.js +29 -23
  132. package/dist/react-native/StyleSheet.js.map +1 -1
  133. package/dist/react-native/Variants.d.ts +3 -3
  134. package/dist/react-native/Variants.d.ts.map +1 -1
  135. package/dist/react-native/Variants.js +2 -2
  136. package/dist/react-native/react.d.ts +1 -1
  137. package/dist/react-native/react.d.ts.map +1 -1
  138. package/dist/react-native/react.js +5 -5
  139. package/dist/react-native/react.js.map +1 -1
  140. package/dist/rollup/index.d.ts +3 -0
  141. package/dist/rollup/index.d.ts.map +1 -0
  142. package/dist/rollup/index.js +5 -0
  143. package/dist/rollup/index.js.map +1 -0
  144. package/dist/runtime/Appearance.d.ts +7 -7
  145. package/dist/runtime/Appearance.d.ts.map +1 -1
  146. package/dist/runtime/Appearance.js +15 -15
  147. package/dist/runtime/Appearance.js.map +1 -1
  148. package/dist/runtime/Dynamic.d.ts.map +1 -1
  149. package/dist/runtime/Dynamic.js +4 -1
  150. package/dist/runtime/Dynamic.js.map +1 -1
  151. package/dist/runtime/NativeContext.d.ts +4 -4
  152. package/dist/runtime/NativeContext.d.ts.map +1 -1
  153. package/dist/runtime/NativeContext.js +5 -5
  154. package/dist/runtime/NativeContext.js.map +1 -1
  155. package/dist/runtime/NativeDynamic.d.ts +1 -1
  156. package/dist/runtime/NativeDynamic.d.ts.map +1 -1
  157. package/dist/runtime/NativeDynamic.js.map +1 -1
  158. package/dist/runtime/Props.d.ts +1 -1
  159. package/dist/runtime/Props.js +3 -3
  160. package/dist/runtime/Props.js.map +1 -1
  161. package/dist/runtime/Selection.d.ts +14 -10
  162. package/dist/runtime/Selection.d.ts.map +1 -1
  163. package/dist/runtime/Selection.js +19 -18
  164. package/dist/runtime/Selection.js.map +1 -1
  165. package/dist/styleFunction.d.ts +14 -14
  166. package/dist/styleFunction.d.ts.map +1 -1
  167. package/dist/styleFunction.js.map +1 -1
  168. package/dist/unplugin/index.d.ts +20 -0
  169. package/dist/unplugin/index.d.ts.map +1 -0
  170. package/dist/unplugin/index.js +498 -0
  171. package/dist/unplugin/index.js.map +1 -0
  172. package/dist/variants.d.ts +3 -3
  173. package/dist/variants.d.ts.map +1 -1
  174. package/dist/variants.js.map +1 -1
  175. package/dist/vite/index.d.ts.map +1 -1
  176. package/dist/vite/index.js +6 -3
  177. package/dist/vite/index.js.map +1 -1
  178. package/dist/web/Css.d.ts +4 -3
  179. package/dist/web/Css.d.ts.map +1 -1
  180. package/dist/web/Css.js +4 -4
  181. package/dist/web/Css.js.map +1 -1
  182. package/dist/web/internal/Themes.d.ts +3 -2
  183. package/dist/web/internal/Themes.d.ts.map +1 -1
  184. package/dist/web/internal/Themes.js +42 -6
  185. package/dist/web/internal/Themes.js.map +1 -1
  186. package/dist/webpack/index.d.ts +3 -0
  187. package/dist/webpack/index.d.ts.map +1 -0
  188. package/dist/webpack/index.js +5 -0
  189. package/dist/webpack/index.js.map +1 -0
  190. package/package.json +23 -2
  191. package/src/Config.ts +43 -685
  192. package/src/Style.ts +97 -34
  193. package/src/Vars.ts +299 -0
  194. package/src/compiler/Graph.ts +14 -9
  195. package/src/compiler/Native.ts +29 -32
  196. package/src/compiler/Source.ts +59 -21
  197. package/src/compiler/Transform.ts +73 -23
  198. package/src/compiler/internal/Compositions.ts +36 -3
  199. package/src/compiler/internal/Configurations.ts +83 -11
  200. package/src/compiler/internal/Contract.ts +207 -15
  201. package/src/compiler/internal/Contributions.ts +1 -1
  202. package/src/compiler/internal/Dynamic.ts +1 -1
  203. package/src/compiler/internal/Expression.ts +26 -0
  204. package/src/compiler/internal/Identifiers.ts +2 -1
  205. package/src/compiler/internal/NativeBindings.ts +3 -3
  206. package/src/compiler/internal/PackedStyles.ts +22 -26
  207. package/src/compiler/internal/Recipes.ts +1 -1
  208. package/src/compiler/internal/Selectors.ts +1 -1
  209. package/src/compiler/internal/Themes.ts +266 -57
  210. package/src/compiler/internal/{Variables.ts → Vars.ts} +2 -2
  211. package/src/default.ts +173 -154
  212. package/src/esbuild/index.ts +5 -0
  213. package/src/index.ts +4 -4
  214. package/src/internal/Authoring.ts +5 -7
  215. package/src/internal/Binding.ts +1 -1
  216. package/src/internal/Completion.ts +42 -0
  217. package/src/internal/Condition.ts +31 -1
  218. package/src/internal/Configuration.ts +970 -0
  219. package/src/{Theme.ts → internal/Theme.ts} +75 -20
  220. package/src/internal/Token.ts +258 -85
  221. package/src/internal/Typography.ts +71 -16
  222. package/src/internal/Value.ts +45 -26
  223. package/src/internal/VariableSets.ts +458 -0
  224. package/src/next/loader.ts +19 -5
  225. package/src/node/Host.ts +1 -2
  226. package/src/react-native/Host.ts +6 -6
  227. package/src/react-native/StyleSheet.ts +49 -42
  228. package/src/react-native/Variants.ts +3 -3
  229. package/src/react-native/react.ts +6 -6
  230. package/src/rollup/index.ts +5 -0
  231. package/src/runtime/Appearance.ts +20 -20
  232. package/src/runtime/Dynamic.ts +4 -1
  233. package/src/runtime/NativeContext.ts +8 -8
  234. package/src/runtime/NativeDynamic.ts +2 -4
  235. package/src/runtime/Props.ts +3 -3
  236. package/src/runtime/Selection.ts +44 -33
  237. package/src/styleFunction.ts +22 -19
  238. package/src/unplugin/index.ts +600 -0
  239. package/src/variants.ts +7 -5
  240. package/src/vite/index.ts +5 -4
  241. package/src/web/Css.ts +10 -7
  242. package/src/web/internal/Themes.ts +52 -9
  243. package/src/webpack/index.ts +5 -0
  244. package/dist/Theme.d.ts.map +0 -1
  245. package/dist/Theme.js.map +0 -1
  246. package/dist/compiler/internal/Variables.d.ts.map +0 -1
  247. package/dist/compiler/internal/Variables.js.map +0 -1
package/src/Style.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  * Copies typed style declarations into immutable, ordered, target-independent data.
3
3
  * @module
4
4
  */
5
+ import * as VariableSets from './internal/VariableSets.js'
6
+ import type * as Vars from './Vars.js'
5
7
  import * as Condition from './internal/Condition.js'
6
8
  import * as Query from './internal/Query.js'
7
9
  import * as Binding from './internal/Binding.js'
@@ -9,7 +11,7 @@ import type * as Literal from './internal/Literal.js'
9
11
  import * as Token from './internal/Token.js'
10
12
  import * as Typography from './internal/Typography.js'
11
13
  import * as Value from './internal/Value.js'
12
- import type * as Theme from './Theme.js'
14
+ import type * as Theme from './internal/Theme.js'
13
15
  import * as Targets from './internal/Targets.js'
14
16
 
15
17
  /** Validates only authored keys, recursively retaining nested token inference. */
@@ -26,7 +28,7 @@ export type Accepted<
26
28
  | 'selectors'
27
29
  | 'targets'
28
30
  | 'typography'
29
- | 'variables'
31
+ | 'vars'
30
32
  >,
31
33
  never
32
34
  > &
@@ -47,14 +49,18 @@ export type Accepted<
47
49
  : never
48
50
  }
49
51
  : never
50
- : key extends 'variables'
52
+ : key extends 'vars'
51
53
  ? style[key] extends Record<string, unknown>
52
54
  ? {
53
55
  [name in keyof style[key]]: style[key][name] extends
54
56
  | number
55
57
  | string
56
58
  ? Literal.Checked<style[key][name]>
57
- : never
59
+ : literal extends true
60
+ ? never
61
+ : style[key][name] extends Token.Reference
62
+ ? style[key][name]
63
+ : never
58
64
  }
59
65
  : never
60
66
  : key extends 'typography'
@@ -168,6 +174,22 @@ export type Declaration = {
168
174
  * @returns Immutable definitions retaining the inferred style-name union.
169
175
  * @throws {InvalidError} If the input structure cannot represent ordered declarations.
170
176
  */
177
+ export function define<
178
+ const values extends Vars.Values,
179
+ const styles extends Record<string, unknown>,
180
+ >(
181
+ styles: styles &
182
+ NoInfer<Exact<styles, Vars.Mapped<values, {}>>> & {
183
+ [key in keyof styles]: WithoutRelationships<styles[key]>
184
+ },
185
+ options: {
186
+ readonly vars: Vars.Definition<values>
187
+ readonly locations?: readonly SourceLocation[]
188
+ },
189
+ ): Definition<
190
+ `${Extract<keyof styles, string | number>}`,
191
+ Targets.Domains<styles>
192
+ >
171
193
  export function define<
172
194
  const styles extends Record<string, unknown>,
173
195
  const tokens extends Theme.Tokens,
@@ -195,6 +217,11 @@ export function define(
195
217
  styles: Record<string, unknown>,
196
218
  options: define.Options = {},
197
219
  ): Definition {
220
+ const theme =
221
+ options.vars &&
222
+ (typeof Reflect.get(options.vars, 'style') === 'function'
223
+ ? (options.vars as Theme.Definition)
224
+ : VariableSets.theme(options.vars as Vars.Definition))
198
225
  if ((options[nesting] ?? 0) > 128)
199
226
  throw new InvalidError([
200
227
  {
@@ -299,7 +326,7 @@ export function define(
299
326
  if (name.length === 0)
300
327
  report('invalid_structure', [name], 'Style names must not be empty.')
301
328
 
302
- const mappings = options.theme?.[Token.definition].contract.shorthands
329
+ const mappings = theme?.[Token.definition].contract.shorthands
303
330
  const authored = entries(style, [name]).filter(
304
331
  ([key, value]) => key !== 'targets' || value !== undefined,
305
332
  )
@@ -388,9 +415,8 @@ export function define(
388
415
  }
389
416
 
390
417
  const path = parsed?.value ?? input
391
- const data = options.theme?.[Token.definition]
392
- const fields = Typography.fields(options.theme, path)
393
- if (!fields.length) {
418
+ const entries = Typography.entries(theme, path)
419
+ if (!entries.length) {
394
420
  report(
395
421
  'invalid_value',
396
422
  [name, property],
@@ -403,24 +429,9 @@ export function define(
403
429
  const explicit = new Set(
404
430
  authored.flatMap(([property]) => mappings?.[property] ?? [property]),
405
431
  )
406
- return fields
407
- .filter((field) => !explicit.has(field))
408
- .map((field) => {
409
- const key = `typography.${path}.${field}`
410
- const reference = Token.create({
411
- contract: data!.contract,
412
- group: field,
413
- path: key,
414
- value: data!.values[key]!,
415
- })
416
- return [
417
- field,
418
- parsed?.important
419
- ? Token.compose([reference, ' !important'])
420
- : reference,
421
- property,
422
- ] as const
423
- })
432
+ return Typography.entries(theme, path, explicit, parsed?.important).map(
433
+ ([field, value]) => [field, value, property] as const,
434
+ )
424
435
  },
425
436
  )
426
437
 
@@ -440,7 +451,7 @@ export function define(
440
451
  const condition = Condition.is(key)
441
452
  ? Query.resolve(
442
453
  key,
443
- options.theme?.[Token.definition].queries ?? {
454
+ theme?.[Token.definition].queries ?? {
444
455
  breakpoints: {},
445
456
  containers: {},
446
457
  containerNames: [],
@@ -597,7 +608,7 @@ export function define(
597
608
  const scalar = parsed ? parsed.value : entry
598
609
 
599
610
  const resolved = (() => {
600
- if (!options.theme) return scalar
611
+ if (!theme) return scalar
601
612
 
602
613
  if (typeof scalar !== 'string' && typeof scalar !== 'number')
603
614
  return scalar
@@ -607,7 +618,7 @@ export function define(
607
618
 
608
619
  const resolved = Token.resolve(scalar, {
609
620
  property: key,
610
- theme: options.theme,
621
+ theme,
611
622
  })
612
623
 
613
624
  if (Token.is(resolved)) {
@@ -621,6 +632,19 @@ export function define(
621
632
  return resolved
622
633
  })()
623
634
 
635
+ if (
636
+ Token.is(resolved) &&
637
+ resolved.contract.variableSet &&
638
+ !Token.acceptsReference(resolved, key)
639
+ ) {
640
+ report(
641
+ 'invalid_value',
642
+ [name, authoredProperty],
643
+ 'Variable value is incompatible with this property.',
644
+ )
645
+ continue
646
+ }
647
+
624
648
  const value = parsed && resolved === '0' ? 0 : resolved
625
649
 
626
650
  declarations.push(
@@ -645,9 +669,48 @@ export function define(
645
669
 
646
670
  if (diagnostics.length) throw new InvalidError(diagnostics)
647
671
 
672
+ const defaultLayer = theme?.[Token.definition].contract.defaultLayer
673
+ // Apply defaults after validation to retain authored diagnostic paths and explicit layer nesting.
674
+ function layered(style: NamedStyle): NamedStyle {
675
+ const { targets, ...body } = style
676
+ const rules = (() => {
677
+ if (style.rules)
678
+ return style.rules.map((rule) =>
679
+ rule.condition === '@layer' || rule.condition?.startsWith('@layer ')
680
+ ? rule
681
+ : Object.freeze({ ...rule, style: layered(rule.style) }),
682
+ )
683
+
684
+ if (!style.declarations.length) return []
685
+
686
+ return [
687
+ Object.freeze({
688
+ condition: `@layer ${defaultLayer}`,
689
+ style: Object.freeze(body),
690
+ }),
691
+ ]
692
+ })()
693
+
694
+ return Object.freeze({
695
+ ...body,
696
+ declarations: style.rules ? style.declarations : Object.freeze([]),
697
+ rules: Object.freeze(rules),
698
+ ...(targets
699
+ ? {
700
+ targets: Object.freeze({
701
+ ...targets,
702
+ ...(targets.web ? { web: layered(targets.web) } : {}),
703
+ }),
704
+ }
705
+ : {}),
706
+ })
707
+ }
708
+
648
709
  // Validated names are precisely the input's enumerable string keys.
649
710
  return Object.freeze({
650
- styles: Object.freeze(output),
711
+ styles: Object.freeze(
712
+ defaultLayer && !options[nesting] ? output.map(layered) : output,
713
+ ),
651
714
  })
652
715
  }
653
716
 
@@ -663,11 +726,11 @@ export declare namespace define {
663
726
  } & ([tokens] extends [never]
664
727
  ? {
665
728
  /** Optional themes do not enable shorthand inference. */
666
- readonly theme?: Theme.Definition | undefined
729
+ readonly vars?: Theme.Definition | Vars.Definition | undefined
667
730
  }
668
731
  : {
669
732
  /** Shorthand inference requires a defined token contract. */
670
- readonly theme: Theme.Definition<tokens>
733
+ readonly vars: Theme.Definition<tokens>
671
734
  })
672
735
  }
673
736
 
@@ -753,7 +816,7 @@ export type DeclarationProperties<tokens extends Theme.Tokens = {}> = {
753
816
  | Value.Atom<Token.Names<tokens, property>>
754
817
  | {
755
818
  [group in Token.Group]: property extends Token.Properties<group>
756
- ? Token.Reference<group>
819
+ ? Value.Atom<Token.Reference<group> | Token.Variable<group>>
757
820
  : never
758
821
  }[Token.Group]
759
822
  >
@@ -803,7 +866,7 @@ type WithoutRelationships<value> = value extends readonly unknown[]
803
866
  ? unknown
804
867
  : value extends object
805
868
  ? {
806
- [key in keyof value]: key extends symbol | 'selectors' | 'variables'
869
+ [key in keyof value]: key extends symbol | 'selectors' | 'vars'
807
870
  ? never
808
871
  : key extends keyof Literal.Properties
809
872
  ? unknown
package/src/Vars.ts ADDED
@@ -0,0 +1,299 @@
1
+ /** Defines immutable variable sets and compatible scoped overrides. @module */
2
+ import type * as Typography from './internal/Typography.js'
3
+ import type * as Theme from './internal/Theme.js'
4
+ import * as Identity from './internal/Identity.js'
5
+ import type * as Literal from './internal/Literal.js'
6
+ import * as Token from './internal/Token.js'
7
+ import * as VariableSets from './internal/VariableSets.js'
8
+ import type { style } from './styleFunction.js'
9
+
10
+ /** Portable scalar reference with its accepted value domain. */
11
+ export type Reference<group extends Token.Group = Token.Group> =
12
+ Token.Reference<group>
13
+
14
+ const shape = Symbol('zyzz.variables.shape')
15
+
16
+ /** A scalar, a color-scheme pair, or ordered media overrides with a required default. */
17
+ export type Value =
18
+ | string
19
+ | number
20
+ | Token.Reference
21
+ | {
22
+ readonly light: string | Token.Reference
23
+ readonly dark: string | Token.Reference
24
+ }
25
+ | ({ readonly default: Value } & {
26
+ readonly [query: `@media ${string}`]: Value
27
+ })
28
+
29
+ /** Nested categories and variable paths. */
30
+ export type Values = {
31
+ readonly [key: string]: Value | Values | readonly string[]
32
+ }
33
+
34
+ /** Immutable references retaining their shared set contract. */
35
+ export type Definition<values extends Values = Values> = (Values extends values
36
+ ? {}
37
+ : References<values>) & {
38
+ /** Authored value shape retained for inference. */
39
+ readonly [shape]: values
40
+ /** Compiler-owned identity and values. */
41
+ readonly [Token.definition]: Token.Metadata
42
+ }
43
+
44
+ /** Reference tree preserving the domain of each scalar leaf. */
45
+ export type References<values, root extends boolean = true> = {
46
+ readonly [key in Exclude<
47
+ keyof values,
48
+ root extends true ? 'breakpoints' | 'containers' | 'containerNames' : never
49
+ >]: values[key] extends Value
50
+ ? Token.Reference<Domain<Scalar<values[key]>>> & {
51
+ readonly [Token.scalar]: Scalar<values[key]>
52
+ }
53
+ : References<values[key], false>
54
+ }
55
+
56
+ /** Resolves the scalar types represented by all conditional branches. */
57
+ export type Scalar<value> = Value extends value
58
+ ? string | number
59
+ : value extends { readonly [Token.scalar]: infer scalar }
60
+ ? scalar
61
+ : value extends readonly string[]
62
+ ? value
63
+ : value extends Token.Reference<infer group>
64
+ ? group extends 'color'
65
+ ? Literal.Color
66
+ : group extends 'spacing'
67
+ ? Literal.Length
68
+ : group extends 'number'
69
+ ? number
70
+ : string
71
+ : value extends { default: unknown }
72
+ ? Scalar<value[keyof value]>
73
+ : value extends { light: infer light; dark: infer dark }
74
+ ? Scalar<light | dark>
75
+ : value
76
+
77
+ /** Scalar domain shared by compatible set alternatives. */
78
+ export type Domain<value> = [value] extends [Literal.Color]
79
+ ? 'color'
80
+ : [value] extends [Literal.Length]
81
+ ? 'spacing'
82
+ : [value] extends [number]
83
+ ? 'number'
84
+ : 'string'
85
+
86
+ /** Creates typed references without emitting CSS or reading the environment. */
87
+ export function define<const values extends Values>(
88
+ values: values & NoInfer<Validated<values, false, true>>,
89
+ options?: style.DefinitionOptions,
90
+ ): Definition<values>
91
+ /** Deeply merges derived leaves, rejecting duplicate paths and leaf/category conflicts. */
92
+ export function define<
93
+ const values extends Values,
94
+ const derived extends Values,
95
+ >(
96
+ values: values & NoInfer<Validated<values, false, true>>,
97
+ derive: ((vars: References<values>) => derived) &
98
+ NoInfer<(vars: References<values>) => Validated<derived, false, true>>,
99
+ options?: style.DefinitionOptions,
100
+ ): Definition<Merge<values, derived>>
101
+ export function define(
102
+ values: Values,
103
+ derive: style.DefinitionOptions | ((vars: References<Values>) => Values) = {},
104
+ options: style.DefinitionOptions = {},
105
+ ): Definition {
106
+ if (typeof derive !== 'function') options = derive
107
+
108
+ const contract = Object.freeze({
109
+ variableSet: true,
110
+ ...(options.id === undefined
111
+ ? {}
112
+ : {
113
+ [Token.identity]: Identity.requireId(options.id, 'Vars.define'),
114
+ [Token.complete]: true,
115
+ }),
116
+ })
117
+ const base = VariableSets.build(values, contract)
118
+ if (typeof derive !== 'function') return base
119
+
120
+ const merged = VariableSets.merge(values, derive(base as References<Values>))
121
+ return VariableSets.build(merged, contract)
122
+ }
123
+
124
+ type Merge<base, derived> = {
125
+ readonly [key in keyof base | keyof derived]: key extends keyof derived
126
+ ? key extends keyof base
127
+ ? Merge<base[key], derived[key]>
128
+ : derived[key]
129
+ : key extends keyof base
130
+ ? base[key]
131
+ : never
132
+ }
133
+
134
+ /** Replaces existing leaves while preserving paths, domains, and reference identity. */
135
+ export function extend<const values extends Values>(
136
+ variables: Definition<values>,
137
+ overrides: Overrides<values>,
138
+ ): Definition<values> {
139
+ const metadata = Object.getOwnPropertyDescriptor(variables, Token.definition)
140
+ ?.value as Token.Metadata | undefined
141
+ if (!metadata?.contract.variableSet)
142
+ throw new InvalidError([], 'Expected a variable set.')
143
+ return VariableSets.build(
144
+ overrides,
145
+ metadata.contract,
146
+ metadata.values,
147
+ metadata.queries,
148
+ metadata.paths,
149
+ ) as Definition<values>
150
+ }
151
+
152
+ /** Partial compatible overrides. Conditional leaves are replaced in full. */
153
+ export type Overrides<values> = {
154
+ readonly [key in keyof values]?: values[key] extends Value
155
+ ? Conditional<Compatible<Scalar<values[key]>>>
156
+ : Overrides<values[key]>
157
+ }
158
+
159
+ type Conditional<scalar> =
160
+ | scalar
161
+ | {
162
+ readonly default: Conditional<scalar>
163
+ readonly [query: `@media ${string}`]: Conditional<scalar>
164
+ }
165
+ type Compatible<scalar> = [scalar] extends [Literal.Color]
166
+ ?
167
+ | Literal.Color
168
+ | Token.Reference<'color'>
169
+ | {
170
+ readonly light: Literal.Color | Token.Reference<'color'>
171
+ readonly dark: Literal.Color | Token.Reference<'color'>
172
+ }
173
+ : [scalar] extends [Literal.Length]
174
+ ? Literal.Length | Token.Reference<'spacing'>
175
+ : [scalar] extends [number]
176
+ ? number | Token.Reference<'number'>
177
+ : string | Token.Reference<'string'>
178
+
179
+ /** Category names mapped to the CSS properties that accept their shorthand tokens. */
180
+ export type Mappings = Readonly<
181
+ Record<string, readonly (keyof Literal.Properties)[]>
182
+ >
183
+
184
+ /** Type carrier for configured shorthand lookup. */
185
+ export type Mapped<values, mappings> = (Pick<
186
+ values,
187
+ keyof values &
188
+ ('breakpoints' | 'containers' | 'containerNames' | 'typography')
189
+ > extends infer metadata extends Theme.Tokens
190
+ ? metadata
191
+ : {}) & {
192
+ readonly color?: undefined
193
+ readonly '~vars': {
194
+ readonly values: values
195
+ readonly mappings: mappings
196
+ }
197
+ }
198
+
199
+ /** Reads the values declared by a reusable definition or inline set. */
200
+ export type Extract<input> = input extends { readonly [shape]: infer values }
201
+ ? values
202
+ : input
203
+
204
+ /** Invalid variable data with the offending path. */
205
+ export class InvalidError extends Error {
206
+ /** Creates a diagnostic for invalid data at the supplied path. */
207
+ constructor(
208
+ readonly path: readonly string[],
209
+ message: string,
210
+ ) {
211
+ super(`${JSON.stringify(path)}: ${message}`)
212
+ }
213
+ /** Stable diagnostic name. */
214
+ override name = 'Vars.InvalidError'
215
+ }
216
+
217
+ type Validated<
218
+ value,
219
+ typography extends boolean = false,
220
+ root extends boolean = false,
221
+ > = Values extends value
222
+ ? value
223
+ : value extends readonly string[]
224
+ ? never
225
+ : value extends Token.Reference
226
+ ? value
227
+ : value extends string | number
228
+ ? Literal.Checked<value>
229
+ : root extends true
230
+ ? {
231
+ readonly [key in keyof value]: key extends 'containerNames'
232
+ ? value[key] extends readonly string[]
233
+ ? value[key]
234
+ : never
235
+ : key extends
236
+ | `${string}.${string}`
237
+ | `${string}!${string}`
238
+ | `@${string}`
239
+ | ''
240
+ ? never
241
+ : Validated<
242
+ value[key],
243
+ key extends 'typography' ? true : false
244
+ >
245
+ }
246
+ : value extends { default: infer base }
247
+ ? Conditional<Compatible<Scalar<base>>> &
248
+ Record<
249
+ Exclude<keyof value, 'default' | `@media ${string}`>,
250
+ never
251
+ >
252
+ : value extends { light: unknown; dark: unknown }
253
+ ? Pair<value>
254
+ : keyof value extends 'light' | 'dark'
255
+ ? Pair<value>
256
+ : {
257
+ readonly [key in keyof value]: key extends
258
+ | `${string}.${string}`
259
+ | `${string}!${string}`
260
+ | `@${string}`
261
+ | ''
262
+ ? typography extends true
263
+ ? key extends Typography.Condition
264
+ ? Validated<value[key], true>
265
+ : never
266
+ : never
267
+ : Validated<
268
+ value[key],
269
+ key extends 'typography' ? true : typography
270
+ >
271
+ }
272
+
273
+ /** Applies a compatible variable set and optional color scheme to a scope. */
274
+ export type Selector<
275
+ name extends string,
276
+ output extends style.Output = 'react',
277
+ > = {
278
+ <
279
+ const selection extends {
280
+ readonly set?: name | undefined
281
+ readonly colorScheme?: 'light' | 'dark' | 'light dark' | undefined
282
+ } = {},
283
+ >(
284
+ options?: selection &
285
+ Record<Exclude<keyof selection, 'set' | 'colorScheme'>, never>,
286
+ ): style.Props<output>
287
+ }
288
+
289
+ type Pair<value> = {
290
+ readonly light: Literal.Color | Token.Reference<'color'>
291
+ readonly dark: Literal.Color | Token.Reference<'color'>
292
+ } & Record<Exclude<keyof value, 'light' | 'dark'>, never>
293
+
294
+ /** Configured references and a selector for compatible scopes. */
295
+ export type Bound<
296
+ values extends Values,
297
+ name extends string = never,
298
+ output extends style.Output = 'react',
299
+ > = Definition<values> & Selector<name, output>
@@ -13,7 +13,7 @@ import type * as Ast from '@oxc-project/types'
13
13
  import * as Parser from 'oxc-parser'
14
14
  import * as Syntax from './internal/Syntax.js'
15
15
  import * as Walker from 'oxc-walker'
16
- import type * as Theme from '../Theme.js'
16
+ import type * as Theme from '../internal/Theme.js'
17
17
  import * as Token from '../internal/Token.js'
18
18
  import * as Contract from './internal/Contract.js'
19
19
  import * as Relative from './internal/Relative.js'
@@ -135,7 +135,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
135
135
  Object.keys(options.native ?? {}).length ||
136
136
  Object.entries(cache?.native ?? {}).some(([key, value]) => {
137
137
  const next = Reflect.get(options.native ?? {}, key)
138
- if (key !== 'fonts' && key !== 'themes' && key !== 'units')
138
+ if (key !== 'fonts' && key !== 'vars' && key !== 'units')
139
139
  return value !== next
140
140
 
141
141
  return (
@@ -961,7 +961,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
961
961
  source: options.modules[moduleId]!,
962
962
  }
963
963
 
964
- Object.assign(themes, result.themes)
964
+ Object.assign(themes, result.vars)
965
965
  visiting.delete(moduleId)
966
966
 
967
967
  return result
@@ -1060,7 +1060,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1060
1060
  native: {
1061
1061
  ...options.native,
1062
1062
  ...(options.native.fonts && { fonts: { ...options.native.fonts } }),
1063
- ...(options.native.themes && { themes: { ...options.native.themes } }),
1063
+ ...(options.native.vars && { vars: { ...options.native.vars } }),
1064
1064
  ...(options.native.units && { units: { ...options.native.units } }),
1065
1065
  },
1066
1066
  resolutions: Object.freeze(resolutions),
@@ -1121,7 +1121,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1121
1121
  ? ''
1122
1122
  : (Css.compile({
1123
1123
  styles: { styles: [] },
1124
- themes: sharedThemes,
1124
+ vars: sharedThemes,
1125
1125
  contributions: [contribution],
1126
1126
  }).contributionCss ?? ''),
1127
1127
  layers: contribution.kind === 'layers' ? [contribution.names] : [],
@@ -1345,7 +1345,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1345
1345
  )
1346
1346
  identities.set(name, signature)
1347
1347
  }
1348
- for (const [name, theme] of Object.entries(module.themes)) {
1348
+ for (const [name, theme] of Object.entries(module.vars)) {
1349
1349
  const data = theme[Token.definition]
1350
1350
  if (data.contract[Token.identity]?.startsWith('id-'))
1351
1351
  register(`theme:${name}`, JSON.stringify(data.values))
@@ -1403,7 +1403,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1403
1403
  [Themes.context]: {
1404
1404
  extracted: Object.freeze({
1405
1405
  ...extracted.get(moduleId)!,
1406
- themes: sharedThemes,
1406
+ vars: sharedThemes,
1407
1407
  contributions: undefined,
1408
1408
  }),
1409
1409
  links: {},
@@ -1435,7 +1435,12 @@ function build(options: compile.Options, cache?: Cache): Cache {
1435
1435
  }
1436
1436
 
1437
1437
  for (const call of extracted.get(moduleId)!.calls)
1438
- if (call.identity)
1438
+ if (
1439
+ call.identity &&
1440
+ !call.composition &&
1441
+ !call.runtimeComposition &&
1442
+ !call.compositionCase
1443
+ )
1439
1444
  styleClasses[call.identity] = modules[moduleId]!.classes[call.name]!
1440
1445
  }
1441
1446
 
@@ -1581,6 +1586,6 @@ function nativeOutput(
1581
1586
  get map() {
1582
1587
  return (sourceMap ??= JSON.parse(output.map) as Mapping.EncodedSourceMap)
1583
1588
  },
1584
- themes: Object.freeze({}),
1589
+ vars: Object.freeze({}),
1585
1590
  })
1586
1591
  }