@yahoo/uds-create-config 4.27.0 → 4.28.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/configs/system.js +2 -0
- package/dist/entities/system/CanvasRole.d.ts +6 -11
- package/dist/entities/system/CanvasRole.js +7 -11
- package/dist/framework/Config.d.ts +1 -1
- package/dist/framework/Config.js +1 -1
- package/dist/framework/schema-version.d.ts +1 -1
- package/dist/framework/schema-version.js +5 -5
- package/dist/migrations/20260925143319_canvas_role_slot.d.ts +12 -0
- package/dist/migrations/20260925143319_canvas_role_slot.js +8 -0
- package/dist/spec/instance.d.ts +4 -3
- package/dist/spec/instance.js +5 -4
- package/dist/spec/slot.d.ts +9 -6
- package/dist/spec/slot.js +15 -12
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/configs/system.js
CHANGED
|
@@ -41,6 +41,7 @@ import { transitionTokenValueMigration } from "../migrations/20260923144958_tran
|
|
|
41
41
|
import { renderTokenRefsMigration } from "../migrations/20260923160425_render_token_refs.js";
|
|
42
42
|
import { globalStyleDerivedColorsMigration } from "../migrations/20260923163604_global_style_derived_colors.js";
|
|
43
43
|
import { slotCodeFormsMigration } from "../migrations/20260924044539_slot_code_forms.js";
|
|
44
|
+
import { canvasRoleSlotMigration } from "../migrations/20260925143319_canvas_role_slot.js";
|
|
44
45
|
//#region src/configs/system.ts
|
|
45
46
|
/**
|
|
46
47
|
* `System` — the design-system config TYPE. Declares the exact kinds a design system owns (tokens,
|
|
@@ -102,5 +103,6 @@ if (!registeredSchemaMigrations().has(20260923144958)) registerSchemaMigrations(
|
|
|
102
103
|
if (!registeredSchemaMigrations().has(20260923160425)) registerSchemaMigrations(renderTokenRefsMigration);
|
|
103
104
|
if (!registeredSchemaMigrations().has(20260923163604)) registerSchemaMigrations(globalStyleDerivedColorsMigration);
|
|
104
105
|
if (!registeredSchemaMigrations().has(20260924044539)) registerSchemaMigrations(slotCodeFormsMigration);
|
|
106
|
+
if (!registeredSchemaMigrations().has(20260925143319)) registerSchemaMigrations(canvasRoleSlotMigration);
|
|
105
107
|
//#endregion
|
|
106
108
|
export { System };
|
|
@@ -3,19 +3,14 @@ import { z } from "zod";
|
|
|
3
3
|
|
|
4
4
|
//#region src/entities/system/CanvasRole.d.ts
|
|
5
5
|
/**
|
|
6
|
-
* The roles a canvas has a tool for
|
|
6
|
+
* The roles a canvas has a tool for, the vocabulary a design system fills in. A role a config leaves
|
|
7
|
+
* unregistered has no entries, and its tool is disabled rather than falling back to a guess; what
|
|
8
|
+
* fills a role is whichever component the config points at, never a name the editor chose.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* naming a role here offers the slot without asserting anything fills it, and what fills it is
|
|
11
|
-
* never a name the editor chose — it is whichever component the config pointed at.
|
|
12
|
-
*
|
|
13
|
-
* The names live here, with the entity, because the entity is what they are names OF. They were
|
|
14
|
-
* previously kept in `@yahoo/uds-create-platform-types` as a hand-maintained copy, annotated as
|
|
15
|
-
* one ("mirrors `@yahoo/uds-create-config`'s `CanvasRole` union without importing it") — a second
|
|
16
|
-
* source of truth wearing a comment admitting it.
|
|
10
|
+
* `slot` is the one role no toolbar draws with. Its entries are the host layers a component's new
|
|
11
|
+
* slot property can start as, and an entry's `defaultProps` are the props that layer starts with.
|
|
17
12
|
*/
|
|
18
|
-
declare const CANVAS_ROLES: readonly ["frame", "text", "image", "icon"];
|
|
13
|
+
declare const CANVAS_ROLES: readonly ["frame", "text", "image", "icon", "slot"];
|
|
19
14
|
type CanvasRoleName = (typeof CANVAS_ROLES)[number];
|
|
20
15
|
declare const CanvasRole: EntityClass<z.ZodObject<{
|
|
21
16
|
entries: z.ZodArray<z.ZodObject<{
|
|
@@ -15,23 +15,19 @@ import { z } from "zod";
|
|
|
15
15
|
* });
|
|
16
16
|
*/
|
|
17
17
|
/**
|
|
18
|
-
* The roles a canvas has a tool for
|
|
18
|
+
* The roles a canvas has a tool for, the vocabulary a design system fills in. A role a config leaves
|
|
19
|
+
* unregistered has no entries, and its tool is disabled rather than falling back to a guess; what
|
|
20
|
+
* fills a role is whichever component the config points at, never a name the editor chose.
|
|
19
21
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* naming a role here offers the slot without asserting anything fills it, and what fills it is
|
|
23
|
-
* never a name the editor chose — it is whichever component the config pointed at.
|
|
24
|
-
*
|
|
25
|
-
* The names live here, with the entity, because the entity is what they are names OF. They were
|
|
26
|
-
* previously kept in `@yahoo/uds-create-platform-types` as a hand-maintained copy, annotated as
|
|
27
|
-
* one ("mirrors `@yahoo/uds-create-config`'s `CanvasRole` union without importing it") — a second
|
|
28
|
-
* source of truth wearing a comment admitting it.
|
|
22
|
+
* `slot` is the one role no toolbar draws with. Its entries are the host layers a component's new
|
|
23
|
+
* slot property can start as, and an entry's `defaultProps` are the props that layer starts with.
|
|
29
24
|
*/
|
|
30
25
|
const CANVAS_ROLES = [
|
|
31
26
|
"frame",
|
|
32
27
|
"text",
|
|
33
28
|
"image",
|
|
34
|
-
"icon"
|
|
29
|
+
"icon",
|
|
30
|
+
"slot"
|
|
35
31
|
];
|
|
36
32
|
const CanvasRole = defineEntity({
|
|
37
33
|
kind: "canvas-role",
|
|
@@ -72,7 +72,7 @@ interface RecordedSource {
|
|
|
72
72
|
* The dense-counter `2` a short-lived scheme stamped before the chain existed reads as the mint
|
|
73
73
|
* that replaced it (see `detectedWireVersion`).
|
|
74
74
|
*/
|
|
75
|
-
declare const SERIALIZED_CONFIG_VERSION =
|
|
75
|
+
declare const SERIALIZED_CONFIG_VERSION = 20260925143319;
|
|
76
76
|
interface SerializedConfig {
|
|
77
77
|
/** See {@link SERIALIZED_CONFIG_VERSION}. Always written; a stored artifact may lack it. */
|
|
78
78
|
readonly version: number;
|
package/dist/framework/Config.js
CHANGED
|
@@ -4883,7 +4883,7 @@ var Config = class Config {
|
|
|
4883
4883
|
* links from the provided sources. A declared `linkedKind` with no provided source throws. */
|
|
4884
4884
|
hydrateFrom(stored, options) {
|
|
4885
4885
|
const claimed = schemaVersionOf(stored);
|
|
4886
|
-
if (claimed >
|
|
4886
|
+
if (claimed > 20260925143319) throw new SchemaVersionTooNew(claimed);
|
|
4887
4887
|
const wire = upgradeSerializedConfig(stored);
|
|
4888
4888
|
if (!Array.isArray(wire.ownedKinds) || typeof wire.items !== "object" || wire.items === null) throw new ConfigFormatError(`Config "${stored.name ?? "system-config"}" cannot be hydrated: this is not a serialized config-v2 config (no "ownedKinds"/"items"). A pre-cutover build artifact converts through the registered cutover migration — import the config type's module (e.g. \`configs/system\`) before hydrating, or port the repo once with \`uds migrate\`.`);
|
|
4889
4889
|
const leftover = wire.options;
|
|
@@ -15,7 +15,7 @@ import { Patch, SerializedConfig } from "./Config.js";
|
|
|
15
15
|
* sets this constant to its own older timestamp; the merge ref then carries a registered migration
|
|
16
16
|
* newer than the constant, and the assertion fails until the author re-mints.
|
|
17
17
|
*/
|
|
18
|
-
declare const CURRENT_SCHEMA_VERSION =
|
|
18
|
+
declare const CURRENT_SCHEMA_VERSION = 20260925143319;
|
|
19
19
|
/** What the walkers need to see of an envelope — loose on purpose, so a typed `SerializedConfig`
|
|
20
20
|
* and a raw old-shape record both flow in without casts. */
|
|
21
21
|
interface VersionStamped {
|
|
@@ -13,7 +13,7 @@ import { ConfigFormatError } from "./rejection.js";
|
|
|
13
13
|
* sets this constant to its own older timestamp; the merge ref then carries a registered migration
|
|
14
14
|
* newer than the constant, and the assertion fails until the author re-mints.
|
|
15
15
|
*/
|
|
16
|
-
const CURRENT_SCHEMA_VERSION =
|
|
16
|
+
const CURRENT_SCHEMA_VERSION = 20260925143319;
|
|
17
17
|
/** The mint that moved `options` into the `settings` kind — restated here, rather than imported
|
|
18
18
|
* from the migration that owns it, because that migration imports this module. */
|
|
19
19
|
const SETTINGS_AS_KIND_VERSION = 20260908171448;
|
|
@@ -45,7 +45,7 @@ function registerSchemaMigrations(...migrations) {
|
|
|
45
45
|
for (const migration of migrations) {
|
|
46
46
|
if (migration.version !== 1 && !isMintTimestamp(migration.version)) throw new Error(`Schema migration version ${migration.version} is not a mint timestamp — mint one with \`date +%Y%m%d%H%M%S\`, like a supabase migration.`);
|
|
47
47
|
if (REGISTERED.has(migration.version)) throw new Error(`A schema migration at version ${migration.version} is already registered.`);
|
|
48
|
-
if (migration.version >
|
|
48
|
+
if (migration.version > 20260925143319) throw new Error(`Schema migration ${migration.version} is newer than CURRENT_SCHEMA_VERSION (${CURRENT_SCHEMA_VERSION}) — a stale branch merged, or the mint forgot to bump the constant. Re-mint: set CURRENT_SCHEMA_VERSION to the newest migration version.`);
|
|
49
49
|
REGISTERED.set(migration.version, migration);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -102,7 +102,7 @@ function pendingFor(version, target, options) {
|
|
|
102
102
|
* Already-current input passes through untouched — same reference, so hot paths pay nothing.
|
|
103
103
|
*/
|
|
104
104
|
function upgradeSerializedConfig(json, options) {
|
|
105
|
-
const target = options?.target ??
|
|
105
|
+
const target = options?.target ?? 20260925143319;
|
|
106
106
|
const version = detectedWireVersion(json);
|
|
107
107
|
if (version > target) throw new SchemaVersionTooNew(version, target);
|
|
108
108
|
const raw = json;
|
|
@@ -160,7 +160,7 @@ function upgradedSources(json, options) {
|
|
|
160
160
|
* meaning under the current schema and replay skips it — reported by the caller, not swallowed here.
|
|
161
161
|
*/
|
|
162
162
|
function upgradePatch(patch, writtenAt, options) {
|
|
163
|
-
const target = options?.target ??
|
|
163
|
+
const target = options?.target ?? 20260925143319;
|
|
164
164
|
if (writtenAt > target) throw new SchemaVersionTooNew(writtenAt, target);
|
|
165
165
|
let current = patch;
|
|
166
166
|
for (const migration of pendingFor(writtenAt, target, options)) {
|
|
@@ -179,7 +179,7 @@ function upgradePatch(patch, writtenAt, options) {
|
|
|
179
179
|
* stamp would cause.
|
|
180
180
|
*/
|
|
181
181
|
function upgradeDraftEntries(draft, options) {
|
|
182
|
-
const target = options?.target ??
|
|
182
|
+
const target = options?.target ?? 20260925143319;
|
|
183
183
|
const entries = [];
|
|
184
184
|
const held = [];
|
|
185
185
|
const retired = [];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An additive fence: `slot` joins the canvas roles, naming the host layer a new slot property starts
|
|
3
|
+
* as. No stored byte moves.
|
|
4
|
+
*
|
|
5
|
+
* Identity, so a stamp below this version means "may lack these fields" and one at it means they
|
|
6
|
+
* are understood, which is what lets the pull gate keep an older client from stripping them.
|
|
7
|
+
*
|
|
8
|
+
* Deletable once no stored config artifact is below this version.
|
|
9
|
+
*/
|
|
10
|
+
import type { SchemaMigration } from '../framework/schema-version';
|
|
11
|
+
export declare const CANVAS_ROLE_SLOT_VERSION = 20260925143319;
|
|
12
|
+
export declare const canvasRoleSlotMigration: SchemaMigration;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/migrations/20260925143319_canvas_role_slot.ts
|
|
2
|
+
const CANVAS_ROLE_SLOT_VERSION = 20260925143319;
|
|
3
|
+
const canvasRoleSlotMigration = {
|
|
4
|
+
version: CANVAS_ROLE_SLOT_VERSION,
|
|
5
|
+
up: (json) => json
|
|
6
|
+
};
|
|
7
|
+
//#endregion
|
|
8
|
+
export { CANVAS_ROLE_SLOT_VERSION, canvasRoleSlotMigration };
|
package/dist/spec/instance.d.ts
CHANGED
|
@@ -38,7 +38,8 @@ declare class Instance {
|
|
|
38
38
|
get slots(): readonly InstanceSlot[];
|
|
39
39
|
/** The slot a prop names, or `undefined` when the prop is no slot. */
|
|
40
40
|
slot(prop: string): InstanceSlot | undefined;
|
|
41
|
-
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none
|
|
41
|
+
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none; a slot on
|
|
42
|
+
* the root is hosted by no layer, as {@link slotHostedBy} says. */
|
|
42
43
|
slotHostedBy(layer: string): InstanceSlot | undefined;
|
|
43
44
|
/** The slot holding the element `childKey`, or `undefined` when it holds none of this instance's. */
|
|
44
45
|
slotHolding(childKey: string): InstanceSlot | undefined;
|
|
@@ -58,8 +59,8 @@ declare function instanceAt({
|
|
|
58
59
|
}): Instance | undefined;
|
|
59
60
|
/**
|
|
60
61
|
* The instance and slot holding the element `childKey`, or `undefined` when no instance in the spec
|
|
61
|
-
* holds it in a slot. A
|
|
62
|
-
*
|
|
62
|
+
* holds it in a slot. A component that takes children on its root holds them in its `children`
|
|
63
|
+
* slot, whose `onRoot` says the slot is no level of its own.
|
|
63
64
|
*/
|
|
64
65
|
declare function instanceHolding({
|
|
65
66
|
config,
|
package/dist/spec/instance.js
CHANGED
|
@@ -37,9 +37,10 @@ var Instance = class {
|
|
|
37
37
|
slot(prop) {
|
|
38
38
|
return this.slots.find((entry) => entry.slot.from === prop);
|
|
39
39
|
}
|
|
40
|
-
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none
|
|
40
|
+
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none; a slot on
|
|
41
|
+
* the root is hosted by no layer, as {@link slotHostedBy} says. */
|
|
41
42
|
slotHostedBy(layer) {
|
|
42
|
-
return this.slots.find((entry) => entry.slot.layer === layer);
|
|
43
|
+
return this.slots.find((entry) => entry.slot.layer === layer && !entry.slot.onRoot);
|
|
43
44
|
}
|
|
44
45
|
/** The slot holding the element `childKey`, or `undefined` when it holds none of this instance's. */
|
|
45
46
|
slotHolding(childKey) {
|
|
@@ -58,8 +59,8 @@ function instanceAt({ config, spec, elementKey }) {
|
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
61
|
* The instance and slot holding the element `childKey`, or `undefined` when no instance in the spec
|
|
61
|
-
* holds it in a slot. A
|
|
62
|
-
*
|
|
62
|
+
* holds it in a slot. A component that takes children on its root holds them in its `children`
|
|
63
|
+
* slot, whose `onRoot` says the slot is no level of its own.
|
|
63
64
|
*/
|
|
64
65
|
function instanceHolding({ config, spec, childKey }) {
|
|
65
66
|
if (!spec) return void 0;
|
package/dist/spec/slot.d.ts
CHANGED
|
@@ -26,8 +26,11 @@ declare class Slot implements SlotTarget {
|
|
|
26
26
|
readonly accepts: readonly string[];
|
|
27
27
|
/** Built by {@link listSlots}; a surface reaches one through `Component.slots` or `Component.slot`. */
|
|
28
28
|
constructor(config: Config, component: string, facts: SlotFacts);
|
|
29
|
-
/** Whether this is the component's `children
|
|
29
|
+
/** Whether this is the component's `children`. */
|
|
30
30
|
get isChildren(): boolean;
|
|
31
|
+
/** Whether the content lands on the component's root layer, so an instance holds it directly
|
|
32
|
+
* rather than in a layer of its own. */
|
|
33
|
+
get onRoot(): boolean;
|
|
31
34
|
/**
|
|
32
35
|
* Whether the slot takes an element: anything when it accepts nothing in particular, else an
|
|
33
36
|
* element whose ref one of the accepted refs names, exactly or as a member of a group the ref
|
|
@@ -162,10 +165,9 @@ declare class Slot implements SlotTarget {
|
|
|
162
165
|
private writeSource;
|
|
163
166
|
}
|
|
164
167
|
/**
|
|
165
|
-
* Every slot of a component that content can be placed in
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* same array comes back for the same config.
|
|
168
|
+
* Every slot of a component that content can be placed in, `children` included wherever it lands.
|
|
169
|
+
* A text slot is typed in place rather than filled, so it is not one. The same array comes back for
|
|
170
|
+
* the same config.
|
|
169
171
|
*/
|
|
170
172
|
declare function listSlots({
|
|
171
173
|
config,
|
|
@@ -192,7 +194,8 @@ declare function slotOf({
|
|
|
192
194
|
path: string;
|
|
193
195
|
slot: string;
|
|
194
196
|
}): Slot | undefined;
|
|
195
|
-
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none.
|
|
197
|
+
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none. A root
|
|
198
|
+
* layer stands for the instance itself, so a slot on the root is listed but hosted by no layer. */
|
|
196
199
|
declare function slotHostedBy({
|
|
197
200
|
config,
|
|
198
201
|
path,
|
package/dist/spec/slot.js
CHANGED
|
@@ -47,10 +47,16 @@ var Slot = class {
|
|
|
47
47
|
this.into = facts.into;
|
|
48
48
|
this.accepts = facts.accepts;
|
|
49
49
|
}
|
|
50
|
-
/** Whether this is the component's `children
|
|
50
|
+
/** Whether this is the component's `children`. */
|
|
51
51
|
get isChildren() {
|
|
52
52
|
return this.from === "children";
|
|
53
53
|
}
|
|
54
|
+
/** Whether the content lands on the component's root layer, so an instance holds it directly
|
|
55
|
+
* rather than in a layer of its own. */
|
|
56
|
+
get onRoot() {
|
|
57
|
+
const layers = (this.config.resolve("component", this.component)?.body)?.layers;
|
|
58
|
+
return layers !== void 0 && rootLayerOf(layers)[0] === this.layer;
|
|
59
|
+
}
|
|
54
60
|
/**
|
|
55
61
|
* Whether the slot takes an element: anything when it accepts nothing in particular, else an
|
|
56
62
|
* element whose ref one of the accepted refs names, exactly or as a member of a group the ref
|
|
@@ -282,10 +288,9 @@ var Slot = class {
|
|
|
282
288
|
}
|
|
283
289
|
};
|
|
284
290
|
/**
|
|
285
|
-
* Every slot of a component that content can be placed in
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
* same array comes back for the same config.
|
|
291
|
+
* Every slot of a component that content can be placed in, `children` included wherever it lands.
|
|
292
|
+
* A text slot is typed in place rather than filled, so it is not one. The same array comes back for
|
|
293
|
+
* the same config.
|
|
289
294
|
*/
|
|
290
295
|
function listSlots({ config, path }) {
|
|
291
296
|
let byPath = listsByConfig.get(config);
|
|
@@ -313,12 +318,13 @@ function slotOf({ config, path, slot }) {
|
|
|
313
318
|
path
|
|
314
319
|
}).find((entry) => entry.from === slot);
|
|
315
320
|
}
|
|
316
|
-
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none.
|
|
321
|
+
/** The slot whose content lands in `layer`, or `undefined` when the layer hosts none. A root
|
|
322
|
+
* layer stands for the instance itself, so a slot on the root is listed but hosted by no layer. */
|
|
317
323
|
function slotHostedBy({ config, path, layer }) {
|
|
318
324
|
return listSlots({
|
|
319
325
|
config,
|
|
320
326
|
path
|
|
321
|
-
}).find((entry) => entry.layer === layer);
|
|
327
|
+
}).find((entry) => entry.layer === layer && !entry.onRoot);
|
|
322
328
|
}
|
|
323
329
|
/** A list stored back the way content is authored: one element bare, several as the list. */
|
|
324
330
|
function storedContent(list) {
|
|
@@ -483,13 +489,10 @@ function slotFacts(config, path) {
|
|
|
483
489
|
function factsOfBody({ config, body, routes }) {
|
|
484
490
|
const props = body.props;
|
|
485
491
|
const layers = body.layers;
|
|
486
|
-
|
|
492
|
+
return routes.filter((route) => {
|
|
487
493
|
if ((props?.[route.from])?.text === true) return false;
|
|
488
494
|
return !routesToText(config, layers, route);
|
|
489
|
-
})
|
|
490
|
-
const root = layers ? rootLayerOf(layers)[0] : void 0;
|
|
491
|
-
const positionedChildren = layers !== void 0 && Object.keys(layers).length >= 2;
|
|
492
|
-
return fillable.filter((route) => route.from !== "children" || positionedChildren && route.layer !== root).map((route) => ({
|
|
495
|
+
}).map((route) => ({
|
|
493
496
|
...route,
|
|
494
497
|
accepts: acceptsOf({
|
|
495
498
|
config,
|