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
@@ -13,7 +13,7 @@ import * as Walker from 'oxc-walker'
13
13
 
14
14
  /**
15
15
  * Compiles local style and variants calls for an explicit native context.
16
- * @param options - Shared source, destination mappings, and selected theme/scheme.
16
+ * @param options - Shared source, destination mappings, and selected set/scheme.
17
17
  * @returns Native callables, source map, and static recipe tables.
18
18
  * @throws {Source.ExtractError} For invalid source authoring.
19
19
  * @throws {CompileError} For native features outside the static source boundary.
@@ -38,7 +38,7 @@ export function compile(options: compile.Options): compile.ReturnType {
38
38
  (extracted.themeAppearances?.length || extracted.themeScripts?.length))
39
39
  )
40
40
  throw new CompileError(
41
- 'Native static modules do not support CSS contributions, variables, or web theme controls.',
41
+ 'Native static modules do not support CSS contributions, variables, or web set controls.',
42
42
  )
43
43
  const parsed = options[Themes.context]?.parsed ?? Syntax.parse(options)
44
44
  const names = new Set(options[Themes.context]?.identifiers)
@@ -93,10 +93,7 @@ export function compile(options: compile.Options): compile.ReturnType {
93
93
 
94
94
  const staticTables = new Map<Source.Call, Variants.Definition>()
95
95
  if (options.contextual) {
96
- const groups = new Map<
97
- StyleSheet.compile.Options['themes'],
98
- Source.Call[]
99
- >()
96
+ const groups = new Map<StyleSheet.compile.Options['vars'], Source.Call[]>()
100
97
  for (const call of extracted.calls) {
101
98
  if (
102
99
  call.recipe ||
@@ -106,12 +103,12 @@ export function compile(options: compile.Options): compile.ReturnType {
106
103
  call.output === 'html'
107
104
  )
108
105
  continue
109
- const themes = call.nativeContext?.themes ?? options.themes
110
- const group = groups.get(themes)
106
+ const vars = call.nativeContext?.vars ?? options.vars
107
+ const group = groups.get(vars)
111
108
  if (group) group.push(call)
112
- else groups.set(themes, [call])
109
+ else groups.set(vars, [call])
113
110
  }
114
- for (const [themes, calls] of groups) {
111
+ for (const [vars, calls] of groups) {
115
112
  if (calls.length < 2) continue
116
113
  try {
117
114
  const compiled = StyleSheet.compile({
@@ -126,13 +123,13 @@ export function compile(options: compile.Options): compile.ReturnType {
126
123
  })),
127
124
  })),
128
125
  },
129
- themes,
126
+ vars,
130
127
  units: options.units,
131
128
  })
132
129
  for (const call of calls) {
133
130
  const styles = Object.fromEntries(
134
- Object.entries(compiled.styles).map(([theme, schemes]) => [
135
- theme,
131
+ Object.entries(compiled.styles).map(([set, schemes]) => [
132
+ set,
136
133
  Object.freeze({
137
134
  light: Object.freeze({ '0': schemes.light[call.name]! }),
138
135
  dark: Object.freeze({ '0': schemes.dark[call.name]! }),
@@ -237,32 +234,32 @@ export function compile(options: compile.Options): compile.ReturnType {
237
234
  bindings?: ReturnType<typeof NativeBindings.prepare>,
238
235
  ): string {
239
236
  if (contextOptions.contextual) {
240
- const themes = call?.nativeContext?.themes ?? contextOptions.themes
237
+ const vars = call?.nativeContext?.vars ?? contextOptions.vars
241
238
  if (!call?.slots && !call?.recipe?.payloads?.length)
242
239
  compiled ??= Variants.compile({
243
240
  recipe,
244
241
  fonts: contextOptions.fonts,
245
242
  platform: contextOptions.platform,
246
- themes,
243
+ vars,
247
244
  units: contextOptions.units,
248
245
  })
249
246
  else {
250
247
  try {
251
248
  bindings = NativeBindings.prepare(recipe, call!, {
252
249
  ...contextOptions,
253
- themes,
250
+ vars,
254
251
  })
255
252
  } catch (error) {
256
253
  if (error instanceof StyleSheet.CompileError) throw error
257
254
  throw new CompileError((error as Error).message)
258
255
  }
259
256
  }
260
- const defaultTheme =
261
- call?.nativeContext?.defaultTheme ?? contextOptions.theme ?? 'default'
257
+ const defaultVars =
258
+ call?.nativeContext?.defaultVars ?? contextOptions.set ?? 'default'
262
259
  const tables = new Map<string, string>()
263
- const alternatives = (themes ? Object.keys(themes) : ['default']).map(
264
- (theme) => ({
265
- theme,
260
+ const alternatives = (vars ? Object.keys(vars) : ['default']).map(
261
+ (set) => ({
262
+ set,
266
263
  schemes: (['light', 'dark'] as const).map((colorScheme) => {
267
264
  const value = callable(
268
265
  recipe,
@@ -271,8 +268,8 @@ export function compile(options: compile.Options): compile.ReturnType {
271
268
  {
272
269
  ...contextOptions,
273
270
  contextual: false,
274
- themes,
275
- theme,
271
+ vars,
272
+ set,
276
273
  colorScheme,
277
274
  },
278
275
  compiled,
@@ -285,8 +282,8 @@ export function compile(options: compile.Options): compile.ReturnType {
285
282
  }),
286
283
  )
287
284
  const entries = alternatives.map(
288
- ({ theme, schemes }) =>
289
- `${JSON.stringify(theme)}:{${schemes.map(({ colorScheme, value }) => `${JSON.stringify(colorScheme)}:${tables.get(value)}`).join(',')}}`,
285
+ ({ set, schemes }) =>
286
+ `${JSON.stringify(set)}:{${schemes.map(({ colorScheme, value }) => `${JSON.stringify(colorScheme)}:${tables.get(value)}`).join(',')}}`,
290
287
  )
291
288
  const parameters = [...tables.values()].map((name, index) =>
292
289
  typed ? `${name}:T${index}` : name,
@@ -294,7 +291,7 @@ export function compile(options: compile.Options): compile.ReturnType {
294
291
  const types = typed
295
292
  ? `<${parameters.map((_, index) => `const T${index} extends (input:never)=>import('zyzz/runtime').Native.Props<object>`).join(',')},>`
296
293
  : ''
297
- const expression = `${types}(${parameters.join(',')})=>${helper}Context.create({${entries.join(',')}},${JSON.stringify(defaultTheme)})`
294
+ const expression = `${types}(${parameters.join(',')})=>${helper}Context.create({${entries.join(',')}},${JSON.stringify(defaultVars)})`
298
295
  let context = contexts.get(expression)
299
296
  if (!context) {
300
297
  context = `${helper}ContextFactory${contexts.size}`
@@ -351,12 +348,12 @@ export function compile(options: compile.Options): compile.ReturnType {
351
348
  recipe,
352
349
  fonts: contextOptions.fonts,
353
350
  platform: contextOptions.platform,
354
- themes: contextOptions.themes,
351
+ vars: contextOptions.vars,
355
352
  units: contextOptions.units,
356
353
  })
357
354
  recipes[name] = compiled
358
355
  const styles = StyleSheet.select(compiled.styles, {
359
- theme: contextOptions.theme ?? 'default',
356
+ set: contextOptions.set ?? 'default',
360
357
  colorScheme: contextOptions.colorScheme,
361
358
  })
362
359
  const cached = compiledCalls.get(compiled)
@@ -743,7 +740,7 @@ export declare namespace compile {
743
740
  readonly [Edits.runtime]?: boolean | undefined
744
741
  /** Compiler-owned graph context. */
745
742
  readonly [Themes.context]?: Themes.Context | undefined
746
- /** Retain every theme and scheme for render-local selection. */
743
+ /** Retain every set and scheme for render-local selection. */
747
744
  readonly contextual?: boolean | undefined
748
745
  /** Scheme compiled into this module's callables. Recompile to select another scheme. */
749
746
  readonly colorScheme: StyleSheet.ColorScheme
@@ -751,8 +748,8 @@ export declare namespace compile {
751
748
  readonly moduleId: string
752
749
  /** Shared local style and variants authoring. */
753
750
  readonly source: string
754
- /** Label selected from supplied themes. Defaults to the token-fallback default table. */
755
- readonly theme?: string | undefined
751
+ /** Label selected from supplied vars. Defaults to the token-fallback default table. */
752
+ readonly set?: string | undefined
756
753
  }
757
754
  /** Executable source with immutable recipe tables and authored source mappings. */
758
755
  type ReturnType = {
@@ -762,7 +759,7 @@ export declare namespace compile {
762
759
  readonly code: string
763
760
  /** Version-three source map encoded as JSON. */
764
761
  readonly map: string
765
- /** All theme/scheme tables for each extracted definition. */
762
+ /** All set/scheme tables for each extracted definition. */
766
763
  readonly recipes: Readonly<Record<string, Variants.Definition>>
767
764
  }
768
765
  }
@@ -27,13 +27,13 @@ import * as Scope from './internal/Scope.js'
27
27
  import type * as Shorthands from '../internal/Shorthands.js'
28
28
  import * as Static from './internal/Static.js'
29
29
  import * as Style from '../Style.js'
30
- import type * as Theme from '../Theme.js'
30
+ import type * as Theme from '../internal/Theme.js'
31
31
  import * as Themes from './internal/Themes.js'
32
32
  import * as ThemeValues from '../web/internal/Themes.js'
33
33
  import * as Token from '../internal/Token.js'
34
34
  import * as Typography from '../internal/Typography.js'
35
35
  import * as Value from '../internal/Value.js'
36
- import * as Variables from './internal/Variables.js'
36
+ import * as Vars from './internal/Vars.js'
37
37
  import * as Walker from 'oxc-walker'
38
38
 
39
39
  // JavaScript extraction supplies untyped values. Keep structural checks without
@@ -49,9 +49,9 @@ export type Call = {
49
49
  readonly nativeContext?:
50
50
  | {
51
51
  /** Default label selected when the provider omits its theme. */
52
- readonly defaultTheme: string
52
+ readonly defaultVars: string
53
53
  /** Compatible alternatives from the owning configuration. */
54
- readonly themes: Readonly<Record<string, Theme.Definition>>
54
+ readonly vars: Readonly<Record<string, Theme.Definition>>
55
55
  }
56
56
  | undefined
57
57
  /** Class identity available without source rewriting. */
@@ -101,6 +101,8 @@ export type Call = {
101
101
  readonly shorthands?: Shorthands.Map | undefined
102
102
  /** Emitted typography field counts keyed by authored property offsets. */
103
103
  readonly typography?: ReadonlyMap<number, number> | undefined
104
+ /** Emitted typography query counts keyed by authored property offsets. */
105
+ readonly typographyQueries?: ReadonlyMap<number, number> | undefined
104
106
  /** Native HTML attribute output selected by the bound configuration. */
105
107
  readonly output?: 'html' | undefined
106
108
  /** Typed runtime slots for callback definitions. */
@@ -178,6 +180,27 @@ export function extract(options: extract.Options): extract.ReturnType {
178
180
 
179
181
  const namespace = identity(options.moduleId)
180
182
  const parsed = options[Themes.context]?.parsed ?? Syntax.parse(options)
183
+ for (const node of parsed.program.body) {
184
+ if (node.type !== 'ImportDeclaration' || node.source.value !== 'zyzz')
185
+ continue
186
+ for (const specifier of node.specifiers) {
187
+ if (specifier.type !== 'ImportSpecifier') continue
188
+ const name =
189
+ specifier.imported.type === 'Identifier'
190
+ ? specifier.imported.name
191
+ : specifier.imported.value
192
+ if (name === 'Theme' || name === 'Variables')
193
+ throw new ExtractError([
194
+ {
195
+ code: 'unsupported_syntax',
196
+ message: `Import Vars instead of ${name}.`,
197
+ source: options.moduleId,
198
+ start: specifier.start,
199
+ end: specifier.end,
200
+ },
201
+ ])
202
+ }
203
+ }
181
204
 
182
205
  if (parsed.errors.length) {
183
206
  for (const error of parsed.errors) {
@@ -220,7 +243,7 @@ export function extract(options: extract.Options): extract.ReturnType {
220
243
 
221
244
  const variables = (() => {
222
245
  try {
223
- return Variables.collect(
246
+ return Vars.collect(
224
247
  program,
225
248
  namespace,
226
249
  scopeTracker,
@@ -294,7 +317,7 @@ export function extract(options: extract.Options): extract.ReturnType {
294
317
 
295
318
  const binding =
296
319
  node.type === 'Identifier'
297
- ? declaration ?? null
320
+ ? (declaration ?? null)
298
321
  : scopeTracker.getDeclaration(node.name)
299
322
 
300
323
  contributions.read(node, parent, binding)
@@ -348,6 +371,7 @@ export function extract(options: extract.Options): extract.ReturnType {
348
371
  name === 'cx' ||
349
372
  name === 'style' ||
350
373
  name === 'Theme' ||
374
+ name === 'Vars' ||
351
375
  name === 'variable' ||
352
376
  name === 'variants'
353
377
  )
@@ -645,6 +669,7 @@ export function extract(options: extract.Options): extract.ReturnType {
645
669
  const name = `style-${namespace}-${call.start}`
646
670
  const locations: Style.SourceLocation[] = []
647
671
  const typography = new Map<number, number>()
672
+ const typographyQueries = new Map<number, number>()
648
673
  const conditionKeys = new Map<string, Ast.Node>()
649
674
 
650
675
  function object(
@@ -695,7 +720,7 @@ export function extract(options: extract.Options): extract.ReturnType {
695
720
  ? entry.key.value
696
721
  : undefined
697
722
  : undefined
698
- if (key !== 'selectors' && key !== 'variables') {
723
+ if (key !== 'selectors' && key !== 'vars') {
699
724
  properties.push(entry)
700
725
  continue
701
726
  }
@@ -984,11 +1009,17 @@ export function extract(options: extract.Options): extract.ReturnType {
984
1009
  !(Binding.is(part)
985
1010
  ? (dynamicValues !== undefined &&
986
1011
  Object.values(dynamicValues.slots).includes(part)) ||
987
- targets.every((target) =>
988
- Binding.accepts(part.type, target),
1012
+ targets.every(
1013
+ (target) =>
1014
+ Binding.accepts(part.type, target) ||
1015
+ (part.type === 'color' &&
1016
+ Expression.acceptsColor(template, target)),
989
1017
  )
990
- : targets.every((target) =>
991
- Token.accepts(part.group, target),
1018
+ : targets.every(
1019
+ (target) =>
1020
+ Token.acceptsReference(part, target) ||
1021
+ (part.group === 'color' &&
1022
+ Expression.acceptsColor(template, target)),
992
1023
  ))
993
1024
  ) {
994
1025
  report(
@@ -1008,7 +1039,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1008
1039
  reference &&
1009
1040
  Token.is(reference) &&
1010
1041
  !targets.every((target) =>
1011
- Token.accepts(reference.group, target),
1042
+ Token.acceptsReference(reference, target),
1012
1043
  ) &&
1013
1044
  !targets.every((target) =>
1014
1045
  dynamicValues?.accepts(
@@ -1113,10 +1144,12 @@ export function extract(options: extract.Options): extract.ReturnType {
1113
1144
  Object.keys(values).flatMap((key) => mappings?.[key] ?? [key]),
1114
1145
  )
1115
1146
  const parsed = Value.parse(values.typography, 'fontFamily')
1116
- const count = Typography.fields(
1147
+ const keys = Typography.keys(
1117
1148
  theme,
1118
1149
  parsed && !('invalid' in parsed) ? parsed.value : values.typography,
1119
- ).filter((field) => !explicit.has(field)).length
1150
+ explicit,
1151
+ )
1152
+ const queries = keys.filter(Typography.condition).length
1120
1153
  for (const property of properties) {
1121
1154
  if (property.type !== 'Property') continue
1122
1155
  const key =
@@ -1125,7 +1158,10 @@ export function extract(options: extract.Options): extract.ReturnType {
1125
1158
  : property.key.type === 'Literal'
1126
1159
  ? property.key.value
1127
1160
  : undefined
1128
- if (key === 'typography') typography.set(property.start, count)
1161
+ if (key === 'typography') {
1162
+ typography.set(property.start, keys.length - queries)
1163
+ if (queries) typographyQueries.set(property.start, queries)
1164
+ }
1129
1165
  }
1130
1166
  }
1131
1167
 
@@ -1138,7 +1174,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1138
1174
  try {
1139
1175
  const definition = define(
1140
1176
  { [name]: values },
1141
- { locations, theme: themes?.styles.get(call.start)?.theme },
1177
+ { locations, vars: themes?.styles.get(call.start)?.theme },
1142
1178
  )
1143
1179
 
1144
1180
  function validate(style: Style.NamedStyle, path: readonly string[]) {
@@ -1194,7 +1230,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1194
1230
  matches,
1195
1231
  value: define(
1196
1232
  { [`${name}-${index}`]: object(value) },
1197
- { locations, theme: themes?.styles.get(call.start)?.theme },
1233
+ { locations, vars: themes?.styles.get(call.start)?.theme },
1198
1234
  ),
1199
1235
  })),
1200
1236
  }
@@ -1214,6 +1250,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1214
1250
  : {}),
1215
1251
  ...(shorthands ? { shorthands } : {}),
1216
1252
  ...(typography.size ? { typography } : {}),
1253
+ ...(typographyQueries.size ? { typographyQueries } : {}),
1217
1254
  ...(themes?.styles.get(call.start)?.output
1218
1255
  ? { output: 'html' as const }
1219
1256
  : {}),
@@ -1268,6 +1305,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1268
1305
  identity: namespace,
1269
1306
  links: options[Themes.context]?.links,
1270
1307
  program,
1308
+ scopes: themes?.scopeApplications,
1271
1309
  source: options.source,
1272
1310
  styles,
1273
1311
  })) {
@@ -1344,7 +1382,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1344
1382
  const rendered = Css.compile({
1345
1383
  styles: { styles: [] },
1346
1384
  contributions: contributionData,
1347
- themes: themes?.themes,
1385
+ vars: themes?.themes,
1348
1386
  }).css
1349
1387
  AtRules.transform({
1350
1388
  filename: options.moduleId,
@@ -1482,7 +1520,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1482
1520
  }
1483
1521
  : {}),
1484
1522
  themeReferences: Object.freeze(themes?.references ?? []),
1485
- themes: themes?.themes ?? Object.freeze({}),
1523
+ vars: themes?.themes ?? Object.freeze({}),
1486
1524
  })
1487
1525
  }
1488
1526
 
@@ -1514,7 +1552,7 @@ export declare namespace extract {
1514
1552
  readonly contributions?: readonly Css.Contribution[] | undefined
1515
1553
  readonly contributionCalls?: readonly Contributions.Call[] | undefined
1516
1554
  /** Explicit variable contracts replaced by fixed slot data. */
1517
- readonly variableCalls?: readonly Variables.Call[] | undefined
1555
+ readonly variableCalls?: readonly Vars.Call[] | undefined
1518
1556
  /** Direct calls in source order. */
1519
1557
  readonly calls: readonly Call[]
1520
1558
  /** Validated definitions accepted by Css.compile. */
@@ -1541,7 +1579,7 @@ export declare namespace extract {
1541
1579
  /** Resolved authoring exports when extracted as part of a source graph. */
1542
1580
  readonly themeExports?: Readonly<Record<string, Themes.Link>> | undefined
1543
1581
  /** Stable scope keys and validated local theme definitions. */
1544
- readonly themes: Readonly<Record<string, Theme.Definition>>
1582
+ readonly vars: Readonly<Record<string, Theme.Definition>>
1545
1583
  }
1546
1584
  }
1547
1585
 
@@ -43,7 +43,7 @@ export function compile(options: compile.Options): compile.ReturnType {
43
43
  )
44
44
  portableNames[call.name] = call.portable
45
45
  }
46
- for (const [name, theme] of Object.entries(extracted.themes))
46
+ for (const [name, theme] of Object.entries(extracted.vars))
47
47
  if (
48
48
  (Object.keys(theme[Token.definition].values).length ||
49
49
  extracted.themeCalls.some(
@@ -57,7 +57,7 @@ export function compile(options: compile.Options): compile.ReturnType {
57
57
  !theme[Token.definition].contract[Token.identity]?.startsWith('id-')
58
58
  )
59
59
  throw new Error(
60
- 'CSS-only themes require an explicit id on Config.create or Theme.define.',
60
+ 'CSS-only themes require an explicit id on Config.create or Vars.define.',
61
61
  )
62
62
  for (const call of extracted.contributionCalls ?? [])
63
63
  if (
@@ -138,7 +138,9 @@ export function compile(options: compile.Options): compile.ReturnType {
138
138
  ? property.key.name
139
139
  : property.key.type === 'Literal'
140
140
  ? property.key.value
141
- : undefined) !== 'themes',
141
+ : undefined) !== 'themes' &&
142
+ (property.key.type !== 'Identifier' ||
143
+ property.key.name !== 'variables'),
142
144
  )
143
145
  )
144
146
  unusedSelections.add(Expression.unwrap(node.init).start)
@@ -215,7 +217,7 @@ export function compile(options: compile.Options): compile.ReturnType {
215
217
  }
216
218
  })(),
217
219
  contributions: extracted.contributions,
218
- themes: Object.keys(extracted.themes).length ? extracted.themes : undefined,
220
+ vars: Object.keys(extracted.vars).length ? extracted.vars : undefined,
219
221
  })
220
222
 
221
223
  let runtime = '__zyzzProps'
@@ -461,7 +463,7 @@ export function compile(options: compile.Options): compile.ReturnType {
461
463
  .join(',')
462
464
 
463
465
  const className = JSON.stringify(classes[call.name])
464
- const value = `(input${typed ? `:Parameters<${type}>[0]` : ''})=>{${reads}const external=input.className;const style=input.style;return {className:external?${className}+" "+external:${className},style:{...input.variables,...style,${assignments}}}}`
466
+ const value = `(input${typed ? `:Parameters<${type}>[0]` : ''})=>{${reads}const external=input.className;const style=input.style;return {className:external?${className}+" "+external:${className},style:{...input.vars,...style,${assignments}}}}`
465
467
  const result = composeHtml
466
468
  ? `${compositionHtml}.bind(${value})`
467
469
  : call.output === 'html'
@@ -540,11 +542,12 @@ export function compile(options: compile.Options): compile.ReturnType {
540
542
  }
541
543
 
542
544
  for (const call of extracted.themeCalls) {
543
- const scope = (name: string) => ({ className: emitted.themes[name] })
545
+ const scope = (name: string) => ({ className: emitted.vars[name] })
544
546
 
545
547
  const props = (() => {
548
+ if (call.variableSet) return '{}'
546
549
  if (!call.members)
547
- return `{className:${JSON.stringify(emitted.themes[call.name])}}`
550
+ return `{className:${JSON.stringify(emitted.vars[call.name])}}`
548
551
 
549
552
  const script = extracted.themeScripts?.includes(call.name)
550
553
  const root = extracted.themeAppearances?.includes(call.name)
@@ -559,19 +562,48 @@ export function compile(options: compile.Options): compile.ReturnType {
559
562
  : ''
560
563
  const rootOptions =
561
564
  storage || defaultTheme
562
- ? `,${JSON.stringify({ ...(defaultTheme ? { defaultTheme } : {}), ...(storage ? { storageKey: storage } : {}) })}`
565
+ ? `,${JSON.stringify({ ...(defaultTheme ? { defaultVars: defaultTheme } : {}), ...(storage ? { storageKey: storage } : {}) })}`
563
566
  : ''
564
567
 
565
568
  return `${root ? `appearance:${appearance}.root(${entries}${rootOptions}),` : ''}${script ? `script:${appearance}.create(${entries}${scriptOptions}),` : ''}`
566
569
  }
567
570
 
571
+ if (call.variableConfig) {
572
+ const selected =
573
+ extracted.themeSelections?.includes(call.name) ||
574
+ Object.values(extracted.themeExports ?? {}).some(
575
+ (link) =>
576
+ link.call.name === call.name &&
577
+ link.kind === 'config' &&
578
+ !link.call.initialization &&
579
+ !link.call.root,
580
+ )
581
+ const entries = call.options?.themes
582
+ ? Object.entries(call.members)
583
+ .filter(([key]) => {
584
+ const path = JSON.parse(key) as string[]
585
+ return path[0] === 'themes' && path.length === 2
586
+ })
587
+ .map(([key, name]) => [
588
+ (JSON.parse(key) as string[])[1],
589
+ emitted.vars[name],
590
+ ])
591
+ : [['default', emitted.vars[call.name]]]
592
+ const fallback = call.options?.defaultTheme ?? 'default'
593
+ if (!selected)
594
+ return `{${helpers(JSON.stringify(call.options?.themes ? entries : []), call.options?.themes ? String(fallback) : undefined).replace(/,$/, '')}}`
595
+ usesSelection = true
596
+ const selector = `${selection}.create(${JSON.stringify(entries)},${call.options?.output === 'html'},'set',${JSON.stringify(fallback)})`
597
+ return `{${helpers(JSON.stringify(call.options?.themes ? entries : []), call.options?.themes ? String(fallback) : undefined)}vars:/*#__PURE__*/${selector}}`
598
+ }
599
+
568
600
  if (call.options?.themes) {
569
601
  const catalog = Object.fromEntries(
570
602
  Object.entries(call.members)
571
603
  .filter(([key]) => (JSON.parse(key) as string[]).length === 2)
572
604
  .map(([key, name]) => [
573
605
  (JSON.parse(key) as string[])[1]!,
574
- emitted.themes[name],
606
+ emitted.vars[name],
575
607
  ]),
576
608
  )
577
609
 
@@ -595,7 +627,7 @@ export function compile(options: compile.Options): compile.ReturnType {
595
627
  })()
596
628
 
597
629
  const assertion = /\.[cm]?tsx?$/.test(options.moduleId)
598
- ? ` as ${call.type ?? `import('zyzz').Theme.Definition<${call.tokenType}>`}`
630
+ ? ` as ${call.type ?? `import('zyzz').Vars.Definition<${call.tokenType}>`}`
599
631
  : ''
600
632
 
601
633
  module.overwrite(call.start, call.end, `(${props}${assertion})`)
@@ -607,7 +639,7 @@ export function compile(options: compile.Options): compile.ReturnType {
607
639
  module.overwrite(
608
640
  alias.start,
609
641
  alias.end,
610
- `(${options.source.slice(alias.start, alias.end)} as ${alias.type ?? `import('zyzz').Theme.Definition<${alias.tokenType}>`})`,
642
+ `(${options.source.slice(alias.start, alias.end)} as ${alias.type ?? `import('zyzz').Vars.Definition<${alias.tokenType}>`})`,
611
643
  )
612
644
 
613
645
  continue
@@ -619,7 +651,7 @@ export function compile(options: compile.Options): compile.ReturnType {
619
651
  ? `{${members.map((member) => `${member}:undefined`).join(',')}}`
620
652
  : 'undefined'
621
653
  const type =
622
- alias.type ?? `import('zyzz').Theme.Definition<${alias.tokenType}>`
654
+ alias.type ?? `import('zyzz').Vars.Definition<${alias.tokenType}>`
623
655
  const assertion = /\.[cm]?tsx?$/.test(options.moduleId)
624
656
  ? ` as unknown as ${alias.destructured ? `{${members.map((member) => `readonly ${member}:${type}['${member}']`).join(';')}}` : `${type}['${member}']`}`
625
657
  : ''
@@ -667,7 +699,7 @@ export function compile(options: compile.Options): compile.ReturnType {
667
699
  module.overwrite(
668
700
  reference.start,
669
701
  reference.end,
670
- JSON.stringify(emitted.themes[reference.name]),
702
+ JSON.stringify(emitted.vars[reference.name]),
671
703
  )
672
704
 
673
705
  replacements.push(
@@ -692,7 +724,7 @@ export function compile(options: compile.Options): compile.ReturnType {
692
724
  specifier.importKind === 'type' ||
693
725
  !(
694
726
  node.source.value === 'zyzz'
695
- ? ['Config', 'cx', 'style', 'Theme', 'variable', 'variants']
727
+ ? ['Config', 'cx', 'style', 'Vars', 'variable', 'variants']
696
728
  : [
697
729
  'Css',
698
730
  'cssFunction',
@@ -830,14 +862,14 @@ export function compile(options: compile.Options): compile.ReturnType {
830
862
  const themeOwners = new Map(
831
863
  extracted.themeCalls.flatMap((call) =>
832
864
  [...new Set([call.name, ...Object.values(call.members ?? {})])].map(
833
- (name) => [emitted.themes[name], { ...call, name }] as const,
865
+ (name) => [emitted.vars[name], { ...call, name }] as const,
834
866
  ),
835
867
  ),
836
868
  )
837
869
 
838
870
  const linkedOwners = new Map(
839
871
  Object.entries(options[Themes.context]?.owners ?? {}).map(
840
- ([key, owner]) => [emitted.themes[key], owner],
872
+ ([key, owner]) => [emitted.vars[key], owner],
841
873
  ),
842
874
  )
843
875
 
@@ -873,9 +905,7 @@ export function compile(options: compile.Options): compile.ReturnType {
873
905
  Css.compile({
874
906
  styles: { styles: [] },
875
907
  contributions: [contribution.definition],
876
- themes: Object.keys(extracted.themes).length
877
- ? extracted.themes
878
- : undefined,
908
+ vars: Object.keys(extracted.vars).length ? extracted.vars : undefined,
879
909
  }).contributionCss ?? ''
880
910
  if (!rendered) continue
881
911
  for (const _ of rendered.split('\n')) {
@@ -933,7 +963,7 @@ export function compile(options: compile.Options): compile.ReturnType {
933
963
  return rule
934
964
  }
935
965
 
936
- if (Object.values(emitted.themes).includes(name)) {
966
+ if (Object.values(emitted.vars).includes(name)) {
937
967
  // Packed theme declarations have no authored source in this graph.
938
968
  Mapping.addMapping(cssMap, { generated: { column: 0, line } })
939
969
 
@@ -947,6 +977,19 @@ export function compile(options: compile.Options): compile.ReturnType {
947
977
  return rule
948
978
  }
949
979
 
980
+ if (
981
+ rule.startsWith(':root{') ||
982
+ rule.startsWith(':where(*){--z-f') ||
983
+ (rule.startsWith('@media ') &&
984
+ (rule.includes(':root{') ||
985
+ Object.values(emitted.vars).some((name) =>
986
+ rule.includes(`.${name}{`),
987
+ )))
988
+ ) {
989
+ Mapping.addMapping(cssMap, { generated: { column: 0, line } })
990
+ return rule
991
+ }
992
+
950
993
  const selector = `.${names.get(name)!}`
951
994
  const call = owners.get(name)!
952
995
 
@@ -995,11 +1038,18 @@ export function compile(options: compile.Options): compile.ReturnType {
995
1038
  ? String(property.key.value)
996
1039
  : ''
997
1040
 
998
- if (key === 'typography' && call.typography?.has(property.start))
1041
+ if (key === 'typography' && call.typography?.has(property.start)) {
1042
+ conditionNodes.push(
1043
+ ...Array.from(
1044
+ { length: call.typographyQueries?.get(property.start) ?? 0 },
1045
+ () => property,
1046
+ ),
1047
+ )
999
1048
  return Array.from(
1000
1049
  { length: call.typography.get(property.start)! },
1001
1050
  () => property,
1002
1051
  )
1052
+ }
1003
1053
 
1004
1054
  const authoredLocations: readonly Ast.Node[] =
1005
1055
  value.type === 'ArrayExpression'
@@ -1111,7 +1161,7 @@ export function compile(options: compile.Options): compile.ReturnType {
1111
1161
  sourcesContent: map.sourcesContent!,
1112
1162
  version: 3 as const,
1113
1163
  },
1114
- themes: emitted.themes,
1164
+ vars: emitted.vars,
1115
1165
  })
1116
1166
  }
1117
1167
 
@@ -1151,7 +1201,7 @@ export declare namespace compile {
1151
1201
  /** Standard rewritten-module map, including original source content. */
1152
1202
  readonly map: Mapping.EncodedSourceMap
1153
1203
  /** Stable scope classes keyed by local module/binding identity. */
1154
- readonly themes: Readonly<Record<string, string>>
1204
+ readonly vars: Readonly<Record<string, string>>
1155
1205
  }
1156
1206
  }
1157
1207