@meltemi/diagrams-motion 0.0.0-stage → 1.9.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Architecture Studio contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,51 @@
1
- # Temporary Holding Version
1
+ # @meltemi/diagrams-motion
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Motion on a deterministic clock: effects (flow particles, moving dashes, pulses, traces) planned on a
4
+ laid-out scene, the frame at any time, the CSS-animated SVG profile, and the timeline and frames
5
+ of stories.
6
+
7
+ It is part of [Meltemi Diagrams](https://github.com/askenaz-dev/meltemi-diagrams#readme), diagrams as code with a canvas, motion and
8
+ exports. Every package of the product has the same version.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @meltemi/diagrams-motion
14
+ ```
15
+
16
+ Node 22.12.0 or later. The package is an ES module with type declarations.
17
+
18
+ ## Use
19
+
20
+ ```ts
21
+ import { layoutDiagram } from "@meltemi/diagrams-layout";
22
+ import { createElkEngine } from "@meltemi/diagrams-layout-elk";
23
+ import { compile } from "@meltemi/diagrams-model";
24
+ import { planMotion, sceneAt } from "@meltemi/diagrams-motion";
25
+ import { renderSvg } from "@meltemi/diagrams-render";
26
+
27
+ const text = `language "0.2"
28
+
29
+ diagram shop: flow {
30
+ web -> api: "HTTPS" as call
31
+ animate call { effect flow; duration 1200ms; repeat forever }
32
+ }
33
+ `;
34
+
35
+ const compilation = compile(text);
36
+ const diagram = compilation.document.diagrams[0]!;
37
+ const { scene } = layoutDiagram(compilation, diagram, { engine: createElkEngine() });
38
+ const plan = planMotion(diagram, scene!);
39
+ const frame = renderSvg(sceneAt(scene!, plan, 600)); // the picture at 600 ms
40
+ console.log(plan.effects.length, frame.length > 0); // 1 true
41
+ ```
42
+
43
+ ## Documentation
44
+
45
+ - [Motion](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/docs/language/motion.md)
46
+ - [Stories](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/docs/language/stories.md)
47
+ - [All documentation](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/docs/README.md)
48
+
49
+ ## Licence
50
+
51
+ MIT. Third-party components and their licences are listed in [THIRD_PARTY_LICENSES.md](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/THIRD_PARTY_LICENSES.md).
package/dist/css.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { Scene } from "@meltemi/diagrams-layout";
2
+ import { type MotionPlan } from "./plan.js";
3
+ /** The class every animated element carries, so reduced motion can stop them all. */
4
+ export declare const MOTION_CLASS = "mdg-m";
5
+ /**
6
+ * The scene with the animated SVG profile: a CSS style sheet and classes on the targets and on
7
+ * overlays that are invisible outside their animations, so the drawing without effects is what
8
+ * shows before a delay, after the last cycle, with reduced motion and where CSS animation is not
9
+ * supported. CSS only: opacity, motion paths, dash offsets and scale, all linear.
10
+ */
11
+ export declare function animatedScene(scene: Scene, plan: MotionPlan): Scene;
12
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAa,MAAM,0BAA0B,CAAC;AAUjE,OAAO,EAOL,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAEnB,qFAAqF;AACrF,eAAO,MAAM,YAAY,UAAU,CAAC;AAuDpC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,GAAG,KAAK,CAoJnE"}
package/dist/css.js ADDED
@@ -0,0 +1,194 @@
1
+ import { circlePath, particleRadius, round, roundedRectPath, trackLength, trackPath, } from "./geometry.js";
2
+ import { beforeLabel, outlineIndex, targetKey, traceTrack, withTargets } from "./frames.js";
3
+ import { DASH_PATTERN, DASH_PERIOD, GLOW, HALO, TRACE, } from "./plan.js";
4
+ /** The class every animated element carries, so reduced motion can stop them all. */
5
+ export const MOTION_CLASS = "mdg-m";
6
+ const percent = (value) => `${round(value * 100)}%`;
7
+ /** `animation` of an effect: one keyframe set, linear, its delay and repeat, no fill mode. */
8
+ function animation(name, effect) {
9
+ const count = effect.repeat === "forever" ? "infinite" : String(effect.repeat);
10
+ return `animation: ${name} ${effect.durationMs}ms linear ${effect.delayMs}ms ${count} normal none;`;
11
+ }
12
+ /**
13
+ * Keyframes of particle `i` of `k`: it starts at `i/k` of the track, reaches the end, jumps to the
14
+ * start and comes back to `i/k`, so every particle shares the effect's delay.
15
+ */
16
+ function particleKeyframes(name, k, i, reverse) {
17
+ const at = (d) => `offset-distance: ${percent(reverse ? 1 - d : d)}; opacity: 1;`;
18
+ const s = i / k;
19
+ if (i === 0)
20
+ return `@keyframes ${name} { 0% { ${at(0)} } 100% { ${at(1)} } }`;
21
+ const turn = 1 - s;
22
+ return [
23
+ `@keyframes ${name} {`,
24
+ ` 0% { ${at(s)} }`,
25
+ ` ${percent(turn)} { ${at(1)} }`,
26
+ ` ${round(turn * 100) + 0.001}% { ${at(0)} }`,
27
+ ` 100% { ${at(s)} }`,
28
+ "}",
29
+ ].join("\n");
30
+ }
31
+ /**
32
+ * Keyframes of a trace's line: one dash as long as the track, offset from the whole length to
33
+ * nothing while it grows, then the lit line fades. Per effect, since lengths differ.
34
+ */
35
+ function traceKeyframes(name, length) {
36
+ const L = round(length);
37
+ const at = (offset, opacity) => `stroke-dasharray: ${L} ${L}; stroke-dashoffset: ${round(offset)}; opacity: ${opacity};`;
38
+ return [
39
+ `@keyframes ${name} {`,
40
+ ` 0% { ${at(L, 1)} }`,
41
+ ` ${percent(TRACE.fill)} { ${at(0, 1)} }`,
42
+ ` 100% { ${at(0, 0)} }`,
43
+ "}",
44
+ ].join("\n");
45
+ }
46
+ /** Keyframes of a trace's head dot, which rides the track while the line grows, then fades. */
47
+ const TRACE_DOT_KEYFRAMES = [
48
+ "@keyframes mdg-trace-dot {",
49
+ " 0% { offset-distance: 0%; opacity: 1; }",
50
+ ` ${percent(TRACE.fill)} { offset-distance: 100%; opacity: 1; }`,
51
+ " 100% { offset-distance: 100%; opacity: 0; }",
52
+ "}",
53
+ ].join("\n");
54
+ /**
55
+ * The scene with the animated SVG profile: a CSS style sheet and classes on the targets and on
56
+ * overlays that are invisible outside their animations, so the drawing without effects is what
57
+ * shows before a delay, after the last cycle, with reduced motion and where CSS animation is not
58
+ * supported. CSS only: opacity, motion paths, dash offsets and scale, all linear.
59
+ */
60
+ export function animatedScene(scene, plan) {
61
+ if (plan.effects.length === 0)
62
+ return scene;
63
+ const rules = [];
64
+ const keyframes = new Map();
65
+ const particleRules = [];
66
+ const dashes = new Map();
67
+ const overlays = [];
68
+ const halos = [];
69
+ const traces = new Map();
70
+ for (const effect of plan.effects) {
71
+ const own = `mdg-e${effect.index}`;
72
+ if (effect.effect === "trace") {
73
+ // The line and its dot go into the relation's group, under its label, as in frames.
74
+ const points = traceTrack(effect);
75
+ const name = `mdg-trace-${effect.index}`;
76
+ keyframes.set(name, traceKeyframes(name, trackLength(points)));
77
+ keyframes.set("mdg-trace-dot", TRACE_DOT_KEYFRAMES);
78
+ rules.push(`.${own} { ${animation(name, effect)} }`);
79
+ particleRules.push(`.${own}-dot { offset-path: path("${trackPath(points)}"); offset-rotate: 0deg; ${animation("mdg-trace-dot", effect)} }`);
80
+ traces.set(targetKey(effect.role, effect.target), [
81
+ {
82
+ kind: "polyline",
83
+ points,
84
+ stroke: effect.color,
85
+ strokeWidth: round(effect.width + TRACE.extra),
86
+ dashed: false,
87
+ opacity: 0,
88
+ className: `${MOTION_CLASS} ${own}`,
89
+ },
90
+ {
91
+ kind: "path",
92
+ d: circlePath(0, 0, effect.width + TRACE.dot),
93
+ fill: effect.color,
94
+ stroke: "none",
95
+ strokeWidth: 0,
96
+ dashed: false,
97
+ opacity: 0,
98
+ className: `${MOTION_CLASS} ${own}-dot`,
99
+ },
100
+ ]);
101
+ continue;
102
+ }
103
+ if (effect.effect === "dash") {
104
+ dashes.set(targetKey(effect.role, effect.target), effect);
105
+ const name = effect.reverse ? "mdg-dash-reverse" : "mdg-dash";
106
+ keyframes.set(name, `@keyframes ${name} { from { stroke-dasharray: ${DASH_PATTERN.join(" ")}; stroke-dashoffset: 0; } to { stroke-dasharray: ${DASH_PATTERN.join(" ")}; stroke-dashoffset: ${effect.reverse ? DASH_PERIOD : -DASH_PERIOD}; } }`);
107
+ rules.push(`.${own} { ${animation(name, effect)} }`);
108
+ continue;
109
+ }
110
+ if (effect.effect === "pulse") {
111
+ if (effect.bounds) {
112
+ keyframes.set("mdg-halo", `@keyframes mdg-halo { from { opacity: ${HALO.opacity}; transform: scale(1); } to { opacity: 0; transform: scale(${1 + HALO.scale}); } }`);
113
+ rules.push(`.${own} { transform-box: fill-box; transform-origin: center; ${animation("mdg-halo", effect)} }`);
114
+ halos.push({
115
+ kind: "path",
116
+ d: roundedRectPath(effect.bounds),
117
+ fill: "none",
118
+ stroke: effect.color,
119
+ strokeWidth: HALO.width,
120
+ dashed: false,
121
+ opacity: 0,
122
+ className: `${MOTION_CLASS} ${own}`,
123
+ });
124
+ }
125
+ else {
126
+ keyframes.set("mdg-glow", `@keyframes mdg-glow { from { opacity: ${GLOW.opacity}; } to { opacity: 0; } }`);
127
+ rules.push(`.${own} { ${animation("mdg-glow", effect)} }`);
128
+ halos.push({
129
+ kind: "polyline",
130
+ points: effect.track.map((p) => ({ x: round(p.x), y: round(p.y) })),
131
+ stroke: effect.color,
132
+ strokeWidth: effect.width + GLOW.extra,
133
+ dashed: false,
134
+ opacity: 0,
135
+ className: `${MOTION_CLASS} ${own}`,
136
+ });
137
+ }
138
+ continue;
139
+ }
140
+ // Flow: one particle per class, moved along the track by a motion path.
141
+ const path = trackPath(effect.track);
142
+ const r = particleRadius(effect.width);
143
+ for (let i = 0; i < effect.particles; i++) {
144
+ // The first particle's keyframes do not depend on how many particles there are.
145
+ const name = `mdg-flow${effect.reverse ? "-reverse" : ""}${i === 0 ? "" : `-${effect.particles}-${i}`}`;
146
+ keyframes.set(name, particleKeyframes(name, effect.particles, i, effect.reverse));
147
+ const particle = `${own}-${i}`;
148
+ particleRules.push(`.${particle} { offset-path: path("${path}"); offset-rotate: 0deg; ${animation(name, effect)} }`);
149
+ overlays.push({
150
+ kind: "path",
151
+ d: circlePath(0, 0, r),
152
+ fill: effect.color,
153
+ stroke: "none",
154
+ strokeWidth: 0,
155
+ dashed: false,
156
+ opacity: 0,
157
+ className: `${MOTION_CLASS} ${particle}`,
158
+ });
159
+ }
160
+ }
161
+ const items = withTargets(scene.items, (group) => {
162
+ const key = targetKey(group.role, group.id);
163
+ const effect = dashes.get(key);
164
+ const trace = traces.get(key);
165
+ if (!effect && !trace)
166
+ return null;
167
+ let list = group.items;
168
+ const index = effect ? outlineIndex(list) : -1;
169
+ if (effect && index >= 0) {
170
+ list = list.map((item, i) => i === index && item.kind !== "group" && item.kind !== "text" && item.kind !== "image"
171
+ ? { ...item, className: `${MOTION_CLASS} mdg-e${effect.index}` }
172
+ : item);
173
+ }
174
+ if (trace)
175
+ list = beforeLabel(list, trace);
176
+ return list === group.items ? null : [...list];
177
+ });
178
+ const motion = [...halos, ...overlays];
179
+ if (motion.length > 0)
180
+ items.push({ kind: "group", id: "motion", role: "motion", items: motion });
181
+ const sheet = [
182
+ ...[...keyframes.keys()].sort().map((k) => keyframes.get(k)),
183
+ ...rules,
184
+ // Motion paths are newer than the rest; without them particles and trace dots stay invisible.
185
+ ...(particleRules.length > 0
186
+ ? [`@supports (offset-path: path("M0 0")) {`, ...particleRules.map((r) => ` ${r}`), "}"]
187
+ : []),
188
+ // Overlays never take pointer events, so a canvas can still be clicked through them.
189
+ `[data-role="motion"] { pointer-events: none; }`,
190
+ `@media (prefers-reduced-motion: reduce) { .${MOTION_CLASS} { animation: none !important; } }`,
191
+ ];
192
+ return { ...scene, items, styleSheet: sheet.join("\n") };
193
+ }
194
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.js","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { Scene } from "@meltemi/diagrams-layout";
2
+ import { type StoryFrameOptions, type StoryTimeline, type StoryViews } from "./story.js";
3
+ /** How long a drill-down's two phases last: the camera move, then the change of view. */
4
+ export declare const DRILL_DURATIONS: {
5
+ readonly cameraMs: 320;
6
+ readonly transitionMs: 480;
7
+ };
8
+ export type DrillTransition = "morph" | "fade";
9
+ export type DrillDirection = "down" | "up";
10
+ /**
11
+ * A move between a view and the view an element opens. Going down, `from` is the view that draws
12
+ * `element` and `to` the view it opens; going up, `from` is the view being left and `to` the view
13
+ * that draws `element`, and the frames are those of the way down played backwards.
14
+ */
15
+ export interface DrillSpec {
16
+ readonly from: string;
17
+ readonly to: string;
18
+ readonly element: string;
19
+ readonly transition: DrillTransition;
20
+ readonly direction: DrillDirection;
21
+ readonly cameraMs: number;
22
+ readonly transitionMs: number;
23
+ }
24
+ /**
25
+ * The timeline of the way down: a scene on the parent view with a camera on the element, then a
26
+ * scene on the child view that the transition starts. Plain data; the way up plays it backwards.
27
+ */
28
+ export declare function drillTimeline(spec: DrillSpec): StoryTimeline;
29
+ /**
30
+ * The scene of a drill-down at `t` milliseconds: the story frame of `drillTimeline`, with the
31
+ * camera carried into the change of view (the view box goes from the element's camera box to the
32
+ * whole child view) and the size of the larger view at every instant, so the picture never jumps.
33
+ * The view box is always set. Null when a view is missing or the element has no bounds. Pure.
34
+ */
35
+ export declare function drillFrame(spec: DrillSpec, views: StoryViews, t: number, options?: StoryFrameOptions): Scene | null;
36
+ /**
37
+ * How a view opens another from one of its elements: `morph` when both scenes draw an element
38
+ * with that id and bounds (a system box becomes the boundary of its container view), else `fade`.
39
+ */
40
+ export declare function transitionFor(parent: Scene, child: Scene, element: string): DrillTransition;
41
+ //# sourceMappingURL=drill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drill.d.ts","sourceRoot":"","sources":["../src/drill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAa,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,yFAAyF;AACzF,eAAO,MAAM,eAAe;;;CAAgD,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;AAC/C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,IAAI,CAAC;AAE3C;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AASD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,aAAa,CA+C5D;AAUD;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,MAAM,EACT,OAAO,GAAE,iBAAsB,GAC9B,KAAK,GAAG,IAAI,CA6Cd;AAWD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAE3F"}
package/dist/drill.js ADDED
@@ -0,0 +1,145 @@
1
+ import { round } from "./geometry.js";
2
+ import { boundsOf, frameBox, storyFrame, } from "./story.js";
3
+ /** How long a drill-down's two phases last: the camera move, then the change of view. */
4
+ export const DRILL_DURATIONS = { cameraMs: 320, transitionMs: 480 };
5
+ /** The way down of a spec: from the view that draws the element to the one it opens. */
6
+ function downward(spec) {
7
+ return spec.direction === "down"
8
+ ? { parent: spec.from, child: spec.to }
9
+ : { parent: spec.to, child: spec.from };
10
+ }
11
+ /**
12
+ * The timeline of the way down: a scene on the parent view with a camera on the element, then a
13
+ * scene on the child view that the transition starts. Plain data; the way up plays it backwards.
14
+ */
15
+ export function drillTimeline(spec) {
16
+ const { parent, child } = downward(spec);
17
+ const camera = Math.max(0, spec.cameraMs);
18
+ const change = Math.max(0, spec.transitionMs);
19
+ return {
20
+ id: "drill",
21
+ title: null,
22
+ durationMs: camera + change,
23
+ views: [parent, child],
24
+ scenes: [
25
+ {
26
+ id: "from",
27
+ title: null,
28
+ view: parent,
29
+ transition: null,
30
+ startMs: 0,
31
+ durationMs: camera,
32
+ line: 0,
33
+ actions: [
34
+ {
35
+ kind: "camera",
36
+ path: [0, 0],
37
+ targets: [{ id: spec.element, kind: "element" }],
38
+ all: false,
39
+ startMs: 0,
40
+ durationMs: camera,
41
+ children: [],
42
+ line: 0,
43
+ },
44
+ ],
45
+ },
46
+ {
47
+ id: "to",
48
+ title: null,
49
+ view: child,
50
+ transition: {
51
+ kind: change > 0 ? spec.transition : "cut",
52
+ startMs: camera,
53
+ durationMs: change,
54
+ },
55
+ startMs: camera,
56
+ durationMs: change,
57
+ line: 0,
58
+ actions: [],
59
+ },
60
+ ],
61
+ };
62
+ }
63
+ const lerp = (a, b, p) => a + (b - a) * p;
64
+ const whole = (scene) => ({
65
+ x: 0,
66
+ y: 0,
67
+ width: scene.width,
68
+ height: scene.height,
69
+ });
70
+ /**
71
+ * The scene of a drill-down at `t` milliseconds: the story frame of `drillTimeline`, with the
72
+ * camera carried into the change of view (the view box goes from the element's camera box to the
73
+ * whole child view) and the size of the larger view at every instant, so the picture never jumps.
74
+ * The view box is always set. Null when a view is missing or the element has no bounds. Pure.
75
+ */
76
+ export function drillFrame(spec, views, t, options = {}) {
77
+ const { parent, child } = downward(spec);
78
+ const above = views(parent);
79
+ const below = views(child);
80
+ if (!above || !below)
81
+ return null;
82
+ // Only an element's box opens a view: a relation's track is no target.
83
+ if (!hasElement(above.scene.items, spec.element))
84
+ return null;
85
+ const bounds = boundsOf(above.scene, [spec.element]);
86
+ if (!bounds)
87
+ return null;
88
+ const timeline = drillTimeline(spec);
89
+ const duration = timeline.durationMs;
90
+ const clamped = Math.min(Math.max(0, t), duration);
91
+ // The way up is the way down played backwards.
92
+ const time = spec.direction === "down" ? clamped : duration - clamped;
93
+ const camera = Math.max(0, spec.cameraMs);
94
+ const frame = storyFrame(timeline, views, time, options);
95
+ if (!frame)
96
+ return null;
97
+ const width = Math.max(above.scene.width, below.scene.width);
98
+ const height = Math.max(above.scene.height, below.scene.height);
99
+ let box;
100
+ if (time < camera || duration === 0) {
101
+ box = duration === 0 ? whole(below.scene) : (frame.viewBox ?? whole(above.scene));
102
+ }
103
+ else {
104
+ const change = duration - camera;
105
+ const p = change <= 0 ? 1 : Math.min(1, (time - camera) / change);
106
+ const from = frameBox(above.scene, bounds);
107
+ const to = whole(below.scene);
108
+ box = {
109
+ x: lerp(from.x, to.x, p),
110
+ y: lerp(from.y, to.y, p),
111
+ width: lerp(from.width, to.width, p),
112
+ height: lerp(from.height, to.height, p),
113
+ };
114
+ }
115
+ return {
116
+ ...frame,
117
+ width,
118
+ height,
119
+ viewBox: {
120
+ x: round(box.x),
121
+ y: round(box.y),
122
+ width: round(box.width),
123
+ height: round(box.height),
124
+ },
125
+ };
126
+ }
127
+ function hasElement(items, id) {
128
+ for (const item of items) {
129
+ if (item.kind !== "group")
130
+ continue;
131
+ if (item.role === "element" && item.id === id && item.bounds)
132
+ return true;
133
+ if (hasElement(item.items, id))
134
+ return true;
135
+ }
136
+ return false;
137
+ }
138
+ /**
139
+ * How a view opens another from one of its elements: `morph` when both scenes draw an element
140
+ * with that id and bounds (a system box becomes the boundary of its container view), else `fade`.
141
+ */
142
+ export function transitionFor(parent, child, element) {
143
+ return hasElement(parent.items, element) && hasElement(child.items, element) ? "morph" : "fade";
144
+ }
145
+ //# sourceMappingURL=drill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drill.js","sourceRoot":"","sources":["../src/drill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { GroupItem, Scene, SceneItem } from "@meltemi/diagrams-layout";
2
+ import type { Point } from "@meltemi/diagrams-model";
3
+ import { type MotionEffect, type MotionPlan } from "./plan.js";
4
+ /** The items with `change` applied to every group; unchanged groups keep their identity. */
5
+ export declare function withTargets(items: readonly SceneItem[], change: (group: GroupItem) => readonly SceneItem[] | null): SceneItem[];
6
+ /** The index of the first stroked line or outline of a group, or -1. */
7
+ export declare function outlineIndex(items: readonly SceneItem[]): number;
8
+ export declare const targetKey: (role: string, id: string) => string;
9
+ /** The track a trace runs along, from where it starts: reversed for `direction reverse`. */
10
+ export declare function traceTrack(effect: MotionEffect): Point[];
11
+ /** How far a trace has grown at `phase` (0 to 1) and how visible it is. */
12
+ export declare function traceState(phase: number): {
13
+ grown: number;
14
+ opacity: number;
15
+ };
16
+ /**
17
+ * A trace at `phase`: the track drawn with one dash as long as the track, offset so that the part
18
+ * grown so far shows, and a dot at its head; the animated profile draws the same values.
19
+ */
20
+ export declare function traceAt(effect: MotionEffect, phase: number): SceneItem[];
21
+ /** The items of a relation's group with `extra` inserted before its label, so the label stays on top. */
22
+ export declare function beforeLabel(items: readonly SceneItem[], extra: readonly SceneItem[]): SceneItem[];
23
+ /** The halo, glow or particles an effect draws at `phase`, above everything else. */
24
+ export declare function overlayAt(effect: MotionEffect, phase: number): SceneItem[];
25
+ /**
26
+ * The scene at `t` milliseconds: dashes moved along their lines and outlines, traces grown along
27
+ * their relations, halos and glows, particles on their tracks. Targets outside their effect's
28
+ * window are drawn as without effects. Pure: the same scene, plan and time give the same result.
29
+ */
30
+ export declare function sceneAt(scene: Scene, plan: MotionPlan, t: number): Scene;
31
+ //# sourceMappingURL=frames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../src/frames.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AASrD,OAAO,EAOL,KAAK,YAAY,EACjB,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAEnB,4FAA4F;AAC5F,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,MAAM,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,SAAS,EAAE,GAAG,IAAI,GACxD,SAAS,EAAE,CAQb;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAMhE;AAED,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,IAAI,MAAM,WAAyB,CAAC;AAE5E,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,CAGxD;AAED,2EAA2E;AAC3E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAI5E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,CAyBxE;AAED,yGAAyG;AACzG,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,EAAE,CAIjG;AAED,qFAAqF;AACrF,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,CA+C1E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAuCxE"}