@yahoo/uds-create-config 5.54.0 → 5.55.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/dist/capture/node-ops.js +1 -1
- package/dist/configs/system.js +2 -0
- package/dist/entities/canvas/node-gestures.js +1 -1
- package/dist/entities/canvas/node-patches.js +1 -1
- package/dist/entities/system/Component.d.ts +5 -2
- package/dist/entities/system/Component.js +121 -8
- package/dist/entities/system/LinkedSystem.js +2 -2
- package/dist/entities/system/Operation.js +1 -1
- package/dist/entities/system/component-forwards.js +1 -1
- package/dist/entities/system/component-source-fields.js +1 -1
- package/dist/entities/system/component-style-set.js +1 -1
- package/dist/entities/system/conditional-defaults.d.ts +45 -0
- package/dist/entities/system/conditional-defaults.js +142 -0
- package/dist/entities/system/copy-plan.js +1 -1
- package/dist/entities/system/css-motion-reach.js +1 -1
- package/dist/entities/system/defineComponent.d.ts +11 -2
- package/dist/entities/system/defineComponent.js +3 -0
- package/dist/entities/system/link-plan.js +1 -1
- package/dist/entities/system/motion-convert.js +1 -1
- package/dist/entities/system/motion-variants.js +2 -2
- package/dist/framework/Config.d.ts +1 -1
- package/dist/framework/Config.js +13 -4
- package/dist/framework/class-names.js +18 -6
- package/dist/framework/default-conditions.d.ts +26 -0
- package/dist/framework/default-conditions.js +35 -0
- package/dist/framework/defineEntity.js +1 -1
- package/dist/framework/inline-sources.js +1 -1
- package/dist/framework/layer-styles.js +7 -2
- package/dist/framework/plan.js +1 -1
- package/dist/framework/projections.js +18 -5
- package/dist/framework/render-spec.js +10 -2
- package/dist/framework/schema-version.d.ts +1 -1
- package/dist/framework/schema-version.js +5 -5
- package/dist/framework/schemas.js +2 -2
- package/dist/framework/source-integrity.js +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +5 -3
- package/dist/migrations/20261023152030_conditional_defaults.d.ts +6 -0
- package/dist/migrations/20261023152030_conditional_defaults.js +8 -0
- package/dist/spec/bake.js +14 -6
- package/dist/spec/cell.d.ts +2 -1
- package/dist/spec/cell.js +14 -6
- package/dist/spec/detach.js +5 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/capture/node-ops.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { rejectData } from "../framework/rejection.js";
|
|
2
1
|
import { pathOf } from "../framework/utils/refs.js";
|
|
2
|
+
import { rejectData } from "../framework/rejection.js";
|
|
3
3
|
import { pathInput } from "../framework/schemas.js";
|
|
4
4
|
import { CapturedNode } from "./captured-tree.js";
|
|
5
5
|
import { specFromCapture } from "./capture-to-spec.js";
|
package/dist/configs/system.js
CHANGED
|
@@ -29,6 +29,7 @@ import { lintSettingsMigration } from "../migrations/20261020183330_lint_setting
|
|
|
29
29
|
import { directLayerCompositesMigration } from "../migrations/20261022124223_direct_layer_composites.js";
|
|
30
30
|
import { cssContentScriptsMigration } from "../migrations/20261022152120_css_content_scripts.js";
|
|
31
31
|
import { linkTypeMigration } from "../migrations/20261022184639_link_type.js";
|
|
32
|
+
import { conditionalDefaultsMigration } from "../migrations/20261023152030_conditional_defaults.js";
|
|
32
33
|
import { CanvasRole } from "../entities/system/CanvasRole.js";
|
|
33
34
|
import { GlobalStyle } from "../entities/system/GlobalStyle.js";
|
|
34
35
|
import { Guidance } from "../entities/system/Guidance.js";
|
|
@@ -191,5 +192,6 @@ if (!registeredSchemaMigrations().has(20261020183330)) {
|
|
|
191
192
|
}
|
|
192
193
|
if (!registeredSchemaMigrations().has(20261022152120)) registerSchemaMigrations(cssContentScriptsMigration);
|
|
193
194
|
if (!registeredSchemaMigrations().has(20261022184639)) registerSchemaMigrations(linkTypeMigration);
|
|
195
|
+
if (!registeredSchemaMigrations().has(20261023152030)) registerSchemaMigrations(conditionalDefaultsMigration);
|
|
194
196
|
//#endregion
|
|
195
197
|
export { System };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { rejectData } from "../../framework/rejection.js";
|
|
2
1
|
import { pathOf, ref } from "../../framework/utils/refs.js";
|
|
2
|
+
import { rejectData } from "../../framework/rejection.js";
|
|
3
3
|
import { pathInput } from "../../framework/schemas.js";
|
|
4
4
|
import { childrenPolicy } from "../system/element.js";
|
|
5
5
|
import { surfaceProps } from "../../framework/prop-surface.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { rejectData } from "../../framework/rejection.js";
|
|
2
1
|
import { ref } from "../../framework/utils/refs.js";
|
|
2
|
+
import { rejectData } from "../../framework/rejection.js";
|
|
3
3
|
//#region src/entities/canvas/node-patches.ts
|
|
4
4
|
/**
|
|
5
5
|
* A spec as the node rows of one new placed node. A placed node's content is its subtree rows, one
|
|
@@ -9,10 +9,11 @@ import { Named } from "../../framework/named.js";
|
|
|
9
9
|
import { PackageClass } from "./Package.js";
|
|
10
10
|
import { StyleClass } from "./style-bag.js";
|
|
11
11
|
import { TokenClass } from "./Token.js";
|
|
12
|
+
import { StoredDefaultCondition } from "../../framework/default-conditions.js";
|
|
12
13
|
import { StoredPreviewCondition } from "../../framework/preview-store.js";
|
|
13
14
|
import { RepeatSpec } from "../../framework/render-spec.js";
|
|
14
15
|
import { ComponentSourceInput } from "./component-source-fields.js";
|
|
15
|
-
import { AsInput,
|
|
16
|
+
import { AsInput, AuthoredDefaultsOf, LayerMap, PhantomCallProps, PhantomReadProps, PropMap, RenderArgs, StateMap, StyleRuleInput } from "./defineComponent.js";
|
|
16
17
|
import { listSlots, namedSlots, slotHostedBy, slotOf, slotsFor } from "../../spec/slot.js";
|
|
17
18
|
import { cellAt } from "../../spec/cell.js";
|
|
18
19
|
import { instanceAt } from "../../spec/instance.js";
|
|
@@ -658,6 +659,7 @@ declare const componentFields: z.ZodObject<{
|
|
|
658
659
|
renderProps: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
659
660
|
anatomy: z.ZodOptional<AnatomyNodeClass>;
|
|
660
661
|
defaultProps: z.ZodOptional<StyleClass>;
|
|
662
|
+
defaultPropsWhen: z.ZodOptional<z.ZodUnion<readonly [z.ZodPipe<z.ZodArray<z.ZodType<StoredDefaultCondition, unknown, z.core.$ZodTypeInternals<StoredDefaultCondition, unknown>>>, z.ZodTransform<Record<string, StoredDefaultCondition>, StoredDefaultCondition[]>>, SubEntityClass<z.ZodType<StoredDefaultCondition, unknown, z.core.$ZodTypeInternals<StoredDefaultCondition, unknown>>>]>>;
|
|
661
663
|
preview: z.ZodOptional<z.ZodUnion<readonly [z.ZodPipe<z.ZodArray<z.ZodType<StoredPreviewCondition, unknown, z.core.$ZodTypeInternals<StoredPreviewCondition, unknown>>>, z.ZodTransform<Record<string, StoredPreviewCondition>, StoredPreviewCondition[]>>, SubEntityClass<z.ZodType<StoredPreviewCondition, unknown, z.core.$ZodTypeInternals<StoredPreviewCondition, unknown>>>]>>;
|
|
662
664
|
file: z.ZodOptional<z.ZodObject<{
|
|
663
665
|
__ref: z.ZodString;
|
|
@@ -699,6 +701,7 @@ declare const ComponentEntity: EntityClass<z.ZodObject<{
|
|
|
699
701
|
renderProps: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
700
702
|
anatomy: z.ZodOptional<AnatomyNodeClass>;
|
|
701
703
|
defaultProps: z.ZodOptional<StyleClass>;
|
|
704
|
+
defaultPropsWhen: z.ZodOptional<z.ZodUnion<readonly [z.ZodPipe<z.ZodArray<z.ZodType<StoredDefaultCondition, unknown, z.core.$ZodTypeInternals<StoredDefaultCondition, unknown>>>, z.ZodTransform<Record<string, StoredDefaultCondition>, StoredDefaultCondition[]>>, SubEntityClass<z.ZodType<StoredDefaultCondition, unknown, z.core.$ZodTypeInternals<StoredDefaultCondition, unknown>>>]>>;
|
|
702
705
|
preview: z.ZodOptional<z.ZodUnion<readonly [z.ZodPipe<z.ZodArray<z.ZodType<StoredPreviewCondition, unknown, z.core.$ZodTypeInternals<StoredPreviewCondition, unknown>>>, z.ZodTransform<Record<string, StoredPreviewCondition>, StoredPreviewCondition[]>>, SubEntityClass<z.ZodType<StoredPreviewCondition, unknown, z.core.$ZodTypeInternals<StoredPreviewCondition, unknown>>>]>>;
|
|
703
706
|
file: z.ZodOptional<z.ZodObject<{
|
|
704
707
|
__ref: z.ZodString;
|
|
@@ -954,7 +957,7 @@ type ComponentReference<Contract = ComponentContractOf<string>, Path extends str
|
|
|
954
957
|
/** An extension's `defaultProps`, checked against the props it ends up with the way
|
|
955
958
|
* `defineComponent` checks its own: a declared prop takes its values, and any other key stays open. */
|
|
956
959
|
type ExtensionDefaults<Contract, Delta> = {
|
|
957
|
-
readonly defaultProps?:
|
|
960
|
+
readonly defaultProps?: AuthoredDefaultsOf<ResolvedProps<Contract, Delta>>;
|
|
958
961
|
};
|
|
959
962
|
/**
|
|
960
963
|
* Two style rules with the same condition, as the one rule they are: each layer's bag merged, the
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import "../../configs/platform.js";
|
|
2
|
-
import { reject, rejectData } from "../../framework/rejection.js";
|
|
3
|
-
import { canonicalCondition, collectRefs, isRef, kindOf, memberRef, pathOf, ref, refLeaf, refSchema, sourceOf, splitRef } from "../../framework/utils/refs.js";
|
|
4
2
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
3
|
+
import { canonicalCondition, collectRefs, isRef, kindOf, memberRef, pathOf, ref, refLeaf, refSchema, sourceOf, splitRef } from "../../framework/utils/refs.js";
|
|
4
|
+
import { storedDefaultConditions } from "../../framework/default-conditions.js";
|
|
5
|
+
import { reject, rejectData } from "../../framework/rejection.js";
|
|
5
6
|
import { pathInput } from "../../framework/schemas.js";
|
|
6
7
|
import { derivedColor, gradient, oklchColor } from "./color.js";
|
|
7
8
|
import { shadowValue } from "./shadow.js";
|
|
@@ -26,6 +27,7 @@ import { instanceAt } from "../../spec/instance.js";
|
|
|
26
27
|
import { forwardOptions, forwardsWrite } from "./component-forwards.js";
|
|
27
28
|
import { assertComponentSourceInput } from "./component-source-fields.js";
|
|
28
29
|
import { checkStyleSet, styleSetEdits } from "./component-style-set.js";
|
|
30
|
+
import { storedDefaults } from "./conditional-defaults.js";
|
|
29
31
|
import { forwardRouteInvariants, refusedRoutes } from "./forward-route-invariants.js";
|
|
30
32
|
import { iconDomainInvariants } from "./icon-domain-invariants.js";
|
|
31
33
|
import { rootLayerInvariants } from "./root-layer-invariants.js";
|
|
@@ -346,8 +348,16 @@ const VariantValue = defineSubEntity({
|
|
|
346
348
|
* which takes its styling with it. */
|
|
347
349
|
deprecated: z.boolean().optional()
|
|
348
350
|
}),
|
|
349
|
-
namedValuesIn: [
|
|
350
|
-
|
|
351
|
+
namedValuesIn: [
|
|
352
|
+
"defaultProps",
|
|
353
|
+
"preview/*/props",
|
|
354
|
+
"defaultPropsWhen/*/props"
|
|
355
|
+
],
|
|
356
|
+
orphans: [
|
|
357
|
+
"styles",
|
|
358
|
+
"preview",
|
|
359
|
+
"defaultPropsWhen"
|
|
360
|
+
]
|
|
351
361
|
});
|
|
352
362
|
/**
|
|
353
363
|
* A variant's domain: the values it owns, a ref that delegates to whatever owns them, or a list of
|
|
@@ -557,8 +567,16 @@ const Prop = defineSubEntity({
|
|
|
557
567
|
namespaces: "value",
|
|
558
568
|
namesMembersOf: { when: "props" },
|
|
559
569
|
subEntities: { value: VariantValue },
|
|
560
|
-
keyedByNameIn: [
|
|
561
|
-
|
|
570
|
+
keyedByNameIn: [
|
|
571
|
+
"defaultProps",
|
|
572
|
+
"preview/*/props",
|
|
573
|
+
"defaultPropsWhen/*/props"
|
|
574
|
+
],
|
|
575
|
+
orphans: [
|
|
576
|
+
"styles",
|
|
577
|
+
"preview",
|
|
578
|
+
"defaultPropsWhen"
|
|
579
|
+
]
|
|
562
580
|
});
|
|
563
581
|
/** {@link Prop}'s per-owner schema. Reached only through the memo in its `fields`. */
|
|
564
582
|
function propSchemaFor(config, owner) {
|
|
@@ -1168,6 +1186,61 @@ const Preview = defineSubEntity({
|
|
|
1168
1186
|
});
|
|
1169
1187
|
}
|
|
1170
1188
|
});
|
|
1189
|
+
const DEFAULT_CONDITIONS_DESCRIPTION = "Defaults that hold only under a condition on this component's other props, laid over `defaultProps` the way a style rule is over the unconditional one: a list of entries, each identified by its condition. `{ \"when\": { \"modal\": false }, \"props\": { \"includeScrim\": false } }` defaults `includeScrim` to `false` while `modal` is `false`, and to its `defaultProps` value otherwise. When several entries hold, the later one wins on the prop it sets. Both sides name the component's own variant, string, number or boolean props, a prop set here is never part of a condition, and a value the call site passes always wins. Authored as `conditionalDefault(fallback, [{ when, value }])` inside `.defaultProps`.";
|
|
1190
|
+
const defaultConditionShapeError = "a conditional default is `{ \"when\": { \"<prop>\": <value> }, \"props\": { \"<prop>\": <value> } }`: both name this component's own variant, string, number or boolean props (not `as`), `when` at one of their values.";
|
|
1191
|
+
const defaultConditionBase = z.object({
|
|
1192
|
+
when: z.record(z.string(), z.unknown()),
|
|
1193
|
+
props: z.record(z.string(), z.unknown())
|
|
1194
|
+
});
|
|
1195
|
+
const defaultConditionSchemas = /* @__PURE__ */ new WeakMap();
|
|
1196
|
+
/** The props a conditional default may set or condition on: the component's own scalar props, the
|
|
1197
|
+
* ones its module binds and tests. `as` decides the element, so it never depends on another prop. */
|
|
1198
|
+
function conditionallyDefaultable(props) {
|
|
1199
|
+
return Object.entries(props ?? {}).filter(([name, decl]) => {
|
|
1200
|
+
const type = decl?.type;
|
|
1201
|
+
return name !== "as" && (type === "variant" || type === "string" || type === "number" || type === "boolean");
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
/** Whether a conditional default sets nothing: its `props` are empty. */
|
|
1205
|
+
function defaultConditionSetsNothing(entry) {
|
|
1206
|
+
const props = entry?.props;
|
|
1207
|
+
return !props || Object.keys(props).length === 0;
|
|
1208
|
+
}
|
|
1209
|
+
const DefaultCondition = defineSubEntity({
|
|
1210
|
+
name: "defaultCondition",
|
|
1211
|
+
label: "Conditional default",
|
|
1212
|
+
labelPlural: "Conditional defaults",
|
|
1213
|
+
key: (entry) => canonicalWhen(entry?.when),
|
|
1214
|
+
vacant: defaultConditionSetsNothing,
|
|
1215
|
+
namesMembersOf: { when: "props" },
|
|
1216
|
+
base: defaultConditionBase,
|
|
1217
|
+
fields: ({ config, parent }) => {
|
|
1218
|
+
const body = parent;
|
|
1219
|
+
if (!config || !body) return defaultConditionBase;
|
|
1220
|
+
return perOwner({
|
|
1221
|
+
cache: defaultConditionSchemas,
|
|
1222
|
+
config,
|
|
1223
|
+
owner: body,
|
|
1224
|
+
build: () => {
|
|
1225
|
+
const styleField = Style.fields;
|
|
1226
|
+
const when = {};
|
|
1227
|
+
const props = {};
|
|
1228
|
+
for (const [name, decl] of conditionallyDefaultable(body.props)) {
|
|
1229
|
+
when[name] = conditionValue(name, decl, config).optional();
|
|
1230
|
+
props[name] = styleField({
|
|
1231
|
+
config,
|
|
1232
|
+
parent: body,
|
|
1233
|
+
key: name
|
|
1234
|
+
}).optional();
|
|
1235
|
+
}
|
|
1236
|
+
return z.strictObject({
|
|
1237
|
+
when: z.strictObject(when, { error: defaultConditionShapeError }).refine((value) => Object.keys(value).length > 0, { error: "a conditional default holds under a condition; an unconditional one belongs in `defaultProps`." }),
|
|
1238
|
+
props: z.strictObject(props, { error: defaultConditionShapeError })
|
|
1239
|
+
}, { error: defaultConditionShapeError });
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1171
1244
|
/** Why a slot refuses an element, for a write the config turns away. */
|
|
1172
1245
|
function slotRefusal({ slot, element }) {
|
|
1173
1246
|
const named = isRef(element) ? element.__ref : String(element);
|
|
@@ -1724,6 +1797,9 @@ const componentFields = z.strictObject({
|
|
|
1724
1797
|
renderProps: z.array(z.string()).optional().describe("Props the render reads beyond those declared, read off the source at build. Not authored: declare a prop in `props` instead."),
|
|
1725
1798
|
anatomy: AnatomyNode.optional().describe("The tree of what this component renders, keyed by node. Each node names what it renders (a layer, for anything a style rule reaches) and lists its `children`; the node keyed `root` is the top. A one-layer component may omit it. Anatomy read from an extension's own source file replaces the inherited tree; edits to a borrowed render merge into its tree."),
|
|
1726
1799
|
defaultProps: Style.optional(),
|
|
1800
|
+
/** The defaults that hold only under a condition on the component's other props — see
|
|
1801
|
+
* `conditionalDefault`. */
|
|
1802
|
+
defaultPropsWhen: orList(DefaultCondition).optional().describe(DEFAULT_CONDITIONS_DESCRIPTION),
|
|
1727
1803
|
/** What the tile and the matrix render with — see `preview({ defaultProps, when })`. Read off
|
|
1728
1804
|
* `.preview()` at build, and written per cell from the matrix. */
|
|
1729
1805
|
preview: orList(Preview).optional().describe(PREVIEW_DESCRIPTION),
|
|
@@ -1769,6 +1845,39 @@ const componentFields = z.strictObject({
|
|
|
1769
1845
|
message: `\`${name}\` conditions on itself. \`when\` names a sibling prop and one of its values.`
|
|
1770
1846
|
});
|
|
1771
1847
|
}
|
|
1848
|
+
const conditions = storedDefaultConditions(body);
|
|
1849
|
+
const defaulted = new Set(Object.values(conditions).flatMap(({ props }) => Object.keys(props ?? {})));
|
|
1850
|
+
const defaultable = new Set(conditionallyDefaultable(body.props).map(([name]) => name));
|
|
1851
|
+
for (const [key, { when, props }] of Object.entries(conditions)) {
|
|
1852
|
+
for (const [field, names] of [["when", Object.keys(when ?? {})], ["props", Object.keys(props ?? {})]]) for (const name of names) {
|
|
1853
|
+
if (defaultable.has(name)) continue;
|
|
1854
|
+
ctx.issues.push({
|
|
1855
|
+
code: "custom",
|
|
1856
|
+
input: field === "when" ? when : props,
|
|
1857
|
+
path: [
|
|
1858
|
+
"defaultPropsWhen",
|
|
1859
|
+
key,
|
|
1860
|
+
field,
|
|
1861
|
+
name
|
|
1862
|
+
],
|
|
1863
|
+
message: `\`${name}\` isn't one of this component's own variant, string, number or boolean props, so a conditional default can't name it. ${defaultConditionShapeError}`
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
for (const name of Object.keys(when ?? {})) {
|
|
1867
|
+
if (!defaulted.has(name)) continue;
|
|
1868
|
+
ctx.issues.push({
|
|
1869
|
+
code: "custom",
|
|
1870
|
+
input: when,
|
|
1871
|
+
path: [
|
|
1872
|
+
"defaultPropsWhen",
|
|
1873
|
+
key,
|
|
1874
|
+
"when",
|
|
1875
|
+
name
|
|
1876
|
+
],
|
|
1877
|
+
message: `\`${name}\` has a conditional default of its own, so it can't be part of a condition. Condition on the props it depends on instead.`
|
|
1878
|
+
});
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1772
1881
|
if (isPlainObject(body.states) && Object.keys(body.states).length > 0) {
|
|
1773
1882
|
const props = isPlainObject(body.props) ? body.props : {};
|
|
1774
1883
|
if (Object.hasOwn(props, "states")) ctx.issues.push({
|
|
@@ -1905,7 +2014,8 @@ const ComponentEntity = defineEntity({
|
|
|
1905
2014
|
styles: StyleRule,
|
|
1906
2015
|
preview: Preview,
|
|
1907
2016
|
anatomy: AnatomyNode,
|
|
1908
|
-
defaultProps: Style
|
|
2017
|
+
defaultProps: Style,
|
|
2018
|
+
defaultPropsWhen: DefaultCondition
|
|
1909
2019
|
},
|
|
1910
2020
|
computed: {
|
|
1911
2021
|
/**
|
|
@@ -2846,7 +2956,10 @@ function componentRef(path) {
|
|
|
2846
2956
|
*/
|
|
2847
2957
|
const step = (delta) => {
|
|
2848
2958
|
assertComponentSourceInput(delta);
|
|
2849
|
-
const extended = base.extend(
|
|
2959
|
+
const extended = base.extend({
|
|
2960
|
+
...delta,
|
|
2961
|
+
...storedDefaults(delta)
|
|
2962
|
+
});
|
|
2850
2963
|
Object.defineProperty(extended, "render", {
|
|
2851
2964
|
enumerable: false,
|
|
2852
2965
|
configurable: false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { rejectData } from "../../framework/rejection.js";
|
|
2
|
-
import { isRef, kindOf, pathOf, refSchema } from "../../framework/utils/refs.js";
|
|
3
1
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
|
+
import { isRef, kindOf, pathOf, refSchema } from "../../framework/utils/refs.js";
|
|
3
|
+
import { rejectData } from "../../framework/rejection.js";
|
|
4
4
|
import { pathInput } from "../../framework/schemas.js";
|
|
5
5
|
import { kindBorrowable } from "../../framework/registry.js";
|
|
6
6
|
import { defineEntity } from "../../framework/defineEntity.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CONFIG_OPERATION_KIND } from "../../framework/config-operation-kind.js";
|
|
2
1
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
|
+
import { CONFIG_OPERATION_KIND } from "../../framework/config-operation-kind.js";
|
|
3
3
|
import { resolveInputSchema } from "../../framework/schemas.js";
|
|
4
4
|
import { opsForKind } from "../../framework/registry.js";
|
|
5
5
|
import { opOf } from "../../framework/config-op.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { reject } from "../../framework/rejection.js";
|
|
2
1
|
import { isRef, kindOf, memberRef, pathOf } from "../../framework/utils/refs.js";
|
|
2
|
+
import { reject } from "../../framework/rejection.js";
|
|
3
3
|
import { forwardedPropName } from "./element.js";
|
|
4
4
|
import { propOwner, resolveComponentProps } from "../../framework/projections.js";
|
|
5
5
|
import { forwardClaims } from "../../framework/prop-surface.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { rejectData } from "../../framework/rejection.js";
|
|
2
1
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
|
+
import { rejectData } from "../../framework/rejection.js";
|
|
3
3
|
//#region src/entities/system/component-source-fields.ts
|
|
4
4
|
/** Source constructors leave these facts to the render extractor and module build.
|
|
5
5
|
* Stored component bodies, including Create drafts, still carry them. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { reject } from "../../framework/rejection.js";
|
|
2
1
|
import { canonicalCondition } from "../../framework/utils/refs.js";
|
|
2
|
+
import { reject } from "../../framework/rejection.js";
|
|
3
3
|
//#region src/entities/system/component-style-set.ts
|
|
4
4
|
/** A modifier as a style bag keys it: its leaf with a leading `_`. */
|
|
5
5
|
function bagKey(modifier) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { StoredDefaultCondition } from "../../framework/default-conditions.js";
|
|
2
|
+
|
|
3
|
+
//#region src/entities/system/conditional-defaults.d.ts
|
|
4
|
+
declare const CONDITIONAL_DEFAULT: unique symbol;
|
|
5
|
+
/** One condition of a {@link ConditionalDefault}: the value the prop defaults to while `when` holds. */
|
|
6
|
+
interface ConditionalDefaultEntry<V = unknown> {
|
|
7
|
+
readonly when: Readonly<Record<string, unknown>>;
|
|
8
|
+
readonly value: V;
|
|
9
|
+
}
|
|
10
|
+
/** A default chosen by the component's other props — see {@link conditionalDefault}. */
|
|
11
|
+
interface ConditionalDefault<V = unknown> {
|
|
12
|
+
readonly [CONDITIONAL_DEFAULT]: true;
|
|
13
|
+
readonly fallback: V;
|
|
14
|
+
readonly entries: readonly ConditionalDefaultEntry<V>[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A default that depends on the component's other props, for `.defaultProps` and
|
|
18
|
+
* `.extend({ defaultProps })` only.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* .defaultProps({
|
|
22
|
+
* modal: true,
|
|
23
|
+
* includeScrim: conditionalDefault(true, [{ when: { modal: false }, value: false }]),
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* `fallback` applies when no entry's `when` holds; when several hold, the later entry wins. A `when`
|
|
28
|
+
* is the grammar a style rule uses, over the component's own props. A value the call site passes
|
|
29
|
+
* still wins over any of it.
|
|
30
|
+
*/
|
|
31
|
+
declare function conditionalDefault<const V>(fallback: V, entries: readonly ConditionalDefaultEntry<V>[]): ConditionalDefault<V>;
|
|
32
|
+
declare function isConditionalDefault(value: unknown): value is ConditionalDefault;
|
|
33
|
+
/**
|
|
34
|
+
* Stored defaults as authored: the inverse of {@link splitConditionalDefaults}, each prop
|
|
35
|
+
* `defaultPropsWhen` names given back as a {@link conditionalDefault} over its fallback.
|
|
36
|
+
*/
|
|
37
|
+
declare function joinConditionalDefaults({
|
|
38
|
+
defaultProps,
|
|
39
|
+
defaultPropsWhen
|
|
40
|
+
}: {
|
|
41
|
+
defaultProps: Readonly<Record<string, unknown>> | undefined;
|
|
42
|
+
defaultPropsWhen: Readonly<Record<string, StoredDefaultCondition>> | undefined;
|
|
43
|
+
}): Record<string, unknown>;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { ConditionalDefault, ConditionalDefaultEntry, conditionalDefault, isConditionalDefault, joinConditionalDefaults };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
|
+
import { canonicalCondition } from "../../framework/utils/refs.js";
|
|
3
|
+
//#region src/entities/system/conditional-defaults.ts
|
|
4
|
+
const CONDITIONAL_DEFAULT = Symbol.for("uds.conditionalDefault");
|
|
5
|
+
/**
|
|
6
|
+
* A default that depends on the component's other props, for `.defaultProps` and
|
|
7
|
+
* `.extend({ defaultProps })` only.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* .defaultProps({
|
|
11
|
+
* modal: true,
|
|
12
|
+
* includeScrim: conditionalDefault(true, [{ when: { modal: false }, value: false }]),
|
|
13
|
+
* })
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* `fallback` applies when no entry's `when` holds; when several hold, the later entry wins. A `when`
|
|
17
|
+
* is the grammar a style rule uses, over the component's own props. A value the call site passes
|
|
18
|
+
* still wins over any of it.
|
|
19
|
+
*/
|
|
20
|
+
function conditionalDefault(fallback, entries) {
|
|
21
|
+
return {
|
|
22
|
+
[CONDITIONAL_DEFAULT]: true,
|
|
23
|
+
fallback,
|
|
24
|
+
entries
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function isConditionalDefault(value) {
|
|
28
|
+
return typeof value === "object" && value !== null && value[CONDITIONAL_DEFAULT] === true;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Authored defaults as stored: each {@link conditionalDefault} leaves its fallback in `defaultProps`
|
|
32
|
+
* and its entries in `defaultPropsWhen`. `defaultPropsWhen` is `undefined` when nothing was
|
|
33
|
+
* conditional, so a body without one stores exactly what it did before.
|
|
34
|
+
*
|
|
35
|
+
* Stored by condition, every prop shares one order of conditions, while precedence is per prop. The
|
|
36
|
+
* order taken keeps each prop's own; two props that order the same two conditions oppositely can't
|
|
37
|
+
* share one, and are refused.
|
|
38
|
+
*/
|
|
39
|
+
function splitConditionalDefaults(authored) {
|
|
40
|
+
const defaultProps = {};
|
|
41
|
+
const perProp = /* @__PURE__ */ new Map();
|
|
42
|
+
for (const [prop, value] of Object.entries(authored)) {
|
|
43
|
+
if (!isConditionalDefault(value)) {
|
|
44
|
+
defaultProps[prop] = value;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (value.fallback !== void 0) defaultProps[prop] = value.fallback;
|
|
48
|
+
const entries = /* @__PURE__ */ new Map();
|
|
49
|
+
for (const entry of value.entries) {
|
|
50
|
+
const key = canonicalCondition(entry.when);
|
|
51
|
+
entries.delete(key);
|
|
52
|
+
entries.set(key, entry);
|
|
53
|
+
}
|
|
54
|
+
perProp.set(prop, entries);
|
|
55
|
+
}
|
|
56
|
+
if (perProp.size === 0) return { defaultProps };
|
|
57
|
+
const order = conditionOrder(perProp);
|
|
58
|
+
const defaultPropsWhen = {};
|
|
59
|
+
for (const key of order) {
|
|
60
|
+
let when;
|
|
61
|
+
const props = {};
|
|
62
|
+
for (const [prop, entries] of perProp) {
|
|
63
|
+
const entry = entries.get(key);
|
|
64
|
+
if (!entry) continue;
|
|
65
|
+
when ??= { ...entry.when };
|
|
66
|
+
props[prop] = entry.value;
|
|
67
|
+
}
|
|
68
|
+
if (when) defaultPropsWhen[key] = {
|
|
69
|
+
when,
|
|
70
|
+
props
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
defaultProps,
|
|
75
|
+
defaultPropsWhen
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* `defaultProps` as stored: each `conditionalDefault` splits into its fallback, which stays in
|
|
80
|
+
* `defaultProps`, and its conditions, which go to `defaultPropsWhen`. Empty for a body whose
|
|
81
|
+
* defaults are all plain, so it stores what it did before.
|
|
82
|
+
*/
|
|
83
|
+
function storedDefaults(body) {
|
|
84
|
+
if (!isPlainObject(body.defaultProps)) return {};
|
|
85
|
+
const { defaultProps, defaultPropsWhen } = splitConditionalDefaults(body.defaultProps);
|
|
86
|
+
return defaultPropsWhen ? {
|
|
87
|
+
defaultProps,
|
|
88
|
+
defaultPropsWhen
|
|
89
|
+
} : {};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* One order of every condition that keeps each prop's own order, by first appearance where props
|
|
93
|
+
* don't constrain it.
|
|
94
|
+
*/
|
|
95
|
+
function conditionOrder(perProp) {
|
|
96
|
+
const seen = [];
|
|
97
|
+
const after = /* @__PURE__ */ new Map();
|
|
98
|
+
for (const [prop, entries] of perProp) {
|
|
99
|
+
const keys = [...entries.keys()];
|
|
100
|
+
keys.forEach((key, at) => {
|
|
101
|
+
if (!seen.includes(key)) seen.push(key);
|
|
102
|
+
const earlier = after.get(key) ?? /* @__PURE__ */ new Map();
|
|
103
|
+
for (const before of keys.slice(0, at)) earlier.set(before, prop);
|
|
104
|
+
after.set(key, earlier);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
for (const [key, earlier] of after) for (const [before, prop] of earlier) {
|
|
108
|
+
const other = after.get(before)?.get(key);
|
|
109
|
+
if (other === void 0) continue;
|
|
110
|
+
throw new Error(`\`${prop}\` puts \`${before}\` before \`${key}\` and \`${other}\` puts them the other way round. Conditional defaults share one order of conditions, so give both props the same order.`);
|
|
111
|
+
}
|
|
112
|
+
const order = [];
|
|
113
|
+
const placed = /* @__PURE__ */ new Set();
|
|
114
|
+
const placing = /* @__PURE__ */ new Set();
|
|
115
|
+
const place = (key) => {
|
|
116
|
+
if (placed.has(key)) return;
|
|
117
|
+
if (placing.has(key)) throw new Error(`Conditional defaults order \`${key}\` both before and after another condition across their props. They share one order of conditions, so give every prop the same order.`);
|
|
118
|
+
placing.add(key);
|
|
119
|
+
for (const before of after.get(key)?.keys() ?? []) place(before);
|
|
120
|
+
placing.delete(key);
|
|
121
|
+
placed.add(key);
|
|
122
|
+
order.push(key);
|
|
123
|
+
};
|
|
124
|
+
for (const key of seen) place(key);
|
|
125
|
+
return order;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Stored defaults as authored: the inverse of {@link splitConditionalDefaults}, each prop
|
|
129
|
+
* `defaultPropsWhen` names given back as a {@link conditionalDefault} over its fallback.
|
|
130
|
+
*/
|
|
131
|
+
function joinConditionalDefaults({ defaultProps, defaultPropsWhen }) {
|
|
132
|
+
const out = { ...defaultProps };
|
|
133
|
+
const entries = /* @__PURE__ */ new Map();
|
|
134
|
+
for (const { when, props } of Object.values(defaultPropsWhen ?? {})) for (const [prop, value] of Object.entries(props ?? {})) entries.set(prop, [...entries.get(prop) ?? [], {
|
|
135
|
+
when,
|
|
136
|
+
value
|
|
137
|
+
}]);
|
|
138
|
+
for (const [prop, list] of entries) out[prop] = conditionalDefault(out[prop], list);
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { conditionalDefault, isConditionalDefault, joinConditionalDefaults, storedDefaults };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { rejectData } from "../../framework/rejection.js";
|
|
2
1
|
import { MINTED, collectRefs, isMintedRow, kindOf, pathOf, rewriteRefs, sourceOf, splitRef } from "../../framework/utils/refs.js";
|
|
2
|
+
import { rejectData } from "../../framework/rejection.js";
|
|
3
3
|
import { kindBorrowable } from "../../framework/registry.js";
|
|
4
4
|
import { File } from "./File.js";
|
|
5
5
|
import { componentModuleFilePaths, componentRegistryImports } from "./component-module.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isRef, kindOf, pathOf } from "../../framework/utils/refs.js";
|
|
2
1
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
|
+
import { isRef, kindOf, pathOf } from "../../framework/utils/refs.js";
|
|
3
3
|
import { createSliceMemo } from "../../framework/memo.js";
|
|
4
4
|
import { drawnMotionBody, drawnMotionName } from "./drawn-motion.js";
|
|
5
5
|
import { convertMotion } from "./motion-convert.js";
|
|
@@ -3,6 +3,7 @@ import { RegisteredComponentHandles, RegisteredGroupPaths, RegisteredModifiers,
|
|
|
3
3
|
import { Authored } from "../../framework/authoring.js";
|
|
4
4
|
import { StyleValue } from "./style-bag.js";
|
|
5
5
|
import { ComponentSourceInput } from "./component-source-fields.js";
|
|
6
|
+
import { ConditionalDefault } from "./conditional-defaults.js";
|
|
6
7
|
import { VariantValues } from "./Component.js";
|
|
7
8
|
import { AllHTMLAttributes, ComponentPropsWithRef, ComponentType, ElementType, JSX, ReactElement, ReactNode, Ref } from "react";
|
|
8
9
|
|
|
@@ -663,6 +664,11 @@ type ForwardedPropsOf<L extends LayerMap, F extends string> = [NonRootForward<L,
|
|
|
663
664
|
type DefaultsOf<P extends PropMap> = Partial<DeclaredProps<P>> & {
|
|
664
665
|
[key: string]: unknown;
|
|
665
666
|
};
|
|
667
|
+
/** {@link DefaultsOf} as `.defaultProps` takes it: a declared prop other than `as` may also default
|
|
668
|
+
* through {@link conditionalDefault}. */
|
|
669
|
+
type AuthoredDefaultsOf<P extends PropMap> = { [K in keyof DeclaredProps<P>]?: K extends 'as' ? DeclaredProps<P>[K] : DeclaredProps<P>[K] | ConditionalDefault<DeclaredProps<P>[K]> } & {
|
|
670
|
+
[key: string]: unknown;
|
|
671
|
+
};
|
|
666
672
|
/**
|
|
667
673
|
* `T` without the keys in `K` — `Omit` that leaves an index signature alone.
|
|
668
674
|
*
|
|
@@ -778,8 +784,11 @@ F extends string = never, /** The states `.states()` declared — what the rende
|
|
|
778
784
|
*
|
|
779
785
|
* `const`, so an `as` keeps its literal type: without it `{ as: 'input' }` widens to `string` and
|
|
780
786
|
* there's no tag left to resolve the element's props against.
|
|
787
|
+
*
|
|
788
|
+
* A default that depends on another prop is a `conditionalDefault`:
|
|
789
|
+
* `includeScrim: conditionalDefault(true, [{ when: { modal: false }, value: false }])`.
|
|
781
790
|
*/
|
|
782
|
-
defaultProps<const D2 extends
|
|
791
|
+
defaultProps<const D2 extends AuthoredDefaultsOf<P>>(defaults: D2): ComponentBuilder<L, P, E, D2, F, S>;
|
|
783
792
|
/**
|
|
784
793
|
* The layers whose element props this component ALSO exposes, keyed by layer.
|
|
785
794
|
*
|
|
@@ -892,4 +901,4 @@ interface DefineComponent {
|
|
|
892
901
|
declare function definePropsFirst<const P extends PropMap<LayerPath>>(props: P & NoInfer<{ [K in keyof P]: Exact<P[K], AuthoredProp<LayerPath>> }>): ComponentBuilder<LayerMap, P>;
|
|
893
902
|
declare const defineComponent: DefineComponent;
|
|
894
903
|
//#endregion
|
|
895
|
-
export { AsInput, AuthoredComponent, AuthoredProp, ComponentBuilder, ComponentPropsOf,
|
|
904
|
+
export { AsInput, AuthoredComponent, AuthoredDefaultsOf, AuthoredProp, ComponentBuilder, ComponentPropsOf, GlyphComponent, GlyphValue, LayerElement, LayerMap, LinkedHandle, PhantomCallProps, PhantomReadProps, PropCondition, PropDecl, PropMap, RegisteredMembers, RenderArgs, SlotCodeForm, SlotDecl, StateMap, StyleRuleInput, defineComponent };
|
|
@@ -2,6 +2,7 @@ import { canonicalCondition, isRef, kindOf, memberRef, pathOf } from "../../fram
|
|
|
2
2
|
import { glyphIdentityOf, glyphPackageRefOf, isComponentType } from "./glyph-identity.js";
|
|
3
3
|
import "../../framework/preview-store.js";
|
|
4
4
|
import { assertComponentSourceInput } from "./component-source-fields.js";
|
|
5
|
+
import { isConditionalDefault, storedDefaults } from "./conditional-defaults.js";
|
|
5
6
|
import { Component, layerRef, storedStyleRules } from "./Component.js";
|
|
6
7
|
//#region src/entities/system/defineComponent.ts
|
|
7
8
|
function build(body) {
|
|
@@ -145,6 +146,7 @@ function storableElement(value) {
|
|
|
145
146
|
*/
|
|
146
147
|
function storableValue(value) {
|
|
147
148
|
if (value === null) return null;
|
|
149
|
+
if (isConditionalDefault(value)) throw new Error("`conditionalDefault` is a default, so it goes in `.defaultProps` or `.extend({ defaultProps })`. A preview conditions its props with `.preview({ when: [{ when, props }] })`.");
|
|
148
150
|
const type = typeof value;
|
|
149
151
|
if (type === "string" || type === "number" || type === "boolean") return value;
|
|
150
152
|
if (isComponentType(value)) return storableComponentRef(value);
|
|
@@ -388,6 +390,7 @@ function toStored(body) {
|
|
|
388
390
|
if (Object.keys(keyed).length === 0) delete stored.preview;
|
|
389
391
|
else stored.preview = keyed;
|
|
390
392
|
}
|
|
393
|
+
Object.assign(stored, storedDefaults(body));
|
|
391
394
|
if (body.props && typeof body.props === "object") {
|
|
392
395
|
const props = {};
|
|
393
396
|
for (const [name, decl] of Object.entries(body.props)) props[name] = storedProp(decl, body.layers);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isConfigRejection, rejectData } from "../../framework/rejection.js";
|
|
2
1
|
import { collectRefs, isMintedRow, ref, sourceOf, splitRef } from "../../framework/utils/refs.js";
|
|
2
|
+
import { isConfigRejection, rejectData } from "../../framework/rejection.js";
|
|
3
3
|
import { blockedBy } from "../../framework/plan.js";
|
|
4
4
|
import { excludedCondition } from "../../framework/source-integrity.js";
|
|
5
5
|
import { PIN_KIND, covers, declarationOf, entriesFor, excludePaths, excludes, includePaths, narrowDeclaration } from "./link-declaration.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isRef } from "../../framework/utils/refs.js";
|
|
2
1
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
|
+
import { isRef } from "../../framework/utils/refs.js";
|
|
3
3
|
import { MOTION_EASING_NAMES, bezierPoints, motionOfCssKeyword } from "./easings.js";
|
|
4
4
|
import { cssEasing } from "./css-timing.js";
|
|
5
5
|
import { JS_ONLY_FIELDS } from "./Motion.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { reject } from "../../framework/rejection.js";
|
|
2
|
-
import { isRef, kindOf, pathOf } from "../../framework/utils/refs.js";
|
|
3
1
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
|
+
import { isRef, kindOf, pathOf } from "../../framework/utils/refs.js";
|
|
3
|
+
import { reject } from "../../framework/rejection.js";
|
|
4
4
|
import { createSliceMemo } from "../../framework/memo.js";
|
|
5
5
|
import { drawnMotionBody, drawnMotionName } from "./drawn-motion.js";
|
|
6
6
|
import { webMotionBody } from "./motion-types.js";
|
|
@@ -73,7 +73,7 @@ interface RecordedSource {
|
|
|
73
73
|
* The dense-counter `2` a short-lived scheme stamped before the chain existed reads as the mint
|
|
74
74
|
* that replaced it (see `detectedWireVersion`).
|
|
75
75
|
*/
|
|
76
|
-
declare const SERIALIZED_CONFIG_VERSION =
|
|
76
|
+
declare const SERIALIZED_CONFIG_VERSION = 20261023152030;
|
|
77
77
|
interface SerializedConfig {
|
|
78
78
|
/** See {@link SERIALIZED_CONFIG_VERSION}. Always written; a stored artifact may lack it. */
|
|
79
79
|
readonly version: number;
|