@flyingrobots/bijou-tui 1.7.0 → 2.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.
Files changed (57) hide show
  1. package/dist/app-frame-actions.d.ts +37 -0
  2. package/dist/app-frame-actions.d.ts.map +1 -0
  3. package/dist/app-frame-actions.js +313 -0
  4. package/dist/app-frame-actions.js.map +1 -0
  5. package/dist/app-frame-palette.d.ts +16 -0
  6. package/dist/app-frame-palette.d.ts.map +1 -0
  7. package/dist/app-frame-palette.js +158 -0
  8. package/dist/app-frame-palette.js.map +1 -0
  9. package/dist/app-frame-render.d.ts +37 -0
  10. package/dist/app-frame-render.d.ts.map +1 -0
  11. package/dist/app-frame-render.js +277 -0
  12. package/dist/app-frame-render.js.map +1 -0
  13. package/dist/app-frame-types.d.ts +135 -0
  14. package/dist/app-frame-types.d.ts.map +1 -0
  15. package/dist/app-frame-types.js +72 -0
  16. package/dist/app-frame-types.js.map +1 -0
  17. package/dist/app-frame-utils.d.ts +37 -0
  18. package/dist/app-frame-utils.d.ts.map +1 -0
  19. package/dist/app-frame-utils.js +141 -0
  20. package/dist/app-frame-utils.js.map +1 -0
  21. package/dist/app-frame.d.ts +20 -4
  22. package/dist/app-frame.d.ts.map +1 -1
  23. package/dist/app-frame.js +52 -747
  24. package/dist/app-frame.js.map +1 -1
  25. package/dist/eventbus.d.ts +5 -0
  26. package/dist/eventbus.d.ts.map +1 -1
  27. package/dist/eventbus.js +17 -3
  28. package/dist/eventbus.js.map +1 -1
  29. package/dist/index.d.ts +4 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +17 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/layout-preset.d.ts +81 -0
  34. package/dist/layout-preset.d.ts.map +1 -0
  35. package/dist/layout-preset.js +107 -0
  36. package/dist/layout-preset.js.map +1 -0
  37. package/dist/panel-dock.d.ts +52 -0
  38. package/dist/panel-dock.d.ts.map +1 -0
  39. package/dist/panel-dock.js +112 -0
  40. package/dist/panel-dock.js.map +1 -0
  41. package/dist/panel-state.d.ts +30 -0
  42. package/dist/panel-state.d.ts.map +1 -0
  43. package/dist/panel-state.js +50 -0
  44. package/dist/panel-state.js.map +1 -0
  45. package/dist/screen.d.ts +2 -5
  46. package/dist/screen.d.ts.map +1 -1
  47. package/dist/screen.js +2 -4
  48. package/dist/screen.js.map +1 -1
  49. package/dist/split-pane.d.ts +5 -0
  50. package/dist/split-pane.d.ts.map +1 -1
  51. package/dist/split-pane.js +6 -8
  52. package/dist/split-pane.js.map +1 -1
  53. package/dist/transition-shaders.d.ts +101 -3
  54. package/dist/transition-shaders.d.ts.map +1 -1
  55. package/dist/transition-shaders.js +281 -6
  56. package/dist/transition-shaders.js.map +1 -1
  57. package/package.json +3 -3
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Layout rendering for `app-frame.ts`.
3
+ *
4
+ * Recursive tree renderer, page content, maximized pane, header/help lines,
5
+ * transition shader, and string-to-grid tokenization.
6
+ */
7
+ import { resolveSafeCtx } from '@flyingrobots/bijou';
8
+ import { TRANSITION_SHADERS } from './transition-shaders.js';
9
+ import { fitBlock } from './layout-utils.js';
10
+ import { splitPane, splitPaneLayout } from './split-pane.js';
11
+ import { grid, gridLayout } from './grid.js';
12
+ import { createFocusAreaState, focusArea, focusAreaScrollTo, focusAreaScrollToX, } from './focus-area.js';
13
+ import { isMinimized, createPanelVisibilityState } from './panel-state.js';
14
+ import { createPanelDockState, resolveChildOrder, getNodeId } from './panel-dock.js';
15
+ import { tokenizeAnsi } from './viewport.js';
16
+ import { helpShort } from './help.js';
17
+ import { findPaneNode, isPaneMinimized, mergeMaps, offsetRect, fitLine, mergeBindingSources, } from './app-frame-utils.js';
18
+ /** Recursively render a layout tree node (pane, split, or grid) into a rect. */
19
+ export function renderFrameNode(node, rect, ctx) {
20
+ if (rect.width <= 0 || rect.height <= 0) {
21
+ return { output: '', paneRects: new Map(), paneOrder: [] };
22
+ }
23
+ if (node.kind === 'pane') {
24
+ // Minimized pane: render as collapsed title bar
25
+ if (isMinimized(ctx.visibility, node.paneId)) {
26
+ const titleBar = `[${node.paneId}] \u25b8`; // ▸
27
+ const output = fitBlock(titleBar, rect.width, rect.height).join('\n');
28
+ return {
29
+ output,
30
+ paneRects: new Map([[node.paneId, rect]]),
31
+ paneOrder: [node.paneId],
32
+ };
33
+ }
34
+ const prior = ctx.scrollByPane[node.paneId] ?? { x: 0, y: 0 };
35
+ const content = node.render(rect.width, rect.height);
36
+ let state = createFocusAreaState({
37
+ content,
38
+ width: rect.width,
39
+ height: rect.height,
40
+ overflowX: node.overflowX ?? 'hidden',
41
+ });
42
+ state = focusAreaScrollTo(state, prior.y);
43
+ state = focusAreaScrollToX(state, prior.x);
44
+ const output = focusArea(state, { focused: node.paneId === ctx.focusedPaneId });
45
+ return {
46
+ output,
47
+ paneRects: new Map([[node.paneId, rect]]),
48
+ paneOrder: [node.paneId],
49
+ };
50
+ }
51
+ if (node.kind === 'split') {
52
+ const direction = node.direction ?? 'row';
53
+ // Consult dock state for child order
54
+ const defaultChildIds = [getNodeId(node.paneA), getNodeId(node.paneB)];
55
+ const resolvedOrder = resolveChildOrder(ctx.dockState, node.splitId, defaultChildIds);
56
+ const swapped = resolvedOrder[0] !== defaultChildIds[0];
57
+ const effectiveA = swapped ? node.paneB : node.paneA;
58
+ const effectiveB = swapped ? node.paneA : node.paneB;
59
+ // Check for minimized panes — give minimized pane 1 row, sibling gets rest
60
+ const aMinimized = isPaneMinimized(effectiveA, ctx.visibility);
61
+ const bMinimized = isPaneMinimized(effectiveB, ctx.visibility);
62
+ let splitState = node.state;
63
+ // Apply split ratio overrides from layout presets
64
+ const ratioOverride = ctx.model.splitRatioOverrides[ctx.pageId]?.[node.splitId];
65
+ if (ratioOverride !== undefined) {
66
+ splitState = { ...splitState, ratio: ratioOverride };
67
+ }
68
+ if (aMinimized && !bMinimized) {
69
+ // A is minimized: give it minimal space
70
+ const mainAxisTotal = direction === 'row' ? rect.width : rect.height;
71
+ const minimizedSize = Math.min(1, mainAxisTotal);
72
+ splitState = { ...splitState, ratio: minimizedSize / Math.max(1, mainAxisTotal) };
73
+ }
74
+ else if (bMinimized && !aMinimized) {
75
+ // B is minimized: give A most of the space
76
+ const mainAxisTotal = direction === 'row' ? rect.width : rect.height;
77
+ const minimizedSize = Math.min(1, mainAxisTotal);
78
+ splitState = { ...splitState, ratio: 1 - minimizedSize / Math.max(1, mainAxisTotal) };
79
+ }
80
+ const layout = splitPaneLayout(splitState, {
81
+ direction,
82
+ width: rect.width,
83
+ height: rect.height,
84
+ minA: node.minA,
85
+ minB: node.minB,
86
+ });
87
+ const aRect = offsetRect(layout.paneA, rect.row, rect.col);
88
+ const bRect = offsetRect(layout.paneB, rect.row, rect.col);
89
+ const a = renderFrameNode(effectiveA, aRect, ctx);
90
+ const b = renderFrameNode(effectiveB, bRect, ctx);
91
+ const output = splitPane(splitState, {
92
+ direction,
93
+ width: rect.width,
94
+ height: rect.height,
95
+ minA: node.minA,
96
+ minB: node.minB,
97
+ dividerChar: node.dividerChar,
98
+ paneA: () => a.output,
99
+ paneB: () => b.output,
100
+ });
101
+ return {
102
+ output,
103
+ paneRects: mergeMaps(a.paneRects, b.paneRects),
104
+ paneOrder: [...a.paneOrder, ...b.paneOrder],
105
+ };
106
+ }
107
+ const relRects = gridLayout({
108
+ width: rect.width,
109
+ height: rect.height,
110
+ columns: node.columns,
111
+ rows: node.rows,
112
+ areas: node.areas,
113
+ gap: node.gap,
114
+ });
115
+ const renderedByArea = new Map();
116
+ for (const [areaName, areaRect] of relRects) {
117
+ const absoluteAreaRect = offsetRect(areaRect, rect.row, rect.col);
118
+ const child = node.cells[areaName];
119
+ if (child == null) {
120
+ resolveSafeCtx()?.io.writeError(`createFramedApp: grid cell "${areaName}" missing in page "${ctx.pageId}" — rendering placeholder\n`);
121
+ renderedByArea.set(areaName, renderMissingGridCell(areaName, absoluteAreaRect));
122
+ continue;
123
+ }
124
+ renderedByArea.set(areaName, renderFrameNode(child, absoluteAreaRect, ctx));
125
+ }
126
+ const output = grid({
127
+ width: rect.width,
128
+ height: rect.height,
129
+ columns: node.columns,
130
+ rows: node.rows,
131
+ areas: node.areas,
132
+ gap: node.gap,
133
+ cells: Object.fromEntries([...renderedByArea.entries()].map(([name, rendered]) => [name, () => rendered.output])),
134
+ });
135
+ let paneRects = new Map();
136
+ const seenPaneIds = new Set();
137
+ const paneOrder = [];
138
+ for (const rendered of renderedByArea.values()) {
139
+ for (const [paneId, paneRect] of rendered.paneRects.entries()) {
140
+ if (paneRects.has(paneId)) {
141
+ throw new Error(`createFramedApp: duplicate paneId "${paneId}" in rendered layout`);
142
+ }
143
+ paneRects.set(paneId, paneRect);
144
+ }
145
+ for (const paneId of rendered.paneOrder) {
146
+ if (seenPaneIds.has(paneId)) {
147
+ throw new Error(`createFramedApp: duplicate paneId "${paneId}" in rendered pane order`);
148
+ }
149
+ seenPaneIds.add(paneId);
150
+ paneOrder.push(paneId);
151
+ }
152
+ }
153
+ return { output, paneRects, paneOrder };
154
+ }
155
+ /** Render a placeholder for a grid area that has no matching cell definition. */
156
+ export function renderMissingGridCell(areaName, rect) {
157
+ return {
158
+ output: fitBlock(`[missing grid cell: ${areaName}]`, rect.width, rect.height).join('\n'),
159
+ paneRects: new Map(),
160
+ paneOrder: [],
161
+ };
162
+ }
163
+ /** Render a page's layout tree within the frame body rect. */
164
+ export function renderPageContent(pageId, model, bodyRect, pagesById) {
165
+ const page = pagesById.get(pageId);
166
+ const pageModel = model.pageModels[pageId];
167
+ const renderCtx = {
168
+ model,
169
+ pageId,
170
+ focusedPaneId: model.focusedPaneByPage[pageId],
171
+ scrollByPane: model.scrollByPage[pageId] ?? {},
172
+ visibility: model.minimizedByPage[pageId] ?? createPanelVisibilityState(),
173
+ dockState: model.dockStateByPage[pageId] ?? createPanelDockState(),
174
+ };
175
+ return renderFrameNode(page.layout(pageModel), bodyRect, renderCtx);
176
+ }
177
+ /** Render only the maximized pane at the full body rect. */
178
+ export function renderMaximizedPane(pageId, model, bodyRect, pagesById, maximizedPaneId) {
179
+ const page = pagesById.get(pageId);
180
+ const pageModel = model.pageModels[pageId];
181
+ const layoutTree = page.layout(pageModel);
182
+ const paneNode = findPaneNode(layoutTree, maximizedPaneId);
183
+ if (paneNode == null) {
184
+ // Pane not found, fall back to normal rendering
185
+ return renderPageContent(pageId, model, bodyRect, pagesById);
186
+ }
187
+ const prior = model.scrollByPage[pageId]?.[maximizedPaneId] ?? { x: 0, y: 0 };
188
+ const content = paneNode.render(bodyRect.width, bodyRect.height);
189
+ let state = createFocusAreaState({
190
+ content,
191
+ width: bodyRect.width,
192
+ height: bodyRect.height,
193
+ overflowX: paneNode.overflowX ?? 'hidden',
194
+ });
195
+ state = focusAreaScrollTo(state, prior.y);
196
+ state = focusAreaScrollToX(state, prior.x);
197
+ const output = focusArea(state, { focused: true });
198
+ return {
199
+ output,
200
+ paneRects: new Map([[maximizedPaneId, bodyRect]]),
201
+ paneOrder: [maximizedPaneId],
202
+ };
203
+ }
204
+ /** Render the top header line showing the app title and tab bar. */
205
+ export function renderHeaderLine(model, options, pagesById) {
206
+ const title = options.title ?? 'App';
207
+ const tabs = model.pageOrder.map((id) => {
208
+ const page = pagesById.get(id);
209
+ return id === model.activePageId ? `[${page.title}]` : ` ${page.title} `;
210
+ }).join(' ');
211
+ return fitLine(`${title} ${tabs}`, model.columns);
212
+ }
213
+ /** Render the bottom status line showing mode, focused pane, and key hints. */
214
+ export function renderHelpLine(model, frameKeys, options, activePage) {
215
+ const mode = model.commandPalette != null
216
+ ? 'PALETTE'
217
+ : model.helpOpen
218
+ ? 'HELP'
219
+ : 'NORMAL';
220
+ const focusedPane = model.focusedPaneByPage[model.activePageId] ?? '-';
221
+ const status = `[${mode}] page:${model.activePageId} pane:${focusedPane}`;
222
+ const source = mergeBindingSources(frameKeys, options.globalKeys, activePage.helpSource ?? activePage.keyMap);
223
+ const hint = helpShort(source);
224
+ const line = hint.length > 0
225
+ ? ` ${status} ${hint}`
226
+ : ` ${status}`;
227
+ return fitLine(line, model.columns);
228
+ }
229
+ /**
230
+ * Split a styled multiline string into a 2D grid of single-column characters.
231
+ * Each cell is a fully-styled string (including resets).
232
+ */
233
+ export function stringToGrid(str, width, height) {
234
+ const lines = str.split('\n');
235
+ const grid = [];
236
+ for (let y = 0; y < height; y++) {
237
+ const line = lines[y] ?? '';
238
+ grid.push(tokenizeAnsi(line, width));
239
+ }
240
+ return grid;
241
+ }
242
+ /**
243
+ * Apply a transition shader to blend between the previous and next page views.
244
+ *
245
+ * @param frame - Monotonic frame counter passed to shaders for temporal effects
246
+ * (glitch flickering, static noise). Defaults to 0 for stateless shaders.
247
+ */
248
+ export function renderTransition(prev, next, style, progress, width, height, ctx, frame = 0) {
249
+ const shader = typeof style === 'function' ? style : TRANSITION_SHADERS[style];
250
+ if (!shader)
251
+ return next;
252
+ if (width <= 0 || height <= 0)
253
+ return next;
254
+ const prevGrid = stringToGrid(prev, width, height);
255
+ const nextGrid = stringToGrid(next, width, height);
256
+ const lines = [];
257
+ for (let y = 0; y < height; y++) {
258
+ let line = '';
259
+ for (let x = 0; x < width; x++) {
260
+ // Shared stable-ish pseudo-random seed based on coordinates
261
+ const seed = Math.sin(x * 12.9898 + y * 78.233) * 43758.5453;
262
+ const rand = seed - Math.floor(seed);
263
+ const result = shader({ x, y, width, height, progress, rand, frame, ctx });
264
+ const showNext = result.showNext;
265
+ const charOverride = result.char;
266
+ if (charOverride !== undefined) {
267
+ line += charOverride;
268
+ }
269
+ else {
270
+ line += (showNext ? nextGrid[y]?.[x] : prevGrid[y]?.[x]) ?? ' ';
271
+ }
272
+ }
273
+ lines.push(line);
274
+ }
275
+ return lines.join('\n');
276
+ }
277
+ //# sourceMappingURL=app-frame-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-frame-render.js","sourceRoot":"","sources":["../src/app-frame-render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Internal types and message utilities for `app-frame.ts`.
3
+ *
4
+ * These types are NOT part of the public API surface — they support
5
+ * the internal wiring of `createFramedApp`.
6
+ */
7
+ import type { CommandPaletteItem } from './command-palette.js';
8
+ import type { KeyMsg, Cmd } from './types.js';
9
+ import type { BindingInfo } from './keybindings.js';
10
+ import type { PanelVisibilityState } from './panel-state.js';
11
+ import type { PanelDockState } from './panel-dock.js';
12
+ import type { FrameModel } from './app-frame.js';
13
+ export declare const PAGE_MSG_TOKEN: unique symbol;
14
+ export declare const FRAME_MSG_TOKEN: unique symbol;
15
+ /** Internal model extending the public FrameModel with palette entries. */
16
+ export interface InternalFrameModel<PageModel, Msg> extends FrameModel<PageModel> {
17
+ readonly commandPaletteEntries?: readonly PaletteEntry<Msg>[];
18
+ }
19
+ /** A command palette entry linking a UI item to an action or message. */
20
+ export interface PaletteEntry<Msg> {
21
+ readonly id: string;
22
+ readonly item: CommandPaletteItem;
23
+ readonly msgAction?: Msg;
24
+ readonly targetPageId?: string;
25
+ readonly frameAction?: FrameAction;
26
+ }
27
+ /** Per-call context passed through the recursive layout renderer. */
28
+ export interface RenderContext<PageModel, Msg> {
29
+ readonly model: InternalFrameModel<PageModel, Msg>;
30
+ readonly pageId: string;
31
+ readonly focusedPaneId: string | undefined;
32
+ readonly scrollByPane: Readonly<Record<string, {
33
+ readonly x: number;
34
+ readonly y: number;
35
+ }>>;
36
+ readonly visibility: PanelVisibilityState;
37
+ readonly dockState: PanelDockState;
38
+ }
39
+ /** Output of a layout node render pass. */
40
+ export interface RenderResult {
41
+ readonly output: string;
42
+ readonly paneRects: ReadonlyMap<string, import('./layout-rect.js').LayoutRect>;
43
+ readonly paneOrder: readonly string[];
44
+ }
45
+ /** Discriminated union of all frame-level actions (tabs, panes, scroll, palette, help, transitions). */
46
+ export type FrameAction = {
47
+ type: 'toggle-help';
48
+ } | {
49
+ type: 'prev-tab';
50
+ } | {
51
+ type: 'next-tab';
52
+ } | {
53
+ type: 'next-pane';
54
+ } | {
55
+ type: 'prev-pane';
56
+ } | {
57
+ type: 'scroll-up';
58
+ } | {
59
+ type: 'scroll-down';
60
+ } | {
61
+ type: 'page-up';
62
+ } | {
63
+ type: 'page-down';
64
+ } | {
65
+ type: 'top';
66
+ } | {
67
+ type: 'bottom';
68
+ } | {
69
+ type: 'scroll-left';
70
+ } | {
71
+ type: 'scroll-right';
72
+ } | {
73
+ type: 'open-palette';
74
+ } | {
75
+ type: 'toggle-minimize';
76
+ } | {
77
+ type: 'toggle-maximize';
78
+ } | {
79
+ type: 'dock-up';
80
+ } | {
81
+ type: 'dock-down';
82
+ } | {
83
+ type: 'dock-left';
84
+ } | {
85
+ type: 'dock-right';
86
+ } | {
87
+ type: 'transition';
88
+ progress: number;
89
+ generation: number;
90
+ } | {
91
+ type: 'transition-complete';
92
+ generation: number;
93
+ };
94
+ /** Discriminated union of command palette navigation/selection actions. */
95
+ export type PaletteAction = {
96
+ type: 'cp-next';
97
+ } | {
98
+ type: 'cp-prev';
99
+ } | {
100
+ type: 'cp-page-down';
101
+ } | {
102
+ type: 'cp-page-up';
103
+ } | {
104
+ type: 'cp-select';
105
+ } | {
106
+ type: 'cp-close';
107
+ };
108
+ /** Wrapper that tags a user message with its originating page ID. */
109
+ export interface PageScopedMsg<Msg> {
110
+ readonly [PAGE_MSG_TOKEN]: true;
111
+ readonly pageId: string;
112
+ readonly msg: Msg;
113
+ }
114
+ /** Wrapper that tags a frame-internal action for the update loop. */
115
+ export interface FrameScopedMsg {
116
+ readonly [FRAME_MSG_TOKEN]: true;
117
+ readonly action: FrameAction;
118
+ }
119
+ /** Type guard: is this message a frame-internal action wrapper? */
120
+ export declare function isFrameScopedMsg(value: unknown): value is FrameScopedMsg;
121
+ /** Wrap a frame action into a FrameScopedMsg for the update loop. */
122
+ export declare function wrapFrameMsg(action: FrameAction): FrameScopedMsg;
123
+ /** Type guard: is this message a page-scoped wrapper? */
124
+ export declare function isPageScopedMsg<Msg>(value: unknown): value is PageScopedMsg<Msg>;
125
+ /** Tag a user message with its originating page ID. */
126
+ export declare function wrapPageMsg<Msg>(pageId: string, msg: Msg): Msg;
127
+ /** Create a command that immediately resolves with the given message. */
128
+ export declare function emitMsg<Msg>(msg: Msg): Cmd<Msg>;
129
+ /** Create a command that emits a page-scoped message. */
130
+ export declare function emitMsgForPage<Msg>(pageId: string, msg: Msg): Cmd<Msg>;
131
+ /** Wrap a page-level command so its emitted messages are tagged with the page ID. */
132
+ export declare function wrapCmdForPage<Msg>(pageId: string, cmd: Cmd<Msg>): Cmd<Msg>;
133
+ /** Convert a binding's key combo into a synthetic KeyMsg for dispatch. */
134
+ export declare function comboToMsg(binding: BindingInfo): KeyMsg;
135
+ //# sourceMappingURL=app-frame-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-frame-types.d.ts","sourceRoot":"","sources":["../src/app-frame-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Internal types and message utilities for `app-frame.ts`.
3
+ *
4
+ * These types are NOT part of the public API surface — they support
5
+ * the internal wiring of `createFramedApp`.
6
+ */
7
+ import { QUIT } from './types.js';
8
+ // ---------------------------------------------------------------------------
9
+ // Symbols
10
+ // ---------------------------------------------------------------------------
11
+ export const PAGE_MSG_TOKEN = Symbol('app-frame-page-msg');
12
+ export const FRAME_MSG_TOKEN = Symbol('app-frame-frame-msg');
13
+ // ---------------------------------------------------------------------------
14
+ // Message utility functions
15
+ // ---------------------------------------------------------------------------
16
+ /** Type guard: is this message a frame-internal action wrapper? */
17
+ export function isFrameScopedMsg(value) {
18
+ return typeof value === 'object'
19
+ && value !== null
20
+ && FRAME_MSG_TOKEN in value
21
+ && value[FRAME_MSG_TOKEN] === true;
22
+ }
23
+ /** Wrap a frame action into a FrameScopedMsg for the update loop. */
24
+ export function wrapFrameMsg(action) {
25
+ return {
26
+ [FRAME_MSG_TOKEN]: true,
27
+ action,
28
+ };
29
+ }
30
+ /** Type guard: is this message a page-scoped wrapper? */
31
+ export function isPageScopedMsg(value) {
32
+ return typeof value === 'object'
33
+ && value !== null
34
+ && PAGE_MSG_TOKEN in value
35
+ && value[PAGE_MSG_TOKEN] === true;
36
+ }
37
+ /** Tag a user message with its originating page ID. */
38
+ export function wrapPageMsg(pageId, msg) {
39
+ return {
40
+ [PAGE_MSG_TOKEN]: true,
41
+ pageId,
42
+ msg,
43
+ };
44
+ }
45
+ /** Create a command that immediately resolves with the given message. */
46
+ export function emitMsg(msg) {
47
+ return () => Promise.resolve(msg);
48
+ }
49
+ /** Create a command that emits a page-scoped message. */
50
+ export function emitMsgForPage(pageId, msg) {
51
+ return async () => wrapPageMsg(pageId, msg);
52
+ }
53
+ /** Wrap a page-level command so its emitted messages are tagged with the page ID. */
54
+ export function wrapCmdForPage(pageId, cmd) {
55
+ return async (emit) => {
56
+ const result = await cmd((msg) => emit(wrapPageMsg(pageId, msg)));
57
+ if (result === undefined || result === QUIT)
58
+ return result;
59
+ return wrapPageMsg(pageId, result);
60
+ };
61
+ }
62
+ /** Convert a binding's key combo into a synthetic KeyMsg for dispatch. */
63
+ export function comboToMsg(binding) {
64
+ return {
65
+ type: 'key',
66
+ key: binding.combo.key,
67
+ ctrl: binding.combo.ctrl,
68
+ alt: binding.combo.alt,
69
+ shift: binding.combo.shift,
70
+ };
71
+ }
72
+ //# sourceMappingURL=app-frame-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-frame-types.js","sourceRoot":"","sources":["../src/app-frame-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAMlC,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AA4F7D,8EAA8E;AAC9E,4BAA4B;AAC5B,8EAA8E;AAE9E,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ;WAC3B,KAAK,KAAK,IAAI;WACd,eAAe,IAAI,KAAK;WACvB,KAAwB,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;AAC3D,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,OAAO;QACL,CAAC,eAAe,CAAC,EAAE,IAAI;QACvB,MAAM;KACP,CAAC;AACJ,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,eAAe,CAAM,KAAc;IACjD,OAAO,OAAO,KAAK,KAAK,QAAQ;WAC3B,KAAK,KAAK,IAAI;WACd,cAAc,IAAI,KAAK;WACtB,KAA4B,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;AAC9D,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAM,MAAc,EAAE,GAAQ;IACvD,OAAO;QACL,CAAC,cAAc,CAAC,EAAE,IAAI;QACtB,MAAM;QACN,GAAG;KACc,CAAC;AACtB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,OAAO,CAAM,GAAQ;IACnC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,cAAc,CAAM,MAAc,EAAE,GAAQ;IAC1D,OAAO,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,cAAc,CAAM,MAAc,EAAE,GAAa;IAC/D,OAAO,KAAK,EAAE,IAAI,EAAE,EAAE;QACpB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAmB,CAAC,CAAC,CAAC;QACpF,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC;QAC3D,OAAO,WAAW,CAAC,MAAM,EAAE,MAAa,CAAC,CAAC;IAC5C,CAAC,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,UAAU,CAAC,OAAoB;IAC7C,OAAO;QACL,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG;QACtB,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;QACxB,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK;KAC3B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Pure utility functions for `app-frame.ts`.
3
+ *
4
+ * Tree traversal, layout geometry, key map construction, and binding
5
+ * source merging — no state, no side effects.
6
+ */
7
+ import type { FrameLayoutNode } from './app-frame.js';
8
+ import type { FrameAction } from './app-frame-types.js';
9
+ import type { LayoutRect } from './layout-rect.js';
10
+ import type { PanelVisibilityState } from './panel-state.js';
11
+ import { type KeyMap } from './keybindings.js';
12
+ import type { BindingSource } from './help.js';
13
+ /** Recursively collect all pane IDs from a layout tree in declaration order. */
14
+ export declare function collectPaneIds(node: FrameLayoutNode): string[];
15
+ /** Extract unique area names from CSS-grid-style template strings. */
16
+ export declare function declaredAreaNames(areas: readonly string[]): string[];
17
+ /** Throw if any pane ID appears more than once in the given list. */
18
+ export declare function assertUniquePaneIds(paneIds: readonly string[], scope: string): void;
19
+ /** Walk the layout tree to find the pane node with the given ID. */
20
+ export declare function findPaneNode(node: FrameLayoutNode, paneId: string): Extract<FrameLayoutNode, {
21
+ kind: 'pane';
22
+ }> | undefined;
23
+ /** Check if a layout node (or its first descendant pane) is minimized. */
24
+ export declare function isPaneMinimized(node: FrameLayoutNode, visibility: PanelVisibilityState): boolean;
25
+ /** Merge two read-only maps into a new mutable map. */
26
+ export declare function mergeMaps<K, V>(a: ReadonlyMap<K, V>, b: ReadonlyMap<K, V>): Map<K, V>;
27
+ /** Translate a layout rect by the given row and column offsets. */
28
+ export declare function offsetRect(rect: LayoutRect, rowOffset: number, colOffset: number): LayoutRect;
29
+ /** Compute the available rect for page content (screen minus header and footer). */
30
+ export declare function frameBodyRect(columns: number, rows: number): LayoutRect;
31
+ /** Clip or pad a single line to exactly `width` visible columns. */
32
+ export declare function fitLine(line: string, width: number): string;
33
+ /** Combine multiple binding sources into a single source for help display. */
34
+ export declare function mergeBindingSources(...sources: Array<BindingSource | undefined>): BindingSource;
35
+ /** Build the default key map for frame-level actions (tabs, panes, scroll, help '?', command palette 'ctrl+p'/':'). */
36
+ export declare function createFrameKeyMap(): KeyMap<FrameAction>;
37
+ //# sourceMappingURL=app-frame-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-frame-utils.d.ts","sourceRoot":"","sources":["../src/app-frame-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAI/C,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,EAAE,CAW9D;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAQpE;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQnF;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAQ1H;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAKhG;AAED,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAKrF;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAO7F;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAOvE;AAED,oEAAoE;AACpE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,aAAa,GAAG,SAAS,CAAC,GAAG,aAAa,CAW/F;AAED,uHAAuH;AACvH,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,WAAW,CAAC,CA6BvD"}