@reliverse/relinka 1.1.7 → 1.1.8

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.
Files changed (121) hide show
  1. package/dist-npm/components/anykey/index.js +57 -77
  2. package/dist-npm/components/block/block.js +48 -61
  3. package/dist-npm/components/checkbox/index.js +178 -211
  4. package/dist-npm/components/confirm/confirm-main.js +85 -122
  5. package/dist-npm/components/confirm/confirm-three.js +24 -27
  6. package/dist-npm/components/confirm/index.js +36 -45
  7. package/dist-npm/components/core/Separator.js +15 -17
  8. package/dist-npm/components/core/create-prompt.js +101 -124
  9. package/dist-npm/components/core/errors.js +19 -15
  10. package/dist-npm/components/core/hook-engine.js +91 -120
  11. package/dist-npm/components/core/index.js +12 -12
  12. package/dist-npm/components/core/key.js +16 -6
  13. package/dist-npm/components/core/lines.js +45 -54
  14. package/dist-npm/components/core/make-theme.js +21 -30
  15. package/dist-npm/components/core/position.js +27 -23
  16. package/dist-npm/components/core/promise-polyfill.js +11 -14
  17. package/dist-npm/components/core/screen-manager.js +59 -74
  18. package/dist-npm/components/core/theme.js +22 -32
  19. package/dist-npm/components/core/use-effect.js +9 -15
  20. package/dist-npm/components/core/use-keypress.js +19 -23
  21. package/dist-npm/components/core/use-memo.js +10 -16
  22. package/dist-npm/components/core/use-pagination.js +33 -32
  23. package/dist-npm/components/core/use-prefix.js +40 -38
  24. package/dist-npm/components/core/use-ref.js +2 -5
  25. package/dist-npm/components/core/use-state.js +15 -23
  26. package/dist-npm/components/core/useKeyPress.js +14 -17
  27. package/dist-npm/components/core/usePromptState.js +8 -14
  28. package/dist-npm/components/core/utils.js +7 -16
  29. package/dist-npm/components/date/date.js +173 -204
  30. package/dist-npm/components/editor/index.js +71 -92
  31. package/dist-npm/components/expand/index.js +96 -124
  32. package/dist-npm/components/figures/index.js +283 -294
  33. package/dist-npm/components/input/index.js +61 -87
  34. package/dist-npm/components/input/text-main.js +97 -124
  35. package/dist-npm/components/input/text.js +24 -28
  36. package/dist-npm/components/instance/basic.js +17 -25
  37. package/dist-npm/components/instance/browser.js +14 -18
  38. package/dist-npm/components/instance/reporter/basic.js +46 -65
  39. package/dist-npm/components/instance/reporter/browser.js +44 -47
  40. package/dist-npm/components/instance/reporter/fancy.js +83 -96
  41. package/dist-npm/components/instance/shared.js +2 -2
  42. package/dist-npm/components/mono/mono.js +52 -62
  43. package/dist-npm/components/mono/monoTwo.js +35 -49
  44. package/dist-npm/components/multiselect/group-multiselect.js +55 -71
  45. package/dist-npm/components/multiselect/multi-select-two.js +97 -130
  46. package/dist-npm/components/multiselect/multi-select.js +43 -49
  47. package/dist-npm/components/multiselect/multiselect-main.d.ts +1 -0
  48. package/dist-npm/components/multiselect/multiselect-main.js +158 -145
  49. package/dist-npm/components/multiselect/num-multi-select.js +97 -130
  50. package/dist-npm/components/multiselect/num-multiselect-main.js +24 -35
  51. package/dist-npm/components/next-steps/next-steps.js +23 -25
  52. package/dist-npm/components/number/index.js +78 -112
  53. package/dist-npm/components/number/number-main.js +95 -2
  54. package/dist-npm/components/password/index.js +54 -73
  55. package/dist-npm/components/password/password-main.js +119 -2
  56. package/dist-npm/components/password/password-three.js +26 -30
  57. package/dist-npm/components/progressbar/ProgressBar.js +45 -64
  58. package/dist-npm/components/progressbar/helper.js +33 -40
  59. package/dist-npm/components/progressbar/index.js +1 -1
  60. package/dist-npm/components/prompts/create.js +29 -44
  61. package/dist-npm/components/prompts/index.d.ts +1 -0
  62. package/dist-npm/components/prompts/index.js +46 -45
  63. package/dist-npm/components/prompts/prompt.js +211 -260
  64. package/dist-npm/components/prompts/promptTwo.js +561 -605
  65. package/dist-npm/components/prompts/relinka.js +237 -295
  66. package/dist-npm/components/range/range.js +247 -294
  67. package/dist-npm/components/rawlist/index.js +87 -107
  68. package/dist-npm/components/results/results.js +31 -37
  69. package/dist-npm/components/search/index.js +148 -193
  70. package/dist-npm/components/select/index.js +148 -186
  71. package/dist-npm/components/select/num-select-main.js +27 -27
  72. package/dist-npm/components/select/num-select.js +124 -5
  73. package/dist-npm/components/select/select-key.js +24 -25
  74. package/dist-npm/components/select/select-main.d.ts +1 -0
  75. package/dist-npm/components/select/select-main.js +143 -133
  76. package/dist-npm/components/select/select-three.js +32 -36
  77. package/dist-npm/components/select/select-two.js +94 -87
  78. package/dist-npm/components/spinner/index.js +107 -136
  79. package/dist-npm/components/st-end/end.js +34 -26
  80. package/dist-npm/components/st-end/start.js +29 -15
  81. package/dist-npm/components/toggle/index.js +113 -137
  82. package/dist-npm/components/visual/animate/animate.js +53 -10
  83. package/dist-npm/components/visual/ascii-art/ascii-art.js +12 -1
  84. package/dist-npm/main.js +1 -0
  85. package/dist-npm/testing/index.js +58 -83
  86. package/dist-npm/types/general.d.ts +1 -1
  87. package/dist-npm/types/general.js +0 -1
  88. package/dist-npm/types/index.js +2 -3
  89. package/dist-npm/types/keypress.js +35 -36
  90. package/dist-npm/types/readline.js +0 -1
  91. package/dist-npm/types/relinka.js +0 -1
  92. package/dist-npm/types/utils.js +0 -1
  93. package/dist-npm/utils/box.js +135 -137
  94. package/dist-npm/utils/color.js +65 -74
  95. package/dist-npm/utils/colorize.js +124 -156
  96. package/dist-npm/utils/component.js +532 -657
  97. package/dist-npm/utils/constants.js +64 -63
  98. package/dist-npm/utils/core.js +2 -3
  99. package/dist-npm/utils/decoder.js +244 -223
  100. package/dist-npm/utils/error.js +4 -9
  101. package/dist-npm/utils/errors.js +14 -4
  102. package/dist-npm/utils/format.js +19 -24
  103. package/dist-npm/utils/keypress.js +316 -414
  104. package/dist-npm/utils/log.js +11 -15
  105. package/dist-npm/utils/mapping.js +45 -52
  106. package/dist-npm/utils/messages.js +196 -183
  107. package/dist-npm/utils/platforms.js +16 -20
  108. package/dist-npm/utils/prompt-tmp.js +235 -286
  109. package/dist-npm/utils/prompt-two.js +235 -286
  110. package/dist-npm/utils/readline.js +5 -7
  111. package/dist-npm/utils/skeleton.js +130 -170
  112. package/dist-npm/utils/stream.js +2 -2
  113. package/dist-npm/utils/string.js +44 -58
  114. package/dist-npm/utils/terminal.js +23 -34
  115. package/dist-npm/utils/tree.js +30 -41
  116. package/dist-npm/utils/types.js +0 -1
  117. package/dist-npm/utils/utils.js +8 -8
  118. package/dist-npm/utils/variants.js +36 -44
  119. package/package.json +14 -14
  120. package/dist-npm/mod.js +0 -2
  121. /package/dist-npm/{mod.d.ts → main.d.ts} +0 -0
@@ -1,144 +1,111 @@
1
- import {Value} from '@sinclair/typebox/value';
1
+ import { Value } from "@sinclair/typebox/value";
2
+ import { stdin as input, stdout as output } from "node:process";
3
+ import readline from "node:readline/promises";
4
+ import { colorize } from "../../utils/colorize.js";
5
+ import { bar, fmt, msg } from "../../utils/messages.js";
2
6
  import {
3
- stdin as input,
4
- stdout as output,
5
- } from 'node:process';
6
- import readline from 'node:readline/promises';
7
- import {colorize} from '../../utils/colorize.js';
8
- import {
9
- bar,
10
- fmt,
11
- msg,
12
- } from '../../utils/messages.js';
13
- import {
14
- countLines,
15
- deleteLastLine,
16
- deleteLastLines,
17
- } from '../../utils/terminal.js';
18
-
7
+ countLines,
8
+ deleteLastLine,
9
+ deleteLastLines
10
+ } from "../../utils/terminal.js";
19
11
  export async function numMultiSelectPrompt(options) {
20
- const {
21
- title,
22
- choices,
23
- schema,
24
- defaultValue,
25
- titleColor = 'cyanBright',
26
- titleTypography = 'bold',
12
+ const {
13
+ title,
14
+ choices,
15
+ schema,
16
+ defaultValue,
17
+ titleColor = "cyanBright",
18
+ titleTypography = "bold",
19
+ titleVariant,
20
+ hint,
21
+ content,
22
+ contentColor = "dim",
23
+ contentTypography,
24
+ contentVariant,
25
+ borderColor = "viceGradient",
26
+ variantOptions
27
+ } = options;
28
+ if (!choices || choices.length === 0) {
29
+ throw new Error("Choices are required for multiselect prompt.");
30
+ }
31
+ const rl = readline.createInterface({ input, output });
32
+ const formattedBar = bar({ borderColor });
33
+ let linesToDelete = 0;
34
+ let errorMessage = "";
35
+ try {
36
+ while (true) {
37
+ if (linesToDelete > 0) {
38
+ deleteLastLines(linesToDelete);
39
+ }
40
+ const question = fmt({
41
+ type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
42
+ title: `${title}${defaultValue ? ` [Default: ${Array.isArray(defaultValue) ? defaultValue.join(", ") : defaultValue}]` : ""}`,
43
+ titleColor,
44
+ titleTypography,
27
45
  titleVariant,
28
- hint,
29
46
  content,
30
- contentColor = 'dim',
47
+ contentColor,
31
48
  contentTypography,
32
49
  contentVariant,
33
- borderColor = 'viceGradient',
34
- variantOptions,
35
- } = options;
36
-
37
- if (!choices || !choices.length) {
38
- throw Error('Choices are required for multiselect prompt.');
39
- }
40
-
41
- const rl = readline.createInterface({
42
- input,
43
- output,
44
- });
45
- const formattedBar = bar({
46
50
  borderColor,
47
- });
48
- let linesToDelete = 0;
49
- let errorMessage = '';
50
-
51
- try {
52
- while (true) {
53
- if (linesToDelete > 0) {
54
- deleteLastLines(linesToDelete);
55
- }
56
-
57
- const question = fmt({
58
- type: errorMessage !== '' ? 'M_ERROR' : 'M_GENERAL',
59
- title: `${title}${defaultValue ? ` [Default: ${Array.isArray(defaultValue) ? defaultValue.join(', ') : defaultValue}]` : ''}`,
60
- titleColor,
61
- titleTypography,
62
- titleVariant,
63
- content,
64
- contentColor,
65
- contentTypography,
66
- contentVariant,
67
- borderColor,
68
- hint,
69
- variantOptions,
70
- errorMessage,
71
- addNewLineBefore: false,
72
- addNewLineAfter: false,
73
- });
74
-
75
- const choicesText = choices
76
- .map((choice, index) => `${formattedBar} ${index + 1}) ${choice.title}${choice.description ? ` - ${choice.description}` : ''}`)
77
- .join('\n');
78
-
79
- const fullPrompt = `${question}
51
+ hint,
52
+ variantOptions,
53
+ errorMessage,
54
+ addNewLineBefore: false,
55
+ addNewLineAfter: false
56
+ });
57
+ const choicesText = choices.map(
58
+ (choice, index) => `${formattedBar} ${index + 1}) ${choice.title}${choice.description ? ` - ${choice.description}` : ""}`
59
+ ).join("\n");
60
+ const fullPrompt = `${question}
80
61
  ${choicesText}
81
62
  ${formattedBar} ${colorize(`Enter your choices (comma-separated numbers between 1-${choices.length})`, contentColor)}:
82
63
  ${formattedBar} `;
83
-
84
- const formattedPrompt = fmt({
85
- type: 'M_NULL',
86
- title: fullPrompt,
87
- });
88
-
89
- const questionLines = countLines(formattedPrompt);
90
-
91
- linesToDelete = questionLines + 1;
92
- const answer = (await rl.question(formattedPrompt)).trim();
93
-
94
- if (!answer && defaultValue !== void 0) {
95
- deleteLastLine();
96
- msg({
97
- type: 'M_MIDDLE',
98
- title: ` ${Array.isArray(defaultValue) ? defaultValue.join(', ') : defaultValue}`,
99
- titleColor: 'none',
100
- });
101
- msg({
102
- type: 'M_NEWLINE',
103
- });
104
- return defaultValue;
105
- }
106
-
107
- const selections = answer
108
- .split(',')
109
- .map((s) => s.trim());
110
-
111
- const invalidSelections = selections.filter((s) => {
112
- const num = Number(s);
113
- return isNaN(num) || num < 1 || num > choices.length;
114
- });
115
-
116
- if (invalidSelections.length > 0) {
117
- errorMessage = `Invalid selections: ${invalidSelections.join(', ')}. Please enter numbers between 1 and ${choices.length}.`;
118
- continue;
119
- }
120
-
121
- const selectedValues = selections.map((s) => choices[Number(s) - 1]?.id);
122
- let isValid = true;
123
-
124
- errorMessage = '';
125
- if (schema) {
126
- isValid = Value.Check(schema, selectedValues);
127
- if (!isValid) {
128
- const errors = Value.Errors(schema, selectedValues);
129
- errorMessage = errors.length > 0 ? errors[0]?.message ?? 'Invalid input.' : 'Invalid input.';
130
- }
131
- }
132
-
133
- if (isValid) {
134
- msg({
135
- type: 'M_NEWLINE',
136
- });
137
- rl.close();
138
- return selectedValues;
139
- }
64
+ const formattedPrompt = fmt({
65
+ type: "M_NULL",
66
+ title: fullPrompt
67
+ });
68
+ const questionLines = countLines(formattedPrompt);
69
+ linesToDelete = questionLines + 1;
70
+ const answer = (await rl.question(formattedPrompt)).trim();
71
+ if (!answer && defaultValue !== void 0) {
72
+ deleteLastLine();
73
+ msg({
74
+ type: "M_MIDDLE",
75
+ title: ` ${Array.isArray(defaultValue) ? defaultValue.join(", ") : defaultValue}`,
76
+ titleColor: "none"
77
+ });
78
+ msg({ type: "M_NEWLINE" });
79
+ return defaultValue;
80
+ }
81
+ const selections = answer.split(",").map((s) => s.trim());
82
+ const invalidSelections = selections.filter((s) => {
83
+ const num = Number(s);
84
+ return isNaN(num) || num < 1 || num > choices.length;
85
+ });
86
+ if (invalidSelections.length > 0) {
87
+ errorMessage = `Invalid selections: ${invalidSelections.join(
88
+ ", "
89
+ )}. Please enter numbers between 1 and ${choices.length}.`;
90
+ continue;
91
+ }
92
+ const selectedValues = selections.map((s) => choices[Number(s) - 1]?.id);
93
+ let isValid = true;
94
+ errorMessage = "";
95
+ if (schema) {
96
+ isValid = Value.Check(schema, selectedValues);
97
+ if (!isValid) {
98
+ const errors = [...Value.Errors(schema, selectedValues)];
99
+ errorMessage = errors.length > 0 ? errors[0]?.message ?? "Invalid input." : "Invalid input.";
140
100
  }
141
- } finally {
101
+ }
102
+ if (isValid) {
103
+ msg({ type: "M_NEWLINE" });
142
104
  rl.close();
105
+ return selectedValues;
106
+ }
143
107
  }
108
+ } finally {
109
+ rl.close();
110
+ }
144
111
  }
@@ -1,39 +1,28 @@
1
- import {
2
- stdin as input,
3
- stdout as output,
4
- } from 'node:process';
5
- import readline from 'node:readline/promises';
6
-
1
+ import { stdin as input, stdout as output } from "process";
2
+ import readline from "readline/promises";
7
3
  export async function multiselectPrompt(params) {
8
- const {
9
- options,
10
- required = false,
11
- initial = [],
12
- } = params;
13
- const rl = readline.createInterface({
14
- input,
15
- output,
4
+ const { message, options, required = false, initial = [] } = params;
5
+ const rl = readline.createInterface({ input, output });
6
+ while (true) {
7
+ console.log(`
8
+ ${message}`);
9
+ options.forEach((option, index) => {
10
+ const isSelected = initial.includes(option) ? "[x]" : "[ ]";
11
+ console.log(`${index + 1}. ${isSelected} ${option}`);
16
12
  });
17
-
18
- while (true) {
19
- const promptMessage = initial.length > 0 ? `Please select options by number (separated by commas, default ${initial
20
- .map((opt) => options.indexOf(opt) + 1)
21
- .join(', ')}): ` : 'Please select options by number (separated by commas): ';
22
- const response = await rl.question(promptMessage);
23
- let indices;
24
-
25
- if (response.trim() === '' && initial.length > 0) {
26
- indices = initial.map((opt) => options.indexOf(opt));
27
- } else {
28
- indices = response
29
- .split(',')
30
- .map((num) => parseInt(num.trim(), 10) - 1)
31
- .filter((index) => index >= 0 && index < options.length);
32
- }
33
-
34
- if (indices.length > 0 || !required && !indices.length) {
35
- rl.close();
36
- return indices.map((index) => options[index]);
37
- }
13
+ const promptMessage = initial.length > 0 ? `Please select options by number (separated by commas, default ${initial.map((opt) => options.indexOf(opt) + 1).join(", ")}): ` : "Please select options by number (separated by commas): ";
14
+ const response = await rl.question(promptMessage);
15
+ let indices;
16
+ if (response.trim() === "" && initial.length > 0) {
17
+ indices = initial.map((opt) => options.indexOf(opt));
18
+ } else {
19
+ indices = response.split(",").map((num) => parseInt(num.trim(), 10) - 1).filter((index) => index >= 0 && index < options.length);
38
20
  }
21
+ if (indices.length > 0 || !required && indices.length === 0) {
22
+ rl.close();
23
+ return indices.map((index) => options[index]);
24
+ } else {
25
+ console.log("Invalid selection. Please try again.");
26
+ }
27
+ }
39
28
  }
@@ -1,26 +1,24 @@
1
- import {msg} from '../../utils/messages.js';
2
-
3
- export function nextStepsPrompt(options) {
4
- const {
5
- title,
6
- titleColor = 'cyanBright',
7
- titleVariant,
8
- titleTypography = 'bold',
9
- content,
10
- contentColor,
11
- contentVariant,
12
- contentTypography,
13
- } = options;
14
-
15
- msg({
16
- type: 'M_INFO',
17
- title,
18
- titleColor,
19
- titleVariant,
20
- titleTypography,
21
- content,
22
- contentColor,
23
- contentVariant,
24
- contentTypography,
25
- });
1
+ import { msg } from "../../utils/messages.js";
2
+ export async function nextStepsPrompt(options) {
3
+ const {
4
+ title,
5
+ titleColor = "cyanBright",
6
+ titleVariant,
7
+ titleTypography = "bold",
8
+ content,
9
+ contentColor,
10
+ contentVariant,
11
+ contentTypography
12
+ } = options;
13
+ msg({
14
+ type: "M_INFO",
15
+ title,
16
+ titleColor,
17
+ titleVariant,
18
+ titleTypography,
19
+ content,
20
+ contentColor,
21
+ contentVariant,
22
+ contentTypography
23
+ });
26
24
  }
@@ -1,134 +1,100 @@
1
1
  import {
2
- createPrompt,
3
- useState,
4
- useKeypress,
5
- usePrefix,
6
- isEnterKey,
7
- isBackspaceKey,
8
- makeTheme,
9
- } from '../../components/core/index.js';
10
-
2
+ createPrompt,
3
+ useState,
4
+ useKeypress,
5
+ usePrefix,
6
+ isEnterKey,
7
+ isBackspaceKey,
8
+ makeTheme
9
+ } from "../../components/core/index.js";
11
10
  function isStepOf(value, step, min) {
12
- const valuePow = value * 10 ** 6;
13
- const stepPow = step * 10 ** 6;
14
- const minPow = min * 10 ** 6;
15
-
16
- return !((valuePow - (Number.isFinite(min) ? minPow : 0)) % stepPow);
11
+ const valuePow = value * Math.pow(10, 6);
12
+ const stepPow = step * Math.pow(10, 6);
13
+ const minPow = min * Math.pow(10, 6);
14
+ return (valuePow - (Number.isFinite(min) ? minPow : 0)) % stepPow === 0;
17
15
  }
18
-
19
- function validateNumber(value, {min, max, step}) {
20
- if (value == null || Number.isNaN(value)) {
21
- return false;
22
- }
23
-
24
- if (value < min || value > max) {
25
- return `Value must be between ${min} and ${max}`;
26
- }
27
-
28
- if (step !== 'any' && !isStepOf(value, step, min)) {
29
- return `Value must be a multiple of ${step}${Number.isFinite(min) ? ` starting from ${min}` : ''}`;
30
- }
31
-
32
- return true;
16
+ function validateNumber(value, {
17
+ min,
18
+ max,
19
+ step
20
+ }) {
21
+ if (value == null || Number.isNaN(value)) {
22
+ return false;
23
+ } else if (value < min || value > max) {
24
+ return `Value must be between ${min} and ${max}`;
25
+ } else if (step !== "any" && !isStepOf(value, step, min)) {
26
+ return `Value must be a multiple of ${step}${Number.isFinite(min) ? ` starting from ${min}` : ""}`;
27
+ }
28
+ return true;
33
29
  }
34
-
35
- export default createPrompt((config, done) => {
30
+ export default createPrompt(
31
+ (config, done) => {
36
32
  const {
37
- validate = () => true,
38
- min = -Infinity,
39
- max = Infinity,
40
- step = 1,
41
- required = false,
33
+ validate = () => true,
34
+ min = -Infinity,
35
+ max = Infinity,
36
+ step = 1,
37
+ required = false
42
38
  } = config;
43
-
44
39
  const theme = makeTheme(config.theme);
45
- const [status, setStatus] = useState('idle');
46
- const [value, setValue] = useState('');
47
- const validDefault = validateNumber(config.default, {
48
- min,
49
- max,
50
- step,
51
- }) ? config.default?.toString() : void 0;
52
- const [defaultValue = '', setDefaultValue] = useState(validDefault);
40
+ const [status, setStatus] = useState("idle");
41
+ const [value, setValue] = useState("");
42
+ const validDefault = validateNumber(config.default, { min, max, step }) === true ? config.default?.toString() : void 0;
43
+ const [defaultValue = "", setDefaultValue] = useState(validDefault);
53
44
  const [errorMsg, setError] = useState();
54
- const prefix = usePrefix({
55
- status,
56
- theme,
57
- });
58
-
45
+ const prefix = usePrefix({ status, theme });
59
46
  useKeypress(async (key, rl) => {
60
- if (status !== 'idle') {
61
- return;
47
+ if (status !== "idle") {
48
+ return;
49
+ }
50
+ if (isEnterKey(key)) {
51
+ const input = value || defaultValue;
52
+ const answer = input === "" ? void 0 : Number(input);
53
+ setStatus("loading");
54
+ let isValid = true;
55
+ if (required || answer != null) {
56
+ isValid = validateNumber(answer, { min, max, step });
57
+ }
58
+ if (isValid === true) {
59
+ isValid = await validate(answer);
62
60
  }
63
-
64
- if (isEnterKey(key)) {
65
- const input = value || defaultValue;
66
- const answer = input === '' ? void 0 : Number(input);
67
- setStatus('loading');
68
- let isValid = true;
69
-
70
- if (required || answer != null) {
71
- isValid = validateNumber(answer, {
72
- min,
73
- max,
74
- step,
75
- });
76
- }
77
-
78
- if (isValid) {
79
- isValid = await validate(answer);
80
- }
81
-
82
- if (isValid) {
83
- setValue(String(answer ?? ''));
84
- setStatus('done');
85
- done(answer);
86
- } else {
87
- rl.write(value);
88
- setError(isValid || 'You must provide a valid numeric value');
89
- setStatus('idle');
90
- }
91
- } else if (isBackspaceKey(key) && !value) {
92
- setDefaultValue(void 0);
93
- } else if (key.name === 'tab' && !value) {
94
- setDefaultValue(void 0);
95
- rl.clearLine(0);
96
- rl.write(defaultValue);
97
- setValue(defaultValue);
61
+ if (isValid === true) {
62
+ setValue(String(answer ?? ""));
63
+ setStatus("done");
64
+ done(answer);
98
65
  } else {
99
- setValue(rl.line);
100
- setError(void 0);
66
+ rl.write(value);
67
+ setError(isValid || "You must provide a valid numeric value");
68
+ setStatus("idle");
101
69
  }
102
-
70
+ } else if (isBackspaceKey(key) && !value) {
71
+ setDefaultValue(void 0);
72
+ } else if (key.name === "tab" && !value) {
73
+ setDefaultValue(void 0);
74
+ rl.clearLine(0);
75
+ rl.write(defaultValue);
76
+ setValue(defaultValue);
77
+ } else {
78
+ setValue(rl.line);
79
+ setError(void 0);
80
+ }
103
81
  });
104
82
  const message = theme.style.message(config.message, status);
105
83
  let formattedValue = value;
106
-
107
- if (status === 'done') {
108
- formattedValue = theme.style.answer(value);
84
+ if (status === "done") {
85
+ formattedValue = theme.style.answer(value);
109
86
  }
110
-
111
87
  let defaultStr;
112
-
113
- if (defaultValue && status !== 'done' && !value) {
114
- defaultStr = theme.style.defaultAnswer(defaultValue);
88
+ if (defaultValue && status !== "done" && !value) {
89
+ defaultStr = theme.style.defaultAnswer(defaultValue);
115
90
  }
116
-
117
- let error = '';
118
-
91
+ let error = "";
119
92
  if (errorMsg) {
120
- error = theme.style.error(errorMsg);
93
+ error = theme.style.error(errorMsg);
121
94
  }
122
-
123
95
  return [
124
- [
125
- prefix,
126
- message,
127
- defaultStr,
128
- formattedValue,
129
- ]
130
- .filter((v) => v !== void 0)
131
- .join(' '),
132
- error,
96
+ [prefix, message, defaultStr, formattedValue].filter((v) => v !== void 0).join(" "),
97
+ error
133
98
  ];
134
- });
99
+ }
100
+ );
@@ -1,2 +1,95 @@
1
- export function numberPrompt() {
2
- while (true) {}}
1
+ import { Value } from "@sinclair/typebox/value";
2
+ import { stdin as input, stdout as output } from "node:process";
3
+ import readline from "node:readline/promises";
4
+ import { fmt, msg } from "../../utils/messages.js";
5
+ import {
6
+ countLines,
7
+ deleteLastLine,
8
+ deleteLastLines
9
+ } from "../../utils/terminal.js";
10
+ export async function numberPrompt(options) {
11
+ const {
12
+ title,
13
+ hint,
14
+ validate,
15
+ defaultValue,
16
+ schema,
17
+ titleColor = "cyanBright",
18
+ titleTypography = "bold",
19
+ titleVariant,
20
+ content,
21
+ contentColor,
22
+ contentTypography,
23
+ contentVariant,
24
+ borderColor = "viceGradient",
25
+ variantOptions
26
+ } = options;
27
+ const rl = readline.createInterface({ input, output });
28
+ let linesToDelete = 0;
29
+ let errorMessage = "";
30
+ while (true) {
31
+ if (linesToDelete > 0) {
32
+ deleteLastLines(linesToDelete);
33
+ }
34
+ const question = fmt({
35
+ type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
36
+ title,
37
+ titleColor,
38
+ titleTypography,
39
+ titleVariant,
40
+ content,
41
+ contentColor,
42
+ contentTypography,
43
+ contentVariant,
44
+ borderColor,
45
+ hint,
46
+ variantOptions,
47
+ errorMessage
48
+ });
49
+ const questionLines = countLines(question);
50
+ const prompt = await rl.question(question);
51
+ linesToDelete = questionLines + 1;
52
+ const answer = prompt.trim() || defaultValue;
53
+ if (prompt.trim() === "" && defaultValue !== void 0) {
54
+ deleteLastLine();
55
+ const defaultMsg = fmt({
56
+ type: "M_MIDDLE",
57
+ title: ` ${defaultValue}`,
58
+ borderColor
59
+ });
60
+ console.log(defaultMsg);
61
+ linesToDelete += countLines(defaultMsg);
62
+ }
63
+ const num = Number(answer);
64
+ if (isNaN(num)) {
65
+ errorMessage = "Please enter a valid number.";
66
+ continue;
67
+ }
68
+ let isValid = true;
69
+ errorMessage = "";
70
+ if (schema) {
71
+ isValid = Value.Check(schema, num);
72
+ if (!isValid) {
73
+ const errors = [...Value.Errors(schema, num)];
74
+ if (errors.length > 0) {
75
+ errorMessage = errors[0]?.message ?? "Invalid input.";
76
+ } else {
77
+ errorMessage = "Invalid input.";
78
+ }
79
+ }
80
+ }
81
+ if (validate && isValid) {
82
+ const validation = await validate(num);
83
+ if (validation !== true) {
84
+ isValid = false;
85
+ errorMessage = typeof validation === "string" ? validation : "Invalid input.";
86
+ }
87
+ }
88
+ if (isValid) {
89
+ msg({ type: "M_NEWLINE" });
90
+ rl.close();
91
+ return num;
92
+ } else {
93
+ }
94
+ }
95
+ }