@xynogen/pix-ask 0.2.0 → 0.2.2
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/package.json +4 -3
- package/src/frame.ts +30 -6
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-ask",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Pi tool
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Pi tool \u2014 structured questionnaire UI (ask_user)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"typebox": "^1.1.38"
|
|
37
|
+
"typebox": "^1.1.38",
|
|
38
|
+
"@xynogen/pix-pretty": "*"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"@earendil-works/pi-coding-agent": "*",
|
package/src/frame.ts
CHANGED
|
@@ -1,30 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modal frame primitives — inlined from pix-pretty/modal-frame to avoid
|
|
3
|
+
* cross-package subpath imports that break under Node CJS require.
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
7
|
|
|
8
|
+
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
3
10
|
const MIN_WIDTH = 40;
|
|
4
11
|
const MAX_WIDTH = 96;
|
|
5
12
|
const MARGIN = 4;
|
|
6
|
-
|
|
13
|
+
/** 2 border cols + 2 padding spaces */
|
|
7
14
|
const CHROME = 4;
|
|
8
15
|
|
|
16
|
+
// ── Width ─────────────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
/** Clamp terminal width to a sane modal width (40–96 cols). */
|
|
9
19
|
export function modalWidth(termWidth: number): number {
|
|
10
20
|
return Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, termWidth - MARGIN));
|
|
11
21
|
}
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
// ── Frame ─────────────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
export interface FrameOptions {
|
|
14
26
|
width: number;
|
|
15
27
|
lines: string[];
|
|
28
|
+
/** Color function for border glyphs — e.g. `(s) => theme.fg("accent", s)` */
|
|
16
29
|
color: (s: string) => string;
|
|
30
|
+
/** Background fill function — e.g. `(s) => theme.bg("customMessageBg", s)` */
|
|
17
31
|
bg?: (s: string) => string;
|
|
32
|
+
/** Optional pre-styled string rendered as the first content row (tab bar etc.) */
|
|
18
33
|
top?: string;
|
|
19
|
-
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Render a rounded modal box.
|
|
38
|
+
*
|
|
39
|
+
* Returns an array of full-width ANSI strings:
|
|
40
|
+
* ╭──────────────────╮
|
|
41
|
+
* │ [top row] │ ← only if top is set
|
|
42
|
+
* │ content line 1 │
|
|
43
|
+
* │ content line 2 │
|
|
44
|
+
* ╰──────────────────╯
|
|
45
|
+
*/
|
|
46
|
+
export function frameLines(opts: FrameOptions): string[] {
|
|
20
47
|
const { width, lines, color, top } = opts;
|
|
21
48
|
const bg = opts.bg ?? ((s: string) => s);
|
|
22
49
|
const inner = Math.max(1, width - CHROME);
|
|
23
50
|
const dashes = "─".repeat(width - 2);
|
|
24
51
|
|
|
25
|
-
// Derive the bg OPEN sequence so we can re-assert it after any full reset
|
|
26
|
-
// (\x1b[0m) or bg reset (\x1b[49m) embedded in content — theme fg/bold spans
|
|
27
|
-
// emit \x1b[0m, which would otherwise punch transparent holes in the fill.
|
|
28
52
|
const SENTINEL = "\x00";
|
|
29
53
|
const bgOpen = bg(SENTINEL).split(SENTINEL)[0] ?? "";
|
|
30
54
|
const reassert = (s: string): string =>
|