@scenar/core 0.0.1
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 +190 -0
- package/README.md +65 -0
- package/cursor/compute-position.d.ts +14 -0
- package/cursor/compute-position.d.ts.map +1 -0
- package/cursor/compute-position.js +17 -0
- package/cursor/compute-position.js.map +1 -0
- package/dom/scroll.d.ts +27 -0
- package/dom/scroll.d.ts.map +1 -0
- package/dom/scroll.js +63 -0
- package/dom/scroll.js.map +1 -0
- package/index.d.ts +15 -0
- package/index.d.ts.map +1 -0
- package/index.js +14 -0
- package/index.js.map +1 -0
- package/narration/types.d.ts +26 -0
- package/narration/types.d.ts.map +1 -0
- package/narration/types.js +11 -0
- package/narration/types.js.map +1 -0
- package/package.json +29 -0
- package/scenario/step-action.d.ts +105 -0
- package/scenario/step-action.d.ts.map +1 -0
- package/scenario/step-action.js +2 -0
- package/scenario/step-action.js.map +1 -0
- package/scenario/types.d.ts +35 -0
- package/scenario/types.d.ts.map +1 -0
- package/scenario/types.js +8 -0
- package/scenario/types.js.map +1 -0
- package/src/cursor/compute-position.test.ts +46 -0
- package/src/cursor/compute-position.ts +23 -0
- package/src/dom/scroll.test.ts +35 -0
- package/src/dom/scroll.ts +64 -0
- package/src/index.ts +53 -0
- package/src/narration/types.ts +27 -0
- package/src/scenario/step-action.ts +113 -0
- package/src/scenario/types.ts +36 -0
- package/src/targeting/data-attributes.test.ts +22 -0
- package/src/targeting/data-attributes.ts +30 -0
- package/src/timeline/compute-step-timeline.test.ts +60 -0
- package/src/timeline/compute-step-timeline.ts +49 -0
- package/src/timeline/derive-step.test.ts +37 -0
- package/src/timeline/derive-step.ts +15 -0
- package/src/timeline/step-duration.test.ts +38 -0
- package/src/timeline/step-duration.ts +25 -0
- package/src/timing/constants.ts +59 -0
- package/src/viewport/transform.ts +13 -0
- package/targeting/data-attributes.d.ts +21 -0
- package/targeting/data-attributes.d.ts.map +1 -0
- package/targeting/data-attributes.js +25 -0
- package/targeting/data-attributes.js.map +1 -0
- package/timeline/compute-step-timeline.d.ts +27 -0
- package/timeline/compute-step-timeline.d.ts.map +1 -0
- package/timeline/compute-step-timeline.js +26 -0
- package/timeline/compute-step-timeline.js.map +1 -0
- package/timeline/derive-step.d.ts +7 -0
- package/timeline/derive-step.d.ts.map +1 -0
- package/timeline/derive-step.js +13 -0
- package/timeline/derive-step.js.map +1 -0
- package/timeline/step-duration.d.ts +12 -0
- package/timeline/step-duration.d.ts.map +1 -0
- package/timeline/step-duration.js +18 -0
- package/timeline/step-duration.js.map +1 -0
- package/timing/constants.d.ts +55 -0
- package/timing/constants.d.ts.map +1 -0
- package/timing/constants.js +55 -0
- package/timing/constants.js.map +1 -0
- package/viewport/transform.d.ts +9 -0
- package/viewport/transform.d.ts.map +1 -0
- package/viewport/transform.js +7 -0
- package/viewport/transform.js.map +1 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getStepDurationMs } from "./step-duration.js";
|
|
3
|
+
|
|
4
|
+
describe("getStepDurationMs", () => {
|
|
5
|
+
const steps = [
|
|
6
|
+
{ delayMs: 0, data: null },
|
|
7
|
+
{ delayMs: 1500, data: null },
|
|
8
|
+
{ delayMs: 2000, data: null },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
it("returns narration duration when manifest has an entry", () => {
|
|
12
|
+
const manifest = {
|
|
13
|
+
steps: [{ src: "a.mp3", durationMs: 4000 }, null, null],
|
|
14
|
+
};
|
|
15
|
+
expect(getStepDurationMs(0, manifest, steps)).toBe(4000);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("falls back to next step delayMs when no narration", () => {
|
|
19
|
+
expect(getStepDurationMs(0, undefined, steps)).toBe(1500);
|
|
20
|
+
expect(getStepDurationMs(1, undefined, steps)).toBe(2000);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("falls back to 3000 for the last step with no narration", () => {
|
|
24
|
+
expect(getStepDurationMs(2, undefined, steps)).toBe(3000);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("treats zero narration duration as missing", () => {
|
|
28
|
+
const manifest = {
|
|
29
|
+
steps: [{ src: "a.mp3", durationMs: 0 }, null, null],
|
|
30
|
+
};
|
|
31
|
+
expect(getStepDurationMs(0, manifest, steps)).toBe(1500);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("handles null entries in manifest", () => {
|
|
35
|
+
const manifest = { steps: [null, null, null] };
|
|
36
|
+
expect(getStepDurationMs(0, manifest, steps)).toBe(1500);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { NarrationManifest } from "../narration/types.js";
|
|
2
|
+
import type { ScenarioStep } from "../scenario/types.js";
|
|
3
|
+
|
|
4
|
+
/** Fallback duration for the last step when no narration exists. */
|
|
5
|
+
const LAST_STEP_FALLBACK_MS = 3000;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Compute the effective duration of a step for interaction timing.
|
|
9
|
+
*
|
|
10
|
+
* Uses the narration clip duration if available. Falls back to the
|
|
11
|
+
* next step's `delayMs` (since the next step's delay is the time
|
|
12
|
+
* until it appears, which equals the current step's screen time).
|
|
13
|
+
* For the last step, falls back to {@link LAST_STEP_FALLBACK_MS}.
|
|
14
|
+
*/
|
|
15
|
+
export function getStepDurationMs<T>(
|
|
16
|
+
stepIndex: number,
|
|
17
|
+
manifest: NarrationManifest | undefined,
|
|
18
|
+
steps: readonly ScenarioStep<T>[],
|
|
19
|
+
): number {
|
|
20
|
+
const narrationMs = manifest?.steps[stepIndex]?.durationMs;
|
|
21
|
+
if (narrationMs != null && narrationMs > 0) return narrationMs;
|
|
22
|
+
|
|
23
|
+
const nextStep = steps[stepIndex + 1];
|
|
24
|
+
return nextStep ? nextStep.delayMs : LAST_STEP_FALLBACK_MS;
|
|
25
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared timing constants for the scenario playback engine.
|
|
3
|
+
*
|
|
4
|
+
* These values coordinate animation timing between the Cursor component
|
|
5
|
+
* (visual ripple) and the step-interactions hook (action dispatch).
|
|
6
|
+
* Both must agree on when the cursor has "arrived" at its target so
|
|
7
|
+
* the click ripple and the DOM click event fire in sync.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Milliseconds after a cursor target is set before the cursor is
|
|
12
|
+
* considered "arrived" and the click ripple appears.
|
|
13
|
+
*
|
|
14
|
+
* Derived from the Cursor spring parameters (stiffness 170,
|
|
15
|
+
* damping 22, mass 0.6) — the spring visually settles within
|
|
16
|
+
* this window for typical travel distances in the viewport.
|
|
17
|
+
*/
|
|
18
|
+
export const CLICK_DELAY_MS = 450;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Default milliseconds between characters for the `type` action.
|
|
22
|
+
*
|
|
23
|
+
* 50 ms per character = 20 characters/second — fast enough to feel
|
|
24
|
+
* like confident typing, slow enough that each character is readable
|
|
25
|
+
* in both browser playback and video export. Overridable per-action
|
|
26
|
+
* via {@link StepAction.typeDelay}.
|
|
27
|
+
*/
|
|
28
|
+
export const TYPE_CHAR_DELAY_MS = 50;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Default milliseconds to hold the cursor in place during a `hover`
|
|
32
|
+
* action, between the enter-event dispatch and the leave-event
|
|
33
|
+
* dispatch.
|
|
34
|
+
*
|
|
35
|
+
* 1500 ms gives viewers enough time to read a tooltip or notice a
|
|
36
|
+
* hover-state change in both browser playback and video export.
|
|
37
|
+
* Overridable per-action via {@link StepAction.hoverDuration}.
|
|
38
|
+
*/
|
|
39
|
+
export const HOVER_HOLD_MS = 1500;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Milliseconds to pause at the drag source after pressing before
|
|
43
|
+
* starting the drag movement to the destination.
|
|
44
|
+
*
|
|
45
|
+
* 200 ms mimics the brief human hesitation between mousedown and the
|
|
46
|
+
* start of a deliberate drag gesture.
|
|
47
|
+
*/
|
|
48
|
+
export const DRAG_SETTLE_MS = 200;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Expected milliseconds for the viewport transition spring to settle
|
|
52
|
+
* after a zoom or pan change.
|
|
53
|
+
*
|
|
54
|
+
* The ViewportTransformLayer uses a softer spring (stiffness 100,
|
|
55
|
+
* damping 20, mass 0.8) than the cursor spring, so it takes longer
|
|
56
|
+
* to settle. Used for dev-mode warnings when a subsequent cursor
|
|
57
|
+
* action is scheduled too close to a viewport transition.
|
|
58
|
+
*/
|
|
59
|
+
export const VIEWPORT_SETTLE_MS = 500;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Viewport transform state produced by step interactions. */
|
|
2
|
+
export interface ViewportTransform {
|
|
3
|
+
scale: number;
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** The identity transform — no zoom, no translation. */
|
|
9
|
+
export const VIEWPORT_TRANSFORM_IDENTITY: Readonly<ViewportTransform> = {
|
|
10
|
+
scale: 1,
|
|
11
|
+
x: 0,
|
|
12
|
+
y: 0,
|
|
13
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized data-attribute contract for the scenario engine.
|
|
3
|
+
*
|
|
4
|
+
* The engine identifies interactive elements in the DOM via these
|
|
5
|
+
* data attributes. This module is the single source of truth for
|
|
6
|
+
* attribute names and selector builders — consumers never hard-code
|
|
7
|
+
* attribute strings.
|
|
8
|
+
*/
|
|
9
|
+
/** Attribute name for cursor-targetable elements. */
|
|
10
|
+
export declare const CURSOR_TARGET_ATTRIBUTE = "data-cursor-target";
|
|
11
|
+
/** Attribute name for scroll-targetable elements. */
|
|
12
|
+
export declare const SCROLL_TARGET_ATTRIBUTE = "data-scroll-target";
|
|
13
|
+
/** Attribute set on elements during hover interactions. */
|
|
14
|
+
export declare const HOVER_STATE_ATTRIBUTE = "data-hover";
|
|
15
|
+
/** Attribute set on elements during drag interactions. */
|
|
16
|
+
export declare const DRAG_STATE_ATTRIBUTE = "data-dragging";
|
|
17
|
+
/** Build a CSS selector for a cursor target by its ID. */
|
|
18
|
+
export declare function cursorTargetSelector(id: string): string;
|
|
19
|
+
/** Build a CSS selector for a scroll target by its ID. */
|
|
20
|
+
export declare function scrollTargetSelector(id: string): string;
|
|
21
|
+
//# sourceMappingURL=data-attributes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-attributes.d.ts","sourceRoot":"","sources":["../../src/targeting/data-attributes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAE5D,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAE5D,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,0DAA0D;AAC1D,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,0DAA0D;AAC1D,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEvD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized data-attribute contract for the scenario engine.
|
|
3
|
+
*
|
|
4
|
+
* The engine identifies interactive elements in the DOM via these
|
|
5
|
+
* data attributes. This module is the single source of truth for
|
|
6
|
+
* attribute names and selector builders — consumers never hard-code
|
|
7
|
+
* attribute strings.
|
|
8
|
+
*/
|
|
9
|
+
/** Attribute name for cursor-targetable elements. */
|
|
10
|
+
export const CURSOR_TARGET_ATTRIBUTE = "data-cursor-target";
|
|
11
|
+
/** Attribute name for scroll-targetable elements. */
|
|
12
|
+
export const SCROLL_TARGET_ATTRIBUTE = "data-scroll-target";
|
|
13
|
+
/** Attribute set on elements during hover interactions. */
|
|
14
|
+
export const HOVER_STATE_ATTRIBUTE = "data-hover";
|
|
15
|
+
/** Attribute set on elements during drag interactions. */
|
|
16
|
+
export const DRAG_STATE_ATTRIBUTE = "data-dragging";
|
|
17
|
+
/** Build a CSS selector for a cursor target by its ID. */
|
|
18
|
+
export function cursorTargetSelector(id) {
|
|
19
|
+
return `[${CURSOR_TARGET_ATTRIBUTE}="${id}"]`;
|
|
20
|
+
}
|
|
21
|
+
/** Build a CSS selector for a scroll target by its ID. */
|
|
22
|
+
export function scrollTargetSelector(id) {
|
|
23
|
+
return `[${SCROLL_TARGET_ATTRIBUTE}="${id}"]`;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data-attributes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-attributes.js","sourceRoot":"","sources":["../../src/targeting/data-attributes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAE5D,qDAAqD;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAE5D,2DAA2D;AAC3D,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC;AAElD,0DAA0D;AAC1D,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD,0DAA0D;AAC1D,MAAM,UAAU,oBAAoB,CAAC,EAAU;IAC7C,OAAO,IAAI,uBAAuB,KAAK,EAAE,IAAI,CAAC;AAChD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,oBAAoB,CAAC,EAAU;IAC7C,OAAO,IAAI,uBAAuB,KAAK,EAAE,IAAI,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { NarrationManifest } from "../narration/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal step shape for timeline computation. Accepts any
|
|
4
|
+
* ScenarioStep<T> without caring about the data payload.
|
|
5
|
+
*/
|
|
6
|
+
interface StepTiming {
|
|
7
|
+
delayMs: number;
|
|
8
|
+
}
|
|
9
|
+
export interface StepTimeline {
|
|
10
|
+
/** Start time of each step in milliseconds (index 0 is always 0). */
|
|
11
|
+
stepStartTimesMs: number[];
|
|
12
|
+
/** Total playback duration in milliseconds. */
|
|
13
|
+
totalDurationMs: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Pre-compute step start times and total duration from step definitions
|
|
17
|
+
* and an optional narration manifest.
|
|
18
|
+
*
|
|
19
|
+
* Step N+1 starts after `max(steps[N+1].delayMs, manifest.steps[N].durationMs)` —
|
|
20
|
+
* whichever is longer, the base delay or the narration clip for the current step.
|
|
21
|
+
*
|
|
22
|
+
* Shared between browser ScenarioPlayer (progress bar) and Remotion
|
|
23
|
+
* video export (frame-based timeline).
|
|
24
|
+
*/
|
|
25
|
+
export declare function computeStepTimeline(steps: readonly StepTiming[], manifest: NarrationManifest | null | undefined): StepTimeline;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=compute-step-timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-step-timeline.d.ts","sourceRoot":"","sources":["../../src/timeline/compute-step-timeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D;;;GAGG;AACH,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAC7C,YAAY,CAed"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Dwell time on the final step so viewers can absorb the result. */
|
|
2
|
+
const FINAL_DWELL_MS = 3_000;
|
|
3
|
+
/**
|
|
4
|
+
* Pre-compute step start times and total duration from step definitions
|
|
5
|
+
* and an optional narration manifest.
|
|
6
|
+
*
|
|
7
|
+
* Step N+1 starts after `max(steps[N+1].delayMs, manifest.steps[N].durationMs)` —
|
|
8
|
+
* whichever is longer, the base delay or the narration clip for the current step.
|
|
9
|
+
*
|
|
10
|
+
* Shared between browser ScenarioPlayer (progress bar) and Remotion
|
|
11
|
+
* video export (frame-based timeline).
|
|
12
|
+
*/
|
|
13
|
+
export function computeStepTimeline(steps, manifest) {
|
|
14
|
+
const stepStartTimesMs = [0];
|
|
15
|
+
for (let i = 1; i < steps.length; i++) {
|
|
16
|
+
const prevStart = stepStartTimesMs[i - 1];
|
|
17
|
+
const baseDelay = steps[i].delayMs;
|
|
18
|
+
const narrationMs = manifest?.steps[i - 1]?.durationMs ?? 0;
|
|
19
|
+
stepStartTimesMs.push(prevStart + Math.max(baseDelay, narrationMs));
|
|
20
|
+
}
|
|
21
|
+
const lastStepStart = stepStartTimesMs[stepStartTimesMs.length - 1] ?? 0;
|
|
22
|
+
const lastNarrationMs = manifest?.steps[steps.length - 1]?.durationMs ?? 0;
|
|
23
|
+
const totalDurationMs = lastStepStart + Math.max(FINAL_DWELL_MS, lastNarrationMs);
|
|
24
|
+
return { stepStartTimesMs, totalDurationMs };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=compute-step-timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-step-timeline.js","sourceRoot":"","sources":["../../src/timeline/compute-step-timeline.ts"],"names":[],"mappings":"AAUA,qEAAqE;AACrE,MAAM,cAAc,GAAG,KAAK,CAAC;AAS7B;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA4B,EAC5B,QAA8C;IAE9C,MAAM,gBAAgB,GAAa,CAAC,CAAC,CAAC,CAAC;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC;QACpC,MAAM,WAAW,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,IAAI,CAAC,CAAC;QAC5D,gBAAgB,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,eAAe,GAAG,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,UAAU,IAAI,CAAC,CAAC;IAC3E,MAAM,eAAe,GAAG,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;IAElF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the active step for a given playback time by scanning the
|
|
3
|
+
* pre-computed step start times in reverse. Returns `0` if the
|
|
4
|
+
* time precedes all steps.
|
|
5
|
+
*/
|
|
6
|
+
export declare function deriveStepFromTime(currentTimeMs: number, stepStartTimesMs: readonly number[], maxIndex: number): number;
|
|
7
|
+
//# sourceMappingURL=derive-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-step.d.ts","sourceRoot":"","sources":["../../src/timeline/derive-step.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,QAAQ,EAAE,MAAM,GACf,MAAM,CAKR"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the active step for a given playback time by scanning the
|
|
3
|
+
* pre-computed step start times in reverse. Returns `0` if the
|
|
4
|
+
* time precedes all steps.
|
|
5
|
+
*/
|
|
6
|
+
export function deriveStepFromTime(currentTimeMs, stepStartTimesMs, maxIndex) {
|
|
7
|
+
for (let i = stepStartTimesMs.length - 1; i >= 0; i--) {
|
|
8
|
+
if (currentTimeMs >= stepStartTimesMs[i])
|
|
9
|
+
return Math.min(i, maxIndex);
|
|
10
|
+
}
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=derive-step.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-step.js","sourceRoot":"","sources":["../../src/timeline/derive-step.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,aAAqB,EACrB,gBAAmC,EACnC,QAAgB;IAEhB,KAAK,IAAI,CAAC,GAAG,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACtD,IAAI,aAAa,IAAI,gBAAgB,CAAC,CAAC,CAAE;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { NarrationManifest } from "../narration/types.js";
|
|
2
|
+
import type { ScenarioStep } from "../scenario/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Compute the effective duration of a step for interaction timing.
|
|
5
|
+
*
|
|
6
|
+
* Uses the narration clip duration if available. Falls back to the
|
|
7
|
+
* next step's `delayMs` (since the next step's delay is the time
|
|
8
|
+
* until it appears, which equals the current step's screen time).
|
|
9
|
+
* For the last step, falls back to {@link LAST_STEP_FALLBACK_MS}.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getStepDurationMs<T>(stepIndex: number, manifest: NarrationManifest | undefined, steps: readonly ScenarioStep<T>[]): number;
|
|
12
|
+
//# sourceMappingURL=step-duration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-duration.d.ts","sourceRoot":"","sources":["../../src/timeline/step-duration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAKzD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,GAAG,SAAS,EACvC,KAAK,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,GAChC,MAAM,CAMR"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Fallback duration for the last step when no narration exists. */
|
|
2
|
+
const LAST_STEP_FALLBACK_MS = 3000;
|
|
3
|
+
/**
|
|
4
|
+
* Compute the effective duration of a step for interaction timing.
|
|
5
|
+
*
|
|
6
|
+
* Uses the narration clip duration if available. Falls back to the
|
|
7
|
+
* next step's `delayMs` (since the next step's delay is the time
|
|
8
|
+
* until it appears, which equals the current step's screen time).
|
|
9
|
+
* For the last step, falls back to {@link LAST_STEP_FALLBACK_MS}.
|
|
10
|
+
*/
|
|
11
|
+
export function getStepDurationMs(stepIndex, manifest, steps) {
|
|
12
|
+
const narrationMs = manifest?.steps[stepIndex]?.durationMs;
|
|
13
|
+
if (narrationMs != null && narrationMs > 0)
|
|
14
|
+
return narrationMs;
|
|
15
|
+
const nextStep = steps[stepIndex + 1];
|
|
16
|
+
return nextStep ? nextStep.delayMs : LAST_STEP_FALLBACK_MS;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=step-duration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-duration.js","sourceRoot":"","sources":["../../src/timeline/step-duration.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAiB,EACjB,QAAuC,EACvC,KAAiC;IAEjC,MAAM,WAAW,GAAG,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAC3D,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,GAAG,CAAC;QAAE,OAAO,WAAW,CAAC;IAE/D,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IACtC,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared timing constants for the scenario playback engine.
|
|
3
|
+
*
|
|
4
|
+
* These values coordinate animation timing between the Cursor component
|
|
5
|
+
* (visual ripple) and the step-interactions hook (action dispatch).
|
|
6
|
+
* Both must agree on when the cursor has "arrived" at its target so
|
|
7
|
+
* the click ripple and the DOM click event fire in sync.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Milliseconds after a cursor target is set before the cursor is
|
|
11
|
+
* considered "arrived" and the click ripple appears.
|
|
12
|
+
*
|
|
13
|
+
* Derived from the Cursor spring parameters (stiffness 170,
|
|
14
|
+
* damping 22, mass 0.6) — the spring visually settles within
|
|
15
|
+
* this window for typical travel distances in the viewport.
|
|
16
|
+
*/
|
|
17
|
+
export declare const CLICK_DELAY_MS = 450;
|
|
18
|
+
/**
|
|
19
|
+
* Default milliseconds between characters for the `type` action.
|
|
20
|
+
*
|
|
21
|
+
* 50 ms per character = 20 characters/second — fast enough to feel
|
|
22
|
+
* like confident typing, slow enough that each character is readable
|
|
23
|
+
* in both browser playback and video export. Overridable per-action
|
|
24
|
+
* via {@link StepAction.typeDelay}.
|
|
25
|
+
*/
|
|
26
|
+
export declare const TYPE_CHAR_DELAY_MS = 50;
|
|
27
|
+
/**
|
|
28
|
+
* Default milliseconds to hold the cursor in place during a `hover`
|
|
29
|
+
* action, between the enter-event dispatch and the leave-event
|
|
30
|
+
* dispatch.
|
|
31
|
+
*
|
|
32
|
+
* 1500 ms gives viewers enough time to read a tooltip or notice a
|
|
33
|
+
* hover-state change in both browser playback and video export.
|
|
34
|
+
* Overridable per-action via {@link StepAction.hoverDuration}.
|
|
35
|
+
*/
|
|
36
|
+
export declare const HOVER_HOLD_MS = 1500;
|
|
37
|
+
/**
|
|
38
|
+
* Milliseconds to pause at the drag source after pressing before
|
|
39
|
+
* starting the drag movement to the destination.
|
|
40
|
+
*
|
|
41
|
+
* 200 ms mimics the brief human hesitation between mousedown and the
|
|
42
|
+
* start of a deliberate drag gesture.
|
|
43
|
+
*/
|
|
44
|
+
export declare const DRAG_SETTLE_MS = 200;
|
|
45
|
+
/**
|
|
46
|
+
* Expected milliseconds for the viewport transition spring to settle
|
|
47
|
+
* after a zoom or pan change.
|
|
48
|
+
*
|
|
49
|
+
* The ViewportTransformLayer uses a softer spring (stiffness 100,
|
|
50
|
+
* damping 20, mass 0.8) than the cursor spring, so it takes longer
|
|
51
|
+
* to settle. Used for dev-mode warnings when a subsequent cursor
|
|
52
|
+
* action is scheduled too close to a viewport transition.
|
|
53
|
+
*/
|
|
54
|
+
export declare const VIEWPORT_SETTLE_MS = 500;
|
|
55
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/timing/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,MAAM,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared timing constants for the scenario playback engine.
|
|
3
|
+
*
|
|
4
|
+
* These values coordinate animation timing between the Cursor component
|
|
5
|
+
* (visual ripple) and the step-interactions hook (action dispatch).
|
|
6
|
+
* Both must agree on when the cursor has "arrived" at its target so
|
|
7
|
+
* the click ripple and the DOM click event fire in sync.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Milliseconds after a cursor target is set before the cursor is
|
|
11
|
+
* considered "arrived" and the click ripple appears.
|
|
12
|
+
*
|
|
13
|
+
* Derived from the Cursor spring parameters (stiffness 170,
|
|
14
|
+
* damping 22, mass 0.6) — the spring visually settles within
|
|
15
|
+
* this window for typical travel distances in the viewport.
|
|
16
|
+
*/
|
|
17
|
+
export const CLICK_DELAY_MS = 450;
|
|
18
|
+
/**
|
|
19
|
+
* Default milliseconds between characters for the `type` action.
|
|
20
|
+
*
|
|
21
|
+
* 50 ms per character = 20 characters/second — fast enough to feel
|
|
22
|
+
* like confident typing, slow enough that each character is readable
|
|
23
|
+
* in both browser playback and video export. Overridable per-action
|
|
24
|
+
* via {@link StepAction.typeDelay}.
|
|
25
|
+
*/
|
|
26
|
+
export const TYPE_CHAR_DELAY_MS = 50;
|
|
27
|
+
/**
|
|
28
|
+
* Default milliseconds to hold the cursor in place during a `hover`
|
|
29
|
+
* action, between the enter-event dispatch and the leave-event
|
|
30
|
+
* dispatch.
|
|
31
|
+
*
|
|
32
|
+
* 1500 ms gives viewers enough time to read a tooltip or notice a
|
|
33
|
+
* hover-state change in both browser playback and video export.
|
|
34
|
+
* Overridable per-action via {@link StepAction.hoverDuration}.
|
|
35
|
+
*/
|
|
36
|
+
export const HOVER_HOLD_MS = 1500;
|
|
37
|
+
/**
|
|
38
|
+
* Milliseconds to pause at the drag source after pressing before
|
|
39
|
+
* starting the drag movement to the destination.
|
|
40
|
+
*
|
|
41
|
+
* 200 ms mimics the brief human hesitation between mousedown and the
|
|
42
|
+
* start of a deliberate drag gesture.
|
|
43
|
+
*/
|
|
44
|
+
export const DRAG_SETTLE_MS = 200;
|
|
45
|
+
/**
|
|
46
|
+
* Expected milliseconds for the viewport transition spring to settle
|
|
47
|
+
* after a zoom or pan change.
|
|
48
|
+
*
|
|
49
|
+
* The ViewportTransformLayer uses a softer spring (stiffness 100,
|
|
50
|
+
* damping 20, mass 0.8) than the cursor spring, so it takes longer
|
|
51
|
+
* to settle. Used for dev-mode warnings when a subsequent cursor
|
|
52
|
+
* action is scheduled too close to a viewport transition.
|
|
53
|
+
*/
|
|
54
|
+
export const VIEWPORT_SETTLE_MS = 500;
|
|
55
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/timing/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Viewport transform state produced by step interactions. */
|
|
2
|
+
export interface ViewportTransform {
|
|
3
|
+
scale: number;
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
/** The identity transform — no zoom, no translation. */
|
|
8
|
+
export declare const VIEWPORT_TRANSFORM_IDENTITY: Readonly<ViewportTransform>;
|
|
9
|
+
//# sourceMappingURL=transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/viewport/transform.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,wDAAwD;AACxD,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC,iBAAiB,CAInE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/viewport/transform.ts"],"names":[],"mappings":"AAOA,wDAAwD;AACxD,MAAM,CAAC,MAAM,2BAA2B,GAAgC;IACtE,KAAK,EAAE,CAAC;IACR,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;CACL,CAAC"}
|