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
@@ -6,7 +6,10 @@ import * as Contributions from './internal/Contributions.js'
6
6
  import * as Stylesheets from './internal/Stylesheets.js'
7
7
  import type * as Mapping from '@jridgewell/gen-mapping'
8
8
  import * as Css from '../web/Css.js'
9
+ import * as ClassName from '../web/internal/ClassName.js'
9
10
  import * as Native from './Native.js'
11
+ import * as NativeVars from './internal/NativeVars.js'
12
+ import * as NativeStyleSheet from '../react-native/StyleSheet.js'
10
13
  import * as Edits from './internal/Edits.js'
11
14
  import * as Identity from '../internal/Identity.js'
12
15
  import type * as Ast from '@oxc-project/types'
@@ -39,6 +42,8 @@ export declare namespace compile {
39
42
 
40
43
  /** Source modules available for relative import resolution. */
41
44
  type Options = {
45
+ /** CSS-only hosts publish variable scopes once with shared rules. */
46
+ readonly [ThemeRules.shared]?: 'all' | 'defaults' | undefined
42
47
  /** Host entrypoints emit owned stylesheet effects without packed contracts. */
43
48
  readonly [Stylesheets.entry]?: string | undefined
44
49
  /** Host syntax from the same immutable source snapshot. */
@@ -156,6 +161,7 @@ type Cache = {
156
161
  native: compile.Options['native']
157
162
  result: compile.ReturnType
158
163
  schemes: boolean
164
+ shared?: 'all' | 'defaults' | undefined
159
165
  sources: Readonly<Record<string, string>>
160
166
  themes: Readonly<Record<string, Theme.Definition>>
161
167
  }
@@ -193,6 +199,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
193
199
  if (cache?.reset !== options.reset) cache = undefined
194
200
  if (cache?.cssOutput !== options.cssOutput) cache = undefined
195
201
  if (cache?.composition !== options.composition) cache = undefined
202
+ if (cache?.shared !== options[ThemeRules.shared]) cache = undefined
196
203
  if (
197
204
  (cache?.entry === undefined) !==
198
205
  (options[Stylesheets.entry] === undefined)
@@ -295,7 +302,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
295
302
  previous.type !== slot.type)
296
303
  )
297
304
  throw new Error(
298
- `Conflicting packed variable identity: ${slot.name}; compile libraries with package-qualified module IDs.`,
305
+ `Conflicting packed variable identity: ${slot.name}; supply distinct declaration ids.`,
299
306
  )
300
307
 
301
308
  variableSlots.set(slot.name, {
@@ -1014,7 +1021,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1014
1021
  )
1015
1022
  fail(
1016
1023
  moduleId,
1017
- `Conflicting variable identity: ${slot.name}; compile libraries with package-qualified module IDs.`,
1024
+ `Conflicting variable identity: ${slot.name}; supply distinct declaration ids.`,
1018
1025
  call,
1019
1026
  )
1020
1027
 
@@ -1081,10 +1088,82 @@ function build(options: compile.Options, cache?: Cache): Cache {
1081
1088
  : {}),
1082
1089
  }
1083
1090
  }
1091
+ const profiles = new Map<
1092
+ string,
1093
+ {
1094
+ definitions: Map<string, string>
1095
+ reads: Map<number, { name: string; source?: string }>
1096
+ }
1097
+ >()
1098
+ const reserved = new Set(
1099
+ [...identifiers.values()].flatMap((names) => [...names]),
1100
+ )
1101
+ function profile(moduleId: string) {
1102
+ let value = profiles.get(moduleId)
1103
+ if (!value) {
1104
+ value = { definitions: new Map(), reads: new Map() }
1105
+ profiles.set(moduleId, value)
1106
+ }
1107
+ return value
1108
+ }
1109
+ if (ids.some((id) => extracted.get(id)!.nativeVars?.length))
1110
+ NativeStyleSheet.compile({
1111
+ fonts: native.fonts,
1112
+ platform: native.platform,
1113
+ units: native.units,
1114
+ styles: { styles: [] },
1115
+ })
1116
+ for (const moduleId of ids) {
1117
+ for (const read of extracted.get(moduleId)!.nativeVars ?? []) {
1118
+ const owner = owners[read.owner]?.moduleId
1119
+ // Single-file adapters cannot publish changes to dependency modules.
1120
+ // Packed catalogs without source also retain their local fallback.
1121
+ if (
1122
+ native[Edits.runtime] ||
1123
+ !owner ||
1124
+ !Object.hasOwn(options.modules, owner)
1125
+ )
1126
+ continue
1127
+ let value: string
1128
+ try {
1129
+ value = JSON.stringify(
1130
+ NativeVars.compile({
1131
+ ...read,
1132
+ fonts: native.fonts,
1133
+ units: native.units,
1134
+ }),
1135
+ )
1136
+ } catch (error) {
1137
+ throw new Native.CompileError((error as Error).message)
1138
+ }
1139
+ const definitions = profile(owner).definitions
1140
+ let name = definitions.get(value)
1141
+ if (!name) {
1142
+ name = `__zyzzProfile${Identity.hash(value)}`
1143
+ while (reserved.has(name)) name += '_'
1144
+ reserved.add(name)
1145
+ definitions.set(value, name)
1146
+ }
1147
+ const from = moduleId.split('/').slice(0, -1)
1148
+ const to = owner.split('/')
1149
+ while (from.length && from[0] === to[0]) {
1150
+ from.shift()
1151
+ to.shift()
1152
+ }
1153
+ const source =
1154
+ (from.length ? '../'.repeat(from.length) : './') +
1155
+ to.join('/').replace(/\.([cm]?)tsx?$/, '.$1js')
1156
+ profile(moduleId).reads.set(read.start, {
1157
+ name,
1158
+ ...(owner !== moduleId ? { source } : {}),
1159
+ })
1160
+ }
1161
+ }
1084
1162
  const modules = Object.fromEntries(
1085
1163
  ids.map((moduleId) => {
1086
1164
  if (
1087
1165
  previous &&
1166
+ !profiles.size &&
1088
1167
  extracted.get(moduleId) === previous.extracted.get(moduleId)
1089
1168
  )
1090
1169
  return [moduleId, previous.result.modules[moduleId]!]
@@ -1128,6 +1207,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1128
1207
  }
1129
1208
  const output = Native.compile({
1130
1209
  ...native,
1210
+ [NativeVars.shared]: profiles.get(moduleId),
1131
1211
  moduleId,
1132
1212
  source: options.modules[moduleId]!,
1133
1213
  [Themes.context]: {
@@ -1455,23 +1535,26 @@ function build(options: compile.Options, cache?: Cache): Cache {
1455
1535
  for (const library of Object.values(libraries))
1456
1536
  for (const link of Object.values(library.links)) published(link)
1457
1537
 
1458
- const atomicOwners = new Map<string, string>()
1459
- function packedOwners(link: Themes.Link, moduleId: string) {
1460
- for (const name of link.style?.className?.split(' ') ?? []) {
1461
- if (
1462
- !name.startsWith('z-') ||
1463
- name.startsWith('z-style-') ||
1464
- name.startsWith('z-content-')
1465
- )
1466
- continue
1467
- if (!atomicOwners.has(name)) atomicOwners.set(name, moduleId)
1538
+ const emittedRules = new Map<string, { body: string; moduleId: string }>()
1539
+ function registerRules(
1540
+ classRules: Readonly<Record<string, string>>,
1541
+ moduleId: string,
1542
+ ) {
1543
+ for (const [name, body] of Object.entries(classRules)) {
1544
+ const previous = emittedRules.get(name)
1545
+ if (previous && previous.body !== body)
1546
+ throw new Css.CompileError([
1547
+ {
1548
+ code: 'identity_collision',
1549
+ message: `Generated ${name.startsWith('@scope:') ? `scope ${name.split(':')[1]}` : `class ${name}`} conflicts with module ${previous.moduleId}. Supply distinct config or style ids.`,
1550
+ path: [moduleId],
1551
+ },
1552
+ ])
1553
+ emittedRules.set(name, { body, moduleId })
1468
1554
  }
1469
- for (const member of Object.values(link.members ?? {}))
1470
- packedOwners(member, moduleId)
1471
1555
  }
1472
1556
  for (const [moduleId, library] of Object.entries(libraries))
1473
- for (const link of Object.values(library.links))
1474
- packedOwners(link, moduleId)
1557
+ registerRules(library.classRules, moduleId)
1475
1558
  if (options.compiler === false) {
1476
1559
  const identities = new Map<string, string>()
1477
1560
  for (const [moduleId, library] of Object.entries(libraries)) {
@@ -1570,7 +1653,9 @@ function build(options: compile.Options, cache?: Cache): Cache {
1570
1653
  ? previous!.result.modules[moduleId]!
1571
1654
  : Transform.compile({
1572
1655
  [ThemeRules.shared]:
1573
- options[Stylesheets.entry] === undefined ? 'defaults' : 'all',
1656
+ options[Stylesheets.entry] === undefined
1657
+ ? (options[ThemeRules.shared] ?? 'defaults')
1658
+ : 'all',
1574
1659
  compiler: options.compiler,
1575
1660
  development: options.development,
1576
1661
  composition: options.composition,
@@ -1610,34 +1695,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1610
1695
  })
1611
1696
  if (transformed.size > 256)
1612
1697
  transformed.delete(transformed.keys().next().value!)
1613
- // Module-local checks cannot detect truncated ownership hashes colliding across files.
1614
- const emitted = new Set(
1615
- Array.from(
1616
- modules[moduleId]!.css.matchAll(/\.(z-[\w-]+)\{/g),
1617
- (match) => match[1],
1618
- ),
1619
- )
1620
- for (const value of Object.values(modules[moduleId]!.classes))
1621
- for (const name of value.split(' ')) {
1622
- if (
1623
- options.compiler === false ||
1624
- !name.startsWith('z-') ||
1625
- !emitted.has(name)
1626
- )
1627
- continue
1628
-
1629
- const owner = atomicOwners.get(name)
1630
- if (owner !== undefined && owner !== moduleId)
1631
- throw new Css.CompileError([
1632
- {
1633
- code: 'invalid_name',
1634
- message: `Atomic class ${name} is also owned by module ${owner}.`,
1635
- path: [moduleId],
1636
- },
1637
- ])
1638
-
1639
- atomicOwners.set(name, moduleId)
1640
- }
1698
+ registerRules(modules[moduleId]![ClassName.rules], moduleId)
1641
1699
 
1642
1700
  for (const call of extracted.get(moduleId)!.calls)
1643
1701
  if (
@@ -1651,20 +1709,32 @@ function build(options: compile.Options, cache?: Cache): Cache {
1651
1709
 
1652
1710
  const defaults = new Set<string>()
1653
1711
  const defaultRules = new Map<string, ThemeRules.Rule[]>()
1712
+ const defaultSections: Stylesheets.Section[] = []
1654
1713
  if (options[Stylesheets.entry] === undefined)
1655
1714
  for (const [source, output] of Object.entries(modules))
1656
1715
  for (const resource of output[ThemeRules.shared] ?? []) {
1657
1716
  if (defaults.has(resource.id)) continue
1658
1717
  defaults.add(resource.id)
1659
1718
 
1719
+ if (!resource.rules) {
1720
+ defaultSections.push({
1721
+ css: resource.css,
1722
+ key: resource.id,
1723
+ layers: [],
1724
+ source,
1725
+ })
1726
+ continue
1727
+ }
1728
+
1660
1729
  const rules = defaultRules.get(source) ?? []
1661
- rules.push(...(resource.rules ?? []))
1730
+ rules.push(...resource.rules)
1662
1731
  defaultRules.set(source, rules)
1663
1732
  }
1664
1733
 
1665
1734
  const shared = defaults.size
1666
1735
  ? renderShared([
1667
1736
  ...sharedSections,
1737
+ ...defaultSections,
1668
1738
  ...[...defaultRules].map(([source, rules]) => ({
1669
1739
  css: ThemeRules.render(rules),
1670
1740
  key: 'theme-defaults',
@@ -1675,6 +1745,22 @@ function build(options: compile.Options, cache?: Cache): Cache {
1675
1745
  : contributions
1676
1746
  const sharedCss = shared.css
1677
1747
 
1748
+ function publishedRules(
1749
+ id: string,
1750
+ visited = new Set<string>(),
1751
+ ): Readonly<Record<string, string>> {
1752
+ if (visited.has(id)) return {}
1753
+ visited.add(id)
1754
+ return Object.assign(
1755
+ {},
1756
+ ...(dependencies[id] ?? []).map((dependency) =>
1757
+ publishedRules(dependency, visited),
1758
+ ),
1759
+ libraries[id]?.classRules,
1760
+ modules[id]?.[ClassName.rules],
1761
+ )
1762
+ }
1763
+
1678
1764
  function publishedStyle(link: Themes.Link): Themes.Link {
1679
1765
  return {
1680
1766
  ...link,
@@ -1733,6 +1819,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1733
1819
 
1734
1820
  return {
1735
1821
  compiler: options.compiler !== false,
1822
+ shared: options[ThemeRules.shared],
1736
1823
  composition: options.composition,
1737
1824
  cssOutput: options.cssOutput,
1738
1825
  contracts,
@@ -1803,6 +1890,7 @@ function build(options: compile.Options, cache?: Cache): Cache {
1803
1890
  })),
1804
1891
  id,
1805
1892
  configurations(id),
1893
+ publishedRules(id),
1806
1894
  ),
1807
1895
  ]),
1808
1896
  ),
@@ -1825,6 +1913,7 @@ function nativeOutput(
1825
1913
  let sourceMap: Mapping.EncodedSourceMap | undefined
1826
1914
 
1827
1915
  return Object.freeze({
1916
+ [ClassName.rules]: Object.freeze({}),
1828
1917
  classes: Object.freeze({}),
1829
1918
  [Edits.key]: output[Edits.key],
1830
1919
  code: output.code,
@@ -5,6 +5,8 @@ import type * as Recipe from '../internal/Recipe.js'
5
5
  import * as Source from './Source.js'
6
6
  import * as Edits from './internal/Edits.js'
7
7
  import * as NativeBindings from './internal/NativeBindings.js'
8
+ import * as NativeMedia from './internal/NativeMedia.js'
9
+ import * as NativeVars from './internal/NativeVars.js'
8
10
  import * as Themes from './internal/Themes.js'
9
11
  import * as StyleSheet from '../react-native/StyleSheet.js'
10
12
  import * as Syntax from './internal/Syntax.js'
@@ -12,7 +14,7 @@ import * as Variants from '../react-native/Variants.js'
12
14
  import * as Walker from 'oxc-walker'
13
15
 
14
16
  /**
15
- * Compiles local style and variants calls for an explicit native context.
17
+ * Compiles local styles, variants, and variable reads for an explicit native target.
16
18
  * @param options - Shared source, destination mappings, and selected set/scheme.
17
19
  * @returns Native callables, source map, and static recipe tables.
18
20
  * @throws {Source.ExtractError} For invalid source authoring.
@@ -50,9 +52,13 @@ export function compile(options: compile.Options): compile.ReturnType {
50
52
  })
51
53
  let helper = '__zyzzNative'
52
54
  while (
53
- [helper, `${helper}Context`, `${helper}Dynamic`].some((name) =>
54
- names.has(name),
55
- )
55
+ [
56
+ helper,
57
+ `${helper}Context`,
58
+ `${helper}Dynamic`,
59
+ `${helper}Static`,
60
+ `${helper}Vars`,
61
+ ].some((name) => names.has(name))
56
62
  )
57
63
  helper += '_'
58
64
  let dynamicHelper = `${helper}Dynamic`
@@ -70,6 +76,7 @@ export function compile(options: compile.Options): compile.ReturnType {
70
76
  }
71
77
  const recipes: Record<string, Variants.Definition> = Object.create(null)
72
78
  let dynamic = false
79
+ let finite = false
73
80
  const contexts = new Map<string, string>()
74
81
  const compiledCalls = new WeakMap<
75
82
  Variants.Definition,
@@ -92,6 +99,54 @@ export function compile(options: compile.Options): compile.ReturnType {
92
99
  }
93
100
 
94
101
  const staticTables = new Map<Source.Call, Variants.Definition>()
102
+ if (extracted.nativeVars?.length)
103
+ StyleSheet.compile({
104
+ fonts: options.fonts,
105
+ platform: options.platform,
106
+ styles: { styles: [] },
107
+ units: options.units,
108
+ })
109
+
110
+ const shared = options[NativeVars.shared]
111
+ const variables = new Map(shared?.definitions)
112
+ const imports = new Set<string>()
113
+ for (const read of extracted.nativeVars ?? []) {
114
+ const imported = shared?.reads.get(read.start)
115
+ if (imported) {
116
+ if (imported.source)
117
+ imports.add(
118
+ `import {${imported.name}} from ${JSON.stringify(imported.source)};`,
119
+ )
120
+ const type = typed
121
+ ? ` as typeof ${options.source.slice(read.start, read.end)}`
122
+ : ''
123
+ overwrite(read.start, read.end, `(${imported.name}${type})`, true)
124
+ continue
125
+ }
126
+ const definition = (() => {
127
+ try {
128
+ return NativeVars.compile({
129
+ ...read,
130
+ fonts: options.fonts,
131
+ units: options.units,
132
+ })
133
+ } catch (error) {
134
+ throw new CompileError((error as Error).message)
135
+ }
136
+ })()
137
+ const key = JSON.stringify(definition)
138
+ let name = variables.get(key)
139
+ if (!name) {
140
+ name = `${helper}Vars${variables.size}`
141
+ while (names.has(name)) name += '_'
142
+ names.add(name)
143
+ variables.set(key, name)
144
+ }
145
+ const type = typed
146
+ ? ` as typeof ${options.source.slice(read.start, read.end)}`
147
+ : ''
148
+ overwrite(read.start, read.end, `(${name}${type})`, true)
149
+ }
95
150
  if (options.contextual) {
96
151
  const groups = new Map<StyleSheet.compile.Options['vars'], Source.Call[]>()
97
152
  for (const call of extracted.calls) {
@@ -104,6 +159,15 @@ export function compile(options: compile.Options): compile.ReturnType {
104
159
  )
105
160
  continue
106
161
  const vars = call.nativeContext?.vars ?? options.vars
162
+ try {
163
+ if (
164
+ NativeMedia.prepare(stylesByName.get(call.name) ?? [], vars, options)
165
+ )
166
+ continue
167
+ } catch (error) {
168
+ throw new CompileError((error as Error).message)
169
+ }
170
+
107
171
  const group = groups.get(vars)
108
172
  if (group) group.push(call)
109
173
  else groups.set(vars, [call])
@@ -233,9 +297,58 @@ export function compile(options: compile.Options): compile.ReturnType {
233
297
  compiled?: Variants.Definition,
234
298
  bindings?: ReturnType<typeof NativeBindings.prepare>,
235
299
  ): string {
300
+ const program =
301
+ Object.keys(recipe.axes).length > 0 ||
302
+ call?.slots ||
303
+ call?.recipe?.payloads?.length
304
+
236
305
  if (contextOptions.contextual) {
237
306
  const vars = call?.nativeContext?.vars ?? contextOptions.vars
238
- if (!call?.slots && !call?.recipe?.payloads?.length)
307
+ const media = (() => {
308
+ try {
309
+ return NativeMedia.prepare(
310
+ recipe.rules.flatMap((rule) => rule.value.styles),
311
+ vars,
312
+ contextOptions,
313
+ )
314
+ } catch (error) {
315
+ throw new CompileError((error as Error).message)
316
+ }
317
+ })()
318
+ if (media) {
319
+ const profiles = media.selections.map((selection) => {
320
+ const selected = media.select(selection)
321
+ const next = {
322
+ ...recipe,
323
+ rules: recipe.rules.map((rule) => ({
324
+ ...rule,
325
+ value: {
326
+ ...rule.value,
327
+ styles: rule.value.styles.map(selected.style),
328
+ },
329
+ })),
330
+ }
331
+ const source = call?.nativeContext
332
+ ? {
333
+ ...call,
334
+ nativeContext: {
335
+ ...call.nativeContext,
336
+ vars: selected.vars as typeof call.nativeContext.vars,
337
+ },
338
+ }
339
+ : call
340
+ const value = callable(next, name, source, {
341
+ ...contextOptions,
342
+ vars: selected.vars,
343
+ })
344
+ return `${JSON.stringify(selection)}:${value}`
345
+ })
346
+ // A single static table cannot represent the responsive callable.
347
+ delete recipes[name]
348
+
349
+ return `${helper}Context.responsive(${JSON.stringify(media.queries)},{${profiles.join(',')}})`
350
+ }
351
+ if (!program)
239
352
  compiled ??= Variants.compile({
240
353
  recipe,
241
354
  fonts: contextOptions.fonts,
@@ -245,7 +358,7 @@ export function compile(options: compile.Options): compile.ReturnType {
245
358
  })
246
359
  else {
247
360
  try {
248
- bindings = NativeBindings.prepare(recipe, call!, {
361
+ bindings = NativeBindings.prepare(recipe, call ?? {}, {
249
362
  ...contextOptions,
250
363
  vars,
251
364
  })
@@ -315,18 +428,36 @@ export function compile(options: compile.Options): compile.ReturnType {
315
428
  }
316
429
  return `${context}(${[...tables.keys()].join(',')})`
317
430
  }
318
- if (call?.slots || call?.recipe?.payloads?.length) {
319
- dynamic = true
431
+ const axes = Object.entries(recipe.axes)
432
+ .map(
433
+ ([axis, choices]) =>
434
+ `${JSON.stringify(axis)}:readonly ${JSON.stringify(choices)}`,
435
+ )
436
+ .join(';')
437
+
438
+ if (program) {
439
+ const scalar = !!(call?.slots || call?.recipe?.payloads?.length)
440
+ dynamic ||= scalar
441
+ finite ||= !scalar
320
442
  const compiled = (() => {
321
443
  try {
322
- return NativeBindings.compile(recipe, call, contextOptions, bindings)
444
+ const compiled = NativeBindings.compile(
445
+ recipe,
446
+ call ?? {},
447
+ contextOptions,
448
+ bindings,
449
+ )
450
+ return scalar ? compiled : NativeBindings.finite(compiled)
323
451
  } catch (error) {
324
452
  if (error instanceof StyleSheet.CompileError) throw error
325
453
  throw new CompileError((error as Error).message)
326
454
  }
327
455
  })()
328
- const value = create(dynamicHelper, compiled)
456
+ const value = create(scalar ? dynamicHelper : `${helper}Static`, compiled)
329
457
  if (!typed) return value
458
+ if (!call?.slots && !call?.recipe?.payloads?.length)
459
+ return `(${value} as import('zyzz/runtime').Native.Callable<{${axes}}>)`
460
+
330
461
  let input = call.valuesType ?? '{}'
331
462
  if (call.recipe) {
332
463
  input = `{${Object.entries(recipe.axes)
@@ -371,12 +502,6 @@ export function compile(options: compile.Options): compile.ReturnType {
371
502
  })
372
503
  if (options.contextual) compiledCalls.set(compiled, { styles, value })
373
504
  if (!typed) return value
374
- const axes = Object.entries(compiled.axes)
375
- .map(
376
- ([axis, choices]) =>
377
- `${JSON.stringify(axis)}:readonly ${JSON.stringify(choices)}`,
378
- )
379
- .join(';')
380
505
  return `(${value} as import('zyzz/runtime').Native.Callable<{${axes}}>)`
381
506
  }
382
507
 
@@ -483,10 +608,9 @@ export function compile(options: compile.Options): compile.ReturnType {
483
608
  throw new CompileError(
484
609
  `Packed native callable ${name} requires a static recipe contract.`,
485
610
  )
486
- const expression = callable(
487
- recipe,
488
- `${specifier}:${name}`,
489
- link.style?.dynamic
611
+ const expression = callable(recipe, `${specifier}:${name}`, {
612
+ nativeContext: link.style?.nativeContext,
613
+ ...(link.style?.dynamic
490
614
  ? {
491
615
  slots: link.style.dynamic.slots,
492
616
  recipe: {
@@ -496,8 +620,8 @@ export function compile(options: compile.Options): compile.ReturnType {
496
620
  defaultPayloads: link.style.dynamic.defaultPayloads,
497
621
  },
498
622
  }
499
- : undefined,
500
- )
623
+ : {}),
624
+ })
501
625
  if (!link.style?.dynamic || !typed) return expression
502
626
  const type = `typeof import(${JSON.stringify(specifier)})${path
503
627
  .map((part) => `[${JSON.stringify(part)}]`)
@@ -698,7 +822,13 @@ export function compile(options: compile.Options): compile.ReturnType {
698
822
  imports.length ? `import ${imports.join(',')} from 'zyzz';` : '',
699
823
  )
700
824
  }
701
- if (extracted.calls.length || compositions.length || packed.length) {
825
+ if (
826
+ extracted.calls.length ||
827
+ compositions.length ||
828
+ packed.length ||
829
+ variables.size ||
830
+ imports.size
831
+ ) {
702
832
  let offset = 0
703
833
  if (options.source.startsWith('#!')) {
704
834
  const newline = /\r\n|[\n\r\u2028\u2029]/.exec(options.source)
@@ -713,7 +843,7 @@ export function compile(options: compile.Options): compile.ReturnType {
713
843
  offset = node.end
714
844
  }
715
845
 
716
- const prelude = `\nimport {Native as ${helper}${dynamic ? `,NativeDynamic as ${dynamicHelper}` : ''}${options.contextual ? `,NativeContext as ${helper}Context` : ''}} from 'zyzz/runtime';\n${[...factories].map(([expression, factory]) => `const ${factory.name}=(${factory.parameters.join(',')})=>${expression};`).join('\n')}\n${[...contexts].map(([expression, name]) => `const ${name}=${expression};`).join('\n')}\n${[...compositions, ...packed].join('\n')}\n`
846
+ const prelude = `\nimport {Native as ${helper}${dynamic ? `,NativeDynamic as ${dynamicHelper}` : ''}${finite ? `,NativeStatic as ${helper}Static` : ''}${options.contextual ? `,NativeContext as ${helper}Context` : ''}${variables.size ? `,NativeVars as ${helper}Vars` : ''}} from 'zyzz/runtime';\n${[...factories].map(([expression, factory]) => `const ${factory.name}=(${factory.parameters.join(',')})=>${expression};`).join('\n')}\n${[...contexts].map(([expression, name]) => `const ${name}=${expression};`).join('\n')}\n${[...variables].map(([value, name]) => `${shared?.definitions.has(value) ? 'export ' : ''}const ${name}=${helper}Vars.create(JSON.parse(${JSON.stringify(value)}));`).join('\n')}\n${[...imports, ...compositions, ...packed].join('\n')}\n`
717
847
  module.appendLeft(offset, prelude)
718
848
  edits.push({ start: offset, end: offset, code: prelude, expression: false })
719
849
  }
@@ -738,6 +868,8 @@ export declare namespace compile {
738
868
  type Options = Omit<StyleSheet.compile.Options, 'styles'> & {
739
869
  /** Internal Babel emission mode; authoring types are still validated. */
740
870
  readonly [Edits.runtime]?: boolean | undefined
871
+ /** Compiler-owned shared native variable profiles. */
872
+ readonly [NativeVars.shared]?: NativeVars.Shared | undefined
741
873
  /** Compiler-owned graph context. */
742
874
  readonly [Themes.context]?: Themes.Context | undefined
743
875
  /** Retain every set and scheme for render-local selection. */
@@ -751,7 +883,7 @@ export declare namespace compile {
751
883
  /** Label selected from supplied vars. Defaults to the token-fallback default table. */
752
884
  readonly set?: string | undefined
753
885
  }
754
- /** Executable source with immutable recipe tables and authored source mappings. */
886
+ /** Executable source with immutable native data and authored source mappings. */
755
887
  type ReturnType = {
756
888
  /** Internal node replacements for syntax-tree adapters. */
757
889
  readonly [Edits.key]: readonly Edits.Edit[]
@@ -759,7 +891,7 @@ export declare namespace compile {
759
891
  readonly code: string
760
892
  /** Version-three source map encoded as JSON. */
761
893
  readonly map: string
762
- /** All set/scheme tables for each extracted definition. */
894
+ /** Set/scheme tables for definitions without variant or scalar programs. */
763
895
  readonly recipes: Readonly<Record<string, Variants.Definition>>
764
896
  }
765
897
  }