@flyingrobots/bijou-tui 0.2.0 → 0.4.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 +39 -12
- package/dist/accordion.d.ts +69 -0
- package/dist/accordion.d.ts.map +1 -0
- package/dist/accordion.js +126 -0
- package/dist/accordion.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/overlay.d.ts +44 -0
- package/dist/overlay.d.ts.map +1 -0
- package/dist/overlay.js +160 -0
- package/dist/overlay.js.map +1 -0
- package/dist/pager.d.ts +88 -0
- package/dist/pager.d.ts.map +1 -0
- package/dist/pager.js +143 -0
- package/dist/pager.js.map +1 -0
- package/dist/panels.d.ts +31 -0
- package/dist/panels.d.ts.map +1 -0
- package/dist/panels.js +110 -0
- package/dist/panels.js.map +1 -0
- package/dist/viewport.d.ts +28 -1
- package/dist/viewport.d.ts.map +1 -1
- package/dist/viewport.js +97 -11
- package/dist/viewport.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,20 +4,16 @@ 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.
|
|
7
|
+
## What's New in 0.4.0?
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- **`
|
|
12
|
-
- **`
|
|
13
|
-
- **`
|
|
14
|
-
- **`
|
|
15
|
-
- **`EventBus`** — centralized typed event emitter unifying keyboard, resize, and multi-message commands.
|
|
16
|
-
- **Keybinding manager** — `createKeyMap()` for declarative key binding with modifiers, named groups, runtime enable/disable.
|
|
17
|
-
- **Help generator** — `helpView()`, `helpShort()`, `helpFor()` auto-generated from registered keybindings.
|
|
18
|
-
- **Input stack** — `createInputStack()` for layered input dispatch with opaque (modal) and passthrough layers.
|
|
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
|
|
19
15
|
|
|
20
|
-
See the [CHANGELOG](https://github.com/flyingrobots/bijou/blob/main/CHANGELOG.md) for the full release history.
|
|
16
|
+
See the [CHANGELOG](https://github.com/flyingrobots/bijou/blob/main/docs/CHANGELOG.md) for the full release history.
|
|
21
17
|
|
|
22
18
|
## Install
|
|
23
19
|
|
|
@@ -259,6 +255,37 @@ stack.remove(modalId);
|
|
|
259
255
|
|
|
260
256
|
`KeyMap` implements `InputHandler`, so it plugs directly into the input stack.
|
|
261
257
|
|
|
258
|
+
## Overlay Compositing
|
|
259
|
+
|
|
260
|
+
Paint overlays (modals, toasts) on top of existing content:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { composite, modal, toast } from '@flyingrobots/bijou-tui';
|
|
264
|
+
|
|
265
|
+
// Create a centered dialog
|
|
266
|
+
const dialog = modal({
|
|
267
|
+
title: 'Confirm',
|
|
268
|
+
body: 'Delete this item?',
|
|
269
|
+
hint: 'y/n',
|
|
270
|
+
screenWidth: 80,
|
|
271
|
+
screenHeight: 24,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Create a toast notification
|
|
275
|
+
const notification = toast({
|
|
276
|
+
message: 'Saved successfully',
|
|
277
|
+
variant: 'success', // 'success' | 'error' | 'info'
|
|
278
|
+
anchor: 'bottom-right', // 'top-right' | 'bottom-right' | 'bottom-left' | 'top-left'
|
|
279
|
+
screenWidth: 80,
|
|
280
|
+
screenHeight: 24,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Paint overlays onto background content
|
|
284
|
+
const output = composite(backgroundView, [dialog, notification], { dim: true });
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
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
|
+
|
|
262
289
|
## Related Packages
|
|
263
290
|
|
|
264
291
|
- [`@flyingrobots/bijou`](https://www.npmjs.com/package/@flyingrobots/bijou) — Zero-dependency core with all components and theme engine
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive accordion building block.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the static `accordion()` from bijou core with focus management
|
|
5
|
+
* and expand/collapse state transformers.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* // In TEA init:
|
|
9
|
+
* const accState = createAccordionState(sections);
|
|
10
|
+
*
|
|
11
|
+
* // In TEA view:
|
|
12
|
+
* const output = interactiveAccordion(model.accordion);
|
|
13
|
+
*
|
|
14
|
+
* // In TEA update:
|
|
15
|
+
* case 'focus-next':
|
|
16
|
+
* return [{ ...model, accordion: focusNext(model.accordion) }, []];
|
|
17
|
+
* case 'toggle':
|
|
18
|
+
* return [{ ...model, accordion: toggleFocused(model.accordion) }, []];
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { type AccordionSection, type AccordionOptions, type BijouContext } from '@flyingrobots/bijou';
|
|
22
|
+
import { type KeyMap } from './keybindings.js';
|
|
23
|
+
export type { AccordionSection } from '@flyingrobots/bijou';
|
|
24
|
+
export interface AccordionState {
|
|
25
|
+
readonly sections: readonly AccordionSection[];
|
|
26
|
+
readonly focusIndex: number;
|
|
27
|
+
}
|
|
28
|
+
export interface InteractiveAccordionOptions {
|
|
29
|
+
/** Token for the expand/collapse indicator. */
|
|
30
|
+
readonly indicatorToken?: AccordionOptions['indicatorToken'];
|
|
31
|
+
/** Token for section titles. */
|
|
32
|
+
readonly titleToken?: AccordionOptions['titleToken'];
|
|
33
|
+
/** Character for the focus indicator. Default: '>' */
|
|
34
|
+
readonly focusChar?: string;
|
|
35
|
+
readonly ctx?: BijouContext;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create initial accordion state from sections.
|
|
39
|
+
* Preserves existing `expanded` flags; focus starts at index 0.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createAccordionState(sections: AccordionSection[]): AccordionState;
|
|
42
|
+
/** Move focus to the next section (wraps around). */
|
|
43
|
+
export declare function focusNext(state: AccordionState): AccordionState;
|
|
44
|
+
/** Move focus to the previous section (wraps around). */
|
|
45
|
+
export declare function focusPrev(state: AccordionState): AccordionState;
|
|
46
|
+
/** Toggle the expanded state of the focused section. */
|
|
47
|
+
export declare function toggleFocused(state: AccordionState): AccordionState;
|
|
48
|
+
/** Expand all sections. */
|
|
49
|
+
export declare function expandAll(state: AccordionState): AccordionState;
|
|
50
|
+
/** Collapse all sections. */
|
|
51
|
+
export declare function collapseAll(state: AccordionState): AccordionState;
|
|
52
|
+
/**
|
|
53
|
+
* Render the interactive accordion with a focus indicator on the
|
|
54
|
+
* currently focused section.
|
|
55
|
+
*
|
|
56
|
+
* Delegates to the static `accordion()` for the actual rendering,
|
|
57
|
+
* then prepends a focus indicator to the focused section's line.
|
|
58
|
+
*/
|
|
59
|
+
export declare function interactiveAccordion(state: AccordionState, options?: InteractiveAccordionOptions): string;
|
|
60
|
+
/**
|
|
61
|
+
* Create a preconfigured KeyMap for accordion navigation.
|
|
62
|
+
*/
|
|
63
|
+
export declare function accordionKeyMap<Msg>(actions: {
|
|
64
|
+
focusNext: Msg;
|
|
65
|
+
focusPrev: Msg;
|
|
66
|
+
toggle: Msg;
|
|
67
|
+
quit: Msg;
|
|
68
|
+
}): KeyMap<Msg>;
|
|
69
|
+
//# sourceMappingURL=accordion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../src/accordion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG7D,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAM5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,2BAA2B;IAC1C,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAC7D,gCAAgC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACrD,sDAAsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC;CAC7B;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,cAAc,CAKjF;AAMD,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAM/D;AAED,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAM/D;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAMnE;AAED,2BAA2B;AAC3B,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAE/D;AAED,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAEjE;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,cAAc,EACrB,OAAO,CAAC,EAAE,2BAA2B,GACpC,MAAM,CA4BR;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE;IAC5C,SAAS,EAAE,GAAG,CAAC;IACf,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;CACX,GAAG,MAAM,CAAC,GAAG,CAAC,CAcd"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive accordion building block.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the static `accordion()` from bijou core with focus management
|
|
5
|
+
* and expand/collapse state transformers.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* // In TEA init:
|
|
9
|
+
* const accState = createAccordionState(sections);
|
|
10
|
+
*
|
|
11
|
+
* // In TEA view:
|
|
12
|
+
* const output = interactiveAccordion(model.accordion);
|
|
13
|
+
*
|
|
14
|
+
* // In TEA update:
|
|
15
|
+
* case 'focus-next':
|
|
16
|
+
* return [{ ...model, accordion: focusNext(model.accordion) }, []];
|
|
17
|
+
* case 'toggle':
|
|
18
|
+
* return [{ ...model, accordion: toggleFocused(model.accordion) }, []];
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { accordion, } from '@flyingrobots/bijou';
|
|
22
|
+
import { createKeyMap } from './keybindings.js';
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// State creation
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Create initial accordion state from sections.
|
|
28
|
+
* Preserves existing `expanded` flags; focus starts at index 0.
|
|
29
|
+
*/
|
|
30
|
+
export function createAccordionState(sections) {
|
|
31
|
+
return {
|
|
32
|
+
sections: sections.map((s) => ({ ...s })),
|
|
33
|
+
focusIndex: 0,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// State transformers
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
/** Move focus to the next section (wraps around). */
|
|
40
|
+
export function focusNext(state) {
|
|
41
|
+
if (state.sections.length === 0)
|
|
42
|
+
return state;
|
|
43
|
+
return {
|
|
44
|
+
...state,
|
|
45
|
+
focusIndex: (state.focusIndex + 1) % state.sections.length,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Move focus to the previous section (wraps around). */
|
|
49
|
+
export function focusPrev(state) {
|
|
50
|
+
if (state.sections.length === 0)
|
|
51
|
+
return state;
|
|
52
|
+
return {
|
|
53
|
+
...state,
|
|
54
|
+
focusIndex: (state.focusIndex - 1 + state.sections.length) % state.sections.length,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** Toggle the expanded state of the focused section. */
|
|
58
|
+
export function toggleFocused(state) {
|
|
59
|
+
if (state.sections.length === 0)
|
|
60
|
+
return state;
|
|
61
|
+
const sections = state.sections.map((s, i) => i === state.focusIndex ? { ...s, expanded: !s.expanded } : s);
|
|
62
|
+
return { ...state, sections };
|
|
63
|
+
}
|
|
64
|
+
/** Expand all sections. */
|
|
65
|
+
export function expandAll(state) {
|
|
66
|
+
return { ...state, sections: state.sections.map((s) => ({ ...s, expanded: true })) };
|
|
67
|
+
}
|
|
68
|
+
/** Collapse all sections. */
|
|
69
|
+
export function collapseAll(state) {
|
|
70
|
+
return { ...state, sections: state.sections.map((s) => ({ ...s, expanded: false })) };
|
|
71
|
+
}
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Render
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
/**
|
|
76
|
+
* Render the interactive accordion with a focus indicator on the
|
|
77
|
+
* currently focused section.
|
|
78
|
+
*
|
|
79
|
+
* Delegates to the static `accordion()` for the actual rendering,
|
|
80
|
+
* then prepends a focus indicator to the focused section's line.
|
|
81
|
+
*/
|
|
82
|
+
export function interactiveAccordion(state, options) {
|
|
83
|
+
if (state.sections.length === 0)
|
|
84
|
+
return '';
|
|
85
|
+
const focusChar = options?.focusChar ?? '>';
|
|
86
|
+
// Normalize focusIndex to avoid stale/out-of-range values
|
|
87
|
+
const focusIndex = ((state.focusIndex % state.sections.length) + state.sections.length) % state.sections.length;
|
|
88
|
+
// Continuation-line padding must match the focus prefix width
|
|
89
|
+
const padWidth = focusChar.length + 1; // focusChar + space
|
|
90
|
+
const continuationPad = ' '.repeat(padWidth);
|
|
91
|
+
// Render each section individually so we can prepend the focus indicator
|
|
92
|
+
const renderedSections = state.sections.map((section, i) => {
|
|
93
|
+
const rendered = accordion([section], {
|
|
94
|
+
indicatorToken: options?.indicatorToken,
|
|
95
|
+
titleToken: options?.titleToken,
|
|
96
|
+
ctx: options?.ctx,
|
|
97
|
+
});
|
|
98
|
+
const prefix = i === focusIndex ? `${focusChar} ` : continuationPad;
|
|
99
|
+
// Prepend the focus indicator to each line of the rendered section
|
|
100
|
+
return rendered
|
|
101
|
+
.split('\n')
|
|
102
|
+
.map((line, lineIdx) => (lineIdx === 0 ? prefix + line : continuationPad + line))
|
|
103
|
+
.join('\n');
|
|
104
|
+
});
|
|
105
|
+
return renderedSections.join('\n\n');
|
|
106
|
+
}
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// Convenience keymap
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
/**
|
|
111
|
+
* Create a preconfigured KeyMap for accordion navigation.
|
|
112
|
+
*/
|
|
113
|
+
export function accordionKeyMap(actions) {
|
|
114
|
+
return createKeyMap()
|
|
115
|
+
.group('Navigation', (g) => g
|
|
116
|
+
.bind('j', 'Next section', actions.focusNext)
|
|
117
|
+
.bind('down', 'Next section', actions.focusNext)
|
|
118
|
+
.bind('k', 'Previous section', actions.focusPrev)
|
|
119
|
+
.bind('up', 'Previous section', actions.focusPrev))
|
|
120
|
+
.group('Actions', (g) => g
|
|
121
|
+
.bind('enter', 'Toggle section', actions.toggle)
|
|
122
|
+
.bind('space', 'Toggle section', actions.toggle))
|
|
123
|
+
.bind('q', 'Quit', actions.quit)
|
|
124
|
+
.bind('ctrl+c', 'Quit', actions.quit);
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=accordion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion.js","sourceRoot":"","sources":["../src/accordion.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,10 +8,14 @@ export { type BusMsg, type EventBus, createEventBus, } from './eventbus.js';
|
|
|
8
8
|
export { vstack, hstack } from './layout.js';
|
|
9
9
|
export { type SpringConfig, type SpringPreset, type SpringState, SPRING_PRESETS, springStep, createSpringState, resolveSpringConfig, type EasingFn, EASINGS, type TweenConfig, type TweenState, tweenStep, createTweenState, resolveTweenConfig, } from './spring.js';
|
|
10
10
|
export { type SpringAnimateOptions, type TweenAnimateOptions, type AnimateOptions, animate, sequence, } from './animate.js';
|
|
11
|
-
export { type ViewportOptions, type ScrollState, viewport, createScrollState, scrollBy, scrollTo, scrollToTop, scrollToBottom, pageDown, pageUp, } from './viewport.js';
|
|
11
|
+
export { type ViewportOptions, type ScrollState, viewport, createScrollState, scrollBy, scrollTo, scrollToTop, scrollToBottom, pageDown, pageUp, stripAnsi, visibleLength, clipToWidth, sliceAnsi, scrollByX, scrollToX, } from './viewport.js';
|
|
12
12
|
export { type Position, type SpringTrackDef, type TweenTrackDef, type TrackDef, type TimelineState, type TimelineBuilder, type Timeline, timeline, } from './timeline.js';
|
|
13
13
|
export { type FlexOptions, type FlexChild, flex, } from './flex.js';
|
|
14
14
|
export { type KeyCombo, type BindingInfo, type KeyMap, type KeyMapGroup, createKeyMap, parseKeyCombo, formatKeyCombo, } from './keybindings.js';
|
|
15
15
|
export { type BindingSource, type HelpOptions, helpView, helpShort, helpFor, } from './help.js';
|
|
16
16
|
export { type InputHandler, type LayerOptions, type LayerInfo, type InputStack, createInputStack, } from './inputstack.js';
|
|
17
|
+
export { type PagerState, type PagerOptions, type PagerRenderOptions, createPagerState, pager, pagerScrollBy, pagerScrollTo, pagerScrollToTop, pagerScrollToBottom, pagerPageDown, pagerPageUp, pagerSetContent, pagerKeyMap, } from './pager.js';
|
|
18
|
+
export { type PanelDef, type PanelGroupOptions, type PanelGroup, createPanelGroup, } from './panels.js';
|
|
19
|
+
export { type Overlay, type CompositeOptions, type ModalOptions, type ToastVariant, type ToastAnchor, type ToastOptions, composite, modal, toast, } from './overlay.js';
|
|
20
|
+
export { type AccordionState, type InteractiveAccordionOptions, createAccordionState, interactiveAccordion, focusNext, focusPrev, toggleFocused, expandAll, collapseAll, accordionKeyMap, } from './accordion.js';
|
|
17
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ export { vstack, hstack } from './layout.js';
|
|
|
15
15
|
export { SPRING_PRESETS, springStep, createSpringState, resolveSpringConfig, EASINGS, tweenStep, createTweenState, resolveTweenConfig, } from './spring.js';
|
|
16
16
|
export { animate, sequence, } from './animate.js';
|
|
17
17
|
// Viewport — scrollable content pane
|
|
18
|
-
export { viewport, createScrollState, scrollBy, scrollTo, scrollToTop, scrollToBottom, pageDown, pageUp, } from './viewport.js';
|
|
18
|
+
export { viewport, createScrollState, scrollBy, scrollTo, scrollToTop, scrollToBottom, pageDown, pageUp, stripAnsi, visibleLength, clipToWidth, sliceAnsi, scrollByX, scrollToX, } from './viewport.js';
|
|
19
19
|
// Timeline — GSAP-style animation orchestration
|
|
20
20
|
export { timeline, } from './timeline.js';
|
|
21
21
|
// Flexbox layout
|
|
@@ -26,4 +26,12 @@ export { createKeyMap, parseKeyCombo, formatKeyCombo, } from './keybindings.js';
|
|
|
26
26
|
export { helpView, helpShort, helpFor, } from './help.js';
|
|
27
27
|
// Input stack
|
|
28
28
|
export { createInputStack, } from './inputstack.js';
|
|
29
|
+
// Pager — scrollable text viewer
|
|
30
|
+
export { createPagerState, pager, pagerScrollBy, pagerScrollTo, pagerScrollToTop, pagerScrollToBottom, pagerPageDown, pagerPageUp, pagerSetContent, pagerKeyMap, } from './pager.js';
|
|
31
|
+
// Panel group — multi-pane focus management
|
|
32
|
+
export { createPanelGroup, } from './panels.js';
|
|
33
|
+
// Overlay compositing
|
|
34
|
+
export { composite, modal, toast, } from './overlay.js';
|
|
35
|
+
// Interactive accordion
|
|
36
|
+
export { createAccordionState, interactiveAccordion, focusNext, focusPrev, toggleFocused, expandAll, collapseAll, accordionKeyMap, } from './accordion.js';
|
|
29
37
|
//# 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,
|
|
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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overlay compositing primitives for TUI apps.
|
|
3
|
+
*
|
|
4
|
+
* - `composite()` — paint overlays onto a background string (ANSI-safe)
|
|
5
|
+
* - `modal()` — centered dialog overlay with title, body, hint
|
|
6
|
+
* - `toast()` — anchored notification overlay with variant icons
|
|
7
|
+
*/
|
|
8
|
+
import type { BijouContext, TokenValue } from '@flyingrobots/bijou';
|
|
9
|
+
export interface Overlay {
|
|
10
|
+
readonly content: string;
|
|
11
|
+
readonly row: number;
|
|
12
|
+
readonly col: number;
|
|
13
|
+
}
|
|
14
|
+
export interface CompositeOptions {
|
|
15
|
+
/** Wrap background lines in dim (ANSI 2m). */
|
|
16
|
+
readonly dim?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface ModalOptions {
|
|
19
|
+
readonly title?: string;
|
|
20
|
+
readonly body: string;
|
|
21
|
+
readonly hint?: string;
|
|
22
|
+
readonly screenWidth: number;
|
|
23
|
+
readonly screenHeight: number;
|
|
24
|
+
/** Override box width (default: auto from content). */
|
|
25
|
+
readonly width?: number;
|
|
26
|
+
readonly borderToken?: TokenValue;
|
|
27
|
+
readonly ctx?: BijouContext;
|
|
28
|
+
}
|
|
29
|
+
export type ToastVariant = 'success' | 'error' | 'info';
|
|
30
|
+
export type ToastAnchor = 'top-right' | 'bottom-right' | 'bottom-left' | 'top-left';
|
|
31
|
+
export interface ToastOptions {
|
|
32
|
+
readonly message: string;
|
|
33
|
+
readonly variant?: ToastVariant;
|
|
34
|
+
readonly anchor?: ToastAnchor;
|
|
35
|
+
readonly screenWidth: number;
|
|
36
|
+
readonly screenHeight: number;
|
|
37
|
+
/** Rows/cols from edge. Default: 1. */
|
|
38
|
+
readonly margin?: number;
|
|
39
|
+
readonly ctx?: BijouContext;
|
|
40
|
+
}
|
|
41
|
+
export declare function composite(background: string, overlays: readonly Overlay[], options?: CompositeOptions): string;
|
|
42
|
+
export declare function modal(options: ModalOptions): Overlay;
|
|
43
|
+
export declare function toast(options: ToastOptions): Overlay;
|
|
44
|
+
//# sourceMappingURL=overlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOpE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,cAAc,GAAG,aAAa,GAAG,UAAU,CAAC;AAEpF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC;CAC7B;AAoCD,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAqBR;AAwBD,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CA6CpD;AAkBD,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAsDpD"}
|
package/dist/overlay.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overlay compositing primitives for TUI apps.
|
|
3
|
+
*
|
|
4
|
+
* - `composite()` — paint overlays onto a background string (ANSI-safe)
|
|
5
|
+
* - `modal()` — centered dialog overlay with title, body, hint
|
|
6
|
+
* - `toast()` — anchored notification overlay with variant icons
|
|
7
|
+
*/
|
|
8
|
+
import { sliceAnsi, visibleLength } from './viewport.js';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Border characters (same as core box.ts)
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
const BORDER = {
|
|
13
|
+
tl: '\u250c', // ┌
|
|
14
|
+
tr: '\u2510', // ┐
|
|
15
|
+
bl: '\u2514', // └
|
|
16
|
+
br: '\u2518', // ┘
|
|
17
|
+
h: '\u2500', // ─
|
|
18
|
+
v: '\u2502', // │
|
|
19
|
+
};
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// spliceLine (internal)
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
function spliceLine(bgLine, overlayLine, col) {
|
|
24
|
+
const overlayVis = visibleLength(overlayLine);
|
|
25
|
+
const bgVis = visibleLength(bgLine);
|
|
26
|
+
const left = bgVis <= col
|
|
27
|
+
? bgLine + ' '.repeat(col - bgVis)
|
|
28
|
+
: sliceAnsi(bgLine, 0, col);
|
|
29
|
+
const right = sliceAnsi(bgLine, col + overlayVis, bgVis);
|
|
30
|
+
return left + '\x1b[0m' + overlayLine + '\x1b[0m' + right;
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// composite()
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
export function composite(background, overlays, options) {
|
|
36
|
+
const bgLines = background.split('\n');
|
|
37
|
+
if (options?.dim) {
|
|
38
|
+
for (let i = 0; i < bgLines.length; i++) {
|
|
39
|
+
if (visibleLength(bgLines[i]) > 0) {
|
|
40
|
+
bgLines[i] = '\x1b[2m' + bgLines[i] + '\x1b[0m';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
for (const overlay of overlays) {
|
|
45
|
+
const oLines = overlay.content.split('\n');
|
|
46
|
+
for (let i = 0; i < oLines.length; i++) {
|
|
47
|
+
const targetRow = overlay.row + i;
|
|
48
|
+
if (targetRow < 0 || targetRow >= bgLines.length)
|
|
49
|
+
continue;
|
|
50
|
+
bgLines[targetRow] = spliceLine(bgLines[targetRow], oLines[i], overlay.col);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return bgLines.join('\n');
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// renderBox (shared between modal and toast)
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
function renderBox(lines, borderColor) {
|
|
59
|
+
const innerWidth = lines.reduce((max, l) => Math.max(max, visibleLength(l)), 0);
|
|
60
|
+
const top = borderColor(BORDER.tl + BORDER.h.repeat(innerWidth + 2) + BORDER.tr);
|
|
61
|
+
const bottom = borderColor(BORDER.bl + BORDER.h.repeat(innerWidth + 2) + BORDER.br);
|
|
62
|
+
const body = lines.map((l) => {
|
|
63
|
+
const pad = innerWidth - visibleLength(l);
|
|
64
|
+
return borderColor(BORDER.v) + ' ' + l + ' '.repeat(pad) + ' ' + borderColor(BORDER.v);
|
|
65
|
+
});
|
|
66
|
+
return [top, ...body, bottom].join('\n');
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// modal()
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
export function modal(options) {
|
|
72
|
+
const { title, body, hint, screenWidth, screenHeight, ctx } = options;
|
|
73
|
+
const contentLines = [];
|
|
74
|
+
if (title != null) {
|
|
75
|
+
const titleText = ctx ? ctx.style.bold(title) : title;
|
|
76
|
+
contentLines.push(titleText, '');
|
|
77
|
+
}
|
|
78
|
+
contentLines.push(...body.split('\n'));
|
|
79
|
+
if (hint != null) {
|
|
80
|
+
contentLines.push('');
|
|
81
|
+
const hintText = ctx
|
|
82
|
+
? ctx.style.styled(ctx.theme.theme.semantic.muted, hint)
|
|
83
|
+
: hint;
|
|
84
|
+
contentLines.push(hintText);
|
|
85
|
+
}
|
|
86
|
+
// If width override, constrain inner width
|
|
87
|
+
if (options.width != null) {
|
|
88
|
+
const targetInner = options.width - 4; // border + padding
|
|
89
|
+
// Pad short lines, but don't truncate (user controls width)
|
|
90
|
+
for (let i = 0; i < contentLines.length; i++) {
|
|
91
|
+
const vis = visibleLength(contentLines[i]);
|
|
92
|
+
if (vis < targetInner) {
|
|
93
|
+
contentLines[i] = contentLines[i] + ' '.repeat(targetInner - vis);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const borderColor = ctx && options.borderToken
|
|
98
|
+
? (s) => ctx.style.styled(options.borderToken, s)
|
|
99
|
+
: (s) => s;
|
|
100
|
+
const boxStr = renderBox(contentLines, borderColor);
|
|
101
|
+
const boxLines = boxStr.split('\n');
|
|
102
|
+
const boxHeight = boxLines.length;
|
|
103
|
+
const boxWidth = visibleLength(boxLines[0]);
|
|
104
|
+
const row = Math.max(0, Math.floor((screenHeight - boxHeight) / 2));
|
|
105
|
+
const col = Math.max(0, Math.floor((screenWidth - boxWidth) / 2));
|
|
106
|
+
return { content: boxStr, row, col };
|
|
107
|
+
}
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// toast()
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
const TOAST_ICONS = {
|
|
112
|
+
success: '\u2714', // ✔
|
|
113
|
+
error: '\u2718', // ✘
|
|
114
|
+
info: '\u2139', // ℹ
|
|
115
|
+
};
|
|
116
|
+
const TOAST_BORDER = {
|
|
117
|
+
success: 'success',
|
|
118
|
+
error: 'error',
|
|
119
|
+
info: 'primary',
|
|
120
|
+
};
|
|
121
|
+
export function toast(options) {
|
|
122
|
+
const { message, variant = 'info', anchor = 'bottom-right', screenWidth, screenHeight, margin = 1, ctx, } = options;
|
|
123
|
+
const icon = TOAST_ICONS[variant];
|
|
124
|
+
let line = icon + ' ' + message;
|
|
125
|
+
if (ctx) {
|
|
126
|
+
line = ctx.style.styled(ctx.theme.theme.semantic[variant], line);
|
|
127
|
+
}
|
|
128
|
+
const borderKey = TOAST_BORDER[variant];
|
|
129
|
+
const borderColor = ctx
|
|
130
|
+
? (s) => ctx.style.styled(ctx.theme.theme.border[borderKey], s)
|
|
131
|
+
: (s) => s;
|
|
132
|
+
const boxStr = renderBox([line], borderColor);
|
|
133
|
+
const boxLines = boxStr.split('\n');
|
|
134
|
+
const boxHeight = boxLines.length;
|
|
135
|
+
const boxWidth = visibleLength(boxLines[0]);
|
|
136
|
+
let row;
|
|
137
|
+
let col;
|
|
138
|
+
switch (anchor) {
|
|
139
|
+
case 'top-right':
|
|
140
|
+
row = margin;
|
|
141
|
+
col = screenWidth - boxWidth - margin;
|
|
142
|
+
break;
|
|
143
|
+
case 'bottom-right':
|
|
144
|
+
row = screenHeight - boxHeight - margin;
|
|
145
|
+
col = screenWidth - boxWidth - margin;
|
|
146
|
+
break;
|
|
147
|
+
case 'bottom-left':
|
|
148
|
+
row = screenHeight - boxHeight - margin;
|
|
149
|
+
col = margin;
|
|
150
|
+
break;
|
|
151
|
+
case 'top-left':
|
|
152
|
+
row = margin;
|
|
153
|
+
col = margin;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
row = Math.max(0, row);
|
|
157
|
+
col = Math.max(0, col);
|
|
158
|
+
return { content: boxStr, row, col };
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"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"}
|
package/dist/pager.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pager building block — a scrollable text viewer with status line.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `viewport()` with a "Line N/M" status indicator and provides
|
|
5
|
+
* a convenience keymap for vim-style scroll navigation.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* // In TEA init:
|
|
9
|
+
* const pagerState = createPagerState({ content, width: 80, height: 20 });
|
|
10
|
+
*
|
|
11
|
+
* // In TEA view:
|
|
12
|
+
* const output = pager(model.pagerState);
|
|
13
|
+
*
|
|
14
|
+
* // In TEA update:
|
|
15
|
+
* case 'scroll-down':
|
|
16
|
+
* return [{ ...model, pagerState: pagerScrollBy(model.pagerState, 1) }, []];
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import { type ScrollState } from './viewport.js';
|
|
20
|
+
import { type KeyMap } from './keybindings.js';
|
|
21
|
+
export interface PagerState {
|
|
22
|
+
readonly scroll: ScrollState;
|
|
23
|
+
readonly content: string;
|
|
24
|
+
readonly width: number;
|
|
25
|
+
readonly height: number;
|
|
26
|
+
}
|
|
27
|
+
export interface PagerOptions {
|
|
28
|
+
readonly content: string;
|
|
29
|
+
readonly width: number;
|
|
30
|
+
readonly height: number;
|
|
31
|
+
}
|
|
32
|
+
export interface PagerRenderOptions {
|
|
33
|
+
/** Show a scrollbar track on the right edge. Default: true. */
|
|
34
|
+
readonly showScrollbar?: boolean;
|
|
35
|
+
/** Show a "Line N/M" status line below the viewport. Default: true. */
|
|
36
|
+
readonly showStatus?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create initial pager state for the given content and dimensions.
|
|
40
|
+
*
|
|
41
|
+
* The viewport height is `height - 1` when status is shown (the default),
|
|
42
|
+
* reserving one line for the status indicator.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createPagerState(options: PagerOptions): PagerState;
|
|
45
|
+
/** Scroll by a relative number of lines. */
|
|
46
|
+
export declare function pagerScrollBy(state: PagerState, dy: number): PagerState;
|
|
47
|
+
/** Scroll to an absolute line. */
|
|
48
|
+
export declare function pagerScrollTo(state: PagerState, y: number): PagerState;
|
|
49
|
+
/** Scroll to the first line. */
|
|
50
|
+
export declare function pagerScrollToTop(state: PagerState): PagerState;
|
|
51
|
+
/** Scroll to the last line. */
|
|
52
|
+
export declare function pagerScrollToBottom(state: PagerState): PagerState;
|
|
53
|
+
/** Page down (one viewport height). */
|
|
54
|
+
export declare function pagerPageDown(state: PagerState): PagerState;
|
|
55
|
+
/** Page up (one viewport height). */
|
|
56
|
+
export declare function pagerPageUp(state: PagerState): PagerState;
|
|
57
|
+
/** Update content while preserving scroll position (clamped). */
|
|
58
|
+
export declare function pagerSetContent(state: PagerState, content: string): PagerState;
|
|
59
|
+
/**
|
|
60
|
+
* Render the pager — viewport content plus optional status line.
|
|
61
|
+
*/
|
|
62
|
+
export declare function pager(state: PagerState, options?: PagerRenderOptions): string;
|
|
63
|
+
/**
|
|
64
|
+
* Create a preconfigured KeyMap for pager navigation.
|
|
65
|
+
*
|
|
66
|
+
* The caller provides their own message types for each action:
|
|
67
|
+
* ```ts
|
|
68
|
+
* const keys = pagerKeyMap({
|
|
69
|
+
* scrollUp: { type: 'scroll', dy: -1 },
|
|
70
|
+
* scrollDown: { type: 'scroll', dy: 1 },
|
|
71
|
+
* pageUp: { type: 'page-up' },
|
|
72
|
+
* pageDown: { type: 'page-down' },
|
|
73
|
+
* top: { type: 'top' },
|
|
74
|
+
* bottom: { type: 'bottom' },
|
|
75
|
+
* quit: { type: 'quit' },
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function pagerKeyMap<Msg>(actions: {
|
|
80
|
+
scrollUp: Msg;
|
|
81
|
+
scrollDown: Msg;
|
|
82
|
+
pageUp: Msg;
|
|
83
|
+
pageDown: Msg;
|
|
84
|
+
top: Msg;
|
|
85
|
+
bottom: Msg;
|
|
86
|
+
quit: Msg;
|
|
87
|
+
}): KeyMap<Msg>;
|
|
88
|
+
//# sourceMappingURL=pager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pager.d.ts","sourceRoot":"","sources":["../src/pager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,KAAK,WAAW,EASjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B;AAMD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,CASlE;AAMD,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAEvE;AAED,kCAAkC;AAClC,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAEtE;AAED,gCAAgC;AAChC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAE9D;AAED,+BAA+B;AAC/B,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEjE;AAED,uCAAuC;AACvC,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAE3D;AAED,qCAAqC;AACrC,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEzD;AAED,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAS9E;AAMD;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,MAAM,CA4B7E;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE;IACxC,QAAQ,EAAE,GAAG,CAAC;IACd,UAAU,EAAE,GAAG,CAAC;IAChB,MAAM,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,GAAG,CAAC;IACd,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;CACX,GAAG,MAAM,CAAC,GAAG,CAAC,CAgBd"}
|
package/dist/pager.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pager building block — a scrollable text viewer with status line.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `viewport()` with a "Line N/M" status indicator and provides
|
|
5
|
+
* a convenience keymap for vim-style scroll navigation.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* // In TEA init:
|
|
9
|
+
* const pagerState = createPagerState({ content, width: 80, height: 20 });
|
|
10
|
+
*
|
|
11
|
+
* // In TEA view:
|
|
12
|
+
* const output = pager(model.pagerState);
|
|
13
|
+
*
|
|
14
|
+
* // In TEA update:
|
|
15
|
+
* case 'scroll-down':
|
|
16
|
+
* return [{ ...model, pagerState: pagerScrollBy(model.pagerState, 1) }, []];
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import { viewport, createScrollState, scrollBy, scrollTo, scrollToTop, scrollToBottom, pageDown, pageUp, } from './viewport.js';
|
|
20
|
+
import { createKeyMap } from './keybindings.js';
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// State creation
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Create initial pager state for the given content and dimensions.
|
|
26
|
+
*
|
|
27
|
+
* The viewport height is `height - 1` when status is shown (the default),
|
|
28
|
+
* reserving one line for the status indicator.
|
|
29
|
+
*/
|
|
30
|
+
export function createPagerState(options) {
|
|
31
|
+
const { content, width, height } = options;
|
|
32
|
+
const viewportHeight = Math.max(1, height - 1); // reserve 1 for status
|
|
33
|
+
return {
|
|
34
|
+
scroll: createScrollState(content, viewportHeight),
|
|
35
|
+
content,
|
|
36
|
+
width,
|
|
37
|
+
height,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// State transformers
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
/** Scroll by a relative number of lines. */
|
|
44
|
+
export function pagerScrollBy(state, dy) {
|
|
45
|
+
return { ...state, scroll: scrollBy(state.scroll, dy) };
|
|
46
|
+
}
|
|
47
|
+
/** Scroll to an absolute line. */
|
|
48
|
+
export function pagerScrollTo(state, y) {
|
|
49
|
+
return { ...state, scroll: scrollTo(state.scroll, y) };
|
|
50
|
+
}
|
|
51
|
+
/** Scroll to the first line. */
|
|
52
|
+
export function pagerScrollToTop(state) {
|
|
53
|
+
return { ...state, scroll: scrollToTop(state.scroll) };
|
|
54
|
+
}
|
|
55
|
+
/** Scroll to the last line. */
|
|
56
|
+
export function pagerScrollToBottom(state) {
|
|
57
|
+
return { ...state, scroll: scrollToBottom(state.scroll) };
|
|
58
|
+
}
|
|
59
|
+
/** Page down (one viewport height). */
|
|
60
|
+
export function pagerPageDown(state) {
|
|
61
|
+
return { ...state, scroll: pageDown(state.scroll) };
|
|
62
|
+
}
|
|
63
|
+
/** Page up (one viewport height). */
|
|
64
|
+
export function pagerPageUp(state) {
|
|
65
|
+
return { ...state, scroll: pageUp(state.scroll) };
|
|
66
|
+
}
|
|
67
|
+
/** Update content while preserving scroll position (clamped). */
|
|
68
|
+
export function pagerSetContent(state, content) {
|
|
69
|
+
const viewportHeight = Math.max(1, state.height - 1);
|
|
70
|
+
const newScroll = createScrollState(content, viewportHeight);
|
|
71
|
+
const clampedY = Math.min(state.scroll.y, newScroll.maxY);
|
|
72
|
+
return {
|
|
73
|
+
...state,
|
|
74
|
+
content,
|
|
75
|
+
scroll: { ...newScroll, y: clampedY },
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Render
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
/**
|
|
82
|
+
* Render the pager — viewport content plus optional status line.
|
|
83
|
+
*/
|
|
84
|
+
export function pager(state, options) {
|
|
85
|
+
const showScrollbar = options?.showScrollbar ?? true;
|
|
86
|
+
const showStatus = options?.showStatus ?? true;
|
|
87
|
+
const viewportHeight = showStatus
|
|
88
|
+
? Math.max(1, state.height - 1)
|
|
89
|
+
: state.height;
|
|
90
|
+
// Clamp scroll to the active viewport height (which may differ from
|
|
91
|
+
// the height used when creating state if showStatus changed).
|
|
92
|
+
const maxY = Math.max(0, state.scroll.totalLines - viewportHeight);
|
|
93
|
+
const clampedY = Math.max(0, Math.min(state.scroll.y, maxY));
|
|
94
|
+
const body = viewport({
|
|
95
|
+
width: state.width,
|
|
96
|
+
height: viewportHeight,
|
|
97
|
+
content: state.content,
|
|
98
|
+
scrollY: clampedY,
|
|
99
|
+
showScrollbar,
|
|
100
|
+
});
|
|
101
|
+
if (!showStatus)
|
|
102
|
+
return body;
|
|
103
|
+
const currentLine = clampedY + 1;
|
|
104
|
+
const totalLines = state.scroll.totalLines;
|
|
105
|
+
const status = ` Line ${currentLine}/${totalLines}`;
|
|
106
|
+
return body + '\n' + status;
|
|
107
|
+
}
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Convenience keymap
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
/**
|
|
112
|
+
* Create a preconfigured KeyMap for pager navigation.
|
|
113
|
+
*
|
|
114
|
+
* The caller provides their own message types for each action:
|
|
115
|
+
* ```ts
|
|
116
|
+
* const keys = pagerKeyMap({
|
|
117
|
+
* scrollUp: { type: 'scroll', dy: -1 },
|
|
118
|
+
* scrollDown: { type: 'scroll', dy: 1 },
|
|
119
|
+
* pageUp: { type: 'page-up' },
|
|
120
|
+
* pageDown: { type: 'page-down' },
|
|
121
|
+
* top: { type: 'top' },
|
|
122
|
+
* bottom: { type: 'bottom' },
|
|
123
|
+
* quit: { type: 'quit' },
|
|
124
|
+
* });
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export function pagerKeyMap(actions) {
|
|
128
|
+
return createKeyMap()
|
|
129
|
+
.group('Scroll', (g) => g
|
|
130
|
+
.bind('k', 'Up', actions.scrollUp)
|
|
131
|
+
.bind('up', 'Up', actions.scrollUp)
|
|
132
|
+
.bind('j', 'Down', actions.scrollDown)
|
|
133
|
+
.bind('down', 'Down', actions.scrollDown)
|
|
134
|
+
.bind('u', 'Page up', actions.pageUp)
|
|
135
|
+
.bind('pageup', 'Page up', actions.pageUp)
|
|
136
|
+
.bind('d', 'Page down', actions.pageDown)
|
|
137
|
+
.bind('pagedown', 'Page down', actions.pageDown)
|
|
138
|
+
.bind('g', 'Top', actions.top)
|
|
139
|
+
.bind('shift+g', 'Bottom', actions.bottom))
|
|
140
|
+
.bind('q', 'Quit', actions.quit)
|
|
141
|
+
.bind('ctrl+c', 'Quit', actions.quit);
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=pager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pager.js","sourceRoot":"","sources":["../src/pager.ts"],"names":[],"mappings":"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"}
|
package/dist/panels.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-pane focus management for TUI applications.
|
|
3
|
+
*
|
|
4
|
+
* Each panel has a hotkey, label, and its own KeyMap. The group tracks
|
|
5
|
+
* which panel is focused, routes input to the active panel's keymap,
|
|
6
|
+
* and switches focus on hotkey press.
|
|
7
|
+
*/
|
|
8
|
+
import type { KeyMsg } from './types.js';
|
|
9
|
+
import type { KeyMap } from './keybindings.js';
|
|
10
|
+
import type { InputStack } from './inputstack.js';
|
|
11
|
+
import type { BijouContext } from '@flyingrobots/bijou';
|
|
12
|
+
export interface PanelDef<A> {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly hotkey: string;
|
|
15
|
+
readonly label: string;
|
|
16
|
+
readonly keyMap: KeyMap<A>;
|
|
17
|
+
}
|
|
18
|
+
export interface PanelGroupOptions<A> {
|
|
19
|
+
readonly panels: readonly PanelDef<A>[];
|
|
20
|
+
readonly defaultFocus: string;
|
|
21
|
+
readonly inputStack?: InputStack<KeyMsg, A>;
|
|
22
|
+
}
|
|
23
|
+
export interface PanelGroup<A> {
|
|
24
|
+
readonly focused: string;
|
|
25
|
+
focus(id: string): void;
|
|
26
|
+
handle(msg: KeyMsg): A | undefined;
|
|
27
|
+
formatLabel(id: string, ctx?: BijouContext): string;
|
|
28
|
+
dispose(): void;
|
|
29
|
+
}
|
|
30
|
+
export declare function createPanelGroup<A>(options: PanelGroupOptions<A>): PanelGroup<A>;
|
|
31
|
+
//# sourceMappingURL=panels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../src/panels.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMxD,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IACpD,OAAO,IAAI,IAAI,CAAC;CACjB;AAMD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAuHhF"}
|
package/dist/panels.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-pane focus management for TUI applications.
|
|
3
|
+
*
|
|
4
|
+
* Each panel has a hotkey, label, and its own KeyMap. The group tracks
|
|
5
|
+
* which panel is focused, routes input to the active panel's keymap,
|
|
6
|
+
* and switches focus on hotkey press.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Implementation
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export function createPanelGroup(options) {
|
|
12
|
+
const panelMap = new Map();
|
|
13
|
+
const hotkeyMap = new Map();
|
|
14
|
+
for (const panel of options.panels) {
|
|
15
|
+
panelMap.set(panel.id, panel);
|
|
16
|
+
hotkeyMap.set(panel.hotkey, panel.id);
|
|
17
|
+
}
|
|
18
|
+
if (!panelMap.has(options.defaultFocus)) {
|
|
19
|
+
throw new Error(`createPanelGroup: defaultFocus "${options.defaultFocus}" does not match any panel id. ` +
|
|
20
|
+
`Available: ${[...panelMap.keys()].join(', ')}`);
|
|
21
|
+
}
|
|
22
|
+
let focusedId = options.defaultFocus;
|
|
23
|
+
const { inputStack } = options;
|
|
24
|
+
let hotkeyLayerId;
|
|
25
|
+
let panelLayerId;
|
|
26
|
+
if (inputStack) {
|
|
27
|
+
// Hotkey layer: passthrough, handles hotkey presses
|
|
28
|
+
hotkeyLayerId = inputStack.push({
|
|
29
|
+
handle(msg) {
|
|
30
|
+
if (!msg.ctrl && !msg.alt && !msg.shift) {
|
|
31
|
+
const targetId = hotkeyMap.get(msg.key);
|
|
32
|
+
if (targetId !== undefined && targetId !== focusedId) {
|
|
33
|
+
group.focus(targetId);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
},
|
|
38
|
+
}, { passthrough: true, name: 'panel-group:hotkeys' });
|
|
39
|
+
// Focused panel keymap layer
|
|
40
|
+
const focusedPanel = panelMap.get(focusedId);
|
|
41
|
+
if (focusedPanel) {
|
|
42
|
+
panelLayerId = inputStack.push(focusedPanel.keyMap, {
|
|
43
|
+
passthrough: true,
|
|
44
|
+
name: `panel:${focusedId}`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const group = {
|
|
49
|
+
get focused() {
|
|
50
|
+
return focusedId;
|
|
51
|
+
},
|
|
52
|
+
focus(id) {
|
|
53
|
+
if (!panelMap.has(id) || id === focusedId)
|
|
54
|
+
return;
|
|
55
|
+
focusedId = id;
|
|
56
|
+
if (inputStack && panelLayerId !== undefined) {
|
|
57
|
+
inputStack.remove(panelLayerId);
|
|
58
|
+
const panel = panelMap.get(id);
|
|
59
|
+
panelLayerId = inputStack.push(panel.keyMap, {
|
|
60
|
+
passthrough: true,
|
|
61
|
+
name: `panel:${id}`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
handle(msg) {
|
|
66
|
+
// Check hotkeys first (only plain keys, no modifiers)
|
|
67
|
+
if (!msg.ctrl && !msg.alt && !msg.shift) {
|
|
68
|
+
const targetId = hotkeyMap.get(msg.key);
|
|
69
|
+
if (targetId !== undefined && targetId !== focusedId) {
|
|
70
|
+
group.focus(targetId);
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Delegate to focused panel's keymap
|
|
75
|
+
const panel = panelMap.get(focusedId);
|
|
76
|
+
if (panel) {
|
|
77
|
+
return panel.keyMap.handle(msg);
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
},
|
|
81
|
+
formatLabel(id, ctx) {
|
|
82
|
+
const panel = panelMap.get(id);
|
|
83
|
+
if (!panel)
|
|
84
|
+
return '';
|
|
85
|
+
if (!ctx) {
|
|
86
|
+
return `[${panel.hotkey}] ${panel.label}`;
|
|
87
|
+
}
|
|
88
|
+
const style = ctx.style;
|
|
89
|
+
const semantic = ctx.theme.theme.semantic;
|
|
90
|
+
if (id === focusedId) {
|
|
91
|
+
return style.bold(style.styled(semantic.primary, panel.label));
|
|
92
|
+
}
|
|
93
|
+
return style.styled(semantic.muted, panel.label);
|
|
94
|
+
},
|
|
95
|
+
dispose() {
|
|
96
|
+
if (inputStack) {
|
|
97
|
+
if (panelLayerId !== undefined) {
|
|
98
|
+
inputStack.remove(panelLayerId);
|
|
99
|
+
panelLayerId = undefined;
|
|
100
|
+
}
|
|
101
|
+
if (hotkeyLayerId !== undefined) {
|
|
102
|
+
inputStack.remove(hotkeyLayerId);
|
|
103
|
+
hotkeyLayerId = undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
return group;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=panels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panels.js","sourceRoot":"","sources":["../src/panels.ts"],"names":[],"mappings":"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"}
|
package/dist/viewport.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface ViewportOptions {
|
|
|
13
13
|
readonly content: string;
|
|
14
14
|
/** Vertical scroll offset (0-based line index). Default: 0. */
|
|
15
15
|
readonly scrollY?: number;
|
|
16
|
+
/** Horizontal scroll offset (0-based column index). Default: 0. */
|
|
17
|
+
readonly scrollX?: number;
|
|
16
18
|
/** Show a scrollbar track on the right edge. Default: true. */
|
|
17
19
|
readonly showScrollbar?: boolean;
|
|
18
20
|
}
|
|
@@ -21,11 +23,28 @@ export interface ScrollState {
|
|
|
21
23
|
readonly y: number;
|
|
22
24
|
/** Maximum vertical scroll offset. */
|
|
23
25
|
readonly maxY: number;
|
|
26
|
+
/** Current horizontal scroll offset. */
|
|
27
|
+
readonly x: number;
|
|
28
|
+
/** Maximum horizontal scroll offset. */
|
|
29
|
+
readonly maxX: number;
|
|
24
30
|
/** Total number of content lines. */
|
|
25
31
|
readonly totalLines: number;
|
|
26
32
|
/** Number of visible lines (viewport height). */
|
|
27
33
|
readonly visibleLines: number;
|
|
28
34
|
}
|
|
35
|
+
export declare function stripAnsi(str: string): string;
|
|
36
|
+
export declare function visibleLength(str: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* Clip a string to a maximum visible width, preserving ANSI escapes.
|
|
39
|
+
* Appends a reset sequence if the string was clipped mid-style.
|
|
40
|
+
*/
|
|
41
|
+
export declare function clipToWidth(str: string, maxWidth: number): string;
|
|
42
|
+
/**
|
|
43
|
+
* Extract a visible-column substring from an ANSI-styled string.
|
|
44
|
+
* Returns characters between visible columns [startCol, endCol).
|
|
45
|
+
* Preserves any active ANSI styles seen before startCol.
|
|
46
|
+
*/
|
|
47
|
+
export declare function sliceAnsi(str: string, startCol: number, endCol: number): string;
|
|
29
48
|
/**
|
|
30
49
|
* Render a scrollable viewport into content.
|
|
31
50
|
*
|
|
@@ -36,7 +55,7 @@ export declare function viewport(options: ViewportOptions): string;
|
|
|
36
55
|
/**
|
|
37
56
|
* Create initial scroll state for content within a viewport.
|
|
38
57
|
*/
|
|
39
|
-
export declare function createScrollState(content: string, viewportHeight: number): ScrollState;
|
|
58
|
+
export declare function createScrollState(content: string, viewportHeight: number, viewportWidth?: number): ScrollState;
|
|
40
59
|
/**
|
|
41
60
|
* Scroll by a relative amount. Clamps to valid range.
|
|
42
61
|
*/
|
|
@@ -45,6 +64,14 @@ export declare function scrollBy(state: ScrollState, dy: number): ScrollState;
|
|
|
45
64
|
* Scroll to an absolute position. Clamps to valid range.
|
|
46
65
|
*/
|
|
47
66
|
export declare function scrollTo(state: ScrollState, y: number): ScrollState;
|
|
67
|
+
/**
|
|
68
|
+
* Scroll horizontally by a relative amount. Clamps to valid range.
|
|
69
|
+
*/
|
|
70
|
+
export declare function scrollByX(state: ScrollState, dx: number): ScrollState;
|
|
71
|
+
/**
|
|
72
|
+
* Scroll horizontally to an absolute position. Clamps to valid range.
|
|
73
|
+
*/
|
|
74
|
+
export declare function scrollToX(state: ScrollState, x: number): ScrollState;
|
|
48
75
|
/**
|
|
49
76
|
* Scroll to the top.
|
|
50
77
|
*/
|
package/dist/viewport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;
|
|
1
|
+
{"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAQD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CA+BjE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAqD/E;AAsCD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CA+CzD;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,MAAM,GACrB,WAAW,CAsBb;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,CAGpE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,CAEnE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,CAErE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,CAEpE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAE3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAE9D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAExD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAEtD"}
|
package/dist/viewport.js
CHANGED
|
@@ -8,17 +8,17 @@
|
|
|
8
8
|
// ANSI helpers
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
const ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
11
|
-
function stripAnsi(str) {
|
|
11
|
+
export function stripAnsi(str) {
|
|
12
12
|
return str.replace(ANSI_RE, '');
|
|
13
13
|
}
|
|
14
|
-
function visibleLength(str) {
|
|
14
|
+
export function visibleLength(str) {
|
|
15
15
|
return stripAnsi(str).length;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Clip a string to a maximum visible width, preserving ANSI escapes.
|
|
19
19
|
* Appends a reset sequence if the string was clipped mid-style.
|
|
20
20
|
*/
|
|
21
|
-
function clipToWidth(str, maxWidth) {
|
|
21
|
+
export function clipToWidth(str, maxWidth) {
|
|
22
22
|
let visible = 0;
|
|
23
23
|
let result = '';
|
|
24
24
|
let inEscape = false;
|
|
@@ -45,6 +45,63 @@ function clipToWidth(str, maxWidth) {
|
|
|
45
45
|
}
|
|
46
46
|
return result;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Extract a visible-column substring from an ANSI-styled string.
|
|
50
|
+
* Returns characters between visible columns [startCol, endCol).
|
|
51
|
+
* Preserves any active ANSI styles seen before startCol.
|
|
52
|
+
*/
|
|
53
|
+
export function sliceAnsi(str, startCol, endCol) {
|
|
54
|
+
let visible = 0;
|
|
55
|
+
let inEscape = false;
|
|
56
|
+
let activeAnsi = '';
|
|
57
|
+
let result = '';
|
|
58
|
+
let collecting = false;
|
|
59
|
+
let hasStyle = false;
|
|
60
|
+
for (let i = 0; i < str.length; i++) {
|
|
61
|
+
const ch = str[i];
|
|
62
|
+
if (ch === '\x1b') {
|
|
63
|
+
inEscape = true;
|
|
64
|
+
if (collecting) {
|
|
65
|
+
result += ch;
|
|
66
|
+
hasStyle = true;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
activeAnsi += ch;
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (inEscape) {
|
|
74
|
+
if (collecting) {
|
|
75
|
+
result += ch;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
activeAnsi += ch;
|
|
79
|
+
}
|
|
80
|
+
if (ch === 'm')
|
|
81
|
+
inEscape = false;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (visible >= endCol) {
|
|
85
|
+
if (hasStyle)
|
|
86
|
+
result += '\x1b[0m';
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
if (visible >= startCol) {
|
|
90
|
+
if (!collecting) {
|
|
91
|
+
collecting = true;
|
|
92
|
+
result = activeAnsi;
|
|
93
|
+
if (activeAnsi.length > 0)
|
|
94
|
+
hasStyle = true;
|
|
95
|
+
}
|
|
96
|
+
result += ch;
|
|
97
|
+
}
|
|
98
|
+
visible++;
|
|
99
|
+
}
|
|
100
|
+
// Append reset if we reached end of string with an active style
|
|
101
|
+
if (collecting && hasStyle)
|
|
102
|
+
result += '\x1b[0m';
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
48
105
|
// ---------------------------------------------------------------------------
|
|
49
106
|
// Scrollbar rendering
|
|
50
107
|
// ---------------------------------------------------------------------------
|
|
@@ -77,7 +134,7 @@ function renderScrollbar(viewportHeight, totalLines, scrollY) {
|
|
|
77
134
|
* characters wide (plus optional scrollbar).
|
|
78
135
|
*/
|
|
79
136
|
export function viewport(options) {
|
|
80
|
-
const { width, height, content, scrollY = 0, showScrollbar = true, } = options;
|
|
137
|
+
const { width, height, content, scrollY = 0, scrollX = 0, showScrollbar = true, } = options;
|
|
81
138
|
const allLines = content.split('\n');
|
|
82
139
|
const totalLines = allLines.length;
|
|
83
140
|
const maxScroll = Math.max(0, totalLines - height);
|
|
@@ -93,12 +150,16 @@ export function viewport(options) {
|
|
|
93
150
|
}
|
|
94
151
|
// Clip/pad each line to content width
|
|
95
152
|
const rendered = visibleSlice.map((line) => {
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
153
|
+
let sliced;
|
|
154
|
+
if (scrollX > 0) {
|
|
155
|
+
sliced = sliceAnsi(line, scrollX, scrollX + contentWidth);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
const vis = visibleLength(line);
|
|
159
|
+
sliced = vis > contentWidth ? clipToWidth(line, contentWidth) : line;
|
|
99
160
|
}
|
|
100
|
-
|
|
101
|
-
return
|
|
161
|
+
const slicedVis = visibleLength(sliced);
|
|
162
|
+
return slicedVis < contentWidth ? sliced + ' '.repeat(contentWidth - slicedVis) : sliced;
|
|
102
163
|
});
|
|
103
164
|
// Append scrollbar
|
|
104
165
|
if (needsScrollbar) {
|
|
@@ -113,11 +174,24 @@ export function viewport(options) {
|
|
|
113
174
|
/**
|
|
114
175
|
* Create initial scroll state for content within a viewport.
|
|
115
176
|
*/
|
|
116
|
-
export function createScrollState(content, viewportHeight) {
|
|
117
|
-
const
|
|
177
|
+
export function createScrollState(content, viewportHeight, viewportWidth) {
|
|
178
|
+
const lines = content.split('\n');
|
|
179
|
+
const totalLines = lines.length;
|
|
180
|
+
let maxX = 0;
|
|
181
|
+
if (viewportWidth !== undefined) {
|
|
182
|
+
let widest = 0;
|
|
183
|
+
for (const line of lines) {
|
|
184
|
+
const w = visibleLength(line);
|
|
185
|
+
if (w > widest)
|
|
186
|
+
widest = w;
|
|
187
|
+
}
|
|
188
|
+
maxX = Math.max(0, widest - viewportWidth);
|
|
189
|
+
}
|
|
118
190
|
return {
|
|
119
191
|
y: 0,
|
|
120
192
|
maxY: Math.max(0, totalLines - viewportHeight),
|
|
193
|
+
x: 0,
|
|
194
|
+
maxX,
|
|
121
195
|
totalLines,
|
|
122
196
|
visibleLines: viewportHeight,
|
|
123
197
|
};
|
|
@@ -135,6 +209,18 @@ export function scrollBy(state, dy) {
|
|
|
135
209
|
export function scrollTo(state, y) {
|
|
136
210
|
return { ...state, y: Math.max(0, Math.min(y, state.maxY)) };
|
|
137
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Scroll horizontally by a relative amount. Clamps to valid range.
|
|
214
|
+
*/
|
|
215
|
+
export function scrollByX(state, dx) {
|
|
216
|
+
return { ...state, x: Math.max(0, Math.min(state.x + dx, state.maxX)) };
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Scroll horizontally to an absolute position. Clamps to valid range.
|
|
220
|
+
*/
|
|
221
|
+
export function scrollToX(state, x) {
|
|
222
|
+
return { ...state, x: Math.max(0, Math.min(x, state.maxX)) };
|
|
223
|
+
}
|
|
138
224
|
/**
|
|
139
225
|
* Scroll to the top.
|
|
140
226
|
*/
|
package/dist/viewport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewport.js","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"viewport.js","sourceRoot":"","sources":["../src/viewport.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.
|
|
3
|
+
"version": "0.4.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
|
"dependencies": {
|
|
27
|
-
"@flyingrobots/bijou": "0.
|
|
27
|
+
"@flyingrobots/bijou": "0.4.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "^22.0.0",
|