@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,809 @@
1
+ import { kindOf, memberOf, pathOf, ref, splitRef } from "./utils/refs.js";
2
+ import { authoredBag, memberFromLeaf, resolveComponentProps } from "./projections.js";
3
+ import { intoName, routesContent } from "./prop-surface.js";
4
+ import { graftPreviewElements } from "../spec/preview-elements.js";
5
+ import { componentLayerClass, componentPropClasses, componentRuleClasses, layerCompositeProps, splitStyleProps, styleRuleMotionClasses } from "./class-names.js";
6
+ //#region src/framework/render-spec.ts
7
+ const refOf = (value) => typeof value?.__ref === "string" ? value.__ref : void 0;
8
+ const layerOf = (element) => {
9
+ const target = refOf(element);
10
+ if (target === void 0) return void 0;
11
+ const { kind, qualifiedPath } = splitRef(target);
12
+ return kind === "layer" ? qualifiedPath : void 0;
13
+ };
14
+ /** The prop a node's element is CHOSEN BY — `{ $state: '/name' }`. */
15
+ const boundPropOf = (element) => {
16
+ const marker = element?.$state;
17
+ return typeof marker === "string" ? marker.replace(/^\//, "") : void 0;
18
+ };
19
+ /** The slot PROP a node STANDS FOR — a `Slot`-typed node whose `name` prop says which prop's
20
+ * instance content splices at its position among the siblings. json-render's own vocabulary (the
21
+ * `Slot` registry primitive and its `name` prop), so the stored node and the rendered element are
22
+ * one grammar. */
23
+ const slotAnatomyPropOf = (node) => {
24
+ if (node?.element !== "Slot") return void 0;
25
+ const name = node.props?.name;
26
+ return typeof name === "string" ? name : void 0;
27
+ };
28
+ const bodyOf = (config, path) => config.resolve("component", path)?.toJSON();
29
+ /** The node a tree is rooted at — the one named `root`, else the first declared. The same rule
30
+ * `rootLayerOf` uses for layers, which is why neither is stored. */
31
+ function rootKeyOf(nodes) {
32
+ return "root" in nodes ? "root" : Object.keys(nodes)[0] ?? "root";
33
+ }
34
+ /** Every key a node holds — child edges plus slot fills, which nest without an edge. */
35
+ function heldKeys(node) {
36
+ return [...node?.children ?? [], ...Object.values(node?.slots ?? {}).flat()];
37
+ }
38
+ /** How many nodes a key reaches, itself included — the size of the tree hanging off it. Visited-set
39
+ * guarded, so a cycle counts each node once instead of running forever. */
40
+ function reachOf(nodes, from) {
41
+ const seen = new Set([from]);
42
+ const queue = [from];
43
+ while (queue.length > 0) {
44
+ const key = queue.shift();
45
+ for (const child of heldKeys(nodes[key])) {
46
+ if (seen.has(child)) continue;
47
+ seen.add(child);
48
+ queue.push(child);
49
+ }
50
+ }
51
+ return seen.size;
52
+ }
53
+ /**
54
+ * The node a tree ENTERS at — the one nothing else claims as a child.
55
+ *
56
+ * A name can't answer this. `root` names the root LAYER, and a render is free to put a wrapper above
57
+ * that layer — a menu provider, a positioner, a portal — so the layer is somewhere in the middle of
58
+ * its own tree. Entering by name amputated every ancestor: the tree rendered without the provider
59
+ * that its own descendants read from, and those descendants threw on the first paint.
60
+ *
61
+ * Structure states it instead, and in a whole tree exactly one node is unclaimed. Two or more is a
62
+ * FOREST — a reader that couldn't finish, or a condition that left siblings with no parent — and then
63
+ * the component is whichever of them holds most of it: the strays get dropped either way, and
64
+ * dropping the real tree to render a stray leaf is the worse of the two. Nothing unclaimed at all
65
+ * (a cycle) falls back to the name, which is the best a malformed tree deserves.
66
+ */
67
+ function entryKeyOf(nodes) {
68
+ const claimed = /* @__PURE__ */ new Set();
69
+ for (const node of Object.values(nodes)) for (const child of heldKeys(node)) claimed.add(child);
70
+ const unclaimed = Object.keys(nodes).filter((key) => !claimed.has(key));
71
+ if (unclaimed.length <= 1) return unclaimed[0] ?? rootKeyOf(nodes);
72
+ let best = unclaimed[0];
73
+ let bestReach = reachOf(nodes, best);
74
+ for (const key of unclaimed.slice(1)) {
75
+ const reach = reachOf(nodes, key);
76
+ if (reach > bestReach || reach === bestReach && key === "root") {
77
+ best = key;
78
+ bestReach = reach;
79
+ }
80
+ }
81
+ return best;
82
+ }
83
+ /** What a node's `element` renders, as a spec `type`. A layer ref resolves through the component's
84
+ * own layers to whatever that layer is; a bound element has no json-render form (its `type` is a
85
+ * plain string), so it is reported rather than guessed at. */
86
+ function typeOf(layers, element) {
87
+ const layer = layerOf(element);
88
+ const target = layer === void 0 ? element : layers[layer];
89
+ if (typeof target === "string") return target;
90
+ return refOf(target);
91
+ }
92
+ /**
93
+ * A node's stored props as an author wrote them. The anatomy keeps a style prop's token as a ref
94
+ * (`bg` as `token:spectrum/carbon/5`) so a rename cascades; a spec sets the leaf the prop's own
95
+ * domain names (`carbon/5`), and a component handed the ref object paints nothing. `authoredBag` is
96
+ * the one inverse of that binding, so the projection reads through it rather than trimming a path.
97
+ */
98
+ function authoredProps(config, props) {
99
+ return props ? authoredBag(config, props) : {};
100
+ }
101
+ /**
102
+ * A component's anatomy, projected to the json-render spec a canvas reads.
103
+ *
104
+ * The artifact's SOURCE changes and its shape does not: `element` becomes `type` and a ref
105
+ * serializes to its string form, while `children` / `visible` / `text` pass through, since those
106
+ * were borrowed from json-render's own vocabulary rather than invented.
107
+ *
108
+ * A component with no stored anatomy but ONE layer is still answered outright — it is one element,
109
+ * and that was always stated rather than run.
110
+ */
111
+ function deriveSpec(config, path) {
112
+ const body = bodyOf(config, path) ?? {};
113
+ const layers = body.layers ?? {};
114
+ const anatomy = body.anatomy;
115
+ if (!anatomy || Object.keys(anatomy).length === 0) {
116
+ if (Object.keys(layers).length !== 1) return void 0;
117
+ return instanceSpec(path, {
118
+ "data-uds-component": path,
119
+ "data-uds-layer": rootKeyOf(layers)
120
+ });
121
+ }
122
+ const elements = {};
123
+ for (const [key, node] of Object.entries(anatomy)) {
124
+ const slotAnatomyProp = slotAnatomyPropOf(node);
125
+ if (slotAnatomyProp !== void 0) {
126
+ elements[key] = {
127
+ type: "Slot",
128
+ props: {
129
+ ...authoredProps(config, node.props),
130
+ "data-uds-slot-anatomy": slotAnatomyProp
131
+ }
132
+ };
133
+ continue;
134
+ }
135
+ const type = typeOf(layers, node.element);
136
+ if (!type) return void 0;
137
+ const layer = layerOf(node.element);
138
+ const props = {
139
+ ...authoredProps(config, node.props),
140
+ ...node.text !== void 0 ? { children: node.text } : {},
141
+ ...layer !== void 0 ? {
142
+ "data-uds-layer": layer,
143
+ "data-uds-component": path
144
+ } : {}
145
+ };
146
+ elements[key] = {
147
+ type,
148
+ ...Object.keys(props).length ? { props } : {},
149
+ ...node.children?.length ? { children: node.children } : {},
150
+ ...node.slots && Object.keys(node.slots).length ? { slots: node.slots } : {},
151
+ ...node.visible !== void 0 ? { visible: node.visible } : {}
152
+ };
153
+ }
154
+ return {
155
+ root: entryKeyOf(elements),
156
+ elements
157
+ };
158
+ }
159
+ /**
160
+ * ONE COMPONENT, as a spec — the instance form, and the only place the `component:` prefix is minted.
161
+ *
162
+ * A spec type is `kind:identity`, always: the emitted registry keys every entry that way and holds
163
+ * no bare names, so `Box` resolves to nothing while `component:Box` resolves to the module. That
164
+ * makes the prefix load-bearing rather than decorative, and something load-bearing spelled by
165
+ * string-concatenation at each site is a spelling waiting to drift — three places in this file did
166
+ * it, and a consumer that wanted the same shape had no choice but to add a fourth.
167
+ *
168
+ * So consumers ask for the SHAPE instead of assembling it, and the type itself comes from `ref` —
169
+ * the same maker `Component.ref` is bound to — rather than a template. A caller outside this
170
+ * package has no business knowing the prefix at all.
171
+ */
172
+ function instanceSpec(path, props = {}) {
173
+ return {
174
+ root: "root",
175
+ elements: { root: {
176
+ type: ref("component", path).__ref,
177
+ props
178
+ } }
179
+ };
180
+ }
181
+ /**
182
+ * The spec for a component, ALWAYS — the leaf form when its composition doesn't project.
183
+ *
184
+ * `deriveSpec` declines rather than guess, and that is right: a tree missing a node is worse than an
185
+ * admission that it can't be built. But a caller still has to paint something, and the honest thing to
186
+ * paint is the component ITSELF — one element, `component:<path>`, which the renderer resolves to the
187
+ * real module with whatever its render closes over intact. That is strictly better than the previous
188
+ * fallback (a spec captured by an earlier build), which showed a structure the config no longer
189
+ * describes and let an editor author against it.
190
+ *
191
+ * So the two answers are separated: what to RENDER (always available) and WHICH of the two it is. A
192
+ * surface reads `kind` to decide whether to offer composition tools, and `reason` to explain why not.
193
+ */
194
+ function componentSpec(config, path) {
195
+ const derived = deriveSpec(config, path);
196
+ if (derived) return {
197
+ spec: derived,
198
+ kind: "composition"
199
+ };
200
+ const body = bodyOf(config, path) ?? {};
201
+ const layers = Object.keys(body.layers ?? {}).length;
202
+ const reason = !body.anatomy || Object.keys(body.anatomy).length === 0 ? `"${path}" has ${layers} layers but no anatomy saying how they assemble, so its composition can't be shown or edited here — it renders as itself.` : `"${path}" has an element whose type only an instance settles (a bound element), so its composition can't be shown or edited here — it renders as itself.`;
203
+ return {
204
+ spec: instanceSpec(path),
205
+ kind: "leaf",
206
+ reason
207
+ };
208
+ }
209
+ /**
210
+ * A component as it is SHOWN — itself, in the example state its author wrote.
211
+ *
212
+ * The sibling above answers "what is this made of", and that is the question a layer panel and a
213
+ * variant matrix ask. A catalogue card, a palette card and a docs thumbnail ask the other one, and
214
+ * answering them with a composition is what left those tiles wrong: {@link deriveSpec} reads anatomy
215
+ * off the render's JSX STATICALLY, without the preview's props, so a prop-driven branch arrives as an
216
+ * unresolved `$state` condition and prop-driven text doesn't arrive at all. The tile painted the
217
+ * structure with its example content missing.
218
+ *
219
+ * One element, always, whatever the component is made of — because WHO DRAWS IT isn't this
220
+ * projection's call. A built component is in the renderer's registry, so the element resolves to its
221
+ * real module and is handed the example props directly. One created in Studio isn't, so
222
+ * {@link expandSpec} replaces it with the tree the config describes, resolving those same props'
223
+ * conditions and bound elements on the way. Both paths exist already; emitting the component and
224
+ * letting the renderer choose is what reaches them.
225
+ *
226
+ * Only the preview's props. A component's `defaultProps` are already folded into its layer's
227
+ * zero-specificity rule at build time, so seeding them here would re-apply as an instance's style
228
+ * props what the stylesheet has said once already.
229
+ *
230
+ * One stored preview value is not a prop yet: JSX such as `startIcon: <Icon/>` crosses config.json as
231
+ * a `PreviewElement` data marker. It is lowered here into the native `slots` + keyed-element form a
232
+ * spec authors directly. That makes this projection render-ready for every host instead of relying on
233
+ * a Studio-only registry wrapper to revive the marker later.
234
+ */
235
+ function previewSpec(config, path) {
236
+ const body = bodyOf(config, path);
237
+ if (!body) return void 0;
238
+ const values = body.previewProps ?? {};
239
+ return graftPreviewElements(instanceSpec(path, values), values);
240
+ }
241
+ /** A key no emitted element is using yet. Anatomy keys are namespaced under the instance they belong
242
+ * to, so two instances of one component can't collide; the suffix loop is the backstop for a
243
+ * design file that happens to have named an element the same thing. */
244
+ function freeKey(sink, hint) {
245
+ if (!(hint in sink.elements)) return hint;
246
+ let index = 2;
247
+ while (`${hint}${index}` in sink.elements) index += 1;
248
+ return `${hint}${index}`;
249
+ }
250
+ /** Whether this expansion should replace `type` with what the config says it's made of. */
251
+ function expandable(sink, type) {
252
+ if (kindOf(type) !== "component") return false;
253
+ if (sink.rendered?.has(type)) return false;
254
+ const path = pathOf(type);
255
+ if (sink.expanding.includes(path)) return false;
256
+ return sink.config.resolve("component", path) !== void 0;
257
+ }
258
+ /**
259
+ * Resolve every element's `visible` CONDITION against a prop bag, leaving a plain boolean.
260
+ *
261
+ * json-render evaluates the condition itself at render time, so this changes nothing about what
262
+ * paints. What it changes is what the spec can be ASKED: an unresolved `{ $state: '/startIcon' }`
263
+ * says only "it depends", where `false` says "this draws nothing", and a reader that has to decide
264
+ * whether a container is empty needs the second.
265
+ *
266
+ * That reader is the UDS renderer. A container whose children all draw nothing must fall back to its
267
+ * `props.children` label — and with the condition unresolved it could not tell, so every `Button`
268
+ * cell in the matrix rendered blank: the root lists `startIcon`/`endIcon`, and an unset icon is a
269
+ * node whose condition is false. `expandSpec` already resolves visibility for an INSTANCE; this is
270
+ * the same answer for a spec rendered as the component's own anatomy, where the caller supplies the
271
+ * state instead of an instance.
272
+ *
273
+ * A condition that does not resolve is left exactly as it was, so nothing is claimed about it.
274
+ */
275
+ function specWithResolvedVisibility(spec, state) {
276
+ let changed = false;
277
+ const elements = {};
278
+ for (const [key, element] of Object.entries(spec.elements)) {
279
+ const resolved = element.visible === void 0 ? void 0 : resolveVisibility(element.visible, state);
280
+ if (resolved === void 0 || resolved === element.visible) {
281
+ elements[key] = element;
282
+ continue;
283
+ }
284
+ changed = true;
285
+ elements[key] = {
286
+ ...element,
287
+ visible: resolved
288
+ };
289
+ }
290
+ return changed ? {
291
+ ...spec,
292
+ elements
293
+ } : spec;
294
+ }
295
+ /**
296
+ * How each operator judges a state value against its operand. One table for every reader of the
297
+ * grammar: `resolveVisibility` applies it, `visibilityTerms` names it, and the entity's schema is
298
+ * checked against its keys. Insertion order is precedence for a malformed test that carries more
299
+ * than one operator, and the readers share it through {@link OPERATORS}.
300
+ */
301
+ const COMPARATORS = {
302
+ eq: (value, operand) => value === operand,
303
+ neq: (value, operand) => value !== operand,
304
+ gt: (value, operand) => Number(value) > Number(operand),
305
+ gte: (value, operand) => Number(value) >= Number(operand),
306
+ lt: (value, operand) => Number(value) < Number(operand),
307
+ lte: (value, operand) => Number(value) <= Number(operand)
308
+ };
309
+ const OPERATORS = Object.keys(COMPARATORS);
310
+ /** The operator a `$state` test carries, or undefined for a bare truthiness test. */
311
+ function operatorOf(test) {
312
+ return OPERATORS.find((name) => name in test);
313
+ }
314
+ /** A value in json-render's `visible` grammar, resolved against a prop bag. `undefined` when this
315
+ * reader can't settle it, which leaves the condition on the element for the renderer to judge. */
316
+ function resolveVisibility(condition, state) {
317
+ if (condition === void 0) return true;
318
+ if (typeof condition === "boolean") return condition;
319
+ if (Array.isArray(condition)) {
320
+ let known = true;
321
+ for (const entry of condition) {
322
+ const result = resolveVisibility(entry, state);
323
+ if (result === false) return false;
324
+ if (result === void 0) known = false;
325
+ }
326
+ return known ? true : void 0;
327
+ }
328
+ if (typeof condition !== "object" || condition === null) return void 0;
329
+ const test = condition;
330
+ if (Array.isArray(test.$or)) {
331
+ let known = true;
332
+ for (const entry of test.$or) {
333
+ const result = resolveVisibility(entry, state);
334
+ if (result === true) return true;
335
+ if (result === void 0) known = false;
336
+ }
337
+ return known ? false : void 0;
338
+ }
339
+ if (Array.isArray(test.$and)) return resolveVisibility(test.$and, state);
340
+ if (typeof test.$state !== "string") return void 0;
341
+ const value = state[test.$state.replace(/^\//, "")];
342
+ const operator = operatorOf(test);
343
+ const result = operator ? COMPARATORS[operator](value, test[operator]) : Boolean(value);
344
+ return test.not === true ? !result : result;
345
+ }
346
+ /**
347
+ * Which PROPS a `visible` condition reads, in the order they appear.
348
+ *
349
+ * `resolveVisibility` answers "does this draw here"; this answers "what decides that" — the question
350
+ * an editor asks. A surface offering to bind visibility to a property needs to know whether one is
351
+ * already driving it, and a surface refusing an edit needs to name what to change instead of the
352
+ * layer. Both were guessing: the layers panel told an author to "switch to a matching cell" for a
353
+ * node gated on a slot being filled, where no cell in the matrix can ever match.
354
+ *
355
+ * Duplicates are collapsed, so a condition testing one prop twice reads as the one prop it is about.
356
+ */
357
+ function visibilityStateProps(condition) {
358
+ const names = [];
359
+ collectStateProps(condition, names);
360
+ return [...new Set(names)];
361
+ }
362
+ function collectStateProps(condition, sink) {
363
+ if (Array.isArray(condition)) {
364
+ for (const entry of condition) collectStateProps(entry, sink);
365
+ return;
366
+ }
367
+ if (typeof condition !== "object" || condition === null) return;
368
+ const test = condition;
369
+ if (Array.isArray(test.$or)) {
370
+ for (const entry of test.$or) collectStateProps(entry, sink);
371
+ return;
372
+ }
373
+ if (Array.isArray(test.$and)) {
374
+ for (const entry of test.$and) collectStateProps(entry, sink);
375
+ return;
376
+ }
377
+ if (typeof test.$state === "string") sink.push(test.$state.replace(/^\//, ""));
378
+ }
379
+ /**
380
+ * The tests a `visible` condition makes, in order, flattened to one list.
381
+ *
382
+ * `visibilityStateProps` names the props; this keeps what is asked of each one, so a surface can say
383
+ * "shows when `tone` is `danger`" rather than "follows `tone`". Grouping survives as `junction` and
384
+ * `group`: the stored grammar is an and-list whose entries are single tests or one `$or` each, so
385
+ * the two together are enough to read the condition back. A boolean or a shape this reader does not
386
+ * know yields no terms.
387
+ */
388
+ function visibilityTerms(condition) {
389
+ const sink = [];
390
+ collectTerms({
391
+ condition,
392
+ junction: "and",
393
+ group: 0,
394
+ sink
395
+ });
396
+ return sink;
397
+ }
398
+ /** The index for a term that opens a new group: one past the last term collected. */
399
+ function nextGroup(sink) {
400
+ const last = sink[sink.length - 1];
401
+ return last ? last.group + 1 : 0;
402
+ }
403
+ function collectTerms({ condition, junction, group, sink }) {
404
+ if (Array.isArray(condition)) {
405
+ for (const entry of condition) collectTerms({
406
+ condition: entry,
407
+ junction: "and",
408
+ group: nextGroup(sink),
409
+ sink
410
+ });
411
+ return;
412
+ }
413
+ if (typeof condition !== "object" || condition === null) return;
414
+ const test = condition;
415
+ if (Array.isArray(test.$or)) {
416
+ const shared = nextGroup(sink);
417
+ for (const entry of test.$or) collectTerms({
418
+ condition: entry,
419
+ junction: "or",
420
+ group: shared,
421
+ sink
422
+ });
423
+ return;
424
+ }
425
+ if (Array.isArray(test.$and)) {
426
+ collectTerms({
427
+ condition: test.$and,
428
+ junction: "and",
429
+ group,
430
+ sink
431
+ });
432
+ return;
433
+ }
434
+ if (typeof test.$state !== "string") return;
435
+ const operator = operatorOf(test);
436
+ sink.push({
437
+ prop: test.$state.replace(/^\//, ""),
438
+ operator: operator ?? "truthy",
439
+ ...operator ? { value: test[operator] } : {},
440
+ negated: test.not === true,
441
+ junction,
442
+ group
443
+ });
444
+ }
445
+ /**
446
+ * A `visible` condition with every bare truthiness test of `prop` taken out.
447
+ *
448
+ * Three answers: `undefined` for a condition that makes no such test, so a caller leaves the field
449
+ * alone; `null` when nothing survives the removal, which is the value that clears it; otherwise the
450
+ * condition that remains, unwrapped when one term is left.
451
+ *
452
+ * Only the bare form goes — `{ $state: '/prop' }` with no comparison and no `not`, which is the test
453
+ * a value being present answers. A `$or` group holding one goes whole, since a true member settles
454
+ * the group; its other members go with it, and moving the fill out later does not bring them back,
455
+ * which is also true of a bare gate. `$state` is matched without its JSON-pointer slash, so both
456
+ * spellings are the same test.
457
+ */
458
+ function withoutTruthyTerm({ condition, prop }) {
459
+ if (spentBy({
460
+ condition,
461
+ prop
462
+ })) return null;
463
+ if (!Array.isArray(condition)) return void 0;
464
+ const kept = condition.filter((entry) => !spentBy({
465
+ condition: entry,
466
+ prop
467
+ }));
468
+ if (kept.length === condition.length) return void 0;
469
+ if (kept.length === 0) return null;
470
+ return kept.length === 1 ? kept[0] : kept;
471
+ }
472
+ /** Whether a single term of an and-list is one `prop` being present makes true: the bare test, an
473
+ * `eq: true` test (content is never the boolean `true`, so presence is the only reading that can
474
+ * ever hold), or an `$or` group with one of those among its members. */
475
+ function spentBy({ condition, prop }) {
476
+ if (typeof condition !== "object" || condition === null) return false;
477
+ const test = condition;
478
+ if (Array.isArray(test.$or)) return test.$or.some((entry) => spentBy({
479
+ condition: entry,
480
+ prop
481
+ }));
482
+ if (typeof test.$state !== "string") return false;
483
+ return test.$state.replace(/^\//, "") === prop && test.not !== true && (operatorOf(test) === void 0 || operatorOf(test) === "eq" && test.eq === true);
484
+ }
485
+ /**
486
+ * The type a BOUND element resolves to, given the value its prop was handed.
487
+ *
488
+ * This is the one thing json-render has no vocabulary for — `UIElement.type` is a plain string — so
489
+ * a stored spec can't hold it and `deriveSpec` declines. An expansion is a different position: the
490
+ * instance is right here, so the prop has a value, and the prop's own declaration says what domain
491
+ * that value is drawn from. `Icon` is the case that matters: one bound node, resolved per instance,
492
+ * rather than 51 conditioned siblings copying a library's index into every component that draws a
493
+ * glyph.
494
+ *
495
+ * Two ways the domain is known, in order: the prop DELEGATES it (`value` is a ref to the library,
496
+ * which is the shape that keeps 1,530 names in one place), or the prop enumerates its values and the
497
+ * member is found by asking which group declares it. The second exists because a config migrated
498
+ * from v1 spells an icon prop as an enumeration, and a glyph is no less resolvable for it.
499
+ */
500
+ function boundElementType(config, componentPath, prop, value) {
501
+ if (typeof value !== "string" || !value) return void 0;
502
+ if (value.includes("/")) return void 0;
503
+ const decl = resolveComponentProps(config, componentPath)[prop];
504
+ const target = refOf(decl?.value);
505
+ if (target) {
506
+ if (memberOf(target) !== void 0) return void 0;
507
+ const member = memberFromLeaf(config, target, value);
508
+ return member ? `${kindOf(target)}:${member}` : void 0;
509
+ }
510
+ const matches = config.list("icon").filter((member) => (member.path.split("/").pop() ?? "") === value);
511
+ return matches.length === 1 ? `icon:${matches[0]?.path}` : void 0;
512
+ }
513
+ /**
514
+ * The props of an instance that the component CONSUMES rather than passes on — the same split the
515
+ * emitted module's destructuring makes (`downlevel.ts`, `styleRuleBindings`).
516
+ *
517
+ * A variant selects a style rule and a slot routes content, so neither reaches the DOM. Neither does
518
+ * a DECLARED prop a style rule tests: the config says it picks a class and says nothing else about
519
+ * it, which makes it part of the component's API rather than an attribute. `PanelIconButton`'s
520
+ * `active` is the shape of it — a boolean the rules branch on, spread onto the button by both this
521
+ * projection and the emitted module until each learned to consume it.
522
+ *
523
+ * An UNDECLARED prop a rule tests stays: the component never claimed it, so a call site passing it
524
+ * (`disabled` on a Pressable) means it for the element.
525
+ */
526
+ function consumedProps(config, path, body) {
527
+ const consumed = new Set(["className", "layerProps"]);
528
+ const declared = body.props ?? {};
529
+ for (const [name, decl] of Object.entries(declared)) if (decl?.type === "variant" || decl?.type === "slot" || decl?.type === "forward" || decl?.type === "composite") consumed.add(name);
530
+ for (const rule of componentRuleClasses(config, path)) for (const prop of Object.keys(rule.when)) if (declared[prop]) consumed.add(prop);
531
+ return consumed;
532
+ }
533
+ /** The prop JSX children arrive on — json-render's content channel, and the same name
534
+ * `childrenPolicy` reads to answer whether a component accepts any. Not a system-defined name: a
535
+ * design system names its components and tokens, and this one names the channel. */
536
+ const CONTENT_PROP = "children";
537
+ function slotTargets(config, body) {
538
+ const byLayer = /* @__PURE__ */ new Map();
539
+ const untargeted = [];
540
+ for (const [from, decl] of Object.entries(body.props ?? {})) {
541
+ if (decl?.type === "slot") {
542
+ untargeted.push({
543
+ ...decl,
544
+ from,
545
+ untargeted: true
546
+ });
547
+ continue;
548
+ }
549
+ if (decl?.type !== "forward") continue;
550
+ if (!routesContent(config, body.layers, decl)) continue;
551
+ const target = refOf(decl.target);
552
+ if (target) byLayer.set(pathOf(target), {
553
+ ...decl,
554
+ from
555
+ });
556
+ else untargeted.push({
557
+ ...decl,
558
+ from,
559
+ untargeted: true
560
+ });
561
+ }
562
+ const root = rootKeyOf(body.layers ?? {});
563
+ const content = untargeted.find((route) => route.from === CONTENT_PROP) ?? untargeted[0];
564
+ if (root && content && !byLayer.has(root)) byLayer.set(root, content);
565
+ return {
566
+ byLayer,
567
+ untargeted
568
+ };
569
+ }
570
+ /**
571
+ * Where a component's slot props route their content, as the config states it.
572
+ *
573
+ * {@link expandInstance} has always known this; nothing outside this file could ask. A surface that
574
+ * needs the same answer had to guess from the spec's shape instead — "the one element carrying a
575
+ * string" — and a spec projected from the ANATOMY carries no strings at all, so the guess fell
576
+ * through to the root. For a component whose content slot NAMES its layer that is the wrong element
577
+ * AND an occupied one: the label lands beside the element children it was supposed to go inside, and
578
+ * the layer meant to hold it renders empty. Every one of Studio's own components shaped that way
579
+ * (`Badge`, `StudioButton`, `Toggle`, …) painted as an empty shell in the component editor.
580
+ *
581
+ * Exported so the answer has ONE owner. An untargeted slot still resolves to the root here — that is
582
+ * `slotTargets`' rule, not a caller's assumption, and it is the same rule the expansion renders by.
583
+ */
584
+ function slotTargetsOf(config, path) {
585
+ const body = bodyOf(config, path);
586
+ if (!body) return [];
587
+ const { byLayer, untargeted } = slotTargets(config, body);
588
+ const root = rootKeyOf(body.layers ?? {});
589
+ return [...[...byLayer].filter(([, decl]) => !decl.untargeted).map(([layer, decl]) => ({
590
+ layer,
591
+ from: decl.from,
592
+ into: intoName(decl.into)
593
+ })), ...root ? untargeted.map((decl) => ({
594
+ layer: root,
595
+ from: decl.from,
596
+ into: intoName(decl.into)
597
+ })) : []];
598
+ }
599
+ /** The className a layer wears for one instance: its own class, every style rule whose condition
600
+ * holds, and — on the root only — what the call site passed. */
601
+ function classesFor(config, path, layer, state, extra) {
602
+ const parts = [componentLayerClass(config, path, layer)];
603
+ parts.push(...componentPropClasses(config, path, state)[layer] ?? []);
604
+ parts.push(...styleRuleMotionClasses(config, path, state)[layer] ?? []);
605
+ for (const rule of componentRuleClasses(config, path)) {
606
+ if (rule.layer !== layer) continue;
607
+ if (Object.entries(rule.when).every(([prop, value]) => String(state[prop]) === String(value))) parts.push(rule.className);
608
+ }
609
+ parts.push(...extra);
610
+ return parts.filter(Boolean).join(" ");
611
+ }
612
+ /** Emit one element, expanding it when the config describes what it's made of. Returns the key it
613
+ * was emitted under. */
614
+ function place(sink, type, props, children, hint, slots) {
615
+ if (expandable(sink, type)) return expandInstance(sink, pathOf(type), props, children, hint, slots);
616
+ let tag = type;
617
+ let own = props;
618
+ if (!type.includes(":") && typeof props.as === "string") {
619
+ const { as, ...rest } = props;
620
+ tag = as;
621
+ own = rest;
622
+ }
623
+ if (sink.rendered && !sink.rendered.has(tag)) sink.unresolved.add(tag);
624
+ const key = freeKey(sink, hint);
625
+ sink.elements[key] = {
626
+ type: tag,
627
+ props: own,
628
+ ...children.length ? { children: [...children] } : {},
629
+ ...slots && Object.keys(slots).length ? { slots } : {}
630
+ };
631
+ return key;
632
+ }
633
+ /**
634
+ * Replace one component instance with the tree it is made of.
635
+ *
636
+ * Every class is computed HERE, from the config as it stands, which is the difference between this
637
+ * and a stored spec: an edit to a token, a style rule or a layer shows up on the next render with
638
+ * nothing to regenerate. `content` is the children the instance was given — placed on the root when
639
+ * the component has nowhere else declared to put them.
640
+ */
641
+ function expandInstance(sink, path, instanceProps, content, hint, instanceSlots) {
642
+ const { config } = sink;
643
+ const body = bodyOf(config, path) ?? {};
644
+ const layers = body.layers ?? {};
645
+ const anatomy = body.anatomy && Object.keys(body.anatomy).length > 0 ? body.anatomy : { root: { element: { __ref: `layer:${rootKeyOf(layers)}` } } };
646
+ const filled = {};
647
+ for (const [from, fills] of Object.entries(instanceSlots ?? {})) if (fills.length > 0 && instanceProps[from] === void 0) filled[from] = true;
648
+ const state = {
649
+ ...body.defaultProps,
650
+ ...filled,
651
+ ...instanceProps
652
+ };
653
+ const consumed = consumedProps(config, path, body);
654
+ const { byLayer: targets } = slotTargets(config, body);
655
+ const supplied = {
656
+ ...body.defaultProps ?? {},
657
+ ...instanceProps
658
+ };
659
+ const bag = {};
660
+ for (const [name, value] of Object.entries(supplied)) if (!consumed.has(name)) bag[name] = value;
661
+ const { className: styleClasses, rest } = splitStyleProps({
662
+ config,
663
+ bag,
664
+ through: [path]
665
+ });
666
+ const layerProps = instanceProps.layerProps ?? {};
667
+ const forwarded = layerCompositeProps(config, path, state);
668
+ const entryNode = entryKeyOf(anatomy);
669
+ const rootLayer = rootKeyOf(layers);
670
+ const hostNode = Object.keys(anatomy).find((key) => layerOf(anatomy[key]?.element) === rootLayer) ?? entryNode;
671
+ const nested = {
672
+ ...sink,
673
+ expanding: [...sink.expanding, path]
674
+ };
675
+ const rootTarget = targets.get(rootLayer);
676
+ const untargetedSlot = rootTarget?.untargeted ? rootTarget.from : void 0;
677
+ let contentPlaced = false;
678
+ const routedFroms = /* @__PURE__ */ new Set();
679
+ for (const target of targets.values()) routedFroms.add(target.from);
680
+ const unroutedFills = Object.entries(instanceSlots ?? {}).filter(([from]) => !routedFroms.has(from)).flatMap(([, fills]) => fills);
681
+ const allContent = [...content, ...unroutedFills];
682
+ const emit = (key, keyHint) => {
683
+ const node = anatomy[key];
684
+ if (!node) return void 0;
685
+ const visible = resolveVisibility(node.visible, state);
686
+ const layer = layerOf(node.element);
687
+ const isRoot = key === hostNode;
688
+ let type = typeOf(layers, node.element);
689
+ const bound = boundPropOf(node.element);
690
+ if (bound) type = boundElementType(config, path, bound, state[bound]);
691
+ if (!type) {
692
+ sink.unresolved.add(bound ? `component:${path}#${key} (${bound})` : `component:${path}#${key}`);
693
+ return;
694
+ }
695
+ if (visible === false) {
696
+ const key = freeKey(nested, keyHint);
697
+ nested.elements[key] = {
698
+ type,
699
+ props: {},
700
+ visible: false
701
+ };
702
+ return key;
703
+ }
704
+ const slot = layer ? targets.get(layer) : void 0;
705
+ const slotValue = slot ? instanceProps[slot.from] : void 0;
706
+ const props = layer ? {
707
+ ...authoredProps(config, node.props),
708
+ "data-uds-component": path,
709
+ "data-uds-layer": layer,
710
+ ...forwarded[layer],
711
+ ...isRoot ? rest : {},
712
+ ...slot && slotValue !== void 0 ? { [intoName(slot.into)]: slotValue } : {},
713
+ ...layerProps[layer],
714
+ className: classesFor(config, path, layer, state, [
715
+ isRoot ? styleClasses : void 0,
716
+ isRoot ? instanceProps.className : void 0,
717
+ layerProps[layer]?.className
718
+ ]) || void 0
719
+ } : authoredProps(config, node.props);
720
+ if (node.text !== void 0) props.children = node.text;
721
+ const children = [];
722
+ for (const child of node.children ?? []) {
723
+ const childSlot = slotAnatomyPropOf(anatomy[child]);
724
+ if (childSlot !== void 0) {
725
+ if (childSlot === untargetedSlot && allContent.length > 0) {
726
+ children.push(...allContent);
727
+ contentPlaced = true;
728
+ }
729
+ continue;
730
+ }
731
+ const placed = emit(child, `${keyHint}•${child}`);
732
+ if (placed) children.push(placed);
733
+ }
734
+ if (isRoot && allContent.length > 0 && !contentPlaced) children.push(...allContent);
735
+ const slots = {};
736
+ const routed = slot ? instanceSlots?.[slot.from] : void 0;
737
+ const overridden = routed?.length && slot && !slot.untargeted ? intoName(slot.into) : void 0;
738
+ for (const [name, fills] of Object.entries(node.slots ?? {})) {
739
+ if (name === overridden) continue;
740
+ const placedFills = fills.map((fill) => emit(fill, `${keyHint}•${fill}`)).filter((fillKey) => fillKey !== void 0);
741
+ if (placedFills.length) slots[name] = placedFills;
742
+ }
743
+ if (overridden && routed) slots[overridden] = [...routed];
744
+ if (routed?.length && !overridden) children.push(...routed);
745
+ const placed = place(nested, type, props, children, keyHint, Object.keys(slots).length ? slots : void 0);
746
+ if (visible === void 0) withCondition(nested, placed, { visible: node.visible });
747
+ return placed;
748
+ };
749
+ return emit(entryNode, hint) ?? hint;
750
+ }
751
+ /** Attach a condition the reader couldn't settle to an already-emitted element. */
752
+ function withCondition(sink, key, condition) {
753
+ const element = sink.elements[key];
754
+ if (element && condition.visible !== void 0) sink.elements[key] = {
755
+ ...element,
756
+ visible: condition.visible
757
+ };
758
+ return key;
759
+ }
760
+ /**
761
+ * Expand every component element the renderer can't name into the tree it is made of.
762
+ *
763
+ * The spec's own keys are KEPT — an expanded instance's root is emitted under the key it already
764
+ * had, so a `slots` entry, a selection marker, or anything else that names an element by key
765
+ * still resolves. Only the nodes an expansion adds get new keys, namespaced under the instance they
766
+ * belong to.
767
+ */
768
+ function expandSpec(config, spec, options = {}) {
769
+ const sink = {
770
+ config,
771
+ rendered: options.rendered,
772
+ elements: {},
773
+ unresolved: /* @__PURE__ */ new Set(),
774
+ expanding: []
775
+ };
776
+ const emit = (key) => {
777
+ const element = spec.elements[key];
778
+ if (!element) return void 0;
779
+ const children = [];
780
+ for (const child of element.children ?? []) {
781
+ const placed = emit(child);
782
+ if (placed) children.push(placed);
783
+ }
784
+ const slots = {};
785
+ for (const [name, fills] of Object.entries(element.slots ?? {})) slots[name] = fills.map((fill) => emit(fill)).filter((placed) => placed !== void 0);
786
+ const placed = place(sink, element.type, { ...element.props }, children, key, slots);
787
+ if (element.visible !== void 0) withCondition(sink, placed, { visible: element.visible });
788
+ return placed;
789
+ };
790
+ return {
791
+ spec: {
792
+ root: emit(spec.root) ?? spec.root,
793
+ elements: sink.elements
794
+ },
795
+ unresolved: [...sink.unresolved]
796
+ };
797
+ }
798
+ /**
799
+ * One component instance, expanded from nothing but the config — what a canvas paints for a
800
+ * component created in Studio.
801
+ *
802
+ * The single-element spec this starts from is what a design-file node amounts to, so this is
803
+ * {@link expandSpec} with the ceremony removed.
804
+ */
805
+ function expandComponent(config, path, props = {}, options = {}) {
806
+ return expandSpec(config, instanceSpec(path, props), options);
807
+ }
808
+ //#endregion
809
+ export { boundElementType, componentSpec, deriveSpec, entryKeyOf, expandComponent, expandSpec, instanceSpec, previewSpec, resolveVisibility, slotAnatomyPropOf, slotTargetsOf, specWithResolvedVisibility, visibilityStateProps, visibilityTerms, withoutTruthyTerm };