@yahoo/uds-create-config 1.1.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 (130) hide show
  1. package/dist/AssetGroup.d.ts +77 -0
  2. package/dist/AssetGroup.js +125 -0
  3. package/dist/Component.d.ts +308 -0
  4. package/dist/Component.js +896 -0
  5. package/dist/ComponentGroup.d.ts +20 -0
  6. package/dist/ComponentGroup.js +46 -0
  7. package/dist/CompositeStyle.d.ts +27 -0
  8. package/dist/CompositeStyle.js +52 -0
  9. package/dist/Config.d.ts +423 -0
  10. package/dist/Config.js +1429 -0
  11. package/dist/Mode.d.ts +41 -0
  12. package/dist/Mode.js +81 -0
  13. package/dist/Modifier.d.ts +51 -0
  14. package/dist/Modifier.js +97 -0
  15. package/dist/MotionDef.d.ts +49 -0
  16. package/dist/MotionDef.js +97 -0
  17. package/dist/Props.d.ts +317 -0
  18. package/dist/Props.js +35 -0
  19. package/dist/Provider.d.ts +20 -0
  20. package/dist/Provider.js +14 -0
  21. package/dist/StyleProp.d.ts +112 -0
  22. package/dist/StyleProp.js +197 -0
  23. package/dist/Token.d.ts +55 -0
  24. package/dist/Token.js +112 -0
  25. package/dist/TokenGroup.d.ts +32 -0
  26. package/dist/TokenGroup.js +68 -0
  27. package/dist/asset-kind.d.ts +55 -0
  28. package/dist/asset-kind.js +29 -0
  29. package/dist/brands.d.ts +30 -0
  30. package/dist/brands.js +20 -0
  31. package/dist/captureCallerPath.d.ts +48 -0
  32. package/dist/captureCallerPath.js +95 -0
  33. package/dist/colorExpressions.d.ts +131 -0
  34. package/dist/colorExpressions.js +148 -0
  35. package/dist/defineAssetGroup.d.ts +166 -0
  36. package/dist/defineAssetGroup.js +264 -0
  37. package/dist/defineProvider.d.ts +29 -0
  38. package/dist/defineProvider.js +60 -0
  39. package/dist/element-marker.d.ts +54 -0
  40. package/dist/element-marker.js +113 -0
  41. package/dist/entity-utils.d.ts +56 -0
  42. package/dist/entity-utils.js +105 -0
  43. package/dist/factories.d.ts +707 -0
  44. package/dist/factories.js +393 -0
  45. package/dist/foreign-component-name.d.ts +21 -0
  46. package/dist/foreign-component-name.js +42 -0
  47. package/dist/index.d.ts +32 -0
  48. package/dist/index.js +28 -0
  49. package/dist/interpolate.d.ts +20 -0
  50. package/dist/interpolate.js +10 -0
  51. package/dist/jsx/__fixtures__/cross-component-preview.d.ts +3 -0
  52. package/dist/jsx/__fixtures__/cross-component-preview.js +15 -0
  53. package/dist/jsx/jsx-dev-runtime.d.ts +15 -0
  54. package/dist/jsx/jsx-dev-runtime.js +11 -0
  55. package/dist/jsx/jsx-runtime.d.ts +48 -0
  56. package/dist/jsx/jsx-runtime.js +305 -0
  57. package/dist/markers.d.ts +217 -0
  58. package/dist/markers.js +67 -0
  59. package/dist/refs.d.ts +158 -0
  60. package/dist/refs.js +104 -0
  61. package/dist/renderer/RendererErrorBoundary.d.ts +26 -0
  62. package/dist/renderer/RendererErrorBoundary.js +30 -0
  63. package/dist/renderer/UdsRenderer.d.ts +80 -0
  64. package/dist/renderer/UdsRenderer.js +33 -0
  65. package/dist/renderer/assetRenderable.d.ts +13 -0
  66. package/dist/renderer/assetRenderable.js +13 -0
  67. package/dist/renderer/index.d.ts +14 -0
  68. package/dist/renderer/index.js +14 -0
  69. package/dist/renderer/makeRegistry.d.ts +34 -0
  70. package/dist/renderer/makeRegistry.js +52 -0
  71. package/dist/renderer/makeUdsRenderer.d.ts +29 -0
  72. package/dist/renderer/makeUdsRenderer.js +35 -0
  73. package/dist/renderer/primitives/FragmentRenderer.d.ts +12 -0
  74. package/dist/renderer/primitives/FragmentRenderer.js +11 -0
  75. package/dist/renderer/primitives/SlotRenderer.d.ts +21 -0
  76. package/dist/renderer/primitives/SlotRenderer.js +20 -0
  77. package/dist/renderer/wrapRegistry.d.ts +64 -0
  78. package/dist/renderer/wrapRegistry.js +39 -0
  79. package/dist/renderer/wrappers/component-slots.d.ts +41 -0
  80. package/dist/renderer/wrappers/component-slots.js +66 -0
  81. package/dist/renderer/wrappers/event-bridge.d.ts +20 -0
  82. package/dist/renderer/wrappers/event-bridge.js +78 -0
  83. package/dist/renderer/wrappers/hex-normalize.d.ts +14 -0
  84. package/dist/renderer/wrappers/hex-normalize.js +35 -0
  85. package/dist/renderer/wrappers/html-aliases.d.ts +24 -0
  86. package/dist/renderer/wrappers/html-aliases.js +62 -0
  87. package/dist/renderer/wrappers/inline-styles.d.ts +16 -0
  88. package/dist/renderer/wrappers/inline-styles.js +104 -0
  89. package/dist/renderer/wrappers/slot-resolution.d.ts +25 -0
  90. package/dist/renderer/wrappers/slot-resolution.js +68 -0
  91. package/dist/renderer/wrappers/void-elements.d.ts +23 -0
  92. package/dist/renderer/wrappers/void-elements.js +28 -0
  93. package/dist/spec/apply-forced-modifiers.d.ts +19 -0
  94. package/dist/spec/apply-forced-modifiers.js +49 -0
  95. package/dist/spec/asset-jsx.d.ts +48 -0
  96. package/dist/spec/asset-jsx.js +48 -0
  97. package/dist/spec/collapse-text-labels.d.ts +44 -0
  98. package/dist/spec/collapse-text-labels.js +107 -0
  99. package/dist/spec/empty-node-slots.d.ts +51 -0
  100. package/dist/spec/empty-node-slots.js +141 -0
  101. package/dist/spec/index.d.ts +10 -0
  102. package/dist/spec/index.js +10 -0
  103. package/dist/spec/jsxToSpec.d.ts +48 -0
  104. package/dist/spec/jsxToSpec.js +506 -0
  105. package/dist/spec/layer-props.d.ts +52 -0
  106. package/dist/spec/layer-props.js +149 -0
  107. package/dist/spec/preview-controls.d.ts +44 -0
  108. package/dist/spec/preview-controls.js +139 -0
  109. package/dist/spec/slot-refs.d.ts +39 -0
  110. package/dist/spec/slot-refs.js +56 -0
  111. package/dist/spec/specToJsx.d.ts +35 -0
  112. package/dist/spec/specToJsx.js +127 -0
  113. package/dist/token-override-rows.d.ts +66 -0
  114. package/dist/token-override-rows.js +223 -0
  115. package/dist/tokenValueType.d.ts +34 -0
  116. package/dist/tokenValueType.js +138 -0
  117. package/dist/tsconfig.tsbuildinfo +1 -0
  118. package/dist/types/css-properties.d.ts +232 -0
  119. package/dist/types/css-properties.js +14 -0
  120. package/dist/types/css-property-keywords.d.ts +156 -0
  121. package/dist/types/css-property-keywords.js +616 -0
  122. package/dist/types/css-values.d.ts +63 -0
  123. package/dist/types/css-values.js +16 -0
  124. package/dist/types.d.ts +708 -0
  125. package/dist/types.js +12 -0
  126. package/dist/units.d.ts +14 -0
  127. package/dist/units.js +16 -0
  128. package/dist/utils/index.d.ts +4 -0
  129. package/dist/utils/index.js +4 -0
  130. package/package.json +81 -0
@@ -0,0 +1,896 @@
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, 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
+ preview;
139
+ metadata;
140
+ /**
141
+ * Absolute path of the file that called `defineComponent('Name', …)`.
142
+ * Captured via the stack walk in `captureCallerPath` and stashed
143
+ * non-enumerably on the authored definition; lifted onto the class
144
+ * here so codegen consumers don't have to thread a separate
145
+ * `componentSourceMap`. `undefined` when the component was hydrated
146
+ * from JSON (no original define call) or built outside the `define*`
147
+ * helpers.
148
+ */
149
+ sourceFilePath;
150
+ /**
151
+ * `true` when the authored definition chained `.render(fn)` — the
152
+ * non-enumerable `__hasRenderFn` flag set by the builder. Codegen
153
+ * needs this to classify single-layer components that ship a custom
154
+ * render fn (e.g. Accordion) into the transform path rather than
155
+ * the inline primitive emitter, so the two paths don't both emit a
156
+ * wrapper FC with the same name.
157
+ */
158
+ hasRenderFn;
159
+ /**
160
+ * The actual `.render(fn)` callback when `hasRenderFn` is `true`.
161
+ * Lifted from the seed's non-enumerable `__renderFn` so the spec
162
+ * extractor can invoke it under the mock-react plugin to capture
163
+ * the component's internal structure as a Spec. Not used at
164
+ * production render time — the codegen-emitted per-file FC handles
165
+ * that path.
166
+ */
167
+ renderFn;
168
+ /**
169
+ * Name of the component this one value-extends from
170
+ * (`defineComponent(Box)` → `'Box'`). Resolved from the non-
171
+ * enumerable `__extendsFrom.__componentName` chain stamped by
172
+ * `defineComponent`'s value-extend branch and `Config.registerComponents`'
173
+ * registration loop. `undefined` for primitives, brace-ref shorthand
174
+ * forms, and JSON-hydrated configs (the wire format doesn't carry
175
+ * this relationship).
176
+ */
177
+ extendsFrom;
178
+ #componentGroup;
179
+ #subcomponentOf;
180
+ #subcomponents;
181
+ #namespaceGetter;
182
+ #prefixGetter;
183
+ #componentResolver;
184
+ #resolveStylePropValueToken;
185
+ #isStyleProp;
186
+ /**
187
+ * Globally-unique lookup key — the spec `type` string a renderer
188
+ * resolves against the registry. When the owning `Config` has a
189
+ * namespace set (`Config.configure({ namespace: 'uds' })`), this is
190
+ * `<namespace>:<name>` (`uds:Badge`); otherwise it's the bare `name`
191
+ * (un-namespaced configs). Read live via a getter so it reflects the
192
+ * namespace regardless of whether `configure` ran before or after the
193
+ * component was registered — mirrors the lazy `prefixGetter` pattern
194
+ * used for token CSS vars.
195
+ *
196
+ * `name` stays the bare authored/display/export identifier; codegen
197
+ * emits a bare-name alias alongside the canonical key so existing
198
+ * specs referencing the bare `name` keep resolving.
199
+ */
200
+ get registryKey() {
201
+ const namespace = this.#namespaceGetter?.();
202
+ return namespace ? `${namespace}:${this.name}` : this.name;
203
+ }
204
+ #derived;
205
+ constructor(args) {
206
+ this.name = args.name;
207
+ this.#namespaceGetter = args.namespaceGetter;
208
+ this.#prefixGetter = args.prefixGetter;
209
+ this.#componentResolver = args.componentResolver;
210
+ this.#resolveStylePropValueToken = args.resolveStylePropValueToken;
211
+ this.#isStyleProp = args.isStyleProp;
212
+ const layers = /* @__PURE__ */ new Map();
213
+ const liftedLayerBase = {};
214
+ for (const [layerName, tag] of Object.entries(args.definition.layers)) {
215
+ layers.set(layerName, new Layer({
216
+ name: layerName,
217
+ tag
218
+ }));
219
+ if (typeof tag === "object" && tag !== null && !("__kind" in tag) && "tag" in tag) {
220
+ const overrides = tag;
221
+ const merged = {
222
+ ...overrides.defaultProps,
223
+ ...overrides.base
224
+ };
225
+ if (Object.keys(merged).length > 0) liftedLayerBase[layerName] = merged;
226
+ }
227
+ }
228
+ this.layers = layers;
229
+ this.props = args.definition.props ?? {};
230
+ const authoredBase = args.definition.base;
231
+ if (Object.keys(liftedLayerBase).length > 0) {
232
+ const merged = { ...liftedLayerBase };
233
+ if (authoredBase) for (const [layerName, layerStyles] of Object.entries(authoredBase)) merged[layerName] = {
234
+ ...merged[layerName] ?? {},
235
+ ...layerStyles
236
+ };
237
+ this.base = merged;
238
+ } else this.base = authoredBase;
239
+ this.defaultProps = args.definition.defaultProps;
240
+ this.compoundProps = args.definition.compoundProps;
241
+ this.motion = args.definition.motion;
242
+ const def = args.definition;
243
+ const previewField = typeof def.preview === "function" ? void 0 : def.preview;
244
+ this.preview = def.__preview ?? previewField;
245
+ const metaField = def.metadata;
246
+ this.metadata = {
247
+ ...metaField,
248
+ label: metaField?.label ?? humanizeComponentName(this.name)
249
+ };
250
+ this.sourceFilePath = readSourcePath(args.definition);
251
+ this.hasRenderFn = args.definition.__hasRenderFn === true;
252
+ this.renderFn = args.definition.__renderFn;
253
+ const extendsFromSeed = args.definition.__extendsFrom;
254
+ const extendsFromName = extendsFromSeed && typeof extendsFromSeed === "object" && typeof extendsFromSeed.__componentName === "string" ? extendsFromSeed.__componentName : void 0;
255
+ this.extendsFrom = extendsFromName ?? args.definition.extendsFrom;
256
+ this.#componentGroup = args.componentGroup;
257
+ this.#subcomponentOf = args.subcomponentOf;
258
+ this.#subcomponents = args.subcomponents;
259
+ }
260
+ get derived() {
261
+ if (!this.#derived) {
262
+ const propsArray = [];
263
+ const propsIndex = /* @__PURE__ */ new Map();
264
+ for (const [propName, binding] of Object.entries(this.props)) {
265
+ const info = inferPropInfo(propName, binding, this.layers, this.#componentResolver);
266
+ if (info === void 0) continue;
267
+ propsArray.push(info);
268
+ propsIndex.set(propName, info);
269
+ }
270
+ const styleUsage = collectStyleUsage(this.base, this.props, this.compoundProps, this.#resolveStylePropValueToken, this.#isStyleProp);
271
+ this.#derived = {
272
+ layers: Array.from(this.layers.values()),
273
+ classNames: componentClassNames(this.#prefixGetter?.() ?? "", this.name),
274
+ compoundOverrides: buildCompoundOverrides(this.compoundProps),
275
+ ...compact({
276
+ componentGroup: this.#componentGroup,
277
+ subcomponentOf: this.#subcomponentOf,
278
+ subcomponents: this.#subcomponents
279
+ }),
280
+ props: propsArray,
281
+ stylePropNames: propsArray.filter((p) => p.kind === "styleProp").map((p) => p.name),
282
+ tokenRefs: styleUsage.tokenRefs,
283
+ stylePropTokenUsages: styleUsage.stylePropTokenUsages,
284
+ stylePropKeywords: styleUsage.stylePropKeywords,
285
+ kind: this.#deriveKind(),
286
+ acceptsChildren: derivesAcceptsChildren(this.layers, propsArray),
287
+ acceptsChildNodes: derivesAcceptsChildNodes(this.layers, propsArray),
288
+ prop(propName) {
289
+ return propsIndex.get(propName);
290
+ }
291
+ };
292
+ }
293
+ return this.#derived;
294
+ }
295
+ /** Classify authoring shape: `extends` wins (value-extension is the defining
296
+ * trait), then anything with multiple layers or a custom render is
297
+ * `multi-layer`, else a bare single-tag `primitive`. */
298
+ #deriveKind() {
299
+ if (this.extendsFrom) return "extends";
300
+ if (this.layers.size > 1 || this.hasRenderFn) return "multi-layer";
301
+ return "primitive";
302
+ }
303
+ toJSON(opts) {
304
+ const layers = {};
305
+ for (const [layerName, layer] of this.layers) {
306
+ if (layer.tag === void 0) continue;
307
+ layers[layerName] = serializeLayerTag(layer.tag);
308
+ }
309
+ let sourceFilePath = this.sourceFilePath;
310
+ if (sourceFilePath && opts?.projectRoot) sourceFilePath = sourceFilePath.replace(`${opts.projectRoot}/`, "");
311
+ return {
312
+ name: this.name,
313
+ layers,
314
+ ...compact({
315
+ props: Object.keys(this.props).length > 0 ? serializeAcceptsInProps(this.props) : void 0,
316
+ base: this.base,
317
+ defaultProps: this.defaultProps,
318
+ compoundProps: this.compoundProps,
319
+ motion: this.motion,
320
+ preview: this.preview ? serializeElementsDeep(this.preview) : void 0,
321
+ metadata: this.metadata,
322
+ sourceFilePath,
323
+ subcomponentOf: this.#subcomponentOf,
324
+ subcomponents: this.#subcomponents,
325
+ extendsFrom: this.extendsFrom
326
+ })
327
+ };
328
+ }
329
+ };
330
+ /**
331
+ * The token + keyword usage a component carries across its styling — one walk
332
+ * of `base`, each prop binding's variant styles, and `compoundProps` overrides,
333
+ * recursing modifier sub-objects (`_hover`) and color expressions. Produces
334
+ * three views the reverse lookups read for "what breaks if I remove this?":
335
+ * - `tokenRefs` — every qualified token name referenced, from structured
336
+ * `token('color/brand')` refs (matched at any depth) and shorthand
337
+ * style-prop values (`bg: 'tertiary'`, resolved via `resolveStylePropValueToken`,
338
+ * which returns `undefined` for keywords / arbitrary literals).
339
+ * - `stylePropTokenUsages` — the `(styleProp, token)` pair for each, so a
340
+ * consumer can tell *which* prop used a token. A token's style prop is the
341
+ * key it sits under: directly (`bg: token(...)` / `bg: 'tertiary'`) or as a
342
+ * color-expression value (`bg: darken(token(...))`), whose nested refs are
343
+ * all attributed to that key.
344
+ * - `stylePropKeywords` — `(styleProp, value)` pairs for the *non-token*
345
+ * keyword values a style prop carries (`display=flex`). Disjoint from
346
+ * `tokenRefs`; `isStyleProp` gates it so layer keys / marker internals
347
+ * don't read as keywords, and bracketed arbitrary literals are excluded.
348
+ * Internal `__`-prefixed keys (`__kind`, a slot's `__accepts` child defs) are
349
+ * skipped, so a child's usage never bleeds into the parent's sets.
350
+ */
351
+ function collectStyleUsage(base, props, compoundProps, resolveStylePropValueToken, isStyleProp) {
352
+ const refs = /* @__PURE__ */ new Set();
353
+ const pairKeys = /* @__PURE__ */ new Set();
354
+ const pairs = [];
355
+ const keywords = /* @__PURE__ */ new Map();
356
+ const seen = /* @__PURE__ */ new WeakSet();
357
+ const addPair = (styleProp, token) => {
358
+ const key = `${styleProp}${token}`;
359
+ if (pairKeys.has(key)) return;
360
+ pairKeys.add(key);
361
+ pairs.push({
362
+ styleProp,
363
+ token
364
+ });
365
+ };
366
+ const collectUnder = (node, styleProp) => {
367
+ if (node === null || typeof node !== "object") return;
368
+ if (isTokenRef(node)) {
369
+ refs.add(node.ref);
370
+ addPair(styleProp, node.ref);
371
+ return;
372
+ }
373
+ for (const value of Object.values(node)) collectUnder(value, styleProp);
374
+ };
375
+ const walk = (node) => {
376
+ if (node === null || typeof node !== "object") return;
377
+ if (isTokenRef(node)) {
378
+ refs.add(node.ref);
379
+ return;
380
+ }
381
+ if (seen.has(node)) return;
382
+ seen.add(node);
383
+ if (Array.isArray(node)) {
384
+ for (const item of node) walk(item);
385
+ return;
386
+ }
387
+ for (const [key, value] of Object.entries(node)) {
388
+ if (key.startsWith("__")) continue;
389
+ if (typeof value === "string") {
390
+ const ref = resolveStylePropValueToken?.(key, value);
391
+ if (ref) {
392
+ refs.add(ref);
393
+ addPair(key, ref);
394
+ } else if (isStyleProp?.(key) && !value.startsWith("[")) {
395
+ const values = keywords.get(key) ?? /* @__PURE__ */ new Set();
396
+ values.add(value);
397
+ keywords.set(key, values);
398
+ }
399
+ } else if (isTokenRef(value)) {
400
+ refs.add(value.ref);
401
+ addPair(key, value.ref);
402
+ } else if (isColorExpression(value)) collectUnder(value, key);
403
+ else walk(value);
404
+ }
405
+ };
406
+ if (base) walk(base);
407
+ for (const binding of Object.values(props)) walk(binding);
408
+ for (const entry of compoundProps ?? []) walk(entry.layers);
409
+ const stylePropKeywords = [...keywords].flatMap(([styleProp, values]) => [...values].map((value) => ({
410
+ styleProp,
411
+ value
412
+ })));
413
+ return {
414
+ tokenRefs: [...refs],
415
+ stylePropTokenUsages: pairs,
416
+ stylePropKeywords
417
+ };
418
+ }
419
+ function inferPropInfo(name, binding, layers, resolve) {
420
+ if (binding === void 0 || binding === null) return void 0;
421
+ if (typeof binding === "function") return {
422
+ kind: "function",
423
+ name,
424
+ required: false,
425
+ isEventHandler: name.startsWith("on") && name.length > 2
426
+ };
427
+ if (typeof binding !== "object") return void 0;
428
+ if (isSlotMarker(binding)) return resolveSlotPropInfo(name, binding, layers, resolve);
429
+ if (isVariantMarker(binding)) {
430
+ const values = isVariantArrayMarker(binding) ? binding.values : Object.keys(binding.values);
431
+ return {
432
+ kind: "variant",
433
+ name,
434
+ required: binding.__required === true,
435
+ values
436
+ };
437
+ }
438
+ if (isBoolMarker(binding)) return {
439
+ kind: "boolean",
440
+ name,
441
+ required: binding.__required === true
442
+ };
443
+ if (isStringMarker(binding)) return {
444
+ kind: "string",
445
+ name,
446
+ required: binding.__required === true
447
+ };
448
+ if (isNumberMarker(binding)) return {
449
+ kind: "number",
450
+ name,
451
+ required: binding.__required === true
452
+ };
453
+ if (isStylePropRef(binding)) return {
454
+ kind: "styleProp",
455
+ name,
456
+ required: false,
457
+ stylePropName: binding.ref
458
+ };
459
+ const obj = binding;
460
+ if (obj.__kind === "composite" && typeof obj.ref === "string") return {
461
+ kind: "composite",
462
+ name,
463
+ required: false,
464
+ compositeName: obj.ref,
465
+ ...typeof obj.layer === "string" ? { layer: obj.layer } : {}
466
+ };
467
+ }
468
+ /**
469
+ * Build a `kind: 'slot'` `PropInfo` from a `SlotMarker | SlotRef`.
470
+ * Walks the slot's forward chain (when it targets a composed-component
471
+ * layer's slot prop) to resolve:
472
+ *
473
+ * - `accepts` — outer marker's `__accepts` wins; otherwise inherits
474
+ * from the innermost descendant slot that declared `.accepts(...)`.
475
+ * - `valueType` — what the JSX value resolves to at the terminal
476
+ * binding (the non-slot binding the chain bottoms out at, or
477
+ * `'ReactNode'` for open/children slots).
478
+ *
479
+ * Cycle protection: `seen` keys on `"layer/layerProp"`.
480
+ */
481
+ function resolveSlotPropInfo(name, binding, layers, resolve) {
482
+ const layer = "layer" in binding ? binding.layer : void 0;
483
+ const layerProp = "layerProp" in binding && binding.layerProp || "children";
484
+ const required = binding.__required === true;
485
+ const isEventHandler = layerProp.startsWith("on") && layerProp.length > 2;
486
+ const chain = walkSlotForwardChain(binding, layers, resolve);
487
+ const baseValueType = isEventHandler ? "function" : chain.valueType;
488
+ const authoredType = binding.__valueType ?? (baseValueType === "string" ? "string" : void 0);
489
+ return {
490
+ kind: "slot",
491
+ name,
492
+ required,
493
+ layerProp,
494
+ valueType: baseValueType,
495
+ ...layer !== void 0 ? { layer } : {},
496
+ ...chain.accepts !== void 0 ? { accepts: chain.accepts } : {},
497
+ ...chain.acceptsAssetGroup !== void 0 ? { acceptsAssetGroup: chain.acceptsAssetGroup } : {},
498
+ ...authoredType !== void 0 ? { authoredType } : {},
499
+ ...baseValueType === "variant" && chain.options !== void 0 ? { valueOptions: chain.options } : {},
500
+ ...baseValueType === "composite" && chain.compositeName !== void 0 ? { compositeName: chain.compositeName } : {}
501
+ };
502
+ }
503
+ /**
504
+ * Walk a slot's forward chain across composed-component layers.
505
+ *
506
+ * The chain ends when we hit a non-slot binding (boolean/variant/string/
507
+ * styleProp/function/etc.), an HTML-element layer (no `__config`), or an
508
+ * open slot with no further layer to follow. A `children`-targeted ref is
509
+ * followed into its layer (a Text leaf resolves to `'string'`, a node
510
+ * container to `'ReactNode'`) rather than short-circuited — only the
511
+ * component's own open `slot()` is treated as a node container outright.
512
+ * `accepts` is collected as the first `__accepts` seen anywhere in the
513
+ * chain (outermost wins, then any inner ancestor that declared one).
514
+ */
515
+ function walkSlotForwardChain(start, startLayers, resolve) {
516
+ const startAccepts = resolveAccepts(start.__accepts);
517
+ let accepts = startAccepts.names;
518
+ let acceptsAssetGroup = startAccepts.assetGroup;
519
+ let current = start;
520
+ let currentLayers = startLayers;
521
+ let followed = false;
522
+ const seen = /* @__PURE__ */ new Set();
523
+ while (true) {
524
+ const layer = "layer" in current ? current.layer : void 0;
525
+ const layerProp = "layerProp" in current && current.layerProp || "children";
526
+ if (!layer) return {
527
+ valueType: (followed && current.__valueType === "string" ? "string" : void 0) ?? "ReactNode",
528
+ accepts,
529
+ acceptsAssetGroup
530
+ };
531
+ const key = `${layer}/${layerProp}`;
532
+ if (seen.has(key)) return {
533
+ valueType: "ReactNode",
534
+ accepts,
535
+ acceptsAssetGroup
536
+ };
537
+ seen.add(key);
538
+ const innerLayers = currentLayers;
539
+ if (!innerLayers) return {
540
+ valueType: "ReactNode",
541
+ accepts,
542
+ acceptsAssetGroup
543
+ };
544
+ const layerTag = innerLayers.get(layer)?.tag;
545
+ const surface = resolveLayerSurface(layerTag, resolve);
546
+ if (!surface) return {
547
+ valueType: layerProp === "children" ? "ReactNode" : "string",
548
+ accepts,
549
+ acceptsAssetGroup
550
+ };
551
+ const innerBinding = surface.props?.[layerProp];
552
+ if (innerBinding === void 0) return {
553
+ valueType: layerProp === "children" ? "ReactNode" : "string",
554
+ accepts,
555
+ acceptsAssetGroup
556
+ };
557
+ if (isSlotMarker(innerBinding)) {
558
+ if (accepts === void 0 || acceptsAssetGroup === void 0) {
559
+ const inner = resolveAccepts(innerBinding.__accepts);
560
+ if (accepts === void 0) accepts = inner.names;
561
+ if (acceptsAssetGroup === void 0) acceptsAssetGroup = inner.assetGroup;
562
+ }
563
+ current = innerBinding;
564
+ currentLayers = surface.layers;
565
+ followed = true;
566
+ continue;
567
+ }
568
+ return {
569
+ ...terminalResult(innerBinding),
570
+ accepts,
571
+ acceptsAssetGroup
572
+ };
573
+ }
574
+ }
575
+ /**
576
+ * A layer's prop surface + sub-layers, resolved from either an inline
577
+ * composed definition or a registered-component ref. `undefined` for HTML-
578
+ * element layers (`'div'`) and unresolvable refs — the chain stops there.
579
+ */
580
+ function resolveLayerSurface(layerTag, resolve) {
581
+ const inlineDef = getComposedLayerDefinition(layerTag);
582
+ if (inlineDef) return {
583
+ props: inlineDef.props,
584
+ layers: toLayerMap(inlineDef.layers)
585
+ };
586
+ const ref = componentRefName(layerTag);
587
+ const comp = ref ? resolve?.(ref) : void 0;
588
+ if (comp) return {
589
+ props: comp.props,
590
+ layers: comp.layers
591
+ };
592
+ }
593
+ /** Read a registered-component-ref layer tag's target name, from the wire
594
+ * form (`{ __kind: 'component', ref }`) or the in-memory `__componentName`
595
+ * stamp. Element/inline layers have neither and return `undefined`. */
596
+ function componentRefName(tag) {
597
+ if (tag === null || typeof tag !== "object") return void 0;
598
+ const obj = tag;
599
+ if (obj.__kind === "component" && typeof obj.ref === "string") return obj.ref;
600
+ if (typeof obj.__componentName === "string") return obj.__componentName;
601
+ }
602
+ /** Resolve a terminal (non-slot) binding's value kind plus, for a variant, its
603
+ * selectable values, or for a composite ref its registry name, so tools can
604
+ * render the matching control (a dropdown / composite picker). */
605
+ function terminalResult(binding) {
606
+ if (typeof binding === "function") return { valueType: "function" };
607
+ if (binding === null || typeof binding !== "object") return { valueType: "string" };
608
+ if (isVariantMarker(binding)) return {
609
+ valueType: "variant",
610
+ options: isVariantArrayMarker(binding) ? binding.values : Object.keys(binding.values)
611
+ };
612
+ if (isCompositeRef(binding)) return {
613
+ valueType: "composite",
614
+ compositeName: binding.ref
615
+ };
616
+ if (isBoolMarker(binding)) return { valueType: "boolean" };
617
+ if (isNumberMarker(binding)) return { valueType: "number" };
618
+ if (isStringMarker(binding)) return { valueType: "string" };
619
+ if (isStylePropRef(binding)) return { valueType: "string" };
620
+ return { valueType: "string" };
621
+ }
622
+ /**
623
+ * Resolve a slot's `__accepts` into the two distinct things a slot can
624
+ * accept: registered component *names* and a placeable asset-group *slug*.
625
+ *
626
+ * Component entries are `ComponentDefinition`s in memory (carrying an
627
+ * authored `name` or the `__componentName` stamp) and bare name strings on
628
+ * the wire; either way `readDefinitionName` reads the name. Asset-group
629
+ * entries are the double-duty group definition in memory and a
630
+ * `{ __kind: 'assetGroup', ref }` marker on the wire; `isAssetGroupRef`
631
+ * catches both and `readAcceptedAssetGroupSlug` reads the slug. The asset
632
+ * branch throws for a non-placeable class (a font group), keyed to the
633
+ * `isPlaceable` capability rather than to any one class — without it a font
634
+ * group would silently contribute nothing and the designer panel would fall
635
+ * back to the all-components picker.
636
+ *
637
+ * `names` is `undefined` (not `[]`) when no component was accepted, so callers
638
+ * can distinguish "unconstrained" from "empty list"; `assetGroup` is the first
639
+ * accepted group's slug (slots target a single group in practice).
640
+ */
641
+ function resolveAccepts(accepts) {
642
+ if (!accepts) return {};
643
+ const names = [];
644
+ let assetGroup;
645
+ for (const entry of accepts) {
646
+ if (isAssetGroupRef(entry)) {
647
+ assertAcceptedAssetGroupPlaceable(entry);
648
+ const slug = readAcceptedAssetGroupSlug(entry);
649
+ if (slug === void 0) throw new Error(UNREGISTERED_ACCEPTED_GROUP_ERROR);
650
+ if (assetGroup === void 0) assetGroup = slug;
651
+ continue;
652
+ }
653
+ const name = readDefinitionName(entry);
654
+ if (name) names.push(name);
655
+ }
656
+ return {
657
+ names: names.length > 0 ? names : void 0,
658
+ assetGroup
659
+ };
660
+ }
661
+ /**
662
+ * Read an accepted asset group's slug from either form an `__accepts` entry
663
+ * takes: the live double-duty definition (slug on the internal `__slug` slot)
664
+ * or the serialized `{ __kind: 'assetGroup', ref }` wire marker.
665
+ *
666
+ * Crucially this never reads the live definition's `ref` *getter* — that getter
667
+ * throws "read before registration" until `registerAssetGroups` stamps `__slug`,
668
+ * which would turn a recoverable "group not registered" condition into a cryptic
669
+ * crash on the first `derived`/`toJSON` access. The `.ref` fallback is reached
670
+ * only for wire markers (no `assetKind` field); an unregistered *live* group
671
+ * resolves to `undefined` here, and the caller raises a clear error.
672
+ */
673
+ function readAcceptedAssetGroupSlug(entry) {
674
+ const live = readAssetGroupSlug(entry);
675
+ if (live) return live;
676
+ if (entry !== null && typeof entry === "object" && !("assetKind" in entry)) {
677
+ const ref = entry.ref;
678
+ if (typeof ref === "string" && ref.length > 0) return ref;
679
+ }
680
+ }
681
+ /** Shared message for an accepted asset group whose slug can't be resolved —
682
+ * it was pointed at by `.accepts(...)` but never registered. */
683
+ 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.";
684
+ /**
685
+ * Throw for `.accepts(<non-placeable group>)`. Reads the stamped
686
+ * `assetKind` off the accepted group (the double-duty definition
687
+ * object); a bare `{ __kind, ref }` marker carries no class to
688
+ * validate, so it passes through.
689
+ */
690
+ function assertAcceptedAssetGroupPlaceable(entry, context) {
691
+ const group = entry;
692
+ const assetKind = group.assetKind;
693
+ if (assetKind === void 0) return;
694
+ if (isPlaceable({ assetKind })) return;
695
+ const slug = readAssetGroupSlug(entry) ?? group.label ?? "unknown";
696
+ const where = context ? `component "${context.componentName}" prop "${context.propName}": ` : "";
697
+ 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.`);
698
+ }
699
+ /**
700
+ * Catches a slot that declares `.accepts(<non-placeable group>)` — e.g.
701
+ * a slot wired to accept a font group, which can never fill a slot.
702
+ *
703
+ * This is the *eager* guard: `Config.registerComponents` and
704
+ * `registerComponentGroups` run it once per definition at registration
705
+ * time, so the error surfaces right when the component is registered
706
+ * rather than later, on the first lazy `derived` read buried deep in a
707
+ * render path (where it'd be much harder to trace back to the cause).
708
+ *
709
+ * There's also a *lazy* check inside `resolveAccepts`. We keep both
710
+ * on purpose: this eager walk only sees the top-level definition, so the
711
+ * lazy check is the backstop for bindings it can't reach. (Inner slots
712
+ * of a composed layer aren't a gap — they get validated through their
713
+ * own component's registration.)
714
+ *
715
+ * The same pass enforces the `slot({ type: 'component' })` contract: a
716
+ * component-typed slot resolves to the icon component itself, which is only
717
+ * meaningful when it accepts an asset group, so one declared without an
718
+ * asset-group `.accepts(...)` is a config-load error.
719
+ *
720
+ * Hydration note: the serialized `{ __kind: 'assetGroup', ref }` marker
721
+ * (`serializeAcceptsList`) is enumerable plain JSON, so `isAssetGroupRef`
722
+ * recognizes it browser-side and the placeable group's slug reaches
723
+ * `SlotInfo.acceptsAssetGroup` after a round-trip. The placeability throw,
724
+ * however, does NOT re-fire on the wire form — the marker carries no
725
+ * `assetKind`, so `assertAcceptedAssetGroupPlaceable` returns early. That's
726
+ * fine in practice: `serializeAcceptsList` runs the same throw on the way
727
+ * *out*, so a non-placeable group can never be written to a wire blob this
728
+ * code produces. The browser-side guarantee is the safe-degradation one —
729
+ * an unresolvable or non-icon group yields no `acceptsAssetGroup` and an
730
+ * empty picker, never the all-components fallback — not a re-validation.
731
+ */
732
+ function assertDefinitionAcceptsPlaceable(componentName, definition) {
733
+ for (const [propName, binding] of Object.entries(definition.props ?? {})) {
734
+ if (!isSlotMarker(binding)) continue;
735
+ const groupRefs = (binding.__accepts ?? []).filter(isAssetGroupRef);
736
+ for (const entry of groupRefs) assertAcceptedAssetGroupPlaceable(entry, {
737
+ componentName,
738
+ propName
739
+ });
740
+ if (groupRefs.length > 1) throw new Error(`component "${componentName}" prop "${propName}": a slot can accept at most one asset group (got ${groupRefs.length}).`);
741
+ const isForwardingRef = "layer" in binding && binding.layer !== void 0;
742
+ 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.`);
743
+ }
744
+ }
745
+ function readDefinitionName(entry) {
746
+ if (typeof entry === "string") return entry.length > 0 ? entry : void 0;
747
+ if (entry === null) return void 0;
748
+ if (typeof entry !== "object" && typeof entry !== "function") return void 0;
749
+ const direct = entry.name;
750
+ if (typeof direct === "string" && direct.length > 0) return direct;
751
+ const stamped = entry.__componentName;
752
+ if (typeof stamped === "string" && stamped.length > 0) return stamped;
753
+ const inner = entry.__config;
754
+ if (inner && typeof inner === "object") return readDefinitionName(inner);
755
+ }
756
+ /**
757
+ * Rewrite each slot binding's `__accepts` to bare component-name strings
758
+ * for the wire. In memory `__accepts` holds whole `ComponentDefinition`
759
+ * references; serializing them verbatim both bloats the JSON (the entire
760
+ * accepted component is deep-cloned into every consumer) and loses the
761
+ * non-enumerable `__componentName` stamp `JSON.stringify` drops — so after
762
+ * a `fromJSON` round-trip the names can't be recovered and the slot reads
763
+ * as unconstrained. Resolving to names here (while the stamp is present)
764
+ * keeps `accepts` intact across the DB round-trip. Non-slot bindings pass
765
+ * through untouched; the marker's methods are non-enumerable and so are
766
+ * already dropped by the spread.
767
+ *
768
+ * Asset-group entries can't be name strings — the group's live FCs are
769
+ * non-enumerable (so they never leak across the wire) and its `__kind`/`ref`
770
+ * tag is likewise non-enumerable, so a verbatim `JSON.stringify` would drop
771
+ * the ref entirely and the slot would rehydrate as unconstrained. They are
772
+ * rewritten to an explicit `{ __kind: 'assetGroup', ref: slug }` marker —
773
+ * plain JSON that `isAssetGroupRef` recognizes on the way back in.
774
+ */
775
+ function serializeAcceptsInProps(props) {
776
+ const out = {};
777
+ for (const [name, binding] of Object.entries(props)) {
778
+ if (!isSlotMarker(binding)) {
779
+ out[name] = binding;
780
+ continue;
781
+ }
782
+ const { __accepts: _drop, ...rest } = binding;
783
+ const list = serializeAcceptsList(binding.__accepts);
784
+ out[name] = list ? {
785
+ ...rest,
786
+ __accepts: list
787
+ } : rest;
788
+ }
789
+ return out;
790
+ }
791
+ /**
792
+ * Serialize a slot's `__accepts` to its wire form: component entries become
793
+ * bare name strings, asset-group entries become `{ __kind: 'assetGroup', ref }`
794
+ * markers. The non-placeability throw fires here too, so a bad group can't slip
795
+ * onto the wire even if a caller serializes before the eager registration
796
+ * guard runs. Returns `undefined` for an empty/absent list so the serializer
797
+ * omits `__accepts` rather than writing `[]`.
798
+ */
799
+ function serializeAcceptsList(accepts) {
800
+ if (!accepts) return void 0;
801
+ const out = [];
802
+ for (const entry of accepts) {
803
+ if (isAssetGroupRef(entry)) {
804
+ assertAcceptedAssetGroupPlaceable(entry);
805
+ const slug = readAcceptedAssetGroupSlug(entry);
806
+ if (slug === void 0) throw new Error(UNREGISTERED_ACCEPTED_GROUP_ERROR);
807
+ out.push({
808
+ __kind: "assetGroup",
809
+ ref: slug
810
+ });
811
+ continue;
812
+ }
813
+ const componentName = readDefinitionName(entry);
814
+ if (componentName) out.push(componentName);
815
+ }
816
+ return out.length > 0 ? out : void 0;
817
+ }
818
+ /**
819
+ * Pull the inner `ComponentDefinition` off a layer tag value when the
820
+ * layer was authored as a composed-component reference. HTML-element
821
+ * layers (`tag('div')` / bare `'div'`) and `ComponentRef` markers
822
+ * return `undefined` — the chain walk stops there.
823
+ */
824
+ function getComposedLayerDefinition(tagValue) {
825
+ if (tagValue === void 0 || tagValue === null) return void 0;
826
+ if (typeof tagValue === "string") return void 0;
827
+ if (typeof tagValue !== "object" && typeof tagValue !== "function") return;
828
+ const obj = tagValue;
829
+ if (obj.__kind === "tag" || obj.__kind === "component") return void 0;
830
+ if (obj.__config && typeof obj.__config === "object") return obj.__config;
831
+ if (obj.layers && typeof obj.layers === "object") return tagValue;
832
+ }
833
+ /** Build a `Map<layerName, Layer>` from a definition's authored layers. */
834
+ function toLayerMap(layersDef) {
835
+ if (!layersDef) return void 0;
836
+ const out = /* @__PURE__ */ new Map();
837
+ for (const [layerName, layerTag] of Object.entries(layersDef)) out.set(layerName, new Layer({
838
+ name: layerName,
839
+ tag: layerTag
840
+ }));
841
+ return out;
842
+ }
843
+ /**
844
+ * A single primitive root layer (`{ root: 'div' }` or `{ root: tag('div') }`)
845
+ * — render forwards children straight to the element, so the component holds
846
+ * arbitrary node children.
847
+ */
848
+ function hasSinglePrimitiveRoot(layers) {
849
+ if (layers.size !== 1) return false;
850
+ const t = layers.get("root")?.tag;
851
+ if (typeof t === "string") return true;
852
+ if (typeof t === "object" && t !== null) return t.__kind === "tag";
853
+ return false;
854
+ }
855
+ /**
856
+ * `acceptsChildren` is true when either:
857
+ * - the component has a single primitive root layer, OR
858
+ * - a `slot()` prop binds its value to a layer's `children` surface
859
+ * (covered by `kind: 'slot'` with `layerProp === 'children'`).
860
+ *
861
+ * Composed-component roots and multi-layer configs without a children
862
+ * slot do NOT accept children — the auto-render has nowhere to put
863
+ * them. This stays value-kind-agnostic: a string-label `children` (Button)
864
+ * still counts as "accepts children" for codegen/prop purposes. Tools that
865
+ * need "accepts *droppable layers*" should use {@link derivesAcceptsChildNodes}.
866
+ */
867
+ function derivesAcceptsChildren(layers, props) {
868
+ if (hasSinglePrimitiveRoot(layers)) return true;
869
+ for (const info of props) if (info.kind === "slot" && info.layerProp === "children") return true;
870
+ return false;
871
+ }
872
+ /**
873
+ * `acceptsChildNodes` narrows {@link derivesAcceptsChildren} to children that
874
+ * are *renderable nodes* — the ones a layer-reparent tool can drop into. A
875
+ * single primitive root qualifies (it forwards `ReactNode` children), as does
876
+ * a `children` slot — unless the author declared it `slot({ type: 'string' })`
877
+ * (a text label like Button's). The decision keys on the *authored intent*,
878
+ * not the resolved `valueType` (a string label still resolves to `'ReactNode'`,
879
+ * so `valueType` alone can't distinguish the two).
880
+ */
881
+ function derivesAcceptsChildNodes(layers, props) {
882
+ if (hasSinglePrimitiveRoot(layers)) return true;
883
+ for (const info of props) if (info.kind === "slot" && info.layerProp === "children" && info.authoredType !== "string") return true;
884
+ return false;
885
+ }
886
+ function buildCompoundOverrides(entries) {
887
+ const out = {};
888
+ if (!entries) return out;
889
+ for (const entry of entries) for (const [layerName, override] of Object.entries(entry.layers)) {
890
+ if (!out[layerName]) out[layerName] = {};
891
+ Object.assign(out[layerName], override);
892
+ }
893
+ return out;
894
+ }
895
+ //#endregion
896
+ export { Component, Layer, assertDefinitionAcceptsPlaceable };