@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.
- package/README.md +129 -0
- package/dist/ai-lanes.d.ts +23 -0
- package/dist/ai-lanes.js +34 -0
- package/dist/authoring/define-component.d.ts +85 -0
- package/dist/configs/CanvasConfig.d.ts +3237 -0
- package/dist/configs/CanvasConfig.js +332 -0
- package/dist/configs/build-options.d.ts +10 -0
- package/dist/configs/build-options.js +68 -0
- package/dist/configs/platform.d.ts +15 -0
- package/dist/configs/platform.js +17 -0
- package/dist/configs/react-native-system.d.ts +3026 -0
- package/dist/configs/react-native-system.js +64 -0
- package/dist/configs/system.d.ts +2771 -0
- package/dist/configs/system.js +74 -0
- package/dist/css/properties.generated.d.ts +14 -0
- package/dist/css/properties.generated.js +6260 -0
- package/dist/css/value-type.d.ts +48 -0
- package/dist/css/value-type.js +131 -0
- package/dist/css/values.d.ts +33 -0
- package/dist/css/values.js +116 -0
- package/dist/entities/native/NativeModifier.d.ts +25 -0
- package/dist/entities/native/NativeModifier.js +41 -0
- package/dist/entities/native/NativeSettings.d.ts +44 -0
- package/dist/entities/native/NativeSettings.js +39 -0
- package/dist/entities/native/NativeStyleProperty.d.ts +355 -0
- package/dist/entities/native/NativeStyleProperty.js +28 -0
- package/dist/entities/native/NativeToken.d.ts +31 -0
- package/dist/entities/native/NativeToken.js +49 -0
- package/dist/entities/system/CanvasRole.d.ts +34 -0
- package/dist/entities/system/CanvasRole.js +45 -0
- package/dist/entities/system/Component.d.ts +1287 -0
- package/dist/entities/system/Component.js +1840 -0
- package/dist/entities/system/Composite.d.ts +12 -0
- package/dist/entities/system/Composite.js +26 -0
- package/dist/entities/system/Device.d.ts +11 -0
- package/dist/entities/system/Device.js +18 -0
- package/dist/entities/system/File.d.ts +72 -0
- package/dist/entities/system/File.js +136 -0
- package/dist/entities/system/Font.d.ts +48 -0
- package/dist/entities/system/Font.js +56 -0
- package/dist/entities/system/GlobalStyle.d.ts +26 -0
- package/dist/entities/system/GlobalStyle.js +54 -0
- package/dist/entities/system/Guidance.d.ts +85 -0
- package/dist/entities/system/Guidance.js +59 -0
- package/dist/entities/system/GuidanceStyle.d.ts +14 -0
- package/dist/entities/system/GuidanceStyle.js +8 -0
- package/dist/entities/system/Icon.d.ts +46 -0
- package/dist/entities/system/Icon.js +46 -0
- package/dist/entities/system/LinkedSystem.d.ts +504 -0
- package/dist/entities/system/LinkedSystem.js +814 -0
- package/dist/entities/system/Modifier.d.ts +92 -0
- package/dist/entities/system/Modifier.js +120 -0
- package/dist/entities/system/Motion.d.ts +28 -0
- package/dist/entities/system/Motion.js +48 -0
- package/dist/entities/system/Operation.d.ts +100 -0
- package/dist/entities/system/Operation.js +236 -0
- package/dist/entities/system/Package.d.ts +42 -0
- package/dist/entities/system/Package.js +75 -0
- package/dist/entities/system/Settings.d.ts +94 -0
- package/dist/entities/system/Settings.js +166 -0
- package/dist/entities/system/StyleProperty.d.ts +135 -0
- package/dist/entities/system/StyleProperty.js +438 -0
- package/dist/entities/system/Token.d.ts +67 -0
- package/dist/entities/system/Token.js +129 -0
- package/dist/entities/system/Tool.d.ts +134 -0
- package/dist/entities/system/Tool.js +124 -0
- package/dist/entities/system/color.d.ts +64 -0
- package/dist/entities/system/color.js +123 -0
- package/dist/entities/system/component-module.d.ts +63 -0
- package/dist/entities/system/component-module.js +258 -0
- package/dist/entities/system/copy-plan.d.ts +98 -0
- package/dist/entities/system/copy-plan.js +451 -0
- package/dist/entities/system/defineComponent.d.ts +428 -0
- package/dist/entities/system/defineComponent.js +337 -0
- package/dist/entities/system/element.d.ts +101 -0
- package/dist/entities/system/element.js +171 -0
- package/dist/entities/system/icon-library.d.ts +64 -0
- package/dist/entities/system/icon-library.js +112 -0
- package/dist/entities/system/icon-metadata.d.ts +72 -0
- package/dist/entities/system/icon-metadata.js +111 -0
- package/dist/entities/system/link-declaration.d.ts +27 -0
- package/dist/entities/system/link-declaration.js +64 -0
- package/dist/entities/system/link-plan.d.ts +160 -0
- package/dist/entities/system/link-plan.js +770 -0
- package/dist/entities/system/runtime-modules.d.ts +25 -0
- package/dist/entities/system/runtime-modules.js +38 -0
- package/dist/entities/system/style-bag.d.ts +20 -0
- package/dist/entities/system/style-bag.js +246 -0
- package/dist/entities/system/token-index.d.ts +89 -0
- package/dist/entities/system/token-index.js +112 -0
- package/dist/framework/Config.d.ts +2472 -0
- package/dist/framework/Config.js +5023 -0
- package/dist/framework/Entity.d.ts +127 -0
- package/dist/framework/Entity.js +125 -0
- package/dist/framework/authoring.d.ts +24 -0
- package/dist/framework/authoring.js +7 -0
- package/dist/framework/change-hooks.d.ts +119 -0
- package/dist/framework/change-hooks.js +131 -0
- package/dist/framework/changes.d.ts +88 -0
- package/dist/framework/changes.js +246 -0
- package/dist/framework/class-names.d.ts +260 -0
- package/dist/framework/class-names.js +630 -0
- package/dist/framework/coalesce.d.ts +25 -0
- package/dist/framework/coalesce.js +60 -0
- package/dist/framework/config-op.d.ts +76 -0
- package/dist/framework/config-op.js +43 -0
- package/dist/framework/config-operation-kind.d.ts +14 -0
- package/dist/framework/config-operation-kind.js +14 -0
- package/dist/framework/config-ops.d.ts +34 -0
- package/dist/framework/config-ops.js +187 -0
- package/dist/framework/defineConfig.d.ts +196 -0
- package/dist/framework/defineConfig.js +100 -0
- package/dist/framework/defineDerivedEntity.d.ts +74 -0
- package/dist/framework/defineDerivedEntity.js +83 -0
- package/dist/framework/defineEntity.d.ts +318 -0
- package/dist/framework/defineEntity.js +183 -0
- package/dist/framework/defineSubEntity.d.ts +148 -0
- package/dist/framework/defineSubEntity.js +121 -0
- package/dist/framework/derived-mutations.d.ts +20 -0
- package/dist/framework/derived-mutations.js +38 -0
- package/dist/framework/entity-search.d.ts +29 -0
- package/dist/framework/entity-search.js +117 -0
- package/dist/framework/inline-sources.d.ts +49 -0
- package/dist/framework/inline-sources.js +388 -0
- package/dist/framework/layer-styles.d.ts +25 -0
- package/dist/framework/layer-styles.js +49 -0
- package/dist/framework/memo.d.ts +48 -0
- package/dist/framework/memo.js +84 -0
- package/dist/framework/overlay.d.ts +49 -0
- package/dist/framework/overlay.js +17 -0
- package/dist/framework/plan.d.ts +49 -0
- package/dist/framework/plan.js +73 -0
- package/dist/framework/projections.d.ts +480 -0
- package/dist/framework/projections.js +974 -0
- package/dist/framework/prop-surface.d.ts +132 -0
- package/dist/framework/prop-surface.js +278 -0
- package/dist/framework/ref-graph.d.ts +71 -0
- package/dist/framework/ref-graph.js +158 -0
- package/dist/framework/ref-integrity.d.ts +55 -0
- package/dist/framework/ref-integrity.js +171 -0
- package/dist/framework/registered.d.ts +95 -0
- package/dist/framework/registry-dir.d.ts +42 -0
- package/dist/framework/registry-dir.js +48 -0
- package/dist/framework/registry.d.ts +300 -0
- package/dist/framework/registry.js +104 -0
- package/dist/framework/rejection.d.ts +58 -0
- package/dist/framework/rejection.js +111 -0
- package/dist/framework/rename-inference.d.ts +26 -0
- package/dist/framework/rename-inference.js +50 -0
- package/dist/framework/render-spec.d.ts +296 -0
- package/dist/framework/render-spec.js +809 -0
- package/dist/framework/schema-version.d.ts +140 -0
- package/dist/framework/schema-version.js +214 -0
- package/dist/framework/schemas.d.ts +109 -0
- package/dist/framework/schemas.js +615 -0
- package/dist/framework/session.d.ts +196 -0
- package/dist/framework/session.js +367 -0
- package/dist/framework/signature.d.ts +15 -0
- package/dist/framework/signature.js +83 -0
- package/dist/framework/snapshot.d.ts +115 -0
- package/dist/framework/snapshot.js +277 -0
- package/dist/framework/source-integrity.d.ts +226 -0
- package/dist/framework/source-integrity.js +478 -0
- package/dist/framework/sources.d.ts +211 -0
- package/dist/framework/sources.js +89 -0
- package/dist/framework/utils/compiled-schema.d.ts +23 -0
- package/dist/framework/utils/compiled-schema.js +46 -0
- package/dist/framework/utils/content-key.d.ts +15 -0
- package/dist/framework/utils/content-key.js +33 -0
- package/dist/framework/utils/enumerated.d.ts +13 -0
- package/dist/framework/utils/enumerated.js +19 -0
- package/dist/framework/utils/field-path.d.ts +95 -0
- package/dist/framework/utils/field-path.js +136 -0
- package/dist/framework/utils/field-schema.d.ts +55 -0
- package/dist/framework/utils/field-schema.js +183 -0
- package/dist/framework/utils/group.d.ts +37 -0
- package/dist/framework/utils/group.js +13 -0
- package/dist/framework/utils/package-path.d.ts +37 -0
- package/dist/framework/utils/package-path.js +61 -0
- package/dist/framework/utils/refs.d.ts +194 -0
- package/dist/framework/utils/refs.js +403 -0
- package/dist/framework/validate-spec.d.ts +27 -0
- package/dist/framework/validate-spec.js +45 -0
- package/dist/framework/value-domain.d.ts +26 -0
- package/dist/framework/value-domain.js +202 -0
- package/dist/framework/views-facade.d.ts +15 -0
- package/dist/framework/views-facade.js +19 -0
- package/dist/index.d.ts +90 -42
- package/dist/index.js +86 -37
- package/dist/migrations/2.0.0/raw-css.d.ts +11 -0
- package/dist/migrations/2.0.0/raw-css.js +72 -0
- package/dist/migrations/2.0.0/v1-artifact.d.ts +1559 -0
- package/dist/migrations/2.0.0/v1-artifact.js +1018 -0
- package/dist/migrations/20260908171448_settings_as_kind.d.ts +22 -0
- package/dist/migrations/20260908171448_settings_as_kind.js +89 -0
- package/dist/migrations/20260908194245_visible_state_pointer.d.ts +19 -0
- package/dist/migrations/20260908194245_visible_state_pointer.js +115 -0
- package/dist/migrations/20260909183001_icon_knockout_variants.d.ts +18 -0
- package/dist/migrations/20260909183001_icon_knockout_variants.js +8 -0
- package/dist/migrations/20260910212453_linked_system_link_ops.d.ts +13 -0
- package/dist/migrations/20260910212453_linked_system_link_ops.js +8 -0
- package/dist/migrations/index.d.ts +2 -0
- package/dist/migrations/index.js +2 -0
- package/dist/react-native/style-keys.generated.d.ts +10 -0
- package/dist/react-native/style-keys.generated.js +167 -0
- package/dist/renderer/RendererErrorBoundary.d.ts +32 -5
- package/dist/renderer/RendererErrorBoundary.js +59 -10
- package/dist/renderer/UdsRenderer.d.ts +11 -10
- package/dist/renderer/UdsRenderer.js +1 -1
- package/dist/renderer/assetEntries.d.ts +37 -0
- package/dist/renderer/assetEntries.js +39 -0
- package/dist/renderer/assetRenderable.d.ts +14 -6
- package/dist/renderer/assetRenderable.js +8 -2
- package/dist/renderer/componentEntry.d.ts +58 -0
- package/dist/renderer/componentEntry.js +71 -0
- package/dist/renderer/icon-library.d.ts +20 -0
- package/dist/renderer/index.d.ts +7 -7
- package/dist/renderer/index.js +5 -5
- package/dist/renderer/primitives/SlotRenderer.d.ts +1 -1
- package/dist/renderer/primitives/SlotRenderer.js +1 -1
- package/dist/renderer/runtimeComponent.d.ts +33 -0
- package/dist/renderer/runtimeComponent.js +113 -0
- package/dist/renderer/spec-content.d.ts +43 -0
- package/dist/renderer/spec-content.js +95 -0
- package/dist/renderer/wrapRegistry.d.ts +22 -37
- package/dist/renderer/wrapRegistry.js +10 -20
- package/dist/renderer/wrappers/event-bridge.js +6 -5
- package/dist/renderer/wrappers/hex-normalize.js +6 -5
- package/dist/renderer/wrappers/html-aliases.d.ts +7 -2
- package/dist/renderer/wrappers/html-aliases.js +36 -19
- package/dist/renderer/wrappers/inline-styles.js +7 -6
- package/dist/spec/asset-jsx.d.ts +18 -5
- package/dist/spec/asset-jsx.js +27 -16
- package/dist/spec/collapse-text-labels.d.ts +5 -15
- package/dist/spec/collapse-text-labels.js +26 -19
- package/dist/spec/empty-node-slots.d.ts +56 -34
- package/dist/spec/empty-node-slots.js +87 -47
- package/dist/spec/index.d.ts +21 -10
- package/dist/spec/index.js +21 -10
- package/dist/spec/jsxToSpec.d.ts +14 -9
- package/dist/spec/jsxToSpec.js +20 -3
- package/dist/spec/preview-elements.d.ts +63 -0
- package/dist/spec/preview-elements.js +89 -0
- package/dist/spec/rewrite-refs.d.ts +58 -0
- package/dist/spec/rewrite-refs.js +250 -0
- package/dist/spec/specToJsx.js +18 -29
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +39 -52
- package/dist/AssetGroup.d.ts +0 -77
- package/dist/AssetGroup.js +0 -125
- package/dist/Component.d.ts +0 -333
- package/dist/Component.js +0 -1061
- package/dist/ComponentGroup.d.ts +0 -22
- package/dist/ComponentGroup.js +0 -51
- package/dist/CompositeStyle.d.ts +0 -30
- package/dist/CompositeStyle.js +0 -59
- package/dist/Config.d.ts +0 -528
- package/dist/Config.js +0 -1712
- package/dist/Mode.d.ts +0 -41
- package/dist/Mode.js +0 -81
- package/dist/Modifier.d.ts +0 -51
- package/dist/Modifier.js +0 -97
- package/dist/MotionDef.d.ts +0 -81
- package/dist/MotionDef.js +0 -212
- package/dist/Props.d.ts +0 -332
- package/dist/Props.js +0 -35
- package/dist/Provider.d.ts +0 -20
- package/dist/Provider.js +0 -14
- package/dist/StyleProp.d.ts +0 -145
- package/dist/StyleProp.js +0 -239
- package/dist/Token.d.ts +0 -76
- package/dist/Token.js +0 -133
- package/dist/TokenGroup.d.ts +0 -33
- package/dist/TokenGroup.js +0 -69
- package/dist/asset-kind.d.ts +0 -55
- package/dist/asset-kind.js +0 -29
- package/dist/asset-value.d.ts +0 -23
- package/dist/asset-value.js +0 -40
- package/dist/brands.d.ts +0 -30
- package/dist/brands.js +0 -20
- package/dist/captureCallerPath.d.ts +0 -48
- package/dist/captureCallerPath.js +0 -95
- package/dist/colorExpressions.d.ts +0 -131
- package/dist/colorExpressions.js +0 -148
- package/dist/component-referrers.d.ts +0 -30
- package/dist/component-referrers.js +0 -40
- package/dist/config-diagnostics.d.ts +0 -21
- package/dist/config-diagnostics.js +0 -12
- package/dist/defineAssetGroup.d.ts +0 -200
- package/dist/defineAssetGroup.js +0 -323
- package/dist/defineProvider.d.ts +0 -29
- package/dist/defineProvider.js +0 -60
- package/dist/element-marker.d.ts +0 -63
- package/dist/element-marker.js +0 -113
- package/dist/entity-utils.d.ts +0 -56
- package/dist/entity-utils.js +0 -105
- package/dist/extension.d.ts +0 -55
- package/dist/extension.js +0 -214
- package/dist/factories.d.ts +0 -863
- package/dist/factories.js +0 -475
- package/dist/font-face.d.ts +0 -25
- package/dist/font-face.js +0 -72
- package/dist/foreign-component-name.d.ts +0 -21
- package/dist/foreign-component-name.js +0 -42
- package/dist/interpolate.d.ts +0 -20
- package/dist/interpolate.js +0 -10
- package/dist/jsx/__fixtures__/cross-component-preview.d.ts +0 -3
- package/dist/jsx/__fixtures__/cross-component-preview.js +0 -15
- package/dist/jsx/jsx-dev-runtime.d.ts +0 -15
- package/dist/jsx/jsx-dev-runtime.js +0 -11
- package/dist/jsx/jsx-runtime.d.ts +0 -48
- package/dist/jsx/jsx-runtime.js +0 -305
- package/dist/linked-system-pins.d.ts +0 -30
- package/dist/linked-system-pins.js +0 -45
- package/dist/linkedNodePrefixes.d.ts +0 -73
- package/dist/linkedNodePrefixes.js +0 -99
- package/dist/markers.d.ts +0 -235
- package/dist/markers.js +0 -70
- package/dist/motion-constants.d.ts +0 -37
- package/dist/motion-constants.js +0 -61
- package/dist/native/NativeConfig.d.ts +0 -56
- package/dist/native/NativeConfig.js +0 -162
- package/dist/native/assets.d.ts +0 -20
- package/dist/native/assets.js +0 -17
- package/dist/native/components.d.ts +0 -139
- package/dist/native/components.js +0 -67
- package/dist/native/index.d.ts +0 -18
- package/dist/native/index.js +0 -17
- package/dist/native/modes.d.ts +0 -10
- package/dist/native/modes.js +0 -11
- package/dist/native/types.d.ts +0 -95
- package/dist/native/types.js +0 -0
- package/dist/native/validation.d.ts +0 -8
- package/dist/native/validation.js +0 -885
- package/dist/native/values.d.ts +0 -7
- package/dist/native/values.js +0 -15
- package/dist/native.d.ts +0 -12
- package/dist/native.js +0 -10
- package/dist/refs.d.ts +0 -204
- package/dist/refs.js +0 -129
- package/dist/registry-aliases.d.ts +0 -33
- package/dist/registry-aliases.js +0 -35
- package/dist/registry-dir.d.ts +0 -22
- package/dist/registry-dir.js +0 -10
- package/dist/renderer/makeRegistry.d.ts +0 -34
- package/dist/renderer/makeRegistry.js +0 -52
- package/dist/renderer/makeUdsRenderer.d.ts +0 -13
- package/dist/renderer/makeUdsRenderer.js +0 -51
- package/dist/renderer/wrappers/component-slots.d.ts +0 -41
- package/dist/renderer/wrappers/component-slots.js +0 -66
- package/dist/renderer/wrappers/slot-resolution.d.ts +0 -25
- package/dist/renderer/wrappers/slot-resolution.js +0 -68
- package/dist/renderer/wrappers/void-elements.d.ts +0 -37
- package/dist/renderer/wrappers/void-elements.js +0 -40
- package/dist/spec/layer-props.d.ts +0 -52
- package/dist/spec/layer-props.js +0 -149
- package/dist/spec/preview-controls.d.ts +0 -44
- package/dist/spec/preview-controls.js +0 -139
- package/dist/spec/slot-refs.d.ts +0 -39
- package/dist/spec/slot-refs.js +0 -56
- package/dist/token-override-rows.d.ts +0 -68
- package/dist/token-override-rows.js +0 -233
- package/dist/tokenValueType.d.ts +0 -34
- package/dist/tokenValueType.js +0 -138
- package/dist/types/css-properties.d.ts +0 -233
- package/dist/types/css-properties.js +0 -14
- package/dist/types/css-property-keywords.d.ts +0 -156
- package/dist/types/css-property-keywords.js +0 -616
- package/dist/types/css-values.d.ts +0 -63
- package/dist/types/css-values.js +0 -16
- package/dist/types.d.ts +0 -1138
- package/dist/types.js +0 -12
- package/dist/units.d.ts +0 -14
- package/dist/units.js +0 -16
- package/dist/utils/index.d.ts +0 -4
- 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 };
|