@flyingrobots/bijou-tui 1.8.0 → 3.0.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/README.md +64 -21
- package/dist/animate.d.ts +0 -2
- package/dist/animate.d.ts.map +1 -1
- package/dist/animate.js +17 -26
- package/dist/animate.js.map +1 -1
- package/dist/app-frame-actions.d.ts +37 -0
- package/dist/app-frame-actions.d.ts.map +1 -0
- package/dist/app-frame-actions.js +313 -0
- package/dist/app-frame-actions.js.map +1 -0
- package/dist/app-frame-palette.d.ts +16 -0
- package/dist/app-frame-palette.d.ts.map +1 -0
- package/dist/app-frame-palette.js +158 -0
- package/dist/app-frame-palette.js.map +1 -0
- package/dist/app-frame-render.d.ts +39 -0
- package/dist/app-frame-render.d.ts.map +1 -0
- package/dist/app-frame-render.js +319 -0
- package/dist/app-frame-render.js.map +1 -0
- package/dist/app-frame-types.d.ts +135 -0
- package/dist/app-frame-types.d.ts.map +1 -0
- package/dist/app-frame-types.js +72 -0
- package/dist/app-frame-types.js.map +1 -0
- package/dist/app-frame-utils.d.ts +37 -0
- package/dist/app-frame-utils.d.ts.map +1 -0
- package/dist/app-frame-utils.js +141 -0
- package/dist/app-frame-utils.js.map +1 -0
- package/dist/app-frame.d.ts +13 -8
- package/dist/app-frame.d.ts.map +1 -1
- package/dist/app-frame.js +80 -906
- package/dist/app-frame.js.map +1 -1
- package/dist/canvas.d.ts +37 -25
- package/dist/canvas.d.ts.map +1 -1
- package/dist/canvas.js +116 -30
- package/dist/canvas.js.map +1 -1
- package/dist/commands.js +2 -2
- package/dist/commands.js.map +1 -1
- package/dist/css/install.d.ts +4 -0
- package/dist/css/install.d.ts.map +1 -0
- package/dist/css/install.js +24 -0
- package/dist/css/install.js.map +1 -0
- package/dist/css/parser.d.ts +14 -0
- package/dist/css/parser.d.ts.map +1 -0
- package/dist/css/parser.js +92 -0
- package/dist/css/parser.js.map +1 -0
- package/dist/css/resolver.d.ts +36 -0
- package/dist/css/resolver.d.ts.map +1 -0
- package/dist/css/resolver.js +130 -0
- package/dist/css/resolver.js.map +1 -0
- package/dist/css/text-style.d.ts +17 -0
- package/dist/css/text-style.d.ts.map +1 -0
- package/dist/css/text-style.js +59 -0
- package/dist/css/text-style.js.map +1 -0
- package/dist/css/types.d.ts +27 -0
- package/dist/css/types.d.ts.map +1 -0
- package/dist/css/types.js +5 -0
- package/dist/css/types.js.map +1 -0
- package/dist/driver.d.ts +10 -2
- package/dist/driver.d.ts.map +1 -1
- package/dist/driver.js +25 -2
- package/dist/driver.js.map +1 -1
- package/dist/eventbus.d.ts +42 -3
- package/dist/eventbus.d.ts.map +1 -1
- package/dist/eventbus.js +108 -7
- package/dist/eventbus.js.map +1 -1
- package/dist/focus-area.d.ts +4 -0
- package/dist/focus-area.d.ts.map +1 -1
- package/dist/focus-area.js +11 -1
- package/dist/focus-area.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/layout-v3.d.ts +10 -0
- package/dist/layout-v3.d.ts.map +1 -0
- package/dist/layout-v3.js +35 -0
- package/dist/layout-v3.js.map +1 -0
- package/dist/motion/motion.d.ts +14 -0
- package/dist/motion/motion.d.ts.map +1 -0
- package/dist/motion/motion.js +31 -0
- package/dist/motion/motion.js.map +1 -0
- package/dist/motion/reconciler.d.ts +15 -0
- package/dist/motion/reconciler.d.ts.map +1 -0
- package/dist/motion/reconciler.js +109 -0
- package/dist/motion/reconciler.js.map +1 -0
- package/dist/motion/types.d.ts +52 -0
- package/dist/motion/types.d.ts.map +1 -0
- package/dist/motion/types.js +2 -0
- package/dist/motion/types.js.map +1 -0
- package/dist/pipeline/middleware/css.d.ts +20 -0
- package/dist/pipeline/middleware/css.d.ts.map +1 -0
- package/dist/pipeline/middleware/css.js +41 -0
- package/dist/pipeline/middleware/css.js.map +1 -0
- package/dist/pipeline/middleware/grayscale.d.ts +9 -0
- package/dist/pipeline/middleware/grayscale.d.ts.map +1 -0
- package/dist/pipeline/middleware/grayscale.js +39 -0
- package/dist/pipeline/middleware/grayscale.js.map +1 -0
- package/dist/pipeline/middleware/motion.d.ts +6 -0
- package/dist/pipeline/middleware/motion.d.ts.map +1 -0
- package/dist/pipeline/middleware/motion.js +19 -0
- package/dist/pipeline/middleware/motion.js.map +1 -0
- package/dist/pipeline/middleware/paint.d.ts +6 -0
- package/dist/pipeline/middleware/paint.d.ts.map +1 -0
- package/dist/pipeline/middleware/paint.js +21 -0
- package/dist/pipeline/middleware/paint.js.map +1 -0
- package/dist/pipeline/pipeline.d.ts +56 -0
- package/dist/pipeline/pipeline.d.ts.map +1 -0
- package/dist/pipeline/pipeline.js +45 -0
- package/dist/pipeline/pipeline.js.map +1 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +153 -8
- package/dist/runtime.js.map +1 -1
- package/dist/screen.d.ts +12 -1
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +14 -1
- package/dist/screen.js.map +1 -1
- package/dist/subapp/mount.d.ts +67 -0
- package/dist/subapp/mount.d.ts.map +1 -0
- package/dist/subapp/mount.js +60 -0
- package/dist/subapp/mount.js.map +1 -0
- package/dist/transition-shaders.d.ts +101 -3
- package/dist/transition-shaders.d.ts.map +1 -1
- package/dist/transition-shaders.js +281 -6
- package/dist/transition-shaders.js.map +1 -1
- package/dist/types.d.ts +45 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -1
- package/dist/view-output.d.ts +15 -0
- package/dist/view-output.d.ts.map +1 -0
- package/dist/view-output.js +53 -0
- package/dist/view-output.js.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,38 +1,79 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@flyingrobots/bijou-tui`
|
|
2
2
|
|
|
3
|
-
TEA runtime for
|
|
3
|
+
The high-fidelity TEA runtime for Bijou.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`bijou-tui` provides the application loop, layout primitives, motion, and orchestration needed to build complex interactive terminal apps on top of the Bijou core.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## V3.0.0 Evolution
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- **`grid()`** — fixed + fractional track solver with named areas and stable layout geometry.
|
|
11
|
-
- **`createFramedApp()`** — shell scaffolding for tabs, pane focus/scroll isolation, help, overlays, and command palette.
|
|
12
|
-
- **`drawer()` upgrades** — supports `left`/`right`/`top`/`bottom` anchors and optional panel `region` mounting.
|
|
13
|
-
- **`runScript()` upgrades** — scripted driver now supports key, resize, and custom-message steps for richer integration harnesses.
|
|
9
|
+
The TUI package has been completely overhauled in v3.0.0 to operate as a true graphics engine.
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
### 🌟 What's New
|
|
12
|
+
- **Honest view contract:** `App.view` and framed pane renderers now speak `ViewOutput` (`string | Surface | LayoutNode`). Strings still work, but they are the legacy compatibility path.
|
|
13
|
+
- **Programmable Rendering Pipeline:** The TEA `view` output is now processed through a 5-stage middleware pipeline (`Layout -> Paint -> PostProcess -> Diff -> Output`). Add custom fragment shaders or logging middleware effortlessly.
|
|
14
|
+
- **Fractal TEA (Sub-Apps):** Compose nested apps with `initSubApp()`, `updateSubApp()`, `mount()`, and `mapCmds()` instead of flattening everything into one update loop.
|
|
15
|
+
- **Bijou CSS (BCSS):** Style supported V3 surface components and frame shell regions with type/class/id selectors, `var()` token lookups, and terminal-aware media queries (`@media (width < 80)`). This is not yet a global cascade across arbitrary layout nodes.
|
|
16
|
+
- **Declarative Motion:** Wrap any component in `motion({ key: 'id' }, ...)` and watch it smoothly interpolate layout changes (move, resize) using physics-based springs.
|
|
17
|
+
- **Unified Heartbeat:** All animations and physics calculations are now synchronized to a single `PulseMsg`, eliminating timer jitter and saving CPU.
|
|
16
18
|
|
|
17
|
-
##
|
|
19
|
+
## Installation
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
```bash
|
|
22
|
+
npm install @flyingrobots/bijou@3.0.0 @flyingrobots/bijou-node@3.0.0 @flyingrobots/bijou-tui@3.0.0
|
|
23
|
+
```
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
- End-to-end examples live in [`/examples`](https://github.com/flyingrobots/bijou/tree/main/examples)
|
|
23
|
-
- Release-level changes live in the [CHANGELOG](https://github.com/flyingrobots/bijou/blob/main/docs/CHANGELOG.md)
|
|
25
|
+
If you are upgrading an existing app, see [`../../docs/MIGRATING_TO_V3.md`](../../docs/MIGRATING_TO_V3.md).
|
|
24
26
|
|
|
25
|
-
##
|
|
27
|
+
## Quick Start (V3 Sub-App Composition)
|
|
26
28
|
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
+
```typescript
|
|
30
|
+
import { initDefaultContext } from '@flyingrobots/bijou-node';
|
|
31
|
+
import { run, mount, mapCmds, type App } from '@flyingrobots/bijou-tui';
|
|
32
|
+
import { createSurface, type Surface } from '@flyingrobots/bijou';
|
|
33
|
+
|
|
34
|
+
initDefaultContext();
|
|
35
|
+
|
|
36
|
+
// Minimal child apps
|
|
37
|
+
const childApp: App<{ count: number }, any> = {
|
|
38
|
+
init: () => [{ count: 0 }, []],
|
|
39
|
+
update: (msg, model) => [model, []],
|
|
40
|
+
view: (model) => {
|
|
41
|
+
const s = createSurface(20, 5);
|
|
42
|
+
s.fill({ char: '.' });
|
|
43
|
+
return s;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
interface Model {
|
|
48
|
+
left: { count: number };
|
|
49
|
+
right: { count: number };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Parent App mounting two independent Sub-Apps
|
|
53
|
+
const app: App<Model, any> = {
|
|
54
|
+
init: () => [{ left: { count: 0 }, right: { count: 0 } }, []],
|
|
55
|
+
update: (msg, model) => [model, []],
|
|
56
|
+
view: (model) => {
|
|
57
|
+
// Render the children (they return Surfaces!)
|
|
58
|
+
const [leftSurface] = mount(childApp, { model: model.left, onMsg: m => m });
|
|
59
|
+
const [rightSurface] = mount(childApp, { model: model.right, onMsg: m => m });
|
|
60
|
+
|
|
61
|
+
// Composite them onto the main screen
|
|
62
|
+
const screen = createSurface(80, 24);
|
|
63
|
+
screen.blit(leftSurface, 0, 0);
|
|
64
|
+
screen.blit(rightSurface, 40, 0);
|
|
65
|
+
return screen;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
run(app);
|
|
29
70
|
```
|
|
30
71
|
|
|
31
|
-
## Quick Start
|
|
72
|
+
## Quick Start (Basic)
|
|
32
73
|
|
|
33
74
|
```typescript
|
|
34
75
|
import { initDefaultContext } from '@flyingrobots/bijou-node';
|
|
35
|
-
import { run, quit,
|
|
76
|
+
import { run, quit, type App, isKeyMsg } from '@flyingrobots/bijou-tui';
|
|
36
77
|
|
|
37
78
|
initDefaultContext();
|
|
38
79
|
|
|
@@ -42,7 +83,7 @@ const app: App<Model> = {
|
|
|
42
83
|
init: () => [{ count: 0 }, []],
|
|
43
84
|
|
|
44
85
|
update: (msg, model) => {
|
|
45
|
-
if (msg
|
|
86
|
+
if (isKeyMsg(msg)) {
|
|
46
87
|
if (msg.key === 'q') return [model, [quit()]];
|
|
47
88
|
if (msg.key === '+') return [{ count: model.count + 1 }, []];
|
|
48
89
|
if (msg.key === '-') return [{ count: model.count - 1 }, []];
|
|
@@ -373,6 +414,8 @@ Each overlay is a `{ content, row, col }` object. `composite()` splices them ont
|
|
|
373
414
|
- frame help (`?`) and optional command palette (`ctrl+p` / `:`)
|
|
374
415
|
- overlay factory with pane rects for panel-scoped drawers/modals
|
|
375
416
|
|
|
417
|
+
Pane renderers may return a legacy string, a `Surface`, or a `LayoutNode`. The shell normalizes those outputs into the framed scroll/focus path for you.
|
|
418
|
+
|
|
376
419
|
See `examples/release-workbench/main.ts` for the canonical shell demo and `examples/app-frame/main.ts` for a compact focused example.
|
|
377
420
|
|
|
378
421
|
## Building Blocks
|
package/dist/animate.d.ts
CHANGED
|
@@ -26,8 +26,6 @@ interface AnimateBase<M> {
|
|
|
26
26
|
readonly from: number;
|
|
27
27
|
/** Target value. */
|
|
28
28
|
readonly to: number;
|
|
29
|
-
/** Frames per second. Default: 60. */
|
|
30
|
-
readonly fps?: number;
|
|
31
29
|
/** Skip animation — jump to target in one frame. Default: false. */
|
|
32
30
|
readonly immediate?: boolean;
|
|
33
31
|
/** Called each frame with the interpolated value. Return a message for TEA. */
|
package/dist/animate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animate.d.ts","sourceRoot":"","sources":["../src/animate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,QAAQ,EAQd,MAAM,aAAa,CAAC;AAMrB;;;;GAIG;AACH,UAAU,WAAW,CAAC,CAAC;IACrB,sBAAsB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,
|
|
1
|
+
{"version":3,"file":"animate.d.ts","sourceRoot":"","sources":["../src/animate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,QAAQ,EAQd,MAAM,aAAa,CAAC;AAMrB;;;;GAIG;AACH,UAAU,WAAW,CAAC,CAAC;IACrB,sBAAsB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;IACvC,qEAAqE;IACrE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAC7D,kFAAkF;IAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IACzB,oDAAoD;IACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAC5D,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,oBAAoB,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAMjF;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAiB7D;AA+FD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAMrD"}
|
package/dist/animate.js
CHANGED
|
@@ -31,7 +31,7 @@ import { springStep, createSpringState, resolveSpringConfig, tweenStep, createTw
|
|
|
31
31
|
* @returns A TEA command that emits `onFrame` messages as the animation progresses.
|
|
32
32
|
*/
|
|
33
33
|
export function animate(options) {
|
|
34
|
-
const { from, to,
|
|
34
|
+
const { from, to, immediate = false, onFrame, onComplete } = options;
|
|
35
35
|
// Immediate mode — single frame, no physics
|
|
36
36
|
if (immediate) {
|
|
37
37
|
return async (emit) => {
|
|
@@ -41,10 +41,10 @@ export function animate(options) {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
if (options.type === 'tween') {
|
|
44
|
-
return createTweenCmd(from, to, options.duration, options.ease ?? EASINGS.easeOutCubic,
|
|
44
|
+
return createTweenCmd(from, to, options.duration, options.ease ?? EASINGS.easeOutCubic, onFrame, onComplete);
|
|
45
45
|
}
|
|
46
46
|
const config = resolveSpringConfig(options.spring);
|
|
47
|
-
return createSpringCmd(from, to, config,
|
|
47
|
+
return createSpringCmd(from, to, config, onFrame, onComplete);
|
|
48
48
|
}
|
|
49
49
|
// ---------------------------------------------------------------------------
|
|
50
50
|
// Internal: spring command
|
|
@@ -61,24 +61,19 @@ export function animate(options) {
|
|
|
61
61
|
* @param onComplete - Optional callback invoked when the spring settles.
|
|
62
62
|
* @returns A TEA command that resolves when the spring is done.
|
|
63
63
|
*/
|
|
64
|
-
function createSpringCmd(from, to, config,
|
|
65
|
-
return (emit) => new Promise((resolve) => {
|
|
64
|
+
function createSpringCmd(from, to, config, onFrame, onComplete) {
|
|
65
|
+
return (emit, caps) => new Promise((resolve) => {
|
|
66
66
|
let state = createSpringState(from);
|
|
67
|
-
const
|
|
68
|
-
let lastMs = Date.now();
|
|
69
|
-
const id = setInterval(() => {
|
|
70
|
-
const nowMs = Date.now();
|
|
71
|
-
const dt = Math.max(0, (nowMs - lastMs) / 1000);
|
|
72
|
-
lastMs = nowMs;
|
|
67
|
+
const handle = caps.onPulse((dt) => {
|
|
73
68
|
state = springStep(state, to, config, dt);
|
|
74
69
|
emit(onFrame(state.value));
|
|
75
70
|
if (state.done) {
|
|
76
|
-
|
|
71
|
+
handle.dispose();
|
|
77
72
|
if (onComplete)
|
|
78
73
|
emit(onComplete());
|
|
79
74
|
resolve();
|
|
80
75
|
}
|
|
81
|
-
}
|
|
76
|
+
});
|
|
82
77
|
});
|
|
83
78
|
}
|
|
84
79
|
// ---------------------------------------------------------------------------
|
|
@@ -101,25 +96,21 @@ function createSpringCmd(from, to, config, fps, onFrame, onComplete) {
|
|
|
101
96
|
* @param onComplete - Optional callback invoked when the tween completes.
|
|
102
97
|
* @returns A TEA command that resolves when the tween is done.
|
|
103
98
|
*/
|
|
104
|
-
function createTweenCmd(from, to, duration, ease,
|
|
99
|
+
function createTweenCmd(from, to, duration, ease, onFrame, onComplete) {
|
|
105
100
|
const config = resolveTweenConfig({ from, to, duration, ease });
|
|
106
|
-
return (emit) => new Promise((resolve) => {
|
|
101
|
+
return (emit, caps) => new Promise((resolve) => {
|
|
107
102
|
let state = createTweenState(from);
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const nowMs = Date.now();
|
|
112
|
-
const dtMs = Math.max(0, nowMs - lastMs);
|
|
113
|
-
lastMs = nowMs;
|
|
114
|
-
state = tweenStep(state, config, dtMs);
|
|
103
|
+
const handle = caps.onPulse((dt) => {
|
|
104
|
+
// TweenStep expects milliseconds for delta
|
|
105
|
+
state = tweenStep(state, config, dt * 1000);
|
|
115
106
|
emit(onFrame(state.value));
|
|
116
107
|
if (state.done) {
|
|
117
|
-
|
|
108
|
+
handle.dispose();
|
|
118
109
|
if (onComplete)
|
|
119
110
|
emit(onComplete());
|
|
120
111
|
resolve();
|
|
121
112
|
}
|
|
122
|
-
}
|
|
113
|
+
});
|
|
123
114
|
});
|
|
124
115
|
}
|
|
125
116
|
// ---------------------------------------------------------------------------
|
|
@@ -133,9 +124,9 @@ function createTweenCmd(from, to, duration, ease, fps, onFrame, onComplete) {
|
|
|
133
124
|
* @returns A single TEA command that runs all commands serially.
|
|
134
125
|
*/
|
|
135
126
|
export function sequence(...cmds) {
|
|
136
|
-
return async (emit) => {
|
|
127
|
+
return async (emit, caps) => {
|
|
137
128
|
for (const cmd of cmds) {
|
|
138
|
-
await cmd(emit);
|
|
129
|
+
await cmd(emit, caps);
|
|
139
130
|
}
|
|
140
131
|
};
|
|
141
132
|
}
|
package/dist/animate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animate.js","sourceRoot":"","sources":["../src/animate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAIL,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,gBAAgB,EAChB,kBAAkB,EAClB,OAAO,GACR,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"animate.js","sourceRoot":"","sources":["../src/animate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State reducers for `app-frame.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Tab switching, pane cycling, scroll actions, minimize/maximize/dock,
|
|
5
|
+
* page frame state sync, and transition tick command.
|
|
6
|
+
*/
|
|
7
|
+
import type { FramePage, CreateFramedAppOptions } from './app-frame.js';
|
|
8
|
+
import type { InternalFrameModel, FrameAction } from './app-frame-types.js';
|
|
9
|
+
import type { Cmd } from './types.js';
|
|
10
|
+
import type { DockDirection } from './panel-dock.js';
|
|
11
|
+
/** Dispatch a frame-level action (tab switch, pane cycle, scroll, palette, help toggle, transitions). */
|
|
12
|
+
export declare function applyFrameAction<PageModel, Msg>(action: FrameAction, model: InternalFrameModel<PageModel, Msg>, options: CreateFramedAppOptions<PageModel, Msg>, pagesById: Map<string, FramePage<PageModel, Msg>>): [InternalFrameModel<PageModel, Msg>, Cmd<Msg>[]];
|
|
13
|
+
/** Cycle the active tab by `delta` positions, optionally starting a transition. */
|
|
14
|
+
export declare function switchTab<PageModel, Msg>(model: InternalFrameModel<PageModel, Msg>, delta: number, pagesById: Map<string, FramePage<PageModel, Msg>>, options: CreateFramedAppOptions<PageModel, Msg>): [InternalFrameModel<PageModel, Msg>, Cmd<Msg>[]];
|
|
15
|
+
/** Move focus to the next or previous pane in the active page's layout. */
|
|
16
|
+
export declare function cyclePane<PageModel, Msg>(model: InternalFrameModel<PageModel, Msg>, delta: number, pagesById: Map<string, FramePage<PageModel, Msg>>): InternalFrameModel<PageModel, Msg>;
|
|
17
|
+
/** Apply a scroll action to the currently focused pane. */
|
|
18
|
+
export declare function scrollFocusedPane<PageModel, Msg>(model: InternalFrameModel<PageModel, Msg>, action: Extract<FrameAction, {
|
|
19
|
+
type: 'scroll-up' | 'scroll-down' | 'page-up' | 'page-down' | 'top' | 'bottom' | 'scroll-left' | 'scroll-right';
|
|
20
|
+
}>, pagesById: Map<string, FramePage<PageModel, Msg>>): InternalFrameModel<PageModel, Msg>;
|
|
21
|
+
/** Toggle minimize on the focused pane of the active page. */
|
|
22
|
+
export declare function applyToggleMinimize<PageModel, Msg>(model: InternalFrameModel<PageModel, Msg>, pagesById: Map<string, FramePage<PageModel, Msg>>): InternalFrameModel<PageModel, Msg>;
|
|
23
|
+
/** Toggle maximize on the focused pane of the active page. */
|
|
24
|
+
export declare function applyToggleMaximize<PageModel, Msg>(model: InternalFrameModel<PageModel, Msg>, _pagesById: Map<string, FramePage<PageModel, Msg>>): InternalFrameModel<PageModel, Msg>;
|
|
25
|
+
/** Move the focused pane within its container in the given direction. */
|
|
26
|
+
export declare function applyDockMove<PageModel, Msg>(model: InternalFrameModel<PageModel, Msg>, direction: DockDirection, pagesById: Map<string, FramePage<PageModel, Msg>>): InternalFrameModel<PageModel, Msg>;
|
|
27
|
+
/** Reconcile pane IDs, scroll offsets, and focus for a page after init, tab switches, or window resizes. */
|
|
28
|
+
export declare function syncPageFrameState<PageModel, Msg>(model: InternalFrameModel<PageModel, Msg>, pageId: string, pagesById: Map<string, FramePage<PageModel, Msg>>): InternalFrameModel<PageModel, Msg>;
|
|
29
|
+
/**
|
|
30
|
+
* Create a TEA command that drives transition re-renders via `setInterval`.
|
|
31
|
+
*
|
|
32
|
+
* Each tick emits a frame-scoped 'transition' message. The actual progress
|
|
33
|
+
* is computed from wall-clock time in the update handler, not from the
|
|
34
|
+
* interval count. The interval just schedules re-renders.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createTransitionTickCmd<Msg>(durationMs: number, generation: number): Cmd<Msg>;
|
|
37
|
+
//# sourceMappingURL=app-frame-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-frame-actions.d.ts","sourceRoot":"","sources":["../src/app-frame-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State reducers for `app-frame.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Tab switching, pane cycling, scroll actions, minimize/maximize/dock,
|
|
5
|
+
* page frame state sync, and transition tick command.
|
|
6
|
+
*/
|
|
7
|
+
import { wrapFrameMsg } from './app-frame-types.js';
|
|
8
|
+
import { createPanelVisibilityState, createPanelMaximizeState, toggleMinimized, restorePane, isMinimized, toggleMaximize, } from './panel-state.js';
|
|
9
|
+
import { createPanelDockState, movePaneInContainer, resolveChildOrder, findPaneContainer, } from './panel-dock.js';
|
|
10
|
+
import { createFocusAreaState, focusAreaScrollBy, focusAreaScrollByX, focusAreaScrollToBottom, focusAreaScrollToTop, focusAreaPageDown, focusAreaPageUp, focusAreaScrollTo, focusAreaScrollToX, } from './focus-area.js';
|
|
11
|
+
import { timeline } from './timeline.js';
|
|
12
|
+
import { EASINGS } from './spring.js';
|
|
13
|
+
import { collectPaneIds, assertUniquePaneIds, findPaneNode, frameBodyRect, } from './app-frame-utils.js';
|
|
14
|
+
import { framePaneOutputToString, renderFrameNode } from './app-frame-render.js';
|
|
15
|
+
/** Dispatch a frame-level action (tab switch, pane cycle, scroll, palette, help toggle, transitions). */
|
|
16
|
+
export function applyFrameAction(action, model, options, pagesById) {
|
|
17
|
+
switch (action.type) {
|
|
18
|
+
case 'toggle-help':
|
|
19
|
+
return [{ ...model, helpOpen: !model.helpOpen }, []];
|
|
20
|
+
case 'prev-tab':
|
|
21
|
+
return switchTab(model, -1, pagesById, options);
|
|
22
|
+
case 'next-tab':
|
|
23
|
+
return switchTab(model, 1, pagesById, options);
|
|
24
|
+
case 'next-pane':
|
|
25
|
+
return [cyclePane(model, 1, pagesById), []];
|
|
26
|
+
case 'prev-pane':
|
|
27
|
+
return [cyclePane(model, -1, pagesById), []];
|
|
28
|
+
case 'open-palette':
|
|
29
|
+
// Palette opening is gated by `enableCommandPalette` and handled in the
|
|
30
|
+
// key-handler path of app-frame.ts → openCommandPalette(). This no-op
|
|
31
|
+
// covers the recursive case (e.g., a palette frame-action entry that
|
|
32
|
+
// would re-trigger open-palette while the palette is already open).
|
|
33
|
+
return [model, []];
|
|
34
|
+
case 'toggle-minimize':
|
|
35
|
+
return [applyToggleMinimize(model, pagesById), []];
|
|
36
|
+
case 'toggle-maximize':
|
|
37
|
+
return [applyToggleMaximize(model, pagesById), []];
|
|
38
|
+
case 'dock-up':
|
|
39
|
+
case 'dock-down':
|
|
40
|
+
case 'dock-left':
|
|
41
|
+
case 'dock-right': {
|
|
42
|
+
const dir = action.type.replace('dock-', '');
|
|
43
|
+
return [applyDockMove(model, dir, pagesById), []];
|
|
44
|
+
}
|
|
45
|
+
case 'scroll-up':
|
|
46
|
+
case 'scroll-down':
|
|
47
|
+
case 'page-up':
|
|
48
|
+
case 'page-down':
|
|
49
|
+
case 'top':
|
|
50
|
+
case 'bottom':
|
|
51
|
+
case 'scroll-left':
|
|
52
|
+
case 'scroll-right':
|
|
53
|
+
return [scrollFocusedPane(model, action, pagesById), []];
|
|
54
|
+
case 'transition':
|
|
55
|
+
case 'transition-complete':
|
|
56
|
+
return [model, []];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Cycle the active tab by `delta` positions, optionally starting a transition. */
|
|
60
|
+
export function switchTab(model, delta, pagesById, options) {
|
|
61
|
+
const idx = model.pageOrder.indexOf(model.activePageId);
|
|
62
|
+
if (idx < 0)
|
|
63
|
+
return [model, []];
|
|
64
|
+
const nextIdx = (idx + delta + model.pageOrder.length) % model.pageOrder.length;
|
|
65
|
+
const nextId = model.pageOrder[nextIdx];
|
|
66
|
+
if (nextId === model.activePageId)
|
|
67
|
+
return [model, []];
|
|
68
|
+
const activePageModel = model.pageModels[model.activePageId];
|
|
69
|
+
const activeTransition = options.transitionOverride
|
|
70
|
+
? options.transitionOverride(activePageModel)
|
|
71
|
+
: options.transition;
|
|
72
|
+
const hasTransition = activeTransition != null && activeTransition !== 'none';
|
|
73
|
+
const nextGeneration = model.transitionGeneration + 1;
|
|
74
|
+
// Use the user-supplied timeline if provided, otherwise build a default.
|
|
75
|
+
// The timeline MUST contain a 'progress' track (0 → 1).
|
|
76
|
+
const tl = hasTransition
|
|
77
|
+
? (options.transitionTimeline ?? timeline()
|
|
78
|
+
.add('progress', {
|
|
79
|
+
type: 'tween',
|
|
80
|
+
from: 0,
|
|
81
|
+
to: 1,
|
|
82
|
+
duration: options.transitionDuration ?? 300,
|
|
83
|
+
ease: EASINGS.easeInOutCubic,
|
|
84
|
+
})
|
|
85
|
+
.build())
|
|
86
|
+
: undefined;
|
|
87
|
+
const durationMs = tl?.estimatedDurationMs ?? options.transitionDuration ?? 300;
|
|
88
|
+
const nextModel = syncPageFrameState({
|
|
89
|
+
...model,
|
|
90
|
+
activePageId: nextId,
|
|
91
|
+
previousPageId: model.activePageId,
|
|
92
|
+
activeTransition,
|
|
93
|
+
transitionProgress: hasTransition ? 0 : 1,
|
|
94
|
+
transitionGeneration: nextGeneration,
|
|
95
|
+
transitionFrame: 0,
|
|
96
|
+
transitionStartMs: hasTransition ? Date.now() : undefined,
|
|
97
|
+
transitionTimeline: tl,
|
|
98
|
+
transitionTimelineState: tl?.init(),
|
|
99
|
+
}, nextId, pagesById);
|
|
100
|
+
if (hasTransition) {
|
|
101
|
+
// Schedule render ticks at ~60fps for the duration of the transition.
|
|
102
|
+
// Each tick advances the timeline using wall-clock elapsed time.
|
|
103
|
+
const cmd = createTransitionTickCmd(durationMs, nextGeneration);
|
|
104
|
+
return [nextModel, [cmd]];
|
|
105
|
+
}
|
|
106
|
+
return [nextModel, []];
|
|
107
|
+
}
|
|
108
|
+
/** Move focus to the next or previous pane in the active page's layout. */
|
|
109
|
+
export function cyclePane(model, delta, pagesById) {
|
|
110
|
+
const page = pagesById.get(model.activePageId);
|
|
111
|
+
const paneIds = collectPaneIds(page.layout(model.pageModels[model.activePageId]));
|
|
112
|
+
if (paneIds.length === 0)
|
|
113
|
+
return model;
|
|
114
|
+
const curr = model.focusedPaneByPage[model.activePageId];
|
|
115
|
+
const idx = curr == null ? 0 : paneIds.indexOf(curr);
|
|
116
|
+
const nextIdx = idx < 0
|
|
117
|
+
? 0
|
|
118
|
+
: (idx + delta + paneIds.length) % paneIds.length;
|
|
119
|
+
const next = paneIds[nextIdx];
|
|
120
|
+
return {
|
|
121
|
+
...model,
|
|
122
|
+
focusedPaneByPage: {
|
|
123
|
+
...model.focusedPaneByPage,
|
|
124
|
+
[model.activePageId]: next,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Apply a scroll action to the currently focused pane. */
|
|
129
|
+
export function scrollFocusedPane(model, action, pagesById) {
|
|
130
|
+
const pageId = model.activePageId;
|
|
131
|
+
const focusedPaneId = model.focusedPaneByPage[pageId];
|
|
132
|
+
if (focusedPaneId == null)
|
|
133
|
+
return model;
|
|
134
|
+
const page = pagesById.get(pageId);
|
|
135
|
+
const layoutTree = page.layout(model.pageModels[pageId]);
|
|
136
|
+
const bodyRect = frameBodyRect(model.columns, model.rows);
|
|
137
|
+
const resolved = renderFrameNode(layoutTree, bodyRect, {
|
|
138
|
+
model,
|
|
139
|
+
pageId,
|
|
140
|
+
focusedPaneId,
|
|
141
|
+
scrollByPane: model.scrollByPage[pageId] ?? {},
|
|
142
|
+
visibility: model.minimizedByPage[pageId] ?? createPanelVisibilityState(),
|
|
143
|
+
dockState: model.dockStateByPage[pageId] ?? createPanelDockState(),
|
|
144
|
+
});
|
|
145
|
+
const paneRect = resolved.paneRects.get(focusedPaneId);
|
|
146
|
+
if (paneRect == null || paneRect.width <= 0 || paneRect.height <= 0)
|
|
147
|
+
return model;
|
|
148
|
+
const paneNode = findPaneNode(layoutTree, focusedPaneId);
|
|
149
|
+
if (paneNode == null)
|
|
150
|
+
return model;
|
|
151
|
+
const content = framePaneOutputToString(paneNode.render(paneRect.width, paneRect.height), paneRect.width, paneRect.height);
|
|
152
|
+
let state = createFocusAreaState({
|
|
153
|
+
content,
|
|
154
|
+
width: paneRect.width,
|
|
155
|
+
height: paneRect.height,
|
|
156
|
+
overflowX: paneNode.overflowX ?? 'hidden',
|
|
157
|
+
});
|
|
158
|
+
const prior = model.scrollByPage[pageId]?.[focusedPaneId] ?? { x: 0, y: 0 };
|
|
159
|
+
state = focusAreaScrollTo(state, prior.y);
|
|
160
|
+
state = focusAreaScrollToX(state, prior.x);
|
|
161
|
+
switch (action.type) {
|
|
162
|
+
case 'scroll-up':
|
|
163
|
+
state = focusAreaScrollBy(state, -1);
|
|
164
|
+
break;
|
|
165
|
+
case 'scroll-down':
|
|
166
|
+
state = focusAreaScrollBy(state, 1);
|
|
167
|
+
break;
|
|
168
|
+
case 'page-up':
|
|
169
|
+
state = focusAreaPageUp(state);
|
|
170
|
+
break;
|
|
171
|
+
case 'page-down':
|
|
172
|
+
state = focusAreaPageDown(state);
|
|
173
|
+
break;
|
|
174
|
+
case 'top':
|
|
175
|
+
state = focusAreaScrollToTop(state);
|
|
176
|
+
break;
|
|
177
|
+
case 'bottom':
|
|
178
|
+
state = focusAreaScrollToBottom(state);
|
|
179
|
+
break;
|
|
180
|
+
case 'scroll-left':
|
|
181
|
+
state = focusAreaScrollByX(state, -1);
|
|
182
|
+
break;
|
|
183
|
+
case 'scroll-right':
|
|
184
|
+
state = focusAreaScrollByX(state, 1);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
const pageScroll = model.scrollByPage[pageId] ?? {};
|
|
188
|
+
return {
|
|
189
|
+
...model,
|
|
190
|
+
scrollByPage: {
|
|
191
|
+
...model.scrollByPage,
|
|
192
|
+
[pageId]: {
|
|
193
|
+
...pageScroll,
|
|
194
|
+
[focusedPaneId]: { x: state.scroll.x, y: state.scroll.y },
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/** Toggle minimize on the focused pane of the active page. */
|
|
200
|
+
export function applyToggleMinimize(model, pagesById) {
|
|
201
|
+
const pageId = model.activePageId;
|
|
202
|
+
const focusedPaneId = model.focusedPaneByPage[pageId];
|
|
203
|
+
if (focusedPaneId == null)
|
|
204
|
+
return model;
|
|
205
|
+
const page = pagesById.get(pageId);
|
|
206
|
+
const allPaneIds = collectPaneIds(page.layout(model.pageModels[pageId]));
|
|
207
|
+
const current = model.minimizedByPage[pageId] ?? createPanelVisibilityState();
|
|
208
|
+
const next = toggleMinimized(current, focusedPaneId, allPaneIds);
|
|
209
|
+
// If we just minimized the focused pane, move focus to a non-minimized sibling
|
|
210
|
+
let newFocused = focusedPaneId;
|
|
211
|
+
if (isMinimized(next, focusedPaneId)) {
|
|
212
|
+
const visible = allPaneIds.filter((id) => !isMinimized(next, id));
|
|
213
|
+
newFocused = visible[0] ?? focusedPaneId;
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
...model,
|
|
217
|
+
minimizedByPage: { ...model.minimizedByPage, [pageId]: next },
|
|
218
|
+
focusedPaneByPage: { ...model.focusedPaneByPage, [pageId]: newFocused },
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/** Toggle maximize on the focused pane of the active page. */
|
|
222
|
+
export function applyToggleMaximize(model, _pagesById) {
|
|
223
|
+
const pageId = model.activePageId;
|
|
224
|
+
const focusedPaneId = model.focusedPaneByPage[pageId];
|
|
225
|
+
if (focusedPaneId == null)
|
|
226
|
+
return model;
|
|
227
|
+
const current = model.maximizedPaneByPage[pageId] ?? createPanelMaximizeState();
|
|
228
|
+
const next = toggleMaximize(current, focusedPaneId);
|
|
229
|
+
// If maximizing a minimized pane, restore it first
|
|
230
|
+
let visibility = model.minimizedByPage[pageId] ?? createPanelVisibilityState();
|
|
231
|
+
if (next.maximizedPaneId && isMinimized(visibility, next.maximizedPaneId)) {
|
|
232
|
+
visibility = restorePane(visibility, next.maximizedPaneId);
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
...model,
|
|
236
|
+
maximizedPaneByPage: { ...model.maximizedPaneByPage, [pageId]: next },
|
|
237
|
+
minimizedByPage: { ...model.minimizedByPage, [pageId]: visibility },
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/** Move the focused pane within its container in the given direction. */
|
|
241
|
+
export function applyDockMove(model, direction, pagesById) {
|
|
242
|
+
const pageId = model.activePageId;
|
|
243
|
+
const focusedPaneId = model.focusedPaneByPage[pageId];
|
|
244
|
+
if (focusedPaneId == null)
|
|
245
|
+
return model;
|
|
246
|
+
const page = pagesById.get(pageId);
|
|
247
|
+
const layoutTree = page.layout(model.pageModels[pageId]);
|
|
248
|
+
const container = findPaneContainer(layoutTree, focusedPaneId);
|
|
249
|
+
if (container == null)
|
|
250
|
+
return model;
|
|
251
|
+
const dockState = model.dockStateByPage[pageId] ?? createPanelDockState();
|
|
252
|
+
const currentOrder = resolveChildOrder(dockState, container.containerId, container.childIds);
|
|
253
|
+
const next = movePaneInContainer(dockState, container.containerId, focusedPaneId, direction, currentOrder);
|
|
254
|
+
return {
|
|
255
|
+
...model,
|
|
256
|
+
dockStateByPage: { ...model.dockStateByPage, [pageId]: next },
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/** Reconcile pane IDs, scroll offsets, and focus for a page after init, tab switches, or window resizes. */
|
|
260
|
+
export function syncPageFrameState(model, pageId, pagesById) {
|
|
261
|
+
const page = pagesById.get(pageId);
|
|
262
|
+
const paneIds = collectPaneIds(page.layout(model.pageModels[pageId]));
|
|
263
|
+
assertUniquePaneIds(paneIds, `page "${pageId}" layout`);
|
|
264
|
+
const prevScroll = model.scrollByPage[pageId] ?? {};
|
|
265
|
+
const nextScroll = {};
|
|
266
|
+
for (const paneId of paneIds) {
|
|
267
|
+
nextScroll[paneId] = prevScroll[paneId] ?? { x: 0, y: 0 };
|
|
268
|
+
}
|
|
269
|
+
const prevFocused = model.focusedPaneByPage[pageId];
|
|
270
|
+
const focused = prevFocused != null && paneIds.includes(prevFocused)
|
|
271
|
+
? prevFocused
|
|
272
|
+
: paneIds[0];
|
|
273
|
+
return {
|
|
274
|
+
...model,
|
|
275
|
+
focusedPaneByPage: {
|
|
276
|
+
...model.focusedPaneByPage,
|
|
277
|
+
[pageId]: focused,
|
|
278
|
+
},
|
|
279
|
+
scrollByPage: {
|
|
280
|
+
...model.scrollByPage,
|
|
281
|
+
[pageId]: nextScroll,
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Create a TEA command that drives transition re-renders via `setInterval`.
|
|
287
|
+
*
|
|
288
|
+
* Each tick emits a frame-scoped 'transition' message. The actual progress
|
|
289
|
+
* is computed from wall-clock time in the update handler, not from the
|
|
290
|
+
* interval count. The interval just schedules re-renders.
|
|
291
|
+
*/
|
|
292
|
+
export function createTransitionTickCmd(durationMs, generation) {
|
|
293
|
+
return (emit) => new Promise((resolve) => {
|
|
294
|
+
if (durationMs <= 0) {
|
|
295
|
+
emit(wrapFrameMsg({ type: 'transition-complete', generation }));
|
|
296
|
+
resolve();
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const startMs = Date.now();
|
|
300
|
+
const intervalMs = Math.round(1000 / 60);
|
|
301
|
+
const id = setInterval(() => {
|
|
302
|
+
const elapsed = Date.now() - startMs;
|
|
303
|
+
const rawProgress = Math.min(1, elapsed / durationMs);
|
|
304
|
+
emit(wrapFrameMsg({ type: 'transition', progress: rawProgress, generation }));
|
|
305
|
+
if (rawProgress >= 1) {
|
|
306
|
+
clearInterval(id);
|
|
307
|
+
emit(wrapFrameMsg({ type: 'transition-complete', generation }));
|
|
308
|
+
resolve();
|
|
309
|
+
}
|
|
310
|
+
}, intervalMs);
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=app-frame-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-frame-actions.js","sourceRoot":"","sources":["../src/app-frame-actions.ts"],"names":[],"mappings":"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"}
|