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
@@ -0,0 +1,970 @@
1
+ /**
2
+ * Normalizes explicit configuration into isolated typed authoring contracts.
3
+ * @module
4
+ */
5
+ import * as Appearance from '../runtime/Appearance.js'
6
+ import * as Authoring from './Authoring.js'
7
+ import * as Html from '../runtime/CompositionHtml.js'
8
+ import * as Identity from './Identity.js'
9
+ import type * as Binding from './Binding.js'
10
+ import type * as Condition from './Condition.js'
11
+ import * as Literal from './Literal.js'
12
+ import type { style } from '../styleFunction.js'
13
+ import { variants } from '../variants.js'
14
+ import * as Scheme from './Scheme.js'
15
+ import * as Shorthands from './Shorthands.js'
16
+ import type * as Style from '../Style.js'
17
+ import * as Theme from './Theme.js'
18
+ import * as VariableSets from './VariableSets.js'
19
+ import * as Vars from '../Vars.js'
20
+ import * as Selection from '../runtime/Selection.js'
21
+ import * as Token from './Token.js'
22
+ import type * as Completion from './Completion.js'
23
+
24
+ /** Creates token-free authoring without a configuration file or global state. */
25
+ export function create(): create.ReturnType<{}>
26
+ /**
27
+ * Binds inline or reusable themes to an isolated configuration contract.
28
+ * Named themes require an explicit default and identical token paths/domains.
29
+ * Bound helpers reference extracted CSS; this factory emits no CSS rules.
30
+ * @throws {InvalidError} If options, themes, defaults, or layer names are invalid.
31
+ */
32
+ export function create<const options extends create.Options | VariableOptions>(
33
+ options: options &
34
+ NoInfer<
35
+ options extends VariableOptions
36
+ ? VariableValidation<options>
37
+ : Validated<options>
38
+ >,
39
+ ): options extends VariableOptions
40
+ ? VariableConfig<options>
41
+ : options extends create.Options
42
+ ? create.ReturnType<options>
43
+ : never
44
+ export function create(
45
+ options: create.Options | VariableOptions = {},
46
+ ): unknown {
47
+ let input = record(options)
48
+ const variableMode = input.vars !== undefined
49
+ const variableCatalog = variableMode && input.defaultVars !== undefined
50
+ const variableMappings = VariableSets.mappings(input.mappings)
51
+ if (variableMode) {
52
+ if (
53
+ input.theme !== undefined ||
54
+ input.themes !== undefined ||
55
+ input.defaultTheme !== undefined
56
+ )
57
+ throw new InvalidError('Use vars without theme options.')
58
+ const normalize = (value: unknown) => {
59
+ const definition =
60
+ value &&
61
+ (typeof value === 'object' || typeof value === 'function') &&
62
+ Object.getOwnPropertyDescriptor(value, Token.definition)?.value
63
+ ? (value as Vars.Definition)
64
+ : Vars.define(value as Vars.Values)
65
+ const theme = VariableSets.theme(definition, variableMappings)
66
+ if (variableMappings === false) return theme
67
+ const metadata = theme[Token.definition]
68
+ const names = new Map<string, string>()
69
+ for (const path of Object.keys(metadata.values)) {
70
+ const [category, ...parts] = path.split('.')
71
+ const targets =
72
+ variableMappings?.[category!] ??
73
+ Object.keys(Literal.rules).filter((property) =>
74
+ Token.accepts(
75
+ category as Token.Group,
76
+ property as keyof Literal.Properties,
77
+ ),
78
+ )
79
+ for (const property of targets) {
80
+ const key = `${property}:${parts.join('.')}`
81
+ if (
82
+ names.has(key) &&
83
+ (variableMappings?.[category!] ||
84
+ variableMappings?.[names.get(key)!.split('.')[0]!])
85
+ )
86
+ throw new InvalidError(
87
+ `Ambiguous variable token ${parts.join('.')} for ${property}.`,
88
+ )
89
+ names.set(key, path)
90
+ }
91
+ }
92
+ return theme
93
+ }
94
+ const { vars, defaultVars, mappings: _mappings, ...rest } = input
95
+ input = variableCatalog
96
+ ? {
97
+ ...rest,
98
+ defaultTheme: defaultVars,
99
+ themes: Object.fromEntries(
100
+ Object.entries(record(vars)).map(([name, value]) => [
101
+ name,
102
+ normalize(value),
103
+ ]),
104
+ ),
105
+ }
106
+ : { ...rest, theme: normalize(vars) }
107
+ } else if (input.mappings !== undefined || input.defaultVars !== undefined) {
108
+ throw new InvalidError('mappings and defaultVars require vars.')
109
+ }
110
+ function finish(result: Record<string, unknown>) {
111
+ if (!variableMode) return Object.freeze(result)
112
+ const theme = result.theme as Theme.Definition
113
+ const catalog = result.themes as
114
+ | Record<string, Theme.Definition>
115
+ | undefined
116
+ const entries = () =>
117
+ catalog
118
+ ? Object.entries(catalog).map(
119
+ ([name, value]) => [name, value.className] as const,
120
+ )
121
+ : [['default', theme.className] as const]
122
+ let select: ReturnType<typeof Selection.create> | undefined
123
+ const vars = (
124
+ options: {
125
+ set?: string | undefined
126
+ colorScheme?: string | undefined
127
+ } = {},
128
+ ) =>
129
+ (select ??= Selection.create(
130
+ entries(),
131
+ input.output === 'html',
132
+ 'set',
133
+ variableCatalog ? String(input.defaultTheme) : 'default',
134
+ ))(options)
135
+ return Object.freeze({
136
+ appearance: result.appearance,
137
+ script: result.script,
138
+ style: result.style,
139
+ vars: Object.freeze(
140
+ Object.defineProperties(
141
+ vars,
142
+ Object.getOwnPropertyDescriptors(theme.tokens),
143
+ ),
144
+ ),
145
+ variants: result.variants,
146
+ })
147
+ }
148
+
149
+ for (const key of Object.keys(input))
150
+ if (
151
+ ![
152
+ 'cssOutput',
153
+ 'id',
154
+ 'defaultLayer',
155
+ 'defaultTheme',
156
+ 'layers',
157
+ 'output',
158
+ 'shorthands',
159
+ 'storageKey',
160
+ 'theme',
161
+ 'themes',
162
+ ].includes(key)
163
+ )
164
+ throw new InvalidError(`Unknown configuration option: ${key}`)
165
+
166
+ if (
167
+ input.storageKey !== undefined &&
168
+ (typeof input.storageKey !== 'string' || !input.storageKey)
169
+ )
170
+ throw new InvalidError('storageKey must be a nonempty string.')
171
+
172
+ // Validated above; the record type erases the literal narrowing.
173
+ const storageKey = input.storageKey as string | undefined
174
+
175
+ if (
176
+ input.output !== undefined &&
177
+ input.output !== 'html' &&
178
+ input.output !== 'react'
179
+ )
180
+ throw new InvalidError('output must be html or react.')
181
+
182
+ if (
183
+ input.cssOutput !== undefined &&
184
+ input.cssOutput !== 'atomic' &&
185
+ input.cssOutput !== 'grouped'
186
+ )
187
+ throw new InvalidError('cssOutput must be atomic or grouped.')
188
+
189
+ if (input.theme !== undefined && input.themes !== undefined)
190
+ throw new InvalidError('Use either theme or themes, not both.')
191
+
192
+ if (
193
+ input.defaultLayer !== undefined &&
194
+ typeof input.defaultLayer !== 'string'
195
+ )
196
+ throw new InvalidError('defaultLayer must be a CSS layer name.')
197
+
198
+ if (input.layers !== undefined || input.defaultLayer !== undefined) {
199
+ if (input.layers !== undefined && !Array.isArray(input.layers))
200
+ throw new InvalidError('layers must be an array.')
201
+
202
+ const layers = (input.layers ?? []) as readonly unknown[]
203
+ const seen = new Set<string>()
204
+
205
+ for (const layer of [
206
+ ...layers,
207
+ ...(input.defaultLayer === undefined ||
208
+ layers.includes(input.defaultLayer)
209
+ ? []
210
+ : [input.defaultLayer]),
211
+ ]) {
212
+ if (
213
+ typeof layer !== 'string' ||
214
+ !/^(?:--|-?[_a-zA-Z])[\w-]*(?:\.(?:--|-?[_a-zA-Z])[\w-]*)*$/.test(
215
+ layer,
216
+ ) ||
217
+ layer
218
+ .split('.')
219
+ .some((part) =>
220
+ [
221
+ 'default',
222
+ 'inherit',
223
+ 'initial',
224
+ 'revert',
225
+ 'revert-layer',
226
+ 'unset',
227
+ ].includes(part.toLowerCase()),
228
+ )
229
+ )
230
+ throw new InvalidError(
231
+ 'Layer names must be plain CSS identifiers, optionally dotted.',
232
+ )
233
+
234
+ if (seen.has(layer)) throw new InvalidError(`Duplicate layer: ${layer}`)
235
+
236
+ seen.add(layer)
237
+ }
238
+ }
239
+
240
+ const shorthands = (() => {
241
+ if (input.shorthands === undefined) return undefined
242
+
243
+ try {
244
+ return Shorthands.read(input.shorthands)
245
+ } catch (error) {
246
+ throw new InvalidError((error as Error).message)
247
+ }
248
+ })()
249
+
250
+ const contract = Object.freeze({
251
+ ...(variableMode ? { variableSet: true, mappings: variableMappings } : {}),
252
+ ...(input.defaultLayer !== undefined
253
+ ? { defaultLayer: input.defaultLayer as string }
254
+ : {}),
255
+ cssOutput:
256
+ (input.cssOutput as 'atomic' | 'grouped' | undefined) ?? 'atomic',
257
+ ...(shorthands ? { shorthands } : {}),
258
+ ...(typeof input.id === 'string'
259
+ ? {
260
+ [Token.identity]: Identity.requireId(input.id, 'Config.create'),
261
+ [Token.complete]: true,
262
+ }
263
+ : {}),
264
+ })
265
+ function boundStyle(theme?: Theme.Definition) {
266
+ return (styles?: unknown, options: style.DefinitionOptions = {}) => {
267
+ if (
268
+ theme &&
269
+ Object.keys(theme[Token.definition].values).length &&
270
+ !contract[Token.identity]
271
+ )
272
+ Identity.requireId(undefined, 'Config.create')
273
+ return Authoring.create(styles, {
274
+ ...options,
275
+ theme,
276
+ output: input.output as style.Output | undefined,
277
+ })
278
+ }
279
+ }
280
+ function boundVariants(
281
+ definition: Record<string, unknown>,
282
+ options: style.DefinitionOptions = {},
283
+ ) {
284
+ return Authoring.variants(definition, {
285
+ ...options,
286
+ output: input.output as style.Output | undefined,
287
+ })
288
+ }
289
+ function handle(theme: Theme.Definition, name: string) {
290
+ const original = Token.bind(theme, contract)
291
+ const className = () =>
292
+ `z_theme-${Identity.requireId(typeof input.id === 'string' ? input.id : undefined, 'Config.create')}-${name.replace(/[^a-zA-Z0-9-]/g, (character) => `_${character.charCodeAt(0).toString(16)}_`)}`
293
+ const select = (options: { colorScheme?: string } = {}) => {
294
+ const scheme = options.colorScheme
295
+ const selection =
296
+ scheme !== undefined && Object.hasOwn(Scheme.classes, scheme)
297
+ ? ` ${Scheme.classes[scheme as Scheme.Name]}`
298
+ : ''
299
+ const result = {
300
+ className: `${className()}${selection}`,
301
+ ...(scheme ? { style: { colorScheme: scheme } } : {}),
302
+ }
303
+ return input.output === 'html' ? Html.from(result) : result
304
+ }
305
+ const descriptors = Object.getOwnPropertyDescriptors(original)
306
+ delete (descriptors as Record<string, unknown>).className
307
+ delete (descriptors as Record<string, unknown>).style
308
+ delete (descriptors as Record<string, unknown>).variants
309
+ Object.defineProperties(select, descriptors)
310
+ Object.defineProperty(select, 'className', {
311
+ get: className,
312
+ configurable: true,
313
+ })
314
+ Object.assign(select, {
315
+ style: boundStyle(original),
316
+ variants: boundVariants,
317
+ })
318
+ return select
319
+ }
320
+
321
+ if (input.themes !== undefined) {
322
+ const catalog = record(input.themes)
323
+ if (
324
+ typeof input.defaultTheme !== 'string' ||
325
+ !Object.hasOwn(catalog, input.defaultTheme)
326
+ )
327
+ throw new InvalidError('defaultTheme must name a theme in the catalog.')
328
+
329
+ const defaultTheme = input.defaultTheme
330
+ const definitions = Object.fromEntries(
331
+ Object.entries(catalog).map(([name, value]) => {
332
+ if (!name) throw new InvalidError('Theme names must be nonempty.')
333
+
334
+ return [name, definition(value)]
335
+ }),
336
+ )
337
+
338
+ const base = definitions[input.defaultTheme]!
339
+ const paths = Object.keys(base[Token.definition].values).sort()
340
+
341
+ function queries(theme: Theme.Definition) {
342
+ const data = theme[Token.definition].queries
343
+
344
+ return JSON.stringify({
345
+ breakpoints: Object.keys(data?.breakpoints ?? {}).sort(),
346
+ containers: Object.keys(data?.containers ?? {}).sort(),
347
+ containerNames: [...(data?.containerNames ?? [])].sort(),
348
+ })
349
+ }
350
+
351
+ for (const [name, value] of Object.entries(definitions)) {
352
+ const candidate = Object.keys(value[Token.definition].values).sort()
353
+ if (
354
+ queries(base) !== queries(value) ||
355
+ paths.length !== candidate.length ||
356
+ paths.some(
357
+ (path, index) =>
358
+ path !== candidate[index] ||
359
+ (variableMode &&
360
+ VariableSets.domain(base[Token.definition].values[path]!) !==
361
+ VariableSets.domain(value[Token.definition].values[path]!)),
362
+ )
363
+ )
364
+ throw new InvalidError(
365
+ `Theme ${JSON.stringify(name)} must have the default theme's complete token paths and domains.`,
366
+ )
367
+ }
368
+
369
+ const bound = Object.fromEntries(
370
+ Object.entries(definitions).map(([name, value]) => [
371
+ name,
372
+ handle(value, name),
373
+ ]),
374
+ )
375
+
376
+ const select = (options: { theme: string; colorScheme?: string }) =>
377
+ (bound[options.theme] as (options: { colorScheme?: string }) => unknown)(
378
+ options,
379
+ )
380
+
381
+ Object.defineProperties(select, Object.getOwnPropertyDescriptors(bound))
382
+
383
+ const entries = () =>
384
+ Object.entries(bound).map(([name, value]): readonly [string, string] => [
385
+ name,
386
+ (value as unknown as Theme.Definition).className,
387
+ ])
388
+
389
+ // Class names require an identity, so the compiler's collection pass must
390
+ // not read them; root controls resolve their entries on first use.
391
+ const appearance = ((): Appearance.Root<string> => {
392
+ let root: Appearance.Root<string> | undefined
393
+ const resolve = () =>
394
+ (root ??= Appearance.root(entries(), {
395
+ defaultVars: defaultTheme,
396
+ storageKey,
397
+ }))
398
+
399
+ return {
400
+ get: () => resolve().get(),
401
+ set: (selection) => resolve().set(selection),
402
+ }
403
+ })()
404
+
405
+ return finish({
406
+ appearance,
407
+ script: () => Appearance.create(entries(), { storageKey })(),
408
+ style: boundStyle(
409
+ bound[input.defaultTheme] as unknown as Theme.Definition,
410
+ ),
411
+ theme: bound[input.defaultTheme],
412
+ themes: Object.freeze(select),
413
+ variants: boundVariants,
414
+ })
415
+ }
416
+
417
+ if (input.defaultTheme !== undefined)
418
+ throw new InvalidError('defaultTheme requires a named themes catalog.')
419
+
420
+ if (input.theme !== undefined) {
421
+ const theme = handle(definition(input.theme), 'theme')
422
+ return finish({
423
+ appearance: Appearance.root([], { storageKey }),
424
+ script: Appearance.create([], { storageKey }),
425
+ style: boundStyle(theme as unknown as Theme.Definition),
426
+ theme,
427
+ variants: boundVariants,
428
+ })
429
+ }
430
+
431
+ const theme =
432
+ shorthands || input.defaultLayer !== undefined
433
+ ? Token.bind(Theme.define({}), contract)
434
+ : undefined
435
+ return finish({
436
+ appearance: Appearance.root([], { storageKey }),
437
+ script: Appearance.create([], { storageKey }),
438
+ style: boundStyle(theme),
439
+ variants: boundVariants,
440
+ })
441
+ }
442
+
443
+ /** Configuration inputs and inferred results. */
444
+ export declare namespace create {
445
+ /** Optional layer names and mutually exclusive theme modes. */
446
+ type Options = {
447
+ /** CSS representation inherited by bound helpers; atomic by default. */
448
+ readonly cssOutput?: 'atomic' | 'grouped' | undefined
449
+ /** Fallback CSS layer for bound styles and variants; unlayered when omitted. */
450
+ readonly defaultLayer?: string | undefined
451
+ /** Stable theme identity required without source rewriting. */
452
+ readonly id?: string | undefined
453
+ /** Explicit ordered property aliases; none are installed by default. */
454
+ readonly shorthands?: Shorthands.Map | undefined
455
+ /** Renderer props format; React is the default. */
456
+ readonly output?: style.Output | undefined
457
+ /** Ordered plain or dotted CSS layer names; emission follows source integration. */
458
+ readonly layers?: readonly string[] | undefined
459
+ /** localStorage key shared by `script()` and `appearance`; zyzz by default. */
460
+ readonly storageKey?: string | undefined
461
+ } & (
462
+ | {
463
+ /** Single inline or reusable theme. */ readonly theme: Input
464
+ /** Named mode is excluded. */ readonly themes?: never
465
+ /** Only named catalogs use defaults. */ readonly defaultTheme?: never
466
+ }
467
+ | {
468
+ /** Explicit catalog key. */ readonly defaultTheme: string
469
+ /** Single mode is excluded. */ readonly theme?: never
470
+ /** Complete named theme alternatives. */ readonly themes: Readonly<
471
+ Record<string, Input>
472
+ >
473
+ }
474
+ | {
475
+ /** Only named catalogs use defaults. */ readonly defaultTheme?: never
476
+ /** Omit themes for token-free authoring. */ readonly theme?: never
477
+ /** Omit themes for token-free authoring. */ readonly themes?: never
478
+ }
479
+ )
480
+
481
+ /** Bound authoring and the handles corresponding to the selected theme mode. */
482
+ type ReturnType<options extends Options = Options> = {
483
+ /** Reads and persists the root theme and scheme selection on the document element. */
484
+ readonly appearance: Appearance.Root<
485
+ options extends { themes: infer catalog } ? keyof catalog & string : never
486
+ >
487
+ /** Generates synchronous HTML-safe root preference restoration. */
488
+ readonly script: () => string
489
+ /** Inferred callable authoring; execution requires a source transform. */
490
+ readonly style: StyleFactory<
491
+ Tokens<options>,
492
+ options extends { layers: readonly (infer name extends string)[] }
493
+ ? name
494
+ : never,
495
+ options extends { output: infer output extends style.Output }
496
+ ? output
497
+ : 'react',
498
+ Mappings<options>
499
+ >
500
+ /** Theme-, layer-, and mapping-aware recipe authoring. */
501
+ readonly variants: variants.Bound<
502
+ Tokens<options>,
503
+ options extends { output: infer output extends style.Output }
504
+ ? output
505
+ : 'react',
506
+ options extends { layers: readonly (infer name extends string)[] }
507
+ ? name
508
+ : never,
509
+ Mappings<options>
510
+ >
511
+ } & (options extends { theme: infer input }
512
+ ? {
513
+ /** Isolated single-theme contract. */ readonly theme: Handle<
514
+ ExtractTokens<input>,
515
+ Mappings<options>,
516
+ options extends { output: infer output extends style.Output }
517
+ ? output
518
+ : 'react'
519
+ >
520
+ }
521
+ : options extends { themes: infer catalog }
522
+ ? {
523
+ /** Shared default token and variable contract. */ readonly theme: Handle<
524
+ Tokens<options>,
525
+ Mappings<options>,
526
+ options extends { output: infer output extends style.Output }
527
+ ? output
528
+ : 'react'
529
+ >
530
+ /** Selects a compiled named scope; catalog members retain compatibility. */ readonly themes: (<
531
+ const selection extends {
532
+ readonly colorScheme?: 'dark' | 'light' | 'light dark' | undefined
533
+ readonly theme: keyof catalog & string
534
+ },
535
+ >(
536
+ options: selection &
537
+ Record<Exclude<keyof selection, 'theme' | 'colorScheme'>, never>,
538
+ ) => style.Props<
539
+ options extends { output: infer output extends style.Output }
540
+ ? output
541
+ : 'react'
542
+ >) & {
543
+ readonly [name in keyof catalog]: Handle<
544
+ ExtractTokens<catalog[name]>,
545
+ Mappings<options>,
546
+ options extends { output: infer output extends style.Output }
547
+ ? output
548
+ : 'react'
549
+ >
550
+ }
551
+ }
552
+ : {})
553
+ }
554
+
555
+ type Mappings<options> = options extends {
556
+ shorthands: infer map extends Shorthands.Map
557
+ }
558
+ ? string extends keyof map
559
+ ? {}
560
+ : map
561
+ : {}
562
+
563
+ /** Theme handle retaining configured shorthands and renderer output in emitted declarations. */
564
+ export type Handle<
565
+ tokens extends Theme.Tokens,
566
+ mappings extends Shorthands.Map,
567
+ output extends style.Output,
568
+ > = Omit<Theme.Definition<tokens>, 'style' | 'variants'> & {
569
+ /** Style factory bound to this handle. */
570
+ readonly style: StyleFactory<tokens, never, output, mappings>
571
+ /** Variant factory bound to this handle. */
572
+ readonly variants: variants.Bound<tokens, output, never, mappings>
573
+ }
574
+
575
+ /** Configured style factory with a portable name for library declaration emission. */
576
+ export type StyleFactory<
577
+ tokens extends Theme.Tokens,
578
+ layers extends string,
579
+ output extends style.Output,
580
+ mappings extends Shorthands.Map,
581
+ > = {
582
+ (): style.ReturnType<output>
583
+ <
584
+ const values extends Record<string, string | number>,
585
+ const styles extends Record<string, unknown>,
586
+ const callback extends (...args: never[]) => unknown,
587
+ >(
588
+ styles: callback &
589
+ ((
590
+ values: values,
591
+ ) => styles &
592
+ NoInfer<
593
+ Body<styles, tokens, layers, mappings> & Binding.Checked<styles>
594
+ >) &
595
+ Completion.Properties<tokens, NoInfer<styles>>,
596
+ ...options: Parameters<callback> extends [Record<string, string | number>]
597
+ ? values extends Binding.Inputs<values>
598
+ ? [options?: style.DefinitionOptions]
599
+ : [invalid: never, unavailable: never]
600
+ : [invalid: never, unavailable: never]
601
+ ): style.Dynamic<values, output>
602
+ <const styles extends Record<string, unknown>>(
603
+ styles: styles &
604
+ NoInfer<Body<styles, tokens, layers, mappings>> &
605
+ Completion.Properties<tokens>,
606
+ options?: style.DefinitionOptions,
607
+ ): style.ReturnType<output>
608
+ }
609
+
610
+ type Keys<styles> = styles extends unknown ? keyof styles : never
611
+
612
+ /** Checked declaration body shared by configured styles and recipe choices. */
613
+ export type Body<
614
+ styles,
615
+ tokens extends Theme.Tokens,
616
+ layers extends string,
617
+ mappings extends Shorthands.Map,
618
+ targets extends boolean = true,
619
+ > = Record<
620
+ Exclude<
621
+ Keys<styles>,
622
+ | keyof mappings
623
+ | 'selectors'
624
+ | 'targets'
625
+ | 'typography'
626
+ | 'vars'
627
+ | keyof Style.DeclarationProperties
628
+ | Exclude<Condition.Keys<tokens, Keys<styles>>, `@layer${string}`>
629
+ | '@layer'
630
+ | `@layer ${layers}`
631
+ >,
632
+ never
633
+ > &
634
+ (styles extends unknown
635
+ ? {
636
+ [key in keyof styles]: key extends 'targets'
637
+ ? targets extends false
638
+ ? never
639
+ : styles[key] extends undefined
640
+ ? undefined
641
+ : {
642
+ [target in keyof styles[key]]: target extends 'web'
643
+ ?
644
+ | Body<
645
+ NonNullable<styles[key][target]>,
646
+ tokens,
647
+ layers,
648
+ mappings,
649
+ false
650
+ >
651
+ | Extract<styles[key][target], undefined>
652
+ : Style.Accepted<
653
+ { targets: Pick<styles[key], target> },
654
+ tokens
655
+ >['targets'][target]
656
+ }
657
+ : key extends 'selectors'
658
+ ? styles[key] extends Record<string, unknown>
659
+ ? {
660
+ [selector in keyof styles[key]]: styles[key][selector] extends Record<
661
+ string,
662
+ unknown
663
+ >
664
+ ? Body<
665
+ styles[key][selector],
666
+ tokens,
667
+ layers,
668
+ mappings,
669
+ targets
670
+ >
671
+ : never
672
+ }
673
+ : never
674
+ : key extends
675
+ | Exclude<Condition.Keys<tokens, key>, `@layer${string}`>
676
+ | '@layer'
677
+ | `@layer ${layers}`
678
+ ? styles[key] extends Record<string, unknown>
679
+ ? Body<styles[key], tokens, layers, mappings, targets>
680
+ : never
681
+ : key extends keyof mappings
682
+ ? {
683
+ [target in mappings[key][number]]: styles[key] extends Style.Accepted<
684
+ Record<target, styles[key]>,
685
+ tokens
686
+ >[target] &
687
+ Binding.Checked<Record<target, styles[key]>>[target]
688
+ ? never
689
+ : target
690
+ }[mappings[key][number]] extends never
691
+ ? styles[key]
692
+ : never
693
+ : Style.Accepted<Pick<styles, key>, tokens>[key]
694
+ }
695
+ : never)
696
+
697
+ function definition(value: unknown): Theme.Definition {
698
+ try {
699
+ if (
700
+ value &&
701
+ typeof value === 'object' &&
702
+ Object.getOwnPropertyDescriptor(value, Token.definition)?.value
703
+ )
704
+ return value as Theme.Definition
705
+
706
+ return Theme.define(record(value) as Theme.Tokens)
707
+ } catch (error) {
708
+ if (error instanceof InvalidError) throw error
709
+
710
+ throw new InvalidError((error as Error).message)
711
+ }
712
+ }
713
+
714
+ type ExtractTokens<input> =
715
+ input extends Theme.Definition<infer tokens>
716
+ ? tokens
717
+ : input extends Theme.Tokens
718
+ ? input
719
+ : never
720
+
721
+ type Input = Theme.Definition | Theme.Tokens
722
+
723
+ /** Invalid options or incompatible named themes. */
724
+ export class InvalidError extends Error {
725
+ /** Creates a configuration diagnostic without generating styles. */
726
+ constructor(message: string) {
727
+ super(message)
728
+ }
729
+ /** Stable namespaced error identifier. */
730
+ override name = 'Config.InvalidError'
731
+ }
732
+
733
+ function record(value: unknown): Record<string, unknown> {
734
+ if (
735
+ !value ||
736
+ typeof value !== 'object' ||
737
+ Array.isArray(value) ||
738
+ ![null, Object.prototype].includes(Object.getPrototypeOf(value))
739
+ )
740
+ throw new InvalidError('Expected a plain configuration record.')
741
+
742
+ const result: Record<string, unknown> = Object.create(null)
743
+
744
+ for (const [key, descriptor] of Object.entries(
745
+ Object.getOwnPropertyDescriptors(value),
746
+ )) {
747
+ if (!('value' in descriptor))
748
+ throw new InvalidError('Configuration records cannot contain accessors.')
749
+
750
+ result[key] = descriptor.value
751
+ }
752
+
753
+ return result
754
+ }
755
+
756
+ type Tokens<options> = options extends { theme: infer input }
757
+ ? ExtractTokens<input>
758
+ : options extends { themes: infer catalog; defaultTheme: infer key }
759
+ ? key extends keyof catalog
760
+ ? ExtractTokens<catalog[key]>
761
+ : never
762
+ : {}
763
+
764
+ type ValidInput<input> = input extends Theme.Definition
765
+ ? input
766
+ : input extends Theme.Tokens
767
+ ? Parameters<typeof Theme.define<input>>[0]
768
+ : never
769
+
770
+ type Match<input, base> = base extends
771
+ | string
772
+ | number
773
+ | { light: string; dark: string }
774
+ ? input
775
+ : {
776
+ [key in keyof input | keyof base]: key extends keyof input
777
+ ? key extends keyof base
778
+ ? key extends 'containerNames'
779
+ ? input[key] extends readonly string[]
780
+ ? base[key] extends readonly string[]
781
+ ?
782
+ | Exclude<input[key][number], base[key][number]>
783
+ | Exclude<
784
+ base[key][number],
785
+ input[key][number]
786
+ > extends never
787
+ ? input[key]
788
+ : never
789
+ : never
790
+ : never
791
+ : Match<input[key], base[key]>
792
+ : never
793
+ : never
794
+ }
795
+
796
+ type Validated<options> = Record<
797
+ Exclude<keyof options, keyof create.Options>,
798
+ never
799
+ > &
800
+ (options extends { shorthands: infer mappings extends Shorthands.Map }
801
+ ? { shorthands: Shorthands.Validated<mappings> }
802
+ : {}) &
803
+ (options extends { theme: infer input }
804
+ ? { theme: ValidInput<input> }
805
+ : options extends { themes: infer catalog; defaultTheme: infer key }
806
+ ? {
807
+ defaultTheme: keyof catalog
808
+ themes: {
809
+ [name in keyof catalog]: ValidInput<catalog[name]> &
810
+ (key extends keyof catalog
811
+ ? catalog[name] extends Theme.Definition
812
+ ? Theme.Definition<
813
+ ExtractTokens<catalog[name]> &
814
+ Match<
815
+ ExtractTokens<catalog[name]>,
816
+ ExtractTokens<catalog[key]>
817
+ >
818
+ >
819
+ : Match<
820
+ ExtractTokens<catalog[name]>,
821
+ ExtractTokens<catalog[key]>
822
+ >
823
+ : never)
824
+ }
825
+ }
826
+ : {})
827
+
828
+ /** Vars, optional named alternatives, and category-to-property mappings. */
829
+ export type VariableOptions = {
830
+ /** CSS representation inherited by bound helpers; atomic by default. */
831
+ readonly cssOutput?: 'atomic' | 'grouped' | undefined
832
+ /** Fallback CSS layer for bound styles and variants; unlayered when omitted. */
833
+ readonly defaultLayer?: string | undefined
834
+ /** Required default key when vars contains named sets. */
835
+ readonly defaultVars?: string | undefined
836
+ /** Stable identity required without source rewriting. */
837
+ readonly id?: string | undefined
838
+ /** Ordered CSS layer names. */
839
+ readonly layers?: readonly string[] | undefined
840
+ /** Category mappings; false enables full paths in every compatible property. */
841
+ readonly mappings?: Vars.Mappings | false | undefined
842
+ /** Styling props format; React by default. */
843
+ readonly output?: style.Output | undefined
844
+ /** Explicit local property aliases. */
845
+ readonly shorthands?: Shorthands.Map | undefined
846
+ /** Preference storage key; zyzz by default. */
847
+ readonly storageKey?: string | undefined
848
+ /** One inline or reusable set, or a catalog with defaultVars. */
849
+ readonly vars:
850
+ | Vars.Values
851
+ | Vars.Definition
852
+ | Readonly<Record<string, Vars.Definition | Vars.Values>>
853
+ }
854
+
855
+ type VariableValues<options extends VariableOptions> = options extends {
856
+ defaultVars: infer key
857
+ }
858
+ ? key extends keyof options['vars']
859
+ ? Vars.Extract<options['vars'][key]>
860
+ : never
861
+ : Vars.Extract<options['vars']>
862
+
863
+ type VariableTokens<options extends VariableOptions> = Vars.Mapped<
864
+ VariableValues<options>,
865
+ options extends { mappings: infer mappings } ? mappings : {}
866
+ >
867
+
868
+ type VariableInput<input> = input extends {
869
+ readonly [Token.definition]: Token.Metadata
870
+ }
871
+ ? input
872
+ : input extends Vars.Values
873
+ ? Parameters<typeof Vars.define<input>>[0]
874
+ : never
875
+
876
+ type VariableMatch<input, base> = base extends readonly string[]
877
+ ? input extends readonly string[]
878
+ ?
879
+ | Exclude<input[number], base[number]>
880
+ | Exclude<base[number], input[number]> extends never
881
+ ? input
882
+ : never
883
+ : never
884
+ : base extends Vars.Value
885
+ ? input extends Vars.Value
886
+ ? Vars.Domain<Vars.Scalar<input>> extends Vars.Domain<Vars.Scalar<base>>
887
+ ? input
888
+ : never
889
+ : never
890
+ : {
891
+ readonly [key in keyof input | keyof base]: key extends keyof base
892
+ ? key extends keyof input
893
+ ? VariableMatch<input[key], base[key]>
894
+ : never
895
+ : never
896
+ }
897
+
898
+ export type VariableValidation<options extends VariableOptions> =
899
+ VariableOptions extends options
900
+ ? unknown
901
+ : Record<Exclude<keyof options, keyof VariableOptions>, never> &
902
+ (options extends { shorthands: infer map extends Shorthands.Map }
903
+ ? { shorthands: Shorthands.Validated<map> }
904
+ : {}) &
905
+ (options extends { defaultVars: infer selected }
906
+ ? {
907
+ readonly defaultVars: keyof options['vars']
908
+ readonly vars: {
909
+ readonly [key in keyof options['vars']]: VariableInput<
910
+ options['vars'][key]
911
+ > &
912
+ (selected extends keyof options['vars']
913
+ ? Vars.Extract<options['vars'][key]> extends VariableMatch<
914
+ Vars.Extract<options['vars'][key]>,
915
+ Vars.Extract<options['vars'][selected]>
916
+ >
917
+ ? unknown
918
+ : never
919
+ : never)
920
+ }
921
+ }
922
+ : { readonly vars: VariableInput<options['vars']> })
923
+
924
+ /** Configured authoring, portable references, and scoped set selection. */
925
+ export type VariableConfig<options extends VariableOptions> = {
926
+ /** Reads and persists the root set and color scheme. */
927
+ readonly appearance: Appearance.Root<
928
+ options extends { defaultVars: unknown }
929
+ ? keyof options['vars'] & string
930
+ : never
931
+ >
932
+ /** Generates the root preference restoration script. */
933
+ readonly script: () => string
934
+ /** Authors styles with configured tokens and property aliases. */
935
+ readonly style: StyleFactory<
936
+ VariableTokens<options>,
937
+ options extends { layers: readonly (infer layer extends string)[] }
938
+ ? layer
939
+ : never,
940
+ options extends { output: infer output extends style.Output }
941
+ ? output
942
+ : 'react',
943
+ Mappings<options>
944
+ >
945
+ /** Authors recipes with the same variable and mapping contract. */
946
+ readonly variants: variants.Bound<
947
+ VariableTokens<options>,
948
+ options extends { output: infer output extends style.Output }
949
+ ? output
950
+ : 'react',
951
+ options extends { layers: readonly (infer layer extends string)[] }
952
+ ? layer
953
+ : never,
954
+ Mappings<options>
955
+ >
956
+ /** Explicit portable references, independent of shorthand mappings. */
957
+ /** Applies a named or default set and optional color scheme to a scope. */
958
+ readonly vars: VariableScope<options>
959
+ }
960
+
961
+ /** References and scoped selection inferred from a configuration. */
962
+ export type VariableScope<options extends VariableOptions> = Vars.Bound<
963
+ VariableValues<options> extends Vars.Values ? VariableValues<options> : {},
964
+ options extends { defaultVars: unknown }
965
+ ? keyof options['vars'] & string
966
+ : never,
967
+ options extends { output: infer output extends style.Output }
968
+ ? output
969
+ : 'react'
970
+ >