@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.
Files changed (132) hide show
  1. package/README.md +64 -21
  2. package/dist/animate.d.ts +0 -2
  3. package/dist/animate.d.ts.map +1 -1
  4. package/dist/animate.js +17 -26
  5. package/dist/animate.js.map +1 -1
  6. package/dist/app-frame-actions.d.ts +37 -0
  7. package/dist/app-frame-actions.d.ts.map +1 -0
  8. package/dist/app-frame-actions.js +313 -0
  9. package/dist/app-frame-actions.js.map +1 -0
  10. package/dist/app-frame-palette.d.ts +16 -0
  11. package/dist/app-frame-palette.d.ts.map +1 -0
  12. package/dist/app-frame-palette.js +158 -0
  13. package/dist/app-frame-palette.js.map +1 -0
  14. package/dist/app-frame-render.d.ts +39 -0
  15. package/dist/app-frame-render.d.ts.map +1 -0
  16. package/dist/app-frame-render.js +319 -0
  17. package/dist/app-frame-render.js.map +1 -0
  18. package/dist/app-frame-types.d.ts +135 -0
  19. package/dist/app-frame-types.d.ts.map +1 -0
  20. package/dist/app-frame-types.js +72 -0
  21. package/dist/app-frame-types.js.map +1 -0
  22. package/dist/app-frame-utils.d.ts +37 -0
  23. package/dist/app-frame-utils.d.ts.map +1 -0
  24. package/dist/app-frame-utils.js +141 -0
  25. package/dist/app-frame-utils.js.map +1 -0
  26. package/dist/app-frame.d.ts +13 -8
  27. package/dist/app-frame.d.ts.map +1 -1
  28. package/dist/app-frame.js +80 -906
  29. package/dist/app-frame.js.map +1 -1
  30. package/dist/canvas.d.ts +37 -25
  31. package/dist/canvas.d.ts.map +1 -1
  32. package/dist/canvas.js +116 -30
  33. package/dist/canvas.js.map +1 -1
  34. package/dist/commands.js +2 -2
  35. package/dist/commands.js.map +1 -1
  36. package/dist/css/install.d.ts +4 -0
  37. package/dist/css/install.d.ts.map +1 -0
  38. package/dist/css/install.js +24 -0
  39. package/dist/css/install.js.map +1 -0
  40. package/dist/css/parser.d.ts +14 -0
  41. package/dist/css/parser.d.ts.map +1 -0
  42. package/dist/css/parser.js +92 -0
  43. package/dist/css/parser.js.map +1 -0
  44. package/dist/css/resolver.d.ts +36 -0
  45. package/dist/css/resolver.d.ts.map +1 -0
  46. package/dist/css/resolver.js +130 -0
  47. package/dist/css/resolver.js.map +1 -0
  48. package/dist/css/text-style.d.ts +17 -0
  49. package/dist/css/text-style.d.ts.map +1 -0
  50. package/dist/css/text-style.js +59 -0
  51. package/dist/css/text-style.js.map +1 -0
  52. package/dist/css/types.d.ts +27 -0
  53. package/dist/css/types.d.ts.map +1 -0
  54. package/dist/css/types.js +5 -0
  55. package/dist/css/types.js.map +1 -0
  56. package/dist/driver.d.ts +10 -2
  57. package/dist/driver.d.ts.map +1 -1
  58. package/dist/driver.js +25 -2
  59. package/dist/driver.js.map +1 -1
  60. package/dist/eventbus.d.ts +42 -3
  61. package/dist/eventbus.d.ts.map +1 -1
  62. package/dist/eventbus.js +108 -7
  63. package/dist/eventbus.js.map +1 -1
  64. package/dist/focus-area.d.ts +4 -0
  65. package/dist/focus-area.d.ts.map +1 -1
  66. package/dist/focus-area.js +11 -1
  67. package/dist/focus-area.js.map +1 -1
  68. package/dist/index.d.ts +11 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +18 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/layout-v3.d.ts +10 -0
  73. package/dist/layout-v3.d.ts.map +1 -0
  74. package/dist/layout-v3.js +35 -0
  75. package/dist/layout-v3.js.map +1 -0
  76. package/dist/motion/motion.d.ts +14 -0
  77. package/dist/motion/motion.d.ts.map +1 -0
  78. package/dist/motion/motion.js +31 -0
  79. package/dist/motion/motion.js.map +1 -0
  80. package/dist/motion/reconciler.d.ts +15 -0
  81. package/dist/motion/reconciler.d.ts.map +1 -0
  82. package/dist/motion/reconciler.js +109 -0
  83. package/dist/motion/reconciler.js.map +1 -0
  84. package/dist/motion/types.d.ts +52 -0
  85. package/dist/motion/types.d.ts.map +1 -0
  86. package/dist/motion/types.js +2 -0
  87. package/dist/motion/types.js.map +1 -0
  88. package/dist/pipeline/middleware/css.d.ts +20 -0
  89. package/dist/pipeline/middleware/css.d.ts.map +1 -0
  90. package/dist/pipeline/middleware/css.js +41 -0
  91. package/dist/pipeline/middleware/css.js.map +1 -0
  92. package/dist/pipeline/middleware/grayscale.d.ts +9 -0
  93. package/dist/pipeline/middleware/grayscale.d.ts.map +1 -0
  94. package/dist/pipeline/middleware/grayscale.js +39 -0
  95. package/dist/pipeline/middleware/grayscale.js.map +1 -0
  96. package/dist/pipeline/middleware/motion.d.ts +6 -0
  97. package/dist/pipeline/middleware/motion.d.ts.map +1 -0
  98. package/dist/pipeline/middleware/motion.js +19 -0
  99. package/dist/pipeline/middleware/motion.js.map +1 -0
  100. package/dist/pipeline/middleware/paint.d.ts +6 -0
  101. package/dist/pipeline/middleware/paint.d.ts.map +1 -0
  102. package/dist/pipeline/middleware/paint.js +21 -0
  103. package/dist/pipeline/middleware/paint.js.map +1 -0
  104. package/dist/pipeline/pipeline.d.ts +56 -0
  105. package/dist/pipeline/pipeline.d.ts.map +1 -0
  106. package/dist/pipeline/pipeline.js +45 -0
  107. package/dist/pipeline/pipeline.js.map +1 -0
  108. package/dist/runtime.d.ts +1 -1
  109. package/dist/runtime.d.ts.map +1 -1
  110. package/dist/runtime.js +153 -8
  111. package/dist/runtime.js.map +1 -1
  112. package/dist/screen.d.ts +12 -1
  113. package/dist/screen.d.ts.map +1 -1
  114. package/dist/screen.js +14 -1
  115. package/dist/screen.js.map +1 -1
  116. package/dist/subapp/mount.d.ts +67 -0
  117. package/dist/subapp/mount.d.ts.map +1 -0
  118. package/dist/subapp/mount.js +60 -0
  119. package/dist/subapp/mount.js.map +1 -0
  120. package/dist/transition-shaders.d.ts +101 -3
  121. package/dist/transition-shaders.d.ts.map +1 -1
  122. package/dist/transition-shaders.js +281 -6
  123. package/dist/transition-shaders.js.map +1 -1
  124. package/dist/types.d.ts +45 -8
  125. package/dist/types.d.ts.map +1 -1
  126. package/dist/types.js +9 -0
  127. package/dist/types.js.map +1 -1
  128. package/dist/view-output.d.ts +15 -0
  129. package/dist/view-output.d.ts.map +1 -0
  130. package/dist/view-output.js +53 -0
  131. package/dist/view-output.js.map +1 -0
  132. package/package.json +3 -3
package/README.md CHANGED
@@ -1,38 +1,79 @@
1
- # @flyingrobots/bijou-tui
1
+ # `@flyingrobots/bijou-tui`
2
2
 
3
- TEA runtime for terminal UIs — model/update/view with physics-based animation, flexbox layout, declarative keybindings, and a centralized event bus.
3
+ The high-fidelity TEA runtime for Bijou.
4
4
 
5
- Inspired by [Bubble Tea](https://github.com/charmbracelet/bubbletea) (Go) and [GSAP](https://gsap.com/) animation.
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
- ## What's New (v1.3.0 Snapshot)?
7
+ ## V3.0.0 Evolution
8
8
 
9
- - **`splitPane()`** ratio-based split layout with pure reducers and deterministic rect introspection.
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
- See the [CHANGELOG](https://github.com/flyingrobots/bijou/blob/main/docs/CHANGELOG.md) for the full release history.
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
- ## Documentation Status
19
+ ## Installation
18
20
 
19
- This npm README is a quick overview and may lag behind the repository.
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
- - Canonical API details and behavior notes live in [`GUIDE.md`](./GUIDE.md)
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
- ## Install
27
+ ## Quick Start (V3 Sub-App Composition)
26
28
 
27
- ```bash
28
- npm install @flyingrobots/bijou @flyingrobots/bijou-node @flyingrobots/bijou-tui
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, tick, type App, type KeyMsg } from '@flyingrobots/bijou-tui';
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.type === 'key') {
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. */
@@ -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,sCAAsC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,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;AA4GD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAMrD"}
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, fps = 60, immediate = false, onFrame, onComplete } = options;
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, fps, onFrame, onComplete);
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, fps, onFrame, onComplete);
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, fps, onFrame, onComplete) {
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 intervalMs = Math.round(1000 / fps);
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
- clearInterval(id);
71
+ handle.dispose();
77
72
  if (onComplete)
78
73
  emit(onComplete());
79
74
  resolve();
80
75
  }
81
- }, intervalMs);
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, fps, onFrame, onComplete) {
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 intervalMs = Math.round(1000 / fps);
109
- let lastMs = Date.now();
110
- const id = setInterval(() => {
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
- clearInterval(id);
108
+ handle.dispose();
118
109
  if (onComplete)
119
110
  emit(onComplete());
120
111
  resolve();
121
112
  }
122
- }, intervalMs);
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"animate.js","sourceRoot":"","sources":["../src/animate.ts"],"names":[],"mappings":"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"}
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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"}