@yahoo/uds-create-config 2.44.0 → 3.0.0

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 (376) hide show
  1. package/README.md +129 -0
  2. package/dist/ai-lanes.d.ts +23 -0
  3. package/dist/ai-lanes.js +34 -0
  4. package/dist/authoring/define-component.d.ts +85 -0
  5. package/dist/configs/CanvasConfig.d.ts +3237 -0
  6. package/dist/configs/CanvasConfig.js +332 -0
  7. package/dist/configs/build-options.d.ts +10 -0
  8. package/dist/configs/build-options.js +68 -0
  9. package/dist/configs/platform.d.ts +15 -0
  10. package/dist/configs/platform.js +17 -0
  11. package/dist/configs/react-native-system.d.ts +3026 -0
  12. package/dist/configs/react-native-system.js +64 -0
  13. package/dist/configs/system.d.ts +2771 -0
  14. package/dist/configs/system.js +74 -0
  15. package/dist/css/properties.generated.d.ts +14 -0
  16. package/dist/css/properties.generated.js +6260 -0
  17. package/dist/css/value-type.d.ts +48 -0
  18. package/dist/css/value-type.js +131 -0
  19. package/dist/css/values.d.ts +33 -0
  20. package/dist/css/values.js +116 -0
  21. package/dist/entities/native/NativeModifier.d.ts +25 -0
  22. package/dist/entities/native/NativeModifier.js +41 -0
  23. package/dist/entities/native/NativeSettings.d.ts +44 -0
  24. package/dist/entities/native/NativeSettings.js +39 -0
  25. package/dist/entities/native/NativeStyleProperty.d.ts +355 -0
  26. package/dist/entities/native/NativeStyleProperty.js +28 -0
  27. package/dist/entities/native/NativeToken.d.ts +31 -0
  28. package/dist/entities/native/NativeToken.js +49 -0
  29. package/dist/entities/system/CanvasRole.d.ts +34 -0
  30. package/dist/entities/system/CanvasRole.js +45 -0
  31. package/dist/entities/system/Component.d.ts +1287 -0
  32. package/dist/entities/system/Component.js +1840 -0
  33. package/dist/entities/system/Composite.d.ts +12 -0
  34. package/dist/entities/system/Composite.js +26 -0
  35. package/dist/entities/system/Device.d.ts +11 -0
  36. package/dist/entities/system/Device.js +18 -0
  37. package/dist/entities/system/File.d.ts +72 -0
  38. package/dist/entities/system/File.js +136 -0
  39. package/dist/entities/system/Font.d.ts +48 -0
  40. package/dist/entities/system/Font.js +56 -0
  41. package/dist/entities/system/GlobalStyle.d.ts +26 -0
  42. package/dist/entities/system/GlobalStyle.js +54 -0
  43. package/dist/entities/system/Guidance.d.ts +85 -0
  44. package/dist/entities/system/Guidance.js +59 -0
  45. package/dist/entities/system/GuidanceStyle.d.ts +14 -0
  46. package/dist/entities/system/GuidanceStyle.js +8 -0
  47. package/dist/entities/system/Icon.d.ts +46 -0
  48. package/dist/entities/system/Icon.js +46 -0
  49. package/dist/entities/system/LinkedSystem.d.ts +504 -0
  50. package/dist/entities/system/LinkedSystem.js +814 -0
  51. package/dist/entities/system/Modifier.d.ts +92 -0
  52. package/dist/entities/system/Modifier.js +120 -0
  53. package/dist/entities/system/Motion.d.ts +28 -0
  54. package/dist/entities/system/Motion.js +48 -0
  55. package/dist/entities/system/Operation.d.ts +100 -0
  56. package/dist/entities/system/Operation.js +236 -0
  57. package/dist/entities/system/Package.d.ts +42 -0
  58. package/dist/entities/system/Package.js +75 -0
  59. package/dist/entities/system/Settings.d.ts +94 -0
  60. package/dist/entities/system/Settings.js +166 -0
  61. package/dist/entities/system/StyleProperty.d.ts +135 -0
  62. package/dist/entities/system/StyleProperty.js +438 -0
  63. package/dist/entities/system/Token.d.ts +67 -0
  64. package/dist/entities/system/Token.js +129 -0
  65. package/dist/entities/system/Tool.d.ts +134 -0
  66. package/dist/entities/system/Tool.js +124 -0
  67. package/dist/entities/system/color.d.ts +64 -0
  68. package/dist/entities/system/color.js +123 -0
  69. package/dist/entities/system/component-module.d.ts +63 -0
  70. package/dist/entities/system/component-module.js +258 -0
  71. package/dist/entities/system/copy-plan.d.ts +98 -0
  72. package/dist/entities/system/copy-plan.js +451 -0
  73. package/dist/entities/system/defineComponent.d.ts +428 -0
  74. package/dist/entities/system/defineComponent.js +337 -0
  75. package/dist/entities/system/element.d.ts +101 -0
  76. package/dist/entities/system/element.js +171 -0
  77. package/dist/entities/system/icon-library.d.ts +64 -0
  78. package/dist/entities/system/icon-library.js +112 -0
  79. package/dist/entities/system/icon-metadata.d.ts +72 -0
  80. package/dist/entities/system/icon-metadata.js +111 -0
  81. package/dist/entities/system/link-declaration.d.ts +27 -0
  82. package/dist/entities/system/link-declaration.js +64 -0
  83. package/dist/entities/system/link-plan.d.ts +160 -0
  84. package/dist/entities/system/link-plan.js +770 -0
  85. package/dist/entities/system/runtime-modules.d.ts +25 -0
  86. package/dist/entities/system/runtime-modules.js +38 -0
  87. package/dist/entities/system/style-bag.d.ts +20 -0
  88. package/dist/entities/system/style-bag.js +246 -0
  89. package/dist/entities/system/token-index.d.ts +89 -0
  90. package/dist/entities/system/token-index.js +112 -0
  91. package/dist/framework/Config.d.ts +2472 -0
  92. package/dist/framework/Config.js +5023 -0
  93. package/dist/framework/Entity.d.ts +127 -0
  94. package/dist/framework/Entity.js +125 -0
  95. package/dist/framework/authoring.d.ts +24 -0
  96. package/dist/framework/authoring.js +7 -0
  97. package/dist/framework/change-hooks.d.ts +119 -0
  98. package/dist/framework/change-hooks.js +131 -0
  99. package/dist/framework/changes.d.ts +88 -0
  100. package/dist/framework/changes.js +246 -0
  101. package/dist/framework/class-names.d.ts +260 -0
  102. package/dist/framework/class-names.js +630 -0
  103. package/dist/framework/coalesce.d.ts +25 -0
  104. package/dist/framework/coalesce.js +60 -0
  105. package/dist/framework/config-op.d.ts +76 -0
  106. package/dist/framework/config-op.js +43 -0
  107. package/dist/framework/config-operation-kind.d.ts +14 -0
  108. package/dist/framework/config-operation-kind.js +14 -0
  109. package/dist/framework/config-ops.d.ts +34 -0
  110. package/dist/framework/config-ops.js +187 -0
  111. package/dist/framework/defineConfig.d.ts +196 -0
  112. package/dist/framework/defineConfig.js +100 -0
  113. package/dist/framework/defineDerivedEntity.d.ts +74 -0
  114. package/dist/framework/defineDerivedEntity.js +83 -0
  115. package/dist/framework/defineEntity.d.ts +318 -0
  116. package/dist/framework/defineEntity.js +183 -0
  117. package/dist/framework/defineSubEntity.d.ts +148 -0
  118. package/dist/framework/defineSubEntity.js +121 -0
  119. package/dist/framework/derived-mutations.d.ts +20 -0
  120. package/dist/framework/derived-mutations.js +38 -0
  121. package/dist/framework/entity-search.d.ts +29 -0
  122. package/dist/framework/entity-search.js +117 -0
  123. package/dist/framework/inline-sources.d.ts +49 -0
  124. package/dist/framework/inline-sources.js +388 -0
  125. package/dist/framework/layer-styles.d.ts +25 -0
  126. package/dist/framework/layer-styles.js +49 -0
  127. package/dist/framework/memo.d.ts +48 -0
  128. package/dist/framework/memo.js +84 -0
  129. package/dist/framework/overlay.d.ts +49 -0
  130. package/dist/framework/overlay.js +17 -0
  131. package/dist/framework/plan.d.ts +49 -0
  132. package/dist/framework/plan.js +73 -0
  133. package/dist/framework/projections.d.ts +480 -0
  134. package/dist/framework/projections.js +974 -0
  135. package/dist/framework/prop-surface.d.ts +132 -0
  136. package/dist/framework/prop-surface.js +278 -0
  137. package/dist/framework/ref-graph.d.ts +71 -0
  138. package/dist/framework/ref-graph.js +158 -0
  139. package/dist/framework/ref-integrity.d.ts +55 -0
  140. package/dist/framework/ref-integrity.js +171 -0
  141. package/dist/framework/registered.d.ts +95 -0
  142. package/dist/framework/registry-dir.d.ts +42 -0
  143. package/dist/framework/registry-dir.js +48 -0
  144. package/dist/framework/registry.d.ts +300 -0
  145. package/dist/framework/registry.js +104 -0
  146. package/dist/framework/rejection.d.ts +58 -0
  147. package/dist/framework/rejection.js +111 -0
  148. package/dist/framework/rename-inference.d.ts +26 -0
  149. package/dist/framework/rename-inference.js +50 -0
  150. package/dist/framework/render-spec.d.ts +296 -0
  151. package/dist/framework/render-spec.js +809 -0
  152. package/dist/framework/schema-version.d.ts +140 -0
  153. package/dist/framework/schema-version.js +214 -0
  154. package/dist/framework/schemas.d.ts +109 -0
  155. package/dist/framework/schemas.js +615 -0
  156. package/dist/framework/session.d.ts +196 -0
  157. package/dist/framework/session.js +367 -0
  158. package/dist/framework/signature.d.ts +15 -0
  159. package/dist/framework/signature.js +83 -0
  160. package/dist/framework/snapshot.d.ts +115 -0
  161. package/dist/framework/snapshot.js +277 -0
  162. package/dist/framework/source-integrity.d.ts +226 -0
  163. package/dist/framework/source-integrity.js +478 -0
  164. package/dist/framework/sources.d.ts +211 -0
  165. package/dist/framework/sources.js +89 -0
  166. package/dist/framework/utils/compiled-schema.d.ts +23 -0
  167. package/dist/framework/utils/compiled-schema.js +46 -0
  168. package/dist/framework/utils/content-key.d.ts +15 -0
  169. package/dist/framework/utils/content-key.js +33 -0
  170. package/dist/framework/utils/enumerated.d.ts +13 -0
  171. package/dist/framework/utils/enumerated.js +19 -0
  172. package/dist/framework/utils/field-path.d.ts +95 -0
  173. package/dist/framework/utils/field-path.js +136 -0
  174. package/dist/framework/utils/field-schema.d.ts +55 -0
  175. package/dist/framework/utils/field-schema.js +183 -0
  176. package/dist/framework/utils/group.d.ts +37 -0
  177. package/dist/framework/utils/group.js +13 -0
  178. package/dist/framework/utils/package-path.d.ts +37 -0
  179. package/dist/framework/utils/package-path.js +61 -0
  180. package/dist/framework/utils/refs.d.ts +194 -0
  181. package/dist/framework/utils/refs.js +403 -0
  182. package/dist/framework/validate-spec.d.ts +27 -0
  183. package/dist/framework/validate-spec.js +45 -0
  184. package/dist/framework/value-domain.d.ts +26 -0
  185. package/dist/framework/value-domain.js +202 -0
  186. package/dist/framework/views-facade.d.ts +15 -0
  187. package/dist/framework/views-facade.js +19 -0
  188. package/dist/index.d.ts +90 -42
  189. package/dist/index.js +86 -37
  190. package/dist/migrations/2.0.0/raw-css.d.ts +11 -0
  191. package/dist/migrations/2.0.0/raw-css.js +72 -0
  192. package/dist/migrations/2.0.0/v1-artifact.d.ts +1559 -0
  193. package/dist/migrations/2.0.0/v1-artifact.js +1018 -0
  194. package/dist/migrations/20260908171448_settings_as_kind.d.ts +22 -0
  195. package/dist/migrations/20260908171448_settings_as_kind.js +89 -0
  196. package/dist/migrations/20260908194245_visible_state_pointer.d.ts +19 -0
  197. package/dist/migrations/20260908194245_visible_state_pointer.js +115 -0
  198. package/dist/migrations/20260909183001_icon_knockout_variants.d.ts +18 -0
  199. package/dist/migrations/20260909183001_icon_knockout_variants.js +8 -0
  200. package/dist/migrations/20260910212453_linked_system_link_ops.d.ts +13 -0
  201. package/dist/migrations/20260910212453_linked_system_link_ops.js +8 -0
  202. package/dist/migrations/index.d.ts +2 -0
  203. package/dist/migrations/index.js +2 -0
  204. package/dist/react-native/style-keys.generated.d.ts +10 -0
  205. package/dist/react-native/style-keys.generated.js +167 -0
  206. package/dist/renderer/RendererErrorBoundary.d.ts +32 -5
  207. package/dist/renderer/RendererErrorBoundary.js +59 -10
  208. package/dist/renderer/UdsRenderer.d.ts +11 -10
  209. package/dist/renderer/UdsRenderer.js +1 -1
  210. package/dist/renderer/assetEntries.d.ts +37 -0
  211. package/dist/renderer/assetEntries.js +39 -0
  212. package/dist/renderer/assetRenderable.d.ts +14 -6
  213. package/dist/renderer/assetRenderable.js +8 -2
  214. package/dist/renderer/componentEntry.d.ts +58 -0
  215. package/dist/renderer/componentEntry.js +71 -0
  216. package/dist/renderer/icon-library.d.ts +20 -0
  217. package/dist/renderer/index.d.ts +7 -7
  218. package/dist/renderer/index.js +5 -5
  219. package/dist/renderer/primitives/SlotRenderer.d.ts +1 -1
  220. package/dist/renderer/primitives/SlotRenderer.js +1 -1
  221. package/dist/renderer/runtimeComponent.d.ts +33 -0
  222. package/dist/renderer/runtimeComponent.js +113 -0
  223. package/dist/renderer/spec-content.d.ts +43 -0
  224. package/dist/renderer/spec-content.js +95 -0
  225. package/dist/renderer/wrapRegistry.d.ts +22 -37
  226. package/dist/renderer/wrapRegistry.js +10 -20
  227. package/dist/renderer/wrappers/event-bridge.js +6 -5
  228. package/dist/renderer/wrappers/hex-normalize.js +6 -5
  229. package/dist/renderer/wrappers/html-aliases.d.ts +7 -2
  230. package/dist/renderer/wrappers/html-aliases.js +36 -19
  231. package/dist/renderer/wrappers/inline-styles.js +7 -6
  232. package/dist/spec/asset-jsx.d.ts +18 -5
  233. package/dist/spec/asset-jsx.js +27 -16
  234. package/dist/spec/collapse-text-labels.d.ts +5 -15
  235. package/dist/spec/collapse-text-labels.js +26 -19
  236. package/dist/spec/empty-node-slots.d.ts +56 -34
  237. package/dist/spec/empty-node-slots.js +87 -47
  238. package/dist/spec/index.d.ts +21 -10
  239. package/dist/spec/index.js +21 -10
  240. package/dist/spec/jsxToSpec.d.ts +14 -9
  241. package/dist/spec/jsxToSpec.js +20 -3
  242. package/dist/spec/preview-elements.d.ts +63 -0
  243. package/dist/spec/preview-elements.js +89 -0
  244. package/dist/spec/rewrite-refs.d.ts +58 -0
  245. package/dist/spec/rewrite-refs.js +250 -0
  246. package/dist/spec/specToJsx.js +18 -29
  247. package/dist/tsconfig.tsbuildinfo +1 -1
  248. package/package.json +39 -52
  249. package/dist/AssetGroup.d.ts +0 -77
  250. package/dist/AssetGroup.js +0 -125
  251. package/dist/Component.d.ts +0 -333
  252. package/dist/Component.js +0 -1061
  253. package/dist/ComponentGroup.d.ts +0 -22
  254. package/dist/ComponentGroup.js +0 -51
  255. package/dist/CompositeStyle.d.ts +0 -30
  256. package/dist/CompositeStyle.js +0 -59
  257. package/dist/Config.d.ts +0 -528
  258. package/dist/Config.js +0 -1712
  259. package/dist/Mode.d.ts +0 -41
  260. package/dist/Mode.js +0 -81
  261. package/dist/Modifier.d.ts +0 -51
  262. package/dist/Modifier.js +0 -97
  263. package/dist/MotionDef.d.ts +0 -81
  264. package/dist/MotionDef.js +0 -212
  265. package/dist/Props.d.ts +0 -332
  266. package/dist/Props.js +0 -35
  267. package/dist/Provider.d.ts +0 -20
  268. package/dist/Provider.js +0 -14
  269. package/dist/StyleProp.d.ts +0 -145
  270. package/dist/StyleProp.js +0 -239
  271. package/dist/Token.d.ts +0 -76
  272. package/dist/Token.js +0 -133
  273. package/dist/TokenGroup.d.ts +0 -33
  274. package/dist/TokenGroup.js +0 -69
  275. package/dist/asset-kind.d.ts +0 -55
  276. package/dist/asset-kind.js +0 -29
  277. package/dist/asset-value.d.ts +0 -23
  278. package/dist/asset-value.js +0 -40
  279. package/dist/brands.d.ts +0 -30
  280. package/dist/brands.js +0 -20
  281. package/dist/captureCallerPath.d.ts +0 -48
  282. package/dist/captureCallerPath.js +0 -95
  283. package/dist/colorExpressions.d.ts +0 -131
  284. package/dist/colorExpressions.js +0 -148
  285. package/dist/component-referrers.d.ts +0 -30
  286. package/dist/component-referrers.js +0 -40
  287. package/dist/config-diagnostics.d.ts +0 -21
  288. package/dist/config-diagnostics.js +0 -12
  289. package/dist/defineAssetGroup.d.ts +0 -200
  290. package/dist/defineAssetGroup.js +0 -323
  291. package/dist/defineProvider.d.ts +0 -29
  292. package/dist/defineProvider.js +0 -60
  293. package/dist/element-marker.d.ts +0 -63
  294. package/dist/element-marker.js +0 -113
  295. package/dist/entity-utils.d.ts +0 -56
  296. package/dist/entity-utils.js +0 -105
  297. package/dist/extension.d.ts +0 -55
  298. package/dist/extension.js +0 -214
  299. package/dist/factories.d.ts +0 -863
  300. package/dist/factories.js +0 -475
  301. package/dist/font-face.d.ts +0 -25
  302. package/dist/font-face.js +0 -72
  303. package/dist/foreign-component-name.d.ts +0 -21
  304. package/dist/foreign-component-name.js +0 -42
  305. package/dist/interpolate.d.ts +0 -20
  306. package/dist/interpolate.js +0 -10
  307. package/dist/jsx/__fixtures__/cross-component-preview.d.ts +0 -3
  308. package/dist/jsx/__fixtures__/cross-component-preview.js +0 -15
  309. package/dist/jsx/jsx-dev-runtime.d.ts +0 -15
  310. package/dist/jsx/jsx-dev-runtime.js +0 -11
  311. package/dist/jsx/jsx-runtime.d.ts +0 -48
  312. package/dist/jsx/jsx-runtime.js +0 -305
  313. package/dist/linked-system-pins.d.ts +0 -30
  314. package/dist/linked-system-pins.js +0 -45
  315. package/dist/linkedNodePrefixes.d.ts +0 -73
  316. package/dist/linkedNodePrefixes.js +0 -99
  317. package/dist/markers.d.ts +0 -235
  318. package/dist/markers.js +0 -70
  319. package/dist/motion-constants.d.ts +0 -37
  320. package/dist/motion-constants.js +0 -61
  321. package/dist/native/NativeConfig.d.ts +0 -56
  322. package/dist/native/NativeConfig.js +0 -162
  323. package/dist/native/assets.d.ts +0 -20
  324. package/dist/native/assets.js +0 -17
  325. package/dist/native/components.d.ts +0 -139
  326. package/dist/native/components.js +0 -67
  327. package/dist/native/index.d.ts +0 -18
  328. package/dist/native/index.js +0 -17
  329. package/dist/native/modes.d.ts +0 -10
  330. package/dist/native/modes.js +0 -11
  331. package/dist/native/types.d.ts +0 -95
  332. package/dist/native/types.js +0 -0
  333. package/dist/native/validation.d.ts +0 -8
  334. package/dist/native/validation.js +0 -885
  335. package/dist/native/values.d.ts +0 -7
  336. package/dist/native/values.js +0 -15
  337. package/dist/native.d.ts +0 -12
  338. package/dist/native.js +0 -10
  339. package/dist/refs.d.ts +0 -204
  340. package/dist/refs.js +0 -129
  341. package/dist/registry-aliases.d.ts +0 -33
  342. package/dist/registry-aliases.js +0 -35
  343. package/dist/registry-dir.d.ts +0 -22
  344. package/dist/registry-dir.js +0 -10
  345. package/dist/renderer/makeRegistry.d.ts +0 -34
  346. package/dist/renderer/makeRegistry.js +0 -52
  347. package/dist/renderer/makeUdsRenderer.d.ts +0 -13
  348. package/dist/renderer/makeUdsRenderer.js +0 -51
  349. package/dist/renderer/wrappers/component-slots.d.ts +0 -41
  350. package/dist/renderer/wrappers/component-slots.js +0 -66
  351. package/dist/renderer/wrappers/slot-resolution.d.ts +0 -25
  352. package/dist/renderer/wrappers/slot-resolution.js +0 -68
  353. package/dist/renderer/wrappers/void-elements.d.ts +0 -37
  354. package/dist/renderer/wrappers/void-elements.js +0 -40
  355. package/dist/spec/layer-props.d.ts +0 -52
  356. package/dist/spec/layer-props.js +0 -149
  357. package/dist/spec/preview-controls.d.ts +0 -44
  358. package/dist/spec/preview-controls.js +0 -139
  359. package/dist/spec/slot-refs.d.ts +0 -39
  360. package/dist/spec/slot-refs.js +0 -56
  361. package/dist/token-override-rows.d.ts +0 -68
  362. package/dist/token-override-rows.js +0 -233
  363. package/dist/tokenValueType.d.ts +0 -34
  364. package/dist/tokenValueType.js +0 -138
  365. package/dist/types/css-properties.d.ts +0 -233
  366. package/dist/types/css-properties.js +0 -14
  367. package/dist/types/css-property-keywords.d.ts +0 -156
  368. package/dist/types/css-property-keywords.js +0 -616
  369. package/dist/types/css-values.d.ts +0 -63
  370. package/dist/types/css-values.js +0 -16
  371. package/dist/types.d.ts +0 -1138
  372. package/dist/types.js +0 -12
  373. package/dist/units.d.ts +0 -14
  374. package/dist/units.js +0 -16
  375. package/dist/utils/index.d.ts +0 -4
  376. package/dist/utils/index.js +0 -4
@@ -0,0 +1,630 @@
1
+ import { isRef, kindOf, pathOf, refLeaf } from "./utils/refs.js";
2
+ import { rootLayerOf } from "../entities/system/element.js";
3
+ import { classPrefixOf } from "../entities/system/Settings.js";
4
+ import { authoredValue, className, negatedCssValue, renderStyleValue, resolveComponentProps, stylePropLeafForToken, stylePropValueLeaves, stylePropertyPathFor } from "./projections.js";
5
+ import { ruleApplies } from "./layer-styles.js";
6
+ import { createSliceMemo } from "./memo.js";
7
+ //#region src/framework/class-names.ts
8
+ /**
9
+ * What a class is CALLED — the one answer, for everything that has to agree about it.
10
+ *
11
+ * Three things name the same class from three directions: the stylesheet writes the rule, the
12
+ * emitted module puts the class on an element, and the canvas — which renders a component the
13
+ * registry has no module for by expanding its anatomy — has to derive the same string at render
14
+ * time from the live config. v1 kept those derivations apart, and any drift between them
15
+ * tree-shakes away a rule the app uses or puts a class on an element the sheet never styled.
16
+ * Both failures are silent and look like "the styling just didn't apply".
17
+ *
18
+ * It lives in config-v2 rather than in codegen because the third caller runs in a browser: a class
19
+ * name is a projection of the config, like a CSS var name or a token's resolved value, and nothing
20
+ * here reads a source file.
21
+ */
22
+ /** `HStack` → `hstack`, `AvatarItem` → `avatar-item`. A dash only between a lower/digit and an
23
+ * upper, so an initialism isn't split. */
24
+ function kebabComponent(name) {
25
+ return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
26
+ }
27
+ /**
28
+ * Every attribute Create sets only to hold an element in a condition starts with this. The `create`
29
+ * segment keeps it clear of a consumer's own `data-*` attributes, and `force` says the attribute
30
+ * puts the element in the condition rather than describing it.
31
+ */
32
+ const FORCE_ATTRIBUTE_PREFIX = "data-create-force-";
33
+ /**
34
+ * The attribute a surface sets to hold a modifier's state open — `data-create-force-focus-visible`.
35
+ *
36
+ * This is a contract between two sides that can't see each other: an editor sets the attribute on an
37
+ * element, and a stylesheet emitted somewhere else has to match it. Every spelling derives from here,
38
+ * including the playground's inlined copy, since a multi-word modifier (`focusVisible`) matches
39
+ * nothing when one side skips the kebab-casing.
40
+ */
41
+ function forceStateAttribute(modifier) {
42
+ const name = modifier.startsWith("_") ? modifier.slice(1) : modifier;
43
+ return `${FORCE_ATTRIBUTE_PREFIX}${kebabComponent(name.slice(name.lastIndexOf("/") + 1))}`;
44
+ }
45
+ /**
46
+ * The attribute that forces one mode group on an element and its subtree:
47
+ * `data-create-force-mode-<group>="<option>"`. The group is lowercased and a nested group's slashes
48
+ * become dashes, since an attribute name can hold neither. The emitter admits this attribute beside
49
+ * every selector mode's own selector, so an element carrying it is in the mode whatever shape the
50
+ * author gave the selector.
51
+ */
52
+ function forceModeAttribute(group) {
53
+ return `${FORCE_ATTRIBUTE_PREFIX}mode-${group.toLowerCase().replaceAll("/", "-")}`;
54
+ }
55
+ /**
56
+ * The attribute and value that force one mode option (`colorMode/dark` →
57
+ * `data-create-force-mode-colormode="dark"`). A mode outside any group has none, since there is no
58
+ * group to force.
59
+ */
60
+ function forceModeAttributeOf(modePath) {
61
+ const slash = modePath.lastIndexOf("/");
62
+ if (slash <= 0) return void 0;
63
+ return {
64
+ name: forceModeAttribute(modePath.slice(0, slash)),
65
+ value: modePath.slice(slash + 1)
66
+ };
67
+ }
68
+ /**
69
+ * The spec prop that forces a mode group on an element. It keeps the group's authored casing
70
+ * (`data-create-force-mode-colorMode`), and the render wrapper spells it as
71
+ * {@link forceModeAttribute} when it reaches the DOM.
72
+ */
73
+ function forceModeProp(group) {
74
+ return `${FORCE_ATTRIBUTE_PREFIX}mode-${group}`;
75
+ }
76
+ /** Persisted specs still carry the spelling this prop had before it was namespaced. */
77
+ const LEGACY_FORCE_MODE_PROP_PREFIX = "data-mode-";
78
+ /** The group a spec prop forces a mode on, or `undefined` when the prop is something else. */
79
+ function forceModePropGroup(key) {
80
+ const current = `${FORCE_ATTRIBUTE_PREFIX}mode-`;
81
+ if (key.startsWith(current)) return key.slice(current.length);
82
+ if (key.startsWith(LEGACY_FORCE_MODE_PROP_PREFIX)) return key.slice(10);
83
+ }
84
+ /** Whether a spec prop forces a mode group, in the current spelling or the one persisted specs carry. */
85
+ function isForceModeProp(key) {
86
+ return forceModePropGroup(key) !== void 0;
87
+ }
88
+ /**
89
+ * The option a spec's props force for one group, or `undefined`. Reads the current prop first, and
90
+ * falls back to the legacy spelling so a design saved before the rename still forces its mode.
91
+ */
92
+ function forceModePropValue(props, group) {
93
+ if (!props) return void 0;
94
+ for (const key of forceModeProps(group)) {
95
+ const value = props[key];
96
+ if (typeof value === "string" && value) return value;
97
+ }
98
+ }
99
+ /**
100
+ * Every prop that can force one group, current spelling first. A writer clears each of them when it
101
+ * changes the selection, so a legacy key can't keep forcing a mode the user turned off.
102
+ */
103
+ function forceModeProps(group) {
104
+ return [forceModeProp(group), `${LEGACY_FORCE_MODE_PROP_PREFIX}${group}`];
105
+ }
106
+ /**
107
+ * The class stem for a component — `uds-list-item`.
108
+ *
109
+ * Derived from the component's PATH, not its name, so a grouped component (`forms/Toggle`) gets a
110
+ * stem no other group can collide with. Everything a component wears extends this stem.
111
+ */
112
+ function componentClassBase(config, path) {
113
+ return kebabComponent(className(config, "component", path));
114
+ }
115
+ /** The class one layer wears unconditionally — `uds-list-item-label`. A component's defaults land on
116
+ * this selector at zero specificity, so nothing about it is conditional. */
117
+ function componentLayerClass(config, path, layer) {
118
+ return `${componentClassBase(config, path)}-${layer}`;
119
+ }
120
+ /**
121
+ * A rule's condition as it appears in a class name: `{size:'xs'}` → `size-xs`, and an empty condition
122
+ * (an unconditional rule) → `''`.
123
+ *
124
+ * A class name is an IDENTIFIER, so the value is made safe for one: an unescaped `.` starts a second
125
+ * class and `/` is not a name character at all, so a rule keyed on `size: '0.5'` emitted
126
+ * `.uds-card-root-size-0.5` — parsed as `.uds-card-root-size-0` plus garbage, discarding the rule,
127
+ * while the module put the literal string on the element.
128
+ *
129
+ * Written out rather than shared with {@link stylePropClassName}, which applies the same transform:
130
+ * as a small module-private helper it did not survive one of the bundlers this module is compiled
131
+ * through, and `uds build` died on `classSafe is not defined`. Two spellings of four characters is
132
+ * the cheaper problem.
133
+ */
134
+ function ruleCondition(when) {
135
+ return Object.entries(when ?? {}).map(([prop, value]) => `${prop}-${String(value).replaceAll("/", "-").replaceAll(".", "_").replace(/\s+/g, "-")}`).join("-");
136
+ }
137
+ /**
138
+ * Every conditional class a component's style rules produce.
139
+ *
140
+ * Unconditional rules are absent by design: they land on the layer's own zero-specificity selector
141
+ * ({@link componentLayerClass}), which every element already wears with nothing to test.
142
+ */
143
+ function componentRuleClasses(config, path) {
144
+ const component = config.resolve("component", path);
145
+ if (!component) return [];
146
+ const { layers = {}, styles = {} } = component.toJSON();
147
+ const base = componentClassBase(config, path);
148
+ const out = [];
149
+ for (const rule of Object.values(styles)) {
150
+ const when = Object.fromEntries(Object.entries(rule.when ?? {}).map(([prop, value]) => [prop, refLeaf(value)]));
151
+ const condition = ruleCondition(when);
152
+ if (!condition) continue;
153
+ for (const layer of Object.keys(rule.layers ?? {})) {
154
+ if (!(layer in layers)) continue;
155
+ out.push({
156
+ layer,
157
+ when,
158
+ className: `${base}-${layer}-${condition}`
159
+ });
160
+ }
161
+ }
162
+ return out;
163
+ }
164
+ /** The MEMBER a bag value names, under the group its prop binds — the value is either the qualified
165
+ * ref it is stored as, or the bare leaf an older body holds. */
166
+ function memberNamed(groupRef, value) {
167
+ if (isRef(value)) return pathOf(value.__ref);
168
+ return typeof value === "string" ? `${pathOf(groupRef)}/${value}` : void 0;
169
+ }
170
+ /** The same read for a value whose domain is a whole KIND rather than a group, so the ref's path is
171
+ * the name itself. */
172
+ function presetNamed(value) {
173
+ if (isRef(value)) return pathOf(value.__ref);
174
+ return typeof value === "string" ? value : void 0;
175
+ }
176
+ /**
177
+ * Every COMPOSITE class a component's style rules apply, with the condition each applies under.
178
+ *
179
+ * A composite prop names a value (`variant: 'ui6'`) whose CSS is a class rather than a set of
180
+ * declarations, so it can't reach the element the way a style prop does. Same shape as
181
+ * {@link componentRuleClasses} for that reason.
182
+ *
183
+ * This answers WHICH CLASS a rule's composite ends up as, not who applies it — the layer's receiver
184
+ * does, out of the prop it is forwarded ({@link layerCompositeProps}). The caller is the EXTRACTOR,
185
+ * which has to keep that class's CSS from being shaken out as unreferenced: after the forward the
186
+ * value appears in the emitted module only as a prop string, so nothing else in the build names it.
187
+ *
188
+ * Unlike `componentRuleClasses`, an UNCONDITIONAL rule is included (`when` empty). That function
189
+ * omits them because their declarations land on the layer's own zero-specificity selector — but a
190
+ * composite contributes no declarations there, so omitting it would drop the class entirely.
191
+ */
192
+ function componentCompositeClasses(config, path) {
193
+ const component = config.resolve("component", path);
194
+ if (!component) return [];
195
+ const { layers = {}, styles = {} } = component.toJSON();
196
+ const out = [];
197
+ for (const rule of Object.values(styles)) {
198
+ const when = Object.fromEntries(Object.entries(rule.when ?? {}).map(([prop, value]) => [prop, refLeaf(value)]));
199
+ for (const [layer, bag] of Object.entries(rule.layers ?? {})) {
200
+ const element = layers[layer];
201
+ if (!isRef(element)) continue;
202
+ const declared = resolveComponentProps(config, pathOf(element.__ref));
203
+ for (const [prop, value] of Object.entries(bag ?? {})) {
204
+ const bound = declared[prop]?.value;
205
+ if (!isRef(bound) || kindOf(bound.__ref) !== "composite") continue;
206
+ const target = memberNamed(bound.__ref, value);
207
+ if (target === void 0 || !config.resolve("composite", target)) continue;
208
+ out.push({
209
+ layer,
210
+ when,
211
+ className: className(config, "composite", target)
212
+ });
213
+ }
214
+ }
215
+ }
216
+ return out;
217
+ }
218
+ /** The class a CSS motion preset is applied by. Namespaced, so it doesn't share a space with the
219
+ * style-prop utilities; the `@keyframes` it runs keep their own name. */
220
+ function motionClassName(config, path) {
221
+ return `${classPrefixOf(config)}-motion-${path.replaceAll("/", "-")}`;
222
+ }
223
+ /**
224
+ * Every MOTION class a component's style rules apply — a layer bag naming a preset (`motion: 'spin'`).
225
+ *
226
+ * The same shape and the same reason as {@link componentCompositeClasses}: a CSS preset's whole
227
+ * runtime is a class, so a layer that references one has to wear it, under whatever condition its
228
+ * rule declares. Without this the value went nowhere — `motion` names no style property so it isn't
229
+ * a declaration, and it IS a declared prop of the layer's element so it isn't an attribute either.
230
+ *
231
+ * A JS preset is skipped: it animates in the client and has no class to wear.
232
+ */
233
+ function componentMotionClasses(config, path) {
234
+ const component = config.resolve("component", path);
235
+ if (!component) return [];
236
+ const { layers = {}, styles = {} } = component.toJSON();
237
+ const out = [];
238
+ for (const rule of Object.values(styles)) {
239
+ const when = Object.fromEntries(Object.entries(rule.when ?? {}).map(([prop, value]) => [prop, refLeaf(value)]));
240
+ for (const [layer, bag] of Object.entries(rule.layers ?? {})) {
241
+ const element = layers[layer];
242
+ if (!isRef(element)) continue;
243
+ const declared = resolveComponentProps(config, pathOf(element.__ref));
244
+ for (const [prop, value] of Object.entries(bag ?? {})) {
245
+ if (declared[prop]?.type !== "motion") continue;
246
+ const name = presetNamed(value);
247
+ if (name === void 0) continue;
248
+ const preset = config.resolve("motion", name)?.toJSON();
249
+ if (preset?.runtime !== "css" || !preset.keyframes) continue;
250
+ out.push({
251
+ layer,
252
+ when,
253
+ className: motionClassName(config, name)
254
+ });
255
+ }
256
+ }
257
+ }
258
+ return out;
259
+ }
260
+ /**
261
+ * The classes a component's OWN props put on it, by layer — `variant="body"` picking
262
+ * `textVariant/body`'s class.
263
+ *
264
+ * A composite is the only prop that works this way, and it has to: its whole CSS is a class, so it
265
+ * can't ride the prop channel the way a style prop does. That makes it the one piece of an
266
+ * instance's styling a projection can lose entirely, and losing it is what made a component look one
267
+ * way in the component editor and another on a canvas — the expansion resolved it, the anatomy
268
+ * projection had no route for it, and the matrix painted the cell in the wrong typography.
269
+ *
270
+ * So both projections read this and neither derives it. `state` is merged over the component's
271
+ * defaults, because a value the caller didn't set has to read the default — the same rule
272
+ * {@link layerStyles} follows.
273
+ *
274
+ * Keyed by layer even though today it only ever names the ROOT one, so a caller needs no opinion
275
+ * about which layer that is: an instance's own props land where its own props land.
276
+ */
277
+ function componentPropClasses(config, path, state = {}) {
278
+ const component = config.resolve("component", path);
279
+ if (!component) return {};
280
+ const { layers = {}, props = {}, defaultProps = {} } = component.toJSON();
281
+ const [root] = rootLayerOf(layers);
282
+ const resolved = {
283
+ ...defaultProps,
284
+ ...state
285
+ };
286
+ const classes = [];
287
+ for (const [prop, decl] of Object.entries(props)) {
288
+ if (decl?.type !== "composite") continue;
289
+ const group = isRef(decl.value) ? decl.value.__ref : void 0;
290
+ const value = resolved[prop];
291
+ if (!group) continue;
292
+ const target = memberNamed(group, value);
293
+ if (target === void 0) continue;
294
+ if (!config.resolve("composite", target)) continue;
295
+ classes.push(className(config, "composite", target));
296
+ }
297
+ return classes.length > 0 ? { [root]: classes } : {};
298
+ }
299
+ /**
300
+ * The COMPOSITE a style rule sets on each layer, for one instance — forwarded to the layer as a prop.
301
+ *
302
+ * A composite's whole CSS is a class, so a rule's condition class (where the stylesheet hangs its
303
+ * DECLARATIONS) cannot carry one. The route is the layer's RECEIVER: the bag key already IS that
304
+ * receiver's own prop name — `variant` for a `Text`-backed layer, `textVariant` for an `Input`-backed
305
+ * one, both binding the same group — so this copies the key verbatim and there is nothing to resolve.
306
+ * `Text` turns `variant="label3"` into `uds-textVariant-label3` for itself, and always has.
307
+ *
308
+ * Forwarding rather than resolving is what makes a layer's styling live-editable at all: a class only
309
+ * exists once a build has emitted the stylesheet, so an edit that makes a NEW style rule paints
310
+ * nothing until a rebuild, while a prop json-render applies on the spot. Both projections of a
311
+ * component read this, so neither has to know the receiver's name for the group.
312
+ *
313
+ * Only what the receiver DECLARES as composite-typed. A bag key it doesn't declare is an ordinary
314
+ * prop or an attribute, and belongs to whatever channel already carries it.
315
+ */
316
+ function layerCompositeProps(config, path, state = {}) {
317
+ const component = config.resolve("component", path);
318
+ if (!component) return {};
319
+ const { layers = {}, styles = {}, defaultProps = {} } = component.toJSON();
320
+ const resolved = {
321
+ ...defaultProps,
322
+ ...state
323
+ };
324
+ const out = {};
325
+ const applicable = Object.values(styles).filter((rule) => ruleApplies(rule.when, resolved)).sort((left, right) => Object.keys(left.when ?? {}).length - Object.keys(right.when ?? {}).length);
326
+ for (const rule of applicable) for (const [layer, bag] of Object.entries(rule.layers ?? {})) {
327
+ const element = layers[layer];
328
+ if (!isRef(element)) continue;
329
+ const declared = resolveComponentProps(config, pathOf(element.__ref));
330
+ for (const [prop, value] of Object.entries(bag ?? {})) {
331
+ const bound = declared[prop]?.value;
332
+ if (!isRef(bound) || kindOf(bound.__ref) !== "composite") continue;
333
+ out[layer] ??= {};
334
+ out[layer][prop] = authoredValue(config, prop, value);
335
+ }
336
+ }
337
+ return out;
338
+ }
339
+ /**
340
+ * The CSS MOTION classes a style rule puts on a layer, for one instance.
341
+ *
342
+ * A preset's whole runtime is a class too, and a composite's route (forward it, and let the receiver
343
+ * resolve its own prop — {@link layerCompositeProps}) does not exist for this one: `motion` is not a
344
+ * style property, so {@link splitStyleProps} has no dispatch for it and a forwarded `motion="spin"`
345
+ * would reach the element as an attribute and animate nothing. The emitted runtime table DOES carry
346
+ * it — codegen adds a closed `motion` entry — which is why a component with a module needs nothing
347
+ * here, and one expanded from the config alone needs this.
348
+ */
349
+ function styleRuleMotionClasses(config, path, state = {}) {
350
+ const { defaultProps = {} } = config.resolve("component", path)?.toJSON() ?? {};
351
+ const resolved = {
352
+ ...defaultProps,
353
+ ...state
354
+ };
355
+ const out = {};
356
+ for (const rule of componentMotionClasses(config, path)) {
357
+ if (!ruleApplies(rule.when, resolved)) continue;
358
+ out[rule.layer] ??= [];
359
+ if (!out[rule.layer].includes(rule.className)) out[rule.layer].push(rule.className);
360
+ }
361
+ return out;
362
+ }
363
+ /**
364
+ * The class-name stem for a style prop: its authored `classPrefix` when it declares one, else its
365
+ * path — or, for an OPACITY COMPANION, its target's stem plus `-opacity`.
366
+ *
367
+ * An EMPTY prefix is meaningful and not the same as an absent one — `position: absolute` ships as
368
+ * `.uds-absolute`, with no prop segment at all — so this tests for `undefined` rather than
369
+ * falsiness.
370
+ *
371
+ * The companion case exists because the path fallback is wrong for one: a companion is named after
372
+ * the prop it modulates (`bgOpacity`), so falling back to the path spells the stem in the prop's
373
+ * camelCase (`uds-bgOpacity`) rather than the kebab every other class uses, and spells it
374
+ * independently of the target whose fade it is. Deriving it from the PAIRING keeps the two in step —
375
+ * renaming `bg`'s prefix moves `bg-opacity` with it — and costs a config nothing to author. Every
376
+ * opacity prop in every config in this repo declares no prefix, which is what made this reachable.
377
+ */
378
+ function stylePropClassBase(config, path) {
379
+ const { classPrefix, opacityOf } = config.resolve("style-property", path)?.toJSON() ?? {};
380
+ if (classPrefix === void 0 && opacityOf) return `${stylePropClassBase(config, pathOf(opacityOf.__ref))}-opacity`;
381
+ const segment = classPrefix ?? path;
382
+ return segment ? className(config, "style-property", segment) : classPrefixOf(config);
383
+ }
384
+ /**
385
+ * The class for one authored value — `bg="primary"` → `uds-bg-primary`.
386
+ *
387
+ * The value is a LEAF, which is what a call site writes; an empty leaf is a boolean prop's `true`
388
+ * arm, whose class is the bare stem (`uds-border`) because a flag names no value.
389
+ *
390
+ * A slash becomes a dash and a DOT an underscore, because a class name can hold neither: `.uds-p-0.5`
391
+ * is not one selector but two (`uds-p-0` and `5`), so the rule the sheet wrote could never match the
392
+ * element the module classed. `spacing/0.5` is a real token in a real system, which is how that
393
+ * surfaced.
394
+ */
395
+ function stylePropClassName(config, path, leaf) {
396
+ const base = stylePropClassBase(config, path);
397
+ const suffix = leaf.replaceAll("/", "-").replaceAll(".", "_").replace(/\s+/g, "-");
398
+ return suffix ? `${base}-${suffix}` : base;
399
+ }
400
+ /** An off-scale value and what it really is — `[13px]` → `13px`, else `undefined`. The brackets mark
401
+ * a value the system doesn't tokenize; they aren't part of it. No class can exist for one, because a
402
+ * class is emitted per DECLARED value and this is by definition not declared. Inside the brackets an
403
+ * underscore encodes a space (`[repeat(7,_36px)]` → `repeat(7, 36px)`); it must be reversed here
404
+ * because a CSS value with a literal underscore is invalid and the browser drops the declaration.
405
+ * A `url(…)` span is exempt — its underscores are part of the address, not an escape (an AI-repaired
406
+ * spec brackets a model-emitted `url(…)` verbatim), which is the same carve-out Tailwind makes. */
407
+ function offScale(value) {
408
+ if (typeof value !== "string") return void 0;
409
+ return value.startsWith("[") && value.endsWith("]") ? unescapeArbitrary(value.slice(1, -1)) : void 0;
410
+ }
411
+ /** `_` → space, except inside `url(…)` where an underscore is literal. */
412
+ function unescapeArbitrary(value) {
413
+ return value.replace(/url\([^)]*\)|_/g, (span) => span === "_" ? " " : span);
414
+ }
415
+ /**
416
+ * Split a prop bag into a class string and the props that aren't styling.
417
+ *
418
+ * This is the same dispatch the emitted `_style-props` runtime performs, over a live config instead
419
+ * of the table that build baked. Both exist because they run in different places — an app's module
420
+ * has no config at runtime, and the canvas has no baked table for a component that was never built —
421
+ * but the CLASS NAMES both produce come from {@link stylePropClassName}, so the two can't disagree
422
+ * about what a value is called.
423
+ *
424
+ * An off-scale value can't be a class, so it lands in `style` on the returned rest; an explicit
425
+ * `style` the caller passed still wins, since that's the escape hatch of last resort.
426
+ */
427
+ function splitStyleProps({ config, bag, through }) {
428
+ const classes = [];
429
+ const rest = {};
430
+ const style = {};
431
+ const modifiers = new Map(config.list("modifier").map((modifier) => [`_${modifier.leaf}`, modifier.leaf]));
432
+ for (const [key, value] of Object.entries(bag)) {
433
+ const modifier = modifiers.get(key);
434
+ if (modifier) {
435
+ if (value && typeof value === "object" && !Array.isArray(value)) {
436
+ const inner = splitStyleProps({
437
+ config,
438
+ bag: value,
439
+ through
440
+ });
441
+ for (const cls of inner.className.split(" ").filter(Boolean)) classes.push(`${modifier}:${cls}`);
442
+ }
443
+ continue;
444
+ }
445
+ const name = stylePropertyPathFor({
446
+ config,
447
+ through,
448
+ key
449
+ }) ?? key;
450
+ const prop = config.resolve("style-property", name);
451
+ if (!prop) {
452
+ rest[key] = value;
453
+ continue;
454
+ }
455
+ if (value === void 0 || value === null) continue;
456
+ const { arbitrary, properties = [], negates } = prop.toJSON();
457
+ const off = arbitrary ? offScale(value) : void 0;
458
+ if (off !== void 0) {
459
+ const declared = negates ? negatedCssValue(off) : off;
460
+ for (const property of properties) style[reactStyleKey(property)] = declared;
461
+ continue;
462
+ }
463
+ if (isRef(value) && kindOf(value.__ref) === "token") {
464
+ const leaf = stylePropLeafForToken(config, name, pathOf(value.__ref));
465
+ if (leaf !== void 0) {
466
+ classes.push(stylePropClassName(config, name, leaf));
467
+ continue;
468
+ }
469
+ }
470
+ if (typeof value === "boolean") {
471
+ if (value) classes.push(stylePropClassName(config, name, ""));
472
+ continue;
473
+ }
474
+ if (typeof value === "object") {
475
+ const rendered = renderStyleValue(config, value);
476
+ const declared = negates ? negatedCssValue(rendered) : rendered;
477
+ for (const property of properties) style[reactStyleKey(property)] = declared;
478
+ continue;
479
+ }
480
+ classes.push(stylePropClassName(config, name, String(value)));
481
+ }
482
+ if (Object.keys(style).length > 0) {
483
+ const given = rest.style;
484
+ const explicit = {};
485
+ for (const [property, value] of Object.entries(given ?? {})) explicit[reactStyleKey(property)] = value;
486
+ rest.style = {
487
+ ...style,
488
+ ...explicit
489
+ };
490
+ }
491
+ return {
492
+ className: classes.join(" "),
493
+ rest
494
+ };
495
+ }
496
+ /**
497
+ * A CSS property name as REACT's `style` object spells it.
498
+ *
499
+ * `rest.style` is handed to React, not written into a stylesheet, and React's `style` takes
500
+ * camelCase. It does not merely tolerate the CSS spelling — it DROPS the declaration and warns. So
501
+ * every off-scale value, computed colour and gradient on this path painted nothing, and the only
502
+ * sign was a dev-console line among many.
503
+ *
504
+ * A custom property (`--uds-brand`) is passed through untouched: React writes those verbatim, and
505
+ * camelCasing one would break the case that already worked.
506
+ */
507
+ function reactStyleKey(property) {
508
+ if (property.startsWith("--")) return property;
509
+ return property.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
510
+ }
511
+ /**
512
+ * Every class a prop can produce, by leaf.
513
+ *
514
+ * Deduplicated on the leaf, keeping the FIRST: a prop may bind two token groups that share one
515
+ * (`top` takes both `spacing` and `position`, and both declare `0`), and `stylePropValueFromLeaf`
516
+ * resolves such a value with a `.find()` — so authored order already decides which token a leaf
517
+ * means, and the class set follows that rather than inventing a second answer.
518
+ */
519
+ function stylePropClasses(config, path) {
520
+ const out = /* @__PURE__ */ new Map();
521
+ for (const leaf of stylePropValueLeaves(config, path)) if (!out.has(leaf)) out.set(leaf, stylePropClassName(config, path, leaf));
522
+ return out;
523
+ }
524
+ /**
525
+ * Every MODIFIER-prefixed utility class the config itself asks for — `focus:uds-border-color-brand`.
526
+ *
527
+ * Modifier utilities can't be emitted exhaustively: every modifier against every utility is 25 ×
528
+ * 9,284 rules for a real system, and a sheet nobody can load is the same as no sheet. So they're
529
+ * driven by USE, and a build takes `used` from having read the app's source files.
530
+ *
531
+ * Studio has no source files to read, and doesn't need any: a config STATES what it asks for. Every
532
+ * bag it holds — a component's defaults, a preview's, each style rule's per-layer bag, each anatomy
533
+ * node's props, a composite's bag — goes through the same {@link splitStyleProps} the runtime uses,
534
+ * so the strings match on both sides by construction rather than by agreement. For the studio system
535
+ * that's 86 classes against 232,100.
536
+ *
537
+ * WHAT THIS CANNOT SEE, stated because the gap is real: a prop set on a design-file NODE (a
538
+ * `_hover` a user adds in the designer panel) is in the document, not the system, so no projection of
539
+ * the system can predict it. Covering those needs the document as a second source of use.
540
+ */
541
+ function modifierUtilitiesUsed(config) {
542
+ const used = /* @__PURE__ */ new Set();
543
+ const token = vocabularyToken(config);
544
+ const stored = config.snapshot.slice("component").items;
545
+ for (const component of config.list("component")) for (const cls of classesUsedBy(config, stored.get(component.path) ?? component, token, componentBags)) used.add(cls);
546
+ const storedComposites = config.snapshot.slice("composite").items;
547
+ for (const composite of config.list("composite")) for (const cls of classesUsedBy(config, storedComposites.get(composite.path) ?? composite, token, compositeBags)) used.add(cls);
548
+ return used;
549
+ }
550
+ /**
551
+ * Every style bag a COMPONENT states it wants, each with the definitions its keys resolve against.
552
+ *
553
+ * Not uniform, which is the whole reason it travels with the bag. `defaultProps` and `previewProps`
554
+ * are the component's OWN props, and nothing else has a claim. A style rule's per-layer bag and an
555
+ * anatomy node's props are set on a LAYER'S ELEMENT, so that element answers too — after the
556
+ * component itself, whose own declaration of a name is what that name means throughout its
557
+ * definition.
558
+ */
559
+ function componentBags(entity) {
560
+ const { path } = entity;
561
+ const { defaultProps, previewProps, styles, anatomy, layers } = entity.toJSON();
562
+ const bags = [{
563
+ bag: defaultProps,
564
+ through: [path]
565
+ }, {
566
+ bag: previewProps,
567
+ through: [path]
568
+ }];
569
+ for (const rule of Object.values(styles ?? {})) for (const [layer, bag] of Object.entries(rule?.layers ?? {})) bags.push({
570
+ bag,
571
+ through: [path, componentElementOf(layers?.[layer])]
572
+ });
573
+ for (const node of Object.values(anatomy ?? {})) bags.push({
574
+ bag: node?.props,
575
+ through: [path, componentElementOf(node?.element)]
576
+ });
577
+ return bags;
578
+ }
579
+ /** The component an element ref names, or `undefined` for a raw tag or a layer ref — neither of which
580
+ * is a component whose props could be renamed. */
581
+ function componentElementOf(element) {
582
+ return isRef(element) && kindOf(element.__ref) === "component" ? pathOf(element.__ref) : void 0;
583
+ }
584
+ /** A composite states one bag, and it belongs to no component. */
585
+ function compositeBags(entity) {
586
+ return [{ bag: entity.toJSON().styles }];
587
+ }
588
+ /**
589
+ * A token object that changes when the class VOCABULARY does — the style properties, and everything
590
+ * their value domains reach.
591
+ *
592
+ * `splitStyleProps` names a class by asking the config what a prop's leaves are, so a scan's answer
593
+ * survives any edit that leaves those alone. Which is every edit to the entities being scanned.
594
+ */
595
+ const vocabularyToken = createSliceMemo({
596
+ kinds: [
597
+ "style-property",
598
+ "token",
599
+ "composite",
600
+ "motion",
601
+ "icon",
602
+ "font"
603
+ ],
604
+ compute: (_config) => ({})
605
+ });
606
+ const usedClassCache = /* @__PURE__ */ new WeakMap();
607
+ /** One owner's prefixed classes, cached on (its stored entity, the vocabulary). */
608
+ function classesUsedBy(config, stored, token, bagsOf) {
609
+ let byVocabulary = usedClassCache.get(stored);
610
+ if (!byVocabulary) {
611
+ byVocabulary = /* @__PURE__ */ new WeakMap();
612
+ usedClassCache.set(stored, byVocabulary);
613
+ }
614
+ const hit = byVocabulary.get(token);
615
+ if (hit) return hit;
616
+ const found = [];
617
+ for (const { bag, through } of bagsOf(stored)) {
618
+ if (!bag || typeof bag !== "object" || Array.isArray(bag)) continue;
619
+ const { className } = splitStyleProps({
620
+ config,
621
+ bag,
622
+ through
623
+ });
624
+ for (const cls of className.split(" ")) if (cls.includes(":")) found.push(cls);
625
+ }
626
+ byVocabulary.set(token, found);
627
+ return found;
628
+ }
629
+ //#endregion
630
+ export { componentClassBase, componentCompositeClasses, componentLayerClass, componentMotionClasses, componentPropClasses, componentRuleClasses, forceModeAttribute, forceModeAttributeOf, forceModeProp, forceModePropGroup, forceModePropValue, forceModeProps, forceStateAttribute, isForceModeProp, kebabComponent, layerCompositeProps, modifierUtilitiesUsed, motionClassName, ruleCondition, splitStyleProps, stylePropClassBase, stylePropClassName, stylePropClasses, styleRuleMotionClasses };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Run an expensive side effect for the LAST value of a burst, never for the ones it superseded.
3
+ *
4
+ * Here rather than in the app because coalescing is not a property of any one derivation: one user
5
+ * gesture reaches a config holder several times — an edit lands optimistically, comes back as a
6
+ * realtime echo, then again as the pull that trues up against what the server persisted. Each landing
7
+ * describes the same edit, so a subscriber that recomputes per landing pays for two results nobody
8
+ * ever sees, on the frames the gesture is trying to respond on. That is true of every `onChange`
9
+ * point, so {@link runChangeHooks} owns it and a hook never writes it again.
10
+ *
11
+ * Leading-edge, not a trailing debounce: the first value is handed to `schedule` right away, so a
12
+ * continuous gesture (a drag that writes per tick) keeps painting instead of going dark until it
13
+ * stops. What coalesces is everything that arrives while a run is scheduled or in flight — those
14
+ * collapse into ONE follow-up run carrying the newest value.
15
+ *
16
+ * `run` may be async; a value arriving mid-run waits for it rather than overlapping, which is what
17
+ * keeps an older result from landing after a newer one.
18
+ */
19
+ export declare function coalesceLatest<T>({ run, schedule, }: {
20
+ readonly run: (value: T) => void | Promise<void>;
21
+ /** When a queued run fires — an idle callback, a timer, immediately. */
22
+ readonly schedule: (fire: () => void) => void;
23
+ }): ((value: T) => void) & {
24
+ cancel: () => void;
25
+ };