@sigx/terminal-ui 0.5.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 +21 -0
- package/dist/Spinner-JpmBtbPo.js +25 -0
- package/dist/Spinner-JpmBtbPo.js.map +1 -0
- package/dist/buttons/Button.d.ts +8 -0
- package/dist/buttons/index.d.ts +1 -0
- package/dist/buttons/index.js +2 -0
- package/dist/buttons-D5iaiJ6G.js +38 -0
- package/dist/buttons-D5iaiJ6G.js.map +1 -0
- package/dist/data/QRCode.d.ts +17 -0
- package/dist/data/Table.d.ts +11 -0
- package/dist/data/index.d.ts +2 -0
- package/dist/data/index.js +2 -0
- package/dist/data-DKKLsE5K.js +43 -0
- package/dist/data-DKKLsE5K.js.map +1 -0
- package/dist/feedback/Badge.d.ts +14 -0
- package/dist/feedback/ProgressBar.d.ts +31 -0
- package/dist/feedback/Spinner.d.ts +21 -0
- package/dist/feedback/index.d.ts +3 -0
- package/dist/feedback/index.js +3 -0
- package/dist/feedback-1WqdARfx.js +62 -0
- package/dist/feedback-1WqdARfx.js.map +1 -0
- package/dist/forms/Checkbox.d.ts +15 -0
- package/dist/forms/Confirm.d.ts +21 -0
- package/dist/forms/Input.d.ts +15 -0
- package/dist/forms/MultiSelect.d.ts +36 -0
- package/dist/forms/Radio.d.ts +23 -0
- package/dist/forms/Select.d.ts +22 -0
- package/dist/forms/TextArea.d.ts +37 -0
- package/dist/forms/index.d.ts +7 -0
- package/dist/forms/index.js +2 -0
- package/dist/forms-MgpyoQI5.js +399 -0
- package/dist/forms-MgpyoQI5.js.map +1 -0
- package/dist/fx/Banner.d.ts +19 -0
- package/dist/fx/Gradient.d.ts +18 -0
- package/dist/fx/PixelArt.d.ts +16 -0
- package/dist/fx/Shimmer.d.ts +18 -0
- package/dist/fx/blockFont.d.ts +13 -0
- package/dist/fx/index.d.ts +6 -0
- package/dist/fx/index.js +3 -0
- package/dist/fx/paint.d.ts +15 -0
- package/dist/fx/presets.d.ts +14 -0
- package/dist/fx-igWaVCkB.js +452 -0
- package/dist/fx-igWaVCkB.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +13 -0
- package/dist/layout/Card.d.ts +11 -0
- package/dist/layout/index.d.ts +2 -0
- package/dist/layout/index.js +2 -0
- package/dist/layout-CJzMVMDf.js +18 -0
- package/dist/layout-CJzMVMDf.js.map +1 -0
- package/dist/navigation/KeyHints.d.ts +15 -0
- package/dist/navigation/StatusBar.d.ts +9 -0
- package/dist/navigation/SuggestionList.d.ts +22 -0
- package/dist/navigation/Tabs.d.ts +18 -0
- package/dist/navigation/index.d.ts +4 -0
- package/dist/navigation/index.js +2 -0
- package/dist/navigation-B-nI3g0k.js +133 -0
- package/dist/navigation-B-nI3g0k.js.map +1 -0
- package/dist/presets-uqseGRqO.js +31 -0
- package/dist/presets-uqseGRqO.js.map +1 -0
- package/dist/prompts/PromptShell.d.ts +11 -0
- package/dist/prompts/confirm.d.ts +14 -0
- package/dist/prompts/index.d.ts +35 -0
- package/dist/prompts/index.js +2 -0
- package/dist/prompts/multiselect.d.ts +14 -0
- package/dist/prompts/select.d.ts +20 -0
- package/dist/prompts/spinner.d.ts +22 -0
- package/dist/prompts/statics.d.ts +8 -0
- package/dist/prompts/text.d.ts +19 -0
- package/dist/prompts-BLtLCen_.js +381 -0
- package/dist/prompts-BLtLCen_.js.map +1 -0
- package/dist/tasks/LogPanel.d.ts +28 -0
- package/dist/tasks/LogView.d.ts +24 -0
- package/dist/tasks/TaskList.d.ts +26 -0
- package/dist/tasks/index.d.ts +4 -0
- package/dist/tasks/index.js +2 -0
- package/dist/tasks/logStore.d.ts +40 -0
- package/dist/tasks-CdVFFOFs.js +254 -0
- package/dist/tasks-CdVFFOFs.js.map +1 -0
- package/dist/theme/builtins.d.ts +7 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/index.js +2 -0
- package/dist/theme-DASuxf6k.js +150 -0
- package/dist/theme-DASuxf6k.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { t as e } from "./Spinner-JpmBtbPo.js";
|
|
2
|
+
import { CANCEL as t, CANCEL as n, GLYPHS as r, READY_DELAY_MS as i, __setInteractiveOverride as a, enqueue as o, isBackspace as s, isCancel as c, isCancel as l, isCtrlC as u, isDown as d, isEnter as f, isEsc as p, isInteractive as m, isLeft as h, isPrintable as g, isRight as _, isSpace as v, isUp as y, onKey as b, paintToken as x, printStatic as S, renderTerminal as C, resolveColor as w, runPrompt as T } from "@sigx/terminal-zero";
|
|
3
|
+
import { component as E, onMounted as D, onUnmounted as O, signal as k } from "@sigx/runtime-core";
|
|
4
|
+
import { jsx as A, jsxs as j } from "@sigx/runtime-core/jsx-runtime";
|
|
5
|
+
//#region src/prompts/PromptShell.tsx
|
|
6
|
+
function M(e) {
|
|
7
|
+
let t = !!e.error;
|
|
8
|
+
return /* @__PURE__ */ j("box", { children: [
|
|
9
|
+
/* @__PURE__ */ j("box", { children: [/* @__PURE__ */ A("text", {
|
|
10
|
+
color: w(t ? "danger" : "accent"),
|
|
11
|
+
children: t ? "▲" : "◆"
|
|
12
|
+
}), /* @__PURE__ */ j("text", {
|
|
13
|
+
color: w("fg"),
|
|
14
|
+
children: [" ", e.message]
|
|
15
|
+
})] }),
|
|
16
|
+
e.rows,
|
|
17
|
+
/* @__PURE__ */ j("box", { children: [/* @__PURE__ */ A("text", {
|
|
18
|
+
color: w("dim"),
|
|
19
|
+
children: "└ "
|
|
20
|
+
}), t ? /* @__PURE__ */ A("text", {
|
|
21
|
+
color: w("danger"),
|
|
22
|
+
children: e.error
|
|
23
|
+
}) : e.footer ? /* @__PURE__ */ A("text", {
|
|
24
|
+
color: w("dim"),
|
|
25
|
+
children: e.footer
|
|
26
|
+
}) : null] })
|
|
27
|
+
] });
|
|
28
|
+
}
|
|
29
|
+
function N(e) {
|
|
30
|
+
return /* @__PURE__ */ j("box", { children: [/* @__PURE__ */ A("text", {
|
|
31
|
+
color: w("dim"),
|
|
32
|
+
children: "│ "
|
|
33
|
+
}), e] });
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/prompts/text.tsx
|
|
37
|
+
function P(e) {
|
|
38
|
+
return T({
|
|
39
|
+
message: e.message,
|
|
40
|
+
display: (t) => e.mask ? e.mask.repeat([...t].length) : t,
|
|
41
|
+
fallback: () => e.initialValue === void 0 ? { ok: !1 } : {
|
|
42
|
+
ok: !0,
|
|
43
|
+
value: e.initialValue
|
|
44
|
+
},
|
|
45
|
+
build: (n) => /* @__PURE__ */ A(E(() => {
|
|
46
|
+
let r = k({
|
|
47
|
+
value: e.initialValue ?? "",
|
|
48
|
+
error: ""
|
|
49
|
+
}), a = null, o = !1;
|
|
50
|
+
return D(() => {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
o = !0;
|
|
53
|
+
}, i), a = b((i) => {
|
|
54
|
+
if (o) {
|
|
55
|
+
if (p(i) || u(i)) {
|
|
56
|
+
n(t);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (f(i)) {
|
|
60
|
+
let t = e.validate?.(r.value);
|
|
61
|
+
if (t) {
|
|
62
|
+
r.error = t;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
n(r.value);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (s(i)) {
|
|
69
|
+
r.value = r.value.slice(0, -1), r.error = "";
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
g(i) && (r.value += i, r.error = "");
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}), O(() => {
|
|
76
|
+
a?.();
|
|
77
|
+
}), () => {
|
|
78
|
+
let t = e.mask ? e.mask.repeat([...r.value].length) : r.value, n = r.value.length === 0 && e.placeholder ? /* @__PURE__ */ A("text", {
|
|
79
|
+
color: w("dim"),
|
|
80
|
+
children: e.placeholder
|
|
81
|
+
}) : /* @__PURE__ */ A("text", {
|
|
82
|
+
color: w("fg"),
|
|
83
|
+
children: t
|
|
84
|
+
});
|
|
85
|
+
return M({
|
|
86
|
+
message: e.message,
|
|
87
|
+
error: r.error || void 0,
|
|
88
|
+
rows: [N(/* @__PURE__ */ j("text", { children: [n, /* @__PURE__ */ A("text", {
|
|
89
|
+
backgroundColor: w("accent"),
|
|
90
|
+
color: w("accentText"),
|
|
91
|
+
children: " "
|
|
92
|
+
})] }))]
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
}, { name: "TextPrompt" }), {})
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function F(e) {
|
|
99
|
+
return P({
|
|
100
|
+
...e,
|
|
101
|
+
mask: e.mask ?? "•"
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/prompts/select.tsx
|
|
106
|
+
function I(e) {
|
|
107
|
+
return e.label ?? String(e.value);
|
|
108
|
+
}
|
|
109
|
+
function L(e) {
|
|
110
|
+
return T({
|
|
111
|
+
message: e.message,
|
|
112
|
+
display: (t) => {
|
|
113
|
+
let n = e.options.find((e) => e.value === t);
|
|
114
|
+
return n ? I(n) : String(t);
|
|
115
|
+
},
|
|
116
|
+
fallback: () => e.initialValue === void 0 ? { ok: !1 } : {
|
|
117
|
+
ok: !0,
|
|
118
|
+
value: e.initialValue
|
|
119
|
+
},
|
|
120
|
+
build: (n) => /* @__PURE__ */ A(E(() => {
|
|
121
|
+
let a = e.options.findIndex((t) => t.value === e.initialValue), o = k({ cursor: a >= 0 ? a : 0 }), s = null, c = !1;
|
|
122
|
+
return D(() => {
|
|
123
|
+
setTimeout(() => {
|
|
124
|
+
c = !0;
|
|
125
|
+
}, i), s = b((r) => {
|
|
126
|
+
if (c) {
|
|
127
|
+
if (p(r) || u(r)) {
|
|
128
|
+
n(t);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (y(r) || r === "k") {
|
|
132
|
+
o.cursor = o.cursor > 0 ? o.cursor - 1 : e.options.length - 1;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (d(r) || r === "j") {
|
|
136
|
+
o.cursor = o.cursor < e.options.length - 1 ? o.cursor + 1 : 0;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
f(r) && n(e.options[o.cursor].value);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}), O(() => {
|
|
143
|
+
s?.();
|
|
144
|
+
}), () => M({
|
|
145
|
+
message: e.message,
|
|
146
|
+
rows: e.options.map((e, t) => {
|
|
147
|
+
let n = t === o.cursor;
|
|
148
|
+
return N(/* @__PURE__ */ j("text", { children: [
|
|
149
|
+
/* @__PURE__ */ j("text", {
|
|
150
|
+
color: w(n ? "accent" : "faint"),
|
|
151
|
+
children: [n ? r.cursor : " ", " "]
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ A("text", {
|
|
154
|
+
color: w(n ? "accent" : "fg"),
|
|
155
|
+
children: I(e)
|
|
156
|
+
}),
|
|
157
|
+
e.description && n && /* @__PURE__ */ j("text", {
|
|
158
|
+
color: w("dim"),
|
|
159
|
+
children: [" — ", e.description]
|
|
160
|
+
})
|
|
161
|
+
] }));
|
|
162
|
+
})
|
|
163
|
+
});
|
|
164
|
+
}, { name: "SelectPrompt" }), {})
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
//#endregion
|
|
168
|
+
//#region src/prompts/multiselect.tsx
|
|
169
|
+
function R(e) {
|
|
170
|
+
return T({
|
|
171
|
+
message: e.message,
|
|
172
|
+
display: (t) => t.length === 0 ? "none" : e.options.filter((e) => t.includes(e.value)).map(I).join(", "),
|
|
173
|
+
fallback: () => e.initialValues === void 0 ? { ok: !1 } : {
|
|
174
|
+
ok: !0,
|
|
175
|
+
value: e.initialValues
|
|
176
|
+
},
|
|
177
|
+
build: (n) => /* @__PURE__ */ A(E(() => {
|
|
178
|
+
let a = k({
|
|
179
|
+
cursor: 0,
|
|
180
|
+
checked: new Set(e.initialValues ?? []),
|
|
181
|
+
requiredHint: !1
|
|
182
|
+
}), o = null, s = !1, c = () => e.options.filter((e) => a.checked.has(e.value)).map((e) => e.value);
|
|
183
|
+
return D(() => {
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
s = !0;
|
|
186
|
+
}, i), o = b((r) => {
|
|
187
|
+
if (s) {
|
|
188
|
+
if (p(r) || u(r)) {
|
|
189
|
+
n(t);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (y(r) || r === "k") {
|
|
193
|
+
a.cursor = a.cursor > 0 ? a.cursor - 1 : e.options.length - 1;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (d(r) || r === "j") {
|
|
197
|
+
a.cursor = a.cursor < e.options.length - 1 ? a.cursor + 1 : 0;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (v(r)) {
|
|
201
|
+
let t = e.options[a.cursor].value, n = new Set(a.checked);
|
|
202
|
+
n.has(t) ? n.delete(t) : n.add(t), a.checked = n, a.requiredHint = !1;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (r === "a") {
|
|
206
|
+
a.checked = a.checked.size === e.options.length ? /* @__PURE__ */ new Set() : new Set(e.options.map((e) => e.value)), a.requiredHint = !1;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (f(r)) {
|
|
210
|
+
let t = c();
|
|
211
|
+
if (e.required && t.length === 0) {
|
|
212
|
+
a.requiredHint = !0;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
n(t);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}), O(() => {
|
|
220
|
+
o?.();
|
|
221
|
+
}), () => M({
|
|
222
|
+
message: e.message,
|
|
223
|
+
error: a.requiredHint ? "select at least one option (space)" : void 0,
|
|
224
|
+
footer: "space toggle · a all · enter confirm",
|
|
225
|
+
rows: e.options.flatMap((t, n) => {
|
|
226
|
+
let i = n === a.cursor, o = a.checked.has(t.value);
|
|
227
|
+
return [...t.group && t.group !== e.options[n - 1]?.group ? [N(/* @__PURE__ */ A("text", {
|
|
228
|
+
color: w("dim"),
|
|
229
|
+
children: t.group
|
|
230
|
+
}))] : [], N(/* @__PURE__ */ j("text", { children: [
|
|
231
|
+
/* @__PURE__ */ j("text", {
|
|
232
|
+
color: w(i ? "accent" : "faint"),
|
|
233
|
+
children: [i ? r.cursor : " ", " "]
|
|
234
|
+
}),
|
|
235
|
+
/* @__PURE__ */ A("text", {
|
|
236
|
+
color: w(o ? "success" : "line"),
|
|
237
|
+
children: o ? r.checkboxOn : r.checkboxOff
|
|
238
|
+
}),
|
|
239
|
+
/* @__PURE__ */ j("text", {
|
|
240
|
+
color: w(i ? "accent" : "fg"),
|
|
241
|
+
children: [" ", I(t)]
|
|
242
|
+
}),
|
|
243
|
+
t.description && i && /* @__PURE__ */ j("text", {
|
|
244
|
+
color: w("dim"),
|
|
245
|
+
children: [" — ", t.description]
|
|
246
|
+
})
|
|
247
|
+
] }))];
|
|
248
|
+
})
|
|
249
|
+
});
|
|
250
|
+
}, { name: "MultiSelectPrompt" }), {})
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region src/prompts/confirm.tsx
|
|
255
|
+
function z(e) {
|
|
256
|
+
let n = e.active ?? "Yes", a = e.inactive ?? "No";
|
|
257
|
+
return T({
|
|
258
|
+
message: e.message,
|
|
259
|
+
display: (e) => e ? n : a,
|
|
260
|
+
fallback: () => e.initialValue === void 0 ? { ok: !1 } : {
|
|
261
|
+
ok: !0,
|
|
262
|
+
value: e.initialValue
|
|
263
|
+
},
|
|
264
|
+
build: (o) => /* @__PURE__ */ A(E(() => {
|
|
265
|
+
let s = k({ value: e.initialValue ?? !0 }), c = null, l = !1;
|
|
266
|
+
return D(() => {
|
|
267
|
+
setTimeout(() => {
|
|
268
|
+
l = !0;
|
|
269
|
+
}, i), c = b((e) => {
|
|
270
|
+
if (l) {
|
|
271
|
+
if (p(e) || u(e)) {
|
|
272
|
+
o(t);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (e === "y" || e === "Y") {
|
|
276
|
+
o(!0);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (e === "n" || e === "N") {
|
|
280
|
+
o(!1);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (h(e) || _(e) || e === "h" || e === "l") {
|
|
284
|
+
s.value = !s.value;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
f(e) && o(s.value);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}), O(() => {
|
|
291
|
+
c?.();
|
|
292
|
+
}), () => M({
|
|
293
|
+
message: e.message,
|
|
294
|
+
footer: "y / n · enter confirm",
|
|
295
|
+
rows: [N(/* @__PURE__ */ j("text", { children: [
|
|
296
|
+
/* @__PURE__ */ j("text", {
|
|
297
|
+
color: w(s.value ? "accent" : "dim"),
|
|
298
|
+
children: [
|
|
299
|
+
s.value ? r.radioOn : r.radioOff,
|
|
300
|
+
" ",
|
|
301
|
+
n
|
|
302
|
+
]
|
|
303
|
+
}),
|
|
304
|
+
/* @__PURE__ */ A("text", { children: " " }),
|
|
305
|
+
/* @__PURE__ */ j("text", {
|
|
306
|
+
color: w(s.value ? "dim" : "accent"),
|
|
307
|
+
children: [
|
|
308
|
+
s.value ? r.radioOff : r.radioOn,
|
|
309
|
+
" ",
|
|
310
|
+
a
|
|
311
|
+
]
|
|
312
|
+
})
|
|
313
|
+
] }))]
|
|
314
|
+
});
|
|
315
|
+
}, { name: "ConfirmPrompt" }), {})
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region src/prompts/statics.ts
|
|
320
|
+
function B(e) {
|
|
321
|
+
S(`${x("┌", "dim")} ${x(e, "accent")}`);
|
|
322
|
+
}
|
|
323
|
+
function V(e) {
|
|
324
|
+
S(`${x("└", "dim")} ${e}\n`);
|
|
325
|
+
}
|
|
326
|
+
function H(e, t) {
|
|
327
|
+
let n = [];
|
|
328
|
+
t && n.push(`${x("○", "accent")} ${t}`);
|
|
329
|
+
for (let t of e.split("\n")) n.push(`${x("│", "dim")} ${x(t, "dim")}`);
|
|
330
|
+
S(n.join("\n"));
|
|
331
|
+
}
|
|
332
|
+
function U(e) {
|
|
333
|
+
S(`${x("■", "danger")} ${e}`);
|
|
334
|
+
}
|
|
335
|
+
//#endregion
|
|
336
|
+
//#region src/prompts/spinner.tsx
|
|
337
|
+
function W() {
|
|
338
|
+
let t = k({ label: "" }), n = !1, i = null, a = null;
|
|
339
|
+
return {
|
|
340
|
+
start(r = "") {
|
|
341
|
+
if (n) return;
|
|
342
|
+
n = !0, t.label = r;
|
|
343
|
+
let s = new Promise((e) => {
|
|
344
|
+
a = e;
|
|
345
|
+
});
|
|
346
|
+
o(() => n ? (m() && (i = C(/* @__PURE__ */ A(E(() => () => /* @__PURE__ */ A(e, { label: t.label }), { name: "PromptSpinner" }), {}), {
|
|
347
|
+
mode: "inline",
|
|
348
|
+
persistOnExit: !1
|
|
349
|
+
})), s) : Promise.resolve());
|
|
350
|
+
},
|
|
351
|
+
message(e) {
|
|
352
|
+
t.label = e;
|
|
353
|
+
},
|
|
354
|
+
stop(e, o = "success") {
|
|
355
|
+
if (!n) return;
|
|
356
|
+
n = !1, i?.unmount(), i = null;
|
|
357
|
+
let s = e ?? t.label;
|
|
358
|
+
S(`${o === "success" ? x(r.check, "success") : x(r.cross, "danger")} ${s}`), a?.(), a = null;
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
//#endregion
|
|
363
|
+
//#region src/prompts/index.ts
|
|
364
|
+
var G = {
|
|
365
|
+
text: P,
|
|
366
|
+
password: F,
|
|
367
|
+
select: L,
|
|
368
|
+
multiselect: R,
|
|
369
|
+
confirm: z,
|
|
370
|
+
intro: B,
|
|
371
|
+
outro: V,
|
|
372
|
+
note: H,
|
|
373
|
+
cancel: U,
|
|
374
|
+
spinner: W,
|
|
375
|
+
isCancel: c,
|
|
376
|
+
CANCEL: t
|
|
377
|
+
};
|
|
378
|
+
//#endregion
|
|
379
|
+
export { W as a, H as c, R as d, L as f, G as i, V as l, P as m, a as n, U as o, F as p, l as r, B as s, n as t, z as u };
|
|
380
|
+
|
|
381
|
+
//# sourceMappingURL=prompts-BLtLCen_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts-BLtLCen_.js","names":[],"sources":["../src/prompts/PromptShell.tsx","../src/prompts/text.tsx","../src/prompts/select.tsx","../src/prompts/multiselect.tsx","../src/prompts/confirm.tsx","../src/prompts/statics.ts","../src/prompts/spinner.tsx","../src/prompts/index.ts"],"sourcesContent":["/** @jsxImportSource @sigx/runtime-core */\r\n/**\r\n * Shared chrome for the imperative prompts:\r\n *\r\n * ◆ Project name ← state glyph + message\r\n * │ my-sigx-app▌ ← body rows (promptRow)\r\n * └ hint or error ← footer closes the bar\r\n *\r\n * Plain vnode-building helpers (not components) — each prompt composes them\r\n * inside its own render function.\r\n *\r\n * Structural glyphs use the `dim` token, not `line`: inline prompts render on\r\n * the terminal's own background (no themed canvas), where `line` — tuned for\r\n * borders on the theme canvas — can be near-invisible.\r\n */\r\nimport { resolveColor } from '@sigx/terminal-zero';\r\n\r\nexport interface FrameOptions {\r\n message: string;\r\n rows: unknown[];\r\n /** Dim guidance under the bar; replaced by `error` when set. */\r\n footer?: string;\r\n /** Validation error — switches the glyph to ▲ danger. */\r\n error?: string;\r\n}\r\n\r\nexport function promptFrame(opts: FrameOptions) {\r\n const hasError = !!opts.error;\r\n return (\r\n <box>\r\n <box>\r\n <text color={resolveColor(hasError ? 'danger' : 'accent')}>{hasError ? '▲' : '◆'}</text>\r\n <text color={resolveColor('fg')}> {opts.message}</text>\r\n </box>\r\n {opts.rows}\r\n <box>\r\n <text color={resolveColor('dim')}>└ </text>\r\n {hasError\r\n ? <text color={resolveColor('danger')}>{opts.error}</text>\r\n : opts.footer\r\n ? <text color={resolveColor('dim')}>{opts.footer}</text>\r\n : null}\r\n </box>\r\n </box>\r\n );\r\n}\r\n\r\n/** One body row behind the `│` gutter. */\r\nexport function promptRow(children: unknown) {\r\n return (\r\n <box>\r\n <text color={resolveColor('dim')}>│ </text>\r\n {children}\r\n </box>\r\n );\r\n}\r\n","/** @jsxImportSource @sigx/runtime-core */\r\nimport { component, signal, onMounted, onUnmounted } from '@sigx/runtime-core';\r\nimport { onKey, resolveColor, READY_DELAY_MS, CANCEL, runPrompt, isEnter, isEsc, isCtrlC, isBackspace, isPrintable } from '@sigx/terminal-zero';\r\nimport { promptFrame, promptRow } from './PromptShell';\r\n\r\nexport interface TextOptions {\r\n message: string;\r\n placeholder?: string;\r\n initialValue?: string;\r\n /** Return an error string to reject the submit and keep editing. */\r\n validate?: (value: string) => string | undefined;\r\n /** Render every typed character as this string (password fields). */\r\n mask?: string;\r\n}\r\n\r\n/**\r\n * Single-line text prompt. Enter validates and resolves; Esc/Ctrl+C resolve\r\n * the CANCEL symbol (check with isCancel). Editing is end-of-line only.\r\n */\r\nexport function text(opts: TextOptions): Promise<string | typeof CANCEL> {\r\n const display = (v: string) => (opts.mask ? opts.mask.repeat([...v].length) : v);\r\n return runPrompt<string>({\r\n message: opts.message,\r\n display,\r\n fallback: () => (opts.initialValue !== undefined ? { ok: true, value: opts.initialValue } : { ok: false }),\r\n build: (done) => {\r\n const View = component(() => {\r\n const state = signal({ value: opts.initialValue ?? '', error: '' });\r\n let off: (() => void) | null = null;\r\n let ready = false;\r\n\r\n onMounted(() => {\r\n setTimeout(() => { ready = true; }, READY_DELAY_MS);\r\n off = onKey((key) => {\r\n if (!ready) return;\r\n if (isEsc(key) || isCtrlC(key)) {\r\n done(CANCEL);\r\n return;\r\n }\r\n if (isEnter(key)) {\r\n const error = opts.validate?.(state.value);\r\n if (error) {\r\n state.error = error;\r\n return;\r\n }\r\n done(state.value);\r\n return;\r\n }\r\n if (isBackspace(key)) {\r\n state.value = state.value.slice(0, -1);\r\n state.error = '';\r\n return;\r\n }\r\n if (isPrintable(key)) {\r\n state.value += key;\r\n state.error = '';\r\n }\r\n });\r\n });\r\n onUnmounted(() => { off?.(); });\r\n\r\n return () => {\r\n const shown = opts.mask ? opts.mask.repeat([...state.value].length) : state.value;\r\n const body = state.value.length === 0 && opts.placeholder\r\n ? <text color={resolveColor('dim')}>{opts.placeholder}</text>\r\n : <text color={resolveColor('fg')}>{shown}</text>;\r\n return promptFrame({\r\n message: opts.message,\r\n error: state.error || undefined,\r\n rows: [promptRow(\r\n <text>\r\n {body}\r\n <text backgroundColor={resolveColor('accent')} color={resolveColor('accentText')}> </text>\r\n </text>,\r\n )],\r\n });\r\n };\r\n }, { name: 'TextPrompt' });\r\n return <View />;\r\n },\r\n });\r\n}\r\n\r\n/** `text` with masked rendering — the summary shows the mask, never the value. */\r\nexport function password(opts: Omit<TextOptions, 'mask' | 'placeholder'> & { mask?: string }): Promise<string | typeof CANCEL> {\r\n return text({ ...opts, mask: opts.mask ?? '•' });\r\n}\r\n","/** @jsxImportSource @sigx/runtime-core */\r\nimport { component, signal, onMounted, onUnmounted } from '@sigx/runtime-core';\r\nimport { onKey, resolveColor, GLYPHS, READY_DELAY_MS, CANCEL, runPrompt, isEnter, isEsc, isCtrlC, isUp, isDown } from '@sigx/terminal-zero';\r\nimport { promptFrame, promptRow } from './PromptShell';\r\n\r\nexport interface PromptOption<T> {\r\n value: T;\r\n /** Defaults to String(value). */\r\n label?: string;\r\n description?: string;\r\n /**\r\n * Section header rendered above this option when it differs from the\r\n * previous option's group (multiselect only; pre-sort options by group).\r\n */\r\n group?: string;\r\n}\r\n\r\nexport function optionLabel<T>(option: PromptOption<T>): string {\r\n return option.label ?? String(option.value);\r\n}\r\n\r\nexport interface SelectOptions<T> {\r\n message: string;\r\n options: PromptOption<T>[];\r\n initialValue?: T;\r\n}\r\n\r\n/** Single-choice prompt: ↑/k ↓/j move (wrapping), Enter resolves the value. */\r\nexport function select<T = string>(opts: SelectOptions<T>): Promise<T | typeof CANCEL> {\r\n const display = (v: T) => {\r\n const hit = opts.options.find((o) => o.value === v);\r\n return hit ? optionLabel(hit) : String(v);\r\n };\r\n return runPrompt<T>({\r\n message: opts.message,\r\n display,\r\n fallback: () => (opts.initialValue !== undefined ? { ok: true, value: opts.initialValue } : { ok: false }),\r\n build: (done) => {\r\n const View = component(() => {\r\n const initial = opts.options.findIndex((o) => o.value === opts.initialValue);\r\n const state = signal({ cursor: initial >= 0 ? initial : 0 });\r\n let off: (() => void) | null = null;\r\n let ready = false;\r\n\r\n onMounted(() => {\r\n setTimeout(() => { ready = true; }, READY_DELAY_MS);\r\n off = onKey((key) => {\r\n if (!ready) return;\r\n if (isEsc(key) || isCtrlC(key)) {\r\n done(CANCEL);\r\n return;\r\n }\r\n if (isUp(key) || key === 'k') {\r\n state.cursor = state.cursor > 0 ? state.cursor - 1 : opts.options.length - 1;\r\n return;\r\n }\r\n if (isDown(key) || key === 'j') {\r\n state.cursor = state.cursor < opts.options.length - 1 ? state.cursor + 1 : 0;\r\n return;\r\n }\r\n if (isEnter(key)) {\r\n done(opts.options[state.cursor].value);\r\n }\r\n });\r\n });\r\n onUnmounted(() => { off?.(); });\r\n\r\n return () => promptFrame({\r\n message: opts.message,\r\n rows: opts.options.map((option, i) => {\r\n const onCursor = i === state.cursor;\r\n return promptRow(\r\n <text>\r\n <text color={resolveColor(onCursor ? 'accent' : 'faint')}>{onCursor ? GLYPHS.cursor : ' '} </text>\r\n <text color={resolveColor(onCursor ? 'accent' : 'fg')}>{optionLabel(option)}</text>\r\n {option.description && onCursor && <text color={resolveColor('dim')}> — {option.description}</text>}\r\n </text>,\r\n );\r\n }),\r\n });\r\n }, { name: 'SelectPrompt' });\r\n return <View />;\r\n },\r\n });\r\n}\r\n","/** @jsxImportSource @sigx/runtime-core */\r\nimport { component, signal, onMounted, onUnmounted } from '@sigx/runtime-core';\r\nimport { onKey, resolveColor, GLYPHS, READY_DELAY_MS, CANCEL, runPrompt, isEnter, isEsc, isCtrlC, isUp, isDown, isSpace } from '@sigx/terminal-zero';\r\nimport { promptFrame, promptRow } from './PromptShell';\r\nimport { optionLabel, type PromptOption } from './select';\r\n\r\nexport interface MultiSelectPromptOptions<T> {\r\n message: string;\r\n options: PromptOption<T>[];\r\n initialValues?: T[];\r\n /** Block an empty Enter and show a hint instead. Default false. */\r\n required?: boolean;\r\n}\r\n\r\n/**\r\n * Multi-choice prompt: ↑/k ↓/j move, Space toggles, `a` toggles all,\r\n * Enter resolves the checked values (in option order).\r\n */\r\nexport function multiselect<T = string>(opts: MultiSelectPromptOptions<T>): Promise<T[] | typeof CANCEL> {\r\n const display = (values: T[]) => {\r\n if (values.length === 0) return 'none';\r\n return opts.options.filter((o) => values.includes(o.value)).map(optionLabel).join(', ');\r\n };\r\n return runPrompt<T[]>({\r\n message: opts.message,\r\n display,\r\n fallback: () => (opts.initialValues !== undefined ? { ok: true, value: opts.initialValues } : { ok: false }),\r\n build: (done) => {\r\n const View = component(() => {\r\n const state = signal({\r\n cursor: 0,\r\n checked: new Set<T>(opts.initialValues ?? []),\r\n requiredHint: false,\r\n });\r\n let off: (() => void) | null = null;\r\n let ready = false;\r\n\r\n const resolveChecked = () =>\r\n opts.options.filter((o) => state.checked.has(o.value)).map((o) => o.value);\r\n\r\n onMounted(() => {\r\n setTimeout(() => { ready = true; }, READY_DELAY_MS);\r\n off = onKey((key) => {\r\n if (!ready) return;\r\n if (isEsc(key) || isCtrlC(key)) {\r\n done(CANCEL);\r\n return;\r\n }\r\n if (isUp(key) || key === 'k') {\r\n state.cursor = state.cursor > 0 ? state.cursor - 1 : opts.options.length - 1;\r\n return;\r\n }\r\n if (isDown(key) || key === 'j') {\r\n state.cursor = state.cursor < opts.options.length - 1 ? state.cursor + 1 : 0;\r\n return;\r\n }\r\n if (isSpace(key)) {\r\n const value = opts.options[state.cursor].value;\r\n const next = new Set(state.checked);\r\n if (next.has(value)) next.delete(value);\r\n else next.add(value);\r\n state.checked = next;\r\n state.requiredHint = false;\r\n return;\r\n }\r\n if (key === 'a') {\r\n state.checked = state.checked.size === opts.options.length\r\n ? new Set<T>()\r\n : new Set(opts.options.map((o) => o.value));\r\n state.requiredHint = false;\r\n return;\r\n }\r\n if (isEnter(key)) {\r\n const values = resolveChecked();\r\n if (opts.required && values.length === 0) {\r\n state.requiredHint = true;\r\n return;\r\n }\r\n done(values);\r\n }\r\n });\r\n });\r\n onUnmounted(() => { off?.(); });\r\n\r\n return () => promptFrame({\r\n message: opts.message,\r\n error: state.requiredHint ? 'select at least one option (space)' : undefined,\r\n footer: 'space toggle · a all · enter confirm',\r\n rows: opts.options.flatMap((option, i) => {\r\n const onCursor = i === state.cursor;\r\n const isChecked = state.checked.has(option.value);\r\n const header = option.group && option.group !== opts.options[i - 1]?.group\r\n ? [promptRow(<text color={resolveColor('dim')}>{option.group}</text>)]\r\n : [];\r\n return [\r\n ...header,\r\n promptRow(\r\n <text>\r\n <text color={resolveColor(onCursor ? 'accent' : 'faint')}>{onCursor ? GLYPHS.cursor : ' '} </text>\r\n <text color={resolveColor(isChecked ? 'success' : 'line')}>\r\n {isChecked ? GLYPHS.checkboxOn : GLYPHS.checkboxOff}\r\n </text>\r\n <text color={resolveColor(onCursor ? 'accent' : 'fg')}> {optionLabel(option)}</text>\r\n {option.description && onCursor && <text color={resolveColor('dim')}> — {option.description}</text>}\r\n </text>,\r\n ),\r\n ];\r\n }),\r\n });\r\n }, { name: 'MultiSelectPrompt' });\r\n return <View />;\r\n },\r\n });\r\n}\r\n","/** @jsxImportSource @sigx/runtime-core */\r\nimport { component, signal, onMounted, onUnmounted } from '@sigx/runtime-core';\r\nimport { onKey, resolveColor, GLYPHS, READY_DELAY_MS, CANCEL, runPrompt, isEnter, isEsc, isCtrlC, isLeft, isRight } from '@sigx/terminal-zero';\r\nimport { promptFrame, promptRow } from './PromptShell';\r\n\r\nexport interface ConfirmOptions {\r\n message: string;\r\n initialValue?: boolean;\r\n /** Label for true. Default 'Yes'. */\r\n active?: string;\r\n /** Label for false. Default 'No'. */\r\n inactive?: string;\r\n}\r\n\r\n/**\r\n * Yes/No prompt: y/n answer immediately, ←/→ (or h/l) flip the selection,\r\n * Enter resolves the current value.\r\n */\r\nexport function confirm(opts: ConfirmOptions): Promise<boolean | typeof CANCEL> {\r\n const yes = opts.active ?? 'Yes';\r\n const no = opts.inactive ?? 'No';\r\n return runPrompt<boolean>({\r\n message: opts.message,\r\n display: (v) => (v ? yes : no),\r\n fallback: () => (opts.initialValue !== undefined ? { ok: true, value: opts.initialValue } : { ok: false }),\r\n build: (done) => {\r\n const View = component(() => {\r\n const state = signal({ value: opts.initialValue ?? true });\r\n let off: (() => void) | null = null;\r\n let ready = false;\r\n\r\n onMounted(() => {\r\n setTimeout(() => { ready = true; }, READY_DELAY_MS);\r\n off = onKey((key) => {\r\n if (!ready) return;\r\n if (isEsc(key) || isCtrlC(key)) {\r\n done(CANCEL);\r\n return;\r\n }\r\n if (key === 'y' || key === 'Y') {\r\n done(true);\r\n return;\r\n }\r\n if (key === 'n' || key === 'N') {\r\n done(false);\r\n return;\r\n }\r\n if (isLeft(key) || isRight(key) || key === 'h' || key === 'l') {\r\n state.value = !state.value;\r\n return;\r\n }\r\n if (isEnter(key)) {\r\n done(state.value);\r\n }\r\n });\r\n });\r\n onUnmounted(() => { off?.(); });\r\n\r\n return () => promptFrame({\r\n message: opts.message,\r\n footer: 'y / n · enter confirm',\r\n rows: [promptRow(\r\n <text>\r\n <text color={resolveColor(state.value ? 'accent' : 'dim')}>\r\n {state.value ? GLYPHS.radioOn : GLYPHS.radioOff} {yes}\r\n </text>\r\n <text> </text>\r\n <text color={resolveColor(state.value ? 'dim' : 'accent')}>\r\n {state.value ? GLYPHS.radioOff : GLYPHS.radioOn} {no}\r\n </text>\r\n </text>,\r\n )],\r\n });\r\n }, { name: 'ConfirmPrompt' });\r\n return <View />;\r\n },\r\n });\r\n}\r\n","/**\r\n * Static framing for prompt flows — plain permanent lines, no mount:\r\n *\r\n * ┌ create sigx app intro\r\n * ◇ Project name · my-app (prompt summaries land between)\r\n * │ a note line note\r\n * └ Done — next: pnpm dev outro\r\n * ■ Cancelled. cancel\r\n */\r\nimport { printStatic } from '@sigx/terminal-zero';\r\nimport { paintToken } from '@sigx/terminal-zero';\r\n\r\n/** Open a prompt flow with a title bar. */\r\nexport function intro(title: string): void {\r\n printStatic(`${paintToken('┌', 'dim')} ${paintToken(title, 'accent')}`);\r\n}\r\n\r\n/** Close a prompt flow. */\r\nexport function outro(message: string): void {\r\n printStatic(`${paintToken('└', 'dim')} ${message}\\n`);\r\n}\r\n\r\n/** An informational block inside a flow. */\r\nexport function note(message: string, title?: string): void {\r\n const lines: string[] = [];\r\n if (title) lines.push(`${paintToken('○', 'accent')} ${title}`);\r\n for (const line of message.split('\\n')) {\r\n lines.push(`${paintToken('│', 'dim')} ${paintToken(line, 'dim')}`);\r\n }\r\n printStatic(lines.join('\\n'));\r\n}\r\n\r\n/** Announce a cancelled flow (pair with isCancel + process.exit). */\r\nexport function cancel(message: string): void {\r\n printStatic(`${paintToken('■', 'danger')} ${message}`);\r\n}\r\n","/** @jsxImportSource @sigx/runtime-core */\r\nimport { component, signal } from '@sigx/runtime-core';\r\nimport { renderTerminal, printStatic, GLYPHS, enqueue, isInteractive, paintToken } from '@sigx/terminal-zero';\r\nimport { Spinner } from '../feedback/Spinner';\r\n\r\nexport interface SpinnerHandle {\r\n start(label?: string): void;\r\n /** Update the label while spinning. */\r\n message(label: string): void;\r\n /** Stop and leave a permanent `✔ label` / `✖ label` line. */\r\n stop(label?: string, code?: 'success' | 'error'): void;\r\n}\r\n\r\n/**\r\n * Imperative spinner for prompt flows:\r\n *\r\n * const s = spinner();\r\n * s.start('Installing dependencies');\r\n * await install();\r\n * s.stop('Dependencies installed');\r\n *\r\n * Queues behind any in-flight prompts and occupies the live region until\r\n * stopped — don't await another prompt between start() and stop() (it would\r\n * wait for the spinner's slot and deadlock). Ctrl+C stays the renderer\r\n * default here (exit): a long task should be interruptible.\r\n * Non-TTY: start() renders nothing; stop() prints the summary line.\r\n */\r\nexport function spinner(): SpinnerHandle {\r\n const state = signal({ label: '' });\r\n let active = false;\r\n let handle: { unmount: () => void } | null = null;\r\n let release: (() => void) | null = null;\r\n\r\n return {\r\n start(label = '') {\r\n if (active) return;\r\n active = true;\r\n state.label = label;\r\n const gate = new Promise<void>((resolve) => { release = resolve; });\r\n void enqueue(() => {\r\n if (!active) return Promise.resolve(); // stopped before its slot came up\r\n if (isInteractive()) {\r\n const View = component(() => () => <Spinner label={state.label} />, { name: 'PromptSpinner' });\r\n handle = renderTerminal(<View />, { mode: 'inline', persistOnExit: false });\r\n }\r\n return gate;\r\n });\r\n },\r\n message(label: string) {\r\n state.label = label;\r\n },\r\n stop(label?: string, code: 'success' | 'error' = 'success') {\r\n if (!active) return;\r\n active = false;\r\n handle?.unmount();\r\n handle = null;\r\n const finalLabel = label ?? state.label;\r\n const mark = code === 'success' ? paintToken(GLYPHS.check, 'success') : paintToken(GLYPHS.cross, 'danger');\r\n printStatic(`${mark} ${finalLabel}`);\r\n release?.();\r\n release = null;\r\n },\r\n };\r\n}\r\n","/**\r\n * Imperative prompts: linear CLI wizards without a JSX step\r\n * machine. Each prompt mounts a one-shot inline UI, resolves on Enter, and\r\n * collapses into a permanent `◇ message · answer` line — a finished wizard\r\n * reads as a tidy transcript in scrollback.\r\n */\r\nexport { CANCEL, isCancel, __setInteractiveOverride } from '@sigx/terminal-zero';\r\nexport { text, password, type TextOptions } from './text';\r\nexport { select, type SelectOptions, type PromptOption } from './select';\r\nexport { multiselect, type MultiSelectPromptOptions } from './multiselect';\r\nexport { confirm, type ConfirmOptions } from './confirm';\r\nexport { intro, outro, note, cancel } from './statics';\r\nexport { spinner, type SpinnerHandle } from './spinner';\r\n\r\nimport { CANCEL, isCancel } from '@sigx/terminal-zero';\r\nimport { text, password } from './text';\r\nimport { select } from './select';\r\nimport { multiselect } from './multiselect';\r\nimport { confirm } from './confirm';\r\nimport { intro, outro, note, cancel } from './statics';\r\nimport { spinner } from './spinner';\r\n\r\n/** Namespace bundle for collision-free imports: `prompt.select(...)`. */\r\nexport const prompt = {\r\n text, password, select, multiselect, confirm,\r\n intro, outro, note, cancel, spinner,\r\n isCancel, CANCEL,\r\n} as const;\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LogStore } from './logStore';
|
|
2
|
+
/**
|
|
3
|
+
* Streaming log tail: the last `height` lines of a stream, dimmed, in
|
|
4
|
+
* one of three variants:
|
|
5
|
+
* - `bar` — `│` gutter in the `line` color (default)
|
|
6
|
+
* - `panel` — rounded bordered box with the title as its label
|
|
7
|
+
* - `plain` — bare lines
|
|
8
|
+
* Feed it a LogStore (preferred — reactive, `\r`-aware) or a plain `lines`
|
|
9
|
+
* array. Follow-tail is inherent: it always shows the last `height` lines.
|
|
10
|
+
* Lines are truncated escape-aware, so tool output containing its own ANSI
|
|
11
|
+
* can't overflow the inline live region.
|
|
12
|
+
*/
|
|
13
|
+
export declare const LogPanel: import("@sigx/runtime-core").ComponentFactory<{
|
|
14
|
+
store?: LogStore | undefined;
|
|
15
|
+
} & {
|
|
16
|
+
lines?: string[] | undefined;
|
|
17
|
+
} & {
|
|
18
|
+
height?: number | undefined;
|
|
19
|
+
} & {
|
|
20
|
+
width?: number | undefined;
|
|
21
|
+
} & {
|
|
22
|
+
title?: string | undefined;
|
|
23
|
+
} & {
|
|
24
|
+
variant?: "bar" | "panel" | "plain" | undefined;
|
|
25
|
+
} & {
|
|
26
|
+
color?: string | undefined;
|
|
27
|
+
}, void, {}>;
|
|
28
|
+
export default LogPanel;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LogStore } from './logStore';
|
|
2
|
+
/**
|
|
3
|
+
* Focusable, scrollable log viewer — the "logs tab" of a persistent dev TUI.
|
|
4
|
+
* Follows the tail by default; scrolling up pauses follow and pins the
|
|
5
|
+
* visible window even while the stream keeps growing; scrolling back to the
|
|
6
|
+
* bottom (or End / `f`) re-engages follow.
|
|
7
|
+
*
|
|
8
|
+
* Keys while focused: ↑/k ↓/j scroll one line, PgUp/PgDn a page,
|
|
9
|
+
* Home jump to the oldest, End jump to the tail (re-follows), `f` toggle.
|
|
10
|
+
*/
|
|
11
|
+
export declare const LogView: import("@sigx/runtime-core").ComponentFactory<{
|
|
12
|
+
store?: LogStore | undefined;
|
|
13
|
+
} & {
|
|
14
|
+
lines?: string[] | undefined;
|
|
15
|
+
} & {
|
|
16
|
+
height?: number | undefined;
|
|
17
|
+
} & {
|
|
18
|
+
width?: number | undefined;
|
|
19
|
+
} & {
|
|
20
|
+
title?: string | undefined;
|
|
21
|
+
} & {
|
|
22
|
+
autofocus?: boolean | undefined;
|
|
23
|
+
}, void, {}>;
|
|
24
|
+
export default LogView;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { LogStore } from './logStore';
|
|
2
|
+
export type TaskStatus = 'pending' | 'running' | 'success' | 'fail' | 'skipped';
|
|
3
|
+
export interface TaskItem {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
status: TaskStatus;
|
|
7
|
+
/** Optional dimmed suffix, e.g. a duration or a count. */
|
|
8
|
+
detail?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Build-pipeline task list: one row per task with a status glyph (pending ◌,
|
|
12
|
+
* running spinner, ✔/✖, skipped −), in `plain` or `tree` (├─/└─ guides)
|
|
13
|
+
* variants. Pass a LogStore via `log` to stream a LogPanel tail under the
|
|
14
|
+
* running task. Data-driven: mutate the `tasks` array in place (statuses are
|
|
15
|
+
* reactive through the signal proxy).
|
|
16
|
+
*/
|
|
17
|
+
export declare const TaskList: import("@sigx/runtime-core").ComponentFactory<{
|
|
18
|
+
tasks: TaskItem[];
|
|
19
|
+
} & {
|
|
20
|
+
variant?: "plain" | "tree" | undefined;
|
|
21
|
+
} & {
|
|
22
|
+
log?: LogStore | undefined;
|
|
23
|
+
} & {
|
|
24
|
+
logHeight?: number | undefined;
|
|
25
|
+
}, void, {}>;
|
|
26
|
+
export default TaskList;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface LogStoreOptions {
|
|
2
|
+
/** Max retained completed lines (ring buffer). Default 10 000. */
|
|
3
|
+
limit?: number;
|
|
4
|
+
/**
|
|
5
|
+
* Stream completed lines straight to printStatic as they arrive.
|
|
6
|
+
* Default: on when stdout is not a TTY (piped/CI logs stay complete and
|
|
7
|
+
* ordered), off when interactive (the LogPanel shows the tail instead).
|
|
8
|
+
*/
|
|
9
|
+
passthrough?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface LogStore {
|
|
12
|
+
/** Whether this store streams lines to printStatic (fixed at creation). */
|
|
13
|
+
readonly passthrough: boolean;
|
|
14
|
+
push(chunk: string): void;
|
|
15
|
+
/** Commit a trailing partial line, if any. */
|
|
16
|
+
end(): void;
|
|
17
|
+
clear(): void;
|
|
18
|
+
/** Completed lines, plus the live partial as the last entry. Reactive. */
|
|
19
|
+
lines(): readonly string[];
|
|
20
|
+
/** The last `n` of lines(). Reactive. */
|
|
21
|
+
tail(n: number): string[];
|
|
22
|
+
count(): number;
|
|
23
|
+
}
|
|
24
|
+
export declare function createLogStore(opts?: LogStoreOptions): LogStore;
|
|
25
|
+
export interface CollapseOptions {
|
|
26
|
+
label: string;
|
|
27
|
+
ok: boolean;
|
|
28
|
+
durationMs?: number;
|
|
29
|
+
/** On failure, the full captured log is flushed into scrollback first. */
|
|
30
|
+
store?: LogStore;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Print a task's permanent one-line summary above the live region —
|
|
34
|
+
* `✔ pod install (3.2s)` on success; on failure the full log flushes first so
|
|
35
|
+
* it's greppable in scrollback, then `✖ label`. The live-region collapse
|
|
36
|
+
* itself is the consumer flipping the task off `running` (the panel unmounts
|
|
37
|
+
* and the repaint shrinks the region). Inline-mode pattern: in fullscreen,
|
|
38
|
+
* static output queues until the alt screen exits, by design.
|
|
39
|
+
*/
|
|
40
|
+
export declare function collapseTask(o: CollapseOptions): void;
|