@yahoo/uds-create-config 5.52.1 → 5.53.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/entities/system/LinkedSystem.js +4 -4
- package/dist/entities/system/Motion.js +2 -1
- package/dist/entities/system/component-module.d.ts +7 -1
- package/dist/entities/system/component-module.js +15 -2
- package/dist/entities/system/css-motion-reach.js +19 -11
- package/dist/entities/system/css-motion.d.ts +5 -1
- package/dist/entities/system/css-motion.js +25 -3
- package/dist/entities/system/drawn-motion.d.ts +29 -0
- package/dist/entities/system/drawn-motion.js +77 -0
- package/dist/entities/system/motion-presets.d.ts +4 -3
- package/dist/entities/system/motion-presets.js +44 -5
- package/dist/entities/system/motion-variants.js +13 -4
- package/dist/framework/class-names.d.ts +52 -3
- package/dist/framework/class-names.js +119 -36
- package/dist/framework/module-views.d.ts +15 -0
- package/dist/framework/module-views.js +13 -0
- package/dist/framework/projections.d.ts +17 -1
- package/dist/framework/projections.js +21 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/spec/motion.d.ts +2 -1
- package/dist/spec/motion.js +2 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -749,11 +749,11 @@ const LinkedSystemDefinition = defineEntity({
|
|
|
749
749
|
* `Popover` over the v3 Bridge keeps the product's tokens from the Bridge, and the Popover renders
|
|
750
750
|
* Yahoo OS's own Button. Once the old link is gone, the new one can become `linked`.
|
|
751
751
|
*
|
|
752
|
-
*
|
|
753
|
-
*
|
|
754
|
-
*
|
|
752
|
+
* The same holds for the motion presets and composites a taken component names: through a
|
|
753
|
+
* `hybrid` link it plays this system's of that name, and otherwise the source's own, emitted
|
|
754
|
+
* under the pin's names.
|
|
755
755
|
*/
|
|
756
|
-
type: z.enum(["linked", "hybrid"]).optional().describe("How this source joins the system: `linked` (the default) brings in everything its entities reference and refuses a path another link offers differently; `hybrid` brings in only what no other link offers and uses this system's tokens wherever it has one of the same name."),
|
|
756
|
+
type: z.enum(["linked", "hybrid"]).optional().describe("How this source joins the system: `linked` (the default) brings in everything its entities reference and refuses a path another link offers differently; `hybrid` brings in only what no other link offers and uses this system's tokens, motion presets and composites wherever it has one of the same name."),
|
|
757
757
|
/**
|
|
758
758
|
* The exact published version every ref through this link resolves against.
|
|
759
759
|
*
|
|
@@ -3,6 +3,7 @@ import { isRef, refSchema } from "../../framework/utils/refs.js";
|
|
|
3
3
|
import { METADATA_KEYS } from "../../framework/utils/field-schema.js";
|
|
4
4
|
import { pathInput } from "../../framework/schemas.js";
|
|
5
5
|
import { defineEntity } from "../../framework/defineEntity.js";
|
|
6
|
+
import { drawnMotionBody } from "./drawn-motion.js";
|
|
6
7
|
import { authoredValue } from "../../framework/projections.js";
|
|
7
8
|
import { convertMotion } from "./motion-convert.js";
|
|
8
9
|
import { cssMotionValue, motionTransition, reanimatedMotion, webMotionBody } from "./motion-types.js";
|
|
@@ -213,7 +214,7 @@ const Motion = defineEntity({
|
|
|
213
214
|
], { error: "a layer's `motion` is a preset (`Motion.ref('<path>')`) or a JS preset written in place — `{ \"whileHover\": { \"scale\": 1.05 }, \"transition\": { … } }`, the fields `Motion.item` takes with `runtime: 'js'`. A CSS preset is named with `Motion.item`." }),
|
|
214
215
|
reach: ({ config, value, element }) => {
|
|
215
216
|
if (isNativeConfig(config)) return "prop";
|
|
216
|
-
const preset = config
|
|
217
|
+
const preset = drawnMotionBody(config, String(authoredValue(config, "motion", value)));
|
|
217
218
|
if (preset?.type === "react-native-reanimated") throw new Error("No UDS web motion integration for react-native-reanimated. Select a supported preset or disable motion.");
|
|
218
219
|
return preset && webMotionBody(preset).runtime === "css" && isRef(element) ? "prop" : "none";
|
|
219
220
|
},
|
|
@@ -107,17 +107,23 @@ declare function componentModuleSource(config: Config, componentPathOrRef: strin
|
|
|
107
107
|
*
|
|
108
108
|
* One view for the browser's module key, the server's build and the CLI's borrowed modules, so the
|
|
109
109
|
* three name the same classes and hash the same config.
|
|
110
|
+
*
|
|
111
|
+
* The view records the consumer and pin it was built for ({@link moduleViewOf}), so a motion preset
|
|
112
|
+
* its components name is drawn as the consumer draws it. `route` is the pin as the consumer spells
|
|
113
|
+
* it when the owner is reached through another link (`bridge~yos`); `slug` alone names classes.
|
|
110
114
|
*/
|
|
111
115
|
declare function linkedModuleView({
|
|
112
116
|
consumer,
|
|
113
117
|
owner,
|
|
114
118
|
slug,
|
|
115
|
-
shadowed
|
|
119
|
+
shadowed,
|
|
120
|
+
route
|
|
116
121
|
}: {
|
|
117
122
|
readonly consumer: Config;
|
|
118
123
|
readonly owner: Config;
|
|
119
124
|
readonly slug: string;
|
|
120
125
|
readonly shadowed: boolean;
|
|
126
|
+
readonly route?: string;
|
|
121
127
|
}): Config;
|
|
122
128
|
/**
|
|
123
129
|
* A linked component's module source, and the config its module is built from.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isNativeConfig } from "../../configs/platform.js";
|
|
2
2
|
import { isRef, kindOf, pathOf, ref, routedSource, sourceHops, splitRef } from "../../framework/utils/refs.js";
|
|
3
3
|
import { createSliceMemo } from "../../framework/memo.js";
|
|
4
|
+
import { registerModuleView } from "../../framework/module-views.js";
|
|
4
5
|
import { File } from "./File.js";
|
|
5
6
|
import { Settings, classPrefixOf, prefixed, varPrefixOf } from "./Settings.js";
|
|
6
7
|
import { Component } from "./Component.js";
|
|
@@ -339,13 +340,17 @@ function componentModuleSource(config, componentPathOrRef) {
|
|
|
339
340
|
*
|
|
340
341
|
* One view for the browser's module key, the server's build and the CLI's borrowed modules, so the
|
|
341
342
|
* three name the same classes and hash the same config.
|
|
343
|
+
*
|
|
344
|
+
* The view records the consumer and pin it was built for ({@link moduleViewOf}), so a motion preset
|
|
345
|
+
* its components name is drawn as the consumer draws it. `route` is the pin as the consumer spells
|
|
346
|
+
* it when the owner is reached through another link (`bridge~yos`); `slug` alone names classes.
|
|
342
347
|
*/
|
|
343
|
-
function linkedModuleView({ consumer, owner, slug, shadowed }) {
|
|
348
|
+
function linkedModuleView({ consumer, owner, slug, shadowed, route = slug }) {
|
|
344
349
|
const classNames = shadowed ? prefixed({
|
|
345
350
|
prefix: classPrefixOf(consumer),
|
|
346
351
|
name: slug
|
|
347
352
|
}) : classPrefixOf(consumer);
|
|
348
|
-
|
|
353
|
+
const view = owner.apply({
|
|
349
354
|
kind: "settings",
|
|
350
355
|
operation: "update",
|
|
351
356
|
path: "settings",
|
|
@@ -354,6 +359,14 @@ function linkedModuleView({ consumer, owner, slug, shadowed }) {
|
|
|
354
359
|
variables: varPrefixOf(owner)
|
|
355
360
|
} }
|
|
356
361
|
});
|
|
362
|
+
if (view !== owner) registerModuleView({
|
|
363
|
+
view,
|
|
364
|
+
link: {
|
|
365
|
+
consumer,
|
|
366
|
+
slug: route
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
return view;
|
|
357
370
|
}
|
|
358
371
|
/** Views are built per consumer, owner, slug and shadowing, since every linked component of one owner
|
|
359
372
|
* shares one. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isRef, kindOf, pathOf } from "../../framework/utils/refs.js";
|
|
2
2
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
3
3
|
import { createSliceMemo } from "../../framework/memo.js";
|
|
4
|
+
import { drawnMotionBody, drawnMotionName } from "./drawn-motion.js";
|
|
4
5
|
import { convertMotion } from "./motion-convert.js";
|
|
5
6
|
import { webMotionBody } from "./motion-types.js";
|
|
6
7
|
import { placedMotions, variantGroupsOf } from "./motion-variants.js";
|
|
@@ -31,11 +32,6 @@ function unmountableLayers(config, path) {
|
|
|
31
32
|
}
|
|
32
33
|
return out;
|
|
33
34
|
}
|
|
34
|
-
/** The preset a layer bag's `motion` names, by path. */
|
|
35
|
-
function namedPreset(value) {
|
|
36
|
-
if (isRef(value)) return pathOf(value);
|
|
37
|
-
return typeof value === "string" ? value : void 0;
|
|
38
|
-
}
|
|
39
35
|
/**
|
|
40
36
|
* Whether a layer's element wears a CSS preset's class: a plain element through its class list, and a
|
|
41
37
|
* component through the `motion` value its layer is handed, which the component's style-prop runtime
|
|
@@ -46,14 +42,18 @@ function wears(element) {
|
|
|
46
42
|
return isRef(element) && kindOf(element) === "component";
|
|
47
43
|
}
|
|
48
44
|
const resolvePlacements = createSliceMemo({
|
|
49
|
-
kinds: [
|
|
45
|
+
kinds: [
|
|
46
|
+
"component",
|
|
47
|
+
"motion",
|
|
48
|
+
"linked-system"
|
|
49
|
+
],
|
|
50
50
|
compute: (config) => {
|
|
51
51
|
const out = [];
|
|
52
52
|
const seen = /* @__PURE__ */ new Set();
|
|
53
53
|
for (const component of config.list("component")) {
|
|
54
54
|
const { layers = {}, styles = {} } = component.toJSON();
|
|
55
55
|
for (const entry of Object.values(styles)) for (const [layer, bag] of Object.entries(entry?.layers ?? {})) {
|
|
56
|
-
const preset =
|
|
56
|
+
const preset = drawnMotionName(config, isPlainObject(bag) ? bag.motion : void 0);
|
|
57
57
|
if (preset === void 0) continue;
|
|
58
58
|
if (motionBodyAt(config, preset)?.runtime !== "css" || !(layer in layers)) continue;
|
|
59
59
|
const key = `${component.path}\u0000${layer}\u0000${preset}`;
|
|
@@ -80,14 +80,22 @@ function cssMotionPlacements(config) {
|
|
|
80
80
|
* variants its states name only to presets in its own group.
|
|
81
81
|
*/
|
|
82
82
|
const cssMotionVariantGroups = createSliceMemo({
|
|
83
|
-
kinds: [
|
|
83
|
+
kinds: [
|
|
84
|
+
"component",
|
|
85
|
+
"motion",
|
|
86
|
+
"linked-system"
|
|
87
|
+
],
|
|
84
88
|
compute: (config) => variantGroupsOf({
|
|
85
89
|
config,
|
|
86
90
|
placements: cssMotionPlacements(config)
|
|
87
91
|
})
|
|
88
92
|
});
|
|
89
93
|
const resolveExits = createSliceMemo({
|
|
90
|
-
kinds: [
|
|
94
|
+
kinds: [
|
|
95
|
+
"component",
|
|
96
|
+
"motion",
|
|
97
|
+
"linked-system"
|
|
98
|
+
],
|
|
91
99
|
compute: (config) => {
|
|
92
100
|
const out = [];
|
|
93
101
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -95,7 +103,7 @@ const resolveExits = createSliceMemo({
|
|
|
95
103
|
const { styles = {} } = component.toJSON();
|
|
96
104
|
let unmountable;
|
|
97
105
|
for (const entry of Object.values(styles)) for (const [layer, bag] of Object.entries(entry?.layers ?? {})) {
|
|
98
|
-
const preset =
|
|
106
|
+
const preset = drawnMotionName(config, isPlainObject(bag) ? bag.motion : void 0);
|
|
99
107
|
if (preset === void 0) continue;
|
|
100
108
|
const body = motionBodyAt(config, preset);
|
|
101
109
|
if (body?.runtime !== "css" || body.exit === void 0) continue;
|
|
@@ -193,7 +201,7 @@ function linkedMotionSwaps(config) {
|
|
|
193
201
|
return resolveLinkedSwaps(config);
|
|
194
202
|
}
|
|
195
203
|
function motionBodyAt(config, path) {
|
|
196
|
-
const body = config
|
|
204
|
+
const body = drawnMotionBody(config, path);
|
|
197
205
|
return body ? webMotionBody(body) : void 0;
|
|
198
206
|
}
|
|
199
207
|
//#endregion
|
|
@@ -33,7 +33,11 @@ interface CssMotionKeyframeList {
|
|
|
33
33
|
/** Where the list sits, as a dotted path: `variants.show.scale`. */
|
|
34
34
|
readonly at: string;
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Every CSS preset that animates states, by the name it plays under, with the timing of each value per
|
|
38
|
+
* destination: this config's presets, and each linked source's it plays under the pin's name
|
|
39
|
+
* ({@link linkedMotionPresets}), whose tokens are read in the source.
|
|
40
|
+
*/
|
|
37
41
|
declare function cssMotionTransitions(config: Config): Readonly<Record<string, CssMotionTransitions>>;
|
|
38
42
|
/**
|
|
39
43
|
* How long a CSS preset's `exit` takes, in milliseconds: the longest of its values' durations and
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
2
2
|
import { createSliceMemo } from "../../framework/memo.js";
|
|
3
|
+
import { drawnMotionBody, linkedMotionPresets } from "./drawn-motion.js";
|
|
3
4
|
import { cssEasing, easingCurve, linearEasing, springTiming } from "./css-timing.js";
|
|
4
5
|
import { webMotionBody } from "./motion-types.js";
|
|
5
6
|
import { stateVariantNames } from "./motion-variants.js";
|
|
@@ -418,10 +419,31 @@ const resolveCssMotionPresets = createSliceMemo({
|
|
|
418
419
|
};
|
|
419
420
|
}
|
|
420
421
|
});
|
|
421
|
-
/**
|
|
422
|
+
/**
|
|
423
|
+
* Every CSS preset that animates states, by the name it plays under, with the timing of each value per
|
|
424
|
+
* destination: this config's presets, and each linked source's it plays under the pin's name
|
|
425
|
+
* ({@link linkedMotionPresets}), whose tokens are read in the source.
|
|
426
|
+
*/
|
|
422
427
|
function cssMotionTransitions(config) {
|
|
423
|
-
|
|
428
|
+
const own = resolveCssMotionPresets(config).transitions;
|
|
429
|
+
const linked = linkedMotionPresets(config);
|
|
430
|
+
if (linked.length === 0) return own;
|
|
431
|
+
const hit = withLinkedTransitions.get(config);
|
|
432
|
+
if (hit) return hit;
|
|
433
|
+
const out = { ...own };
|
|
434
|
+
for (const preset of linked) {
|
|
435
|
+
const body = webMotionBody(preset.body);
|
|
436
|
+
if (body.runtime !== "css" || !hasStates(body)) continue;
|
|
437
|
+
out[preset.name] = transitionsOf({
|
|
438
|
+
config: preset.source,
|
|
439
|
+
body,
|
|
440
|
+
report: () => {}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
withLinkedTransitions.set(config, out);
|
|
444
|
+
return out;
|
|
424
445
|
}
|
|
446
|
+
const withLinkedTransitions = /* @__PURE__ */ new WeakMap();
|
|
425
447
|
/**
|
|
426
448
|
* How long a CSS preset's `exit` takes, in milliseconds: the longest of its values' durations and
|
|
427
449
|
* delays as the element changes to its exit state. `0` for a preset with no exit, and a timing that is
|
|
@@ -443,7 +465,7 @@ function cssMotionTokens(config) {
|
|
|
443
465
|
return resolveCssMotionPresets(config).tokens;
|
|
444
466
|
}
|
|
445
467
|
function motionBodyAt(config, path) {
|
|
446
|
-
const body = config
|
|
468
|
+
const body = drawnMotionBody(config, path);
|
|
447
469
|
return body ? webMotionBody(body) : void 0;
|
|
448
470
|
}
|
|
449
471
|
//#endregion
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Config } from "../../framework/Config.js";
|
|
2
|
+
|
|
3
|
+
//#region src/entities/system/drawn-motion.d.ts
|
|
4
|
+
/** A linked source's preset this config plays under the pin's name. */
|
|
5
|
+
interface LinkedMotionPreset {
|
|
6
|
+
/** `<path>@<slug>`: the name a motion value plays it by. */
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly slug: string;
|
|
9
|
+
/** Its path in the source. */
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly body: Record<string, unknown>;
|
|
12
|
+
/** The source, which the tokens its body names resolve in. */
|
|
13
|
+
readonly source: Config;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The name the preset a `motion` value names plays under in `config`: a path of `config`'s own, or a
|
|
17
|
+
* source's preset as `<path>@<slug>`. A module view reads its owner's names, and draws them as the
|
|
18
|
+
* consumer it was built for does.
|
|
19
|
+
*/
|
|
20
|
+
declare function drawnMotionName(config: Config, value: unknown): string | undefined;
|
|
21
|
+
/** The body of the preset `name` plays ({@link drawnMotionName}), from whichever config holds it. */
|
|
22
|
+
declare function drawnMotionBody(config: Config, name: string): Record<string, unknown> | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Every linked preset `config` plays under its pin's name: each preset a reached source holds that
|
|
25
|
+
* this config's refs reach, unless the link draws it with a row of this config's own.
|
|
26
|
+
*/
|
|
27
|
+
declare function linkedMotionPresets(config: Config): readonly LinkedMotionPreset[];
|
|
28
|
+
//#endregion
|
|
29
|
+
export { LinkedMotionPreset, drawnMotionBody, drawnMotionName, linkedMotionPresets };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { isRef, pathOf, ref, routedSource, sourceOf } from "../../framework/utils/refs.js";
|
|
2
|
+
import { moduleViewOf } from "../../framework/module-views.js";
|
|
3
|
+
import { linkedLocalRow } from "../../framework/projections.js";
|
|
4
|
+
//#region src/entities/system/drawn-motion.ts
|
|
5
|
+
/**
|
|
6
|
+
* The name the preset a `motion` value names plays under in `config`: a path of `config`'s own, or a
|
|
7
|
+
* source's preset as `<path>@<slug>`. A module view reads its owner's names, and draws them as the
|
|
8
|
+
* consumer it was built for does.
|
|
9
|
+
*/
|
|
10
|
+
function drawnMotionName(config, value) {
|
|
11
|
+
let named;
|
|
12
|
+
if (isRef(value)) named = value.__ref;
|
|
13
|
+
else if (typeof value === "string") named = value;
|
|
14
|
+
if (named === void 0) return void 0;
|
|
15
|
+
const path = pathOf(named);
|
|
16
|
+
const slug = sourceOf(named);
|
|
17
|
+
const view = moduleViewOf(config);
|
|
18
|
+
if (!view) return slug === void 0 ? path : linkedName({
|
|
19
|
+
config,
|
|
20
|
+
slug,
|
|
21
|
+
path
|
|
22
|
+
});
|
|
23
|
+
return linkedName({
|
|
24
|
+
config: view.consumer,
|
|
25
|
+
slug: slug === void 0 ? view.slug : routedSource(view.slug, slug),
|
|
26
|
+
path
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** The body of the preset `name` plays ({@link drawnMotionName}), from whichever config holds it. */
|
|
30
|
+
function drawnMotionBody(config, name) {
|
|
31
|
+
const at = moduleViewOf(config)?.consumer ?? config;
|
|
32
|
+
return (sourceOf(name) === void 0 ? at.resolve("motion", name) : at.resolveRef(ref("motion", name)))?.toJSON();
|
|
33
|
+
}
|
|
34
|
+
function linkedName({ config, slug, path }) {
|
|
35
|
+
return linkedLocalRow({
|
|
36
|
+
config,
|
|
37
|
+
slug,
|
|
38
|
+
kind: "motion",
|
|
39
|
+
path
|
|
40
|
+
}) ?? `${path}@${slug}`;
|
|
41
|
+
}
|
|
42
|
+
const linkedPresets = /* @__PURE__ */ new WeakMap();
|
|
43
|
+
/**
|
|
44
|
+
* Every linked preset `config` plays under its pin's name: each preset a reached source holds that
|
|
45
|
+
* this config's refs reach, unless the link draws it with a row of this config's own.
|
|
46
|
+
*/
|
|
47
|
+
function linkedMotionPresets(config) {
|
|
48
|
+
const hit = linkedPresets.get(config);
|
|
49
|
+
if (hit) return hit;
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const slug of config.reachedSlugs()) {
|
|
52
|
+
const source = config.sourceFor(slug);
|
|
53
|
+
if (!source) continue;
|
|
54
|
+
for (const target of config.sourceClosure(slug, "motion")) {
|
|
55
|
+
const path = pathOf(target);
|
|
56
|
+
if (linkedLocalRow({
|
|
57
|
+
config,
|
|
58
|
+
slug,
|
|
59
|
+
kind: "motion",
|
|
60
|
+
path
|
|
61
|
+
}) !== void 0) continue;
|
|
62
|
+
const body = source.resolve("motion", path)?.toJSON();
|
|
63
|
+
if (body) out.push({
|
|
64
|
+
name: `${path}@${slug}`,
|
|
65
|
+
slug,
|
|
66
|
+
path,
|
|
67
|
+
body,
|
|
68
|
+
source
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
out.sort((a, b) => a.name.localeCompare(b.name));
|
|
73
|
+
linkedPresets.set(config, out);
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { drawnMotionBody, drawnMotionName, linkedMotionPresets };
|
|
@@ -34,9 +34,10 @@ declare function hasJsMotion(config: Config): boolean;
|
|
|
34
34
|
/** The tokens JS presets name that a preset cannot carry as one value, for the build to report. */
|
|
35
35
|
declare function motionPresetTokens(config: Config): MotionPresetToken[];
|
|
36
36
|
/**
|
|
37
|
-
* Each preset's own `reducedMotion`, the default for a layer that plays it and sets none, by
|
|
38
|
-
* the named presets of either runtime,
|
|
37
|
+
* Each preset's own `reducedMotion`, the default for a layer that plays it and sets none, by the name
|
|
38
|
+
* it plays under: the named presets of either runtime, each linked source's this config plays under
|
|
39
|
+
* the pin's name, and the JS presets a style rule writes in place by their id.
|
|
39
40
|
*/
|
|
40
|
-
declare
|
|
41
|
+
declare function presetReducedMotions(config: Config): Readonly<Record<string, ReducedMotion>>;
|
|
41
42
|
//#endregion
|
|
42
43
|
export { MOTION_PACKAGE, MotionPresetToken, hasJsMotion, inlineMotionProps, jsMotionPresets, motionPresetTokens, presetReducedMotions };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { collectRefs, isRef, kindOf, pathOf, refOfKey } from "../../framework/utils/refs.js";
|
|
2
2
|
import { composedValueFormOf } from "./composed-values.js";
|
|
3
3
|
import { createSliceMemo } from "../../framework/memo.js";
|
|
4
|
+
import { linkedMotionPresets } from "./drawn-motion.js";
|
|
4
5
|
import { tokenValueRow } from "./token-values.js";
|
|
5
6
|
import { MOTION_EASING_NAMES, bezierPoints, motionOfCssKeyword } from "./easings.js";
|
|
6
7
|
import { webMotionBody } from "./motion-types.js";
|
|
@@ -241,7 +242,27 @@ const resolveJsMotionPresets = createSliceMemo({
|
|
|
241
242
|
* a style rule sets is the one exception: it reaches `motion/react` as its `var()`.
|
|
242
243
|
*/
|
|
243
244
|
function jsMotionPresets(config) {
|
|
244
|
-
return
|
|
245
|
+
return withLinkedPresets(config).presets;
|
|
246
|
+
}
|
|
247
|
+
const linkedJsPresets = /* @__PURE__ */ new WeakMap();
|
|
248
|
+
/**
|
|
249
|
+
* {@link resolveJsMotionPresets}, with each linked source's JS preset this config plays under the
|
|
250
|
+
* pin's name ({@link linkedMotionPresets}), its tokens read in the source.
|
|
251
|
+
*/
|
|
252
|
+
function withLinkedPresets(config) {
|
|
253
|
+
const own = resolveJsMotionPresets(config);
|
|
254
|
+
const linked = linkedMotionPresets(config).filter((preset) => webMotionBody(preset.body).type === "motion/react");
|
|
255
|
+
if (linked.length === 0) return own;
|
|
256
|
+
const hit = linkedJsPresets.get(config);
|
|
257
|
+
if (hit) return hit;
|
|
258
|
+
const presets = { ...own.presets };
|
|
259
|
+
for (const preset of linked) presets[preset.name] = resolveBody(preset.source, preset.name, webMotionBody(preset.body), []);
|
|
260
|
+
const out = {
|
|
261
|
+
...own,
|
|
262
|
+
presets
|
|
263
|
+
};
|
|
264
|
+
linkedJsPresets.set(config, out);
|
|
265
|
+
return out;
|
|
245
266
|
}
|
|
246
267
|
/** Every JS preset a style rule writes in place, by its id, resolved as {@link jsMotionPresets} are. */
|
|
247
268
|
function inlineMotionProps(config) {
|
|
@@ -252,7 +273,7 @@ const MOTION_PACKAGE = "motion";
|
|
|
252
273
|
/** Whether anything in the system animates through `motion/react`: a JS preset, named or written in
|
|
253
274
|
* place in a style rule. */
|
|
254
275
|
function hasJsMotion(config) {
|
|
255
|
-
const { presets, inline } =
|
|
276
|
+
const { presets, inline } = withLinkedPresets(config);
|
|
256
277
|
return Object.keys(presets).length > 0 || Object.keys(inline).length > 0;
|
|
257
278
|
}
|
|
258
279
|
/** The tokens JS presets name that a preset cannot carry as one value, for the build to report. */
|
|
@@ -260,10 +281,28 @@ function motionPresetTokens(config) {
|
|
|
260
281
|
return resolveJsMotionPresets(config).tokens;
|
|
261
282
|
}
|
|
262
283
|
/**
|
|
263
|
-
* Each preset's own `reducedMotion`, the default for a layer that plays it and sets none, by
|
|
264
|
-
* the named presets of either runtime,
|
|
284
|
+
* Each preset's own `reducedMotion`, the default for a layer that plays it and sets none, by the name
|
|
285
|
+
* it plays under: the named presets of either runtime, each linked source's this config plays under
|
|
286
|
+
* the pin's name, and the JS presets a style rule writes in place by their id.
|
|
265
287
|
*/
|
|
266
|
-
|
|
288
|
+
function presetReducedMotions(config) {
|
|
289
|
+
const own = ownReducedMotions(config);
|
|
290
|
+
const linked = linkedMotionPresets(config).flatMap((preset) => {
|
|
291
|
+
const { reducedMotion } = webMotionBody(preset.body);
|
|
292
|
+
return isReducedMotion(reducedMotion) ? [[preset.name, reducedMotion]] : [];
|
|
293
|
+
});
|
|
294
|
+
if (linked.length === 0) return own;
|
|
295
|
+
const hit = linkedReducedMotions.get(config);
|
|
296
|
+
if (hit) return hit;
|
|
297
|
+
const out = {
|
|
298
|
+
...own,
|
|
299
|
+
...Object.fromEntries(linked)
|
|
300
|
+
};
|
|
301
|
+
linkedReducedMotions.set(config, out);
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
const linkedReducedMotions = /* @__PURE__ */ new WeakMap();
|
|
305
|
+
const ownReducedMotions = createSliceMemo({
|
|
267
306
|
kinds: ["motion", "component"],
|
|
268
307
|
compute: (config) => {
|
|
269
308
|
const out = {};
|
|
@@ -2,6 +2,7 @@ import { reject } from "../../framework/rejection.js";
|
|
|
2
2
|
import { isRef, kindOf, pathOf } from "../../framework/utils/refs.js";
|
|
3
3
|
import { isPlainObject } from "../../framework/utils/field-path.js";
|
|
4
4
|
import { createSliceMemo } from "../../framework/memo.js";
|
|
5
|
+
import { drawnMotionBody, drawnMotionName } from "./drawn-motion.js";
|
|
5
6
|
import { webMotionBody } from "./motion-types.js";
|
|
6
7
|
import { inlineJsMotion } from "./Motion.js";
|
|
7
8
|
//#region src/entities/system/motion-variants.ts
|
|
@@ -90,14 +91,18 @@ function namedVariants(body) {
|
|
|
90
91
|
}
|
|
91
92
|
/** Every JS preset a style rule puts on a layer, across the system. */
|
|
92
93
|
const placedMotions = createSliceMemo({
|
|
93
|
-
kinds: [
|
|
94
|
+
kinds: [
|
|
95
|
+
"component",
|
|
96
|
+
"motion",
|
|
97
|
+
"linked-system"
|
|
98
|
+
],
|
|
94
99
|
compute: (config) => {
|
|
95
100
|
const out = [];
|
|
96
101
|
for (const component of config.list("component")) {
|
|
97
102
|
const { styles = {} } = component.toJSON();
|
|
98
103
|
for (const [rule, entry] of Object.entries(styles)) for (const [layer, bag] of Object.entries(entry?.layers ?? {})) {
|
|
99
104
|
const named = bag?.motion;
|
|
100
|
-
const preset =
|
|
105
|
+
const preset = isInlineMotion(named) ? inlineMotionId(component.path, rule, layer) : drawnMotionName(config, named);
|
|
101
106
|
if (preset === void 0 || !jsBody(config, preset)) continue;
|
|
102
107
|
out.push({
|
|
103
108
|
component: component.path,
|
|
@@ -123,7 +128,11 @@ const composedComponents = (config, path) => {
|
|
|
123
128
|
* nothing joins nothing, which keeps Button and Checkbox apart although both render Box.
|
|
124
129
|
*/
|
|
125
130
|
const motionVariantGroups = createSliceMemo({
|
|
126
|
-
kinds: [
|
|
131
|
+
kinds: [
|
|
132
|
+
"component",
|
|
133
|
+
"motion",
|
|
134
|
+
"linked-system"
|
|
135
|
+
],
|
|
127
136
|
compute: (config) => variantGroupsOf({
|
|
128
137
|
config,
|
|
129
138
|
placements: placedMotions(config)
|
|
@@ -283,7 +292,7 @@ function orphanedMotionVariants(config) {
|
|
|
283
292
|
return out;
|
|
284
293
|
}
|
|
285
294
|
function motionBodyAt(config, path) {
|
|
286
|
-
const body = config
|
|
295
|
+
const body = drawnMotionBody(config, path);
|
|
287
296
|
return body ? webMotionBody(body) : void 0;
|
|
288
297
|
}
|
|
289
298
|
function renamePresetBody(config, path, body, from, to) {
|
|
@@ -138,9 +138,18 @@ declare function componentRuleClasses(config: Config, path: string): ComponentRu
|
|
|
138
138
|
* composite contributes no declarations there, so omitting it would drop the class entirely.
|
|
139
139
|
*/
|
|
140
140
|
declare function componentCompositeClasses(config: Config, path: string): ComponentRuleClass[];
|
|
141
|
-
/**
|
|
142
|
-
*
|
|
141
|
+
/**
|
|
142
|
+
* The class a CSS motion preset is applied by. Namespaced, so it doesn't share a space with the
|
|
143
|
+
* style-prop utilities; the `@keyframes` it runs keep their own name ({@link motionKeyframesName}).
|
|
144
|
+
*
|
|
145
|
+
* `path` is a name {@link drawnMotionName} gives: a linked source's preset played under the pin's
|
|
146
|
+
* name is qualified by the pin (`uds-ds-motion-fade` for `fade@ds`), and a module view's names are
|
|
147
|
+
* its consumer's classes.
|
|
148
|
+
*/
|
|
143
149
|
declare function motionClassName(config: Config, path: string): string;
|
|
150
|
+
/** The `@keyframes` a CSS preset runs: `uds-fade`, or `uds-ds-fade` for a linked source's preset
|
|
151
|
+
* played under the pin's name. */
|
|
152
|
+
declare function motionKeyframesName(config: Config, path: string): string;
|
|
144
153
|
/**
|
|
145
154
|
* Every MOTION class a component's style rules apply — a layer bag naming a preset (`motion: 'spin'`).
|
|
146
155
|
*
|
|
@@ -207,6 +216,46 @@ declare function componentPropComposites(config: Config, path: string, state?: R
|
|
|
207
216
|
* plain-tag layer (which declares nothing) and a key naming no member are left as they are.
|
|
208
217
|
*/
|
|
209
218
|
declare function inlineRuleComposites(config: Config, element: unknown, authored: Record<string, unknown>): Record<string, unknown>;
|
|
219
|
+
/**
|
|
220
|
+
* The composites a rule's bag names that are drawn with another config's row, taken out of the bag.
|
|
221
|
+
*
|
|
222
|
+
* A linked component's rule is read against its source, and a `hybrid` link draws a composite it
|
|
223
|
+
* names with the consuming config's row of that name. `drawnWith` answers which row that is, as a
|
|
224
|
+
* member path in `local`, and the member's styles are that row's, so they have to be rendered against
|
|
225
|
+
* `local` while the rest of the rule is rendered against the source. The marker is the source's, which
|
|
226
|
+
* the component's own `_on<Group><Member>` rules query. `bag` is what's left for
|
|
227
|
+
* {@link inlineRuleComposites}.
|
|
228
|
+
*/
|
|
229
|
+
declare function splitRuleComposites({
|
|
230
|
+
config,
|
|
231
|
+
element,
|
|
232
|
+
bag: authored,
|
|
233
|
+
local,
|
|
234
|
+
drawnWith
|
|
235
|
+
}: {
|
|
236
|
+
readonly config: Config;
|
|
237
|
+
readonly element: unknown;
|
|
238
|
+
readonly bag: Record<string, unknown>;
|
|
239
|
+
readonly local: Config;
|
|
240
|
+
readonly drawnWith: (member: string) => string | undefined;
|
|
241
|
+
}): {
|
|
242
|
+
readonly bag: Record<string, unknown>;
|
|
243
|
+
readonly drawn: Record<string, unknown> | undefined;
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* A composite member's styles as a bag, with the composite's marker
|
|
247
|
+
* (`--<prefix>-composite-<group>: <member>`) that `_on<Group><Member>` finds it by, under the prefix
|
|
248
|
+
* of `markedIn` (`config` unless given).
|
|
249
|
+
*/
|
|
250
|
+
declare function compositeMemberBag({
|
|
251
|
+
config,
|
|
252
|
+
path,
|
|
253
|
+
markedIn
|
|
254
|
+
}: {
|
|
255
|
+
readonly config: Config;
|
|
256
|
+
readonly path: string;
|
|
257
|
+
readonly markedIn?: Config;
|
|
258
|
+
}): Record<string, unknown>;
|
|
210
259
|
/**
|
|
211
260
|
* The props a style rule's bag sends to each layer's ELEMENT rather than to the stylesheet, for one
|
|
212
261
|
* instance. The same split the emitted module makes when it builds a layer's routed bundle.
|
|
@@ -388,4 +437,4 @@ declare function modifierUtilitiesUsed(config: Config): Set<string>;
|
|
|
388
437
|
*/
|
|
389
438
|
declare function splitVariants(cls: string): string[];
|
|
390
439
|
//#endregion
|
|
391
|
-
export { ComponentRuleClass, PickedComposite, SplitStyleProps, arbitraryClassName, arbitraryNeedsClass, classLeaf, classSelector, componentClassBase, componentCompositeClasses, componentLayerClass, componentMotionClasses, componentPropClasses, componentPropComposites, componentRuleClasses, componentStateAttribute, componentStateAttributes, forceModeAttribute, forceModeAttributeOf, forceModeProp, forceModePropGroup, forceModePropValue, forceModeProps, forceStateAttribute, forceStateSelector, inlineRuleComposites, isForceModeProp, kebabComponent, layerJsMotionPresets, layerRoutedProps, modifierUtilitiesUsed, motionClassName, ruleCondition, splitStyleProps, splitVariants, stylePropClassBase, stylePropClassName, stylePropClasses, stylePropOffScaleLiteral, stylePropOwnClasses, styleRuleMotionClasses };
|
|
440
|
+
export { ComponentRuleClass, PickedComposite, SplitStyleProps, arbitraryClassName, arbitraryNeedsClass, classLeaf, classSelector, componentClassBase, componentCompositeClasses, componentLayerClass, componentMotionClasses, componentPropClasses, componentPropComposites, componentRuleClasses, componentStateAttribute, componentStateAttributes, compositeMemberBag, forceModeAttribute, forceModeAttributeOf, forceModeProp, forceModePropGroup, forceModePropValue, forceModeProps, forceStateAttribute, forceStateSelector, inlineRuleComposites, isForceModeProp, kebabComponent, layerJsMotionPresets, layerRoutedProps, modifierUtilitiesUsed, motionClassName, motionKeyframesName, ruleCondition, splitRuleComposites, splitStyleProps, splitVariants, stylePropClassBase, stylePropClassName, stylePropClasses, stylePropOffScaleLiteral, stylePropOwnClasses, styleRuleMotionClasses };
|