@reliverse/relinka 1.0.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.md +21 -0
- package/README.md +141 -0
- package/output/components/animate.d.ts +13 -0
- package/output/components/animate.js +55 -0
- package/output/components/any-key.d.ts +7 -0
- package/output/components/any-key.js +56 -0
- package/output/components/ascii-art.d.ts +6 -0
- package/output/components/ascii-art.js +12 -0
- package/output/components/confirm.d.ts +3 -0
- package/output/components/confirm.js +99 -0
- package/output/components/date.d.ts +6 -0
- package/output/components/date.js +125 -0
- package/output/components/end.d.ts +2 -0
- package/output/components/end.js +36 -0
- package/output/components/mono.d.ts +5 -0
- package/output/components/mono.js +64 -0
- package/output/components/next-steps.d.ts +2 -0
- package/output/components/next-steps.js +25 -0
- package/output/components/num-multi-select.d.ts +3 -0
- package/output/components/num-multi-select.js +108 -0
- package/output/components/num-select.d.ts +5 -0
- package/output/components/num-select.js +122 -0
- package/output/components/number.d.ts +3 -0
- package/output/components/number.js +92 -0
- package/output/components/password.d.ts +3 -0
- package/output/components/password.js +117 -0
- package/output/components/results.d.ts +10 -0
- package/output/components/results.js +34 -0
- package/output/components/select.d.ts +2 -0
- package/output/components/select.js +97 -0
- package/output/components/spinner.d.ts +15 -0
- package/output/components/spinner.js +110 -0
- package/output/components/start.d.ts +2 -0
- package/output/components/start.js +33 -0
- package/output/components/text.d.ts +3 -0
- package/output/components/text.js +88 -0
- package/output/hooks/useKeyPress.d.ts +4 -0
- package/output/hooks/useKeyPress.js +14 -0
- package/output/main.d.ts +16 -0
- package/output/main.js +16 -0
- package/output/types/prod.d.ts +83 -0
- package/output/types/prod.js +0 -0
- package/output/utils/colorize.d.ts +2 -0
- package/output/utils/colorize.js +129 -0
- package/output/utils/errors.d.ts +1 -0
- package/output/utils/errors.js +11 -0
- package/output/utils/mapping.d.ts +4 -0
- package/output/utils/mapping.js +49 -0
- package/output/utils/messages.d.ts +17 -0
- package/output/utils/messages.js +203 -0
- package/output/utils/platforms.d.ts +1 -0
- package/output/utils/platforms.js +22 -0
- package/output/utils/prompt-tmp.d.ts +13 -0
- package/output/utils/prompt-tmp.js +254 -0
- package/output/utils/prompt.d.ts +13 -0
- package/output/utils/prompt.js +254 -0
- package/output/utils/readline.d.ts +2 -0
- package/output/utils/readline.js +9 -0
- package/output/utils/terminal.d.ts +5 -0
- package/output/utils/terminal.js +33 -0
- package/output/utils/variants.d.ts +9 -0
- package/output/utils/variants.js +49 -0
- package/package.json +96 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import gradient, { cristal, mind, passion, retro, vice } from "gradient-string";
|
|
3
|
+
import { rainbow } from "gradient-string";
|
|
4
|
+
import colors from "picocolors";
|
|
5
|
+
export const colorMap = {
|
|
6
|
+
none: colors.reset,
|
|
7
|
+
inverse: colors.inverse,
|
|
8
|
+
black: colors.black,
|
|
9
|
+
blue: colors.blue,
|
|
10
|
+
blueBright: colors.blueBright,
|
|
11
|
+
cyan: colors.cyan,
|
|
12
|
+
cyanBright: colors.cyanBright,
|
|
13
|
+
bgCyan: colors.bgCyan,
|
|
14
|
+
bgCyanBright: colors.bgCyanBright,
|
|
15
|
+
dim: colors.dim,
|
|
16
|
+
gray: colors.gray,
|
|
17
|
+
green: colors.green,
|
|
18
|
+
greenBright: colors.greenBright,
|
|
19
|
+
bgGreen: colors.bgGreen,
|
|
20
|
+
bgGreenBright: colors.bgGreenBright,
|
|
21
|
+
magenta: colors.magenta,
|
|
22
|
+
red: colors.red,
|
|
23
|
+
redBright: colors.redBright,
|
|
24
|
+
bgRed: colors.bgRed,
|
|
25
|
+
bgRedBright: colors.bgRedBright,
|
|
26
|
+
white: colors.white,
|
|
27
|
+
yellow: colors.yellow,
|
|
28
|
+
yellowBright: colors.yellowBright,
|
|
29
|
+
cristalGradient: cristal,
|
|
30
|
+
mindGradient: mind,
|
|
31
|
+
passionGradient: passion,
|
|
32
|
+
rainbowGradient: rainbow,
|
|
33
|
+
retroGradient: retro,
|
|
34
|
+
viceGradient: vice,
|
|
35
|
+
gradientGradient: gradient([
|
|
36
|
+
"red",
|
|
37
|
+
"yellow",
|
|
38
|
+
"green",
|
|
39
|
+
"cyan",
|
|
40
|
+
"blue",
|
|
41
|
+
"magenta"
|
|
42
|
+
])
|
|
43
|
+
};
|
|
44
|
+
export const typographyMap = {
|
|
45
|
+
bold: chalk.bold,
|
|
46
|
+
italic: chalk.italic,
|
|
47
|
+
underline: chalk.underline,
|
|
48
|
+
strikethrough: chalk.strikethrough
|
|
49
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ColorName, FmtMsgOptions } from "../types/prod";
|
|
2
|
+
export declare const symbols: {
|
|
3
|
+
pointer: string;
|
|
4
|
+
start: string;
|
|
5
|
+
middle: string;
|
|
6
|
+
end: string;
|
|
7
|
+
line: string;
|
|
8
|
+
corner_top_right: string;
|
|
9
|
+
step_active: string;
|
|
10
|
+
step_error: string;
|
|
11
|
+
info: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const bar: ({ borderColor, }: {
|
|
14
|
+
borderColor?: ColorName;
|
|
15
|
+
}) => string;
|
|
16
|
+
export declare function fmt(opts: FmtMsgOptions): string;
|
|
17
|
+
export declare function msg(opts: FmtMsgOptions): void;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { emojify } from "node-emoji";
|
|
2
|
+
import { greenBright, redBright } from "picocolors";
|
|
3
|
+
import { colorMap, typographyMap } from "../utils/mapping";
|
|
4
|
+
import { isUnicodeSupported } from "../utils/platforms";
|
|
5
|
+
import { variantMap } from "../utils/variants";
|
|
6
|
+
const unicode = isUnicodeSupported();
|
|
7
|
+
const u = (c, fallback) => unicode ? c : fallback;
|
|
8
|
+
export const symbols = {
|
|
9
|
+
pointer: u("\u{1F449}", ">"),
|
|
10
|
+
start: u("\u256D", "T"),
|
|
11
|
+
middle: u("\u2502", "|"),
|
|
12
|
+
end: u("\u2570", "*"),
|
|
13
|
+
line: u("\u2500", "\u2014"),
|
|
14
|
+
corner_top_right: u("\xBB", "T"),
|
|
15
|
+
step_active: u("\u25C6", "\u2666"),
|
|
16
|
+
step_error: u("\u{1F5F4}", "x"),
|
|
17
|
+
info: u("\u2139", "i")
|
|
18
|
+
};
|
|
19
|
+
function applyStyles(text, colorName = "", typographyName = "", variantName = "", borderColor = "") {
|
|
20
|
+
let styledText = text;
|
|
21
|
+
if (!variantName) {
|
|
22
|
+
if (colorName && colorMap[colorName]) {
|
|
23
|
+
styledText = colorMap[colorName](styledText);
|
|
24
|
+
} else if (colorName) {
|
|
25
|
+
console.warn(
|
|
26
|
+
`Warning: Invalid color "${colorName}" provided to applyStyles.`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (typographyName && typographyMap[typographyName]) {
|
|
30
|
+
styledText = typographyMap[typographyName](styledText);
|
|
31
|
+
} else if (typographyName) {
|
|
32
|
+
console.warn(
|
|
33
|
+
`Warning: Invalid typography "${typographyName}" provided to applyStyles.`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (variantName && variantMap[variantName]) {
|
|
38
|
+
styledText = variantMap[variantName](styledText, borderColor);
|
|
39
|
+
} else if (variantName) {
|
|
40
|
+
console.warn(
|
|
41
|
+
`Warning: Invalid variant "${variantName}" provided to applyStyles.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return styledText;
|
|
45
|
+
}
|
|
46
|
+
export const bar = ({
|
|
47
|
+
borderColor = "viceGradient"
|
|
48
|
+
}) => colorMap[borderColor](symbols.middle);
|
|
49
|
+
export function fmt(opts) {
|
|
50
|
+
if (opts.title?.includes("\u2502 ")) {
|
|
51
|
+
opts.title = opts.title.replace("\u2502 ", "");
|
|
52
|
+
}
|
|
53
|
+
if (!opts.borderColor) {
|
|
54
|
+
opts.borderColor = "viceGradient";
|
|
55
|
+
}
|
|
56
|
+
const formattedBar = bar({ borderColor: opts.borderColor });
|
|
57
|
+
const prefixStartLine = opts.borderColor ? colorMap[opts.borderColor](symbols.start + symbols.line) : symbols.start + symbols.line;
|
|
58
|
+
const prefixEndLine = opts.borderColor ? colorMap[opts.borderColor](symbols.end + symbols.line) : symbols.end + symbols.line;
|
|
59
|
+
const suffixStartLine = opts.borderColor ? colorMap[opts.borderColor](`${symbols.line.repeat(28)}\u22B1`) : `${symbols.line.repeat(28)}\u22B1`;
|
|
60
|
+
const suffixEndLine = opts.borderColor ? colorMap[opts.borderColor](`${symbols.line.repeat(58)}\u22B1`) : `${symbols.line.repeat(58)}\u22B1`;
|
|
61
|
+
const MSG_CONFIGS = {
|
|
62
|
+
M_NULL: {
|
|
63
|
+
symbol: "",
|
|
64
|
+
prefix: "",
|
|
65
|
+
suffix: "",
|
|
66
|
+
newLineBefore: opts.addNewLineBefore ?? false,
|
|
67
|
+
newLineAfter: opts.addNewLineAfter ?? false
|
|
68
|
+
},
|
|
69
|
+
M_START: {
|
|
70
|
+
symbol: "",
|
|
71
|
+
prefix: prefixStartLine,
|
|
72
|
+
suffix: ` ${suffixStartLine}
|
|
73
|
+
${formattedBar}`,
|
|
74
|
+
newLineBefore: false,
|
|
75
|
+
newLineAfter: false
|
|
76
|
+
},
|
|
77
|
+
M_MIDDLE: {
|
|
78
|
+
symbol: formattedBar,
|
|
79
|
+
prefix: "",
|
|
80
|
+
suffix: "",
|
|
81
|
+
newLineBefore: false,
|
|
82
|
+
newLineAfter: false
|
|
83
|
+
},
|
|
84
|
+
M_GENERAL: {
|
|
85
|
+
symbol: "",
|
|
86
|
+
prefix: greenBright(symbols.step_active),
|
|
87
|
+
suffix: "",
|
|
88
|
+
newLineBefore: opts.addNewLineBefore ?? false,
|
|
89
|
+
newLineAfter: opts.addNewLineAfter ?? true
|
|
90
|
+
},
|
|
91
|
+
M_INFO: {
|
|
92
|
+
symbol: "",
|
|
93
|
+
prefix: greenBright(symbols.info),
|
|
94
|
+
suffix: "",
|
|
95
|
+
newLineBefore: false,
|
|
96
|
+
newLineAfter: true
|
|
97
|
+
},
|
|
98
|
+
M_ERROR: {
|
|
99
|
+
symbol: "",
|
|
100
|
+
// prefix: `${formattedBar}\n${s.step_error}`,
|
|
101
|
+
prefix: redBright(symbols.step_error),
|
|
102
|
+
newLineBefore: false,
|
|
103
|
+
newLineAfter: true
|
|
104
|
+
},
|
|
105
|
+
M_END: {
|
|
106
|
+
symbol: "",
|
|
107
|
+
prefix: "",
|
|
108
|
+
suffix: opts.border ? ` ${suffixEndLine}
|
|
109
|
+
${formattedBar}` : "",
|
|
110
|
+
newLineBefore: false,
|
|
111
|
+
newLineAfter: true
|
|
112
|
+
},
|
|
113
|
+
M_END_ANIMATED: {
|
|
114
|
+
symbol: "",
|
|
115
|
+
prefix: greenBright(symbols.info),
|
|
116
|
+
suffix: opts.border ? `
|
|
117
|
+
${formattedBar}
|
|
118
|
+
${prefixEndLine}${suffixEndLine}
|
|
119
|
+
` : "",
|
|
120
|
+
newLineBefore: false,
|
|
121
|
+
newLineAfter: false
|
|
122
|
+
},
|
|
123
|
+
M_NEWLINE: {
|
|
124
|
+
symbol: "",
|
|
125
|
+
prefix: formattedBar,
|
|
126
|
+
newLineBefore: false,
|
|
127
|
+
newLineAfter: false
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const config = MSG_CONFIGS[opts.type];
|
|
131
|
+
if (!config) {
|
|
132
|
+
throw new Error(`Invalid message type: ${opts.type}`);
|
|
133
|
+
}
|
|
134
|
+
const {
|
|
135
|
+
symbol = "",
|
|
136
|
+
prefix = "",
|
|
137
|
+
suffix = "",
|
|
138
|
+
newLineBefore = false,
|
|
139
|
+
newLineAfter = false
|
|
140
|
+
} = config;
|
|
141
|
+
const formattedPrefix = prefix ? `${prefix}${opts.type === "M_START" ? " " : " "}` : "";
|
|
142
|
+
const border = applyStyles(symbols.middle, opts.borderColor);
|
|
143
|
+
const borderError = applyStyles(symbols.middle, "red");
|
|
144
|
+
const borderWithSpace = `${border} `;
|
|
145
|
+
let formattedTitle = "";
|
|
146
|
+
if (opts.title) {
|
|
147
|
+
formattedTitle = applyStyles(
|
|
148
|
+
opts.title,
|
|
149
|
+
opts.titleColor,
|
|
150
|
+
opts.titleTypography,
|
|
151
|
+
opts.titleVariant,
|
|
152
|
+
opts.borderColor
|
|
153
|
+
);
|
|
154
|
+
if (opts.hint) {
|
|
155
|
+
formattedTitle += `
|
|
156
|
+
${borderWithSpace}${colorMap.blueBright(opts.hint)}`;
|
|
157
|
+
}
|
|
158
|
+
if (opts.errorMessage) {
|
|
159
|
+
const formattedError = applyStyles(
|
|
160
|
+
opts.errorMessage,
|
|
161
|
+
"red",
|
|
162
|
+
"bold",
|
|
163
|
+
"",
|
|
164
|
+
opts.borderColor
|
|
165
|
+
);
|
|
166
|
+
formattedTitle += `
|
|
167
|
+
${borderError} ${formattedError}`;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
let formattedContent = "";
|
|
171
|
+
if (opts.content) {
|
|
172
|
+
const contentLines = opts.content.split("\n");
|
|
173
|
+
formattedContent = contentLines.map((line) => {
|
|
174
|
+
const styledLine = applyStyles(
|
|
175
|
+
line,
|
|
176
|
+
opts.contentColor,
|
|
177
|
+
opts.contentTypography,
|
|
178
|
+
opts.contentVariant,
|
|
179
|
+
opts.borderColor
|
|
180
|
+
);
|
|
181
|
+
if (opts.type !== "M_START") {
|
|
182
|
+
return `${borderWithSpace}${styledLine}`;
|
|
183
|
+
} else {
|
|
184
|
+
return styledLine;
|
|
185
|
+
}
|
|
186
|
+
}).join("\n");
|
|
187
|
+
}
|
|
188
|
+
const text = [formattedTitle, formattedContent].filter(Boolean).join(`
|
|
189
|
+
`);
|
|
190
|
+
return [
|
|
191
|
+
symbol,
|
|
192
|
+
newLineBefore ? `
|
|
193
|
+
${formattedBar} ` : "",
|
|
194
|
+
formattedPrefix,
|
|
195
|
+
text,
|
|
196
|
+
newLineAfter ? `
|
|
197
|
+
${formattedBar} ` : "",
|
|
198
|
+
suffix
|
|
199
|
+
].filter(Boolean).join("");
|
|
200
|
+
}
|
|
201
|
+
export function msg(opts) {
|
|
202
|
+
console[opts.type === "M_ERROR" ? "error" : "log"](emojify(fmt(opts)));
|
|
203
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isUnicodeSupported(): boolean;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
const platforms = {
|
|
3
|
+
linux: process.platform !== "win32",
|
|
4
|
+
win32: process.platform === "win32"
|
|
5
|
+
};
|
|
6
|
+
const terminals = {
|
|
7
|
+
linuxConsoleKernel: process.env.TERM !== "linux",
|
|
8
|
+
windowsTerminal: Boolean(process.env.WT_SESSION),
|
|
9
|
+
terminusSublimeOld: Boolean(process.env.TERMINUS_SUBLIME),
|
|
10
|
+
cmderTerminal: process.env.ConEmuTask === "{cmd::Cmder}",
|
|
11
|
+
terminusSublimeNew: process.env.TERM_PROGRAM === "Terminus-Sublime",
|
|
12
|
+
visualStudioCode: process.env.TERM_PROGRAM === "vscode",
|
|
13
|
+
xterm256color: process.env.TERM === "xterm-256color",
|
|
14
|
+
alacrittyTerminal: process.env.TERM === "alacritty",
|
|
15
|
+
jetbrainsJediTerm: process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm"
|
|
16
|
+
};
|
|
17
|
+
export function isUnicodeSupported() {
|
|
18
|
+
if (platforms.linux) {
|
|
19
|
+
return terminals.linuxConsoleKernel;
|
|
20
|
+
}
|
|
21
|
+
return terminals.windowsTerminal || terminals.terminusSublimeOld || terminals.cmderTerminal || terminals.terminusSublimeNew || terminals.visualStudioCode || terminals.xterm256color || terminals.alacrittyTerminal || terminals.jetbrainsJediTerm;
|
|
22
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
export declare function isCancel(value: unknown): value is symbol;
|
|
3
|
+
export type PromptOptions<Self> = {
|
|
4
|
+
render(this: Omit<Self, "prompt">): string | void;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
initialValue?: any;
|
|
7
|
+
validate?: ((value: any) => string | void) | undefined;
|
|
8
|
+
input?: Readable;
|
|
9
|
+
output?: Writable;
|
|
10
|
+
debug?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type StateDeprecated = "initial" | "active" | "cancel" | "submit" | "error";
|
|
13
|
+
export declare function createPrompt({ render: renderFn, input, output, ...opts }: PromptOptions<any>, trackValue?: boolean): any;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { stdin, stdout } from "node:process";
|
|
2
|
+
import readline from "node:readline";
|
|
3
|
+
import { WriteStream } from "node:tty";
|
|
4
|
+
import { cursor, erase } from "sisteransi";
|
|
5
|
+
import wrap from "wrap-ansi";
|
|
6
|
+
function diffLines(a, b) {
|
|
7
|
+
if (a === b) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const aLines = a.split("\n");
|
|
11
|
+
const bLines = b.split("\n");
|
|
12
|
+
const diff = [];
|
|
13
|
+
for (let i = 0; i < Math.max(aLines.length, bLines.length); i++) {
|
|
14
|
+
if (aLines[i] !== bLines[i]) {
|
|
15
|
+
diff.push(i);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return diff;
|
|
19
|
+
}
|
|
20
|
+
const cancel = Symbol("rp:cancel");
|
|
21
|
+
export function isCancel(value) {
|
|
22
|
+
return value === cancel;
|
|
23
|
+
}
|
|
24
|
+
function setRawMode(input, value) {
|
|
25
|
+
if (input.isTTY) {
|
|
26
|
+
input.setRawMode(value);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const aliases = /* @__PURE__ */ new Map([
|
|
30
|
+
["k", "up"],
|
|
31
|
+
["j", "down"],
|
|
32
|
+
["h", "left"],
|
|
33
|
+
["l", "right"]
|
|
34
|
+
]);
|
|
35
|
+
const keys = /* @__PURE__ */ new Set(["up", "down", "left", "right", "space", "enter"]);
|
|
36
|
+
export function createPrompt({
|
|
37
|
+
render: renderFn,
|
|
38
|
+
input = stdin,
|
|
39
|
+
output = stdout,
|
|
40
|
+
...opts
|
|
41
|
+
}, trackValue = true) {
|
|
42
|
+
const _input = input;
|
|
43
|
+
const _output = output;
|
|
44
|
+
let _rl;
|
|
45
|
+
const _opts = opts;
|
|
46
|
+
const _track = trackValue;
|
|
47
|
+
let _cursor = 0;
|
|
48
|
+
let state = "initial";
|
|
49
|
+
let value = _opts.initialValue ?? "";
|
|
50
|
+
let error = "";
|
|
51
|
+
const subscribers = /* @__PURE__ */ new Map();
|
|
52
|
+
let _prevFrame = "";
|
|
53
|
+
const self = {};
|
|
54
|
+
const _render = () => renderFn.call(self);
|
|
55
|
+
function prompt() {
|
|
56
|
+
const sink = new WriteStream(0);
|
|
57
|
+
sink._write = (chunk, encoding, done) => {
|
|
58
|
+
if (_track) {
|
|
59
|
+
value = _rl.line.replace(/\t/g, "");
|
|
60
|
+
_cursor = _rl.cursor;
|
|
61
|
+
emit("value", value);
|
|
62
|
+
}
|
|
63
|
+
done();
|
|
64
|
+
};
|
|
65
|
+
_input.pipe(sink);
|
|
66
|
+
_rl = readline.createInterface({
|
|
67
|
+
input: _input,
|
|
68
|
+
output: sink,
|
|
69
|
+
tabSize: 2,
|
|
70
|
+
prompt: "",
|
|
71
|
+
escapeCodeTimeout: 50
|
|
72
|
+
});
|
|
73
|
+
readline.emitKeypressEvents(_input, _rl);
|
|
74
|
+
_rl.prompt();
|
|
75
|
+
if (_opts.initialValue !== void 0 && _track) {
|
|
76
|
+
_rl.write(_opts.initialValue);
|
|
77
|
+
}
|
|
78
|
+
_input.on("keypress", onKeypress);
|
|
79
|
+
setRawMode(_input, true);
|
|
80
|
+
_output.on("resize", render);
|
|
81
|
+
render();
|
|
82
|
+
return new Promise((resolve) => {
|
|
83
|
+
once("submit", () => {
|
|
84
|
+
_output.write(cursor.show);
|
|
85
|
+
_output.off("resize", render);
|
|
86
|
+
setRawMode(_input, false);
|
|
87
|
+
resolve(value);
|
|
88
|
+
});
|
|
89
|
+
once("cancel", () => {
|
|
90
|
+
_output.write(cursor.show);
|
|
91
|
+
_output.off("resize", render);
|
|
92
|
+
setRawMode(_input, false);
|
|
93
|
+
resolve(cancel);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function on(event, cb) {
|
|
98
|
+
const arr = subscribers.get(event) ?? [];
|
|
99
|
+
arr.push({ cb });
|
|
100
|
+
subscribers.set(event, arr);
|
|
101
|
+
}
|
|
102
|
+
function once(event, cb) {
|
|
103
|
+
const arr = subscribers.get(event) ?? [];
|
|
104
|
+
arr.push({ cb, once: true });
|
|
105
|
+
subscribers.set(event, arr);
|
|
106
|
+
}
|
|
107
|
+
function emit(event, ...data) {
|
|
108
|
+
const cbs = subscribers.get(event) ?? [];
|
|
109
|
+
const cleanup = [];
|
|
110
|
+
for (const subscriber of cbs) {
|
|
111
|
+
subscriber.cb(...data);
|
|
112
|
+
if (subscriber.once) {
|
|
113
|
+
cleanup.push(() => cbs.splice(cbs.indexOf(subscriber), 1));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const cb of cleanup) {
|
|
117
|
+
cb();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function unsubscribe() {
|
|
121
|
+
subscribers.clear();
|
|
122
|
+
}
|
|
123
|
+
function onKeypress(char, key) {
|
|
124
|
+
if (state === "error") {
|
|
125
|
+
state = "active";
|
|
126
|
+
}
|
|
127
|
+
if (key?.name && !_track && aliases.has(key.name)) {
|
|
128
|
+
emit("cursor", aliases.get(key.name));
|
|
129
|
+
}
|
|
130
|
+
if (key?.name && keys.has(key.name)) {
|
|
131
|
+
emit("cursor", key.name);
|
|
132
|
+
}
|
|
133
|
+
if (char && (char.toLowerCase() === "y" || char.toLowerCase() === "n")) {
|
|
134
|
+
emit("confirm", char.toLowerCase() === "y");
|
|
135
|
+
}
|
|
136
|
+
if (char === " " && _opts.placeholder) {
|
|
137
|
+
if (!value) {
|
|
138
|
+
_rl.write(_opts.placeholder);
|
|
139
|
+
emit("value", _opts.placeholder);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (char) {
|
|
143
|
+
emit("key", char.toLowerCase());
|
|
144
|
+
}
|
|
145
|
+
if (key?.name === "return") {
|
|
146
|
+
if (_opts.validate) {
|
|
147
|
+
const problem = _opts.validate(value);
|
|
148
|
+
if (problem) {
|
|
149
|
+
error = problem;
|
|
150
|
+
state = "error";
|
|
151
|
+
_rl.write(value);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (state !== "error") {
|
|
155
|
+
state = "submit";
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (char === "") {
|
|
159
|
+
state = "cancel";
|
|
160
|
+
}
|
|
161
|
+
if (state === "submit" || state === "cancel") {
|
|
162
|
+
emit("finalize");
|
|
163
|
+
}
|
|
164
|
+
render();
|
|
165
|
+
if (state === "submit" || state === "cancel") {
|
|
166
|
+
close();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function close() {
|
|
170
|
+
_input.unpipe();
|
|
171
|
+
_input.removeListener("keypress", onKeypress);
|
|
172
|
+
_output.write("\n");
|
|
173
|
+
setRawMode(_input, false);
|
|
174
|
+
_rl.close();
|
|
175
|
+
emit(state, value);
|
|
176
|
+
unsubscribe();
|
|
177
|
+
}
|
|
178
|
+
function restoreCursor() {
|
|
179
|
+
const lines = wrap(_prevFrame, process.stdout.columns, { hard: true }).split("\n").length - 1;
|
|
180
|
+
_output.write(cursor.move(-999, lines * -1));
|
|
181
|
+
}
|
|
182
|
+
function render() {
|
|
183
|
+
const frame = wrap(_render() || "", process.stdout.columns, {
|
|
184
|
+
hard: true
|
|
185
|
+
});
|
|
186
|
+
if (frame === _prevFrame) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (state === "initial") {
|
|
190
|
+
_output.write(cursor.hide);
|
|
191
|
+
} else {
|
|
192
|
+
const diff = diffLines(_prevFrame, frame);
|
|
193
|
+
restoreCursor();
|
|
194
|
+
if (diff && diff.length === 1) {
|
|
195
|
+
const diffLine = diff[0];
|
|
196
|
+
_output.write(cursor.move(0, diffLine));
|
|
197
|
+
_output.write(erase.lines(1));
|
|
198
|
+
const lines = frame.split("\n");
|
|
199
|
+
_output.write(lines[diffLine]);
|
|
200
|
+
_prevFrame = frame;
|
|
201
|
+
_output.write(cursor.move(0, lines.length - diffLine - 1));
|
|
202
|
+
return;
|
|
203
|
+
} else if (diff && diff.length > 1) {
|
|
204
|
+
const diffLine = diff[0];
|
|
205
|
+
_output.write(cursor.move(0, diffLine));
|
|
206
|
+
_output.write(erase.down());
|
|
207
|
+
const lines = frame.split("\n");
|
|
208
|
+
const newLines = lines.slice(diffLine);
|
|
209
|
+
_output.write(newLines.join("\n"));
|
|
210
|
+
_prevFrame = frame;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
_output.write(erase.down());
|
|
214
|
+
}
|
|
215
|
+
_output.write(frame);
|
|
216
|
+
if (state === "initial") {
|
|
217
|
+
state = "active";
|
|
218
|
+
}
|
|
219
|
+
_prevFrame = frame;
|
|
220
|
+
}
|
|
221
|
+
Object.assign(self, {
|
|
222
|
+
prompt,
|
|
223
|
+
on,
|
|
224
|
+
once,
|
|
225
|
+
emit,
|
|
226
|
+
close,
|
|
227
|
+
render,
|
|
228
|
+
get state() {
|
|
229
|
+
return state;
|
|
230
|
+
},
|
|
231
|
+
set state(val) {
|
|
232
|
+
state = val;
|
|
233
|
+
},
|
|
234
|
+
get value() {
|
|
235
|
+
return value;
|
|
236
|
+
},
|
|
237
|
+
set value(val) {
|
|
238
|
+
value = val;
|
|
239
|
+
},
|
|
240
|
+
get error() {
|
|
241
|
+
return error;
|
|
242
|
+
},
|
|
243
|
+
set error(val) {
|
|
244
|
+
error = val;
|
|
245
|
+
},
|
|
246
|
+
_cursor,
|
|
247
|
+
_track,
|
|
248
|
+
_input,
|
|
249
|
+
_output,
|
|
250
|
+
_rl,
|
|
251
|
+
_opts
|
|
252
|
+
});
|
|
253
|
+
return self;
|
|
254
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
export declare function isCancel(value: unknown): value is symbol;
|
|
3
|
+
export type PromptOptions<Self> = {
|
|
4
|
+
render(this: Omit<Self, "prompt">): string | void;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
initialValue?: any;
|
|
7
|
+
validate?: ((value: any) => string | void) | undefined;
|
|
8
|
+
input?: Readable;
|
|
9
|
+
output?: Writable;
|
|
10
|
+
debug?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type StateDeprecated = "initial" | "active" | "cancel" | "submit" | "error";
|
|
13
|
+
export declare function createPrompt({ render: renderFn, input, output, ...opts }: PromptOptions<any>, trackValue?: boolean): any;
|