@yahoo/uds-create-config 2.45.0 → 3.0.1

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
@@ -1,3 +1,6 @@
1
+ import { kindOf, pathOf } from "../framework/utils/refs.js";
2
+ import { childrenPolicy } from "../entities/system/element.js";
3
+ import { resolveComponentProps } from "../framework/projections.js";
1
4
  //#region src/spec/collapse-text-labels.ts
2
5
  /** Child element keys an element references through its `children` array. */
3
6
  function childKeysOf(element) {
@@ -7,20 +10,14 @@ function childKeysOf(element) {
7
10
  /**
8
11
  * Count every parent→child edge in the spec so a wrapped Text node is only
9
12
  * deleted when nothing *else* still points at it. Covers `children` arrays and
10
- * top-level `$slot` prop refs (the two ways the renderer reaches an element).
13
+ * `slots` entries (the two ways the renderer reaches an element).
11
14
  */
12
15
  function countReferences(elements) {
13
16
  const counts = /* @__PURE__ */ new Map();
14
17
  const bump = (key) => counts.set(key, (counts.get(key) ?? 0) + 1);
15
18
  for (const element of Object.values(elements)) {
16
19
  for (const child of childKeysOf(element)) bump(child);
17
- if (!element.props) continue;
18
- for (const value of Object.values(element.props)) {
19
- if (typeof value !== "object" || value === null || !("$slot" in value)) continue;
20
- const slot = value.$slot;
21
- const refs = Array.isArray(slot) ? slot : [slot];
22
- for (const ref of refs) if (typeof ref === "string") bump(ref);
23
- }
20
+ for (const fills of Object.values(element.slots ?? {})) for (const ref of fills) bump(ref);
24
21
  }
25
22
  return counts;
26
23
  }
@@ -41,21 +38,32 @@ function bareLabelText(element) {
41
38
  return text;
42
39
  }
43
40
  /**
41
+ * The component a spec `type` names, or `undefined` when it names something else.
42
+ *
43
+ * A spec type is `<kind>:<path>` (`component:Badge`), and only a component has children this can
44
+ * reason about — a `package:` member is somebody else's export, whose children are its own business,
45
+ * and an intrinsic tag (`'div'`) carries no kind at all and isn't in the config. Asking `resolve`
46
+ * with an unstripped marker finds nothing; asking it with the path of a NON-component would find a
47
+ * component that merely shares the name.
48
+ */
49
+ function componentPath(type) {
50
+ const kind = kindOf(type);
51
+ if (kind !== type && kind !== "component") return void 0;
52
+ return pathOf(type);
53
+ }
54
+ /**
44
55
  * Hoisting is only lossless when the wrapped child renders *nothing but* its
45
- * text — a Text-like leaf whose `children` binding renders directly (a scalar
56
+ * text — a Text-like leaf whose `children` forward renders directly (a scalar
46
57
  * marker or an open/root slot). A component that forwards `children` into a
47
- * named layer (Badge's `slot('text/children')`) has chrome around the label,
58
+ * named layer (Badge's `{ type: 'forward', target: 'text/children' }`) has chrome around the label,
48
59
  * so collapsing it would silently delete that chrome even when the element
49
60
  * carries no other props. An unresolvable child type stays collapsible — the
50
61
  * structural bare-leaf gate is all we can check, and generators emit known
51
62
  * types anyway.
52
63
  */
53
64
  function childCollapsible(child, config) {
54
- const component = config.getComponent(child.type);
55
- if (!component) return true;
56
- const children = component.derived.prop?.("children");
57
- if (!children) return true;
58
- return children.kind !== "slot" || children.layer === void 0;
65
+ const path = componentPath(child.type);
66
+ return (path ? resolveComponentProps(config, path).children : void 0)?.type !== "forward";
59
67
  }
60
68
  /**
61
69
  * Return a copy of `spec` with every redundant Text-wrapped label folded into a
@@ -69,10 +77,9 @@ function collapseWrappedTextLabels(spec, config) {
69
77
  const rewrites = /* @__PURE__ */ new Map();
70
78
  const toDelete = /* @__PURE__ */ new Set();
71
79
  for (const [key, element] of Object.entries(spec.elements)) {
72
- const component = config.getComponent(element.type);
73
- if (!component) continue;
74
- const { acceptsChildren, acceptsChildNodes } = component.derived;
75
- if (!acceptsChildren || acceptsChildNodes) continue;
80
+ const path = componentPath(element.type);
81
+ if (!path) continue;
82
+ if (childrenPolicy(config, path) !== "text") continue;
76
83
  const childKeys = childKeysOf(element);
77
84
  if (childKeys.length !== 1) continue;
78
85
  const existingLabel = element.props?.children;
@@ -1,21 +1,41 @@
1
- import { Component } from "../Component.js";
1
+ import { Config } from "../framework/Config.js";
2
+ import { SlotTarget } from "../framework/render-spec.js";
2
3
  import { Spec } from "@json-render/core";
3
4
 
4
5
  //#region src/spec/empty-node-slots.d.ts
6
+ /**
7
+ * The component's named node slots — `slotTargetsOf` minus text slots and
8
+ * minus `children`. `children` is the open content hole every container has
9
+ * (a structural insert, not a named fill), and a text slot is an inline-edit
10
+ * surface, not a place a node goes.
11
+ *
12
+ * Text-ness is checked on BOTH ends of the route: the component's own decl
13
+ * (`title: { type: 'slot', text: true }`) and the prop the route lands on — a
14
+ * `forward` into `Text#children` is typed in place, not filled with a dropped
15
+ * node, and only the far end says so. A route whose host component doesn't
16
+ * declare the landing prop is dropped too: the fill op would refuse it, so it
17
+ * must never be offered as a target.
18
+ */
19
+ declare function namedSlotTargets(config: Config, componentPath: string): SlotTarget[];
5
20
  /**
6
21
  * Materialize every EMPTY layer-bound node slot of `spec`'s root as a `Slot`
7
- * element wired through a `$slot` ref, so an unfilled slot is a stable element
8
- * in the spec rather than an absent prop — the studio canvas needs a drop
9
- * target, the layers panel a row, and the inspector an "Empty" state. Slots the
10
- * spec already fills are left as-is. Returns `spec` unchanged when there's
11
- * nothing to inject (no node slots, or all of them filled).
22
+ * element named in the root's `slots` record, so an unfilled slot is a stable
23
+ * element in the spec rather than an absent entry — the studio canvas needs a
24
+ * drop target, the layers panel a row, and the inspector an "Empty" state.
25
+ * Slots the spec already fills are left as-is. Returns `spec` unchanged when
26
+ * there's nothing to inject (no node slots, or all of them filled).
27
+ *
28
+ * `slotNames` is the component's named node slots — {@link namedSlotTargets}'
29
+ * `from` names. Callers pass names rather than a props record because which
30
+ * props are node slots is route-dependent (a `forward` into a text prop is
31
+ * not one), and only the config can answer that.
12
32
  */
13
- declare function withEmptyNodeSlots(spec: Spec, component: Pick<Component, 'derived'>): Spec;
33
+ declare function withEmptyNodeSlots(spec: Spec, slotNames: readonly string[]): Spec;
14
34
  /**
15
35
  * Predicate over a spec element's `type`: does it name a component that forwards
16
36
  * renderable **node** children (a valid drop-*into* target)? This is the single
17
37
  * source of truth for "is a container" — studio builds it from the live Config
18
- * (`buildAcceptsChildren` → `Component.derived.acceptsChildNodes`), which is
38
+ * (`buildClassifyChildNodes` → `childrenPolicy`), which is
19
39
  * namespace-aware, so both bare (`Box`) and namespaced (`uds:Box`) spec types
20
40
  * resolve, along with any custom child-accepting component.
21
41
  */
@@ -27,26 +47,25 @@ type AcceptsChildNodes = (type: string | undefined) => boolean;
27
47
  */
28
48
  type ChildNodesClassification = true | false | undefined;
29
49
  type ClassifyChildNodes = (type: string | undefined) => ChildNodesClassification;
30
- /** The slice of a `Config` the predicate needs — structural so this stays
31
- * decoupled from the `Config` class (and free of an import cycle). */
32
- interface ComponentResolver {
33
- getComponent(type: string): {
34
- derived: {
35
- acceptsChildNodes: boolean;
36
- };
37
- } | undefined;
38
- }
39
50
  /**
40
51
  * Build the single, namespace-aware {@link AcceptsChildNodes} predicate from a
41
52
  * live config: an element type is a node container iff its resolved component's
42
- * `derived.acceptsChildNodes` is true. `getComponent` resolves both bare (`Box`)
43
- * and namespaced (`uds:Box`) types, so the predicate matches whichever form the
44
- * spec carries. Returns a constant `false` when there's no config (nothing can
53
+ * it takes child NODES. `Component.get` resolves a path or the ref a spec carries, so the predicate
54
+ * matches whichever form is in hand. Returns a constant `false` when there's no config (nothing can
45
55
  * be classified yet) — callers thread this into slot injection and drop
46
56
  * hit-testing so every surface agrees on what accepts children.
47
57
  */
48
- declare function buildAcceptsChildNodes(config: ComponentResolver | null | undefined): AcceptsChildNodes;
49
- declare function buildClassifyChildNodes(config: ComponentResolver | null | undefined): ClassifyChildNodes;
58
+ declare function buildAcceptsChildNodes(config: Config | null | undefined): AcceptsChildNodes;
59
+ /**
60
+ * Whether an element type takes child NODES — `true`, `false`, or `undefined` when nothing can say.
61
+ *
62
+ * `childrenPolicy` is the answer, and it is the same answer the spec validator, the emitted module and
63
+ * the anatomy schema use: a void element takes nothing, a text slot takes a string, and everything
64
+ * else takes nodes. v1 asked a flag stamped on each component at registration (`acceptsChildNodes`),
65
+ * which is the same fact computed once and stored — so it could be stale, and only registration could
66
+ * write it.
67
+ */
68
+ declare function buildClassifyChildNodes(config: Config | null | undefined): ClassifyChildNodes;
50
69
  /**
51
70
  * Pin a persistent trailing `Slot` as the last child of every container element
52
71
  * in `spec` (tree-wide), so a container always exposes an insertion drop target
@@ -64,8 +83,8 @@ declare function buildClassifyChildNodes(config: ComponentResolver | null | unde
64
83
  declare function withContainerChildSlots(spec: Spec, acceptsChildNodes: AcceptsChildNodes): Spec;
65
84
  /**
66
85
  * Compose both slot injections into the canvas's render view: layer-bound node
67
- * slots on a component instance's root (`withEmptyNodeSlots`, needs the
68
- * component definition) plus a trailing insertion `Slot` in every container,
86
+ * slots on a component instance's root (`withEmptyNodeSlots`, keyed by the
87
+ * component's `namedSlotTargets`) plus a trailing insertion `Slot` in every container,
69
88
  * tree-wide (`withContainerChildSlots`). This is the spec the studio canvas
70
89
  * renders so empty slots show as drop targets — it is NEVER persisted. Stored
71
90
  * specs stay slot-free; `stripInjectedSlots` is the inverse, applied at every
@@ -73,20 +92,23 @@ declare function withContainerChildSlots(spec: Spec, acceptsChildNodes: AcceptsC
73
92
  * same reference when there's nothing to add, so this is cheap and idempotent —
74
93
  * re-running on an already-slotted spec adds nothing.
75
94
  */
76
- declare function withRenderSlots(spec: Spec, component: Pick<Component, 'derived'> | null | undefined, acceptsChildNodes: AcceptsChildNodes): Spec;
95
+ declare function withRenderSlots(spec: Spec, slotNames: readonly string[] | null | undefined, acceptsChildNodes: AcceptsChildNodes): Spec;
77
96
  /**
78
97
  * Inverse of `withEmptyNodeSlots` + `withContainerChildSlots`: drop every
79
98
  * injected `Slot` element and scrub its references, so a spec carries no
80
- * editing scaffolding. A `Slot`-typed element is ALWAYS an injected content
81
- * hole (json-render's placeholder), never authored content — both injectors
82
- * emit `type: 'Slot'` — so removing all of them and their references is the
83
- * exact reversal: a trailing `children` Slot drops out of its parent's
99
+ * editing scaffolding. An injected `Slot` is render-only — both injectors
100
+ * emit `type: 'Slot'` with no `shown` — so removing them and their references
101
+ * is the exact reversal: a trailing `children` Slot drops out of its parent's
84
102
  * `children`, and an empty node slot drops both its `Slot` element and the
85
- * `{ $slot }` prop that pointed at it (a FILLED slot points at a real element,
86
- * which is not `Slot`-typed, so it survives). Use at export/serialization
87
- * boundaries (e.g. clipboard); the canvas re-injects fresh drop targets on
88
- * load. Idempotent: returns `spec` unchanged when there are no `Slot` elements.
103
+ * `slots` entry that named it (a FILLED slot names a real element,
104
+ * which is not `Slot`-typed, so it survives). A `shown: true` Slot is NOT
105
+ * scaffolding: it is the user-enabled Placeholder `setNodeSlot` deliberately
106
+ * persists, so it survives the strip — without the exemption, a slot fill
107
+ * (which strips the whole spec before persisting) would silently delete a
108
+ * sibling slot's placeholder. Use at export/serialization boundaries (e.g.
109
+ * clipboard); the canvas re-injects fresh drop targets on load. Idempotent:
110
+ * returns `spec` unchanged when there are no strippable `Slot` elements.
89
111
  */
90
112
  declare function stripInjectedSlots(spec: Spec): Spec;
91
113
  //#endregion
92
- export { AcceptsChildNodes, ChildNodesClassification, ClassifyChildNodes, buildAcceptsChildNodes, buildClassifyChildNodes, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
114
+ export { AcceptsChildNodes, ChildNodesClassification, ClassifyChildNodes, buildAcceptsChildNodes, buildClassifyChildNodes, namedSlotTargets, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
@@ -1,40 +1,71 @@
1
+ import { pathOf } from "../framework/utils/refs.js";
2
+ import { childrenPolicy } from "../entities/system/element.js";
3
+ import { resolveComponentProps } from "../framework/projections.js";
4
+ import { slotTargetsOf } from "../framework/render-spec.js";
5
+ import { Component } from "../entities/system/Component.js";
1
6
  //#region src/spec/empty-node-slots.ts
2
7
  const SLOT_TYPE = "Slot";
3
8
  /**
4
- * Layer-bound single-node slots — Button `startIcon`/`endIcon`, Item `media`:
5
- * a `slot()` bound to a named layer whose value is a renderable node. Open
6
- * `children` slots (no layer) are authored as child layers, and text/scalar
7
- * slots as inputs, so neither is materialized here.
9
+ * The component's named node slots — `slotTargetsOf` minus text slots and
10
+ * minus `children`. `children` is the open content hole every container has
11
+ * (a structural insert, not a named fill), and a text slot is an inline-edit
12
+ * surface, not a place a node goes.
13
+ *
14
+ * Text-ness is checked on BOTH ends of the route: the component's own decl
15
+ * (`title: { type: 'slot', text: true }`) and the prop the route lands on — a
16
+ * `forward` into `Text#children` is typed in place, not filled with a dropped
17
+ * node, and only the far end says so. A route whose host component doesn't
18
+ * declare the landing prop is dropped too: the fill op would refuse it, so it
19
+ * must never be offered as a target.
8
20
  */
9
- function nodeSlotNames(component) {
10
- return component.derived.props.filter((p) => p.kind === "slot" && p.layer !== void 0 && p.valueType === "ReactNode" && p.authoredType !== "string").map((p) => p.name);
21
+ function namedSlotTargets(config, componentPath) {
22
+ const component = Component.get(config, componentPath);
23
+ const props = component?.props;
24
+ const layers = component?.layers;
25
+ return slotTargetsOf(config, componentPath).filter((target) => {
26
+ if (target.from === "children") return false;
27
+ const declared = props?.[target.from];
28
+ if (declared?.type === "slot" && declared.text === true) return false;
29
+ const hostRef = layers?.[target.layer];
30
+ if (!hostRef || !Component.get(config, hostRef)) return true;
31
+ const into = resolveComponentProps(config.configFor(hostRef) ?? config, pathOf(hostRef))[target.into];
32
+ if (!into) return false;
33
+ return !(into.type === "slot" && into.text === true);
34
+ });
11
35
  }
12
36
  /**
13
37
  * Materialize every EMPTY layer-bound node slot of `spec`'s root as a `Slot`
14
- * element wired through a `$slot` ref, so an unfilled slot is a stable element
15
- * in the spec rather than an absent prop — the studio canvas needs a drop
16
- * target, the layers panel a row, and the inspector an "Empty" state. Slots the
17
- * spec already fills are left as-is. Returns `spec` unchanged when there's
18
- * nothing to inject (no node slots, or all of them filled).
38
+ * element named in the root's `slots` record, so an unfilled slot is a stable
39
+ * element in the spec rather than an absent entry — the studio canvas needs a
40
+ * drop target, the layers panel a row, and the inspector an "Empty" state.
41
+ * Slots the spec already fills are left as-is. Returns `spec` unchanged when
42
+ * there's nothing to inject (no node slots, or all of them filled).
43
+ *
44
+ * `slotNames` is the component's named node slots — {@link namedSlotTargets}'
45
+ * `from` names. Callers pass names rather than a props record because which
46
+ * props are node slots is route-dependent (a `forward` into a text prop is
47
+ * not one), and only the config can answer that.
19
48
  */
20
- function withEmptyNodeSlots(spec, component) {
21
- const names = nodeSlotNames(component);
49
+ function withEmptyNodeSlots(spec, slotNames) {
50
+ const names = slotNames;
22
51
  if (names.length === 0) return spec;
23
52
  const rootKey = spec.root;
24
53
  const next = structuredClone(spec);
25
54
  const elements = next.elements;
26
55
  const root = elements[rootKey];
27
56
  if (!root) return spec;
28
- root.props = root.props ?? {};
29
57
  let injected = false;
30
58
  for (const name of names) {
31
- if (root.props[name] !== void 0) continue;
59
+ if (root.slots?.[name] !== void 0) continue;
32
60
  const key = `${rootKey}__${name}__slot`;
33
61
  elements[key] = {
34
62
  type: SLOT_TYPE,
35
63
  props: { name }
36
64
  };
37
- root.props[name] = { $slot: key };
65
+ root.slots = {
66
+ ...root.slots,
67
+ [name]: [key]
68
+ };
38
69
  injected = true;
39
70
  }
40
71
  return injected ? next : spec;
@@ -42,9 +73,8 @@ function withEmptyNodeSlots(spec, component) {
42
73
  /**
43
74
  * Build the single, namespace-aware {@link AcceptsChildNodes} predicate from a
44
75
  * live config: an element type is a node container iff its resolved component's
45
- * `derived.acceptsChildNodes` is true. `getComponent` resolves both bare (`Box`)
46
- * and namespaced (`uds:Box`) types, so the predicate matches whichever form the
47
- * spec carries. Returns a constant `false` when there's no config (nothing can
76
+ * it takes child NODES. `Component.get` resolves a path or the ref a spec carries, so the predicate
77
+ * matches whichever form is in hand. Returns a constant `false` when there's no config (nothing can
48
78
  * be classified yet) — callers thread this into slot injection and drop
49
79
  * hit-testing so every surface agrees on what accepts children.
50
80
  */
@@ -52,9 +82,23 @@ function buildAcceptsChildNodes(config) {
52
82
  const classify = buildClassifyChildNodes(config);
53
83
  return (type) => classify(type) === true;
54
84
  }
85
+ /**
86
+ * Whether an element type takes child NODES — `true`, `false`, or `undefined` when nothing can say.
87
+ *
88
+ * `childrenPolicy` is the answer, and it is the same answer the spec validator, the emitted module and
89
+ * the anatomy schema use: a void element takes nothing, a text slot takes a string, and everything
90
+ * else takes nodes. v1 asked a flag stamped on each component at registration (`acceptsChildNodes`),
91
+ * which is the same fact computed once and stored — so it could be stale, and only registration could
92
+ * write it.
93
+ */
55
94
  function buildClassifyChildNodes(config) {
56
95
  if (!config) return () => void 0;
57
- return (type) => type === void 0 ? void 0 : config.getComponent(type)?.derived.acceptsChildNodes;
96
+ return (type) => {
97
+ if (type === void 0) return void 0;
98
+ const component = Component.get(config, type);
99
+ if (!component) return void 0;
100
+ return childrenPolicy(config, component.path) === "nodes";
101
+ };
58
102
  }
59
103
  /**
60
104
  * Pin a persistent trailing `Slot` as the last child of every container element
@@ -98,8 +142,8 @@ function withContainerChildSlots(spec, acceptsChildNodes) {
98
142
  }
99
143
  /**
100
144
  * Compose both slot injections into the canvas's render view: layer-bound node
101
- * slots on a component instance's root (`withEmptyNodeSlots`, needs the
102
- * component definition) plus a trailing insertion `Slot` in every container,
145
+ * slots on a component instance's root (`withEmptyNodeSlots`, keyed by the
146
+ * component's `namedSlotTargets`) plus a trailing insertion `Slot` in every container,
103
147
  * tree-wide (`withContainerChildSlots`). This is the spec the studio canvas
104
148
  * renders so empty slots show as drop targets — it is NEVER persisted. Stored
105
149
  * specs stay slot-free; `stripInjectedSlots` is the inverse, applied at every
@@ -107,32 +151,29 @@ function withContainerChildSlots(spec, acceptsChildNodes) {
107
151
  * same reference when there's nothing to add, so this is cheap and idempotent —
108
152
  * re-running on an already-slotted spec adds nothing.
109
153
  */
110
- function withRenderSlots(spec, component, acceptsChildNodes) {
111
- return withContainerChildSlots(component ? withEmptyNodeSlots(spec, component) : spec, acceptsChildNodes);
112
- }
113
- function slotRefKeys(value) {
114
- if (typeof value !== "object" || value === null || !("$slot" in value)) return;
115
- const ref = value.$slot;
116
- if (typeof ref === "string") return [ref];
117
- return Array.isArray(ref) ? ref : void 0;
154
+ function withRenderSlots(spec, slotNames, acceptsChildNodes) {
155
+ return withContainerChildSlots(slotNames ? withEmptyNodeSlots(spec, slotNames) : spec, acceptsChildNodes);
118
156
  }
119
157
  /**
120
158
  * Inverse of `withEmptyNodeSlots` + `withContainerChildSlots`: drop every
121
159
  * injected `Slot` element and scrub its references, so a spec carries no
122
- * editing scaffolding. A `Slot`-typed element is ALWAYS an injected content
123
- * hole (json-render's placeholder), never authored content — both injectors
124
- * emit `type: 'Slot'` — so removing all of them and their references is the
125
- * exact reversal: a trailing `children` Slot drops out of its parent's
160
+ * editing scaffolding. An injected `Slot` is render-only — both injectors
161
+ * emit `type: 'Slot'` with no `shown` — so removing them and their references
162
+ * is the exact reversal: a trailing `children` Slot drops out of its parent's
126
163
  * `children`, and an empty node slot drops both its `Slot` element and the
127
- * `{ $slot }` prop that pointed at it (a FILLED slot points at a real element,
128
- * which is not `Slot`-typed, so it survives). Use at export/serialization
129
- * boundaries (e.g. clipboard); the canvas re-injects fresh drop targets on
130
- * load. Idempotent: returns `spec` unchanged when there are no `Slot` elements.
164
+ * `slots` entry that named it (a FILLED slot names a real element,
165
+ * which is not `Slot`-typed, so it survives). A `shown: true` Slot is NOT
166
+ * scaffolding: it is the user-enabled Placeholder `setNodeSlot` deliberately
167
+ * persists, so it survives the strip — without the exemption, a slot fill
168
+ * (which strips the whole spec before persisting) would silently delete a
169
+ * sibling slot's placeholder. Use at export/serialization boundaries (e.g.
170
+ * clipboard); the canvas re-injects fresh drop targets on load. Idempotent:
171
+ * returns `spec` unchanged when there are no strippable `Slot` elements.
131
172
  */
132
173
  function stripInjectedSlots(spec) {
133
174
  const elements = spec.elements;
134
175
  if (!elements || typeof elements !== "object") return spec;
135
- const slotKeys = new Set(Object.keys(elements).filter((k) => elements[k]?.type === SLOT_TYPE));
176
+ const slotKeys = new Set(Object.keys(elements).filter((k) => elements[k]?.type === SLOT_TYPE && elements[k]?.props?.shown !== true));
136
177
  if (slotKeys.size === 0) return spec;
137
178
  const next = structuredClone(spec);
138
179
  const nextEls = next.elements;
@@ -140,16 +181,15 @@ function stripInjectedSlots(spec) {
140
181
  for (const el of Object.values(nextEls)) {
141
182
  if (!el) continue;
142
183
  if (Array.isArray(el.children)) el.children = el.children.filter((c) => !slotKeys.has(c));
143
- if (!el.props) continue;
144
- for (const [propName, value] of Object.entries(el.props)) {
145
- const refs = slotRefKeys(value);
146
- if (!refs) continue;
147
- const remaining = refs.filter((r) => !slotKeys.has(r));
148
- if (remaining.length === 0) delete el.props[propName];
149
- else if (remaining.length !== refs.length) el.props[propName] = { $slot: remaining };
184
+ if (!el.slots) continue;
185
+ for (const [name, fills] of Object.entries(el.slots)) {
186
+ const remaining = fills.filter((r) => !slotKeys.has(r));
187
+ if (remaining.length === 0) delete el.slots[name];
188
+ else if (remaining.length !== fills.length) el.slots[name] = remaining;
150
189
  }
190
+ if (Object.keys(el.slots).length === 0) delete el.slots;
151
191
  }
152
192
  return next;
153
193
  }
154
194
  //#endregion
155
- export { buildAcceptsChildNodes, buildClassifyChildNodes, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
195
+ export { buildAcceptsChildNodes, buildClassifyChildNodes, namedSlotTargets, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
@@ -1,18 +1,29 @@
1
+ import { AcceptsChildNodes, ChildNodesClassification, ClassifyChildNodes, buildAcceptsChildNodes, buildClassifyChildNodes, namedSlotTargets, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots } from "./empty-node-slots.js";
2
+ import { DocumentRename, RewritableSpec, SpecRewrite, rewriteSpecRefs } from "./rewrite-refs.js";
1
3
  import { applyForcedModifiers, collectForcedModifierProps } from "./apply-forced-modifiers.js";
2
- import { AssetComponentMap, AssetJsxForm, AssetNodeResolver, assetJsxForm, parseAssetType } from "./asset-jsx.js";
4
+ import { AssetComponentMap, AssetJsxForm, AssetNodeResolver, assetJsxForm, jsxIdentifier, parseAssetType } from "./asset-jsx.js";
3
5
  import { CollapseTextLabelsResult, CollapsedTextLabel, collapseWrappedTextLabels } from "./collapse-text-labels.js";
4
- import { AcceptsChildNodes, ChildNodesClassification, ClassifyChildNodes, buildAcceptsChildNodes, buildClassifyChildNodes, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots } from "./empty-node-slots.js";
5
6
  import { JsxToSpecOptions, UNRESOLVED, hasUnresolvedProps, jsxToSpec, stripUnresolvedProps } from "./jsxToSpec.js";
6
- import { ResolvableComponent, resolveAuthoredLayerProps, resolveRenderedLayerProps } from "./layer-props.js";
7
- import { PreviewControl, PreviewControlKind, derivePreviewControls, propOptions } from "./preview-controls.js";
8
- import { collectSlotRefs, isSlotRef } from "./slot-refs.js";
7
+ import { GraftableElement, GraftableSpec, PreviewElement, PreviewSpecNode, PreviewValue, graftPreviewElements, hasPreviewElementDeep, isPreviewElement, previewElementNodes, previewElementType } from "./preview-elements.js";
9
8
  import { SpecToJsxOptions, SpecToJsxResult, specToJsx } from "./specToJsx.js";
10
9
 
11
10
  //#region src/spec/index.d.ts
12
- /** Internal render-spec provenance stamped on the Text node that preview
13
- * extraction creates for a scalar slot. The value is the originating slot
14
- * name. It lets Studio distinguish that generated proxy from a real authored
15
- * marker-less Text element without changing the rendered layer hierarchy. */
11
+ /**
12
+ * Spec-format helpers — everything that reads or rewrites a json-render Spec in the UDS dialect
13
+ * (slot fills, forced modifier states, JSX ⇄ spec conversion).
14
+ *
15
+ * Nearly all of these are about the SPEC alone: a spec is a document, and asking what its elements
16
+ * are, which of them a slot pulls in, or what its JSX form looks like needs no design system to
17
+ * answer. What a component's layers are STYLED with is the config's question and lives with the
18
+ * config ({@link layerStyles}, {@link componentRuleClasses}).
19
+ *
20
+ * The exception is {@link collapseWrappedTextLabels}, which takes a `Config` — it decides whether a
21
+ * Text wrapper is redundant, and that depends on what the wrapping component takes as children. It
22
+ * belongs here anyway because the RESULT is a rewritten spec; it just can't answer without asking.
23
+ */
24
+ /** Stamped on the Text node that preview extraction creates for a scalar slot; the value is the slot
25
+ * it came from. It's what tells that generated proxy apart from an authored marker-less Text
26
+ * element, without changing the rendered layer hierarchy. */
16
27
  declare const SYNTHETIC_TEXT_SLOT_PROP = "data-uds-synthetic-text-slot";
17
28
  //#endregion
18
- export { type AcceptsChildNodes, type AssetComponentMap, type AssetJsxForm, type AssetNodeResolver, type ChildNodesClassification, type ClassifyChildNodes, type CollapseTextLabelsResult, type CollapsedTextLabel, type JsxToSpecOptions, type PreviewControl, type PreviewControlKind, type ResolvableComponent, SYNTHETIC_TEXT_SLOT_PROP, type SpecToJsxOptions, type SpecToJsxResult, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, collectSlotRefs, derivePreviewControls, hasUnresolvedProps, isSlotRef, jsxToSpec, parseAssetType, propOptions, resolveAuthoredLayerProps, resolveRenderedLayerProps, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
29
+ export { type AcceptsChildNodes, type AssetComponentMap, type AssetJsxForm, type AssetNodeResolver, type ChildNodesClassification, type ClassifyChildNodes, type CollapseTextLabelsResult, type CollapsedTextLabel, type DocumentRename, type GraftableElement, type GraftableSpec, type JsxToSpecOptions, type PreviewElement, type PreviewSpecNode, type PreviewValue, type RewritableSpec, SYNTHETIC_TEXT_SLOT_PROP, type SpecRewrite, type SpecToJsxOptions, type SpecToJsxResult, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, graftPreviewElements, hasPreviewElementDeep, hasUnresolvedProps, isPreviewElement, jsxIdentifier, jsxToSpec, namedSlotTargets, parseAssetType, previewElementNodes, previewElementType, rewriteSpecRefs, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
@@ -1,17 +1,28 @@
1
- import { collectSlotRefs, isSlotRef } from "./slot-refs.js";
1
+ import { graftPreviewElements, hasPreviewElementDeep, isPreviewElement, previewElementNodes, previewElementType } from "./preview-elements.js";
2
+ import { assetJsxForm, jsxIdentifier, parseAssetType } from "./asset-jsx.js";
3
+ import { buildAcceptsChildNodes, buildClassifyChildNodes, namedSlotTargets, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots } from "./empty-node-slots.js";
2
4
  import { applyForcedModifiers, collectForcedModifierProps } from "./apply-forced-modifiers.js";
3
- import { assetJsxForm, parseAssetType } from "./asset-jsx.js";
4
5
  import { collapseWrappedTextLabels } from "./collapse-text-labels.js";
5
- import { buildAcceptsChildNodes, buildClassifyChildNodes, stripInjectedSlots, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots } from "./empty-node-slots.js";
6
6
  import { UNRESOLVED, hasUnresolvedProps, jsxToSpec, stripUnresolvedProps } from "./jsxToSpec.js";
7
- import { resolveAuthoredLayerProps, resolveRenderedLayerProps } from "./layer-props.js";
8
- import { derivePreviewControls, propOptions } from "./preview-controls.js";
7
+ import { rewriteSpecRefs } from "./rewrite-refs.js";
9
8
  import { specToJsx } from "./specToJsx.js";
10
9
  //#region src/spec/index.ts
11
- /** Internal render-spec provenance stamped on the Text node that preview
12
- * extraction creates for a scalar slot. The value is the originating slot
13
- * name. It lets Studio distinguish that generated proxy from a real authored
14
- * marker-less Text element without changing the rendered layer hierarchy. */
10
+ /**
11
+ * Spec-format helpers — everything that reads or rewrites a json-render Spec in the UDS dialect
12
+ * (slot fills, forced modifier states, JSX ⇄ spec conversion).
13
+ *
14
+ * Nearly all of these are about the SPEC alone: a spec is a document, and asking what its elements
15
+ * are, which of them a slot pulls in, or what its JSX form looks like needs no design system to
16
+ * answer. What a component's layers are STYLED with is the config's question and lives with the
17
+ * config ({@link layerStyles}, {@link componentRuleClasses}).
18
+ *
19
+ * The exception is {@link collapseWrappedTextLabels}, which takes a `Config` — it decides whether a
20
+ * Text wrapper is redundant, and that depends on what the wrapping component takes as children. It
21
+ * belongs here anyway because the RESULT is a rewritten spec; it just can't answer without asking.
22
+ */
23
+ /** Stamped on the Text node that preview extraction creates for a scalar slot; the value is the slot
24
+ * it came from. It's what tells that generated proxy apart from an authored marker-less Text
25
+ * element, without changing the rendered layer hierarchy. */
15
26
  const SYNTHETIC_TEXT_SLOT_PROP = "data-uds-synthetic-text-slot";
16
27
  //#endregion
17
- export { SYNTHETIC_TEXT_SLOT_PROP, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, collectSlotRefs, derivePreviewControls, hasUnresolvedProps, isSlotRef, jsxToSpec, parseAssetType, propOptions, resolveAuthoredLayerProps, resolveRenderedLayerProps, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
28
+ export { SYNTHETIC_TEXT_SLOT_PROP, UNRESOLVED, applyForcedModifiers, assetJsxForm, buildAcceptsChildNodes, buildClassifyChildNodes, collapseWrappedTextLabels, collectForcedModifierProps, graftPreviewElements, hasPreviewElementDeep, hasUnresolvedProps, isPreviewElement, jsxIdentifier, jsxToSpec, namedSlotTargets, parseAssetType, previewElementNodes, previewElementType, rewriteSpecRefs, specToJsx, stripInjectedSlots, stripUnresolvedProps, withContainerChildSlots, withEmptyNodeSlots, withRenderSlots };
@@ -19,17 +19,22 @@ interface JsxToSpecOptions {
19
19
  */
20
20
  moduleSource?: string;
21
21
  /**
22
- * Set of known component names in the registry. When provided, any
23
- * PascalCase JSX element whose tag is NOT in this set (e.g. providers,
24
- * wrappers) is treated as a transparent fragment — its children are
25
- * flattened into the parent.
22
+ * Every identifier a tag may name, mapped to the QUALIFIED TYPE it resolves to
23
+ * — `'Badge' → 'component:Badge'`, `'TrophyIcon' → 'icon:icons/TrophyIcon'`.
24
+ * Build it with Studio's `buildKnownComponentSet`, which walks the same
25
+ * components and icon libraries.
26
+ *
27
+ * It decides two things. A PascalCase tag the map doesn't know (a provider, a
28
+ * wrapper) is treated as a transparent fragment — its children flatten into the
29
+ * parent. A tag it does know emits that qualified type, so a round trip through
30
+ * JSX keeps the kind each element named.
26
31
  */
27
- knownComponents?: Set<string>;
32
+ knownComponents?: ReadonlyMap<string, string>;
28
33
  /**
29
- * Reconstructs placed asset nodes from authoring-component tags —
30
- * `<Icon name="Trophy" …/>` → type `yahoo-os:asset:icons/Trophy`. The
31
- * exact inverse of `specToJsx`'s `assetComponents` mapping; without it an
32
- * `<Icon name=…/>` round-trips as a literal `Icon` component node.
34
+ * Reconstructs placed asset nodes from a rendering-component tag —
35
+ * `<Icon name="Trophy" …/>` → type `icon:icons/Trophy`. The exact inverse of
36
+ * `specToJsx`'s `assetComponents` mapping; without it an `<Icon name=…/>`
37
+ * round-trips as a literal `Icon` component node.
33
38
  */
34
39
  resolveAssetNode?: AssetNodeResolver;
35
40
  }
@@ -6,6 +6,16 @@ import { parse } from "@babel/parser";
6
6
  * and should be stripped — $bindState handles write-back automatically.
7
7
  */
8
8
  const STATE_SETTER = Symbol.for("jsxToSpec.stateSetter");
9
+ /**
10
+ * Wrapper `getAttributeValue` hands back for a JSX-element prop value. The
11
+ * converted element is already in the context's `elements` map; the attribute
12
+ * loop records its key on the owning element's `slots` record instead of
13
+ * storing a prop.
14
+ */
15
+ const SLOT_FILL = Symbol.for("jsxToSpec.slotFill");
16
+ function isSlotFill(value) {
17
+ return typeof value === "object" && value !== null && SLOT_FILL in value;
18
+ }
9
19
  function buildModuleScope(ast) {
10
20
  const scope = {
11
21
  values: /* @__PURE__ */ new Map(),
@@ -270,7 +280,7 @@ function getAttributeValue(valueNode, scope, ctx) {
270
280
  const expr = valueNode.expression;
271
281
  if (ctx && (expr.type === "JSXElement" || expr.type === "JSXFragment")) {
272
282
  const slotKey = convertJsxNode(expr, ctx);
273
- if (slotKey) return { $slot: slotKey };
283
+ if (slotKey) return { [SLOT_FILL]: slotKey };
274
284
  return UNRESOLVED;
275
285
  }
276
286
  return evaluateExpression(expr, scope);
@@ -360,6 +370,7 @@ function convertElement(node, ctx) {
360
370
  if (ctx.knownComponents && tagName[0] === tagName[0].toUpperCase() && !ctx.knownComponents.has(tagName)) return flattenChildrenAsFragment(node.children, ctx);
361
371
  const key = nextKey(ctx);
362
372
  const props = {};
373
+ const slots = {};
363
374
  const onBindings = {};
364
375
  for (const attr of node.openingElement.attributes) if (attr.type === "JSXAttribute") {
365
376
  const jsxAttr = attr;
@@ -369,7 +380,12 @@ function convertElement(node, ctx) {
369
380
  onBindings[binding.event] = binding.action;
370
381
  continue;
371
382
  }
372
- props[propName] = getAttributeValue(jsxAttr.value, ctx.scope, ctx);
383
+ const propValue = getAttributeValue(jsxAttr.value, ctx.scope, ctx);
384
+ if (isSlotFill(propValue)) {
385
+ slots[propName] = [propValue[SLOT_FILL]];
386
+ continue;
387
+ }
388
+ props[propName] = propValue;
373
389
  } else if (attr.type === "JSXSpreadAttribute") props.__spread__ = UNRESOLVED;
374
390
  const childKeys = [];
375
391
  const textContent = collectTextChildren(node.children);
@@ -381,10 +397,11 @@ function convertElement(node, ctx) {
381
397
  const assetType = ctx.resolveAssetNode?.(tagName, props) ?? null;
382
398
  if (assetType) delete props.name;
383
399
  const element = {
384
- type: assetType ?? tagName,
400
+ type: assetType ?? ctx.knownComponents?.get(tagName) ?? tagName,
385
401
  props
386
402
  };
387
403
  if (childKeys.length > 0) element.children = childKeys;
404
+ if (Object.keys(slots).length > 0) element.slots = slots;
388
405
  if (Object.keys(onBindings).length > 0) element.on = onBindings;
389
406
  ctx.elements[key] = element;
390
407
  return key;