zyzz 0.0.20 → 0.0.22

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 (298) hide show
  1. package/Zyzz.podspec +16 -0
  2. package/dist/Style.d.ts +10 -1
  3. package/dist/Style.d.ts.map +1 -1
  4. package/dist/Style.js +1 -5
  5. package/dist/Style.js.map +1 -1
  6. package/dist/babel/NativeJsx.d.ts.map +1 -1
  7. package/dist/babel/NativeJsx.js +204 -12
  8. package/dist/babel/NativeJsx.js.map +1 -1
  9. package/dist/babel/index.d.ts +6 -2
  10. package/dist/babel/index.d.ts.map +1 -1
  11. package/dist/babel/index.js +10 -1
  12. package/dist/babel/index.js.map +1 -1
  13. package/dist/compiler/Graph.d.ts +3 -0
  14. package/dist/compiler/Graph.d.ts.map +1 -1
  15. package/dist/compiler/Graph.js +108 -37
  16. package/dist/compiler/Graph.js.map +1 -1
  17. package/dist/compiler/Native.d.ts +6 -3
  18. package/dist/compiler/Native.d.ts.map +1 -1
  19. package/dist/compiler/Native.js +142 -24
  20. package/dist/compiler/Native.js.map +1 -1
  21. package/dist/compiler/Source.d.ts +6 -0
  22. package/dist/compiler/Source.d.ts.map +1 -1
  23. package/dist/compiler/Source.js +80 -11
  24. package/dist/compiler/Source.js.map +1 -1
  25. package/dist/compiler/Transform.d.ts +4 -1
  26. package/dist/compiler/Transform.d.ts.map +1 -1
  27. package/dist/compiler/Transform.js +32 -46
  28. package/dist/compiler/Transform.js.map +1 -1
  29. package/dist/compiler/internal/Catalogs.d.ts.map +1 -1
  30. package/dist/compiler/internal/Catalogs.js +6 -1
  31. package/dist/compiler/internal/Catalogs.js.map +1 -1
  32. package/dist/compiler/internal/Compositions.d.ts.map +1 -1
  33. package/dist/compiler/internal/Compositions.js +5 -0
  34. package/dist/compiler/internal/Compositions.js.map +1 -1
  35. package/dist/compiler/internal/Configurations.d.ts +2 -0
  36. package/dist/compiler/internal/Configurations.d.ts.map +1 -1
  37. package/dist/compiler/internal/Configurations.js +23 -4
  38. package/dist/compiler/internal/Configurations.js.map +1 -1
  39. package/dist/compiler/internal/Contract.d.ts +4 -1
  40. package/dist/compiler/internal/Contract.d.ts.map +1 -1
  41. package/dist/compiler/internal/Contract.js +97 -151
  42. package/dist/compiler/internal/Contract.js.map +1 -1
  43. package/dist/compiler/internal/Contributions.d.ts.map +1 -1
  44. package/dist/compiler/internal/Contributions.js +8 -4
  45. package/dist/compiler/internal/Contributions.js.map +1 -1
  46. package/dist/compiler/internal/Descriptors.d.ts.map +1 -1
  47. package/dist/compiler/internal/Descriptors.js +11 -2
  48. package/dist/compiler/internal/Descriptors.js.map +1 -1
  49. package/dist/compiler/internal/Dynamic.d.ts +1 -1
  50. package/dist/compiler/internal/Dynamic.d.ts.map +1 -1
  51. package/dist/compiler/internal/Dynamic.js +5 -5
  52. package/dist/compiler/internal/Dynamic.js.map +1 -1
  53. package/dist/compiler/internal/Names.d.ts +5 -0
  54. package/dist/compiler/internal/Names.d.ts.map +1 -0
  55. package/dist/compiler/internal/Names.js +37 -0
  56. package/dist/compiler/internal/Names.js.map +1 -0
  57. package/dist/compiler/internal/NativeBindings.d.ts +24 -26
  58. package/dist/compiler/internal/NativeBindings.d.ts.map +1 -1
  59. package/dist/compiler/internal/NativeBindings.js +61 -8
  60. package/dist/compiler/internal/NativeBindings.js.map +1 -1
  61. package/dist/compiler/internal/NativeMedia.d.ts +14 -0
  62. package/dist/compiler/internal/NativeMedia.d.ts.map +1 -0
  63. package/dist/compiler/internal/NativeMedia.js +287 -0
  64. package/dist/compiler/internal/NativeMedia.js.map +1 -0
  65. package/dist/compiler/internal/NativeVars.d.ts +28 -0
  66. package/dist/compiler/internal/NativeVars.d.ts.map +1 -0
  67. package/dist/compiler/internal/NativeVars.js +157 -0
  68. package/dist/compiler/internal/NativeVars.js.map +1 -0
  69. package/dist/compiler/internal/PackedStyles.d.ts +2 -0
  70. package/dist/compiler/internal/PackedStyles.d.ts.map +1 -1
  71. package/dist/compiler/internal/PackedStyles.js +2 -0
  72. package/dist/compiler/internal/PackedStyles.js.map +1 -1
  73. package/dist/compiler/internal/Selectors.d.ts +1 -1
  74. package/dist/compiler/internal/Selectors.d.ts.map +1 -1
  75. package/dist/compiler/internal/Selectors.js +5 -2
  76. package/dist/compiler/internal/Selectors.js.map +1 -1
  77. package/dist/compiler/internal/Stylesheets.js +2 -2
  78. package/dist/compiler/internal/Stylesheets.js.map +1 -1
  79. package/dist/compiler/internal/Themes.d.ts +22 -1
  80. package/dist/compiler/internal/Themes.d.ts.map +1 -1
  81. package/dist/compiler/internal/Themes.js +120 -4
  82. package/dist/compiler/internal/Themes.js.map +1 -1
  83. package/dist/compiler/internal/Vars.d.ts +3 -1
  84. package/dist/compiler/internal/Vars.d.ts.map +1 -1
  85. package/dist/compiler/internal/Vars.js +14 -3
  86. package/dist/compiler/internal/Vars.js.map +1 -1
  87. package/dist/default.d.ts +4 -4
  88. package/dist/default.d.ts.map +1 -1
  89. package/dist/default.js +9 -9
  90. package/dist/default.js.map +2 -2
  91. package/dist/default.js.zyzz.json +1 -1
  92. package/dist/internal/Authoring.d.ts.map +1 -1
  93. package/dist/internal/Authoring.js +8 -3
  94. package/dist/internal/Authoring.js.map +1 -1
  95. package/dist/internal/Binding.d.ts +4 -0
  96. package/dist/internal/Binding.d.ts.map +1 -1
  97. package/dist/internal/Binding.js +2 -0
  98. package/dist/internal/Binding.js.map +1 -1
  99. package/dist/internal/Completion.d.ts +1 -1
  100. package/dist/internal/Completion.d.ts.map +1 -1
  101. package/dist/internal/Configuration.d.ts +2 -2
  102. package/dist/internal/Configuration.d.ts.map +1 -1
  103. package/dist/internal/Configuration.js +4 -2
  104. package/dist/internal/Configuration.js.map +1 -1
  105. package/dist/internal/Identity.d.ts +3 -3
  106. package/dist/internal/Identity.d.ts.map +1 -1
  107. package/dist/internal/Identity.js +11 -9
  108. package/dist/internal/Identity.js.map +1 -1
  109. package/dist/internal/Targets.d.ts.map +1 -1
  110. package/dist/internal/Targets.js +2 -0
  111. package/dist/internal/Targets.js.map +1 -1
  112. package/dist/internal/Theme.js +2 -2
  113. package/dist/internal/Theme.js.map +1 -1
  114. package/dist/internal/Token.d.ts +3 -1
  115. package/dist/internal/Token.d.ts.map +1 -1
  116. package/dist/internal/Token.js +9 -2
  117. package/dist/internal/Token.js.map +1 -1
  118. package/dist/internal/Value.d.ts +7 -0
  119. package/dist/internal/Value.d.ts.map +1 -1
  120. package/dist/internal/Value.js.map +1 -1
  121. package/dist/internal/VariableSets.js +1 -1
  122. package/dist/internal/VariableSets.js.map +1 -1
  123. package/dist/metro/Graph.d.ts +22 -7
  124. package/dist/metro/Graph.d.ts.map +1 -1
  125. package/dist/metro/Graph.js +179 -42
  126. package/dist/metro/Graph.js.map +1 -1
  127. package/dist/metro/Watch.d.ts +28 -4
  128. package/dist/metro/Watch.d.ts.map +1 -1
  129. package/dist/metro/Watch.js +39 -7
  130. package/dist/metro/Watch.js.map +1 -1
  131. package/dist/metro/index.d.ts +15 -4
  132. package/dist/metro/index.d.ts.map +1 -1
  133. package/dist/metro/index.js +27 -0
  134. package/dist/metro/index.js.map +1 -1
  135. package/dist/metro/transformer.d.ts +5 -1
  136. package/dist/metro/transformer.d.ts.map +1 -1
  137. package/dist/metro/transformer.js +5 -3
  138. package/dist/metro/transformer.js.map +1 -1
  139. package/dist/node/Host.d.ts.map +1 -1
  140. package/dist/node/Host.js +2 -0
  141. package/dist/node/Host.js.map +1 -1
  142. package/dist/react-native/StyleSheet.d.ts +3 -2
  143. package/dist/react-native/StyleSheet.d.ts.map +1 -1
  144. package/dist/react-native/StyleSheet.js +17 -34
  145. package/dist/react-native/StyleSheet.js.map +1 -1
  146. package/dist/react-native/index.d.ts +1 -1
  147. package/dist/react-native/index.d.ts.map +1 -1
  148. package/dist/react-native/index.js +1 -1
  149. package/dist/react-native/index.js.map +1 -1
  150. package/dist/react-native/index.native.d.ts +5 -0
  151. package/dist/react-native/index.native.js +20 -0
  152. package/dist/react-native/index.native.js.map +7 -0
  153. package/dist/react-native/internal/Calculation.d.ts +7 -0
  154. package/dist/react-native/internal/Calculation.d.ts.map +1 -0
  155. package/dist/react-native/internal/Calculation.js +134 -0
  156. package/dist/react-native/internal/Calculation.js.map +1 -0
  157. package/dist/react-native/internal/Device.js +191 -0
  158. package/dist/react-native/internal/Device.js.map +7 -0
  159. package/dist/react-native/internal/NativeZyzz.js +7 -0
  160. package/dist/react-native/internal/NativeZyzz.js.map +7 -0
  161. package/dist/react-native/internal/Scalar.d.ts.map +1 -1
  162. package/dist/react-native/internal/Scalar.js +9 -2
  163. package/dist/react-native/internal/Scalar.js.map +1 -1
  164. package/dist/react-native/internal/Store.d.ts +32 -0
  165. package/dist/react-native/internal/Store.d.ts.map +1 -0
  166. package/dist/react-native/internal/Store.js +57 -0
  167. package/dist/react-native/internal/Store.js.map +1 -0
  168. package/dist/react-native/internal/Tokens.d.ts +21 -0
  169. package/dist/react-native/internal/Tokens.d.ts.map +1 -0
  170. package/dist/react-native/internal/Tokens.js +58 -0
  171. package/dist/react-native/internal/Tokens.js.map +1 -0
  172. package/dist/react-native/internal/Viewport.d.ts +6 -0
  173. package/dist/react-native/internal/Viewport.d.ts.map +1 -0
  174. package/dist/react-native/internal/Viewport.js +4 -0
  175. package/dist/react-native/internal/Viewport.js.map +1 -0
  176. package/dist/react-native/react.d.ts +74 -11
  177. package/dist/react-native/react.d.ts.map +1 -1
  178. package/dist/react-native/react.js +111 -12
  179. package/dist/react-native/react.js.map +1 -1
  180. package/dist/react-native/reanimated.d.ts +39 -0
  181. package/dist/react-native/reanimated.d.ts.map +1 -0
  182. package/dist/react-native/reanimated.js +76 -0
  183. package/dist/react-native/reanimated.js.map +1 -0
  184. package/dist/runtime/NativeContext.d.ts +10 -1
  185. package/dist/runtime/NativeContext.d.ts.map +1 -1
  186. package/dist/runtime/NativeContext.js +67 -14
  187. package/dist/runtime/NativeContext.js.map +1 -1
  188. package/dist/runtime/NativeDynamic.d.ts +3 -2
  189. package/dist/runtime/NativeDynamic.d.ts.map +1 -1
  190. package/dist/runtime/NativeDynamic.js +32 -7
  191. package/dist/runtime/NativeDynamic.js.map +1 -1
  192. package/dist/runtime/NativeStatic.d.ts +23 -0
  193. package/dist/runtime/NativeStatic.d.ts.map +1 -0
  194. package/dist/runtime/NativeStatic.js +106 -0
  195. package/dist/runtime/NativeStatic.js.map +1 -0
  196. package/dist/runtime/NativeVars.d.ts +53 -0
  197. package/dist/runtime/NativeVars.d.ts.map +1 -0
  198. package/dist/runtime/NativeVars.js +77 -0
  199. package/dist/runtime/NativeVars.js.map +1 -0
  200. package/dist/runtime/index.d.ts +4 -0
  201. package/dist/runtime/index.d.ts.map +1 -1
  202. package/dist/runtime/index.js +4 -0
  203. package/dist/runtime/index.js.map +1 -1
  204. package/dist/runtime/internal/NativeMedia.d.ts +25 -0
  205. package/dist/runtime/internal/NativeMedia.d.ts.map +1 -0
  206. package/dist/runtime/internal/NativeMedia.js +36 -0
  207. package/dist/runtime/internal/NativeMedia.js.map +1 -0
  208. package/dist/variable.js +1 -1
  209. package/dist/variable.js.map +1 -1
  210. package/dist/vite/index.d.ts.map +1 -1
  211. package/dist/vite/index.js +43 -47
  212. package/dist/vite/index.js.map +1 -1
  213. package/dist/web/Css.d.ts +7 -2
  214. package/dist/web/Css.d.ts.map +1 -1
  215. package/dist/web/Css.js +76 -57
  216. package/dist/web/Css.js.map +1 -1
  217. package/dist/web/internal/ClassName.d.ts +13 -2
  218. package/dist/web/internal/ClassName.d.ts.map +1 -1
  219. package/dist/web/internal/ClassName.js +17 -30
  220. package/dist/web/internal/ClassName.js.map +1 -1
  221. package/dist/web/internal/Themes.d.ts +3 -2
  222. package/dist/web/internal/Themes.d.ts.map +1 -1
  223. package/dist/web/internal/Themes.js +54 -28
  224. package/dist/web/internal/Themes.js.map +1 -1
  225. package/dist/web/page.d.ts +2 -0
  226. package/dist/web/page.d.ts.map +1 -1
  227. package/native/NativeZyzz.cpp +215 -0
  228. package/native/NativeZyzz.h +52 -0
  229. package/native/ZyzzSpecJSI.h +65 -0
  230. package/native/android/CMakeLists.txt +8 -0
  231. package/native/android/ZyzzSpec-generated.cpp +50 -0
  232. package/native/android/ZyzzSpec.h +31 -0
  233. package/native/ios/ZyzzModuleProvider.mm +13 -0
  234. package/package.json +39 -1
  235. package/react-native.config.ts +14 -0
  236. package/src/Style.ts +15 -9
  237. package/src/babel/NativeJsx.ts +305 -28
  238. package/src/babel/index.ts +21 -3
  239. package/src/compiler/Graph.ts +135 -46
  240. package/src/compiler/Native.ts +158 -26
  241. package/src/compiler/Source.ts +115 -10
  242. package/src/compiler/Transform.ts +42 -60
  243. package/src/compiler/internal/Catalogs.ts +9 -1
  244. package/src/compiler/internal/Compositions.ts +7 -0
  245. package/src/compiler/internal/Configurations.ts +27 -4
  246. package/src/compiler/internal/Contract.ts +130 -260
  247. package/src/compiler/internal/Contributions.ts +8 -6
  248. package/src/compiler/internal/Descriptors.ts +12 -8
  249. package/src/compiler/internal/Dynamic.ts +14 -9
  250. package/src/compiler/internal/Names.ts +48 -0
  251. package/src/compiler/internal/NativeBindings.ts +98 -15
  252. package/src/compiler/internal/NativeMedia.ts +342 -0
  253. package/src/compiler/internal/NativeVars.ts +228 -0
  254. package/src/compiler/internal/PackedStyles.ts +4 -0
  255. package/src/compiler/internal/Selectors.ts +6 -1
  256. package/src/compiler/internal/Stylesheets.ts +2 -2
  257. package/src/compiler/internal/Themes.ts +193 -3
  258. package/src/compiler/internal/Vars.ts +21 -2
  259. package/src/default.ts +9 -10
  260. package/src/internal/Authoring.ts +8 -2
  261. package/src/internal/Binding.ts +5 -0
  262. package/src/internal/Completion.ts +6 -3
  263. package/src/internal/Configuration.ts +7 -4
  264. package/src/internal/Identity.ts +14 -12
  265. package/src/internal/Targets.ts +2 -0
  266. package/src/internal/Theme.ts +2 -2
  267. package/src/internal/Token.ts +11 -1
  268. package/src/internal/Value.ts +20 -0
  269. package/src/internal/VariableSets.ts +1 -1
  270. package/src/metro/Graph.ts +235 -50
  271. package/src/metro/Watch.ts +95 -10
  272. package/src/metro/index.ts +62 -4
  273. package/src/metro/transformer.ts +21 -11
  274. package/src/node/Host.ts +3 -0
  275. package/src/react-native/StyleSheet.ts +28 -44
  276. package/src/react-native/index.native.ts +10 -0
  277. package/src/react-native/index.ts +1 -1
  278. package/src/react-native/internal/Calculation.ts +159 -0
  279. package/src/react-native/internal/Device.ts +231 -0
  280. package/src/react-native/internal/NativeZyzz.ts +20 -0
  281. package/src/react-native/internal/Scalar.ts +13 -2
  282. package/src/react-native/internal/Store.ts +78 -0
  283. package/src/react-native/internal/Tokens.ts +85 -0
  284. package/src/react-native/internal/Viewport.ts +8 -0
  285. package/src/react-native/react.ts +211 -19
  286. package/src/react-native/reanimated.ts +162 -0
  287. package/src/runtime/NativeContext.ts +88 -17
  288. package/src/runtime/NativeDynamic.ts +35 -10
  289. package/src/runtime/NativeStatic.ts +145 -0
  290. package/src/runtime/NativeVars.ts +189 -0
  291. package/src/runtime/index.ts +6 -0
  292. package/src/runtime/internal/NativeMedia.ts +63 -0
  293. package/src/variable.ts +1 -1
  294. package/src/vite/index.ts +52 -60
  295. package/src/web/Css.ts +123 -74
  296. package/src/web/internal/ClassName.ts +31 -36
  297. package/src/web/internal/Themes.ts +62 -39
  298. package/src/web/page.ts +2 -0
@@ -0,0 +1,228 @@
1
+ /** Converts authored variables to static native value profiles. @module */
2
+ import * as Calculation from '../../react-native/internal/Calculation.js'
3
+ import * as Literal from '../../internal/Literal.js'
4
+ import * as Media from './NativeMedia.js'
5
+ import type * as Runtime from '../../runtime/NativeVars.js'
6
+ import * as Scalar from '../../react-native/internal/Scalar.js'
7
+ import type * as Theme from '../../internal/Theme.js'
8
+ import * as Token from '../../internal/Token.js'
9
+ import * as VariableSets from '../../internal/VariableSets.js'
10
+
11
+ /** Resolves native domains using the style compiler's unit and font mappings. */
12
+ export function compile(options: compile.Options): Runtime.create.Options {
13
+ const media = Media.prepare(undefined, options.vars, options)
14
+ return {
15
+ defaultVars: options.defaultVars,
16
+ ...(media
17
+ ? {
18
+ media: {
19
+ profiles: Object.fromEntries(
20
+ media.selections.map((selection) => [
21
+ selection,
22
+ compile({ ...options, vars: media.select(selection).vars! })
23
+ .profiles,
24
+ ]),
25
+ ),
26
+ queries: media.queries,
27
+ },
28
+ }
29
+ : {}),
30
+ profiles: Object.fromEntries(
31
+ Object.entries(options.vars).map((entry) => {
32
+ const [name, theme] = entry
33
+ return [
34
+ name,
35
+ { dark: profile(theme, 'dark'), light: profile(theme, 'light') },
36
+ ]
37
+ }),
38
+ ),
39
+ unnamed: options.unnamed,
40
+ }
41
+
42
+ function profile(theme: Theme.Definition, scheme: 'dark' | 'light') {
43
+ const metadata = theme[Token.definition]
44
+ const active = new Set<Token.Reference>()
45
+ type Tree = {
46
+ [key: string]: string | number | Tree | readonly [string]
47
+ }
48
+ const tree: Tree = Object.create(null)
49
+
50
+ function resolve(value: Token.Value): string | number {
51
+ if (typeof value === 'string' || typeof value === 'number') return value
52
+ if (Token.is(value)) {
53
+ if (active.has(value))
54
+ throw new Error('Native token aliases must not form a cycle.')
55
+ const shared =
56
+ metadata.contract === value.contract ||
57
+ (metadata.contract[Token.identity] !== undefined &&
58
+ metadata.contract[Token.identity] ===
59
+ value.contract[Token.identity])
60
+ const next = shared ? metadata.values[value.path] : value.value
61
+ if (next === undefined)
62
+ throw new Error(`Missing native token: ${value.path}.`)
63
+ active.add(value)
64
+ try {
65
+ return resolve(next)
66
+ } finally {
67
+ active.delete(value)
68
+ }
69
+ }
70
+ if (Token.isExpression(value) && 'group' in value) {
71
+ const text = value.parts.map(resolve).join('')
72
+ return value.group === 'spacing' && /^\s*calc\(/i.test(text)
73
+ ? `${Calculation.length(text, options) / (options.units?.px ?? 1)}px`
74
+ : text
75
+ }
76
+ if ('light' in value && 'dark' in value) return resolve(value[scheme])
77
+ throw new Error(
78
+ media
79
+ ? 'Native media-conditioned variables require the native Provider window dimensions.'
80
+ : 'Media-conditioned variables require a web target.',
81
+ )
82
+ }
83
+
84
+ for (const [path, source] of Object.entries(metadata.values)) {
85
+ const parts = metadata.paths?.[path] ?? path.split('.')
86
+ const property = parts.at(-1)
87
+ const domain = VariableSets.domain(source)
88
+ const mappings = metadata.contract.mappings
89
+ const properties = mappings === false ? undefined : mappings?.[parts[0]!]
90
+ const category = parts[0] === 'typography' ? property! : parts[0]!
91
+ const target = category === 'radius' ? 'borderRadius' : category
92
+ const targets = properties?.length
93
+ ? properties
94
+ : Object.hasOwn(Scalar.properties, target)
95
+ ? [target]
96
+ : []
97
+
98
+ const converted = (() => {
99
+ try {
100
+ if (parts.some((part) => /^@(media|container)\s/.test(part)))
101
+ throw new Error('Media-conditioned variables require a web target.')
102
+ const value = resolve(source)
103
+
104
+ function convert(property: string): string | number {
105
+ property =
106
+ property in Literal.aliases
107
+ ? Literal.aliases[property as keyof typeof Literal.aliases]
108
+ : property
109
+ if (!Object.hasOwn(Scalar.properties, property))
110
+ throw new Error(`Unsupported native property: ${property}.`)
111
+
112
+ if (property === 'lineHeight') {
113
+ if (
114
+ typeof value === 'string' &&
115
+ (/^\s*calc\(/i.test(value) ||
116
+ /^\s*[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?(?:px|rem)\s*$/i.test(
117
+ value,
118
+ ))
119
+ )
120
+ return Scalar.length(
121
+ value.trim().toLowerCase(),
122
+ options,
123
+ false,
124
+ [path],
125
+ )
126
+
127
+ const multiplier =
128
+ typeof value === 'number' ? value : Number(value)
129
+ if (
130
+ !Number.isFinite(multiplier) ||
131
+ (typeof value === 'string' && !value.trim())
132
+ )
133
+ throw new Error(`Unsupported native line height: ${value}.`)
134
+ const size =
135
+ parts[0] === 'typography'
136
+ ? metadata.values[
137
+ [...parts.slice(0, -1), 'fontSize'].join('.')
138
+ ]
139
+ : undefined
140
+ if (size === undefined)
141
+ throw new Error(
142
+ `Native line height requires fontSize: ${path}.`,
143
+ )
144
+ return Scalar.convert(
145
+ 'number',
146
+ multiplier *
147
+ Scalar.length(resolve(size), options, false, [path]),
148
+ options,
149
+ [path],
150
+ )
151
+ }
152
+
153
+ const kind =
154
+ Scalar.properties[property as keyof typeof Scalar.properties]
155
+ if (
156
+ typeof kind === 'string' &&
157
+ [
158
+ 'fontVariant',
159
+ 'origin',
160
+ 'shadow',
161
+ 'textShadow',
162
+ 'transform',
163
+ ].includes(kind)
164
+ )
165
+ throw new Error(
166
+ `Native property ${property} does not have a scalar variable value.`,
167
+ )
168
+ if (kind === 'ratio' && typeof value !== 'number')
169
+ throw new Error(
170
+ 'Native aspect ratios require numeric variable values.',
171
+ )
172
+ if (kind === 'box' || kind === 'boxSigned')
173
+ return Scalar.length(value, options, kind === 'boxSigned', [path])
174
+ return Scalar.convert(kind, value, options, [path])
175
+ }
176
+
177
+ if (targets.length) {
178
+ const values = targets.map(convert)
179
+ if (values.some((value) => value !== values[0]))
180
+ throw new Error(
181
+ 'Mapped native properties require different converted values.',
182
+ )
183
+ return values[0]!
184
+ }
185
+ if (domain === 'spacing')
186
+ return Scalar.length(value, options, true, [path])
187
+ if (domain === 'color')
188
+ return Scalar.convert('color', value, options, [path])
189
+ return value
190
+ } catch (error) {
191
+ return [
192
+ `Native variable ${path}: ${error instanceof Error ? error.message : String(error)}`,
193
+ ] as const
194
+ }
195
+ })()
196
+ let parent = tree
197
+ for (const key of parts.slice(0, -1))
198
+ parent = (parent[key] ??= Object.create(null)) as typeof tree
199
+ parent[parts.at(-1)!] = converted
200
+ }
201
+ return tree
202
+ }
203
+ }
204
+
205
+ /** Compiler inputs for resolved native variables. */
206
+ export declare namespace compile {
207
+ /** Complete variable catalog and explicit target mappings. */
208
+ type Options = Scalar.Options & {
209
+ /** Configuration fallback. */
210
+ readonly defaultVars: string
211
+ /** Whether the input is a standalone definition instead of a named catalog. */
212
+ readonly unnamed: boolean
213
+ /** Compatible authored definitions. */
214
+ readonly vars: Readonly<Record<string, Theme.Definition>>
215
+ }
216
+ }
217
+
218
+ /** Graph-owned profile exports and imports, excluded from public adapter options. */
219
+ export const shared = Symbol('zyzz.compiler.native.vars')
220
+
221
+ /** Static profile artifacts belonging to one source module. */
222
+ export type Shared = {
223
+ readonly definitions: ReadonlyMap<string, string>
224
+ readonly reads: ReadonlyMap<
225
+ number,
226
+ { readonly name: string; readonly source?: string | undefined }
227
+ >
228
+ }
@@ -26,6 +26,8 @@ export type Definition = {
26
26
  readonly className?: string | undefined
27
27
  /** Attributes owned by the callable, including conditional selections. */
28
28
  readonly attributes: readonly string[]
29
+ /** Named Provider selections retained by separately compiled styles. */
30
+ readonly nativeContext?: Source.Call['nativeContext']
29
31
  /** Native HTML output; React props are the default. */
30
32
  readonly output?: 'html' | undefined
31
33
  /** Private dynamic custom properties owned by the callable. */
@@ -39,6 +41,7 @@ export type Definition = {
39
41
  /** Captures ownership without retaining source ASTs or executable expressions. */
40
42
  export function create(call: Source.Call, style: Style.NamedStyle): Definition {
41
43
  return {
44
+ ...(call.nativeContext ? { nativeContext: call.nativeContext } : {}),
42
45
  ...(call.slots || call.dynamicRecipe
43
46
  ? {
44
47
  dynamic: {
@@ -419,6 +422,7 @@ export function write(definition: Definition): unknown {
419
422
  JSON.stringify(
420
423
  {
421
424
  ...definition,
425
+ nativeContext: undefined,
422
426
  style: {
423
427
  ...definition.style,
424
428
  cssOutput: definition.style.cssOutput ?? 'atomic',
@@ -6,6 +6,7 @@ import * as Theme from '../../internal/Theme.js'
6
6
  import * as AtRules from './AtRules.js'
7
7
  import * as Identity from '../../internal/Identity.js'
8
8
  import * as Identifiers from './Identifiers.js'
9
+ import * as Names from './Names.js'
9
10
  import * as Expression from './Expression.js'
10
11
  import type * as Scope from './Scope.js'
11
12
  import * as Themes from './Themes.js'
@@ -18,7 +19,10 @@ export function scan(
18
19
  calls: readonly Ast.CallExpression[],
19
20
  links: Readonly<Record<string, Themes.Link>> = {},
20
21
  selectorKeys: ReadonlySet<number> = new Set(),
22
+ cssNamespaces: ReadonlyMap<number, string> = new Map(),
23
+ moduleId = namespace,
21
24
  ) {
25
+ const authoredNames = Names.collect(program)
22
26
  const conditions = new Map<number, string>()
23
27
  const localConditions = new Set<string>()
24
28
  const identities = new Map<number, string>()
@@ -163,7 +167,8 @@ export function scan(
163
167
 
164
168
  function link(call: Ast.CallExpression): Themes.Link {
165
169
  const id = Identifiers.explicit(call)
166
- const name = `z-style-${id === undefined ? `${namespace}-${call.start}` : Identity.requireId(id, 'style')}`
170
+ const prefix = cssNamespaces.get(call.start)
171
+ const name = `z-style-${id === undefined ? `${prefix ? `${prefix}-` : ''}${Identity.compact(moduleId).slice(-6)}-${authoredNames.get(call.start)!}` : `id-${prefix ? `${prefix}-` : ''}${Identity.requireId(id, 'style').slice(3)}`}`
167
172
  identities.set(call.start, name)
168
173
 
169
174
  return {
@@ -214,7 +214,7 @@ export function render(sections: readonly Section[]) {
214
214
  )
215
215
  throw new ConflictError(
216
216
  section.owner ?? section.source,
217
- `Conflicting stylesheet identity: ${identity.name}; compile libraries with package-qualified module IDs.`,
217
+ `Conflicting stylesheet identity: ${identity.name}; supply distinct declaration ids.`,
218
218
  )
219
219
  identities.set(key, { source: section.source, signature })
220
220
  return
@@ -230,7 +230,7 @@ export function render(sections: readonly Section[]) {
230
230
  )
231
231
  throw new ConflictError(
232
232
  section.owner ?? section.source,
233
- `Conflicting animation identity: ${name}; compile libraries with package-qualified module IDs.`,
233
+ `Conflicting animation identity: ${name}; supply distinct declaration ids.`,
234
234
  )
235
235
 
236
236
  animations.set(name, { source: section.source, signature })
@@ -32,6 +32,8 @@ export type Alias = Call & {
32
32
 
33
33
  /** Theme factory span and generated scope key. */
34
34
  export type Call = {
35
+ /** Whether native defineConfig retains a typed React Provider. */
36
+ readonly nativeProvider?: boolean | undefined
35
37
  readonly variableSet?: boolean | undefined
36
38
  readonly directVariables?: boolean | undefined
37
39
  readonly variableConfig?: boolean | undefined
@@ -102,6 +104,22 @@ export type Link = {
102
104
  readonly members?: Readonly<Record<string, Link>> | undefined
103
105
  }
104
106
 
107
+ /** A readonly variable argument consumed by a native React hook. */
108
+ export type VarsRead = {
109
+ /** Owning configuration fallback. */
110
+ readonly defaultVars: string
111
+ /** Exclusive source offset. */
112
+ readonly end: number
113
+ /** Stable configuration identity for graph-owned native profiles. */
114
+ readonly owner: string
115
+ /** Inclusive source offset. */
116
+ readonly start: number
117
+ /** A standalone definition that does not select a named catalog entry. */
118
+ readonly unnamed: boolean
119
+ /** Complete compatible variable alternatives. */
120
+ readonly vars: Readonly<Record<string, Theme.Definition>>
121
+ }
122
+
105
123
  /** Shared graph data; no filesystem or runtime evaluation is involved. */
106
124
  export type Context = {
107
125
  /** Canonical identifier names collected during graph validation. */
@@ -137,6 +155,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
137
155
  { end: number; output: 'html' | undefined }
138
156
  >()
139
157
  const selections = new Set<string>()
158
+ const selectionUses = new Set<string>()
140
159
  const calls: Call[] = []
141
160
  const scripts = new Set<string>()
142
161
  const definitions = new Map<number, Call>()
@@ -145,10 +164,12 @@ export function collect(program: Ast.Program, options: collect.Options) {
145
164
  const variableImports = new Set<number>()
146
165
  const configImports = new Set<number>()
147
166
  const factoryImports = new Map<number, 'create' | 'define' | 'extend'>()
167
+ const nativeFactories = new Set<string>()
148
168
  const configs = new Map<string, Link>()
149
169
  const configBindings = new Map<number, Link>()
150
170
  const factoryReferences = new Set<number>()
151
171
  const references: Reference[] = []
172
+ const varsReads: VarsRead[] = []
152
173
 
153
174
  const styles = new Map<
154
175
  number,
@@ -166,12 +187,28 @@ export function collect(program: Ast.Program, options: collect.Options) {
166
187
  for (const node of program.body) {
167
188
  if (
168
189
  node.type !== 'ImportDeclaration' ||
169
- node.source.value !== 'zyzz' ||
190
+ !['zyzz', 'zyzz/react-native', 'zyzz/react-native/react'].includes(
191
+ node.source.value,
192
+ ) ||
170
193
  node.importKind === 'type'
171
194
  )
172
195
  continue
173
196
 
174
- for (const specifier of node.specifiers)
197
+ for (const specifier of node.specifiers) {
198
+ if (node.source.value !== 'zyzz') {
199
+ if (
200
+ specifier.type === 'ImportSpecifier' &&
201
+ specifier.importKind !== 'type' &&
202
+ (specifier.imported.type === 'Identifier'
203
+ ? specifier.imported.name
204
+ : specifier.imported.value) === 'defineConfig'
205
+ ) {
206
+ factoryImports.set(specifier.start, 'create')
207
+ nativeFactories.add(specifier.local.name)
208
+ }
209
+ continue
210
+ }
211
+
175
212
  if (
176
213
  specifier.type === 'ImportSpecifier' &&
177
214
  specifier.importKind !== 'type' &&
@@ -208,6 +245,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
208
245
  factoryImports.set(specifier.start, 'define')
209
246
  else factoryImports.set(specifier.start, 'extend')
210
247
  }
248
+ }
211
249
  }
212
250
 
213
251
  if (
@@ -686,11 +724,20 @@ export function collect(program: Ast.Program, options: collect.Options) {
686
724
  }
687
725
 
688
726
  if (config) {
727
+ const nativeProvider =
728
+ member.type === 'Identifier' && nativeFactories.has(member.name)
729
+ if (nativeProvider && !options.native)
730
+ fail(
731
+ 'Native defineConfig requires a native compilation target.',
732
+ expression,
733
+ )
734
+
689
735
  try {
690
736
  const link = Configurations.collect({
691
737
  data,
692
738
  expression,
693
739
  name,
740
+ nativeProvider,
694
741
  resolve: (node) => {
695
742
  const link = resolve(node)
696
743
 
@@ -717,6 +764,8 @@ export function collect(program: Ast.Program, options: collect.Options) {
717
764
  themes[link.call.name] = link.definition
718
765
 
719
766
  for (const { key, id } of bindings) {
767
+ if (key === 'Provider' && link.call.nativeProvider) continue
768
+
720
769
  if (
721
770
  (key === 'style' || key === 'variants') &&
722
771
  !link.call.selection &&
@@ -941,7 +990,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
941
990
  'id-',
942
991
  )
943
992
  )
944
- name = definition.className.slice('z_theme-'.length)
993
+ name = definition.className.slice('z-theme-'.length)
945
994
  tokenType = parent.tokenType
946
995
  output = parent.output
947
996
  }
@@ -977,6 +1026,11 @@ export function collect(program: Ast.Program, options: collect.Options) {
977
1026
  : {}),
978
1027
  })
979
1028
 
1029
+ definition = Token.bind(
1030
+ definition,
1031
+ definition[Token.definition].contract,
1032
+ binding,
1033
+ )
980
1034
  calls.push(call)
981
1035
  definitions.set(variable.id.start, call)
982
1036
  factories.add(expression.start)
@@ -1041,6 +1095,15 @@ export function collect(program: Ast.Program, options: collect.Options) {
1041
1095
  })
1042
1096
 
1043
1097
  for (const { key, id } of bindings) {
1098
+ if (
1099
+ key === 'Provider' &&
1100
+ link.call.nativeProvider &&
1101
+ !link.call.initialization &&
1102
+ !link.call.root &&
1103
+ !link.call.selection
1104
+ )
1105
+ continue
1106
+
1044
1107
  if (
1045
1108
  (key === 'style' || key === 'variants') &&
1046
1109
  !link.call.selection &&
@@ -1346,6 +1409,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
1346
1409
  parent: Ast.Node,
1347
1410
  ancestors: readonly Ast.Node[],
1348
1411
  binding: Walker.ScopeTrackerNode | null,
1412
+ lookup: (name: string) => Walker.ScopeTrackerNode | null,
1349
1413
  ): boolean {
1350
1414
  const grandparent = ancestors.at(-3)
1351
1415
 
@@ -1433,6 +1497,13 @@ export function collect(program: Ast.Program, options: collect.Options) {
1433
1497
  )
1434
1498
  fail('Configuration references must follow their definition.', node)
1435
1499
 
1500
+ if (
1501
+ config.call.variableConfig &&
1502
+ config.call.selection &&
1503
+ readVars(node, parent, config, lookup)
1504
+ )
1505
+ return true
1506
+
1436
1507
  // Root controls are an ordinary runtime object; any read or call is valid.
1437
1508
  if (config.call.root) {
1438
1509
  appearances.add(config.call.name)
@@ -1454,6 +1525,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
1454
1525
 
1455
1526
  if (config.call.selection) {
1456
1527
  selections.add(config.call.name)
1528
+ selectionUses.add(config.call.name)
1457
1529
  scopeApplications.set(parent.start, {
1458
1530
  end: parent.end,
1459
1531
  output: config.call.options?.output === 'html' ? 'html' : undefined,
@@ -1499,6 +1571,24 @@ export function collect(program: Ast.Program, options: collect.Options) {
1499
1571
  path.push(key)
1500
1572
  target = member
1501
1573
 
1574
+ if (
1575
+ path.length === 1 &&
1576
+ path[0] === 'Provider' &&
1577
+ config.call.nativeProvider &&
1578
+ !config.call.initialization &&
1579
+ !config.call.root &&
1580
+ !config.call.selection
1581
+ )
1582
+ return true
1583
+
1584
+ if (
1585
+ config.call.variableConfig &&
1586
+ path.length === 1 &&
1587
+ path[0] === 'vars' &&
1588
+ readVars(target, ancestors[index - 1]!, config, lookup)
1589
+ )
1590
+ return true
1591
+
1502
1592
  if (
1503
1593
  aliasReferences.has(target.start) ||
1504
1594
  factoryReferences.has(target.start)
@@ -1557,6 +1647,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
1557
1647
 
1558
1648
  if (path[0] === 'themes' || path[0] === 'vars') {
1559
1649
  selections.add(config.call.name)
1650
+ selectionUses.add(config.call.name)
1560
1651
  const application = ancestors[index - 1]!
1561
1652
  scopeApplications.set(application.start, {
1562
1653
  end: application.end,
@@ -1618,6 +1709,7 @@ export function collect(program: Ast.Program, options: collect.Options) {
1618
1709
  // A compiled selector is an ordinary runtime function, so passing or storing it is safe.
1619
1710
  if (config.call.selection && !config.call.catalogOnly && !path.length) {
1620
1711
  selections.add(config.call.name)
1712
+ selectionUses.add(config.call.name)
1621
1713
 
1622
1714
  return true
1623
1715
  }
@@ -1635,9 +1727,101 @@ export function collect(program: Ast.Program, options: collect.Options) {
1635
1727
  if (!theme) return false
1636
1728
  if (node.start === binding!.node.start) return true
1637
1729
 
1730
+ if (
1731
+ theme.variableSet &&
1732
+ readVars(
1733
+ node,
1734
+ parent,
1735
+ {
1736
+ call: theme,
1737
+ definition: themes[theme.name]!,
1738
+ },
1739
+ lookup,
1740
+ )
1741
+ )
1742
+ return true
1743
+
1638
1744
  return themeReference(node, parent, ancestors, theme)
1639
1745
  }
1640
1746
 
1747
+ function readVars(
1748
+ node: Ast.Node,
1749
+ parent: Ast.Node,
1750
+ link: Pick<Link, 'call' | 'definition' | 'members'>,
1751
+ lookup: (name: string) => Walker.ScopeTrackerNode | null,
1752
+ ): boolean {
1753
+ if (
1754
+ !options.native ||
1755
+ parent.type !== 'CallExpression' ||
1756
+ parent.optional ||
1757
+ parent.arguments[0] !== node
1758
+ )
1759
+ return false
1760
+
1761
+ const callee = parent.callee
1762
+ const name =
1763
+ callee.type === 'Identifier'
1764
+ ? callee.name
1765
+ : callee.type === 'MemberExpression' &&
1766
+ !callee.computed &&
1767
+ !callee.optional &&
1768
+ callee.object.type === 'Identifier' &&
1769
+ callee.property.type === 'Identifier' &&
1770
+ ['useAnimatedVars', 'useVars'].includes(callee.property.name)
1771
+ ? callee.object.name
1772
+ : undefined
1773
+ const binding = name === undefined ? undefined : lookup(name)
1774
+ if (
1775
+ binding?.type !== 'Import' ||
1776
+ ![
1777
+ 'zyzz/react-native',
1778
+ 'zyzz/react-native/reanimated',
1779
+ 'zyzz/react-native/react',
1780
+ ].includes(binding.importNode.source.value) ||
1781
+ binding.importNode.importKind === 'type'
1782
+ )
1783
+ return false
1784
+
1785
+ const specifier = binding.node
1786
+ if (
1787
+ callee.type === 'Identifier'
1788
+ ? specifier.type !== 'ImportSpecifier' ||
1789
+ specifier.importKind === 'type' ||
1790
+ !['useAnimatedVars', 'useVars'].includes(
1791
+ specifier.imported.type === 'Identifier'
1792
+ ? specifier.imported.name
1793
+ : specifier.imported.value,
1794
+ )
1795
+ : specifier.type !== 'ImportNamespaceSpecifier'
1796
+ )
1797
+ return false
1798
+
1799
+ const named = link.call.options?.themes !== undefined
1800
+ const vars = (() => {
1801
+ if (!named) return { default: link.definition }
1802
+ return Object.fromEntries(
1803
+ Object.entries(link.members ?? {}).flatMap((entry) => {
1804
+ const [key, member] = entry
1805
+ const path = JSON.parse(key) as string[]
1806
+ if (path.length === 1 && link.call.selection)
1807
+ return [[path[0]!, member.definition]]
1808
+ if (path.length === 2 && path[0] === 'themes')
1809
+ return [[path[1]!, member.definition]]
1810
+ return []
1811
+ }),
1812
+ )
1813
+ })()
1814
+ varsReads.push({
1815
+ defaultVars: named ? String(link.call.options!.defaultTheme) : 'default',
1816
+ end: node.end,
1817
+ owner: link.call.name,
1818
+ start: node.start,
1819
+ unnamed: !named,
1820
+ vars,
1821
+ })
1822
+ return true
1823
+ }
1824
+
1641
1825
  function themeReference(
1642
1826
  node: Ast.Node,
1643
1827
  parent: Ast.Node,
@@ -2018,6 +2202,8 @@ export function collect(program: Ast.Program, options: collect.Options) {
2018
2202
  const entries = Object.entries(config.members ?? {}).flatMap(
2019
2203
  ([key, value]) => {
2020
2204
  const path = JSON.parse(key) as string[]
2205
+ if (config.call.selection && path.length === 1)
2206
+ return [[path[0]!, value.definition] as const]
2021
2207
  return (path[0] === 'themes' || path[0] === 'vars') &&
2022
2208
  path.length === 2
2023
2209
  ? [[path[1]!, value.definition] as const]
@@ -2040,10 +2226,12 @@ export function collect(program: Ast.Program, options: collect.Options) {
2040
2226
  scopeApplications,
2041
2227
  scripts,
2042
2228
  selections,
2229
+ selectionUses,
2043
2230
  staticTokens,
2044
2231
  styles,
2045
2232
  themes: Object.freeze(themes),
2046
2233
  tokens,
2234
+ varsReads,
2047
2235
  }
2048
2236
  }
2049
2237
 
@@ -2051,6 +2239,8 @@ export function collect(program: Ast.Program, options: collect.Options) {
2051
2239
  export declare namespace collect {
2052
2240
  /** Stable module namespace, independent of token values and call offsets. */
2053
2241
  type Options = {
2242
+ /** Captures readonly variable arguments for native React hooks. */
2243
+ readonly native?: boolean | undefined
2054
2244
  /** Encoded package/module identity from the source adapter. */
2055
2245
  readonly staticBindings?: ReadonlySet<number> | undefined
2056
2246
  readonly contributionCalls?: ReadonlySet<number> | undefined