@flyingrobots/bijou-tui 1.0.0 → 1.1.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 CHANGED
@@ -326,6 +326,31 @@ const state = createFilePickerState({ cwd: process.cwd(), io, height: 15 });
326
326
  const output = filePicker(state);
327
327
  ```
328
328
 
329
+ ### Focus Area
330
+
331
+ ```typescript
332
+ import {
333
+ createFocusAreaState, focusArea, focusAreaScrollBy,
334
+ focusAreaKeyMap,
335
+ } from '@flyingrobots/bijou-tui';
336
+
337
+ const state = createFocusAreaState({ content, width: 60, height: 20, overflowX: 'scroll' });
338
+ const output = focusArea(state, { focused: true, ctx });
339
+ ```
340
+
341
+ ### DAG Pane
342
+
343
+ ```typescript
344
+ import {
345
+ createDagPaneState, dagPane, dagPaneSelectChild,
346
+ dagPaneSelectParent, dagPaneKeyMap,
347
+ } from '@flyingrobots/bijou-tui';
348
+
349
+ const state = createDagPaneState({ source: nodes, width: 80, height: 24, ctx });
350
+ const output = dagPane(state, { focused: true, ctx });
351
+ const next = dagPaneSelectChild(state, ctx); // arrow-key navigation
352
+ ```
353
+
329
354
  All building blocks include `*KeyMap()` factories for preconfigured vim-style keybindings.
330
355
 
331
356
  ## Related Packages
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Interactive DAG pane building block.
3
+ *
4
+ * Composes `dagLayout()` with `focusArea()` to provide a scrollable,
5
+ * keyboard-navigable DAG viewer with arrow-key node selection,
6
+ * auto-scroll-to-selection, and auto-highlight-path.
7
+ *
8
+ * Follows the building block pattern: immutable state + pure transformers +
9
+ * pure render + convenience keymap factory.
10
+ *
11
+ * ```ts
12
+ * // In TEA init:
13
+ * const pane = createDagPaneState({ source: nodes, width: 80, height: 24, ctx });
14
+ *
15
+ * // In TEA view:
16
+ * const output = dagPane(pane, { focused: true, ctx });
17
+ *
18
+ * // In TEA update:
19
+ * case 'select-child':
20
+ * return [{ ...model, pane: dagPaneSelectChild(model.pane, ctx) }, []];
21
+ * ```
22
+ */
23
+ import type { BijouContext, TokenValue, DagNode, DagLayout, SlicedDagSource } from '@flyingrobots/bijou';
24
+ import { type FocusAreaState, type FocusAreaRenderOptions, type OverflowX } from './focus-area.js';
25
+ import { type KeyMap } from './keybindings.js';
26
+ /** DAG rendering options forwarded to `dagLayout()`. */
27
+ export interface DagPaneDagOptions {
28
+ /** Default color/style token for node box borders. */
29
+ readonly nodeToken?: TokenValue;
30
+ /** Color/style token for edge lines and arrowheads. */
31
+ readonly edgeToken?: TokenValue;
32
+ /** Color/style token for highlighted path nodes/edges. */
33
+ readonly highlightToken?: TokenValue;
34
+ /** Color/style token for the selected node box. */
35
+ readonly selectedToken?: TokenValue;
36
+ /** Fixed character width per node box. */
37
+ readonly nodeWidth?: number;
38
+ /** Maximum total character width. */
39
+ readonly maxWidth?: number;
40
+ /** Layout direction. */
41
+ readonly direction?: 'down' | 'right';
42
+ }
43
+ /** Immutable state for the DAG pane widget. */
44
+ export interface DagPaneState {
45
+ /** Graph data source. */
46
+ readonly source: DagNode[] | SlicedDagSource;
47
+ /** Currently selected node ID, or undefined. */
48
+ readonly selectedId: string | undefined;
49
+ /** Cached `dagLayout()` result. */
50
+ readonly layout: DagLayout;
51
+ /** Ordered path from root to selected node (for highlighting). */
52
+ readonly highlightPath: readonly string[];
53
+ /** Underlying focus area (scroll/viewport) state. */
54
+ readonly focusArea: FocusAreaState;
55
+ /** DAG rendering options forwarded to `dagLayout()`. */
56
+ readonly dagOptions: DagPaneDagOptions;
57
+ }
58
+ /** Options for creating a new DAG pane state. */
59
+ export interface DagPaneOptions {
60
+ /** Graph data source (array of nodes or sliced source). */
61
+ readonly source: DagNode[] | SlicedDagSource;
62
+ /** Total width in columns (including gutter). */
63
+ readonly width: number;
64
+ /** Total height in rows. */
65
+ readonly height: number;
66
+ /** Initially selected node ID. */
67
+ readonly selectedId?: string;
68
+ /** Horizontal overflow. Default: `'scroll'` (DAGs are wide). */
69
+ readonly overflowX?: OverflowX;
70
+ /** DAG rendering options. */
71
+ readonly dagOptions?: DagPaneDagOptions;
72
+ /** Bijou context for rendering. */
73
+ readonly ctx?: BijouContext;
74
+ }
75
+ /** Options for rendering the DAG pane view. */
76
+ export type DagPaneRenderOptions = FocusAreaRenderOptions;
77
+ /**
78
+ * Create initial DAG pane state for the given source and dimensions.
79
+ *
80
+ * @param options - Source, dimensions, and rendering options.
81
+ * @returns Fresh DAG pane state.
82
+ */
83
+ export declare function createDagPaneState(options: DagPaneOptions): DagPaneState;
84
+ /**
85
+ * Select a child node (arrow down).
86
+ * If nothing is selected, auto-selects the first root node.
87
+ *
88
+ * @param state - Current DAG pane state.
89
+ * @param ctx - Bijou context for re-rendering.
90
+ * @returns Updated state with new selection.
91
+ */
92
+ export declare function dagPaneSelectChild(state: DagPaneState, ctx?: BijouContext): DagPaneState;
93
+ /**
94
+ * Select a parent node (arrow up).
95
+ * If nothing is selected, auto-selects the first root node.
96
+ *
97
+ * @param state - Current DAG pane state.
98
+ * @param ctx - Bijou context for re-rendering.
99
+ * @returns Updated state with new selection.
100
+ */
101
+ export declare function dagPaneSelectParent(state: DagPaneState, ctx?: BijouContext): DagPaneState;
102
+ /**
103
+ * Select the sibling node to the left in the same layer.
104
+ * If nothing is selected, auto-selects the first root node.
105
+ *
106
+ * @param state - Current DAG pane state.
107
+ * @param ctx - Bijou context for re-rendering.
108
+ * @returns Updated state with new selection.
109
+ */
110
+ export declare function dagPaneSelectLeft(state: DagPaneState, ctx?: BijouContext): DagPaneState;
111
+ /**
112
+ * Select the sibling node to the right in the same layer.
113
+ * If nothing is selected, auto-selects the first root node.
114
+ *
115
+ * @param state - Current DAG pane state.
116
+ * @param ctx - Bijou context for re-rendering.
117
+ * @returns Updated state with new selection.
118
+ */
119
+ export declare function dagPaneSelectRight(state: DagPaneState, ctx?: BijouContext): DagPaneState;
120
+ /**
121
+ * Select a specific node by ID.
122
+ * If the ID is not found in the layout, returns state unchanged (no selection).
123
+ *
124
+ * @param state - Current DAG pane state.
125
+ * @param nodeId - ID of the node to select.
126
+ * @param ctx - Bijou context for re-rendering.
127
+ * @returns Updated state with new selection.
128
+ */
129
+ export declare function dagPaneSelectNode(state: DagPaneState, nodeId: string, ctx?: BijouContext): DagPaneState;
130
+ /**
131
+ * Clear the current selection.
132
+ *
133
+ * @param state - Current DAG pane state.
134
+ * @param ctx - Bijou context for re-rendering.
135
+ * @returns Updated state with no selection.
136
+ */
137
+ export declare function dagPaneClearSelection(state: DagPaneState, ctx?: BijouContext): DagPaneState;
138
+ /**
139
+ * Scroll vertically by a relative amount.
140
+ *
141
+ * @param state - Current DAG pane state.
142
+ * @param dy - Relative vertical offset (positive = down).
143
+ * @returns Updated state.
144
+ */
145
+ export declare function dagPaneScrollBy(state: DagPaneState, dy: number): DagPaneState;
146
+ /**
147
+ * Scroll to the top.
148
+ *
149
+ * @param state - Current DAG pane state.
150
+ * @returns Updated state.
151
+ */
152
+ export declare function dagPaneScrollToTop(state: DagPaneState): DagPaneState;
153
+ /**
154
+ * Scroll to the bottom.
155
+ *
156
+ * @param state - Current DAG pane state.
157
+ * @returns Updated state.
158
+ */
159
+ export declare function dagPaneScrollToBottom(state: DagPaneState): DagPaneState;
160
+ /**
161
+ * Page down.
162
+ *
163
+ * @param state - Current DAG pane state.
164
+ * @returns Updated state.
165
+ */
166
+ export declare function dagPanePageDown(state: DagPaneState): DagPaneState;
167
+ /**
168
+ * Page up.
169
+ *
170
+ * @param state - Current DAG pane state.
171
+ * @returns Updated state.
172
+ */
173
+ export declare function dagPanePageUp(state: DagPaneState): DagPaneState;
174
+ /**
175
+ * Scroll horizontally by a relative amount.
176
+ *
177
+ * @param state - Current DAG pane state.
178
+ * @param dx - Relative horizontal offset (positive = right).
179
+ * @returns Updated state.
180
+ */
181
+ export declare function dagPaneScrollByX(state: DagPaneState, dx: number): DagPaneState;
182
+ /**
183
+ * Replace the graph source and re-render. Clears selection.
184
+ *
185
+ * @param state - Current DAG pane state.
186
+ * @param source - New graph data source.
187
+ * @param ctx - Bijou context for re-rendering.
188
+ * @returns Updated state with new source and cleared selection.
189
+ */
190
+ export declare function dagPaneSetSource(state: DagPaneState, source: DagNode[] | SlicedDagSource, ctx?: BijouContext): DagPaneState;
191
+ /**
192
+ * Render the DAG pane — focus area wrapping the DAG layout output.
193
+ *
194
+ * @param state - Current DAG pane state.
195
+ * @param options - Rendering options (focus, tokens, scrollbar, ctx).
196
+ * @returns Rendered DAG pane string.
197
+ */
198
+ export declare function dagPane(state: DagPaneState, options?: DagPaneRenderOptions): string;
199
+ /**
200
+ * Create a preconfigured KeyMap for DAG pane interaction.
201
+ *
202
+ * Arrow keys are bound to node selection. Vim keys (j/k/h/l) are bound
203
+ * to scroll. `Enter` confirms, `q`/`Ctrl+C` quits.
204
+ *
205
+ * @template Msg - Application message type dispatched by key bindings.
206
+ * @param actions - Map of actions to message values.
207
+ * @returns Preconfigured key map with DAG pane bindings.
208
+ */
209
+ export declare function dagPaneKeyMap<Msg>(actions: {
210
+ selectParent: Msg;
211
+ selectChild: Msg;
212
+ selectLeft: Msg;
213
+ selectRight: Msg;
214
+ scrollUp: Msg;
215
+ scrollDown: Msg;
216
+ scrollLeft: Msg;
217
+ scrollRight: Msg;
218
+ pageUp: Msg;
219
+ pageDown: Msg;
220
+ top: Msg;
221
+ bottom: Msg;
222
+ confirm: Msg;
223
+ quit: Msg;
224
+ }): KeyMap<Msg>;
225
+ //# sourceMappingURL=dag-pane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-pane.d.ts","sourceRoot":"","sources":["../src/dag-pane.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAmB,SAAS,EAAc,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtI,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,SAAS,EAUf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM7D,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAChC,uDAAuD;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAChC,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IACrC,mDAAmD;IACnD,QAAQ,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC;IACpC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,wBAAwB;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACvC;AAED,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC;IAC7C,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,wDAAwD;IACxD,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;CACxC;AAED,iDAAiD;AACjD,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC;IAC7C,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4BAA4B;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,6BAA6B;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IACxC,mCAAmC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,+CAA+C;AAC/C,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAkQ1D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,YAAY,CA2CxE;AAMD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,YAAY,CAexF;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,YAAY,CAezF;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,YAAY,CAgBvF;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,YAAY,CAgBxF;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,YAAY,CAMvG;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,YAAY,CAG3F;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,CAE7E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,CAE9E;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,EACnC,GAAG,CAAC,EAAE,YAAY,GACjB,YAAY,CAad;AAMD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAEnF;AAMD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE;IAC1C,YAAY,EAAE,GAAG,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC;IACjB,UAAU,EAAE,GAAG,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,QAAQ,EAAE,GAAG,CAAC;IACd,UAAU,EAAE,GAAG,CAAC;IAChB,UAAU,EAAE,GAAG,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,MAAM,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,GAAG,CAAC;IACd,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;IACZ,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;CACX,GAAG,MAAM,CAAC,GAAG,CAAC,CAqBd"}
@@ -0,0 +1,510 @@
1
+ /**
2
+ * Interactive DAG pane building block.
3
+ *
4
+ * Composes `dagLayout()` with `focusArea()` to provide a scrollable,
5
+ * keyboard-navigable DAG viewer with arrow-key node selection,
6
+ * auto-scroll-to-selection, and auto-highlight-path.
7
+ *
8
+ * Follows the building block pattern: immutable state + pure transformers +
9
+ * pure render + convenience keymap factory.
10
+ *
11
+ * ```ts
12
+ * // In TEA init:
13
+ * const pane = createDagPaneState({ source: nodes, width: 80, height: 24, ctx });
14
+ *
15
+ * // In TEA view:
16
+ * const output = dagPane(pane, { focused: true, ctx });
17
+ *
18
+ * // In TEA update:
19
+ * case 'select-child':
20
+ * return [{ ...model, pane: dagPaneSelectChild(model.pane, ctx) }, []];
21
+ * ```
22
+ */
23
+ import { dagLayout, isSlicedDagSource } from '@flyingrobots/bijou';
24
+ import { createFocusAreaState, focusArea, focusAreaScrollBy, focusAreaScrollToTop, focusAreaScrollToBottom, focusAreaPageDown, focusAreaPageUp, focusAreaScrollByX, focusAreaSetContent, } from './focus-area.js';
25
+ import { scrollTo, scrollToX } from './viewport.js';
26
+ import { createKeyMap } from './keybindings.js';
27
+ function buildAdjacency(source) {
28
+ const childMap = new Map();
29
+ const parentMap = new Map();
30
+ if (isSlicedDagSource(source)) {
31
+ const ids = source.ids();
32
+ const idSet = new Set(ids);
33
+ for (const id of ids) {
34
+ const children = source.children(id).filter((c) => idSet.has(c));
35
+ childMap.set(id, [...children]);
36
+ if (!parentMap.has(id))
37
+ parentMap.set(id, []);
38
+ for (const child of children) {
39
+ let parents = parentMap.get(child);
40
+ if (!parents) {
41
+ parents = [];
42
+ parentMap.set(child, parents);
43
+ }
44
+ parents.push(id);
45
+ }
46
+ }
47
+ }
48
+ else {
49
+ const idSet = new Set(source.map((n) => n.id));
50
+ for (const node of source) {
51
+ const children = (node.edges ?? []).filter((e) => idSet.has(e));
52
+ childMap.set(node.id, children);
53
+ if (!parentMap.has(node.id))
54
+ parentMap.set(node.id, []);
55
+ for (const child of children) {
56
+ let parents = parentMap.get(child);
57
+ if (!parents) {
58
+ parents = [];
59
+ parentMap.set(child, parents);
60
+ }
61
+ parents.push(node.id);
62
+ }
63
+ }
64
+ }
65
+ const roots = [];
66
+ for (const [id, parents] of parentMap) {
67
+ if (parents.length === 0)
68
+ roots.push(id);
69
+ }
70
+ // Also add any nodes that are in childMap but not parentMap (shouldn't happen, but safe)
71
+ for (const id of childMap.keys()) {
72
+ if (!parentMap.has(id))
73
+ roots.push(id);
74
+ }
75
+ return {
76
+ children: childMap,
77
+ parents: parentMap,
78
+ roots,
79
+ };
80
+ }
81
+ // ---------------------------------------------------------------------------
82
+ // Internal: Highlight path computation
83
+ // ---------------------------------------------------------------------------
84
+ function computeHighlightPath(selectedId, adjacency) {
85
+ if (!selectedId)
86
+ return [];
87
+ // BFS upward from selected to find a root, then reverse
88
+ const visited = new Set();
89
+ const cameFrom = new Map();
90
+ const queue = [selectedId];
91
+ visited.add(selectedId);
92
+ let rootFound;
93
+ while (queue.length > 0) {
94
+ const current = queue.shift();
95
+ const parents = adjacency.parents.get(current) ?? [];
96
+ if (parents.length === 0) {
97
+ rootFound = current;
98
+ break;
99
+ }
100
+ for (const parent of parents) {
101
+ if (!visited.has(parent)) {
102
+ visited.add(parent);
103
+ cameFrom.set(parent, current);
104
+ queue.push(parent);
105
+ }
106
+ }
107
+ }
108
+ if (rootFound === undefined) {
109
+ // Selected node is itself a root (or disconnected)
110
+ return [selectedId];
111
+ }
112
+ // Reconstruct path from root to selected
113
+ const path = [];
114
+ let cursor = rootFound;
115
+ while (cursor !== undefined) {
116
+ path.push(cursor);
117
+ if (cursor === selectedId)
118
+ break;
119
+ cursor = cameFrom.get(cursor);
120
+ }
121
+ // If we couldn't reach selectedId from the root, just return selected
122
+ if (path[path.length - 1] !== selectedId) {
123
+ return [selectedId];
124
+ }
125
+ return path;
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Internal: Spatial navigation helpers
129
+ // ---------------------------------------------------------------------------
130
+ function closestByCol(candidates, currentCenter, positions) {
131
+ let best;
132
+ let bestDist = Infinity;
133
+ for (const id of candidates) {
134
+ const pos = positions.get(id);
135
+ if (!pos)
136
+ continue;
137
+ const center = pos.col + pos.width / 2;
138
+ const dist = Math.abs(center - currentCenter);
139
+ if (dist < bestDist) {
140
+ bestDist = dist;
141
+ best = id;
142
+ }
143
+ }
144
+ return best;
145
+ }
146
+ function nodesOnSameRow(row, positions) {
147
+ const result = [];
148
+ for (const [id, pos] of positions) {
149
+ if (pos.row === row)
150
+ result.push(id);
151
+ }
152
+ return result.sort((a, b) => {
153
+ const pa = positions.get(a);
154
+ const pb = positions.get(b);
155
+ return pa.col - pb.col;
156
+ });
157
+ }
158
+ // ---------------------------------------------------------------------------
159
+ // Internal: Auto-scroll to node
160
+ // ---------------------------------------------------------------------------
161
+ function scrollToNode(faState, nodePos) {
162
+ let scroll = faState.scroll;
163
+ // Vertical: ensure node box (row .. row+height) is within viewport
164
+ const nodeTop = nodePos.row;
165
+ const nodeBottom = nodePos.row + nodePos.height - 1;
166
+ const viewTop = scroll.y;
167
+ const viewBottom = scroll.y + faState.height - 1;
168
+ if (nodeTop < viewTop) {
169
+ scroll = scrollTo(scroll, nodeTop);
170
+ }
171
+ else if (nodeBottom > viewBottom) {
172
+ scroll = scrollTo(scroll, nodeBottom - faState.height + 1);
173
+ }
174
+ // Horizontal: ensure node box (col .. col+width) is within viewport
175
+ if (faState.overflowX === 'scroll') {
176
+ const contentWidth = Math.max(1, faState.width - 1); // minus gutter
177
+ const nodeLeft = nodePos.col;
178
+ const nodeRight = nodePos.col + nodePos.width - 1;
179
+ const viewLeft = scroll.x;
180
+ const viewRight = scroll.x + contentWidth - 1;
181
+ if (nodeLeft < viewLeft) {
182
+ scroll = scrollToX(scroll, nodeLeft);
183
+ }
184
+ else if (nodeRight > viewRight) {
185
+ scroll = scrollToX(scroll, nodeRight - contentWidth + 1);
186
+ }
187
+ }
188
+ return { ...faState, scroll };
189
+ }
190
+ // ---------------------------------------------------------------------------
191
+ // Internal: Selection update
192
+ // ---------------------------------------------------------------------------
193
+ function renderLayout(source, selectedId, highlightPath, dagOptions, ctx) {
194
+ const opts = {
195
+ ...dagOptions,
196
+ selectedId,
197
+ highlightPath: highlightPath.length > 0 ? [...highlightPath] : undefined,
198
+ ctx,
199
+ };
200
+ // Type narrowing required — dagLayout has separate overloads for
201
+ // DagNode[] and SlicedDagSource; a union won't resolve either overload.
202
+ return isSlicedDagSource(source)
203
+ ? dagLayout(source, opts)
204
+ : dagLayout(source, opts);
205
+ }
206
+ function updateSelection(state, newId, adjacency, ctx) {
207
+ const highlightPath = computeHighlightPath(newId, adjacency);
208
+ const layout = renderLayout(state.source, newId, highlightPath, state.dagOptions, ctx);
209
+ let fa = focusAreaSetContent(state.focusArea, layout.output);
210
+ // Auto-scroll to selected node
211
+ if (newId) {
212
+ const nodePos = layout.nodes.get(newId);
213
+ if (nodePos) {
214
+ fa = scrollToNode(fa, nodePos);
215
+ }
216
+ }
217
+ return {
218
+ ...state,
219
+ selectedId: newId,
220
+ highlightPath,
221
+ layout,
222
+ focusArea: fa,
223
+ };
224
+ }
225
+ // ---------------------------------------------------------------------------
226
+ // State creation
227
+ // ---------------------------------------------------------------------------
228
+ /**
229
+ * Create initial DAG pane state for the given source and dimensions.
230
+ *
231
+ * @param options - Source, dimensions, and rendering options.
232
+ * @returns Fresh DAG pane state.
233
+ */
234
+ export function createDagPaneState(options) {
235
+ const { source, width, height, selectedId, overflowX = 'scroll', dagOptions = {}, ctx, } = options;
236
+ const adjacency = buildAdjacency(source);
237
+ // Validate selectedId — fall back to no selection if not in the source
238
+ const validatedId = selectedId !== undefined && adjacency.children.has(selectedId) ? selectedId : undefined;
239
+ const highlightPath = computeHighlightPath(validatedId, adjacency);
240
+ const layout = renderLayout(source, validatedId, highlightPath, dagOptions, ctx);
241
+ const fa = createFocusAreaState({
242
+ content: layout.output,
243
+ width,
244
+ height,
245
+ overflowX,
246
+ });
247
+ // Auto-scroll to initial selection
248
+ let finalFa = fa;
249
+ if (validatedId) {
250
+ const nodePos = layout.nodes.get(validatedId);
251
+ if (nodePos) {
252
+ finalFa = scrollToNode(fa, nodePos);
253
+ }
254
+ }
255
+ return {
256
+ source,
257
+ selectedId: validatedId,
258
+ layout,
259
+ highlightPath,
260
+ focusArea: finalFa,
261
+ dagOptions,
262
+ };
263
+ }
264
+ // ---------------------------------------------------------------------------
265
+ // Navigation transformers
266
+ // ---------------------------------------------------------------------------
267
+ /**
268
+ * Select a child node (arrow down).
269
+ * If nothing is selected, auto-selects the first root node.
270
+ *
271
+ * @param state - Current DAG pane state.
272
+ * @param ctx - Bijou context for re-rendering.
273
+ * @returns Updated state with new selection.
274
+ */
275
+ export function dagPaneSelectChild(state, ctx) {
276
+ const adjacency = buildAdjacency(state.source);
277
+ if (!state.selectedId) {
278
+ const firstRoot = adjacency.roots[0];
279
+ return firstRoot ? updateSelection(state, firstRoot, adjacency, ctx) : state;
280
+ }
281
+ const children = adjacency.children.get(state.selectedId) ?? [];
282
+ if (children.length === 0)
283
+ return state;
284
+ const currentPos = state.layout.nodes.get(state.selectedId);
285
+ const currentCenter = currentPos ? currentPos.col + currentPos.width / 2 : 0;
286
+ const target = closestByCol(children, currentCenter, state.layout.nodes);
287
+ return target ? updateSelection(state, target, adjacency, ctx) : state;
288
+ }
289
+ /**
290
+ * Select a parent node (arrow up).
291
+ * If nothing is selected, auto-selects the first root node.
292
+ *
293
+ * @param state - Current DAG pane state.
294
+ * @param ctx - Bijou context for re-rendering.
295
+ * @returns Updated state with new selection.
296
+ */
297
+ export function dagPaneSelectParent(state, ctx) {
298
+ const adjacency = buildAdjacency(state.source);
299
+ if (!state.selectedId) {
300
+ const firstRoot = adjacency.roots[0];
301
+ return firstRoot ? updateSelection(state, firstRoot, adjacency, ctx) : state;
302
+ }
303
+ const parents = adjacency.parents.get(state.selectedId) ?? [];
304
+ if (parents.length === 0)
305
+ return state;
306
+ const currentPos = state.layout.nodes.get(state.selectedId);
307
+ const currentCenter = currentPos ? currentPos.col + currentPos.width / 2 : 0;
308
+ const target = closestByCol(parents, currentCenter, state.layout.nodes);
309
+ return target ? updateSelection(state, target, adjacency, ctx) : state;
310
+ }
311
+ /**
312
+ * Select the sibling node to the left in the same layer.
313
+ * If nothing is selected, auto-selects the first root node.
314
+ *
315
+ * @param state - Current DAG pane state.
316
+ * @param ctx - Bijou context for re-rendering.
317
+ * @returns Updated state with new selection.
318
+ */
319
+ export function dagPaneSelectLeft(state, ctx) {
320
+ const adjacency = buildAdjacency(state.source);
321
+ if (!state.selectedId) {
322
+ const firstRoot = adjacency.roots[0];
323
+ return firstRoot ? updateSelection(state, firstRoot, adjacency, ctx) : state;
324
+ }
325
+ const currentPos = state.layout.nodes.get(state.selectedId);
326
+ if (!currentPos)
327
+ return state;
328
+ const siblings = nodesOnSameRow(currentPos.row, state.layout.nodes);
329
+ const idx = siblings.indexOf(state.selectedId);
330
+ if (idx <= 0)
331
+ return state; // already leftmost
332
+ return updateSelection(state, siblings[idx - 1], adjacency, ctx);
333
+ }
334
+ /**
335
+ * Select the sibling node to the right in the same layer.
336
+ * If nothing is selected, auto-selects the first root node.
337
+ *
338
+ * @param state - Current DAG pane state.
339
+ * @param ctx - Bijou context for re-rendering.
340
+ * @returns Updated state with new selection.
341
+ */
342
+ export function dagPaneSelectRight(state, ctx) {
343
+ const adjacency = buildAdjacency(state.source);
344
+ if (!state.selectedId) {
345
+ const firstRoot = adjacency.roots[0];
346
+ return firstRoot ? updateSelection(state, firstRoot, adjacency, ctx) : state;
347
+ }
348
+ const currentPos = state.layout.nodes.get(state.selectedId);
349
+ if (!currentPos)
350
+ return state;
351
+ const siblings = nodesOnSameRow(currentPos.row, state.layout.nodes);
352
+ const idx = siblings.indexOf(state.selectedId);
353
+ if (idx < 0 || idx >= siblings.length - 1)
354
+ return state; // already rightmost
355
+ return updateSelection(state, siblings[idx + 1], adjacency, ctx);
356
+ }
357
+ /**
358
+ * Select a specific node by ID.
359
+ * If the ID is not found in the layout, returns state unchanged (no selection).
360
+ *
361
+ * @param state - Current DAG pane state.
362
+ * @param nodeId - ID of the node to select.
363
+ * @param ctx - Bijou context for re-rendering.
364
+ * @returns Updated state with new selection.
365
+ */
366
+ export function dagPaneSelectNode(state, nodeId, ctx) {
367
+ if (!state.layout.nodes.has(nodeId)) {
368
+ return state;
369
+ }
370
+ const adjacency = buildAdjacency(state.source);
371
+ return updateSelection(state, nodeId, adjacency, ctx);
372
+ }
373
+ /**
374
+ * Clear the current selection.
375
+ *
376
+ * @param state - Current DAG pane state.
377
+ * @param ctx - Bijou context for re-rendering.
378
+ * @returns Updated state with no selection.
379
+ */
380
+ export function dagPaneClearSelection(state, ctx) {
381
+ const adjacency = buildAdjacency(state.source);
382
+ return updateSelection(state, undefined, adjacency, ctx);
383
+ }
384
+ // ---------------------------------------------------------------------------
385
+ // Scroll transformers
386
+ // ---------------------------------------------------------------------------
387
+ /**
388
+ * Scroll vertically by a relative amount.
389
+ *
390
+ * @param state - Current DAG pane state.
391
+ * @param dy - Relative vertical offset (positive = down).
392
+ * @returns Updated state.
393
+ */
394
+ export function dagPaneScrollBy(state, dy) {
395
+ return { ...state, focusArea: focusAreaScrollBy(state.focusArea, dy) };
396
+ }
397
+ /**
398
+ * Scroll to the top.
399
+ *
400
+ * @param state - Current DAG pane state.
401
+ * @returns Updated state.
402
+ */
403
+ export function dagPaneScrollToTop(state) {
404
+ return { ...state, focusArea: focusAreaScrollToTop(state.focusArea) };
405
+ }
406
+ /**
407
+ * Scroll to the bottom.
408
+ *
409
+ * @param state - Current DAG pane state.
410
+ * @returns Updated state.
411
+ */
412
+ export function dagPaneScrollToBottom(state) {
413
+ return { ...state, focusArea: focusAreaScrollToBottom(state.focusArea) };
414
+ }
415
+ /**
416
+ * Page down.
417
+ *
418
+ * @param state - Current DAG pane state.
419
+ * @returns Updated state.
420
+ */
421
+ export function dagPanePageDown(state) {
422
+ return { ...state, focusArea: focusAreaPageDown(state.focusArea) };
423
+ }
424
+ /**
425
+ * Page up.
426
+ *
427
+ * @param state - Current DAG pane state.
428
+ * @returns Updated state.
429
+ */
430
+ export function dagPanePageUp(state) {
431
+ return { ...state, focusArea: focusAreaPageUp(state.focusArea) };
432
+ }
433
+ /**
434
+ * Scroll horizontally by a relative amount.
435
+ *
436
+ * @param state - Current DAG pane state.
437
+ * @param dx - Relative horizontal offset (positive = right).
438
+ * @returns Updated state.
439
+ */
440
+ export function dagPaneScrollByX(state, dx) {
441
+ return { ...state, focusArea: focusAreaScrollByX(state.focusArea, dx) };
442
+ }
443
+ /**
444
+ * Replace the graph source and re-render. Clears selection.
445
+ *
446
+ * @param state - Current DAG pane state.
447
+ * @param source - New graph data source.
448
+ * @param ctx - Bijou context for re-rendering.
449
+ * @returns Updated state with new source and cleared selection.
450
+ */
451
+ export function dagPaneSetSource(state, source, ctx) {
452
+ const highlightPath = [];
453
+ const layout = renderLayout(source, undefined, highlightPath, state.dagOptions, ctx);
454
+ const fa = focusAreaSetContent(state.focusArea, layout.output);
455
+ return {
456
+ ...state,
457
+ source,
458
+ selectedId: undefined,
459
+ highlightPath,
460
+ layout,
461
+ focusArea: fa,
462
+ };
463
+ }
464
+ // ---------------------------------------------------------------------------
465
+ // Render
466
+ // ---------------------------------------------------------------------------
467
+ /**
468
+ * Render the DAG pane — focus area wrapping the DAG layout output.
469
+ *
470
+ * @param state - Current DAG pane state.
471
+ * @param options - Rendering options (focus, tokens, scrollbar, ctx).
472
+ * @returns Rendered DAG pane string.
473
+ */
474
+ export function dagPane(state, options) {
475
+ return focusArea(state.focusArea, options);
476
+ }
477
+ // ---------------------------------------------------------------------------
478
+ // Convenience keymap
479
+ // ---------------------------------------------------------------------------
480
+ /**
481
+ * Create a preconfigured KeyMap for DAG pane interaction.
482
+ *
483
+ * Arrow keys are bound to node selection. Vim keys (j/k/h/l) are bound
484
+ * to scroll. `Enter` confirms, `q`/`Ctrl+C` quits.
485
+ *
486
+ * @template Msg - Application message type dispatched by key bindings.
487
+ * @param actions - Map of actions to message values.
488
+ * @returns Preconfigured key map with DAG pane bindings.
489
+ */
490
+ export function dagPaneKeyMap(actions) {
491
+ return createKeyMap()
492
+ .group('Selection', (g) => g
493
+ .bind('up', 'Select parent', actions.selectParent)
494
+ .bind('down', 'Select child', actions.selectChild)
495
+ .bind('left', 'Select left', actions.selectLeft)
496
+ .bind('right', 'Select right', actions.selectRight))
497
+ .group('Scroll', (g) => g
498
+ .bind('j', 'Down', actions.scrollDown)
499
+ .bind('k', 'Up', actions.scrollUp)
500
+ .bind('h', 'Scroll left', actions.scrollLeft)
501
+ .bind('l', 'Scroll right', actions.scrollRight)
502
+ .bind('d', 'Page down', actions.pageDown)
503
+ .bind('u', 'Page up', actions.pageUp)
504
+ .bind('g', 'Top', actions.top)
505
+ .bind('shift+g', 'Bottom', actions.bottom))
506
+ .bind('enter', 'Confirm', actions.confirm)
507
+ .bind('q', 'Quit', actions.quit)
508
+ .bind('ctrl+c', 'Quit', actions.quit);
509
+ }
510
+ //# sourceMappingURL=dag-pane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-pane.js","sourceRoot":"","sources":["../src/dag-pane.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Focus area building block — a scrollable pane with a colored left gutter.
3
+ *
4
+ * Wraps `viewport()` and prepends a styled gutter character (`▎`) to each
5
+ * line indicating focus state: bright accent when focused, muted when unfocused.
6
+ *
7
+ * Follows the building block pattern: immutable state + pure transformers +
8
+ * pure render + convenience keymap factory.
9
+ *
10
+ * ```ts
11
+ * // In TEA init:
12
+ * const fa = createFocusAreaState({ content, width: 60, height: 20 });
13
+ *
14
+ * // In TEA view:
15
+ * const output = focusArea(fa, { focused: true, ctx });
16
+ *
17
+ * // In TEA update:
18
+ * case 'scroll-down':
19
+ * return [{ ...model, fa: focusAreaScrollBy(model.fa, 1) }, []];
20
+ * ```
21
+ */
22
+ import type { BijouContext, TokenValue } from '@flyingrobots/bijou';
23
+ import { type ScrollState } from './viewport.js';
24
+ import { type KeyMap } from './keybindings.js';
25
+ /** Horizontal overflow behavior. */
26
+ export type OverflowX = 'scroll' | 'hidden';
27
+ /** Immutable state for the focus area widget. */
28
+ export interface FocusAreaState {
29
+ /** Full text content displayed in the focus area. */
30
+ readonly content: string;
31
+ /** Underlying scroll position state. */
32
+ readonly scroll: ScrollState;
33
+ /** Total width in columns (including gutter). */
34
+ readonly width: number;
35
+ /** Total height in rows. */
36
+ readonly height: number;
37
+ /** Horizontal overflow behavior. */
38
+ readonly overflowX: OverflowX;
39
+ }
40
+ /** Options for creating a new focus area state. */
41
+ export interface FocusAreaOptions {
42
+ /** Full text content to display. */
43
+ readonly content: string;
44
+ /** Total width in columns (including gutter). */
45
+ readonly width: number;
46
+ /** Total height in rows. */
47
+ readonly height: number;
48
+ /** Horizontal overflow behavior. Default: `'hidden'`. */
49
+ readonly overflowX?: OverflowX;
50
+ }
51
+ /** Options for rendering the focus area view. */
52
+ export interface FocusAreaRenderOptions {
53
+ /** Whether the pane is currently focused. Default: `true`. */
54
+ readonly focused?: boolean;
55
+ /** Token for the focused gutter. Default: `theme.semantic.accent`. */
56
+ readonly focusedGutterToken?: TokenValue;
57
+ /** Token for the unfocused gutter. Default: `theme.semantic.muted`. */
58
+ readonly unfocusedGutterToken?: TokenValue;
59
+ /** Show a scrollbar track on the right edge. Default: `true`. */
60
+ readonly showScrollbar?: boolean;
61
+ /** Bijou context for styling and mode detection. */
62
+ readonly ctx?: BijouContext;
63
+ }
64
+ /**
65
+ * Create initial focus area state for the given content and dimensions.
66
+ *
67
+ * The viewport width is `width - 1` to account for the gutter column.
68
+ * When `overflowX` is `'scroll'`, horizontal scroll bounds are computed
69
+ * from the widest content line.
70
+ *
71
+ * @param options - Content, width, height, and overflow for the focus area.
72
+ * @returns Fresh focus area state with scroll at the top-left.
73
+ */
74
+ export declare function createFocusAreaState(options: FocusAreaOptions): FocusAreaState;
75
+ /**
76
+ * Scroll vertically by a relative amount.
77
+ *
78
+ * @param state - Current focus area state.
79
+ * @param dy - Relative vertical offset (positive = down).
80
+ * @returns Updated state with new scroll position.
81
+ */
82
+ export declare function focusAreaScrollBy(state: FocusAreaState, dy: number): FocusAreaState;
83
+ /**
84
+ * Scroll vertically to an absolute position.
85
+ *
86
+ * @param state - Current focus area state.
87
+ * @param y - Absolute vertical offset (0-based).
88
+ * @returns Updated state with new scroll position.
89
+ */
90
+ export declare function focusAreaScrollTo(state: FocusAreaState, y: number): FocusAreaState;
91
+ /**
92
+ * Scroll to the first line.
93
+ *
94
+ * @param state - Current focus area state.
95
+ * @returns Updated state scrolled to the top.
96
+ */
97
+ export declare function focusAreaScrollToTop(state: FocusAreaState): FocusAreaState;
98
+ /**
99
+ * Scroll to the last line.
100
+ *
101
+ * @param state - Current focus area state.
102
+ * @returns Updated state scrolled to the bottom.
103
+ */
104
+ export declare function focusAreaScrollToBottom(state: FocusAreaState): FocusAreaState;
105
+ /**
106
+ * Page down (one viewport height).
107
+ *
108
+ * @param state - Current focus area state.
109
+ * @returns Updated state advanced by one page.
110
+ */
111
+ export declare function focusAreaPageDown(state: FocusAreaState): FocusAreaState;
112
+ /**
113
+ * Page up (one viewport height).
114
+ *
115
+ * @param state - Current focus area state.
116
+ * @returns Updated state moved back by one page.
117
+ */
118
+ export declare function focusAreaPageUp(state: FocusAreaState): FocusAreaState;
119
+ /**
120
+ * Scroll horizontally by a relative amount.
121
+ * No-op when `overflowX` is `'hidden'`.
122
+ *
123
+ * @param state - Current focus area state.
124
+ * @param dx - Relative horizontal offset (positive = right).
125
+ * @returns Updated state with new horizontal scroll position.
126
+ */
127
+ export declare function focusAreaScrollByX(state: FocusAreaState, dx: number): FocusAreaState;
128
+ /**
129
+ * Scroll horizontally to an absolute position.
130
+ * No-op when `overflowX` is `'hidden'`.
131
+ *
132
+ * @param state - Current focus area state.
133
+ * @param x - Absolute horizontal offset (0-based).
134
+ * @returns Updated state with new horizontal scroll position.
135
+ */
136
+ export declare function focusAreaScrollToX(state: FocusAreaState, x: number): FocusAreaState;
137
+ /**
138
+ * Update content while preserving scroll position (clamped).
139
+ *
140
+ * @param state - Current focus area state.
141
+ * @param content - New text content to display.
142
+ * @returns Updated state with new content and clamped scroll position.
143
+ */
144
+ export declare function focusAreaSetContent(state: FocusAreaState, content: string): FocusAreaState;
145
+ /**
146
+ * Render the focus area — viewport content with a colored left gutter.
147
+ *
148
+ * The gutter character (`▎`) is styled based on focus state:
149
+ * - Focused: `focusedGutterToken` (default: `theme.semantic.accent`)
150
+ * - Unfocused: `unfocusedGutterToken` (default: `theme.semantic.muted`)
151
+ * - Static mode: unstyled gutter
152
+ * - Pipe / accessible mode: no gutter (full width to content)
153
+ *
154
+ * @param state - Current focus area state.
155
+ * @param options - Rendering options (focus, tokens, scrollbar, ctx).
156
+ * @returns Rendered focus area string.
157
+ */
158
+ export declare function focusArea(state: FocusAreaState, options?: FocusAreaRenderOptions): string;
159
+ /**
160
+ * Create a preconfigured KeyMap for focus area navigation.
161
+ *
162
+ * Arrow keys are intentionally excluded — reserved for content-specific
163
+ * navigation (e.g., DAG node selection).
164
+ *
165
+ * @template Msg - Application message type dispatched by key bindings.
166
+ * @param actions - Map of navigation actions to message values.
167
+ * @returns Preconfigured key map with vim-style scroll bindings.
168
+ */
169
+ export declare function focusAreaKeyMap<Msg>(actions: {
170
+ scrollUp: Msg;
171
+ scrollDown: Msg;
172
+ pageUp: Msg;
173
+ pageDown: Msg;
174
+ top: Msg;
175
+ bottom: Msg;
176
+ scrollLeft?: Msg;
177
+ scrollRight?: Msg;
178
+ }): KeyMap<Msg>;
179
+ //# sourceMappingURL=focus-area.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus-area.d.ts","sourceRoot":"","sources":["../src/focus-area.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Focus area building block — a scrollable pane with a colored left gutter.
3
+ *
4
+ * Wraps `viewport()` and prepends a styled gutter character (`▎`) to each
5
+ * line indicating focus state: bright accent when focused, muted when unfocused.
6
+ *
7
+ * Follows the building block pattern: immutable state + pure transformers +
8
+ * pure render + convenience keymap factory.
9
+ *
10
+ * ```ts
11
+ * // In TEA init:
12
+ * const fa = createFocusAreaState({ content, width: 60, height: 20 });
13
+ *
14
+ * // In TEA view:
15
+ * const output = focusArea(fa, { focused: true, ctx });
16
+ *
17
+ * // In TEA update:
18
+ * case 'scroll-down':
19
+ * return [{ ...model, fa: focusAreaScrollBy(model.fa, 1) }, []];
20
+ * ```
21
+ */
22
+ import { viewport, createScrollState, scrollBy, scrollTo, scrollToTop, scrollToBottom, pageDown, pageUp, scrollByX, scrollToX, } from './viewport.js';
23
+ import { createKeyMap } from './keybindings.js';
24
+ // ---------------------------------------------------------------------------
25
+ // Constants
26
+ // ---------------------------------------------------------------------------
27
+ /** Gutter character: left one quarter block (U+258E). */
28
+ const GUTTER_CHAR = '▎';
29
+ // ---------------------------------------------------------------------------
30
+ // State creation
31
+ // ---------------------------------------------------------------------------
32
+ /**
33
+ * Create initial focus area state for the given content and dimensions.
34
+ *
35
+ * The viewport width is `width - 1` to account for the gutter column.
36
+ * When `overflowX` is `'scroll'`, horizontal scroll bounds are computed
37
+ * from the widest content line.
38
+ *
39
+ * @param options - Content, width, height, and overflow for the focus area.
40
+ * @returns Fresh focus area state with scroll at the top-left.
41
+ */
42
+ export function createFocusAreaState(options) {
43
+ const { content, overflowX = 'hidden' } = options;
44
+ // Clamp dimensions to at least 1
45
+ const width = Math.max(1, options.width);
46
+ const height = Math.max(1, options.height);
47
+ // Gutter consumes 1 column; scrollbar consumes 1 more when visible
48
+ const contentWidth = Math.max(1, width - 1);
49
+ const totalLines = content.split('\n').length;
50
+ const hasScrollbar = totalLines > height;
51
+ const scrollableWidth = hasScrollbar ? Math.max(1, contentWidth - 1) : contentWidth;
52
+ const viewportWidth = overflowX === 'scroll' ? scrollableWidth : undefined;
53
+ return {
54
+ content,
55
+ scroll: createScrollState(content, height, viewportWidth),
56
+ width,
57
+ height,
58
+ overflowX,
59
+ };
60
+ }
61
+ // ---------------------------------------------------------------------------
62
+ // State transformers
63
+ // ---------------------------------------------------------------------------
64
+ /**
65
+ * Scroll vertically by a relative amount.
66
+ *
67
+ * @param state - Current focus area state.
68
+ * @param dy - Relative vertical offset (positive = down).
69
+ * @returns Updated state with new scroll position.
70
+ */
71
+ export function focusAreaScrollBy(state, dy) {
72
+ return { ...state, scroll: scrollBy(state.scroll, dy) };
73
+ }
74
+ /**
75
+ * Scroll vertically to an absolute position.
76
+ *
77
+ * @param state - Current focus area state.
78
+ * @param y - Absolute vertical offset (0-based).
79
+ * @returns Updated state with new scroll position.
80
+ */
81
+ export function focusAreaScrollTo(state, y) {
82
+ return { ...state, scroll: scrollTo(state.scroll, y) };
83
+ }
84
+ /**
85
+ * Scroll to the first line.
86
+ *
87
+ * @param state - Current focus area state.
88
+ * @returns Updated state scrolled to the top.
89
+ */
90
+ export function focusAreaScrollToTop(state) {
91
+ return { ...state, scroll: scrollToTop(state.scroll) };
92
+ }
93
+ /**
94
+ * Scroll to the last line.
95
+ *
96
+ * @param state - Current focus area state.
97
+ * @returns Updated state scrolled to the bottom.
98
+ */
99
+ export function focusAreaScrollToBottom(state) {
100
+ return { ...state, scroll: scrollToBottom(state.scroll) };
101
+ }
102
+ /**
103
+ * Page down (one viewport height).
104
+ *
105
+ * @param state - Current focus area state.
106
+ * @returns Updated state advanced by one page.
107
+ */
108
+ export function focusAreaPageDown(state) {
109
+ return { ...state, scroll: pageDown(state.scroll) };
110
+ }
111
+ /**
112
+ * Page up (one viewport height).
113
+ *
114
+ * @param state - Current focus area state.
115
+ * @returns Updated state moved back by one page.
116
+ */
117
+ export function focusAreaPageUp(state) {
118
+ return { ...state, scroll: pageUp(state.scroll) };
119
+ }
120
+ /**
121
+ * Scroll horizontally by a relative amount.
122
+ * No-op when `overflowX` is `'hidden'`.
123
+ *
124
+ * @param state - Current focus area state.
125
+ * @param dx - Relative horizontal offset (positive = right).
126
+ * @returns Updated state with new horizontal scroll position.
127
+ */
128
+ export function focusAreaScrollByX(state, dx) {
129
+ if (state.overflowX === 'hidden')
130
+ return state;
131
+ return { ...state, scroll: scrollByX(state.scroll, dx) };
132
+ }
133
+ /**
134
+ * Scroll horizontally to an absolute position.
135
+ * No-op when `overflowX` is `'hidden'`.
136
+ *
137
+ * @param state - Current focus area state.
138
+ * @param x - Absolute horizontal offset (0-based).
139
+ * @returns Updated state with new horizontal scroll position.
140
+ */
141
+ export function focusAreaScrollToX(state, x) {
142
+ if (state.overflowX === 'hidden')
143
+ return state;
144
+ return { ...state, scroll: scrollToX(state.scroll, x) };
145
+ }
146
+ /**
147
+ * Update content while preserving scroll position (clamped).
148
+ *
149
+ * @param state - Current focus area state.
150
+ * @param content - New text content to display.
151
+ * @returns Updated state with new content and clamped scroll position.
152
+ */
153
+ export function focusAreaSetContent(state, content) {
154
+ const contentWidth = Math.max(1, state.width - 1);
155
+ const totalLines = content.split('\n').length;
156
+ const hasScrollbar = totalLines > state.height;
157
+ const scrollableWidth = hasScrollbar ? Math.max(1, contentWidth - 1) : contentWidth;
158
+ const viewportWidth = state.overflowX === 'scroll' ? scrollableWidth : undefined;
159
+ const newScroll = createScrollState(content, state.height, viewportWidth);
160
+ const clampedY = Math.min(state.scroll.y, newScroll.maxY);
161
+ const clampedX = Math.min(state.scroll.x, newScroll.maxX);
162
+ return {
163
+ ...state,
164
+ content,
165
+ scroll: { ...newScroll, y: clampedY, x: clampedX },
166
+ };
167
+ }
168
+ // ---------------------------------------------------------------------------
169
+ // Render
170
+ // ---------------------------------------------------------------------------
171
+ /**
172
+ * Render the focus area — viewport content with a colored left gutter.
173
+ *
174
+ * The gutter character (`▎`) is styled based on focus state:
175
+ * - Focused: `focusedGutterToken` (default: `theme.semantic.accent`)
176
+ * - Unfocused: `unfocusedGutterToken` (default: `theme.semantic.muted`)
177
+ * - Static mode: unstyled gutter
178
+ * - Pipe / accessible mode: no gutter (full width to content)
179
+ *
180
+ * @param state - Current focus area state.
181
+ * @param options - Rendering options (focus, tokens, scrollbar, ctx).
182
+ * @returns Rendered focus area string.
183
+ */
184
+ export function focusArea(state, options) {
185
+ const focused = options?.focused ?? true;
186
+ const showScrollbar = options?.showScrollbar ?? true;
187
+ const ctx = options?.ctx;
188
+ const mode = ctx?.mode ?? 'interactive';
189
+ // Pipe and accessible modes: no gutter, full width to content
190
+ const hasGutter = mode !== 'pipe' && mode !== 'accessible';
191
+ const contentWidth = hasGutter ? Math.max(1, state.width - 1) : state.width;
192
+ // Clamp scrollX to render-time content width (may differ from state-time
193
+ // width when pipe/accessible mode removes the gutter)
194
+ let scrollX;
195
+ if (state.overflowX === 'scroll') {
196
+ const maxRenderX = Math.max(0, state.scroll.maxX + (contentWidth < state.width ? 0 : 1));
197
+ scrollX = Math.min(state.scroll.x, maxRenderX);
198
+ }
199
+ const body = viewport({
200
+ width: contentWidth,
201
+ height: state.height,
202
+ content: state.content,
203
+ scrollY: state.scroll.y,
204
+ scrollX,
205
+ showScrollbar,
206
+ });
207
+ if (!hasGutter)
208
+ return body;
209
+ // Determine gutter string
210
+ const gutter = resolveGutter(focused, ctx, options);
211
+ // Prepend gutter to each line
212
+ const lines = body.split('\n');
213
+ return lines.map((line) => gutter + line).join('\n');
214
+ }
215
+ /**
216
+ * Resolve the styled gutter string based on focus state and context.
217
+ */
218
+ function resolveGutter(focused, ctx, options) {
219
+ if (!ctx)
220
+ return GUTTER_CHAR;
221
+ const mode = ctx.mode;
222
+ if (mode === 'static')
223
+ return GUTTER_CHAR;
224
+ const token = focused
225
+ ? (options?.focusedGutterToken ?? ctx.theme.theme.semantic.accent)
226
+ : (options?.unfocusedGutterToken ?? ctx.theme.theme.semantic.muted);
227
+ return ctx.style.styled(token, GUTTER_CHAR);
228
+ }
229
+ // ---------------------------------------------------------------------------
230
+ // Convenience keymap
231
+ // ---------------------------------------------------------------------------
232
+ /**
233
+ * Create a preconfigured KeyMap for focus area navigation.
234
+ *
235
+ * Arrow keys are intentionally excluded — reserved for content-specific
236
+ * navigation (e.g., DAG node selection).
237
+ *
238
+ * @template Msg - Application message type dispatched by key bindings.
239
+ * @param actions - Map of navigation actions to message values.
240
+ * @returns Preconfigured key map with vim-style scroll bindings.
241
+ */
242
+ export function focusAreaKeyMap(actions) {
243
+ const km = createKeyMap()
244
+ .group('Scroll', (g) => {
245
+ g.bind('j', 'Down', actions.scrollDown)
246
+ .bind('k', 'Up', actions.scrollUp)
247
+ .bind('d', 'Page down', actions.pageDown)
248
+ .bind('u', 'Page up', actions.pageUp)
249
+ .bind('g', 'Top', actions.top)
250
+ .bind('shift+g', 'Bottom', actions.bottom);
251
+ if (actions.scrollLeft !== undefined) {
252
+ g.bind('h', 'Scroll left', actions.scrollLeft);
253
+ }
254
+ if (actions.scrollRight !== undefined) {
255
+ g.bind('l', 'Scroll right', actions.scrollRight);
256
+ }
257
+ return g;
258
+ });
259
+ return km;
260
+ }
261
+ //# sourceMappingURL=focus-area.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus-area.js","sourceRoot":"","sources":["../src/focus-area.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -35,4 +35,6 @@ export { type FileEntry, type FilePickerState, type FilePickerOptions, type File
35
35
  export { type ScriptStep, type RunScriptOptions, type RunScriptResult, runScript, } from './driver.js';
36
36
  export { type ShaderFn, type CanvasOptions, canvas, } from './canvas.js';
37
37
  export { type CommandPaletteItem, type CommandPaletteState, type CommandPaletteOptions, createCommandPaletteState, cpFilter, cpFocusNext, cpFocusPrev, cpPageDown, cpPageUp, cpSelectedItem, commandPalette, commandPaletteKeyMap, } from './command-palette.js';
38
+ export { type OverflowX, type FocusAreaState, type FocusAreaOptions, type FocusAreaRenderOptions, createFocusAreaState, focusArea, focusAreaScrollBy, focusAreaScrollTo, focusAreaScrollToTop, focusAreaScrollToBottom, focusAreaPageDown, focusAreaPageUp, focusAreaScrollByX, focusAreaScrollToX, focusAreaSetContent, focusAreaKeyMap, } from './focus-area.js';
39
+ export { type DagPaneDagOptions, type DagPaneState, type DagPaneOptions, type DagPaneRenderOptions, createDagPaneState, dagPane, dagPaneSelectChild, dagPaneSelectParent, dagPaneSelectLeft, dagPaneSelectRight, dagPaneSelectNode, dagPaneClearSelection, dagPaneScrollBy, dagPaneScrollToTop, dagPaneScrollToBottom, dagPanePageDown, dagPanePageUp, dagPaneScrollByX, dagPaneSetSource, dagPaneKeyMap, } from './dag-pane.js';
38
40
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1H,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGrE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGjD,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,IAAI,GACL,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGnC,OAAO,EACL,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,cAAc,GACf,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,cAAc,EACd,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,QAAQ,EACb,OAAO,EACP,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,SAAS,EACT,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,OAAO,EACP,QAAQ,GACT,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,QAAQ,EACR,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,cAAc,EACd,QAAQ,EACR,MAAM,EACN,SAAS,EACT,aAAa,EACb,WAAW,EACX,SAAS,EACT,SAAS,EACT,SAAS,GACV,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,QAAQ,GACT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,IAAI,GACL,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,gBAAgB,EAChB,KAAK,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,eAAe,EACf,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,SAAS,EACT,KAAK,EACL,KAAK,EACL,MAAM,EACN,OAAO,GACR,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,oBAAoB,EACpB,oBAAoB,EACpB,SAAS,EACT,SAAS,EACT,aAAa,EACb,SAAS,EACT,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,yBAAyB,EACzB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,cAAc,GACf,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,UAAU,EACV,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,qBAAqB,EACrB,UAAU,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,MAAM,EACN,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,SAAS,GACV,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,MAAM,GACP,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,yBAAyB,EACzB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,QAAQ,EACR,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,kBAAkB,EAClB,OAAO,EACP,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,GACd,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -56,4 +56,8 @@ export { runScript, } from './driver.js';
56
56
  export { canvas, } from './canvas.js';
57
57
  // Command palette
58
58
  export { createCommandPaletteState, cpFilter, cpFocusNext, cpFocusPrev, cpPageDown, cpPageUp, cpSelectedItem, commandPalette, commandPaletteKeyMap, } from './command-palette.js';
59
+ // Focus area — scrollable pane with colored gutter
60
+ export { createFocusAreaState, focusArea, focusAreaScrollBy, focusAreaScrollTo, focusAreaScrollToTop, focusAreaScrollToBottom, focusAreaPageDown, focusAreaPageUp, focusAreaScrollByX, focusAreaScrollToX, focusAreaSetContent, focusAreaKeyMap, } from './focus-area.js';
61
+ // DAG pane — interactive DAG viewer
62
+ export { createDagPaneState, dagPane, dagPaneSelectChild, dagPaneSelectParent, dagPaneSelectLeft, dagPaneSelectRight, dagPaneSelectNode, dagPaneClearSelection, dagPaneScrollBy, dagPaneScrollToTop, dagPaneScrollToBottom, dagPanePageDown, dagPanePageUp, dagPaneScrollByX, dagPaneSetSource, dagPaneKeyMap, } from './dag-pane.js';
59
63
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flyingrobots/bijou-tui",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "TEA runtime for terminal UIs — model/update/view with keyboard input, alt screen, and layout helpers.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -24,7 +24,7 @@
24
24
  "lint": "tsc --noEmit"
25
25
  },
26
26
  "peerDependencies": {
27
- "@flyingrobots/bijou": "1.0.0"
27
+ "@flyingrobots/bijou": "1.1.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^22.0.0",