@flyingrobots/bijou-tui 0.5.1 → 0.6.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
@@ -4,14 +4,11 @@ TEA runtime for terminal UIs — model/update/view with physics-based animation,
4
4
 
5
5
  Inspired by [Bubble Tea](https://github.com/charmbracelet/bubbletea) (Go) and [GSAP](https://gsap.com/) animation.
6
6
 
7
- ## What's New in 0.4.0?
7
+ ## What's New in 0.6.0?
8
8
 
9
- - **`composite()`** — ANSI-safe overlay compositing with dim background support
10
- - **`modal()`** — centered dialog overlay with title, body, hint, and auto-centering
11
- - **`toast()`** — anchored notification overlay with success/error/info variants
12
- - **`pager()`** — scrollable content viewer with status line and convenience keymap
13
- - **`interactiveAccordion()`** — navigable accordion with focus tracking and expand/collapse
14
- - **`createPanelGroup()`** — multi-pane focus management with hotkey switching
9
+ - **`navigableTable()`** — keyboard-navigable table with focus management, vertical scrolling, and vim-style keybindings
10
+ - **`browsableList()`** — navigable list with focus tracking, scroll viewport, descriptions, and convenience keymap
11
+ - **`filePicker()`** — directory browser with focus navigation, extension filtering, and `IOPort` integration
15
12
 
16
13
  See the [CHANGELOG](https://github.com/flyingrobots/bijou/blob/main/docs/CHANGELOG.md) for the full release history.
17
14
 
@@ -286,6 +283,51 @@ const output = composite(backgroundView, [dialog, notification], { dim: true });
286
283
 
287
284
  Each overlay is a `{ content, row, col }` object. `composite()` splices them onto the background using painter's algorithm (last overlay wins on overlap). The `dim` option fades the background with ANSI dim.
288
285
 
286
+ ## Building Blocks
287
+
288
+ Reusable stateful components that follow the TEA state + pure transformers + sync render + convenience keymap pattern:
289
+
290
+ ### Navigable Table
291
+
292
+ ```typescript
293
+ import {
294
+ createNavigableTableState, navigableTable, navTableFocusNext,
295
+ navTableKeyMap, helpShort,
296
+ } from '@flyingrobots/bijou-tui';
297
+
298
+ const state = createNavigableTableState({ columns, rows, height: 10 });
299
+ const output = navigableTable(state, { ctx });
300
+ const next = navTableFocusNext(state);
301
+ ```
302
+
303
+ ### Browsable List
304
+
305
+ ```typescript
306
+ import {
307
+ createBrowsableListState, browsableList, listFocusNext,
308
+ browsableListKeyMap,
309
+ } from '@flyingrobots/bijou-tui';
310
+
311
+ const state = createBrowsableListState({ items, height: 10 });
312
+ const output = browsableList(state);
313
+ ```
314
+
315
+ ### File Picker
316
+
317
+ ```typescript
318
+ import {
319
+ createFilePickerState, filePicker, fpFocusNext, fpEnter, fpBack,
320
+ filePickerKeyMap,
321
+ } from '@flyingrobots/bijou-tui';
322
+ import { nodeIO } from '@flyingrobots/bijou-node';
323
+
324
+ const io = nodeIO();
325
+ const state = createFilePickerState({ cwd: process.cwd(), io, height: 15 });
326
+ const output = filePicker(state);
327
+ ```
328
+
329
+ All building blocks include `*KeyMap()` factories for preconfigured vim-style keybindings.
330
+
289
331
  ## Related Packages
290
332
 
291
333
  - [`@flyingrobots/bijou`](https://www.npmjs.com/package/@flyingrobots/bijou) — Zero-dependency core with all components and theme engine
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Browsable list building block — a scrollable, navigable list with focus tracking.
3
+ *
4
+ * Provides state transformers for focus and page navigation, a pure render
5
+ * function with viewport clipping, and a convenience keymap for vim-style
6
+ * navigation.
7
+ *
8
+ * ```ts
9
+ * // In TEA init:
10
+ * const listState = createBrowsableListState({ items, height: 10 });
11
+ *
12
+ * // In TEA view:
13
+ * const output = browsableList(model.listState);
14
+ *
15
+ * // In TEA update:
16
+ * case 'focus-next':
17
+ * return [{ ...model, listState: listFocusNext(model.listState) }, []];
18
+ * case 'select':
19
+ * const selected = model.listState.items[model.listState.focusIndex];
20
+ * // handle selection...
21
+ * ```
22
+ */
23
+ import type { BijouContext } from '@flyingrobots/bijou';
24
+ import { type KeyMap } from './keybindings.js';
25
+ export interface BrowsableListItem<T = string> {
26
+ label: string;
27
+ value: T;
28
+ description?: string;
29
+ }
30
+ export interface BrowsableListState<T = string> {
31
+ readonly items: readonly BrowsableListItem<T>[];
32
+ readonly focusIndex: number;
33
+ readonly scrollY: number;
34
+ readonly height: number;
35
+ }
36
+ export interface BrowsableListOptions<T = string> {
37
+ readonly items: readonly BrowsableListItem<T>[];
38
+ readonly height?: number;
39
+ }
40
+ export interface BrowsableListRenderOptions {
41
+ readonly focusIndicator?: string;
42
+ readonly ctx?: BijouContext;
43
+ }
44
+ /**
45
+ * Create initial browsable list state from items and optional height.
46
+ * Focus starts at index 0 with scroll at the top.
47
+ */
48
+ export declare function createBrowsableListState<T = string>(options: BrowsableListOptions<T>): BrowsableListState<T>;
49
+ /** Move focus to the next item (wraps around). */
50
+ export declare function listFocusNext<T>(state: BrowsableListState<T>): BrowsableListState<T>;
51
+ /** Move focus to the previous item (wraps around). */
52
+ export declare function listFocusPrev<T>(state: BrowsableListState<T>): BrowsableListState<T>;
53
+ /** Move focus down by one page (clamps to last item). */
54
+ export declare function listPageDown<T>(state: BrowsableListState<T>): BrowsableListState<T>;
55
+ /** Move focus up by one page (clamps to first item). */
56
+ export declare function listPageUp<T>(state: BrowsableListState<T>): BrowsableListState<T>;
57
+ /**
58
+ * Render the browsable list — visible items within the viewport with a
59
+ * focus indicator on the currently focused item.
60
+ *
61
+ * Items with a `description` field render as `label — description`.
62
+ */
63
+ export declare function browsableList<T>(state: BrowsableListState<T>, options?: BrowsableListRenderOptions): string;
64
+ /**
65
+ * Create a preconfigured KeyMap for browsable list navigation.
66
+ *
67
+ * The caller provides their own message types for each action:
68
+ * ```ts
69
+ * const keys = browsableListKeyMap({
70
+ * focusNext: { type: 'next' },
71
+ * focusPrev: { type: 'prev' },
72
+ * pageDown: { type: 'page-down' },
73
+ * pageUp: { type: 'page-up' },
74
+ * select: { type: 'select' },
75
+ * quit: { type: 'quit' },
76
+ * });
77
+ * ```
78
+ */
79
+ export declare function browsableListKeyMap<Msg>(actions: {
80
+ focusNext: Msg;
81
+ focusPrev: Msg;
82
+ pageDown: Msg;
83
+ pageUp: Msg;
84
+ select: Msg;
85
+ quit: Msg;
86
+ }): KeyMap<Msg>;
87
+ //# sourceMappingURL=browsable-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browsable-list.d.ts","sourceRoot":"","sources":["../src/browsable-list.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,MAAM;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;IACT,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,MAAM;IAC5C,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC,GAAG,MAAM;IAC9C,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC;CAC7B;AAMD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,MAAM,EACjD,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,kBAAkB,CAAC,CAAC,CAAC,CAQvB;AAMD,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAIpF;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAIpF;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAInF;AAED,wDAAwD;AACxD,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAIjF;AAqBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC5B,OAAO,CAAC,EAAE,0BAA0B,GACnC,MAAM,CAkBR;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE;IAChD,SAAS,EAAE,GAAG,CAAC;IACf,SAAS,EAAE,GAAG,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;CACX,GAAG,MAAM,CAAC,GAAG,CAAC,CAed"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Browsable list building block — a scrollable, navigable list with focus tracking.
3
+ *
4
+ * Provides state transformers for focus and page navigation, a pure render
5
+ * function with viewport clipping, and a convenience keymap for vim-style
6
+ * navigation.
7
+ *
8
+ * ```ts
9
+ * // In TEA init:
10
+ * const listState = createBrowsableListState({ items, height: 10 });
11
+ *
12
+ * // In TEA view:
13
+ * const output = browsableList(model.listState);
14
+ *
15
+ * // In TEA update:
16
+ * case 'focus-next':
17
+ * return [{ ...model, listState: listFocusNext(model.listState) }, []];
18
+ * case 'select':
19
+ * const selected = model.listState.items[model.listState.focusIndex];
20
+ * // handle selection...
21
+ * ```
22
+ */
23
+ import { createKeyMap } from './keybindings.js';
24
+ // ---------------------------------------------------------------------------
25
+ // State creation
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * Create initial browsable list state from items and optional height.
29
+ * Focus starts at index 0 with scroll at the top.
30
+ */
31
+ export function createBrowsableListState(options) {
32
+ const height = Math.max(1, options.height ?? 10);
33
+ return {
34
+ items: [...options.items],
35
+ focusIndex: 0,
36
+ scrollY: 0,
37
+ height,
38
+ };
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // State transformers
42
+ // ---------------------------------------------------------------------------
43
+ /** Move focus to the next item (wraps around). */
44
+ export function listFocusNext(state) {
45
+ if (state.items.length === 0)
46
+ return state;
47
+ const focusIndex = (state.focusIndex + 1) % state.items.length;
48
+ return { ...state, focusIndex, scrollY: adjustScroll(focusIndex, state.scrollY, state.height, state.items.length) };
49
+ }
50
+ /** Move focus to the previous item (wraps around). */
51
+ export function listFocusPrev(state) {
52
+ if (state.items.length === 0)
53
+ return state;
54
+ const focusIndex = (state.focusIndex - 1 + state.items.length) % state.items.length;
55
+ return { ...state, focusIndex, scrollY: adjustScroll(focusIndex, state.scrollY, state.height, state.items.length) };
56
+ }
57
+ /** Move focus down by one page (clamps to last item). */
58
+ export function listPageDown(state) {
59
+ if (state.items.length === 0)
60
+ return state;
61
+ const focusIndex = Math.min(state.focusIndex + state.height, state.items.length - 1);
62
+ return { ...state, focusIndex, scrollY: adjustScroll(focusIndex, state.scrollY, state.height, state.items.length) };
63
+ }
64
+ /** Move focus up by one page (clamps to first item). */
65
+ export function listPageUp(state) {
66
+ if (state.items.length === 0)
67
+ return state;
68
+ const focusIndex = Math.max(state.focusIndex - state.height, 0);
69
+ return { ...state, focusIndex, scrollY: adjustScroll(focusIndex, state.scrollY, state.height, state.items.length) };
70
+ }
71
+ // ---------------------------------------------------------------------------
72
+ // Scroll helper
73
+ // ---------------------------------------------------------------------------
74
+ function adjustScroll(focusIndex, scrollY, height, totalItems) {
75
+ let newScrollY = scrollY;
76
+ if (focusIndex < newScrollY) {
77
+ newScrollY = focusIndex;
78
+ }
79
+ else if (focusIndex >= newScrollY + height) {
80
+ newScrollY = focusIndex - height + 1;
81
+ }
82
+ const maxScroll = Math.max(0, totalItems - height);
83
+ return Math.min(newScrollY, maxScroll);
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // Render
87
+ // ---------------------------------------------------------------------------
88
+ /**
89
+ * Render the browsable list — visible items within the viewport with a
90
+ * focus indicator on the currently focused item.
91
+ *
92
+ * Items with a `description` field render as `label — description`.
93
+ */
94
+ export function browsableList(state, options) {
95
+ if (state.items.length === 0)
96
+ return '';
97
+ const indicator = options?.focusIndicator ?? '\u25b8';
98
+ const pad = ' '.repeat(indicator.length);
99
+ const visibleItems = state.items.slice(state.scrollY, state.scrollY + state.height);
100
+ const lines = [];
101
+ for (let i = 0; i < visibleItems.length; i++) {
102
+ const item = visibleItems[i];
103
+ const globalIndex = state.scrollY + i;
104
+ const prefix = globalIndex === state.focusIndex ? indicator : pad;
105
+ const desc = item.description ? ` \u2014 ${item.description}` : '';
106
+ lines.push(`${prefix} ${item.label}${desc}`);
107
+ }
108
+ return lines.join('\n');
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Convenience keymap
112
+ // ---------------------------------------------------------------------------
113
+ /**
114
+ * Create a preconfigured KeyMap for browsable list navigation.
115
+ *
116
+ * The caller provides their own message types for each action:
117
+ * ```ts
118
+ * const keys = browsableListKeyMap({
119
+ * focusNext: { type: 'next' },
120
+ * focusPrev: { type: 'prev' },
121
+ * pageDown: { type: 'page-down' },
122
+ * pageUp: { type: 'page-up' },
123
+ * select: { type: 'select' },
124
+ * quit: { type: 'quit' },
125
+ * });
126
+ * ```
127
+ */
128
+ export function browsableListKeyMap(actions) {
129
+ return createKeyMap()
130
+ .group('Navigation', (g) => g
131
+ .bind('j', 'Next item', actions.focusNext)
132
+ .bind('down', 'Next item', actions.focusNext)
133
+ .bind('k', 'Previous item', actions.focusPrev)
134
+ .bind('up', 'Previous item', actions.focusPrev)
135
+ .bind('d', 'Page down', actions.pageDown)
136
+ .bind('pagedown', 'Page down', actions.pageDown)
137
+ .bind('u', 'Page up', actions.pageUp)
138
+ .bind('pageup', 'Page up', actions.pageUp))
139
+ .bind('enter', 'Select', actions.select)
140
+ .bind('q', 'Quit', actions.quit)
141
+ .bind('ctrl+c', 'Quit', actions.quit);
142
+ }
143
+ //# sourceMappingURL=browsable-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browsable-list.js","sourceRoot":"","sources":["../src/browsable-list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * File picker building block — a directory browser with focus navigation.
3
+ *
4
+ * Uses `IOPort.readDir()` to list directory contents and `IOPort.joinPath()`
5
+ * to navigate between directories. Follows the same state + pure transformers
6
+ * + sync render + convenience keymap pattern as pager and accordion.
7
+ *
8
+ * ```ts
9
+ * // In TEA init:
10
+ * const fpState = createFilePickerState({ cwd: '/project', io });
11
+ *
12
+ * // In TEA view:
13
+ * const output = filePicker(model.fpState);
14
+ *
15
+ * // In TEA update:
16
+ * case 'focus-next':
17
+ * return [{ ...model, fpState: fpFocusNext(model.fpState) }, []];
18
+ * case 'enter':
19
+ * return [{ ...model, fpState: fpEnter(model.fpState, io) }, []];
20
+ * ```
21
+ */
22
+ import type { IOPort } from '@flyingrobots/bijou';
23
+ import { type KeyMap } from './keybindings.js';
24
+ export interface FileEntry {
25
+ name: string;
26
+ isDirectory: boolean;
27
+ }
28
+ export interface FilePickerState {
29
+ readonly cwd: string;
30
+ readonly entries: readonly FileEntry[];
31
+ readonly focusIndex: number;
32
+ readonly scrollY: number;
33
+ readonly height: number;
34
+ readonly filter?: string;
35
+ }
36
+ export interface FilePickerOptions {
37
+ readonly cwd: string;
38
+ readonly io: IOPort;
39
+ readonly height?: number;
40
+ readonly filter?: string;
41
+ }
42
+ export interface FilePickerRenderOptions {
43
+ readonly focusIndicator?: string;
44
+ readonly dirIndicator?: string;
45
+ readonly fileIndicator?: string;
46
+ }
47
+ /**
48
+ * Create initial file picker state for the given directory.
49
+ *
50
+ * Reads directory contents via `io.readDir()` and parses entries into
51
+ * directories (trailing `/`) and files. Directories are sorted first,
52
+ * then files, both alphabetically.
53
+ */
54
+ export declare function createFilePickerState(options: FilePickerOptions): FilePickerState;
55
+ /** Move focus to the next entry (wraps around). */
56
+ export declare function fpFocusNext(state: FilePickerState): FilePickerState;
57
+ /** Move focus to the previous entry (wraps around). */
58
+ export declare function fpFocusPrev(state: FilePickerState): FilePickerState;
59
+ /** Enter the focused directory, refreshing the entry list. No-op on files. */
60
+ export declare function fpEnter(state: FilePickerState, io: IOPort): FilePickerState;
61
+ /** Navigate to the parent directory. No-op at filesystem root. */
62
+ export declare function fpBack(state: FilePickerState, io: IOPort): FilePickerState;
63
+ /**
64
+ * Render the file picker — cwd header followed by the visible entry list.
65
+ *
66
+ * Each entry is prefixed with a focus indicator and a type indicator
67
+ * (directory or file). Directories are suffixed with `/`.
68
+ */
69
+ export declare function filePicker(state: FilePickerState, options?: FilePickerRenderOptions): string;
70
+ /**
71
+ * Create a preconfigured KeyMap for file picker navigation.
72
+ *
73
+ * The caller provides their own message types for each action:
74
+ * ```ts
75
+ * const keys = filePickerKeyMap({
76
+ * focusNext: { type: 'next' },
77
+ * focusPrev: { type: 'prev' },
78
+ * enter: { type: 'enter' },
79
+ * back: { type: 'back' },
80
+ * quit: { type: 'quit' },
81
+ * });
82
+ * ```
83
+ */
84
+ export declare function filePickerKeyMap<Msg>(actions: {
85
+ focusNext: Msg;
86
+ focusPrev: Msg;
87
+ enter: Msg;
88
+ back: Msg;
89
+ quit: Msg;
90
+ }): KeyMap<Msg>;
91
+ //# sourceMappingURL=file-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-picker.d.ts","sourceRoot":"","sources":["../src/file-picker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAkDD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,GAAG,eAAe,CAYjF;AAMD,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,CAInE;AAED,uDAAuD;AACvD,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,CAInE;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,eAAe,CAe3E;AAED,kEAAkE;AAClE,wBAAgB,MAAM,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,eAAe,CAa1E;AAqBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CA0B5F;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE;IAC7C,SAAS,EAAE,GAAG,CAAC;IACf,SAAS,EAAE,GAAG,CAAC;IACf,KAAK,EAAE,GAAG,CAAC;IACX,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,GAAG,CAAC;CACX,GAAG,MAAM,CAAC,GAAG,CAAC,CAed"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * File picker building block — a directory browser with focus navigation.
3
+ *
4
+ * Uses `IOPort.readDir()` to list directory contents and `IOPort.joinPath()`
5
+ * to navigate between directories. Follows the same state + pure transformers
6
+ * + sync render + convenience keymap pattern as pager and accordion.
7
+ *
8
+ * ```ts
9
+ * // In TEA init:
10
+ * const fpState = createFilePickerState({ cwd: '/project', io });
11
+ *
12
+ * // In TEA view:
13
+ * const output = filePicker(model.fpState);
14
+ *
15
+ * // In TEA update:
16
+ * case 'focus-next':
17
+ * return [{ ...model, fpState: fpFocusNext(model.fpState) }, []];
18
+ * case 'enter':
19
+ * return [{ ...model, fpState: fpEnter(model.fpState, io) }, []];
20
+ * ```
21
+ */
22
+ import { createKeyMap } from './keybindings.js';
23
+ // ---------------------------------------------------------------------------
24
+ // Helpers
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Safely read and parse directory entries. Returns `[]` if the directory
28
+ * is unreadable (permissions, missing, etc.) instead of throwing.
29
+ */
30
+ function safeReadEntries(io, cwd, filter) {
31
+ try {
32
+ return parseEntries(io.readDir(cwd), filter);
33
+ }
34
+ catch {
35
+ return [];
36
+ }
37
+ }
38
+ /**
39
+ * Parse raw directory listing into sorted `FileEntry[]`.
40
+ *
41
+ * @param names - Names returned by `IOPort.readDir()` (dirs have trailing `/`).
42
+ * @param filter - Optional extension suffix (e.g. `".ts"`) — only files whose
43
+ * name ends with this suffix are included. Directories are
44
+ * always included regardless of the filter.
45
+ */
46
+ function parseEntries(names, filter) {
47
+ const dirs = [];
48
+ const files = [];
49
+ for (const name of names) {
50
+ if (name.endsWith('/')) {
51
+ dirs.push({ name: name.slice(0, -1), isDirectory: true });
52
+ }
53
+ else {
54
+ if (filter && !name.endsWith(filter))
55
+ continue;
56
+ files.push({ name, isDirectory: false });
57
+ }
58
+ }
59
+ // Sort dirs first, then files, both alphabetically
60
+ dirs.sort((a, b) => a.name.localeCompare(b.name));
61
+ files.sort((a, b) => a.name.localeCompare(b.name));
62
+ return [...dirs, ...files];
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // State creation
66
+ // ---------------------------------------------------------------------------
67
+ /**
68
+ * Create initial file picker state for the given directory.
69
+ *
70
+ * Reads directory contents via `io.readDir()` and parses entries into
71
+ * directories (trailing `/`) and files. Directories are sorted first,
72
+ * then files, both alphabetically.
73
+ */
74
+ export function createFilePickerState(options) {
75
+ const height = Math.max(1, options.height ?? 10);
76
+ const entries = safeReadEntries(options.io, options.cwd, options.filter);
77
+ return {
78
+ cwd: options.cwd,
79
+ entries,
80
+ focusIndex: 0,
81
+ scrollY: 0,
82
+ height,
83
+ filter: options.filter,
84
+ };
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // State transformers
88
+ // ---------------------------------------------------------------------------
89
+ /** Move focus to the next entry (wraps around). */
90
+ export function fpFocusNext(state) {
91
+ if (state.entries.length === 0)
92
+ return state;
93
+ const focusIndex = (state.focusIndex + 1) % state.entries.length;
94
+ return { ...state, focusIndex, scrollY: adjustScroll(focusIndex, state.scrollY, state.height, state.entries.length) };
95
+ }
96
+ /** Move focus to the previous entry (wraps around). */
97
+ export function fpFocusPrev(state) {
98
+ if (state.entries.length === 0)
99
+ return state;
100
+ const focusIndex = (state.focusIndex - 1 + state.entries.length) % state.entries.length;
101
+ return { ...state, focusIndex, scrollY: adjustScroll(focusIndex, state.scrollY, state.height, state.entries.length) };
102
+ }
103
+ /** Enter the focused directory, refreshing the entry list. No-op on files. */
104
+ export function fpEnter(state, io) {
105
+ if (state.entries.length === 0)
106
+ return state;
107
+ const entry = state.entries[state.focusIndex];
108
+ if (!entry || !entry.isDirectory)
109
+ return state;
110
+ const newCwd = io.joinPath(state.cwd, entry.name);
111
+ const entries = safeReadEntries(io, newCwd, state.filter);
112
+ return {
113
+ ...state,
114
+ cwd: newCwd,
115
+ entries,
116
+ focusIndex: 0,
117
+ scrollY: 0,
118
+ };
119
+ }
120
+ /** Navigate to the parent directory. No-op at filesystem root. */
121
+ export function fpBack(state, io) {
122
+ const newCwd = io.joinPath(state.cwd, '..');
123
+ if (newCwd === state.cwd)
124
+ return state;
125
+ const entries = safeReadEntries(io, newCwd, state.filter);
126
+ return {
127
+ ...state,
128
+ cwd: newCwd,
129
+ entries,
130
+ focusIndex: 0,
131
+ scrollY: 0,
132
+ };
133
+ }
134
+ // ---------------------------------------------------------------------------
135
+ // Scroll helper
136
+ // ---------------------------------------------------------------------------
137
+ function adjustScroll(focusIndex, scrollY, height, totalItems) {
138
+ let newScrollY = scrollY;
139
+ if (focusIndex < newScrollY) {
140
+ newScrollY = focusIndex;
141
+ }
142
+ else if (focusIndex >= newScrollY + height) {
143
+ newScrollY = focusIndex - height + 1;
144
+ }
145
+ const maxScroll = Math.max(0, totalItems - height);
146
+ return Math.min(newScrollY, maxScroll);
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // Render
150
+ // ---------------------------------------------------------------------------
151
+ /**
152
+ * Render the file picker — cwd header followed by the visible entry list.
153
+ *
154
+ * Each entry is prefixed with a focus indicator and a type indicator
155
+ * (directory or file). Directories are suffixed with `/`.
156
+ */
157
+ export function filePicker(state, options) {
158
+ const indicator = options?.focusIndicator ?? '\u25b8';
159
+ const dirIcon = options?.dirIndicator ?? 'd';
160
+ const fileIcon = options?.fileIndicator ?? '-';
161
+ const pad = ' '.repeat(indicator.length);
162
+ const lines = [];
163
+ lines.push(state.cwd);
164
+ if (state.entries.length === 0) {
165
+ lines.push(' (empty)');
166
+ return lines.join('\n');
167
+ }
168
+ const visibleEntries = state.entries.slice(state.scrollY, state.scrollY + state.height);
169
+ for (let i = 0; i < visibleEntries.length; i++) {
170
+ const entry = visibleEntries[i];
171
+ const globalIndex = state.scrollY + i;
172
+ const prefix = globalIndex === state.focusIndex ? indicator : pad;
173
+ const icon = entry.isDirectory ? dirIcon : fileIcon;
174
+ const suffix = entry.isDirectory ? '/' : '';
175
+ lines.push(`${prefix} ${icon} ${entry.name}${suffix}`);
176
+ }
177
+ return lines.join('\n');
178
+ }
179
+ // ---------------------------------------------------------------------------
180
+ // Convenience keymap
181
+ // ---------------------------------------------------------------------------
182
+ /**
183
+ * Create a preconfigured KeyMap for file picker navigation.
184
+ *
185
+ * The caller provides their own message types for each action:
186
+ * ```ts
187
+ * const keys = filePickerKeyMap({
188
+ * focusNext: { type: 'next' },
189
+ * focusPrev: { type: 'prev' },
190
+ * enter: { type: 'enter' },
191
+ * back: { type: 'back' },
192
+ * quit: { type: 'quit' },
193
+ * });
194
+ * ```
195
+ */
196
+ export function filePickerKeyMap(actions) {
197
+ return createKeyMap()
198
+ .group('Navigation', (g) => g
199
+ .bind('j', 'Next entry', actions.focusNext)
200
+ .bind('down', 'Next entry', actions.focusNext)
201
+ .bind('k', 'Previous entry', actions.focusPrev)
202
+ .bind('up', 'Previous entry', actions.focusPrev))
203
+ .group('Actions', (g) => g
204
+ .bind('enter', 'Enter directory / select file', actions.enter)
205
+ .bind('backspace', 'Parent directory', actions.back)
206
+ .bind('left', 'Parent directory', actions.back))
207
+ .bind('q', 'Quit', actions.quit)
208
+ .bind('ctrl+c', 'Quit', actions.quit);
209
+ }
210
+ //# sourceMappingURL=file-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-picker.js","sourceRoot":"","sources":["../src/file-picker.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -18,4 +18,7 @@ export { type PagerState, type PagerOptions, type PagerRenderOptions, createPage
18
18
  export { type PanelDef, type PanelGroupOptions, type PanelGroup, createPanelGroup, } from './panels.js';
19
19
  export { type Overlay, type CompositeOptions, type ModalOptions, type ToastVariant, type ToastAnchor, type ToastOptions, composite, modal, toast, } from './overlay.js';
20
20
  export { type AccordionState, type InteractiveAccordionOptions, createAccordionState, interactiveAccordion, focusNext, focusPrev, toggleFocused, expandAll, collapseAll, accordionKeyMap, } from './accordion.js';
21
+ export { type NavigableTableState, type NavigableTableOptions, type NavTableRenderOptions, createNavigableTableState, navigableTable, navTableFocusNext, navTableFocusPrev, navTablePageDown, navTablePageUp, navTableKeyMap, } from './navigable-table.js';
22
+ export { type BrowsableListItem, type BrowsableListState, type BrowsableListOptions, type BrowsableListRenderOptions, createBrowsableListState, browsableList, listFocusNext, listFocusPrev, listPageDown, listPageUp, browsableListKeyMap, } from './browsable-list.js';
23
+ export { type FileEntry, type FilePickerState, type FilePickerOptions, type FilePickerRenderOptions, createFilePickerState, filePicker, fpFocusNext, fpFocusPrev, fpEnter, fpBack, filePickerKeyMap, } from './file-picker.js';
21
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrC,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,MAAM,aAAa,CAAC;AAG7C,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,SAAS,EACT,KAAK,EACL,KAAK,GACN,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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -34,4 +34,10 @@ export { createPanelGroup, } from './panels.js';
34
34
  export { composite, modal, toast, } from './overlay.js';
35
35
  // Interactive accordion
36
36
  export { createAccordionState, interactiveAccordion, focusNext, focusPrev, toggleFocused, expandAll, collapseAll, accordionKeyMap, } from './accordion.js';
37
+ // Navigable table
38
+ export { createNavigableTableState, navigableTable, navTableFocusNext, navTableFocusPrev, navTablePageDown, navTablePageUp, navTableKeyMap, } from './navigable-table.js';
39
+ // Browsable list
40
+ export { createBrowsableListState, browsableList, listFocusNext, listFocusPrev, listPageDown, listPageUp, browsableListKeyMap, } from './browsable-list.js';
41
+ // File picker
42
+ export { createFilePickerState, filePicker, fpFocusNext, fpFocusPrev, fpEnter, fpBack, filePickerKeyMap, } from './file-picker.js';
37
43
  //# 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":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,cAAc;AACd,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,iBAAiB;AACjB,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;AAErB,WAAW;AACX,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAElD,UAAU;AACV,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,YAAY;AACZ,OAAO,EAGL,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,SAAS;AACT,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE7C,sCAAsC;AACtC,OAAO,EAIL,cAAc,EACd,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EAEnB,OAAO,EAGP,SAAS,EACT,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAIL,OAAO,EACP,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,qCAAqC;AACrC,OAAO,EAGL,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;AAEvB,gDAAgD;AAChD,OAAO,EAQL,QAAQ,GACT,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EAGL,IAAI,GACL,MAAM,WAAW,CAAC;AAEnB,qBAAqB;AACrB,OAAO,EAKL,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,kBAAkB;AAClB,OAAO,EAGL,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,WAAW,CAAC;AAEnB,cAAc;AACd,OAAO,EAKL,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,iCAAiC;AACjC,OAAO,EAIL,gBAAgB,EAChB,KAAK,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,eAAe,EACf,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,4CAA4C;AAC5C,OAAO,EAIL,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,sBAAsB;AACtB,OAAO,EAOL,SAAS,EACT,KAAK,EACL,KAAK,GACN,MAAM,cAAc,CAAC;AAEtB,wBAAwB;AACxB,OAAO,EAGL,oBAAoB,EACpB,oBAAoB,EACpB,SAAS,EACT,SAAS,EACT,aAAa,EACb,SAAS,EACT,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,cAAc;AACd,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,iBAAiB;AACjB,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;AAErB,WAAW;AACX,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAElD,UAAU;AACV,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,YAAY;AACZ,OAAO,EAGL,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,SAAS;AACT,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE7C,sCAAsC;AACtC,OAAO,EAIL,cAAc,EACd,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EAEnB,OAAO,EAGP,SAAS,EACT,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAIL,OAAO,EACP,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,qCAAqC;AACrC,OAAO,EAGL,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;AAEvB,gDAAgD;AAChD,OAAO,EAQL,QAAQ,GACT,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EAGL,IAAI,GACL,MAAM,WAAW,CAAC;AAEnB,qBAAqB;AACrB,OAAO,EAKL,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,kBAAkB;AAClB,OAAO,EAGL,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,WAAW,CAAC;AAEnB,cAAc;AACd,OAAO,EAKL,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,iCAAiC;AACjC,OAAO,EAIL,gBAAgB,EAChB,KAAK,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,eAAe,EACf,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,4CAA4C;AAC5C,OAAO,EAIL,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,sBAAsB;AACtB,OAAO,EAOL,SAAS,EACT,KAAK,EACL,KAAK,GACN,MAAM,cAAc,CAAC;AAEtB,wBAAwB;AACxB,OAAO,EAGL,oBAAoB,EACpB,oBAAoB,EACpB,SAAS,EACT,SAAS,EACT,aAAa,EACb,SAAS,EACT,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,kBAAkB;AAClB,OAAO,EAIL,yBAAyB,EACzB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,cAAc,GACf,MAAM,sBAAsB,CAAC;AAE9B,iBAAiB;AACjB,OAAO,EAKL,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,UAAU,EACV,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,cAAc;AACd,OAAO,EAKL,qBAAqB,EACrB,UAAU,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,MAAM,EACN,gBAAgB,GACjB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Navigable table building block.
3
+ *
4
+ * Wraps the static `table()` from bijou core with focus management,
5
+ * keyboard navigation, and vertical scrolling.
6
+ *
7
+ * ```ts
8
+ * // In TEA init:
9
+ * const tableState = createNavigableTableState({ columns, rows, height: 10 });
10
+ *
11
+ * // In TEA view:
12
+ * const output = navigableTable(model.tableState, { ctx });
13
+ *
14
+ * // In TEA update:
15
+ * case 'focus-next':
16
+ * return [{ ...model, tableState: navTableFocusNext(model.tableState) }, []];
17
+ * ```
18
+ */
19
+ import { type TableColumn, type BijouContext } from '@flyingrobots/bijou';
20
+ import { type KeyMap } from './keybindings.js';
21
+ export interface NavigableTableState {
22
+ readonly columns: TableColumn[];
23
+ readonly rows: readonly (readonly string[])[];
24
+ readonly focusRow: number;
25
+ readonly scrollY: number;
26
+ readonly height: number;
27
+ }
28
+ export interface NavigableTableOptions {
29
+ readonly columns: TableColumn[];
30
+ readonly rows: readonly (readonly string[])[];
31
+ readonly height?: number;
32
+ }
33
+ export interface NavTableRenderOptions {
34
+ readonly focusIndicator?: string;
35
+ readonly ctx?: BijouContext;
36
+ }
37
+ /**
38
+ * Create initial navigable table state.
39
+ *
40
+ * `height` defaults to 10 rows when not provided.
41
+ */
42
+ export declare function createNavigableTableState(options: NavigableTableOptions): NavigableTableState;
43
+ /** Move focus to the next row (wraps around). */
44
+ export declare function navTableFocusNext(state: NavigableTableState): NavigableTableState;
45
+ /** Move focus to the previous row (wraps around). */
46
+ export declare function navTableFocusPrev(state: NavigableTableState): NavigableTableState;
47
+ /** Move focus down by one page (clamps to last row). */
48
+ export declare function navTablePageDown(state: NavigableTableState): NavigableTableState;
49
+ /** Move focus up by one page (clamps to first row). */
50
+ export declare function navTablePageUp(state: NavigableTableState): NavigableTableState;
51
+ /**
52
+ * Render the navigable table with a focus indicator on the focused row.
53
+ *
54
+ * Slices visible rows based on `scrollY` and `height`, prepends a focus
55
+ * indicator to the first column, then delegates to core `table()`.
56
+ */
57
+ export declare function navigableTable(state: NavigableTableState, options?: NavTableRenderOptions): string;
58
+ /**
59
+ * Create a preconfigured KeyMap for navigable table navigation.
60
+ *
61
+ * The caller provides their own message types for each action:
62
+ * ```ts
63
+ * const keys = navTableKeyMap({
64
+ * focusNext: { type: 'next-row' },
65
+ * focusPrev: { type: 'prev-row' },
66
+ * pageDown: { type: 'page-down' },
67
+ * pageUp: { type: 'page-up' },
68
+ * quit: { type: 'quit' },
69
+ * });
70
+ * ```
71
+ */
72
+ export declare function navTableKeyMap<Msg>(actions: {
73
+ focusNext: Msg;
74
+ focusPrev: Msg;
75
+ pageDown: Msg;
76
+ pageUp: Msg;
77
+ quit: Msg;
78
+ }): KeyMap<Msg>;
79
+ //# sourceMappingURL=navigable-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigable-table.d.ts","sourceRoot":"","sources":["../src/navigable-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC;CAC7B;AAMD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,qBAAqB,GAAG,mBAAmB,CAS7F;AAMD,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,GAAG,mBAAmB,CAIjF;AAED,qDAAqD;AACrD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,GAAG,mBAAmB,CAIjF;AAED,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,GAAG,mBAAmB,CAIhF;AAED,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,mBAAmB,CAI9E;AAqBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAwBlG;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE;IAC3C,SAAS,EAAE,GAAG,CAAC;IACf,SAAS,EAAE,GAAG,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;CACX,GAAG,MAAM,CAAC,GAAG,CAAC,CAcd"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Navigable table building block.
3
+ *
4
+ * Wraps the static `table()` from bijou core with focus management,
5
+ * keyboard navigation, and vertical scrolling.
6
+ *
7
+ * ```ts
8
+ * // In TEA init:
9
+ * const tableState = createNavigableTableState({ columns, rows, height: 10 });
10
+ *
11
+ * // In TEA view:
12
+ * const output = navigableTable(model.tableState, { ctx });
13
+ *
14
+ * // In TEA update:
15
+ * case 'focus-next':
16
+ * return [{ ...model, tableState: navTableFocusNext(model.tableState) }, []];
17
+ * ```
18
+ */
19
+ import { table, } from '@flyingrobots/bijou';
20
+ import { createKeyMap } from './keybindings.js';
21
+ // ---------------------------------------------------------------------------
22
+ // State creation
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Create initial navigable table state.
26
+ *
27
+ * `height` defaults to 10 rows when not provided.
28
+ */
29
+ export function createNavigableTableState(options) {
30
+ const height = Math.max(1, options.height ?? 10);
31
+ return {
32
+ columns: [...options.columns],
33
+ rows: options.rows.map((row) => [...row]),
34
+ focusRow: 0,
35
+ scrollY: 0,
36
+ height,
37
+ };
38
+ }
39
+ // ---------------------------------------------------------------------------
40
+ // State transformers
41
+ // ---------------------------------------------------------------------------
42
+ /** Move focus to the next row (wraps around). */
43
+ export function navTableFocusNext(state) {
44
+ if (state.rows.length === 0)
45
+ return state;
46
+ const focusRow = (state.focusRow + 1) % state.rows.length;
47
+ return { ...state, focusRow, scrollY: adjustScroll(focusRow, state.scrollY, state.height, state.rows.length) };
48
+ }
49
+ /** Move focus to the previous row (wraps around). */
50
+ export function navTableFocusPrev(state) {
51
+ if (state.rows.length === 0)
52
+ return state;
53
+ const focusRow = (state.focusRow - 1 + state.rows.length) % state.rows.length;
54
+ return { ...state, focusRow, scrollY: adjustScroll(focusRow, state.scrollY, state.height, state.rows.length) };
55
+ }
56
+ /** Move focus down by one page (clamps to last row). */
57
+ export function navTablePageDown(state) {
58
+ if (state.rows.length === 0)
59
+ return state;
60
+ const focusRow = Math.min(state.focusRow + state.height, state.rows.length - 1);
61
+ return { ...state, focusRow, scrollY: adjustScroll(focusRow, state.scrollY, state.height, state.rows.length) };
62
+ }
63
+ /** Move focus up by one page (clamps to first row). */
64
+ export function navTablePageUp(state) {
65
+ if (state.rows.length === 0)
66
+ return state;
67
+ const focusRow = Math.max(state.focusRow - state.height, 0);
68
+ return { ...state, focusRow, scrollY: adjustScroll(focusRow, state.scrollY, state.height, state.rows.length) };
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Scroll helper
72
+ // ---------------------------------------------------------------------------
73
+ function adjustScroll(focusRow, scrollY, height, totalRows) {
74
+ let newScrollY = scrollY;
75
+ if (focusRow < newScrollY) {
76
+ newScrollY = focusRow;
77
+ }
78
+ else if (focusRow >= newScrollY + height) {
79
+ newScrollY = focusRow - height + 1;
80
+ }
81
+ const maxScroll = Math.max(0, totalRows - height);
82
+ return Math.min(newScrollY, maxScroll);
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Render
86
+ // ---------------------------------------------------------------------------
87
+ /**
88
+ * Render the navigable table with a focus indicator on the focused row.
89
+ *
90
+ * Slices visible rows based on `scrollY` and `height`, prepends a focus
91
+ * indicator to the first column, then delegates to core `table()`.
92
+ */
93
+ export function navigableTable(state, options) {
94
+ if (state.rows.length === 0) {
95
+ return table({ columns: state.columns, rows: [], ctx: options?.ctx });
96
+ }
97
+ const indicator = options?.focusIndicator ?? '\u25b8';
98
+ const pad = ' '.repeat(indicator.length);
99
+ // Slice visible window
100
+ const visibleRows = state.rows.slice(state.scrollY, state.scrollY + state.height);
101
+ // Prepend focus indicator to first column
102
+ const decoratedRows = visibleRows.map((row, i) => {
103
+ const globalIndex = state.scrollY + i;
104
+ const prefix = globalIndex === state.focusRow ? indicator : pad;
105
+ const firstCol = `${prefix} ${row[0] ?? ''}`;
106
+ return [firstCol, ...row.slice(1)];
107
+ });
108
+ return table({
109
+ columns: state.columns,
110
+ rows: decoratedRows,
111
+ ctx: options?.ctx,
112
+ });
113
+ }
114
+ // ---------------------------------------------------------------------------
115
+ // Convenience keymap
116
+ // ---------------------------------------------------------------------------
117
+ /**
118
+ * Create a preconfigured KeyMap for navigable table navigation.
119
+ *
120
+ * The caller provides their own message types for each action:
121
+ * ```ts
122
+ * const keys = navTableKeyMap({
123
+ * focusNext: { type: 'next-row' },
124
+ * focusPrev: { type: 'prev-row' },
125
+ * pageDown: { type: 'page-down' },
126
+ * pageUp: { type: 'page-up' },
127
+ * quit: { type: 'quit' },
128
+ * });
129
+ * ```
130
+ */
131
+ export function navTableKeyMap(actions) {
132
+ return createKeyMap()
133
+ .group('Navigation', (g) => g
134
+ .bind('j', 'Next row', actions.focusNext)
135
+ .bind('down', 'Next row', actions.focusNext)
136
+ .bind('k', 'Previous row', actions.focusPrev)
137
+ .bind('up', 'Previous row', actions.focusPrev)
138
+ .bind('d', 'Page down', actions.pageDown)
139
+ .bind('pagedown', 'Page down', actions.pageDown)
140
+ .bind('u', 'Page up', actions.pageUp)
141
+ .bind('pageup', 'Page up', actions.pageUp))
142
+ .bind('q', 'Quit', actions.quit)
143
+ .bind('ctrl+c', 'Quit', actions.quit);
144
+ }
145
+ //# sourceMappingURL=navigable-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigable-table.js","sourceRoot":"","sources":["../src/navigable-table.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": "0.5.1",
3
+ "version": "0.6.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": "0.5.1"
27
+ "@flyingrobots/bijou": "0.6.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^22.0.0",