@flyingrobots/bijou-tui 0.1.0 → 0.2.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 +221 -30
- package/dist/animate.d.ts +60 -0
- package/dist/animate.d.ts.map +1 -0
- package/dist/animate.js +98 -0
- package/dist/animate.js.map +1 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +2 -2
- package/dist/commands.js.map +1 -1
- package/dist/eventbus.d.ts +69 -0
- package/dist/eventbus.d.ts.map +1 -0
- package/dist/eventbus.js +120 -0
- package/dist/eventbus.js.map +1 -0
- package/dist/flex.d.ts +64 -0
- package/dist/flex.d.ts.map +1 -0
- package/dist/flex.js +261 -0
- package/dist/flex.js.map +1 -0
- package/dist/help.d.ts +58 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +104 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/inputstack.d.ts +79 -0
- package/dist/inputstack.d.ts.map +1 -0
- package/dist/inputstack.js +81 -0
- package/dist/inputstack.js.map +1 -0
- package/dist/keybindings.d.ts +83 -0
- package/dist/keybindings.d.ts.map +1 -0
- package/dist/keybindings.js +184 -0
- package/dist/keybindings.js.map +1 -0
- package/dist/layout.d.ts +0 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +3 -4
- package/dist/layout.js.map +1 -1
- package/dist/runtime.d.ts +3 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +24 -37
- package/dist/runtime.js.map +1 -1
- package/dist/screen.d.ts +10 -4
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +13 -11
- package/dist/screen.js.map +1 -1
- package/dist/spring.d.ts +139 -0
- package/dist/spring.d.ts.map +1 -0
- package/dist/spring.js +106 -0
- package/dist/spring.js.map +1 -0
- package/dist/timeline.d.ts +127 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +298 -0
- package/dist/timeline.js.map +1 -0
- package/dist/types.d.ts +11 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/viewport.d.ts +64 -0
- package/dist/viewport.d.ts.map +1 -0
- package/dist/viewport.js +162 -0
- package/dist/viewport.js.map +1 -0
- package/package.json +2 -2
package/dist/eventbus.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized event bus for TUI applications.
|
|
3
|
+
*
|
|
4
|
+
* Unifies all input sources (keyboard, resize, commands, custom) into
|
|
5
|
+
* a single typed event stream. The TEA runtime subscribes to the bus
|
|
6
|
+
* instead of manually wiring callbacks.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const bus = createEventBus<Msg>();
|
|
10
|
+
*
|
|
11
|
+
* // Connect I/O sources (keyboard + resize)
|
|
12
|
+
* bus.connectIO(ctx.io);
|
|
13
|
+
*
|
|
14
|
+
* // Subscribe to all events
|
|
15
|
+
* bus.on((msg) => {
|
|
16
|
+
* const [model, cmds] = app.update(msg, model);
|
|
17
|
+
* cmds.forEach(cmd => bus.runCmd(cmd));
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Emit custom events
|
|
21
|
+
* bus.emit({ type: 'tick' });
|
|
22
|
+
*
|
|
23
|
+
* // In tests — emit directly, no I/O needed
|
|
24
|
+
* bus.emit({ type: 'key', key: 'a', ctrl: false, alt: false, shift: false });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import { QUIT } from './types.js';
|
|
28
|
+
import { parseKey } from './keys.js';
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Implementation
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
export function createEventBus() {
|
|
33
|
+
const subscribers = new Set();
|
|
34
|
+
const quitHandlers = new Set();
|
|
35
|
+
const disposables = [];
|
|
36
|
+
let disposed = false;
|
|
37
|
+
function emit(msg) {
|
|
38
|
+
if (disposed)
|
|
39
|
+
return;
|
|
40
|
+
for (const handler of subscribers) {
|
|
41
|
+
handler(msg);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
on(handler) {
|
|
46
|
+
subscribers.add(handler);
|
|
47
|
+
return {
|
|
48
|
+
dispose() {
|
|
49
|
+
subscribers.delete(handler);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
emit,
|
|
54
|
+
connectIO(io) {
|
|
55
|
+
// Keyboard input
|
|
56
|
+
const inputHandle = io.rawInput((raw) => {
|
|
57
|
+
if (disposed)
|
|
58
|
+
return;
|
|
59
|
+
const keyMsg = parseKey(raw);
|
|
60
|
+
// Skip unknown sequences (mouse events, etc.)
|
|
61
|
+
if (keyMsg.key === 'unknown')
|
|
62
|
+
return;
|
|
63
|
+
emit(keyMsg);
|
|
64
|
+
});
|
|
65
|
+
// Resize events
|
|
66
|
+
const resizeHandle = io.onResize((columns, rows) => {
|
|
67
|
+
if (disposed)
|
|
68
|
+
return;
|
|
69
|
+
const msg = { type: 'resize', columns, rows };
|
|
70
|
+
emit(msg);
|
|
71
|
+
});
|
|
72
|
+
const handle = {
|
|
73
|
+
dispose() {
|
|
74
|
+
inputHandle.dispose();
|
|
75
|
+
resizeHandle.dispose();
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
disposables.push(handle);
|
|
79
|
+
return handle;
|
|
80
|
+
},
|
|
81
|
+
runCmd(cmd) {
|
|
82
|
+
if (disposed)
|
|
83
|
+
return;
|
|
84
|
+
void cmd(emit).then((result) => {
|
|
85
|
+
if (disposed)
|
|
86
|
+
return;
|
|
87
|
+
if (result === QUIT) {
|
|
88
|
+
for (const handler of quitHandlers) {
|
|
89
|
+
handler();
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (result !== undefined) {
|
|
94
|
+
emit(result);
|
|
95
|
+
}
|
|
96
|
+
}).catch((err) => {
|
|
97
|
+
// Surface command rejections instead of leaving unhandled promise rejections.
|
|
98
|
+
console.error('[EventBus] Command rejected:', err);
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
onQuit(handler) {
|
|
102
|
+
quitHandlers.add(handler);
|
|
103
|
+
return {
|
|
104
|
+
dispose() {
|
|
105
|
+
quitHandlers.delete(handler);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
dispose() {
|
|
110
|
+
disposed = true;
|
|
111
|
+
for (const d of disposables) {
|
|
112
|
+
d.dispose();
|
|
113
|
+
}
|
|
114
|
+
disposables.length = 0;
|
|
115
|
+
subscribers.clear();
|
|
116
|
+
quitHandlers.clear();
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=eventbus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventbus.js","sourceRoot":"","sources":["../src/eventbus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAoDrC,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,UAAU,cAAc;IAC5B,MAAM,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAC;IACxD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAc,CAAC;IAC3C,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,SAAS,IAAI,CAAC,GAAc;QAC1B,IAAI,QAAQ;YAAE,OAAO;QACrB,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO;QACL,EAAE,CAAC,OAAO;YACR,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACzB,OAAO;gBACL,OAAO;oBACL,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC9B,CAAC;aACF,CAAC;QACJ,CAAC;QAED,IAAI;QAEJ,SAAS,CAAC,EAAU;YAClB,iBAAiB;YACjB,MAAM,WAAW,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAW,EAAE,EAAE;gBAC9C,IAAI,QAAQ;oBAAE,OAAO;gBACrB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC7B,8CAA8C;gBAC9C,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;oBAAE,OAAO;gBACrC,IAAI,CAAC,MAAM,CAAC,CAAC;YACf,CAAC,CAAC,CAAC;YAEH,gBAAgB;YAChB,MAAM,YAAY,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;gBACjD,IAAI,QAAQ;oBAAE,OAAO;gBACrB,MAAM,GAAG,GAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBACzD,IAAI,CAAC,GAAG,CAAC,CAAC;YACZ,CAAC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAe;gBACzB,OAAO;oBACL,WAAW,CAAC,OAAO,EAAE,CAAC;oBACtB,YAAY,CAAC,OAAO,EAAE,CAAC;gBACzB,CAAC;aACF,CAAC;YACF,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzB,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,GAAW;YAChB,IAAI,QAAQ;gBAAE,OAAO;YACrB,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC7B,IAAI,QAAQ;oBAAE,OAAO;gBACrB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;oBACpB,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;wBACnC,OAAO,EAAE,CAAC;oBACZ,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBACzB,IAAI,CAAC,MAAW,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBACxB,8EAA8E;gBAC9E,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,OAAO;YACZ,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC1B,OAAO;gBACL,OAAO;oBACL,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC/B,CAAC;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC5B,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,CAAC;YACD,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;YACvB,WAAW,CAAC,KAAK,EAAE,CAAC;YACpB,YAAY,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/flex.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flexbox-style layout for terminal UIs.
|
|
3
|
+
*
|
|
4
|
+
* Distributes available space among children using flex-grow factors,
|
|
5
|
+
* fixed basis sizes, and min/max constraints. Children can be static
|
|
6
|
+
* strings or render functions that receive their allocated dimensions.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* flex({ direction: 'row', width: 80, height: 24 },
|
|
10
|
+
* { basis: 20, content: sidebar },
|
|
11
|
+
* { flex: 1, content: (w, h) => viewport({ width: w, height: h, content: body }) },
|
|
12
|
+
* )
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export interface FlexOptions {
|
|
16
|
+
/** Layout direction. Default: 'row'. */
|
|
17
|
+
readonly direction?: 'row' | 'column';
|
|
18
|
+
/** Available width in columns. */
|
|
19
|
+
readonly width: number;
|
|
20
|
+
/** Available height in rows. */
|
|
21
|
+
readonly height: number;
|
|
22
|
+
/** Gap between children (in the main axis). Default: 0. */
|
|
23
|
+
readonly gap?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface FlexChild {
|
|
26
|
+
/**
|
|
27
|
+
* Content to render. Either a static string, or a function that
|
|
28
|
+
* receives the allocated (width, height) and returns a string.
|
|
29
|
+
*/
|
|
30
|
+
readonly content: string | ((width: number, height: number) => string);
|
|
31
|
+
/** Flex-grow factor. Children with flex > 0 share remaining space. Default: 0. */
|
|
32
|
+
readonly flex?: number;
|
|
33
|
+
/** Fixed size along the main axis (columns for row, rows for column). */
|
|
34
|
+
readonly basis?: number;
|
|
35
|
+
/** Minimum size along the main axis. */
|
|
36
|
+
readonly minSize?: number;
|
|
37
|
+
/** Maximum size along the main axis. */
|
|
38
|
+
readonly maxSize?: number;
|
|
39
|
+
/** Cross-axis alignment. Default: 'start'. */
|
|
40
|
+
readonly align?: 'start' | 'center' | 'end';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Lay out children using flexbox-style rules.
|
|
44
|
+
*
|
|
45
|
+
* Row direction: children are placed side-by-side horizontally.
|
|
46
|
+
* Column direction: children are stacked vertically.
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* // Sidebar + main content
|
|
50
|
+
* flex({ direction: 'row', width: 80, height: 24, gap: 1 },
|
|
51
|
+
* { basis: 20, content: sidebarContent },
|
|
52
|
+
* { flex: 1, content: (w, h) => renderMain(w, h) },
|
|
53
|
+
* )
|
|
54
|
+
*
|
|
55
|
+
* // Header + body + footer
|
|
56
|
+
* flex({ direction: 'column', width: 80, height: 24 },
|
|
57
|
+
* { basis: 1, content: headerLine },
|
|
58
|
+
* { flex: 1, content: (w, h) => renderBody(w, h) },
|
|
59
|
+
* { basis: 1, content: statusLine },
|
|
60
|
+
* )
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function flex(options: FlexOptions, ...children: FlexChild[]): string;
|
|
64
|
+
//# sourceMappingURL=flex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flex.d.ts","sourceRoot":"","sources":["../src/flex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IACtC,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IACvE,kFAAkF;IAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,wCAAwC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CAC7C;AAoND;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,CAkB3E"}
|
package/dist/flex.js
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flexbox-style layout for terminal UIs.
|
|
3
|
+
*
|
|
4
|
+
* Distributes available space among children using flex-grow factors,
|
|
5
|
+
* fixed basis sizes, and min/max constraints. Children can be static
|
|
6
|
+
* strings or render functions that receive their allocated dimensions.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* flex({ direction: 'row', width: 80, height: 24 },
|
|
10
|
+
* { basis: 20, content: sidebar },
|
|
11
|
+
* { flex: 1, content: (w, h) => viewport({ width: w, height: h, content: body }) },
|
|
12
|
+
* )
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// ANSI helpers
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
const ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
19
|
+
function visualWidth(s) {
|
|
20
|
+
return s.replace(ANSI_RE, '').length;
|
|
21
|
+
}
|
|
22
|
+
function computeSizes(children, mainAxisTotal, crossAxisTotal, gap, isRow) {
|
|
23
|
+
if (children.length === 0)
|
|
24
|
+
return [];
|
|
25
|
+
const totalGaps = gap * (children.length - 1);
|
|
26
|
+
const available = Math.max(0, mainAxisTotal - totalGaps);
|
|
27
|
+
// First pass: allocate fixed-size children (basis or content measurement)
|
|
28
|
+
const sizes = [];
|
|
29
|
+
let usedByFixed = 0;
|
|
30
|
+
let totalFlex = 0;
|
|
31
|
+
for (const child of children) {
|
|
32
|
+
const flexGrow = child.flex ?? 0;
|
|
33
|
+
if (flexGrow > 0) {
|
|
34
|
+
sizes.push(0); // placeholder
|
|
35
|
+
totalFlex += flexGrow;
|
|
36
|
+
}
|
|
37
|
+
else if (child.basis !== undefined) {
|
|
38
|
+
const clamped = clampSize(child.basis, child.minSize, child.maxSize);
|
|
39
|
+
sizes.push(clamped);
|
|
40
|
+
usedByFixed += clamped;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Auto-size from content
|
|
44
|
+
const measured = measureContent(child.content, isRow);
|
|
45
|
+
const clamped = clampSize(measured, child.minSize, child.maxSize);
|
|
46
|
+
sizes.push(clamped);
|
|
47
|
+
usedByFixed += clamped;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Second pass: distribute remaining space to flex children
|
|
51
|
+
const remaining = Math.max(0, available - usedByFixed);
|
|
52
|
+
for (let i = 0; i < children.length; i++) {
|
|
53
|
+
const flexGrow = children[i].flex ?? 0;
|
|
54
|
+
if (flexGrow > 0) {
|
|
55
|
+
const raw = totalFlex > 0 ? Math.floor((flexGrow / totalFlex) * remaining) : 0;
|
|
56
|
+
sizes[i] = clampSize(raw, children[i].minSize, children[i].maxSize);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return children.map((child, i) => ({
|
|
60
|
+
allocatedSize: sizes[i],
|
|
61
|
+
crossSize: crossAxisTotal,
|
|
62
|
+
child,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
function clampSize(size, min, max) {
|
|
66
|
+
let result = size;
|
|
67
|
+
if (min !== undefined)
|
|
68
|
+
result = Math.max(result, min);
|
|
69
|
+
if (max !== undefined)
|
|
70
|
+
result = Math.min(result, max);
|
|
71
|
+
return Math.max(0, result);
|
|
72
|
+
}
|
|
73
|
+
function measureContent(content, isRow) {
|
|
74
|
+
if (typeof content === 'function') {
|
|
75
|
+
// Can't measure a render function — treat as 0 (must use flex or basis)
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
const lines = content.split('\n');
|
|
79
|
+
if (isRow) {
|
|
80
|
+
// Width = max visible line width
|
|
81
|
+
return Math.max(0, ...lines.map(visualWidth));
|
|
82
|
+
}
|
|
83
|
+
// Height = number of lines
|
|
84
|
+
return lines.length;
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Rendering
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
function renderContent(child, width, height) {
|
|
90
|
+
if (typeof child.content === 'function') {
|
|
91
|
+
return child.content(width, height);
|
|
92
|
+
}
|
|
93
|
+
return child.content;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Clip/pad each content line to exact width. Does NOT pad height —
|
|
97
|
+
* that's handled by alignCross.
|
|
98
|
+
*/
|
|
99
|
+
function fitWidth(content, width, align = 'start') {
|
|
100
|
+
const lines = content.split('\n');
|
|
101
|
+
return lines.map((line) => {
|
|
102
|
+
const vis = visualWidth(line);
|
|
103
|
+
if (vis > width) {
|
|
104
|
+
return clipToWidth(line, width);
|
|
105
|
+
}
|
|
106
|
+
const padding = Math.max(0, width - vis);
|
|
107
|
+
switch (align) {
|
|
108
|
+
case 'start':
|
|
109
|
+
return line + ' '.repeat(padding);
|
|
110
|
+
case 'end':
|
|
111
|
+
return ' '.repeat(padding) + line;
|
|
112
|
+
case 'center': {
|
|
113
|
+
const before = Math.floor(padding / 2);
|
|
114
|
+
const after = padding - before;
|
|
115
|
+
return ' '.repeat(before) + line + ' '.repeat(after);
|
|
116
|
+
}
|
|
117
|
+
default: {
|
|
118
|
+
const _exhaustive = align;
|
|
119
|
+
throw new Error(`Unknown alignment: ${_exhaustive}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function clipToWidth(str, maxWidth) {
|
|
125
|
+
let visible = 0;
|
|
126
|
+
let result = '';
|
|
127
|
+
let inEscape = false;
|
|
128
|
+
for (let i = 0; i < str.length; i++) {
|
|
129
|
+
const ch = str[i];
|
|
130
|
+
if (ch === '\x1b') {
|
|
131
|
+
inEscape = true;
|
|
132
|
+
result += ch;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (inEscape) {
|
|
136
|
+
result += ch;
|
|
137
|
+
if (ch === 'm')
|
|
138
|
+
inEscape = false;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (visible >= maxWidth) {
|
|
142
|
+
result += '\x1b[0m';
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
result += ch;
|
|
146
|
+
visible++;
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Align content lines along the cross axis.
|
|
152
|
+
*/
|
|
153
|
+
function alignCross(lines, totalCrossSize, align, width) {
|
|
154
|
+
if (lines.length >= totalCrossSize)
|
|
155
|
+
return lines.slice(0, totalCrossSize);
|
|
156
|
+
const emptyLine = ' '.repeat(Math.max(0, width));
|
|
157
|
+
const padding = totalCrossSize - lines.length;
|
|
158
|
+
switch (align) {
|
|
159
|
+
case 'start':
|
|
160
|
+
return [...lines, ...Array.from({ length: padding }).fill(emptyLine)];
|
|
161
|
+
case 'end':
|
|
162
|
+
return [...Array.from({ length: padding }).fill(emptyLine), ...lines];
|
|
163
|
+
case 'center': {
|
|
164
|
+
const before = Math.floor(padding / 2);
|
|
165
|
+
const after = padding - before;
|
|
166
|
+
return [
|
|
167
|
+
...Array.from({ length: before }).fill(emptyLine),
|
|
168
|
+
...lines,
|
|
169
|
+
...Array.from({ length: after }).fill(emptyLine),
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
// flex() — main API
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
/**
|
|
178
|
+
* Lay out children using flexbox-style rules.
|
|
179
|
+
*
|
|
180
|
+
* Row direction: children are placed side-by-side horizontally.
|
|
181
|
+
* Column direction: children are stacked vertically.
|
|
182
|
+
*
|
|
183
|
+
* ```ts
|
|
184
|
+
* // Sidebar + main content
|
|
185
|
+
* flex({ direction: 'row', width: 80, height: 24, gap: 1 },
|
|
186
|
+
* { basis: 20, content: sidebarContent },
|
|
187
|
+
* { flex: 1, content: (w, h) => renderMain(w, h) },
|
|
188
|
+
* )
|
|
189
|
+
*
|
|
190
|
+
* // Header + body + footer
|
|
191
|
+
* flex({ direction: 'column', width: 80, height: 24 },
|
|
192
|
+
* { basis: 1, content: headerLine },
|
|
193
|
+
* { flex: 1, content: (w, h) => renderBody(w, h) },
|
|
194
|
+
* { basis: 1, content: statusLine },
|
|
195
|
+
* )
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export function flex(options, ...children) {
|
|
199
|
+
const { direction = 'row' } = options;
|
|
200
|
+
const width = Math.max(0, Math.floor(options.width));
|
|
201
|
+
const height = Math.max(0, Math.floor(options.height));
|
|
202
|
+
const gap = Math.max(0, Math.floor(options.gap ?? 0));
|
|
203
|
+
const isRow = direction === 'row';
|
|
204
|
+
const mainAxisTotal = isRow ? width : height;
|
|
205
|
+
const crossAxisTotal = isRow ? height : width;
|
|
206
|
+
if (children.length === 0)
|
|
207
|
+
return '';
|
|
208
|
+
const resolved = computeSizes(children, mainAxisTotal, crossAxisTotal, gap, isRow);
|
|
209
|
+
if (isRow) {
|
|
210
|
+
return renderRow(resolved, height, gap);
|
|
211
|
+
}
|
|
212
|
+
return renderColumn(resolved, width, height, gap);
|
|
213
|
+
}
|
|
214
|
+
function renderRow(items, totalHeight, gap) {
|
|
215
|
+
// Render each child into a column of lines
|
|
216
|
+
const columns = [];
|
|
217
|
+
for (const item of items) {
|
|
218
|
+
const childWidth = item.allocatedSize;
|
|
219
|
+
const rendered = renderContent(item.child, childWidth, totalHeight);
|
|
220
|
+
// In row mode, fitWidth always uses 'start' — align controls cross-axis (vertical) only
|
|
221
|
+
const widthFitted = fitWidth(rendered, childWidth);
|
|
222
|
+
const aligned = alignCross(widthFitted, totalHeight, item.child.align ?? 'start', childWidth);
|
|
223
|
+
columns.push(aligned);
|
|
224
|
+
}
|
|
225
|
+
// Compose columns side-by-side
|
|
226
|
+
const spacer = ' '.repeat(Math.max(0, gap));
|
|
227
|
+
const rows = [];
|
|
228
|
+
for (let r = 0; r < totalHeight; r++) {
|
|
229
|
+
const parts = [];
|
|
230
|
+
for (let c = 0; c < columns.length; c++) {
|
|
231
|
+
parts.push(columns[c][r]);
|
|
232
|
+
}
|
|
233
|
+
rows.push(parts.join(spacer));
|
|
234
|
+
}
|
|
235
|
+
return rows.join('\n');
|
|
236
|
+
}
|
|
237
|
+
function renderColumn(items, totalWidth, totalHeight, gap) {
|
|
238
|
+
const lines = [];
|
|
239
|
+
for (let i = 0; i < items.length; i++) {
|
|
240
|
+
const item = items[i];
|
|
241
|
+
const childHeight = item.allocatedSize;
|
|
242
|
+
const rendered = renderContent(item.child, totalWidth, childHeight);
|
|
243
|
+
const widthFitted = fitWidth(rendered, totalWidth, item.child.align ?? 'start');
|
|
244
|
+
const aligned = alignCross(widthFitted, childHeight, 'start', totalWidth);
|
|
245
|
+
lines.push(...aligned);
|
|
246
|
+
// Add gap between items
|
|
247
|
+
if (i < items.length - 1 && gap > 0) {
|
|
248
|
+
const spacer = ' '.repeat(Math.max(0, totalWidth));
|
|
249
|
+
for (let g = 0; g < gap; g++) {
|
|
250
|
+
lines.push(spacer);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Pad to fill totalHeight if needed
|
|
255
|
+
const emptyLine = ' '.repeat(Math.max(0, totalWidth));
|
|
256
|
+
while (lines.length < totalHeight) {
|
|
257
|
+
lines.push(emptyLine);
|
|
258
|
+
}
|
|
259
|
+
return lines.slice(0, totalHeight).join('\n');
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=flex.js.map
|
package/dist/flex.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flex.js","sourceRoot":"","sources":["../src/flex.ts"],"names":[],"mappings":"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"}
|
package/dist/help.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generate help views from registered keybindings.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* const kb = createKeyMap<Msg>()
|
|
6
|
+
* .bind('q', 'Quit', quitMsg)
|
|
7
|
+
* .group('Navigation', g => g
|
|
8
|
+
* .bind('j', 'Down', downMsg)
|
|
9
|
+
* .bind('k', 'Up', upMsg)
|
|
10
|
+
* );
|
|
11
|
+
*
|
|
12
|
+
* helpView(kb) // full grouped help
|
|
13
|
+
* helpShort(kb) // single-line summary
|
|
14
|
+
* helpFor(kb, 'Nav') // filter by group prefix
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import type { BindingInfo } from './keybindings.js';
|
|
18
|
+
/** Anything that can list its bindings (satisfied by KeyMap). */
|
|
19
|
+
export interface BindingSource {
|
|
20
|
+
bindings(): readonly BindingInfo[];
|
|
21
|
+
}
|
|
22
|
+
export interface HelpOptions {
|
|
23
|
+
/** Only show enabled bindings (default: true). */
|
|
24
|
+
enabledOnly?: boolean;
|
|
25
|
+
/** Filter to bindings in groups matching this prefix. */
|
|
26
|
+
groupFilter?: string;
|
|
27
|
+
/** Separator between key and description (default: " "). */
|
|
28
|
+
separator?: string;
|
|
29
|
+
/** Title shown at the top (default: none). */
|
|
30
|
+
title?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Full help view — grouped, multi-line.
|
|
34
|
+
*
|
|
35
|
+
* ```
|
|
36
|
+
* Navigation
|
|
37
|
+
* j Down
|
|
38
|
+
* k Up
|
|
39
|
+
*
|
|
40
|
+
* General
|
|
41
|
+
* q Quit
|
|
42
|
+
* ? Toggle help
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function helpView(keymap: BindingSource, options?: HelpOptions): string;
|
|
46
|
+
/**
|
|
47
|
+
* Short, single-line help — keys only, no groups.
|
|
48
|
+
*
|
|
49
|
+
* ```
|
|
50
|
+
* q Quit • j Down • k Up • ? Help
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function helpShort(keymap: BindingSource, options?: Pick<HelpOptions, 'enabledOnly' | 'groupFilter'>): string;
|
|
54
|
+
/**
|
|
55
|
+
* Filter help to a specific group (convenience wrapper).
|
|
56
|
+
*/
|
|
57
|
+
export declare function helpFor(keymap: BindingSource, groupPrefix: string, options?: HelpOptions): string;
|
|
58
|
+
//# sourceMappingURL=help.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,IAAI,SAAS,WAAW,EAAE,CAAC;CACpC;AAMD,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAoD7E;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,aAAa,GAAG,aAAa,CAAC,GAAG,MAAM,CAenH;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAEjG"}
|
package/dist/help.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generate help views from registered keybindings.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* const kb = createKeyMap<Msg>()
|
|
6
|
+
* .bind('q', 'Quit', quitMsg)
|
|
7
|
+
* .group('Navigation', g => g
|
|
8
|
+
* .bind('j', 'Down', downMsg)
|
|
9
|
+
* .bind('k', 'Up', upMsg)
|
|
10
|
+
* );
|
|
11
|
+
*
|
|
12
|
+
* helpView(kb) // full grouped help
|
|
13
|
+
* helpShort(kb) // single-line summary
|
|
14
|
+
* helpFor(kb, 'Nav') // filter by group prefix
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { formatKeyCombo } from './keybindings.js';
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Help views
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* Full help view — grouped, multi-line.
|
|
23
|
+
*
|
|
24
|
+
* ```
|
|
25
|
+
* Navigation
|
|
26
|
+
* j Down
|
|
27
|
+
* k Up
|
|
28
|
+
*
|
|
29
|
+
* General
|
|
30
|
+
* q Quit
|
|
31
|
+
* ? Toggle help
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function helpView(keymap, options) {
|
|
35
|
+
const enabledOnly = options?.enabledOnly ?? true;
|
|
36
|
+
const sep = options?.separator ?? ' ';
|
|
37
|
+
const groupFilter = options?.groupFilter;
|
|
38
|
+
let all = keymap.bindings();
|
|
39
|
+
if (enabledOnly)
|
|
40
|
+
all = all.filter((b) => b.enabled);
|
|
41
|
+
if (groupFilter !== undefined) {
|
|
42
|
+
all = all.filter((b) => b.group.toLowerCase().startsWith(groupFilter.toLowerCase()));
|
|
43
|
+
}
|
|
44
|
+
if (all.length === 0)
|
|
45
|
+
return '';
|
|
46
|
+
// Group by group name
|
|
47
|
+
const groups = new Map();
|
|
48
|
+
for (const b of all) {
|
|
49
|
+
const group = b.group || 'General';
|
|
50
|
+
let list = groups.get(group);
|
|
51
|
+
if (!list) {
|
|
52
|
+
list = [];
|
|
53
|
+
groups.set(group, list);
|
|
54
|
+
}
|
|
55
|
+
list.push(b);
|
|
56
|
+
}
|
|
57
|
+
// Find max key width for alignment
|
|
58
|
+
const allFormatted = all.map((b) => formatKeyCombo(b.combo));
|
|
59
|
+
const maxKeyLen = Math.max(...allFormatted.map((k) => k.length));
|
|
60
|
+
const lines = [];
|
|
61
|
+
if (options?.title) {
|
|
62
|
+
lines.push(options.title);
|
|
63
|
+
lines.push('');
|
|
64
|
+
}
|
|
65
|
+
let first = true;
|
|
66
|
+
for (const [groupName, bindings] of groups) {
|
|
67
|
+
if (!first)
|
|
68
|
+
lines.push('');
|
|
69
|
+
first = false;
|
|
70
|
+
lines.push(groupName);
|
|
71
|
+
for (const b of bindings) {
|
|
72
|
+
const key = formatKeyCombo(b.combo).padEnd(maxKeyLen);
|
|
73
|
+
lines.push(` ${key}${sep}${b.description}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return lines.join('\n');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Short, single-line help — keys only, no groups.
|
|
80
|
+
*
|
|
81
|
+
* ```
|
|
82
|
+
* q Quit • j Down • k Up • ? Help
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export function helpShort(keymap, options) {
|
|
86
|
+
const enabledOnly = options?.enabledOnly ?? true;
|
|
87
|
+
const groupFilter = options?.groupFilter;
|
|
88
|
+
let all = keymap.bindings();
|
|
89
|
+
if (enabledOnly)
|
|
90
|
+
all = all.filter((b) => b.enabled);
|
|
91
|
+
if (groupFilter !== undefined) {
|
|
92
|
+
all = all.filter((b) => b.group.toLowerCase().startsWith(groupFilter.toLowerCase()));
|
|
93
|
+
}
|
|
94
|
+
return all
|
|
95
|
+
.map((b) => `${formatKeyCombo(b.combo)} ${b.description}`)
|
|
96
|
+
.join(' • ');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Filter help to a specific group (convenience wrapper).
|
|
100
|
+
*/
|
|
101
|
+
export function helpFor(keymap, groupPrefix, options) {
|
|
102
|
+
return helpView(keymap, { ...options, groupFilter: groupPrefix });
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=help.js.map
|
package/dist/help.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
export type { App, Cmd, KeyMsg, QuitSignal, RunOptions } from './types.js';
|
|
1
|
+
export type { App, Cmd, KeyMsg, ResizeMsg, QuitSignal, RunOptions } from './types.js';
|
|
2
2
|
export { QUIT } from './types.js';
|
|
3
3
|
export { parseKey } from './keys.js';
|
|
4
|
-
export { enterScreen, exitScreen, clearAndHome, renderFrame, ENTER_ALT_SCREEN, EXIT_ALT_SCREEN, HIDE_CURSOR, SHOW_CURSOR, CLEAR_SCREEN, CLEAR_TO_END, CLEAR_LINE, HOME, } from './screen.js';
|
|
4
|
+
export { enterScreen, exitScreen, clearAndHome, renderFrame, ENTER_ALT_SCREEN, EXIT_ALT_SCREEN, HIDE_CURSOR, SHOW_CURSOR, WRAP_DISABLE, WRAP_ENABLE, CLEAR_SCREEN, CLEAR_TO_END, CLEAR_LINE_TO_END, CLEAR_LINE, HOME, } from './screen.js';
|
|
5
5
|
export { quit, tick, batch } from './commands.js';
|
|
6
6
|
export { run } from './runtime.js';
|
|
7
|
+
export { type BusMsg, type EventBus, createEventBus, } from './eventbus.js';
|
|
7
8
|
export { vstack, hstack } from './layout.js';
|
|
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
|
+
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';
|
|
12
|
+
export { type Position, type SpringTrackDef, type TweenTrackDef, type TrackDef, type TimelineState, type TimelineBuilder, type Timeline, timeline, } from './timeline.js';
|
|
13
|
+
export { type FlexOptions, type FlexChild, flex, } from './flex.js';
|
|
14
|
+
export { type KeyCombo, type BindingInfo, type KeyMap, type KeyMapGroup, createKeyMap, parseKeyCombo, formatKeyCombo, } from './keybindings.js';
|
|
15
|
+
export { type BindingSource, type HelpOptions, helpView, helpShort, helpFor, } from './help.js';
|
|
16
|
+
export { type InputHandler, type LayerOptions, type LayerInfo, type InputStack, createInputStack, } from './inputstack.js';
|
|
8
17
|
//# sourceMappingURL=index.d.ts.map
|