@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
package/dist/Component.js DELETED
@@ -1,1061 +0,0 @@
1
- import { compact } from "./entity-utils.js";
2
- import { isPlaceable } from "./asset-kind.js";
3
- import { readSourcePath } from "./captureCallerPath.js";
4
- import { isAssetGroupRef, isCompositeRef, isStylePropRef, isTokenRef, tag } from "./refs.js";
5
- import { isColorExpression } from "./colorExpressions.js";
6
- import { readAssetGroupSlug } from "./defineAssetGroup.js";
7
- import { serializeElementsDeep } from "./element-marker.js";
8
- import { isBoolMarker, isMotionMarker, isNumberMarker, isSlotMarker, isStringMarker, isVariantArrayMarker, isVariantMarker } from "./markers.js";
9
- import { componentClassNames } from "@yahoo/uds-create-utils";
10
- //#region src/Component.ts
11
- /**
12
- * `Component` — a registered component with layers, props, and base
13
- * styles.
14
- *
15
- * Layer instances are purely structural (no derived). Cross-layer
16
- * derivations live on `Component.derived` because they walk
17
- * `compoundProps` + `base` together. `derived.propInfo(name)` returns a
18
- * discriminated union narrowed by `.kind` — that surface replaces
19
- * Studio's bespoke `componentInfo.ts` walker.
20
- *
21
- * `subcomponentOf` / `subcomponents` aren't authored on the component
22
- * itself — they fall out of a parent's
23
- * `defineComponent(...).subcomponents({...})` chain when `Config.
24
- * registerComponents` walks it. They live under `.derived` to keep the
25
- * authored-vs-derived split clean per the config naming convention.
26
- */
27
- /**
28
- * Humanize a PascalCase/camelCase component name into a space-separated
29
- * display label — `"GridItem"` → `"Grid Item"`, `"HStack"` → `"H Stack"`,
30
- * `"TableHeadCell"` → `"Table Head Cell"`. Used as the default
31
- * `metadata.label` when an author didn't supply one, so every consumer
32
- * reads a label off `metadata` uniformly instead of re-deriving a
33
- * fallback from `name` at each call site.
34
- */
35
- function humanizeComponentName(name) {
36
- return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").trim();
37
- }
38
- /**
39
- * Normalize each layer-input authoring form down to the canonical
40
- * marker shape stored on `Layer.tag`:
41
- *
42
- * - bare string → `TagRef`
43
- * - `LayerWithOverrides` (`{ tag, defaultProps?, base?, ... }`) →
44
- * the unwrapped `tag` field (recursing once for the bare-string
45
- * case nested inside).
46
- * - Existing `TagRef` / `ComponentRef` / `ComponentDefinition` value
47
- * is passed through unchanged.
48
- *
49
- * Centralized here so every Layer constructed downstream sees the
50
- * marker shape, regardless of how the consumer authored the layer.
51
- */
52
- function normalizeLayerInput(input) {
53
- if (input === void 0) return void 0;
54
- if (typeof input === "string") return tag(input);
55
- if (typeof input === "object" && input !== null && "tag" in input && typeof input.tag !== "undefined" && !("__kind" in input)) {
56
- const inner = input.tag;
57
- return typeof inner === "string" ? tag(inner) : inner;
58
- }
59
- return input;
60
- }
61
- /**
62
- * Preserve component identity across the JSON wire when a layer was
63
- * authored with a registered `ComponentDefinition` value (e.g.
64
- * `.layers({ root: Box, text: Text })`). Without this, `JSON.stringify`
65
- * inlines the whole definition and drops the non-enumerable
66
- * `__componentName` stamp — consumers reading `Layer.tag` from a
67
- * `Config.fromJSON` round-trip then have no way to tell which
68
- * registered component the layer references. We emit a `ComponentRef`
69
- * marker instead so the identity round-trips.
70
- */
71
- function serializeLayerTag(input) {
72
- if (typeof input === "object" && input !== null && !("__kind" in input) && "__componentName" in input) {
73
- const name = input.__componentName;
74
- if (typeof name === "string") return {
75
- __kind: "component",
76
- ref: name
77
- };
78
- }
79
- return input;
80
- }
81
- var Layer = class {
82
- name;
83
- tag;
84
- base;
85
- constructor(args) {
86
- this.name = args.name;
87
- this.tag = normalizeLayerInput(args.tag);
88
- this.base = args.base;
89
- }
90
- /**
91
- * What this layer renders, normalized across the tag's representations:
92
- * - `{ kind: 'component', ref }` — renders a registered component (`Box`,
93
- * `Text`), so the layer takes that component's prop surface. The identity
94
- * survives both in memory (a non-enumerable `__componentName` stamp on the
95
- * builder) and on the wire (`{ __kind: 'component', ref }` from `fromJSON`).
96
- * - `{ kind: 'tag', ref }` — renders a bare HTML element (`'div'`).
97
- * - `undefined` — an inline anonymous builder with no registered identity.
98
- */
99
- get renders() {
100
- const t = this.tag;
101
- if (t === void 0) return void 0;
102
- if (typeof t === "string") return {
103
- kind: "tag",
104
- ref: t
105
- };
106
- const obj = t;
107
- if (obj.__kind === "component" && typeof obj.ref === "string") return {
108
- kind: "component",
109
- ref: obj.ref
110
- };
111
- if (obj.__kind === "tag" && typeof obj.ref === "string") return {
112
- kind: "tag",
113
- ref: obj.ref
114
- };
115
- if (typeof obj.__componentName === "string") return {
116
- kind: "component",
117
- ref: obj.__componentName
118
- };
119
- }
120
- toJSON() {
121
- return {
122
- name: this.name,
123
- ...compact({
124
- tag: this.tag,
125
- base: this.base
126
- })
127
- };
128
- }
129
- };
130
- var Component = class {
131
- name;
132
- layers;
133
- props;
134
- base;
135
- defaultProps;
136
- compoundProps;
137
- motion;
138
- /** Opt-in forwarded-ref target tag (`.config({ ref: 'button' })`). Drives the
139
- * typed `ref` prop in `@yahoo/uds-create-config` and the codegen forwardRef wrapper. */
140
- ref;
141
- /** Provenance when this component is linked from another system; `undefined`
142
- * for local components. Unrelated to `ref` above — see `SystemLink`. */
143
- link;
144
- /** Applied `.extend(patch)` override on a linked component — payload +
145
- * computed inverse. `undefined` for unextended components. */
146
- extension;
147
- preview;
148
- metadata;
149
- /**
150
- * Absolute path of the file that called `defineComponent('Name', …)`.
151
- * Captured via the stack walk in `captureCallerPath` and stashed
152
- * non-enumerably on the authored definition; lifted onto the class
153
- * here so codegen consumers don't have to thread a separate
154
- * `componentSourceMap`. `undefined` when the component was hydrated
155
- * from JSON (no original define call) or built outside the `define*`
156
- * helpers.
157
- */
158
- sourceFilePath;
159
- /**
160
- * `true` when the authored definition chained `.render(fn)` — the
161
- * non-enumerable `__hasRenderFn` flag set by the builder. Codegen
162
- * needs this to classify single-layer components that ship a custom
163
- * render fn (e.g. Accordion) into the transform path rather than
164
- * the inline primitive emitter, so the two paths don't both emit a
165
- * wrapper FC with the same name.
166
- */
167
- hasRenderFn;
168
- /**
169
- * The actual `.render(fn)` callback when `hasRenderFn` is `true`.
170
- * Lifted from the seed's non-enumerable `__renderFn` so the spec
171
- * extractor can invoke it under the mock-react plugin to capture
172
- * the component's internal structure as a Spec. Not used at
173
- * production render time — the codegen-emitted per-file FC handles
174
- * that path.
175
- */
176
- renderFn;
177
- /** `true` when the authored definition chained `.renderCanvas(fn)` — the
178
- * non-enumerable `__hasRenderCanvasFn` flag. Codegen emits a canvas-only
179
- * overlay artifact for these; spec extraction prefers the canvas fn. */
180
- hasCanvasRenderFn;
181
- /** The `.renderCanvas(fn)` callback when `hasCanvasRenderFn` is `true`.
182
- * In-memory only (functions never serialize). */
183
- canvasRenderFn;
184
- /**
185
- * Name of the component this one value-extends from
186
- * (`defineComponent(Box)` → `'Box'`). Resolved from the non-
187
- * enumerable `__extendsFrom.__componentName` chain stamped by
188
- * `defineComponent`'s value-extend branch and `Config.registerComponents`'
189
- * registration loop. `undefined` for primitives, brace-ref shorthand
190
- * forms, and JSON-hydrated configs (the wire format doesn't carry
191
- * this relationship).
192
- */
193
- extendsFrom;
194
- #componentGroup;
195
- #subcomponentOf;
196
- #subcomponents;
197
- #namespaceGetter;
198
- #prefixGetter;
199
- #componentResolver;
200
- #resolveStylePropValueToken;
201
- #isStyleProp;
202
- /**
203
- * Globally-unique lookup key — the spec `type` string a renderer
204
- * resolves against the registry. When the owning `Config` has a
205
- * namespace set (`Config.configure({ namespace: 'uds' })`), this is
206
- * `<namespace>:<name>` (`uds:Badge`); otherwise it's the bare `name`
207
- * (un-namespaced configs). Read live via a getter so it reflects the
208
- * namespace regardless of whether `configure` ran before or after the
209
- * component was registered — mirrors the lazy `prefixGetter` pattern
210
- * used for token CSS vars.
211
- *
212
- * `name` stays the bare authored/display/export identifier; codegen
213
- * emits a bare-name alias alongside the canonical key so existing
214
- * specs referencing the bare `name` keep resolving.
215
- */
216
- get registryKey() {
217
- const namespace = this.#namespaceGetter?.();
218
- return namespace ? `${namespace}:${this.name}` : this.name;
219
- }
220
- #derived;
221
- constructor(args) {
222
- this.name = args.name;
223
- this.#namespaceGetter = args.namespaceGetter;
224
- this.#prefixGetter = args.prefixGetter;
225
- this.#componentResolver = args.componentResolver;
226
- this.#resolveStylePropValueToken = args.resolveStylePropValueToken;
227
- this.#isStyleProp = args.isStyleProp;
228
- const layers = /* @__PURE__ */ new Map();
229
- const liftedLayerBase = {};
230
- for (const [layerName, tag] of Object.entries(args.definition.layers)) {
231
- layers.set(layerName, new Layer({
232
- name: layerName,
233
- tag
234
- }));
235
- if (typeof tag === "object" && tag !== null && !("__kind" in tag) && "tag" in tag) {
236
- const overrides = tag;
237
- const merged = {
238
- ...overrides.defaultProps,
239
- ...overrides.base
240
- };
241
- if (Object.keys(merged).length > 0) liftedLayerBase[layerName] = merged;
242
- }
243
- }
244
- this.layers = layers;
245
- const definitionProps = args.definition.props ?? {};
246
- this.props = definitionProps.children === null ? {
247
- ...definitionProps,
248
- children: void 0
249
- } : definitionProps;
250
- const authoredBase = args.definition.base;
251
- if (Object.keys(liftedLayerBase).length > 0) {
252
- const merged = { ...liftedLayerBase };
253
- if (authoredBase) for (const [layerName, layerStyles] of Object.entries(authoredBase)) merged[layerName] = {
254
- ...merged[layerName] ?? {},
255
- ...layerStyles
256
- };
257
- this.base = merged;
258
- } else this.base = authoredBase;
259
- this.defaultProps = args.definition.defaultProps;
260
- this.compoundProps = args.definition.compoundProps;
261
- this.motion = args.definition.motion;
262
- this.ref = args.definition.ref;
263
- this.link = args.definition.link;
264
- this.extension = args.definition.extension;
265
- const def = args.definition;
266
- const previewField = typeof def.preview === "function" ? void 0 : def.preview;
267
- this.preview = def.__preview ?? previewField;
268
- const metaField = def.metadata;
269
- this.metadata = {
270
- ...metaField,
271
- label: metaField?.label ?? humanizeComponentName(this.name)
272
- };
273
- this.sourceFilePath = readSourcePath(args.definition);
274
- this.hasRenderFn = args.definition.__hasRenderFn === true || args.definition.hasRenderFn === true;
275
- this.renderFn = args.definition.__renderFn;
276
- this.hasCanvasRenderFn = args.definition.__hasRenderCanvasFn === true || args.definition.hasCanvasRenderFn === true;
277
- this.canvasRenderFn = args.definition.__renderCanvasFn;
278
- const extendsFromSeed = args.definition.__extendsFrom;
279
- const extendsFromName = extendsFromSeed && typeof extendsFromSeed === "object" && typeof extendsFromSeed.__componentName === "string" ? extendsFromSeed.__componentName : void 0;
280
- this.extendsFrom = extendsFromName ?? args.definition.extendsFrom;
281
- this.#componentGroup = args.componentGroup;
282
- this.#subcomponentOf = args.subcomponentOf;
283
- this.#subcomponents = args.subcomponents;
284
- }
285
- get derived() {
286
- if (!this.#derived) {
287
- const propsArray = [];
288
- const propsIndex = /* @__PURE__ */ new Map();
289
- for (const [propName, binding] of Object.entries(this.props)) {
290
- const info = inferPropInfo(propName, binding, this.layers, this.#componentResolver);
291
- if (info === void 0) continue;
292
- propsArray.push(info);
293
- propsIndex.set(propName, info);
294
- }
295
- const styleUsage = collectStyleUsage(this.base, this.props, this.compoundProps, this.#resolveStylePropValueToken, this.#isStyleProp);
296
- const refusesChildren = this.#rootRefusesChildren();
297
- this.#derived = {
298
- layers: Array.from(this.layers.values()),
299
- classNames: componentClassNames(this.#prefixGetter?.() ?? "", this.name),
300
- compoundOverrides: buildCompoundOverrides(this.compoundProps),
301
- ...compact({
302
- componentGroup: this.#componentGroup,
303
- subcomponentOf: this.#subcomponentOf,
304
- subcomponents: this.#subcomponents
305
- }),
306
- props: propsArray,
307
- stylePropNames: propsArray.filter((p) => p.kind === "styleProp").map((p) => p.name),
308
- tokenRefs: styleUsage.tokenRefs,
309
- stylePropTokenUsages: styleUsage.stylePropTokenUsages,
310
- stylePropKeywords: styleUsage.stylePropKeywords,
311
- kind: this.#deriveKind(),
312
- acceptsChildren: !refusesChildren && derivesAcceptsChildren(this.layers, propsArray),
313
- acceptsChildNodes: !refusesChildren && derivesAcceptsChildNodes(this.layers, propsArray),
314
- prop(propName) {
315
- return propsIndex.get(propName);
316
- }
317
- };
318
- }
319
- return this.#derived;
320
- }
321
- /**
322
- * Whether this component's root element can never hold children, making
323
- * `acceptsChildren`/`acceptsChildNodes` false regardless of the structural
324
- * signals those derivations read. Two authored facts qualify (UDS-3068):
325
- *
326
- * - **A void root tag.** A single-primitive-root component whose effective
327
- * tag (own `defaultProps.as`, else the root layer's tag, else the
328
- * value-extends chain's) is a void HTML element (`input`, `img`, …) —
329
- * React throws if such an element receives children, so treating it as a
330
- * container injects drop-target Slots that crash every spec render of it.
331
- * Gated on the single-primitive-root shape: a composed component's render
332
- * decides where children go, so its root tag says nothing about them.
333
- *
334
- * - **An explicitly dropped `children` prop.** The authored
335
- * `children: undefined` (the documented pattern for void/value elements —
336
- * Input, Image, Textarea) is detected two ways: authored configs keep the
337
- * key with an `undefined` value, which IS the drop; hydrated configs
338
- * compact the key away, so there it's absence-against-ancestry (the
339
- * merged props lack `children` while an ancestor declares it — only a
340
- * drop can produce that, since value-extension inherits the parent's
341
- * full prop surface). This catches `textarea`, which isn't HTML-void yet
342
- * still rejects element children in React.
343
- */
344
- #rootRefusesChildren() {
345
- if (hasSinglePrimitiveRoot(this.layers)) {
346
- const tag = resolveRootHtmlTag(this, this.#componentResolver, /* @__PURE__ */ new Set());
347
- if (tag !== void 0 && VOID_HTML_TAGS.has(tag)) return true;
348
- }
349
- return droppedInheritedChildren(this, this.#componentResolver);
350
- }
351
- /** Classify authoring shape: `extends` wins (value-extension is the defining
352
- * trait), then anything with multiple layers or a custom render is
353
- * `multi-layer`, else a bare single-tag `primitive`. */
354
- #deriveKind() {
355
- if (this.extendsFrom) return "extends";
356
- if (this.layers.size > 1 || this.hasRenderFn) return "multi-layer";
357
- return "primitive";
358
- }
359
- toJSON(opts) {
360
- const layers = {};
361
- for (const [layerName, layer] of this.layers) {
362
- if (layer.tag === void 0) continue;
363
- layers[layerName] = serializeLayerTag(layer.tag);
364
- }
365
- let sourceFilePath = this.sourceFilePath;
366
- if (sourceFilePath && opts?.projectRoot) sourceFilePath = sourceFilePath.replace(`${opts.projectRoot}/`, "");
367
- return {
368
- name: this.name,
369
- layers,
370
- ...compact({
371
- props: Object.keys(this.props).length > 0 ? serializeAcceptsInProps(this.props, ancestryDeclaresChildren(this, this.#componentResolver)) : void 0,
372
- base: this.base,
373
- defaultProps: this.defaultProps,
374
- compoundProps: this.compoundProps,
375
- motion: this.motion,
376
- ref: this.ref,
377
- link: this.link,
378
- extension: this.extension,
379
- preview: this.preview ? serializeElementsDeep(this.preview) : void 0,
380
- metadata: this.metadata,
381
- sourceFilePath,
382
- hasRenderFn: this.hasRenderFn || void 0,
383
- hasCanvasRenderFn: this.hasCanvasRenderFn || void 0,
384
- subcomponentOf: this.#subcomponentOf,
385
- subcomponents: this.#subcomponents,
386
- extendsFrom: this.extendsFrom
387
- })
388
- };
389
- }
390
- };
391
- /**
392
- * The token + keyword usage a component carries across its styling — one walk
393
- * of `base`, each prop binding's variant styles, and `compoundProps` overrides,
394
- * recursing modifier sub-objects (`_hover`) and color expressions. Produces
395
- * three views the reverse lookups read for "what breaks if I remove this?":
396
- * - `tokenRefs` — every qualified token name referenced, from structured
397
- * `token('color/brand')` refs (matched at any depth) and shorthand
398
- * style-prop values (`bg: 'tertiary'`, resolved via `resolveStylePropValueToken`,
399
- * which returns `undefined` for keywords / arbitrary literals).
400
- * - `stylePropTokenUsages` — the `(styleProp, token)` pair for each, so a
401
- * consumer can tell *which* prop used a token. A token's style prop is the
402
- * key it sits under: directly (`bg: token(...)` / `bg: 'tertiary'`) or as a
403
- * color-expression value (`bg: darken(token(...))`), whose nested refs are
404
- * all attributed to that key.
405
- * - `stylePropKeywords` — `(styleProp, value)` pairs for the *non-token*
406
- * keyword values a style prop carries (`display=flex`). Disjoint from
407
- * `tokenRefs`; `isStyleProp` gates it so layer keys / marker internals
408
- * don't read as keywords, and bracketed arbitrary literals are excluded.
409
- * Internal `__`-prefixed keys (`__kind`, a slot's `__accepts` child defs) are
410
- * skipped, so a child's usage never bleeds into the parent's sets.
411
- */
412
- function collectStyleUsage(base, props, compoundProps, resolveStylePropValueToken, isStyleProp) {
413
- const refs = /* @__PURE__ */ new Set();
414
- const pairKeys = /* @__PURE__ */ new Set();
415
- const pairs = [];
416
- const keywords = /* @__PURE__ */ new Map();
417
- const seen = /* @__PURE__ */ new WeakSet();
418
- const addPair = (styleProp, token) => {
419
- const key = `${styleProp}\x00${token}`;
420
- if (pairKeys.has(key)) return;
421
- pairKeys.add(key);
422
- pairs.push({
423
- styleProp,
424
- token
425
- });
426
- };
427
- const collectUnder = (node, styleProp) => {
428
- if (node === null || typeof node !== "object") return;
429
- if (isTokenRef(node)) {
430
- refs.add(node.ref);
431
- addPair(styleProp, node.ref);
432
- return;
433
- }
434
- for (const value of Object.values(node)) collectUnder(value, styleProp);
435
- };
436
- const walk = (node) => {
437
- if (node === null || typeof node !== "object") return;
438
- if (isTokenRef(node)) {
439
- refs.add(node.ref);
440
- return;
441
- }
442
- if (seen.has(node)) return;
443
- seen.add(node);
444
- if (Array.isArray(node)) {
445
- for (const item of node) walk(item);
446
- return;
447
- }
448
- for (const [key, value] of Object.entries(node)) {
449
- if (key.startsWith("__")) continue;
450
- if (typeof value === "string") {
451
- const ref = resolveStylePropValueToken?.(key, value);
452
- if (ref) {
453
- refs.add(ref);
454
- addPair(key, ref);
455
- } else if (isStyleProp?.(key) && !value.startsWith("[")) {
456
- const values = keywords.get(key) ?? /* @__PURE__ */ new Set();
457
- values.add(value);
458
- keywords.set(key, values);
459
- }
460
- } else if (isTokenRef(value)) {
461
- refs.add(value.ref);
462
- addPair(key, value.ref);
463
- } else if (isColorExpression(value)) collectUnder(value, key);
464
- else walk(value);
465
- }
466
- };
467
- if (base) walk(base);
468
- for (const binding of Object.values(props)) walk(binding);
469
- for (const entry of compoundProps ?? []) walk(entry.layers);
470
- const stylePropKeywords = [...keywords].flatMap(([styleProp, values]) => [...values].map((value) => ({
471
- styleProp,
472
- value
473
- })));
474
- return {
475
- tokenRefs: [...refs],
476
- stylePropTokenUsages: pairs,
477
- stylePropKeywords
478
- };
479
- }
480
- function inferPropInfo(name, binding, layers, resolve) {
481
- if (binding === void 0 || binding === null) return void 0;
482
- if (typeof binding === "function") return {
483
- kind: "function",
484
- name,
485
- required: false,
486
- isEventHandler: name.startsWith("on") && name.length > 2
487
- };
488
- if (typeof binding !== "object") return void 0;
489
- if (isSlotMarker(binding)) return resolveSlotPropInfo(name, binding, layers, resolve);
490
- if (isVariantMarker(binding)) {
491
- const values = isVariantArrayMarker(binding) ? binding.values : Object.keys(binding.values);
492
- return {
493
- kind: "variant",
494
- name,
495
- required: binding.__required === true,
496
- values
497
- };
498
- }
499
- if (isBoolMarker(binding)) return {
500
- kind: "boolean",
501
- name,
502
- required: binding.__required === true
503
- };
504
- if (isStringMarker(binding)) return {
505
- kind: "string",
506
- name,
507
- required: binding.__required === true,
508
- ...binding.__toggle === true ? { toggle: true } : {}
509
- };
510
- if (isNumberMarker(binding)) return {
511
- kind: "number",
512
- name,
513
- required: binding.__required === true
514
- };
515
- if (isMotionMarker(binding)) return {
516
- kind: "motion",
517
- name,
518
- required: binding.__required === true
519
- };
520
- if (isStylePropRef(binding)) return {
521
- kind: "styleProp",
522
- name,
523
- required: false,
524
- stylePropName: binding.ref
525
- };
526
- const obj = binding;
527
- if (obj.__kind === "composite" && typeof obj.ref === "string") return {
528
- kind: "composite",
529
- name,
530
- required: false,
531
- compositeName: obj.ref,
532
- ...typeof obj.layer === "string" ? { layer: obj.layer } : {}
533
- };
534
- }
535
- /**
536
- * Build a `kind: 'slot'` `PropInfo` from a `SlotMarker | SlotRef`.
537
- * Walks the slot's forward chain (when it targets a composed-component
538
- * layer's slot prop) to resolve:
539
- *
540
- * - `accepts` — outer marker's `__accepts` wins; otherwise inherits
541
- * from the innermost descendant slot that declared `.accepts(...)`.
542
- * - `valueType` — what the JSX value resolves to at the terminal
543
- * binding (the non-slot binding the chain bottoms out at, or
544
- * `'ReactNode'` for open/children slots).
545
- *
546
- * Cycle protection: `seen` keys on `"layer/layerProp"`.
547
- */
548
- function resolveSlotPropInfo(name, binding, layers, resolve) {
549
- const layer = "layer" in binding ? binding.layer : void 0;
550
- const layerProp = "layerProp" in binding && binding.layerProp || "children";
551
- const required = binding.__required === true;
552
- const isEventHandler = layerProp.startsWith("on") && layerProp.length > 2;
553
- const chain = walkSlotForwardChain(binding, layers, resolve);
554
- const baseValueType = isEventHandler ? "function" : chain.valueType;
555
- const authoredType = binding.__valueType ?? (baseValueType === "string" ? "string" : void 0);
556
- return {
557
- kind: "slot",
558
- name,
559
- required,
560
- layerProp,
561
- valueType: baseValueType,
562
- ...layer !== void 0 ? { layer } : {},
563
- ...chain.accepts !== void 0 ? { accepts: chain.accepts } : {},
564
- ...chain.acceptsAssetGroup !== void 0 ? { acceptsAssetGroup: chain.acceptsAssetGroup } : {},
565
- ...authoredType !== void 0 ? { authoredType } : {},
566
- ...baseValueType === "variant" && chain.options !== void 0 ? { valueOptions: chain.options } : {},
567
- ...baseValueType === "composite" && chain.compositeName !== void 0 ? { compositeName: chain.compositeName } : {}
568
- };
569
- }
570
- /**
571
- * Walk a slot's forward chain across composed-component layers.
572
- *
573
- * The chain ends when we hit a non-slot binding (boolean/variant/string/
574
- * styleProp/function/etc.), an HTML-element layer (no `__config`), or an
575
- * open slot with no further layer to follow. A `children`-targeted ref is
576
- * followed into its layer (a Text leaf resolves to `'string'`, a node
577
- * container to `'ReactNode'`) rather than short-circuited — only the
578
- * component's own open `slot()` is treated as a node container outright.
579
- * `accepts` is collected as the first `__accepts` seen anywhere in the
580
- * chain (outermost wins, then any inner ancestor that declared one).
581
- */
582
- function walkSlotForwardChain(start, startLayers, resolve) {
583
- const startAccepts = resolveAccepts(start.__accepts);
584
- let accepts = startAccepts.names;
585
- let acceptsAssetGroup = startAccepts.assetGroup;
586
- let current = start;
587
- let currentLayers = startLayers;
588
- let followed = false;
589
- const seen = /* @__PURE__ */ new Set();
590
- while (true) {
591
- const layer = "layer" in current ? current.layer : void 0;
592
- const layerProp = "layerProp" in current && current.layerProp || "children";
593
- if (!layer) return {
594
- valueType: (followed && current.__valueType === "string" ? "string" : void 0) ?? "ReactNode",
595
- accepts,
596
- acceptsAssetGroup
597
- };
598
- const key = `${layer}/${layerProp}`;
599
- if (seen.has(key)) return {
600
- valueType: "ReactNode",
601
- accepts,
602
- acceptsAssetGroup
603
- };
604
- seen.add(key);
605
- const innerLayers = currentLayers;
606
- if (!innerLayers) return {
607
- valueType: "ReactNode",
608
- accepts,
609
- acceptsAssetGroup
610
- };
611
- const layerTag = innerLayers.get(layer)?.tag;
612
- const surface = resolveLayerSurface(layerTag, resolve);
613
- if (!surface) return {
614
- valueType: layerProp === "children" ? "ReactNode" : "string",
615
- accepts,
616
- acceptsAssetGroup
617
- };
618
- const innerBinding = surface.props?.[layerProp];
619
- if (innerBinding === void 0) return {
620
- valueType: layerProp === "children" ? "ReactNode" : "string",
621
- accepts,
622
- acceptsAssetGroup
623
- };
624
- if (isSlotMarker(innerBinding)) {
625
- if (accepts === void 0 || acceptsAssetGroup === void 0) {
626
- const inner = resolveAccepts(innerBinding.__accepts);
627
- if (accepts === void 0) accepts = inner.names;
628
- if (acceptsAssetGroup === void 0) acceptsAssetGroup = inner.assetGroup;
629
- }
630
- current = innerBinding;
631
- currentLayers = surface.layers;
632
- followed = true;
633
- continue;
634
- }
635
- return {
636
- ...terminalResult(innerBinding),
637
- accepts,
638
- acceptsAssetGroup
639
- };
640
- }
641
- }
642
- /**
643
- * A layer's prop surface + sub-layers, resolved from either an inline
644
- * composed definition or a registered-component ref. `undefined` for HTML-
645
- * element layers (`'div'`) and unresolvable refs — the chain stops there.
646
- */
647
- function resolveLayerSurface(layerTag, resolve) {
648
- const inlineDef = getComposedLayerDefinition(layerTag);
649
- if (inlineDef) return {
650
- props: inlineDef.props,
651
- layers: toLayerMap(inlineDef.layers)
652
- };
653
- const ref = componentRefName(layerTag);
654
- const comp = ref ? resolve?.(ref) : void 0;
655
- if (comp) return {
656
- props: comp.props,
657
- layers: comp.layers
658
- };
659
- }
660
- /** Read a registered-component-ref layer tag's target name, from the wire
661
- * form (`{ __kind: 'component', ref }`) or the in-memory `__componentName`
662
- * stamp. Element/inline layers have neither and return `undefined`. */
663
- function componentRefName(tag) {
664
- if (tag === null || typeof tag !== "object") return void 0;
665
- const obj = tag;
666
- if (obj.__kind === "component" && typeof obj.ref === "string") return obj.ref;
667
- if (typeof obj.__componentName === "string") return obj.__componentName;
668
- }
669
- /** Resolve a terminal (non-slot) binding's value kind plus, for a variant, its
670
- * selectable values, or for a composite ref its registry name, so tools can
671
- * render the matching control (a dropdown / composite picker). */
672
- function terminalResult(binding) {
673
- if (typeof binding === "function") return { valueType: "function" };
674
- if (binding === null || typeof binding !== "object") return { valueType: "string" };
675
- if (isVariantMarker(binding)) return {
676
- valueType: "variant",
677
- options: isVariantArrayMarker(binding) ? binding.values : Object.keys(binding.values)
678
- };
679
- if (isCompositeRef(binding)) return {
680
- valueType: "composite",
681
- compositeName: binding.ref
682
- };
683
- if (isBoolMarker(binding)) return { valueType: "boolean" };
684
- if (isNumberMarker(binding)) return { valueType: "number" };
685
- if (isStringMarker(binding)) return { valueType: "string" };
686
- if (isStylePropRef(binding)) return { valueType: "string" };
687
- return { valueType: "string" };
688
- }
689
- /**
690
- * Resolve a slot's `__accepts` into the two distinct things a slot can
691
- * accept: registered component *names* and a placeable asset-group *slug*.
692
- *
693
- * Component entries are `ComponentDefinition`s in memory (carrying an
694
- * authored `name` or the `__componentName` stamp) and bare name strings on
695
- * the wire; either way `readDefinitionName` reads the name. Asset-group
696
- * entries are the double-duty group definition in memory and a
697
- * `{ __kind: 'assetGroup', ref }` marker on the wire; `isAssetGroupRef`
698
- * catches both and `readAcceptedAssetGroupSlug` reads the slug. The asset
699
- * branch throws for a non-placeable class (a font group), keyed to the
700
- * `isPlaceable` capability rather than to any one class — without it a font
701
- * group would silently contribute nothing and the designer panel would fall
702
- * back to the all-components picker.
703
- *
704
- * `names` is `undefined` (not `[]`) when no component was accepted, so callers
705
- * can distinguish "unconstrained" from "empty list"; `assetGroup` is the first
706
- * accepted group's slug (slots target a single group in practice).
707
- */
708
- function resolveAccepts(accepts) {
709
- if (!accepts) return {};
710
- const names = [];
711
- let assetGroup;
712
- for (const entry of accepts) {
713
- if (isAssetGroupRef(entry)) {
714
- assertAcceptedAssetGroupPlaceable(entry);
715
- const slug = readAcceptedAssetGroupSlug(entry);
716
- if (slug === void 0) throw new Error(UNREGISTERED_ACCEPTED_GROUP_ERROR);
717
- if (assetGroup === void 0) assetGroup = slug;
718
- continue;
719
- }
720
- const name = readDefinitionName(entry);
721
- if (name) names.push(name);
722
- }
723
- return {
724
- names: names.length > 0 ? names : void 0,
725
- assetGroup
726
- };
727
- }
728
- /**
729
- * Read an accepted asset group's slug from either form an `__accepts` entry
730
- * takes: the live double-duty definition (slug on the internal `__slug` slot)
731
- * or the serialized `{ __kind: 'assetGroup', ref }` wire marker.
732
- *
733
- * Crucially this never reads the live definition's `ref` *getter* — that getter
734
- * throws "read before registration" until `registerAssetGroups` stamps `__slug`,
735
- * which would turn a recoverable "group not registered" condition into a cryptic
736
- * crash on the first `derived`/`toJSON` access. The `.ref` fallback is reached
737
- * only for wire markers (no `assetKind` field); an unregistered *live* group
738
- * resolves to `undefined` here, and the caller raises a clear error.
739
- */
740
- function readAcceptedAssetGroupSlug(entry) {
741
- const live = readAssetGroupSlug(entry);
742
- if (live) return live;
743
- if (entry !== null && typeof entry === "object" && !("assetKind" in entry)) {
744
- const ref = entry.ref;
745
- if (typeof ref === "string" && ref.length > 0) return ref;
746
- }
747
- }
748
- /** Shared message for an accepted asset group whose slug can't be resolved —
749
- * it was pointed at by `.accepts(...)` but never registered. */
750
- const UNREGISTERED_ACCEPTED_GROUP_ERROR = "slot .accepts(<asset group>) references a group that has not been registered — call Config.registerAssetGroups(...) for it before the slot is resolved or serialized.";
751
- /**
752
- * Throw for `.accepts(<non-placeable group>)`. Reads the stamped
753
- * `assetKind` off the accepted group (the double-duty definition
754
- * object); a bare `{ __kind, ref }` marker carries no class to
755
- * validate, so it passes through.
756
- */
757
- function assertAcceptedAssetGroupPlaceable(entry, context) {
758
- const group = entry;
759
- const assetKind = group.assetKind;
760
- if (assetKind === void 0) return;
761
- if (isPlaceable({ assetKind })) return;
762
- const slug = readAssetGroupSlug(entry) ?? group.label ?? "unknown";
763
- const where = context ? `component "${context.componentName}" prop "${context.propName}": ` : "";
764
- throw new Error(`${where}slot accepts asset group "${slug}" (class "${assetKind}"), which is not placeable — only placeable asset classes (e.g. icons) can fill a slot.`);
765
- }
766
- /**
767
- * Catches a slot that declares `.accepts(<non-placeable group>)` — e.g.
768
- * a slot wired to accept a font group, which can never fill a slot.
769
- *
770
- * This is the *eager* guard: `Config.registerComponents` and
771
- * `registerComponentGroups` run it once per definition at registration
772
- * time, so the error surfaces right when the component is registered
773
- * rather than later, on the first lazy `derived` read buried deep in a
774
- * render path (where it'd be much harder to trace back to the cause).
775
- *
776
- * There's also a *lazy* check inside `resolveAccepts`. We keep both
777
- * on purpose: this eager walk only sees the top-level definition, so the
778
- * lazy check is the backstop for bindings it can't reach. (Inner slots
779
- * of a composed layer aren't a gap — they get validated through their
780
- * own component's registration.)
781
- *
782
- * The same pass enforces the `slot({ type: 'component' })` contract: a
783
- * component-typed slot resolves to the icon component itself, which is only
784
- * meaningful when it accepts an asset group, so one declared without an
785
- * asset-group `.accepts(...)` is a config-load error.
786
- *
787
- * Hydration note: the serialized `{ __kind: 'assetGroup', ref }` marker
788
- * (`serializeAcceptsList`) is enumerable plain JSON, so `isAssetGroupRef`
789
- * recognizes it browser-side and the placeable group's slug reaches
790
- * `SlotInfo.acceptsAssetGroup` after a round-trip. The placeability throw,
791
- * however, does NOT re-fire on the wire form — the marker carries no
792
- * `assetKind`, so `assertAcceptedAssetGroupPlaceable` returns early. That's
793
- * fine in practice: `serializeAcceptsList` runs the same throw on the way
794
- * *out*, so a non-placeable group can never be written to a wire blob this
795
- * code produces. The browser-side guarantee is the safe-degradation one —
796
- * an unresolvable or non-icon group yields no `acceptsAssetGroup` and an
797
- * empty picker, never the all-components fallback — not a re-validation.
798
- */
799
- function assertDefinitionAcceptsPlaceable(componentName, definition) {
800
- for (const [propName, binding] of Object.entries(definition.props ?? {})) {
801
- if (!isSlotMarker(binding)) continue;
802
- const groupRefs = (binding.__accepts ?? []).filter(isAssetGroupRef);
803
- for (const entry of groupRefs) assertAcceptedAssetGroupPlaceable(entry, {
804
- componentName,
805
- propName
806
- });
807
- if (groupRefs.length > 1) throw new Error(`component "${componentName}" prop "${propName}": a slot can accept at most one asset group (got ${groupRefs.length}).`);
808
- const isForwardingRef = "layer" in binding && binding.layer !== void 0;
809
- if (binding.__valueType === "component" && groupRefs.length === 0 && !isForwardingRef) throw new Error(`component "${componentName}" prop "${propName}": slot({ type: 'component' }) requires an asset-group .accepts() — it resolves to the asset's component (e.g. the aliased Icon pattern), so it must target a placeable asset group.`);
810
- }
811
- }
812
- function readDefinitionName(entry) {
813
- if (typeof entry === "string") return entry.length > 0 ? entry : void 0;
814
- if (entry === null) return void 0;
815
- if (typeof entry !== "object" && typeof entry !== "function") return void 0;
816
- const direct = entry.name;
817
- if (typeof direct === "string" && direct.length > 0) return direct;
818
- const stamped = entry.__componentName;
819
- if (typeof stamped === "string" && stamped.length > 0) return stamped;
820
- const inner = entry.__config;
821
- if (inner && typeof inner === "object") return readDefinitionName(inner);
822
- }
823
- /**
824
- * Rewrite each slot binding's `__accepts` to bare component-name strings
825
- * for the wire. In memory `__accepts` holds whole `ComponentDefinition`
826
- * references; serializing them verbatim both bloats the JSON (the entire
827
- * accepted component is deep-cloned into every consumer) and loses the
828
- * non-enumerable `__componentName` stamp `JSON.stringify` drops — so after
829
- * a `fromJSON` round-trip the names can't be recovered and the slot reads
830
- * as unconstrained. Resolving to names here (while the stamp is present)
831
- * keeps `accepts` intact across the DB round-trip. Non-slot bindings pass
832
- * through untouched; the marker's methods are non-enumerable and so are
833
- * already dropped by the spread.
834
- *
835
- * Asset-group entries can't be name strings — the group's live FCs are
836
- * non-enumerable (so they never leak across the wire) and its `__kind`/`ref`
837
- * tag is likewise non-enumerable, so a verbatim `JSON.stringify` would drop
838
- * the ref entirely and the slot would rehydrate as unconstrained. They are
839
- * rewritten to an explicit `{ __kind: 'assetGroup', ref: slug }` marker —
840
- * plain JSON that `isAssetGroupRef` recognizes on the way back in.
841
- */
842
- function serializeAcceptsInProps(props, ancestryDeclaresChildren = false) {
843
- const out = {};
844
- for (const [name, binding] of Object.entries(props)) {
845
- if (name === "children" && binding === void 0) {
846
- if (!ancestryDeclaresChildren) out[name] = null;
847
- continue;
848
- }
849
- if (!isSlotMarker(binding)) {
850
- out[name] = binding;
851
- continue;
852
- }
853
- const { __accepts: _drop, ...rest } = binding;
854
- const list = serializeAcceptsList(binding.__accepts);
855
- out[name] = list ? {
856
- ...rest,
857
- __accepts: list
858
- } : rest;
859
- }
860
- return out;
861
- }
862
- /**
863
- * Serialize a slot's `__accepts` to its wire form: component entries become
864
- * bare name strings, asset-group entries become `{ __kind: 'assetGroup', ref }`
865
- * markers. The non-placeability throw fires here too, so a bad group can't slip
866
- * onto the wire even if a caller serializes before the eager registration
867
- * guard runs. Returns `undefined` for an empty/absent list so the serializer
868
- * omits `__accepts` rather than writing `[]`.
869
- */
870
- function serializeAcceptsList(accepts) {
871
- if (!accepts) return void 0;
872
- const out = [];
873
- for (const entry of accepts) {
874
- if (isAssetGroupRef(entry)) {
875
- assertAcceptedAssetGroupPlaceable(entry);
876
- const slug = readAcceptedAssetGroupSlug(entry);
877
- if (slug === void 0) throw new Error(UNREGISTERED_ACCEPTED_GROUP_ERROR);
878
- out.push({
879
- __kind: "assetGroup",
880
- ref: slug
881
- });
882
- continue;
883
- }
884
- const componentName = readDefinitionName(entry);
885
- if (componentName) out.push(componentName);
886
- }
887
- return out.length > 0 ? out : void 0;
888
- }
889
- /**
890
- * Pull the inner `ComponentDefinition` off a layer tag value when the
891
- * layer was authored as a composed-component reference. HTML-element
892
- * layers (`tag('div')` / bare `'div'`) and `ComponentRef` markers
893
- * return `undefined` — the chain walk stops there.
894
- */
895
- function getComposedLayerDefinition(tagValue) {
896
- if (tagValue === void 0 || tagValue === null) return void 0;
897
- if (typeof tagValue === "string") return void 0;
898
- if (typeof tagValue !== "object" && typeof tagValue !== "function") return;
899
- const obj = tagValue;
900
- if (obj.__kind === "tag" || obj.__kind === "component") return void 0;
901
- if (obj.__config && typeof obj.__config === "object") return obj.__config;
902
- if (obj.layers && typeof obj.layers === "object") return tagValue;
903
- }
904
- /** Build a `Map<layerName, Layer>` from a definition's authored layers. */
905
- function toLayerMap(layersDef) {
906
- if (!layersDef) return void 0;
907
- const out = /* @__PURE__ */ new Map();
908
- for (const [layerName, layerTag] of Object.entries(layersDef)) out.set(layerName, new Layer({
909
- name: layerName,
910
- tag: layerTag
911
- }));
912
- return out;
913
- }
914
- /**
915
- * A single primitive root layer (`{ root: 'div' }` or `{ root: tag('div') }`)
916
- * — render forwards children straight to the element, so the component holds
917
- * arbitrary node children.
918
- */
919
- function hasSinglePrimitiveRoot(layers) {
920
- if (layers.size !== 1) return false;
921
- const t = layers.get("root")?.tag;
922
- if (typeof t === "string") return true;
923
- if (typeof t === "object" && t !== null) return t.__kind === "tag";
924
- return false;
925
- }
926
- /**
927
- * HTML void elements — tags that must never receive children (React throws).
928
- * Mirrors the HTML spec's void-element list; codegen's registry descriptor
929
- * derives its `voidComponents` set from the same tags.
930
- */
931
- const VOID_HTML_TAGS = new Set([
932
- "area",
933
- "base",
934
- "br",
935
- "col",
936
- "embed",
937
- "hr",
938
- "img",
939
- "input",
940
- "link",
941
- "meta",
942
- "param",
943
- "source",
944
- "track",
945
- "wbr"
946
- ]);
947
- /**
948
- * The HTML tag a component's root element renders as: own `defaultProps.as`
949
- * wins (the `Box as="input"` value-extension pattern), else the root layer's
950
- * tag, else the value-extends chain's answer. Undefined when nothing resolves
951
- * (composed roots, unknown parents) — callers treat that as "no tag fact".
952
- * The `seen` guard stops extends cycles.
953
- *
954
- * Mirrors codegen's `resolveHtmlTag` (getReactArtifacts.ts), which reads the
955
- * same facts off `derived.layers[*].renders` — keep the precedence order
956
- * (`as` → root tag → extends chain) in sync.
957
- */
958
- function resolveRootHtmlTag(component, resolve, seen) {
959
- if (seen.has(component.name)) return void 0;
960
- seen.add(component.name);
961
- const as = component.defaultProps?.as;
962
- if (typeof as === "string") return as;
963
- const t = component.layers.get("root")?.tag;
964
- if (typeof t === "string") return t;
965
- if (typeof t === "object" && t !== null) {
966
- const marker = t;
967
- if (marker.__kind === "tag" && typeof marker.ref === "string") return marker.ref;
968
- }
969
- const parent = component.extendsFrom && resolve ? resolve(component.extendsFrom) : void 0;
970
- return parent ? resolveRootHtmlTag(parent, resolve, seen) : void 0;
971
- }
972
- /**
973
- * Whether the author dropped an inherited `children` prop (`children:
974
- * undefined` in a value-extension — Input/Image/Textarea dropping Box's
975
- * slot). On the wire the drop has two shapes (see `serializeAcceptsInProps`):
976
- * declared-parent drops compact away and are reconstructed here by the
977
- * ancestry fallback; structural-surface drops ride as `children: null`,
978
- * which the constructor restores to the authored own-key-`undefined` shape.
979
- */
980
- function droppedInheritedChildren(component, resolve) {
981
- if (Object.hasOwn(component.props, "children")) return component.props.children === void 0;
982
- return ancestryDeclaresChildren(component, resolve);
983
- }
984
- /**
985
- * Whether any component up the value-extension chain declares a `children`
986
- * prop. Shared by the hydrator's fallback above and the serializer's choice
987
- * of wire shape, so the two sides can't drift apart.
988
- */
989
- function ancestryDeclaresChildren(component, resolve) {
990
- if (!resolve) return false;
991
- const seen = new Set([component.name]);
992
- let parentName = component.extendsFrom;
993
- while (parentName && !seen.has(parentName)) {
994
- seen.add(parentName);
995
- const parent = resolve(parentName);
996
- if (!parent) return false;
997
- if (parent.props.children !== void 0) return true;
998
- parentName = parent.extendsFrom;
999
- }
1000
- return false;
1001
- }
1002
- /**
1003
- * `acceptsChildren` is true when either:
1004
- * - the component has a single primitive root layer, OR
1005
- * - the component declares a `children` slot prop (`children: slot(...)`).
1006
- *
1007
- * Composed-component roots and multi-layer configs without a children
1008
- * slot do NOT accept children — the auto-render has nowhere to put
1009
- * them. This stays value-kind-agnostic: a string-label `children` (Button)
1010
- * still counts as "accepts children" for codegen/prop purposes. Tools that
1011
- * need "accepts *droppable layers*" should use {@link derivesAcceptsChildNodes}.
1012
- *
1013
- * Keyed on the prop NAMED `children`, not on any slot whose forward target is
1014
- * a layer's children surface. A component like Checkbox (`label:
1015
- * slot('label/children')`) routes its LABEL prop into a text layer — that
1016
- * says nothing about the component's own children: it has no destination for
1017
- * them and its render drops them. Counting such forwards used to mark every
1018
- * labeled form control (and Modal/Banner/Toast, via their title/description
1019
- * slots) as children-accepting, which fed the AI catalog the Button-style
1020
- * "put the text in props.children" hint and produced Specs whose `children`
1021
- * leak onto a void `<input>` at render (UDS-2907).
1022
- */
1023
- function derivesAcceptsChildren(layers, props) {
1024
- if (hasSinglePrimitiveRoot(layers)) return true;
1025
- for (const info of props) if (info.kind === "slot" && info.name === "children") return true;
1026
- return false;
1027
- }
1028
- /**
1029
- * `acceptsChildNodes` narrows {@link derivesAcceptsChildren} to children that
1030
- * are *renderable nodes* — the ones a layer-reparent tool can drop into. A
1031
- * single primitive root qualifies (it forwards `ReactNode` children), as does
1032
- * a `children` slot — unless the author declared the children surface to be
1033
- * data rather than nodes: `slot({ type: 'string' })` (a text label like
1034
- * Button's) or any non-slot marker (`children: string()` on a Text that
1035
- * value-extends Box, `number()`, `boolean()`, `variant([...])`). The decision
1036
- * keys on the *authored intent*, not the resolved `valueType` (a string label
1037
- * still resolves to `'ReactNode'`, so `valueType` alone can't distinguish
1038
- * the two).
1039
- */
1040
- function derivesAcceptsChildNodes(layers, props) {
1041
- let hasNodeChildrenSlot = false;
1042
- for (const info of props) {
1043
- if (info.name !== "children") continue;
1044
- if (info.kind !== "slot") return false;
1045
- if (info.authoredType === "string") return false;
1046
- hasNodeChildrenSlot = true;
1047
- }
1048
- if (hasSinglePrimitiveRoot(layers)) return true;
1049
- return hasNodeChildrenSlot;
1050
- }
1051
- function buildCompoundOverrides(entries) {
1052
- const out = {};
1053
- if (!entries) return out;
1054
- for (const entry of entries) for (const [layerName, override] of Object.entries(entry.layers)) {
1055
- if (!out[layerName]) out[layerName] = {};
1056
- Object.assign(out[layerName], override);
1057
- }
1058
- return out;
1059
- }
1060
- //#endregion
1061
- export { Component, Layer, VOID_HTML_TAGS, assertDefinitionAcceptsPlaceable };