@flyingrobots/bijou-tui 3.1.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +159 -21
- package/README.md +205 -39
- package/dist/app-frame-actions.d.ts +5 -5
- package/dist/app-frame-actions.d.ts.map +1 -1
- package/dist/app-frame-actions.js +74 -9
- package/dist/app-frame-actions.js.map +1 -1
- package/dist/app-frame-i18n.d.ts +12 -0
- package/dist/app-frame-i18n.d.ts.map +1 -0
- package/dist/app-frame-i18n.js +92 -0
- package/dist/app-frame-i18n.js.map +1 -0
- package/dist/app-frame-layers.d.ts +29 -0
- package/dist/app-frame-layers.d.ts.map +1 -0
- package/dist/app-frame-layers.js +104 -0
- package/dist/app-frame-layers.js.map +1 -0
- package/dist/app-frame-palette.d.ts +6 -2
- package/dist/app-frame-palette.d.ts.map +1 -1
- package/dist/app-frame-palette.js +42 -10
- package/dist/app-frame-palette.js.map +1 -1
- package/dist/app-frame-render.d.ts +28 -14
- package/dist/app-frame-render.d.ts.map +1 -1
- package/dist/app-frame-render.js +285 -138
- package/dist/app-frame-render.js.map +1 -1
- package/dist/app-frame-types.d.ts +41 -21
- package/dist/app-frame-types.d.ts.map +1 -1
- package/dist/app-frame-types.js +8 -6
- package/dist/app-frame-types.js.map +1 -1
- package/dist/app-frame-utils.d.ts +8 -3
- package/dist/app-frame-utils.d.ts.map +1 -1
- package/dist/app-frame-utils.js +42 -27
- package/dist/app-frame-utils.js.map +1 -1
- package/dist/app-frame.d.ts +128 -12
- package/dist/app-frame.d.ts.map +1 -1
- package/dist/app-frame.js +1212 -91
- package/dist/app-frame.js.map +1 -1
- package/dist/browsable-list.d.ts +20 -1
- package/dist/browsable-list.d.ts.map +1 -1
- package/dist/browsable-list.js +48 -10
- package/dist/browsable-list.js.map +1 -1
- package/dist/collection-surface.d.ts +8 -0
- package/dist/collection-surface.d.ts.map +1 -0
- package/dist/collection-surface.js +41 -0
- package/dist/collection-surface.js.map +1 -0
- package/dist/command-palette.d.ts +17 -1
- package/dist/command-palette.d.ts.map +1 -1
- package/dist/command-palette.js +50 -20
- package/dist/command-palette.js.map +1 -1
- package/dist/commands.js +1 -1
- package/dist/commands.js.map +1 -1
- package/dist/css/text-style.d.ts +2 -1
- package/dist/css/text-style.d.ts.map +1 -1
- package/dist/css/text-style.js +33 -0
- package/dist/css/text-style.js.map +1 -1
- package/dist/design-language.d.ts +49 -0
- package/dist/design-language.d.ts.map +1 -0
- package/dist/design-language.js +70 -0
- package/dist/design-language.js.map +1 -0
- package/dist/driver.d.ts +6 -1
- package/dist/driver.d.ts.map +1 -1
- package/dist/driver.js +3 -0
- package/dist/driver.js.map +1 -1
- package/dist/eventbus.d.ts.map +1 -1
- package/dist/eventbus.js +21 -1
- package/dist/eventbus.js.map +1 -1
- package/dist/file-picker.d.ts +19 -1
- package/dist/file-picker.d.ts.map +1 -1
- package/dist/file-picker.js +47 -20
- package/dist/file-picker.js.map +1 -1
- package/dist/flex.d.ts +35 -1
- package/dist/flex.d.ts.map +1 -1
- package/dist/flex.js +127 -1
- package/dist/flex.js.map +1 -1
- package/dist/focus-area.d.ts +20 -1
- package/dist/focus-area.d.ts.map +1 -1
- package/dist/focus-area.js +107 -12
- package/dist/focus-area.js.map +1 -1
- package/dist/grid.d.ts +10 -0
- package/dist/grid.d.ts.map +1 -1
- package/dist/grid.js +25 -0
- package/dist/grid.js.map +1 -1
- package/dist/help.d.ts +41 -0
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +50 -0
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +23 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -16
- package/dist/index.js.map +1 -1
- package/dist/inspector-drawer.d.ts +36 -0
- package/dist/inspector-drawer.d.ts.map +1 -0
- package/dist/inspector-drawer.js +68 -0
- package/dist/inspector-drawer.js.map +1 -0
- package/dist/layout-node-surface.d.ts +17 -0
- package/dist/layout-node-surface.d.ts.map +1 -0
- package/dist/layout-node-surface.js +61 -0
- package/dist/layout-node-surface.js.map +1 -0
- package/dist/navigable-table.d.ts +16 -1
- package/dist/navigable-table.d.ts.map +1 -1
- package/dist/navigable-table.js +32 -1
- package/dist/navigable-table.js.map +1 -1
- package/dist/notification.d.ts +26 -1
- package/dist/notification.d.ts.map +1 -1
- package/dist/notification.js +294 -41
- package/dist/notification.js.map +1 -1
- package/dist/overlay.d.ts +29 -8
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +248 -137
- package/dist/overlay.js.map +1 -1
- package/dist/pager.d.ts +16 -0
- package/dist/pager.d.ts.map +1 -1
- package/dist/pager.js +61 -1
- package/dist/pager.js.map +1 -1
- package/dist/runtime-engine.d.ts +223 -0
- package/dist/runtime-engine.d.ts.map +1 -0
- package/dist/runtime-engine.js +457 -0
- package/dist/runtime-engine.js.map +1 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +33 -19
- package/dist/runtime.js.map +1 -1
- package/dist/shell-quit.d.ts +12 -0
- package/dist/shell-quit.d.ts.map +1 -0
- package/dist/shell-quit.js +36 -0
- package/dist/shell-quit.js.map +1 -0
- package/dist/split-pane.d.ts +12 -1
- package/dist/split-pane.d.ts.map +1 -1
- package/dist/split-pane.js +31 -1
- package/dist/split-pane.js.map +1 -1
- package/dist/status-bar.d.ts +12 -0
- package/dist/status-bar.d.ts.map +1 -1
- package/dist/status-bar.js +45 -16
- package/dist/status-bar.js.map +1 -1
- package/dist/subapp/mount.d.ts.map +1 -1
- package/dist/subapp/mount.js +3 -0
- package/dist/subapp/mount.js.map +1 -1
- package/dist/surface-layout.d.ts +19 -0
- package/dist/surface-layout.d.ts.map +1 -0
- package/dist/surface-layout.js +87 -0
- package/dist/surface-layout.js.map +1 -0
- package/dist/transition-shaders.d.ts +10 -8
- package/dist/transition-shaders.d.ts.map +1 -1
- package/dist/transition-shaders.js +65 -19
- package/dist/transition-shaders.js.map +1 -1
- package/dist/types.d.ts +21 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -1
- package/dist/view-output.d.ts +5 -4
- package/dist/view-output.d.ts.map +1 -1
- package/dist/view-output.js +37 -29
- package/dist/view-output.js.map +1 -1
- package/dist/viewport.d.ts +30 -1
- package/dist/viewport.d.ts.map +1 -1
- package/dist/viewport.js +77 -1
- package/dist/viewport.js.map +1 -1
- package/package.json +6 -3
- package/dist/layout-v3.d.ts +0 -10
- package/dist/layout-v3.d.ts.map +0 -1
- package/dist/layout-v3.js +0 -35
- package/dist/layout-v3.js.map +0 -1
package/dist/overlay.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Overlay compositing primitives for TUI apps.
|
|
3
3
|
*
|
|
4
4
|
* - `composite()` — paint overlays onto a background string (ANSI-safe)
|
|
5
|
+
* - `compositeSurface()` — paint overlays onto a background surface
|
|
5
6
|
* - `modal()` — centered dialog overlay with title, body, hint
|
|
6
7
|
* - `toast()` — anchored notification overlay with variant icons
|
|
7
8
|
* - `tooltip()` — positioned overlay relative to a target element
|
|
@@ -28,22 +29,26 @@ export interface CompositeOptions {
|
|
|
28
29
|
/** Wrap background lines in dim (ANSI 2m). */
|
|
29
30
|
readonly dim?: boolean;
|
|
30
31
|
}
|
|
32
|
+
/** Structured overlay content accepted by the surface-native overlay family. */
|
|
33
|
+
export type OverlayContent = string | Surface;
|
|
31
34
|
/**
|
|
32
35
|
* Configuration for the {@link modal} overlay.
|
|
33
36
|
*/
|
|
34
37
|
export interface ModalOptions {
|
|
35
38
|
/** Optional title displayed at the top of the modal (bolded when ctx provided). */
|
|
36
39
|
readonly title?: string;
|
|
37
|
-
/** Body content of the modal. */
|
|
38
|
-
readonly body:
|
|
39
|
-
/** Optional hint
|
|
40
|
-
readonly hint?:
|
|
40
|
+
/** Body content of the modal. Accepts plain text or a structured surface. */
|
|
41
|
+
readonly body: OverlayContent;
|
|
42
|
+
/** Optional hint content displayed below the body (muted when ctx provided). */
|
|
43
|
+
readonly hint?: OverlayContent;
|
|
41
44
|
/** Screen width in columns, used for centering. */
|
|
42
45
|
readonly screenWidth: number;
|
|
43
46
|
/** Screen height in rows, used for centering. */
|
|
44
47
|
readonly screenHeight: number;
|
|
45
48
|
/** Preferred minimum width — shorter lines are padded but longer lines are not truncated (default: auto from content). */
|
|
46
49
|
readonly width?: number;
|
|
50
|
+
/** Preferred edge inset from the viewport when the dialog is centered. */
|
|
51
|
+
readonly margin?: number;
|
|
47
52
|
/** Design token for the border color. */
|
|
48
53
|
readonly borderToken?: TokenValue;
|
|
49
54
|
/** Background fill token for the overlay interior. */
|
|
@@ -89,6 +94,22 @@ export interface ToastOptions {
|
|
|
89
94
|
* @returns Composited string with all overlays applied.
|
|
90
95
|
*/
|
|
91
96
|
export declare function composite(background: string, overlays: readonly Overlay[], options?: CompositeOptions): string;
|
|
97
|
+
/**
|
|
98
|
+
* Paint one or more overlays onto a background surface.
|
|
99
|
+
*
|
|
100
|
+
* Overlays are applied in array order, with later overlays painting over
|
|
101
|
+
* earlier ones. String-only overlays are normalized through an explicit
|
|
102
|
+
* ANSI-to-surface bridge at the composition edge.
|
|
103
|
+
*/
|
|
104
|
+
export declare function compositeSurface(background: Surface, overlays: readonly Overlay[], options?: CompositeOptions): Surface;
|
|
105
|
+
/**
|
|
106
|
+
* Paint overlays onto an existing target surface, optionally starting from an
|
|
107
|
+
* existing background surface.
|
|
108
|
+
*
|
|
109
|
+
* When `background` and `target` are the same object, the surface is
|
|
110
|
+
* composited in place without an extra clone.
|
|
111
|
+
*/
|
|
112
|
+
export declare function compositeSurfaceInto(background: Surface, target: Surface, overlays: readonly Overlay[], options?: CompositeOptions): Surface;
|
|
92
113
|
/**
|
|
93
114
|
* Create a centered modal dialog overlay.
|
|
94
115
|
*
|
|
@@ -115,8 +136,8 @@ export type DrawerAnchor = 'left' | 'right' | 'top' | 'bottom';
|
|
|
115
136
|
* Configuration for the {@link drawer} overlay.
|
|
116
137
|
*/
|
|
117
138
|
interface DrawerBaseOptions {
|
|
118
|
-
/** Content
|
|
119
|
-
readonly content:
|
|
139
|
+
/** Content to display inside the drawer. Accepts plain text or a structured surface. */
|
|
140
|
+
readonly content: OverlayContent;
|
|
120
141
|
/** Screen width in columns, used for positioning. */
|
|
121
142
|
readonly screenWidth: number;
|
|
122
143
|
/** Screen height in rows, used for sizing. */
|
|
@@ -179,8 +200,8 @@ export type TooltipDirection = 'top' | 'bottom' | 'left' | 'right';
|
|
|
179
200
|
* Configuration for the {@link tooltip} overlay.
|
|
180
201
|
*/
|
|
181
202
|
export interface TooltipOptions {
|
|
182
|
-
/** Content
|
|
183
|
-
readonly content:
|
|
203
|
+
/** Content to display inside the tooltip. Accepts plain text or a structured surface. */
|
|
204
|
+
readonly content: OverlayContent;
|
|
184
205
|
/** Row of the target element (0-based). */
|
|
185
206
|
readonly row: number;
|
|
186
207
|
/** Column of the target element (0-based). */
|
package/dist/overlay.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"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"}
|
package/dist/overlay.js
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* Overlay compositing primitives for TUI apps.
|
|
3
3
|
*
|
|
4
4
|
* - `composite()` — paint overlays onto a background string (ANSI-safe)
|
|
5
|
+
* - `compositeSurface()` — paint overlays onto a background surface
|
|
5
6
|
* - `modal()` — centered dialog overlay with title, body, hint
|
|
6
7
|
* - `toast()` — anchored notification overlay with variant icons
|
|
7
8
|
* - `tooltip()` — positioned overlay relative to a target element
|
|
8
9
|
*/
|
|
9
|
-
import {
|
|
10
|
+
import { createSurface, graphemeClusterWidth, parseAnsiToSurface, segmentGraphemes, shouldApplyBg, stripAnsi, surfaceToString, } from '@flyingrobots/bijou';
|
|
10
11
|
import { sliceAnsi, visibleLength, clipToWidth } from './viewport.js';
|
|
12
|
+
import { clampCenteredPosition, resolveOverlayMargin } from './design-language.js';
|
|
11
13
|
// ---------------------------------------------------------------------------
|
|
12
14
|
// Border characters (same as core box.ts)
|
|
13
15
|
// ---------------------------------------------------------------------------
|
|
@@ -78,30 +80,170 @@ export function composite(background, overlays, options) {
|
|
|
78
80
|
}
|
|
79
81
|
return bgLines.join('\n');
|
|
80
82
|
}
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
|
-
// renderBox (shared between modal and toast)
|
|
83
|
-
// ---------------------------------------------------------------------------
|
|
84
83
|
/**
|
|
85
|
-
*
|
|
84
|
+
* Paint one or more overlays onto a background surface.
|
|
86
85
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
86
|
+
* Overlays are applied in array order, with later overlays painting over
|
|
87
|
+
* earlier ones. String-only overlays are normalized through an explicit
|
|
88
|
+
* ANSI-to-surface bridge at the composition edge.
|
|
89
|
+
*/
|
|
90
|
+
export function compositeSurface(background, overlays, options) {
|
|
91
|
+
const result = background.clone();
|
|
92
|
+
return compositeSurfaceInto(result, result, overlays, options);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Paint overlays onto an existing target surface, optionally starting from an
|
|
96
|
+
* existing background surface.
|
|
89
97
|
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* @param bgFill - Optional function to wrap interior content with background color styling.
|
|
93
|
-
* @returns Box string with top/bottom borders and bordered content lines.
|
|
98
|
+
* When `background` and `target` are the same object, the surface is
|
|
99
|
+
* composited in place without an extra clone.
|
|
94
100
|
*/
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
export function compositeSurfaceInto(background, target, overlays, options) {
|
|
102
|
+
if (target !== background) {
|
|
103
|
+
target.clear();
|
|
104
|
+
target.blit(background, 0, 0);
|
|
105
|
+
}
|
|
106
|
+
if (options?.dim) {
|
|
107
|
+
for (const cell of target.cells) {
|
|
108
|
+
if (cell.empty || cell.char === ' ')
|
|
109
|
+
continue;
|
|
110
|
+
const modifiers = cell.modifiers ?? [];
|
|
111
|
+
if (!modifiers.includes('dim')) {
|
|
112
|
+
cell.modifiers = [...modifiers, 'dim'];
|
|
113
|
+
}
|
|
114
|
+
cell.empty = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const overlay of overlays) {
|
|
118
|
+
target.blit(overlay.surface ?? surfaceFromContent(overlay.content), overlay.col, overlay.row);
|
|
119
|
+
}
|
|
120
|
+
return target;
|
|
121
|
+
}
|
|
122
|
+
function styleFromToken(token, ctx) {
|
|
123
|
+
if (!ctx || token == null)
|
|
124
|
+
return {};
|
|
125
|
+
return {
|
|
126
|
+
fg: token.hex,
|
|
127
|
+
bg: token.bg,
|
|
128
|
+
modifiers: token.modifiers ? [...token.modifiers] : undefined,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function backgroundStyleFromToken(token, ctx) {
|
|
132
|
+
if (!ctx || !shouldApplyBg(ctx) || !token?.bg)
|
|
133
|
+
return {};
|
|
134
|
+
return { bg: token.bg };
|
|
135
|
+
}
|
|
136
|
+
function mergeStyles(base, extra) {
|
|
137
|
+
const modifiers = [...(base.modifiers ?? []), ...(extra.modifiers ?? [])];
|
|
138
|
+
return {
|
|
139
|
+
fg: extra.fg ?? base.fg,
|
|
140
|
+
bg: extra.bg ?? base.bg,
|
|
141
|
+
modifiers: modifiers.length > 0 ? Array.from(new Set(modifiers)) : undefined,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function plainSurfaceToString(surface) {
|
|
145
|
+
const lines = [];
|
|
146
|
+
for (let y = 0; y < surface.height; y++) {
|
|
147
|
+
let line = '';
|
|
148
|
+
for (let x = 0; x < surface.width; x++) {
|
|
149
|
+
line += surface.get(x, y).char;
|
|
150
|
+
}
|
|
151
|
+
lines.push(line);
|
|
152
|
+
}
|
|
153
|
+
return lines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
function overlayContentFromSurface(surface, ctx) {
|
|
156
|
+
return ctx ? surfaceToString(surface, ctx.style) : plainSurfaceToString(surface);
|
|
157
|
+
}
|
|
158
|
+
function setStyledCell(surface, x, y, char, style) {
|
|
159
|
+
surface.set(x, y, { char, ...style, empty: false });
|
|
160
|
+
}
|
|
161
|
+
function setStyledGrapheme(surface, x, y, char, style) {
|
|
162
|
+
if (x >= surface.width)
|
|
163
|
+
return 0;
|
|
164
|
+
const width = Math.max(1, graphemeClusterWidth(char));
|
|
165
|
+
setStyledCell(surface, x, y, char, style);
|
|
166
|
+
for (let offset = 1; offset < width && x + offset < surface.width; offset++) {
|
|
167
|
+
setStyledCell(surface, x + offset, y, '', style);
|
|
168
|
+
}
|
|
169
|
+
return width;
|
|
170
|
+
}
|
|
171
|
+
function lineSurface(text, style = {}) {
|
|
172
|
+
if (text.length === 0)
|
|
173
|
+
return createSurface(0, 1);
|
|
174
|
+
const plain = stripAnsi(text);
|
|
175
|
+
const width = Math.max(0, visibleLength(text));
|
|
176
|
+
if (width === 0)
|
|
177
|
+
return createSurface(0, 1);
|
|
178
|
+
if (plain !== text && style.fg == null && style.bg == null && style.modifiers == null) {
|
|
179
|
+
return parseAnsiToSurface(text, width, 1);
|
|
180
|
+
}
|
|
181
|
+
const graphemes = segmentGraphemes(plain);
|
|
182
|
+
const surface = createSurface(width, 1);
|
|
183
|
+
let x = 0;
|
|
184
|
+
for (const grapheme of graphemes) {
|
|
185
|
+
if (x >= width)
|
|
186
|
+
break;
|
|
187
|
+
x += setStyledGrapheme(surface, x, 0, grapheme, style);
|
|
188
|
+
}
|
|
189
|
+
return surface;
|
|
190
|
+
}
|
|
191
|
+
function lineWithInheritedBackground(line, bg) {
|
|
192
|
+
if (bg == null || line.width === 0)
|
|
193
|
+
return line;
|
|
194
|
+
const result = line.clone();
|
|
195
|
+
for (let x = 0; x < result.width; x++) {
|
|
196
|
+
const cell = result.get(x, 0);
|
|
197
|
+
if (cell.empty)
|
|
198
|
+
continue;
|
|
199
|
+
result.set(x, 0, { ...cell, bg: cell.bg ?? bg, empty: false });
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
function surfaceRows(surface, maxWidth) {
|
|
204
|
+
const width = maxWidth != null ? Math.max(0, Math.min(surface.width, maxWidth)) : surface.width;
|
|
205
|
+
if (surface.height <= 0)
|
|
206
|
+
return [createSurface(width, 1)];
|
|
207
|
+
const rows = [];
|
|
208
|
+
for (let y = 0; y < surface.height; y++) {
|
|
209
|
+
const row = createSurface(width, 1);
|
|
210
|
+
if (width > 0)
|
|
211
|
+
row.blit(surface, 0, 0, 0, y, width, 1);
|
|
212
|
+
rows.push(row);
|
|
213
|
+
}
|
|
214
|
+
return rows;
|
|
215
|
+
}
|
|
216
|
+
function contentLines(content, maxWidth) {
|
|
217
|
+
if (typeof content === 'string') {
|
|
218
|
+
return content.split('\n').map((line) => lineSurface(maxWidth != null ? clipToWidth(line, maxWidth) : line));
|
|
219
|
+
}
|
|
220
|
+
return surfaceRows(content, maxWidth);
|
|
221
|
+
}
|
|
222
|
+
function renderBoxSurface(lines, borderStyle, fillStyle, innerWidthOverride) {
|
|
223
|
+
const innerWidth = innerWidthOverride ?? lines.reduce((max, line) => Math.max(max, line.width), 0);
|
|
224
|
+
const width = innerWidth + 4;
|
|
225
|
+
const height = lines.length + 2;
|
|
226
|
+
const surface = createSurface(width, height);
|
|
227
|
+
setStyledCell(surface, 0, 0, BORDER.tl, borderStyle);
|
|
228
|
+
for (let x = 1; x < width - 1; x++)
|
|
229
|
+
setStyledCell(surface, x, 0, BORDER.h, borderStyle);
|
|
230
|
+
setStyledCell(surface, width - 1, 0, BORDER.tr, borderStyle);
|
|
231
|
+
setStyledCell(surface, 0, height - 1, BORDER.bl, borderStyle);
|
|
232
|
+
for (let x = 1; x < width - 1; x++)
|
|
233
|
+
setStyledCell(surface, x, height - 1, BORDER.h, borderStyle);
|
|
234
|
+
setStyledCell(surface, width - 1, height - 1, BORDER.br, borderStyle);
|
|
235
|
+
for (let i = 0; i < lines.length; i++) {
|
|
236
|
+
const y = i + 1;
|
|
237
|
+
setStyledCell(surface, 0, y, BORDER.v, borderStyle);
|
|
238
|
+
for (let x = 1; x < width - 1; x++)
|
|
239
|
+
setStyledCell(surface, x, y, ' ', fillStyle);
|
|
240
|
+
setStyledCell(surface, width - 1, y, BORDER.v, borderStyle);
|
|
241
|
+
const line = lineWithInheritedBackground(lines[i], fillStyle.bg);
|
|
242
|
+
if (line.width > 0 && innerWidth > 0) {
|
|
243
|
+
surface.blit(line, 2, y, 0, 0, Math.min(line.width, innerWidth), 1);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return surface;
|
|
105
247
|
}
|
|
106
248
|
// ---------------------------------------------------------------------------
|
|
107
249
|
// modal()
|
|
@@ -117,41 +259,25 @@ function renderBox(lines, borderColor, bgFill) {
|
|
|
117
259
|
*/
|
|
118
260
|
export function modal(options) {
|
|
119
261
|
const { title, body, hint, screenWidth, screenHeight, ctx } = options;
|
|
120
|
-
const
|
|
262
|
+
const lines = [];
|
|
121
263
|
if (title != null) {
|
|
122
|
-
|
|
123
|
-
contentLines.push(titleText, '');
|
|
264
|
+
lines.push(lineSurface(title, ctx ? { modifiers: ['bold'] } : {}), createSurface(0, 1));
|
|
124
265
|
}
|
|
125
|
-
|
|
266
|
+
lines.push(...contentLines(body));
|
|
126
267
|
if (hint != null) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// If width override, constrain inner width
|
|
134
|
-
if (options.width != null) {
|
|
135
|
-
const targetInner = options.width - 4; // border + padding
|
|
136
|
-
// Pad short lines, but don't truncate (user controls width)
|
|
137
|
-
for (let i = 0; i < contentLines.length; i++) {
|
|
138
|
-
const vis = visibleLength(contentLines[i]);
|
|
139
|
-
if (vis < targetInner) {
|
|
140
|
-
contentLines[i] = contentLines[i] + ' '.repeat(targetInner - vis);
|
|
141
|
-
}
|
|
268
|
+
lines.push(createSurface(0, 1));
|
|
269
|
+
if (typeof hint === 'string') {
|
|
270
|
+
lines.push(lineSurface(hint, styleFromToken(ctx?.semantic('muted'), ctx)));
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
lines.push(...surfaceRows(hint));
|
|
142
274
|
}
|
|
143
275
|
}
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
const boxLines = boxStr.split('\n');
|
|
150
|
-
const boxHeight = boxLines.length;
|
|
151
|
-
const boxWidth = visibleLength(boxLines[0]);
|
|
152
|
-
const row = Math.max(0, Math.floor((screenHeight - boxHeight) / 2));
|
|
153
|
-
const col = Math.max(0, Math.floor((screenWidth - boxWidth) / 2));
|
|
154
|
-
return { content: boxStr, row, col };
|
|
276
|
+
const surface = renderBoxSurface(lines, styleFromToken(options.borderToken, ctx), backgroundStyleFromToken(options.bgToken, ctx), options.width != null ? Math.max(0, options.width - 4) : undefined);
|
|
277
|
+
const margin = resolveOverlayMargin(screenWidth, screenHeight, options.margin);
|
|
278
|
+
const row = clampCenteredPosition(screenHeight, surface.height, margin);
|
|
279
|
+
const col = clampCenteredPosition(screenWidth, surface.width, margin);
|
|
280
|
+
return { content: overlayContentFromSurface(surface, ctx), surface, row, col };
|
|
155
281
|
}
|
|
156
282
|
// ---------------------------------------------------------------------------
|
|
157
283
|
// toast()
|
|
@@ -178,44 +304,34 @@ const TOAST_BORDER = {
|
|
|
178
304
|
* @returns Overlay positioned at the specified screen corner.
|
|
179
305
|
*/
|
|
180
306
|
export function toast(options) {
|
|
181
|
-
const { message, variant = 'info', anchor = 'bottom-right', screenWidth, screenHeight, margin
|
|
307
|
+
const { message, variant = 'info', anchor = 'bottom-right', screenWidth, screenHeight, margin, ctx, } = options;
|
|
308
|
+
const resolvedMargin = resolveOverlayMargin(screenWidth, screenHeight, margin);
|
|
182
309
|
const icon = TOAST_ICONS[variant];
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
line = ctx.style.styled(ctx.semantic(variant), line);
|
|
186
|
-
}
|
|
187
|
-
const borderKey = TOAST_BORDER[variant];
|
|
188
|
-
const borderColor = ctx
|
|
189
|
-
? (s) => ctx.style.styled(ctx.border(borderKey), s)
|
|
190
|
-
: (s) => s;
|
|
191
|
-
const bgFill = makeBgFill(options.bgToken, ctx);
|
|
192
|
-
const boxStr = renderBox([line], borderColor, bgFill);
|
|
193
|
-
const boxLines = boxStr.split('\n');
|
|
194
|
-
const boxHeight = boxLines.length;
|
|
195
|
-
const boxWidth = visibleLength(boxLines[0]);
|
|
310
|
+
const line = lineSurface(`${icon} ${message}`, styleFromToken(ctx?.semantic(variant), ctx));
|
|
311
|
+
const surface = renderBoxSurface([line], styleFromToken(ctx?.border(TOAST_BORDER[variant]), ctx), backgroundStyleFromToken(options.bgToken, ctx));
|
|
196
312
|
let row;
|
|
197
313
|
let col;
|
|
198
314
|
switch (anchor) {
|
|
199
315
|
case 'top-right':
|
|
200
|
-
row =
|
|
201
|
-
col = screenWidth -
|
|
316
|
+
row = resolvedMargin;
|
|
317
|
+
col = screenWidth - surface.width - resolvedMargin;
|
|
202
318
|
break;
|
|
203
319
|
case 'bottom-right':
|
|
204
|
-
row = screenHeight -
|
|
205
|
-
col = screenWidth -
|
|
320
|
+
row = screenHeight - surface.height - resolvedMargin;
|
|
321
|
+
col = screenWidth - surface.width - resolvedMargin;
|
|
206
322
|
break;
|
|
207
323
|
case 'bottom-left':
|
|
208
|
-
row = screenHeight -
|
|
209
|
-
col =
|
|
324
|
+
row = screenHeight - surface.height - resolvedMargin;
|
|
325
|
+
col = resolvedMargin;
|
|
210
326
|
break;
|
|
211
327
|
case 'top-left':
|
|
212
|
-
row =
|
|
213
|
-
col =
|
|
328
|
+
row = resolvedMargin;
|
|
329
|
+
col = resolvedMargin;
|
|
214
330
|
break;
|
|
215
331
|
}
|
|
216
332
|
row = Math.max(0, row);
|
|
217
333
|
col = Math.max(0, col);
|
|
218
|
-
return { content:
|
|
334
|
+
return { content: overlayContentFromSurface(surface, ctx), surface, row, col };
|
|
219
335
|
}
|
|
220
336
|
// ---------------------------------------------------------------------------
|
|
221
337
|
// drawer()
|
|
@@ -240,51 +356,54 @@ export function drawer(options) {
|
|
|
240
356
|
const dims = resolveDrawerDimensions(options, region);
|
|
241
357
|
const { width, height, row, col } = dims;
|
|
242
358
|
const innerWidth = Math.max(0, width - 4); // border + padding on each side
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
let topInner;
|
|
250
|
-
if (title) {
|
|
251
|
-
const titleText = ctx ? ctx.style.bold(title) : title;
|
|
252
|
-
const titleVis = visibleLength(titleText);
|
|
253
|
-
const remaining = Math.max(0, innerWidth + 2 - titleVis - 2); // +2 for padding around border, -2 for spaces around title
|
|
254
|
-
const leftDash = Math.floor(remaining / 2);
|
|
255
|
-
const rightDash = remaining - leftDash;
|
|
256
|
-
topInner = BORDER.h.repeat(leftDash) + ' ' + titleText + ' ' + BORDER.h.repeat(rightDash);
|
|
359
|
+
const borderStyle = styleFromToken(options.borderToken, ctx);
|
|
360
|
+
const fillStyle = backgroundStyleFromToken(options.bgToken, ctx);
|
|
361
|
+
const titleStyle = ctx ? { modifiers: ['bold'] } : {};
|
|
362
|
+
const surface = createSurface(width, height);
|
|
363
|
+
if (width === 0 || height === 0) {
|
|
364
|
+
return { content: overlayContentFromSurface(surface, ctx), surface, row, col };
|
|
257
365
|
}
|
|
258
|
-
|
|
259
|
-
|
|
366
|
+
for (let x = 0; x < width; x++) {
|
|
367
|
+
const topChar = x === 0 ? BORDER.tl : x === width - 1 ? BORDER.tr : BORDER.h;
|
|
368
|
+
setStyledCell(surface, x, 0, topChar, borderStyle);
|
|
369
|
+
if (height > 1) {
|
|
370
|
+
const bottomChar = x === 0 ? BORDER.bl : x === width - 1 ? BORDER.br : BORDER.h;
|
|
371
|
+
setStyledCell(surface, x, height - 1, bottomChar, borderStyle);
|
|
372
|
+
}
|
|
260
373
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const vis = visibleLength(raw);
|
|
270
|
-
let clipped;
|
|
271
|
-
if (vis > innerWidth) {
|
|
272
|
-
clipped = clipToWidth(raw, innerWidth);
|
|
374
|
+
if (title != null && width > 2) {
|
|
375
|
+
const titleLine = lineSurface(title, titleStyle);
|
|
376
|
+
const spanWidth = Math.min(width - 2, titleLine.width + 2);
|
|
377
|
+
const startX = 1 + Math.max(0, Math.floor(((width - 2) - spanWidth) / 2));
|
|
378
|
+
setStyledCell(surface, startX, 0, ' ', borderStyle);
|
|
379
|
+
const mergedTitleStyle = mergeStyles(borderStyle, titleStyle);
|
|
380
|
+
for (let x = 0; x < Math.min(titleLine.width, Math.max(0, spanWidth - 2)); x++) {
|
|
381
|
+
setStyledCell(surface, startX + 1 + x, 0, titleLine.get(x, 0).char, mergedTitleStyle);
|
|
273
382
|
}
|
|
274
|
-
|
|
275
|
-
|
|
383
|
+
if (spanWidth >= 2) {
|
|
384
|
+
setStyledCell(surface, startX + spanWidth - 1, 0, ' ', borderStyle);
|
|
276
385
|
}
|
|
277
|
-
bodyLines.push(fitLineExact(borderColor(BORDER.v) + fill(' ' + clipped + ' ') + borderColor(BORDER.v), width));
|
|
278
386
|
}
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
387
|
+
const rows = contentLines(content, innerWidth);
|
|
388
|
+
const availableHeight = Math.max(0, height - 2);
|
|
389
|
+
for (let i = 0; i < availableHeight; i++) {
|
|
390
|
+
const y = i + 1;
|
|
391
|
+
if (width >= 1)
|
|
392
|
+
setStyledCell(surface, 0, y, BORDER.v, borderStyle);
|
|
393
|
+
for (let x = 1; x < Math.max(1, width - 1); x++) {
|
|
394
|
+
if (x < width - 1)
|
|
395
|
+
setStyledCell(surface, x, y, ' ', fillStyle);
|
|
396
|
+
}
|
|
397
|
+
if (width >= 2)
|
|
398
|
+
setStyledCell(surface, width - 1, y, BORDER.v, borderStyle);
|
|
399
|
+
const line = lineWithInheritedBackground(rows[i] ?? createSurface(0, 1), fillStyle.bg);
|
|
400
|
+
if (line.width > 0 && innerWidth > 0 && width >= 4) {
|
|
401
|
+
surface.blit(line, 2, y, 0, 0, Math.min(line.width, innerWidth), 1);
|
|
402
|
+
}
|
|
285
403
|
}
|
|
286
404
|
return {
|
|
287
|
-
content:
|
|
405
|
+
content: overlayContentFromSurface(surface, ctx),
|
|
406
|
+
surface,
|
|
288
407
|
row,
|
|
289
408
|
col,
|
|
290
409
|
};
|
|
@@ -348,13 +467,6 @@ function clampRegion(region, screenWidth, screenHeight) {
|
|
|
348
467
|
height: Math.floor(clamp(region.height, 0, maxHeight)),
|
|
349
468
|
};
|
|
350
469
|
}
|
|
351
|
-
/** Clip or pad a single line to exactly `width` visible columns. */
|
|
352
|
-
function fitLineExact(line, width) {
|
|
353
|
-
const target = Math.max(0, width);
|
|
354
|
-
const clipped = clipToWidth(line, target);
|
|
355
|
-
const vis = visibleLength(clipped);
|
|
356
|
-
return clipped + ' '.repeat(Math.max(0, target - vis));
|
|
357
|
-
}
|
|
358
470
|
/** Clamp a number between min and max. */
|
|
359
471
|
function clamp(value, min, max) {
|
|
360
472
|
return Math.max(min, Math.min(max, value));
|
|
@@ -374,38 +486,37 @@ function clamp(value, min, max) {
|
|
|
374
486
|
export function tooltip(options) {
|
|
375
487
|
const { content, row: targetRow, col: targetCol, direction = 'top', screenWidth, screenHeight, borderToken, bgToken, ctx, } = options;
|
|
376
488
|
const maxContentWidth = Math.max(0, screenWidth - 4);
|
|
377
|
-
const
|
|
378
|
-
const
|
|
379
|
-
? (s) => ctx.style.styled(borderToken, s)
|
|
380
|
-
: (s) => s;
|
|
381
|
-
const bgFill = makeBgFill(bgToken, ctx);
|
|
382
|
-
const boxStr = renderBox(contentLines, borderColor, bgFill);
|
|
383
|
-
const boxLines = boxStr.split('\n');
|
|
384
|
-
const boxHeight = boxLines.length;
|
|
385
|
-
const boxWidth = visibleLength(boxLines[0]);
|
|
489
|
+
const lines = contentLines(content, maxContentWidth);
|
|
490
|
+
const surface = renderBoxSurface(lines, styleFromToken(borderToken, ctx), backgroundStyleFromToken(bgToken, ctx));
|
|
386
491
|
let tipRow;
|
|
387
492
|
let tipCol;
|
|
388
493
|
switch (direction) {
|
|
389
494
|
case 'top':
|
|
390
|
-
tipRow = targetRow -
|
|
391
|
-
tipCol = targetCol - Math.floor(
|
|
495
|
+
tipRow = targetRow - surface.height;
|
|
496
|
+
tipCol = targetCol - Math.floor(surface.width / 2);
|
|
392
497
|
break;
|
|
393
498
|
case 'bottom':
|
|
394
499
|
tipRow = targetRow + 1;
|
|
395
|
-
tipCol = targetCol - Math.floor(
|
|
500
|
+
tipCol = targetCol - Math.floor(surface.width / 2);
|
|
396
501
|
break;
|
|
397
502
|
case 'left':
|
|
398
|
-
tipRow = targetRow - Math.floor(
|
|
399
|
-
tipCol = targetCol -
|
|
503
|
+
tipRow = targetRow - Math.floor(surface.height / 2);
|
|
504
|
+
tipCol = targetCol - surface.width;
|
|
400
505
|
break;
|
|
401
506
|
case 'right':
|
|
402
|
-
tipRow = targetRow - Math.floor(
|
|
507
|
+
tipRow = targetRow - Math.floor(surface.height / 2);
|
|
403
508
|
tipCol = targetCol + 1;
|
|
404
509
|
break;
|
|
405
510
|
}
|
|
406
511
|
// Clamp to screen bounds
|
|
407
|
-
tipRow = Math.max(0, Math.min(tipRow, screenHeight -
|
|
408
|
-
tipCol = Math.max(0, Math.min(tipCol, screenWidth -
|
|
409
|
-
return { content:
|
|
512
|
+
tipRow = Math.max(0, Math.min(tipRow, screenHeight - surface.height));
|
|
513
|
+
tipCol = Math.max(0, Math.min(tipCol, screenWidth - surface.width));
|
|
514
|
+
return { content: overlayContentFromSurface(surface, ctx), surface, row: tipRow, col: tipCol };
|
|
515
|
+
}
|
|
516
|
+
function surfaceFromContent(content) {
|
|
517
|
+
const lines = content.split('\n');
|
|
518
|
+
const width = Math.max(1, ...lines.map((line) => visibleLength(line)));
|
|
519
|
+
const height = Math.max(1, lines.length);
|
|
520
|
+
return parseAnsiToSurface(content, width, height);
|
|
410
521
|
}
|
|
411
522
|
//# sourceMappingURL=overlay.js.map
|