@sundaeswap/sprinkles 0.5.0 → 0.6.1
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/dist/cjs/Sprinkle/__tests__/encryption.test.js +3 -1
- package/dist/cjs/Sprinkle/__tests__/encryption.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/enhancements.test.js +3 -37
- package/dist/cjs/Sprinkle/__tests__/enhancements.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/field-utils.test.js +170 -0
- package/dist/cjs/Sprinkle/__tests__/field-utils.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js +377 -84
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/formatting.test.js +97 -0
- package/dist/cjs/Sprinkle/__tests__/formatting.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/show-menu.test.js +9 -5
- package/dist/cjs/Sprinkle/__tests__/show-menu.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js +9 -0
- package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
- package/dist/cjs/Sprinkle/index.js +174 -94
- package/dist/cjs/Sprinkle/index.js.map +1 -1
- package/dist/cjs/Sprinkle/menus/array-menu.js +195 -0
- package/dist/cjs/Sprinkle/menus/array-menu.js.map +1 -0
- package/dist/cjs/Sprinkle/menus/field-menu.js +161 -0
- package/dist/cjs/Sprinkle/menus/field-menu.js.map +1 -0
- package/dist/cjs/Sprinkle/menus/index.js +33 -0
- package/dist/cjs/Sprinkle/menus/index.js.map +1 -0
- package/dist/cjs/Sprinkle/menus/object-menu.js +324 -0
- package/dist/cjs/Sprinkle/menus/object-menu.js.map +1 -0
- package/dist/cjs/Sprinkle/prompts.js +68 -2
- package/dist/cjs/Sprinkle/prompts.js.map +1 -1
- package/dist/cjs/Sprinkle/type-guards.js +48 -1
- package/dist/cjs/Sprinkle/type-guards.js.map +1 -1
- package/dist/cjs/Sprinkle/types.js +24 -0
- package/dist/cjs/Sprinkle/types.js.map +1 -1
- package/dist/cjs/Sprinkle/utils/field-utils.js +154 -0
- package/dist/cjs/Sprinkle/utils/field-utils.js.map +1 -0
- package/dist/cjs/Sprinkle/utils/formatting.js +126 -0
- package/dist/cjs/Sprinkle/utils/formatting.js.map +1 -0
- package/dist/cjs/Sprinkle/utils/index.js +56 -0
- package/dist/cjs/Sprinkle/utils/index.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/encryption.test.js +3 -1
- package/dist/esm/Sprinkle/__tests__/encryption.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/enhancements.test.js +3 -37
- package/dist/esm/Sprinkle/__tests__/enhancements.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/field-utils.test.js +168 -0
- package/dist/esm/Sprinkle/__tests__/field-utils.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +378 -85
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/formatting.test.js +95 -0
- package/dist/esm/Sprinkle/__tests__/formatting.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/show-menu.test.js +9 -5
- package/dist/esm/Sprinkle/__tests__/show-menu.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js +9 -0
- package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
- package/dist/esm/Sprinkle/index.js +141 -96
- package/dist/esm/Sprinkle/index.js.map +1 -1
- package/dist/esm/Sprinkle/menus/array-menu.js +190 -0
- package/dist/esm/Sprinkle/menus/array-menu.js.map +1 -0
- package/dist/esm/Sprinkle/menus/field-menu.js +155 -0
- package/dist/esm/Sprinkle/menus/field-menu.js.map +1 -0
- package/dist/esm/Sprinkle/menus/index.js +8 -0
- package/dist/esm/Sprinkle/menus/index.js.map +1 -0
- package/dist/esm/Sprinkle/menus/object-menu.js +318 -0
- package/dist/esm/Sprinkle/menus/object-menu.js.map +1 -0
- package/dist/esm/Sprinkle/prompts.js +59 -1
- package/dist/esm/Sprinkle/prompts.js.map +1 -1
- package/dist/esm/Sprinkle/type-guards.js +42 -0
- package/dist/esm/Sprinkle/type-guards.js.map +1 -1
- package/dist/esm/Sprinkle/types.js +24 -0
- package/dist/esm/Sprinkle/types.js.map +1 -1
- package/dist/esm/Sprinkle/utils/field-utils.js +145 -0
- package/dist/esm/Sprinkle/utils/field-utils.js.map +1 -0
- package/dist/esm/Sprinkle/utils/formatting.js +118 -0
- package/dist/esm/Sprinkle/utils/formatting.js.map +1 -0
- package/dist/esm/Sprinkle/utils/index.js +7 -0
- package/dist/esm/Sprinkle/utils/index.js.map +1 -0
- package/dist/types/Sprinkle/index.d.ts +9 -3
- package/dist/types/Sprinkle/index.d.ts.map +1 -1
- package/dist/types/Sprinkle/menus/array-menu.d.ts +31 -0
- package/dist/types/Sprinkle/menus/array-menu.d.ts.map +1 -0
- package/dist/types/Sprinkle/menus/field-menu.d.ts +34 -0
- package/dist/types/Sprinkle/menus/field-menu.d.ts.map +1 -0
- package/dist/types/Sprinkle/menus/index.d.ts +10 -0
- package/dist/types/Sprinkle/menus/index.d.ts.map +1 -0
- package/dist/types/Sprinkle/menus/object-menu.d.ts +34 -0
- package/dist/types/Sprinkle/menus/object-menu.d.ts.map +1 -0
- package/dist/types/Sprinkle/prompts.d.ts +25 -0
- package/dist/types/Sprinkle/prompts.d.ts.map +1 -1
- package/dist/types/Sprinkle/type-guards.d.ts +24 -1
- package/dist/types/Sprinkle/type-guards.d.ts.map +1 -1
- package/dist/types/Sprinkle/types.d.ts +53 -0
- package/dist/types/Sprinkle/types.d.ts.map +1 -1
- package/dist/types/Sprinkle/utils/field-utils.d.ts +47 -0
- package/dist/types/Sprinkle/utils/field-utils.d.ts.map +1 -0
- package/dist/types/Sprinkle/utils/formatting.d.ts +30 -0
- package/dist/types/Sprinkle/utils/formatting.d.ts.map +1 -0
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Sprinkle/__tests__/encryption.test.ts +2 -0
- package/src/Sprinkle/__tests__/enhancements.test.ts +3 -42
- package/src/Sprinkle/__tests__/field-utils.test.ts +191 -0
- package/src/Sprinkle/__tests__/fill-in-struct.test.ts +393 -100
- package/src/Sprinkle/__tests__/formatting.test.ts +115 -0
- package/src/Sprinkle/__tests__/show-menu.test.ts +14 -8
- package/src/Sprinkle/__tests__/tx-dialog.test.ts +9 -0
- package/src/Sprinkle/index.ts +175 -122
- package/src/Sprinkle/menus/array-menu.ts +191 -0
- package/src/Sprinkle/menus/field-menu.ts +145 -0
- package/src/Sprinkle/menus/index.ts +12 -0
- package/src/Sprinkle/menus/object-menu.ts +336 -0
- package/src/Sprinkle/prompts.ts +71 -1
- package/src/Sprinkle/type-guards.ts +42 -0
- package/src/Sprinkle/types.ts +43 -0
- package/src/Sprinkle/utils/field-utils.ts +158 -0
- package/src/Sprinkle/utils/formatting.ts +127 -0
- package/src/Sprinkle/utils/index.ts +17 -0
|
@@ -3,9 +3,17 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.clearLines = clearLines;
|
|
7
|
+
exports.confirmCancellable = void 0;
|
|
8
|
+
exports.confirmWithClear = confirmWithClear;
|
|
9
|
+
exports.inputCancellable = void 0;
|
|
10
|
+
exports.inputWithClear = inputWithClear;
|
|
11
|
+
exports.passwordCancellable = void 0;
|
|
12
|
+
exports.passwordWithClear = passwordWithClear;
|
|
13
|
+
exports.searchCancellable = void 0;
|
|
7
14
|
exports.select = select;
|
|
8
15
|
exports.selectCancellable = void 0;
|
|
16
|
+
exports.selectWithClear = selectWithClear;
|
|
9
17
|
var _core = require("@inquirer/core");
|
|
10
18
|
var _yoctocolorsCjs = _interopRequireDefault(require("yoctocolors-cjs"));
|
|
11
19
|
var _figures = _interopRequireDefault(require("@inquirer/figures"));
|
|
@@ -69,7 +77,7 @@ function normalizeChoices(choices) {
|
|
|
69
77
|
const selectCancellable = exports.selectCancellable = (0, _core.createPrompt)((config, done) => {
|
|
70
78
|
const {
|
|
71
79
|
loop = true,
|
|
72
|
-
pageSize =
|
|
80
|
+
pageSize = 15
|
|
73
81
|
} = config;
|
|
74
82
|
const theme = (0, _core.makeTheme)(selectTheme, config.theme);
|
|
75
83
|
const [status, setStatus] = (0, _core.useState)("idle");
|
|
@@ -164,6 +172,64 @@ const selectCancellable = exports.selectCancellable = (0, _core.createPrompt)((c
|
|
|
164
172
|
const helpTip = _yoctocolorsCjs.default.dim("(Use arrow keys, Enter to select, Esc to cancel)");
|
|
165
173
|
return `${prefix} ${config.message} ${helpTip}\n${page}`;
|
|
166
174
|
});
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Clears N lines above the cursor.
|
|
178
|
+
* Used after prompts to clean up menu output.
|
|
179
|
+
*/
|
|
180
|
+
function clearLines(count) {
|
|
181
|
+
// Move up and clear each line
|
|
182
|
+
process.stdout.write("\x1b[1A\x1b[2K".repeat(count));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Select prompt that clears its output after completion.
|
|
187
|
+
* Returns the selected value or null if cancelled.
|
|
188
|
+
*/
|
|
189
|
+
async function selectWithClear(config) {
|
|
190
|
+
const result = await selectCancellable(config);
|
|
191
|
+
|
|
192
|
+
// Clear the "done" line that inquirer left behind
|
|
193
|
+
// Move up one line, clear it, move cursor to start
|
|
194
|
+
process.stdout.write("\x1b[1A\x1b[2K\x1b[G");
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Input prompt that clears its output after completion.
|
|
200
|
+
* Returns the input value or null if cancelled.
|
|
201
|
+
*/
|
|
202
|
+
async function inputWithClear(config) {
|
|
203
|
+
const result = await inputCancellable(config);
|
|
204
|
+
|
|
205
|
+
// Clear the "done" line
|
|
206
|
+
process.stdout.write("\x1b[1A\x1b[2K\x1b[G");
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Password prompt that clears its output after completion.
|
|
212
|
+
* Returns the password or null if cancelled.
|
|
213
|
+
*/
|
|
214
|
+
async function passwordWithClear(config) {
|
|
215
|
+
const result = await passwordCancellable(config);
|
|
216
|
+
|
|
217
|
+
// Clear the "done" line
|
|
218
|
+
process.stdout.write("\x1b[1A\x1b[2K\x1b[G");
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Confirm prompt that clears its output after completion.
|
|
224
|
+
* Returns true/false or null if cancelled.
|
|
225
|
+
*/
|
|
226
|
+
async function confirmWithClear(config) {
|
|
227
|
+
const result = await confirmCancellable(config);
|
|
228
|
+
|
|
229
|
+
// Clear the "done" line
|
|
230
|
+
process.stdout.write("\x1b[1A\x1b[2K\x1b[G");
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
167
233
|
/**
|
|
168
234
|
* Input prompt with escape key support.
|
|
169
235
|
* Returns null if user presses Escape.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","names":["_core","require","_yoctocolorsCjs","_interopRequireDefault","_figures","e","__esModule","default","isEscapeKey","key","name","selectTheme","icon","cursor","figures","pointer","style","disabled","text","colors","dim","description","cyan","helpTip","helpMode","inputTheme","isSelectable","item","Separator","isSeparator","normalizeChoices","choices","map","choice","value","short","String","selectCancellable","exports","createPrompt","config","done","loop","pageSize","theme","makeTheme","status","setStatus","useState","prefix","usePrefix","items","useMemo","bounds","first","findIndex","last","i","length","ValidationError","defaultItemIndex","active","setActive","selectedChoice","useKeypress","rl","isEnterKey","isUpKey","clearLine","newActive","isDownKey","page","usePagination","renderItem","isActive","separator","line","disabledLabel","color","x","message","inputCancellable","setValue","touched","setTouched","error","setError","answer","validate","result","isBackspaceKey","ctrl","meta","displayValue","transformer","isFinal","errorMsg","red","passwordCancellable","mask","slice","char","sequence","masked","repeat","confirmCancellable","undefined","hint","select","searchCancellable","searchTerm","setSearchTerm","results","setResults","loading","setLoading","source","selected","searchLine","resultLines","join"],"sources":["../../../src/Sprinkle/prompts.ts"],"sourcesContent":["/**\n * Cancellable prompt wrappers with escape key support.\n * Uses @inquirer/core's createPrompt and useKeypress for proper escape handling.\n */\n\nimport {\n createPrompt,\n useState,\n useKeypress,\n usePrefix,\n usePagination,\n useMemo,\n makeTheme,\n isEnterKey,\n isUpKey,\n isDownKey,\n isBackspaceKey,\n Separator,\n ValidationError,\n type Theme,\n} from \"@inquirer/core\";\nimport type { PartialDeep } from \"@inquirer/type\";\nimport colors from \"yoctocolors-cjs\";\nimport figures from \"@inquirer/figures\";\n\n// Check if key is escape\nconst isEscapeKey = (key: { name: string }) => key.name === \"escape\";\n\n// Theme for select prompt\nconst selectTheme = {\n icon: { cursor: figures.pointer },\n style: {\n disabled: (text: string) => colors.dim(`- ${text}`),\n description: (text: string) => colors.cyan(text),\n helpTip: colors.dim(\"(Use arrow keys, Enter to select, Esc to cancel)\"),\n },\n helpMode: \"always\" as const,\n};\n\n// Theme for input prompt\nconst inputTheme = {\n style: {\n helpTip: colors.dim(\"(Esc to cancel)\"),\n },\n};\n\ninterface SelectChoice<T> {\n name?: string;\n value: T;\n description?: string;\n short?: string;\n disabled?: boolean | string;\n}\n\ninterface SelectConfig<T> {\n message: string;\n choices: ReadonlyArray<SelectChoice<T> | Separator | string>;\n default?: T;\n pageSize?: number;\n loop?: boolean;\n theme?: PartialDeep<Theme<typeof selectTheme>>;\n}\n\nfunction isSelectable<T>(item: SelectChoice<T> | Separator): item is SelectChoice<T> {\n return !Separator.isSeparator(item) && !item.disabled;\n}\n\nfunction normalizeChoices<T>(\n choices: ReadonlyArray<SelectChoice<T> | Separator | string>,\n): Array<SelectChoice<T> | Separator> {\n return choices.map((choice) => {\n if (Separator.isSeparator(choice)) return choice;\n if (typeof choice === \"string\") {\n return {\n value: choice as unknown as T,\n name: choice,\n short: choice,\n disabled: false,\n };\n }\n const name = choice.name ?? String(choice.value);\n return {\n value: choice.value,\n name,\n short: choice.short ?? name,\n disabled: choice.disabled ?? false,\n description: choice.description,\n };\n });\n}\n\n/**\n * Select prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const selectCancellable = createPrompt<\n unknown | null,\n SelectConfig<unknown>\n>((config, done) => {\n const { loop = true, pageSize = 7 } = config;\n const theme = makeTheme(selectTheme, config.theme);\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n const items = useMemo(\n () => normalizeChoices(config.choices),\n [config.choices],\n );\n\n const bounds = useMemo(() => {\n const first = items.findIndex(isSelectable);\n // Find last selectable item (compatible with es2022)\n let last = -1;\n for (let i = items.length - 1; i >= 0; i--) {\n if (isSelectable(items[i]!)) {\n last = i;\n break;\n }\n }\n if (first === -1) {\n throw new ValidationError(\n \"[select prompt] No selectable choices. All choices are disabled.\",\n );\n }\n return { first, last };\n }, [items]);\n\n const defaultItemIndex = useMemo(() => {\n if (!(\"default\" in config)) return -1;\n return items.findIndex(\n (item) => isSelectable(item) && item.value === config.default,\n );\n }, [config.default, items]);\n\n const [active, setActive] = useState(\n defaultItemIndex === -1 ? bounds.first : defaultItemIndex,\n );\n\n const selectedChoice = items[active] as SelectChoice<unknown>;\n\n useKeypress((key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n setStatus(\"done\");\n done(selectedChoice.value);\n } else if (isUpKey(key)) {\n rl.clearLine(0);\n if (active === bounds.first && loop) {\n setActive(bounds.last);\n } else {\n let newActive = active - 1;\n while (newActive >= bounds.first && !isSelectable(items[newActive]!)) {\n newActive--;\n }\n if (newActive >= bounds.first) setActive(newActive);\n }\n } else if (isDownKey(key)) {\n rl.clearLine(0);\n if (active === bounds.last && loop) {\n setActive(bounds.first);\n } else {\n let newActive = active + 1;\n while (newActive <= bounds.last && !isSelectable(items[newActive]!)) {\n newActive++;\n }\n if (newActive <= bounds.last) setActive(newActive);\n }\n }\n });\n\n const page = usePagination({\n items,\n active,\n renderItem: ({ item, isActive }) => {\n if (Separator.isSeparator(item)) {\n return ` ${item.separator}`;\n }\n const line = item.name;\n if (item.disabled) {\n const disabledLabel =\n typeof item.disabled === \"string\" ? item.disabled : \"(disabled)\";\n return colors.dim(`- ${line} ${disabledLabel}`);\n }\n const cursor = isActive ? figures.pointer : \" \";\n const color = isActive ? colors.cyan : (x: string) => x;\n return color(`${cursor} ${line}`);\n },\n pageSize,\n loop,\n });\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.cyan(selectedChoice?.short ?? selectedChoice?.name ?? \"\")}`;\n }\n\n const helpTip = colors.dim(\"(Use arrow keys, Enter to select, Esc to cancel)\");\n return `${prefix} ${config.message} ${helpTip}\\n${page}`;\n});\n\ninterface InputConfig {\n message: string;\n default?: string;\n transformer?: (value: string, options: { isFinal: boolean }) => string;\n validate?: (value: string) => boolean | string | Promise<boolean | string>;\n}\n\n/**\n * Input prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const inputCancellable = createPrompt<string | null, InputConfig>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const [value, setValue] = useState(config.default ?? \"\");\n const [touched, setTouched] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const theme = makeTheme(inputTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n useKeypress(async (key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n // If user has edited, use their value (even if empty); otherwise use default\n const answer = touched ? value : (config.default ?? \"\");\n if (config.validate) {\n const result = await config.validate(answer);\n if (result !== true) {\n setError(typeof result === \"string\" ? result : \"Invalid input\");\n return;\n }\n }\n setStatus(\"done\");\n done(answer);\n } else if (isBackspaceKey(key)) {\n // Sync with readline's buffer after backspace\n setValue(rl.line);\n setTouched(true);\n setError(null);\n } else if (key.name !== \"tab\" && !key.ctrl && !(key as any).meta) {\n // Sync state with readline's current line buffer\n setValue(rl.line);\n setTouched(true);\n setError(null);\n }\n });\n\n const displayValue = config.transformer\n ? config.transformer(value, { isFinal: status === \"done\" })\n : value;\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.cyan(displayValue)}`;\n }\n\n const helpTip = colors.dim(\"(Esc to cancel)\");\n const errorMsg = error ? colors.red(`\\n> ${error}`) : \"\";\n return `${prefix} ${config.message} ${helpTip} ${displayValue}${errorMsg}`;\n },\n);\n\ninterface PasswordConfig {\n message: string;\n mask?: string;\n validate?: (value: string) => boolean | string | Promise<boolean | string>;\n}\n\n/**\n * Password prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const passwordCancellable = createPrompt<string | null, PasswordConfig>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const [value, setValue] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const theme = makeTheme(inputTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n const mask = config.mask ?? \"*\";\n\n useKeypress(async (key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n if (config.validate) {\n const result = await config.validate(value);\n if (result !== true) {\n setError(typeof result === \"string\" ? result : \"Invalid input\");\n return;\n }\n }\n setStatus(\"done\");\n done(value);\n } else if (isBackspaceKey(key)) {\n setValue(value.slice(0, -1));\n setError(null);\n } else if (key.name !== \"tab\" && !key.ctrl && !(key as any).meta) {\n // Use key.sequence for single character to avoid rl.line buffer issues\n const char = (key as any).sequence ?? \"\";\n if (char) {\n rl.clearLine(0);\n setValue(value + char);\n setError(null);\n }\n }\n });\n\n const masked = mask.repeat(value.length);\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.dim(masked)}`;\n }\n\n const helpTip = colors.dim(\"(Esc to cancel)\");\n const errorMsg = error ? colors.red(`\\n> ${error}`) : \"\";\n return `${prefix} ${config.message} ${helpTip} ${masked}${errorMsg}`;\n },\n);\n\ninterface ConfirmConfig {\n message: string;\n default?: boolean;\n}\n\n/**\n * Confirm prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const confirmCancellable = createPrompt<boolean | null, ConfirmConfig>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n // Track value as undefined when no default, requiring explicit y/n\n const [value, setValue] = useState<boolean | undefined>(config.default);\n const theme = makeTheme(inputTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n useKeypress((key) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n // Only accept Enter if a value has been chosen (explicit or default)\n if (value !== undefined) {\n setStatus(\"done\");\n done(value);\n }\n } else if (key.name === \"y\" || key.name === \"Y\") {\n setValue(true);\n } else if (key.name === \"n\" || key.name === \"N\") {\n setValue(false);\n }\n });\n\n const hint = config.default === true ? \"(Y/n)\" : config.default === false ? \"(y/N)\" : \"(y/n)\";\n const displayValue = value === true ? \"Yes\" : value === false ? \"No\" : \"\";\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.cyan(displayValue)}`;\n }\n\n const helpTip = colors.dim(\"(Esc to cancel)\");\n return `${prefix} ${config.message} ${helpTip} ${hint} ${displayValue}`;\n },\n);\n\n/**\n * Type-safe wrapper for selectCancellable.\n * Returns the selected value with proper typing, or null if cancelled.\n */\nexport async function select<T>(config: SelectConfig<T>): Promise<T | null> {\n return selectCancellable(config as SelectConfig<unknown>) as Promise<T | null>;\n}\n\ninterface SearchConfig<T> {\n message: string;\n source: (\n term: string | undefined,\n ) => Promise<{ name: string; value: T }[]> | { name: string; value: T }[];\n}\n\n/**\n * Search prompt with escape key support.\n * Returns null if user presses Escape.\n *\n * Note: This wraps @inquirer/search which has built-in escape handling,\n * but we provide a consistent API with other cancellable prompts.\n */\nexport const searchCancellable = createPrompt<unknown | null, SearchConfig<unknown>>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [results, setResults] = useState<{ name: string; value: unknown }[]>([]);\n const [active, setActive] = useState(0);\n const [loading, setLoading] = useState(false);\n const theme = makeTheme(selectTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n // Fetch results when search term changes\n useMemo(async () => {\n setLoading(true);\n try {\n const items = await config.source(searchTerm || undefined);\n setResults(items);\n setActive(0);\n } finally {\n setLoading(false);\n }\n }, [searchTerm]);\n\n useKeypress((key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key) && results.length > 0) {\n setStatus(\"done\");\n done(results[active]?.value ?? null);\n } else if (isUpKey(key) && results.length > 0) {\n rl.clearLine(0);\n setActive(active > 0 ? active - 1 : results.length - 1);\n } else if (isDownKey(key) && results.length > 0) {\n rl.clearLine(0);\n setActive(active < results.length - 1 ? active + 1 : 0);\n } else if (isBackspaceKey(key)) {\n setSearchTerm(rl.line);\n } else if (key.name !== \"tab\" && !key.ctrl && !(key as any).meta) {\n setSearchTerm(rl.line);\n }\n });\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n const selected = results[active];\n return `${prefix} ${config.message} ${colors.cyan(selected?.name ?? \"\")}`;\n }\n\n const helpTip = colors.dim(\"(Type to search, Esc to cancel)\");\n const searchLine = `${prefix} ${config.message} ${helpTip} ${searchTerm}`;\n\n if (loading) {\n return `${searchLine}\\n${colors.dim(\" Searching...\")}`;\n }\n\n if (results.length === 0) {\n return `${searchLine}\\n${colors.dim(\" No results\")}`;\n }\n\n const resultLines = results\n .slice(0, 7)\n .map((item, i) => {\n const cursor = i === active ? figures.pointer : \" \";\n const color = i === active ? colors.cyan : (x: string) => x;\n return color(`${cursor} ${item.name}`);\n })\n .join(\"\\n\");\n\n return `${searchLine}\\n${resultLines}`;\n },\n);\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"prompts.js","names":["_core","require","_yoctocolorsCjs","_interopRequireDefault","_figures","e","__esModule","default","isEscapeKey","key","name","selectTheme","icon","cursor","figures","pointer","style","disabled","text","colors","dim","description","cyan","helpTip","helpMode","inputTheme","isSelectable","item","Separator","isSeparator","normalizeChoices","choices","map","choice","value","short","String","selectCancellable","exports","createPrompt","config","done","loop","pageSize","theme","makeTheme","status","setStatus","useState","prefix","usePrefix","items","useMemo","bounds","first","findIndex","last","i","length","ValidationError","defaultItemIndex","active","setActive","selectedChoice","useKeypress","rl","isEnterKey","isUpKey","clearLine","newActive","isDownKey","page","usePagination","renderItem","isActive","separator","line","disabledLabel","color","x","message","clearLines","count","process","stdout","write","repeat","selectWithClear","result","inputWithClear","inputCancellable","passwordWithClear","passwordCancellable","confirmWithClear","confirmCancellable","setValue","touched","setTouched","error","setError","answer","validate","isBackspaceKey","ctrl","meta","displayValue","transformer","isFinal","errorMsg","red","mask","slice","char","sequence","masked","undefined","hint","select","searchCancellable","searchTerm","setSearchTerm","results","setResults","loading","setLoading","source","selected","searchLine","resultLines","join"],"sources":["../../../src/Sprinkle/prompts.ts"],"sourcesContent":["/**\n * Cancellable prompt wrappers with escape key support.\n * Uses @inquirer/core's createPrompt and useKeypress for proper escape handling.\n */\n\nimport {\n createPrompt,\n useState,\n useKeypress,\n usePrefix,\n usePagination,\n useMemo,\n makeTheme,\n isEnterKey,\n isUpKey,\n isDownKey,\n isBackspaceKey,\n Separator,\n ValidationError,\n type Theme,\n} from \"@inquirer/core\";\nimport type { PartialDeep } from \"@inquirer/type\";\nimport colors from \"yoctocolors-cjs\";\nimport figures from \"@inquirer/figures\";\n\n// Check if key is escape\nconst isEscapeKey = (key: { name: string }) => key.name === \"escape\";\n\n// Theme for select prompt\nconst selectTheme = {\n icon: { cursor: figures.pointer },\n style: {\n disabled: (text: string) => colors.dim(`- ${text}`),\n description: (text: string) => colors.cyan(text),\n helpTip: colors.dim(\"(Use arrow keys, Enter to select, Esc to cancel)\"),\n },\n helpMode: \"always\" as const,\n};\n\n// Theme for input prompt\nconst inputTheme = {\n style: {\n helpTip: colors.dim(\"(Esc to cancel)\"),\n },\n};\n\ninterface SelectChoice<T> {\n name?: string;\n value: T;\n description?: string;\n short?: string;\n disabled?: boolean | string;\n}\n\ninterface SelectConfig<T> {\n message: string;\n choices: ReadonlyArray<SelectChoice<T> | Separator | string>;\n default?: T;\n pageSize?: number;\n loop?: boolean;\n theme?: PartialDeep<Theme<typeof selectTheme>>;\n}\n\nfunction isSelectable<T>(item: SelectChoice<T> | Separator): item is SelectChoice<T> {\n return !Separator.isSeparator(item) && !item.disabled;\n}\n\nfunction normalizeChoices<T>(\n choices: ReadonlyArray<SelectChoice<T> | Separator | string>,\n): Array<SelectChoice<T> | Separator> {\n return choices.map((choice) => {\n if (Separator.isSeparator(choice)) return choice;\n if (typeof choice === \"string\") {\n return {\n value: choice as unknown as T,\n name: choice,\n short: choice,\n disabled: false,\n };\n }\n const name = choice.name ?? String(choice.value);\n return {\n value: choice.value,\n name,\n short: choice.short ?? name,\n disabled: choice.disabled ?? false,\n description: choice.description,\n };\n });\n}\n\n/**\n * Select prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const selectCancellable = createPrompt<\n unknown | null,\n SelectConfig<unknown>\n>((config, done) => {\n const { loop = true, pageSize = 15 } = config;\n const theme = makeTheme(selectTheme, config.theme);\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n const items = useMemo(\n () => normalizeChoices(config.choices),\n [config.choices],\n );\n\n const bounds = useMemo(() => {\n const first = items.findIndex(isSelectable);\n // Find last selectable item (compatible with es2022)\n let last = -1;\n for (let i = items.length - 1; i >= 0; i--) {\n if (isSelectable(items[i]!)) {\n last = i;\n break;\n }\n }\n if (first === -1) {\n throw new ValidationError(\n \"[select prompt] No selectable choices. All choices are disabled.\",\n );\n }\n return { first, last };\n }, [items]);\n\n const defaultItemIndex = useMemo(() => {\n if (!(\"default\" in config)) return -1;\n return items.findIndex(\n (item) => isSelectable(item) && item.value === config.default,\n );\n }, [config.default, items]);\n\n const [active, setActive] = useState(\n defaultItemIndex === -1 ? bounds.first : defaultItemIndex,\n );\n\n const selectedChoice = items[active] as SelectChoice<unknown>;\n\n useKeypress((key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n setStatus(\"done\");\n done(selectedChoice.value);\n } else if (isUpKey(key)) {\n rl.clearLine(0);\n if (active === bounds.first && loop) {\n setActive(bounds.last);\n } else {\n let newActive = active - 1;\n while (newActive >= bounds.first && !isSelectable(items[newActive]!)) {\n newActive--;\n }\n if (newActive >= bounds.first) setActive(newActive);\n }\n } else if (isDownKey(key)) {\n rl.clearLine(0);\n if (active === bounds.last && loop) {\n setActive(bounds.first);\n } else {\n let newActive = active + 1;\n while (newActive <= bounds.last && !isSelectable(items[newActive]!)) {\n newActive++;\n }\n if (newActive <= bounds.last) setActive(newActive);\n }\n }\n });\n\n const page = usePagination({\n items,\n active,\n renderItem: ({ item, isActive }) => {\n if (Separator.isSeparator(item)) {\n return ` ${item.separator}`;\n }\n const line = item.name;\n if (item.disabled) {\n const disabledLabel =\n typeof item.disabled === \"string\" ? item.disabled : \"(disabled)\";\n return colors.dim(`- ${line} ${disabledLabel}`);\n }\n const cursor = isActive ? figures.pointer : \" \";\n const color = isActive ? colors.cyan : (x: string) => x;\n return color(`${cursor} ${line}`);\n },\n pageSize,\n loop,\n });\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.cyan(selectedChoice?.short ?? selectedChoice?.name ?? \"\")}`;\n }\n\n const helpTip = colors.dim(\"(Use arrow keys, Enter to select, Esc to cancel)\");\n return `${prefix} ${config.message} ${helpTip}\\n${page}`;\n});\n\n/**\n * Clears N lines above the cursor.\n * Used after prompts to clean up menu output.\n */\nexport function clearLines(count: number): void {\n // Move up and clear each line\n process.stdout.write(\"\\x1b[1A\\x1b[2K\".repeat(count));\n}\n\n/**\n * Select prompt that clears its output after completion.\n * Returns the selected value or null if cancelled.\n */\nexport async function selectWithClear<T>(\n config: SelectConfig<T>,\n): Promise<T | null> {\n const result = await selectCancellable(config as SelectConfig<unknown>);\n\n // Clear the \"done\" line that inquirer left behind\n // Move up one line, clear it, move cursor to start\n process.stdout.write(\"\\x1b[1A\\x1b[2K\\x1b[G\");\n\n return result as T | null;\n}\n\n/**\n * Input prompt that clears its output after completion.\n * Returns the input value or null if cancelled.\n */\nexport async function inputWithClear(\n config: InputConfig,\n): Promise<string | null> {\n const result = await inputCancellable(config);\n\n // Clear the \"done\" line\n process.stdout.write(\"\\x1b[1A\\x1b[2K\\x1b[G\");\n\n return result;\n}\n\n/**\n * Password prompt that clears its output after completion.\n * Returns the password or null if cancelled.\n */\nexport async function passwordWithClear(\n config: PasswordConfig,\n): Promise<string | null> {\n const result = await passwordCancellable(config);\n\n // Clear the \"done\" line\n process.stdout.write(\"\\x1b[1A\\x1b[2K\\x1b[G\");\n\n return result;\n}\n\n/**\n * Confirm prompt that clears its output after completion.\n * Returns true/false or null if cancelled.\n */\nexport async function confirmWithClear(\n config: ConfirmConfig,\n): Promise<boolean | null> {\n const result = await confirmCancellable(config);\n\n // Clear the \"done\" line\n process.stdout.write(\"\\x1b[1A\\x1b[2K\\x1b[G\");\n\n return result;\n}\n\ninterface InputConfig {\n message: string;\n default?: string;\n transformer?: (value: string, options: { isFinal: boolean }) => string;\n validate?: (value: string) => boolean | string | Promise<boolean | string>;\n}\n\n/**\n * Input prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const inputCancellable = createPrompt<string | null, InputConfig>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const [value, setValue] = useState(config.default ?? \"\");\n const [touched, setTouched] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const theme = makeTheme(inputTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n useKeypress(async (key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n // If user has edited, use their value (even if empty); otherwise use default\n const answer = touched ? value : (config.default ?? \"\");\n if (config.validate) {\n const result = await config.validate(answer);\n if (result !== true) {\n setError(typeof result === \"string\" ? result : \"Invalid input\");\n return;\n }\n }\n setStatus(\"done\");\n done(answer);\n } else if (isBackspaceKey(key)) {\n // Sync with readline's buffer after backspace\n setValue(rl.line);\n setTouched(true);\n setError(null);\n } else if (key.name !== \"tab\" && !key.ctrl && !(key as any).meta) {\n // Sync state with readline's current line buffer\n setValue(rl.line);\n setTouched(true);\n setError(null);\n }\n });\n\n const displayValue = config.transformer\n ? config.transformer(value, { isFinal: status === \"done\" })\n : value;\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.cyan(displayValue)}`;\n }\n\n const helpTip = colors.dim(\"(Esc to cancel)\");\n const errorMsg = error ? colors.red(`\\n> ${error}`) : \"\";\n return `${prefix} ${config.message} ${helpTip} ${displayValue}${errorMsg}`;\n },\n);\n\ninterface PasswordConfig {\n message: string;\n mask?: string;\n validate?: (value: string) => boolean | string | Promise<boolean | string>;\n}\n\n/**\n * Password prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const passwordCancellable = createPrompt<string | null, PasswordConfig>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const [value, setValue] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const theme = makeTheme(inputTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n const mask = config.mask ?? \"*\";\n\n useKeypress(async (key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n if (config.validate) {\n const result = await config.validate(value);\n if (result !== true) {\n setError(typeof result === \"string\" ? result : \"Invalid input\");\n return;\n }\n }\n setStatus(\"done\");\n done(value);\n } else if (isBackspaceKey(key)) {\n setValue(value.slice(0, -1));\n setError(null);\n } else if (key.name !== \"tab\" && !key.ctrl && !(key as any).meta) {\n // Use key.sequence for single character to avoid rl.line buffer issues\n const char = (key as any).sequence ?? \"\";\n if (char) {\n rl.clearLine(0);\n setValue(value + char);\n setError(null);\n }\n }\n });\n\n const masked = mask.repeat(value.length);\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.dim(masked)}`;\n }\n\n const helpTip = colors.dim(\"(Esc to cancel)\");\n const errorMsg = error ? colors.red(`\\n> ${error}`) : \"\";\n return `${prefix} ${config.message} ${helpTip} ${masked}${errorMsg}`;\n },\n);\n\ninterface ConfirmConfig {\n message: string;\n default?: boolean;\n}\n\n/**\n * Confirm prompt with escape key support.\n * Returns null if user presses Escape.\n */\nexport const confirmCancellable = createPrompt<boolean | null, ConfirmConfig>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n // Track value as undefined when no default, requiring explicit y/n\n const [value, setValue] = useState<boolean | undefined>(config.default);\n const theme = makeTheme(inputTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n useKeypress((key) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key)) {\n // Only accept Enter if a value has been chosen (explicit or default)\n if (value !== undefined) {\n setStatus(\"done\");\n done(value);\n }\n } else if (key.name === \"y\" || key.name === \"Y\") {\n setValue(true);\n } else if (key.name === \"n\" || key.name === \"N\") {\n setValue(false);\n }\n });\n\n const hint = config.default === true ? \"(Y/n)\" : config.default === false ? \"(y/N)\" : \"(y/n)\";\n const displayValue = value === true ? \"Yes\" : value === false ? \"No\" : \"\";\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n return `${prefix} ${config.message} ${colors.cyan(displayValue)}`;\n }\n\n const helpTip = colors.dim(\"(Esc to cancel)\");\n return `${prefix} ${config.message} ${helpTip} ${hint} ${displayValue}`;\n },\n);\n\n/**\n * Type-safe wrapper for selectCancellable.\n * Returns the selected value with proper typing, or null if cancelled.\n */\nexport async function select<T>(config: SelectConfig<T>): Promise<T | null> {\n return selectCancellable(config as SelectConfig<unknown>) as Promise<T | null>;\n}\n\ninterface SearchConfig<T> {\n message: string;\n source: (\n term: string | undefined,\n ) => Promise<{ name: string; value: T }[]> | { name: string; value: T }[];\n}\n\n/**\n * Search prompt with escape key support.\n * Returns null if user presses Escape.\n *\n * Note: This wraps @inquirer/search which has built-in escape handling,\n * but we provide a consistent API with other cancellable prompts.\n */\nexport const searchCancellable = createPrompt<unknown | null, SearchConfig<unknown>>(\n (config, done) => {\n const [status, setStatus] = useState<\"idle\" | \"done\" | \"cancelled\">(\"idle\");\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [results, setResults] = useState<{ name: string; value: unknown }[]>([]);\n const [active, setActive] = useState(0);\n const [loading, setLoading] = useState(false);\n const theme = makeTheme(selectTheme);\n const prefix = usePrefix({ status: status === \"cancelled\" ? \"done\" : status, theme });\n\n // Fetch results when search term changes\n useMemo(async () => {\n setLoading(true);\n try {\n const items = await config.source(searchTerm || undefined);\n setResults(items);\n setActive(0);\n } finally {\n setLoading(false);\n }\n }, [searchTerm]);\n\n useKeypress((key, rl) => {\n if (isEscapeKey(key)) {\n setStatus(\"cancelled\");\n done(null);\n } else if (isEnterKey(key) && results.length > 0) {\n setStatus(\"done\");\n done(results[active]?.value ?? null);\n } else if (isUpKey(key) && results.length > 0) {\n rl.clearLine(0);\n setActive(active > 0 ? active - 1 : results.length - 1);\n } else if (isDownKey(key) && results.length > 0) {\n rl.clearLine(0);\n setActive(active < results.length - 1 ? active + 1 : 0);\n } else if (isBackspaceKey(key)) {\n setSearchTerm(rl.line);\n } else if (key.name !== \"tab\" && !key.ctrl && !(key as any).meta) {\n setSearchTerm(rl.line);\n }\n });\n\n if (status === \"cancelled\") {\n return `${prefix} ${config.message} ${colors.dim(\"(cancelled)\")}`;\n }\n\n if (status === \"done\") {\n const selected = results[active];\n return `${prefix} ${config.message} ${colors.cyan(selected?.name ?? \"\")}`;\n }\n\n const helpTip = colors.dim(\"(Type to search, Esc to cancel)\");\n const searchLine = `${prefix} ${config.message} ${helpTip} ${searchTerm}`;\n\n if (loading) {\n return `${searchLine}\\n${colors.dim(\" Searching...\")}`;\n }\n\n if (results.length === 0) {\n return `${searchLine}\\n${colors.dim(\" No results\")}`;\n }\n\n const resultLines = results\n .slice(0, 7)\n .map((item, i) => {\n const cursor = i === active ? figures.pointer : \" \";\n const color = i === active ? colors.cyan : (x: string) => x;\n return color(`${cursor} ${item.name}`);\n })\n .join(\"\\n\");\n\n return `${searchLine}\\n${resultLines}`;\n },\n);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.isUnion = exports.isTuple = exports.isThis = exports.isString = exports.isSensitive = exports.isRef = exports.isOptional = exports.isObject = exports.isLiteral = exports.isImport = exports.isBigInt = exports.isArray = void 0;
|
|
6
|
+
exports.unwrapNullable = exports.isUnion = exports.isTuple = exports.isThis = exports.isString = exports.isSensitive = exports.isRef = exports.isOptional = exports.isObject = exports.isNullable = exports.isNull = exports.isLiteral = exports.isImport = exports.isBigInt = exports.isArray = exports.hasDefault = exports.getDefault = void 0;
|
|
7
7
|
var _typebox = require("@sinclair/typebox");
|
|
8
8
|
/**
|
|
9
9
|
* Type guard utilities for TypeBox schema types.
|
|
@@ -38,5 +38,52 @@ const isUnion = t => t[_typebox.Kind] === "Union";
|
|
|
38
38
|
*/
|
|
39
39
|
exports.isUnion = isUnion;
|
|
40
40
|
const isSensitive = t => isString(t) && t.sensitive === true;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if a schema is a Null type.
|
|
44
|
+
*/
|
|
41
45
|
exports.isSensitive = isSensitive;
|
|
46
|
+
const isNull = t => t[_typebox.Kind] === "Null";
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if a schema allows null values.
|
|
50
|
+
* Returns true for TNull or unions containing TNull.
|
|
51
|
+
*/
|
|
52
|
+
exports.isNull = isNull;
|
|
53
|
+
const isNullable = t => {
|
|
54
|
+
if (isNull(t)) return true;
|
|
55
|
+
if (isUnion(t)) return t.anyOf.some(member => isNull(member));
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Unwrap a nullable type to get the non-null inner type.
|
|
61
|
+
* For unions with Null, returns the union without the Null member.
|
|
62
|
+
* For single non-null member unions, returns just that type.
|
|
63
|
+
*/
|
|
64
|
+
exports.isNullable = isNullable;
|
|
65
|
+
const unwrapNullable = t => {
|
|
66
|
+
if (isUnion(t)) {
|
|
67
|
+
const nonNull = t.anyOf.filter(member => !isNull(member));
|
|
68
|
+
if (nonNull.length === 1) return nonNull[0];
|
|
69
|
+
return {
|
|
70
|
+
...t,
|
|
71
|
+
anyOf: nonNull
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return t;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check if a schema has a default value defined.
|
|
79
|
+
*/
|
|
80
|
+
exports.unwrapNullable = unwrapNullable;
|
|
81
|
+
const hasDefault = t => "default" in t;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get the default value from a schema, if defined.
|
|
85
|
+
*/
|
|
86
|
+
exports.hasDefault = hasDefault;
|
|
87
|
+
const getDefault = t => t.default;
|
|
88
|
+
exports.getDefault = getDefault;
|
|
42
89
|
//# sourceMappingURL=type-guards.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-guards.js","names":["_typebox","require","isOptional","t","OptionalKind","exports","isImport","Kind","isArray","isBigInt","isLiteral","isObject","isRef","isString","isThis","isTuple","isUnion","isSensitive","sensitive"],"sources":["../../../src/Sprinkle/type-guards.ts"],"sourcesContent":["/**\n * Type guard utilities for TypeBox schema types.\n * These are internal helpers used by FillInStruct, encryption, and other modules.\n */\n\nimport {\n Kind,\n type TBigInt,\n type TLiteral,\n type TObject,\n type TSchema,\n type TString,\n type TTuple,\n type TUnion,\n type TArray,\n type TThis,\n type TRef,\n type TImport,\n type TOptional,\n OptionalKind,\n} from \"@sinclair/typebox\";\n\nexport const isOptional = <T extends TSchema>(t: T): t is TOptional<T> =>\n t[OptionalKind] === \"Optional\";\n\nexport const isImport = (t: TSchema): t is TImport => t[Kind] === \"Import\";\n\nexport const isArray = (t: TSchema): t is TArray => t[Kind] === \"Array\";\n\nexport const isBigInt = (t: TSchema): t is TBigInt => t[Kind] === \"BigInt\";\n\nexport const isLiteral = (t: TSchema): t is TLiteral => t[Kind] === \"Literal\";\n\nexport const isObject = (t: TSchema): t is TObject => t[Kind] === \"Object\";\n\nexport const isRef = (t: TSchema): t is TRef => t[Kind] === \"Ref\";\n\nexport const isString = (t: TSchema): t is TString => t[Kind] === \"String\";\n\nexport const isThis = (t: TSchema): t is TThis => t[Kind] === \"This\";\n\nexport const isTuple = (t: TSchema): t is TTuple => t[Kind] === \"Tuple\";\n\nexport const isUnion = (t: TSchema): t is TUnion => t[Kind] === \"Union\";\n\n/**\n * Check if a schema field is marked as sensitive.\n * Sensitive fields are encrypted when saved and masked when displayed.\n */\nexport const isSensitive = (t: TSchema): boolean =>\n isString(t) && t.sensitive === true;\n"],"mappings":";;;;;;AAKA,IAAAA,QAAA,GAAAC,OAAA;AALA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"file":"type-guards.js","names":["_typebox","require","isOptional","t","OptionalKind","exports","isImport","Kind","isArray","isBigInt","isLiteral","isObject","isRef","isString","isThis","isTuple","isUnion","isSensitive","sensitive","isNull","isNullable","anyOf","some","member","unwrapNullable","nonNull","filter","length","hasDefault","getDefault","default"],"sources":["../../../src/Sprinkle/type-guards.ts"],"sourcesContent":["/**\n * Type guard utilities for TypeBox schema types.\n * These are internal helpers used by FillInStruct, encryption, and other modules.\n */\n\nimport {\n Kind,\n type TBigInt,\n type TLiteral,\n type TNull,\n type TObject,\n type TSchema,\n type TString,\n type TTuple,\n type TUnion,\n type TArray,\n type TThis,\n type TRef,\n type TImport,\n type TOptional,\n type Static,\n OptionalKind,\n} from \"@sinclair/typebox\";\n\nexport const isOptional = <T extends TSchema>(t: T): t is TOptional<T> =>\n t[OptionalKind] === \"Optional\";\n\nexport const isImport = (t: TSchema): t is TImport => t[Kind] === \"Import\";\n\nexport const isArray = (t: TSchema): t is TArray => t[Kind] === \"Array\";\n\nexport const isBigInt = (t: TSchema): t is TBigInt => t[Kind] === \"BigInt\";\n\nexport const isLiteral = (t: TSchema): t is TLiteral => t[Kind] === \"Literal\";\n\nexport const isObject = (t: TSchema): t is TObject => t[Kind] === \"Object\";\n\nexport const isRef = (t: TSchema): t is TRef => t[Kind] === \"Ref\";\n\nexport const isString = (t: TSchema): t is TString => t[Kind] === \"String\";\n\nexport const isThis = (t: TSchema): t is TThis => t[Kind] === \"This\";\n\nexport const isTuple = (t: TSchema): t is TTuple => t[Kind] === \"Tuple\";\n\nexport const isUnion = (t: TSchema): t is TUnion => t[Kind] === \"Union\";\n\n/**\n * Check if a schema field is marked as sensitive.\n * Sensitive fields are encrypted when saved and masked when displayed.\n */\nexport const isSensitive = (t: TSchema): boolean =>\n isString(t) && t.sensitive === true;\n\n/**\n * Check if a schema is a Null type.\n */\nexport const isNull = (t: TSchema): t is TNull => t[Kind] === \"Null\";\n\n/**\n * Check if a schema allows null values.\n * Returns true for TNull or unions containing TNull.\n */\nexport const isNullable = (t: TSchema): boolean => {\n if (isNull(t)) return true;\n if (isUnion(t)) return t.anyOf.some((member) => isNull(member));\n return false;\n};\n\n/**\n * Unwrap a nullable type to get the non-null inner type.\n * For unions with Null, returns the union without the Null member.\n * For single non-null member unions, returns just that type.\n */\nexport const unwrapNullable = (t: TSchema): TSchema => {\n if (isUnion(t)) {\n const nonNull = t.anyOf.filter((member) => !isNull(member));\n if (nonNull.length === 1) return nonNull[0]!;\n return { ...t, anyOf: nonNull } as TSchema;\n }\n return t;\n};\n\n/**\n * Check if a schema has a default value defined.\n */\nexport const hasDefault = (t: TSchema): boolean => \"default\" in t;\n\n/**\n * Get the default value from a schema, if defined.\n */\nexport const getDefault = <T extends TSchema>(t: T): Static<T> | undefined =>\n t.default as Static<T> | undefined;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -45,5 +45,29 @@ class UserCancelledError extends Error {
|
|
|
45
45
|
this.name = "UserCancelledError";
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
// --- Menu-based FillInStruct types ---
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* State tracking for a single field during menu-based editing.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
// explicitly set to null
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Result of counting required fields in a schema.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Result from field menu interaction.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Result from object menu interaction.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Result from array menu interaction.
|
|
71
|
+
*/
|
|
48
72
|
exports.UserCancelledError = UserCancelledError;
|
|
49
73
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":["UserCancelledError","Error","constructor","message","name","exports"],"sources":["../../../src/Sprinkle/types.ts"],"sourcesContent":["import { Core } from \"@blaze-cardano/sdk\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\n\n/**\n * Utility type to extract the static type from a TypeBox schema.\n */\nexport type TExact<T> = T extends TSchema ? Static<T> : T;\n\n/**\n * Options for encrypting/decrypting sensitive fields in settings.\n */\nexport interface IEncryptionOptions {\n encrypt: (plaintext: string) => string;\n decrypt: (ciphertext: string) => Promise<string>;\n}\n\n/**\n * Options for configuring a Sprinkle instance.\n */\nexport interface ISprinkleOptions {\n encryption?: IEncryptionOptions;\n}\n\n/**\n * Metadata for a profile.\n */\nexport interface IProfileMeta {\n name: string;\n description?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Current profile information including ID.\n */\nexport interface ICurrentProfile extends IProfileMeta {\n id: string;\n}\n\n/**\n * Profile entry as returned by scanProfiles().\n */\nexport interface IProfileEntry {\n id: string;\n meta: IProfileMeta;\n}\n\n/**\n * Result of the TxDialog interaction.\n */\nexport interface TxDialogResult {\n action: \"submitted\" | \"signed\" | \"cancelled\";\n txId?: string; // present only if action === 'submitted'\n tx: Core.Transaction; // the (potentially signed) transaction\n}\n\n/**\n * Options for TxDialog.\n */\nexport interface TxDialogOptions {\n beforeSign?: () => Promise<void>;\n}\n\n/**\n * Error thrown when user cancels a prompt via Escape key.\n */\nexport class UserCancelledError extends Error {\n constructor(message: string = \"User cancelled the operation\") {\n super(message);\n this.name = \"UserCancelledError\";\n }\n}\n"],"mappings":";;;;;;AAGA;AACA;AACA;;AAGA;AACA;AACA;;AAMA;AACA;AACA;;AAKA;AACA;AACA;;AAQA;AACA;AACA;;AAKA;AACA;AACA;;AAMA;AACA;AACA;;AAOA;AACA;AACA;;AAKA;AACA;AACA;AACO,MAAMA,kBAAkB,SAASC,KAAK,CAAC;EAC5CC,WAAWA,CAACC,OAAe,GAAG,8BAA8B,EAAE;IAC5D,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,IAAI,GAAG,oBAAoB;EAClC;AACF;
|
|
1
|
+
{"version":3,"file":"types.js","names":["UserCancelledError","Error","constructor","message","name","exports"],"sources":["../../../src/Sprinkle/types.ts"],"sourcesContent":["import { Core } from \"@blaze-cardano/sdk\";\nimport type { Static, TSchema } from \"@sinclair/typebox\";\n\n/**\n * Utility type to extract the static type from a TypeBox schema.\n */\nexport type TExact<T> = T extends TSchema ? Static<T> : T;\n\n/**\n * Options for encrypting/decrypting sensitive fields in settings.\n */\nexport interface IEncryptionOptions {\n encrypt: (plaintext: string) => string;\n decrypt: (ciphertext: string) => Promise<string>;\n}\n\n/**\n * Options for configuring a Sprinkle instance.\n */\nexport interface ISprinkleOptions {\n encryption?: IEncryptionOptions;\n}\n\n/**\n * Metadata for a profile.\n */\nexport interface IProfileMeta {\n name: string;\n description?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Current profile information including ID.\n */\nexport interface ICurrentProfile extends IProfileMeta {\n id: string;\n}\n\n/**\n * Profile entry as returned by scanProfiles().\n */\nexport interface IProfileEntry {\n id: string;\n meta: IProfileMeta;\n}\n\n/**\n * Result of the TxDialog interaction.\n */\nexport interface TxDialogResult {\n action: \"submitted\" | \"signed\" | \"cancelled\";\n txId?: string; // present only if action === 'submitted'\n tx: Core.Transaction; // the (potentially signed) transaction\n}\n\n/**\n * Options for TxDialog.\n */\nexport interface TxDialogOptions {\n beforeSign?: () => Promise<void>;\n}\n\n/**\n * Error thrown when user cancels a prompt via Escape key.\n */\nexport class UserCancelledError extends Error {\n constructor(message: string = \"User cancelled the operation\") {\n super(message);\n this.name = \"UserCancelledError\";\n }\n}\n\n// --- Menu-based FillInStruct types ---\n\n/**\n * State tracking for a single field during menu-based editing.\n */\nexport type FieldState<T = unknown> =\n | { status: \"unset\" }\n | { status: \"set\"; value: T }\n | { status: \"null\" }; // explicitly set to null\n\n/**\n * Result of counting required fields in a schema.\n */\nexport interface RequiredFieldCount {\n total: number;\n filled: number;\n}\n\n/**\n * Result from field menu interaction.\n */\nexport type FieldMenuResult<T = unknown> =\n | { action: \"edit\" }\n | { action: \"view\" }\n | { action: \"clear\" }\n | { action: \"setNull\" }\n | { action: \"reset\"; defaultValue: T }\n | { action: \"back\" };\n\n/**\n * Result from object menu interaction.\n */\nexport type ObjectMenuResult<T = unknown> =\n | { action: \"submit\"; value: T }\n | { action: \"cancel\" };\n\n/**\n * Result from array menu interaction.\n */\nexport type ArrayMenuResult<T = unknown> =\n | { action: \"done\"; value: T[] }\n | { action: \"back\" };\n"],"mappings":";;;;;;AAGA;AACA;AACA;;AAGA;AACA;AACA;;AAMA;AACA;AACA;;AAKA;AACA;AACA;;AAQA;AACA;AACA;;AAKA;AACA;AACA;;AAMA;AACA;AACA;;AAOA;AACA;AACA;;AAKA;AACA;AACA;AACO,MAAMA,kBAAkB,SAASC,KAAK,CAAC;EAC5CC,WAAWA,CAACC,OAAe,GAAG,8BAA8B,EAAE;IAC5D,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,IAAI,GAAG,oBAAoB;EAClC;AACF;;AAEA;;AAEA;AACA;AACA;;AAIwB;;AAExB;AACA;AACA;;AAMA;AACA;AACA;;AASA;AACA;AACA;;AAKA;AACA;AACA;AAFAC,OAAA,CAAAL,kBAAA,GAAAA,kBAAA","ignoreList":[]}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.allRequiredFieldsFilled = allRequiredFieldsFilled;
|
|
7
|
+
exports.buildFieldLabel = buildFieldLabel;
|
|
8
|
+
exports.countRequiredFields = countRequiredFields;
|
|
9
|
+
exports.getInitialFieldState = getInitialFieldState;
|
|
10
|
+
exports.isFieldRequired = isFieldRequired;
|
|
11
|
+
var _typeGuards = require("../type-guards.js");
|
|
12
|
+
var _formatting = require("./formatting.js");
|
|
13
|
+
/**
|
|
14
|
+
* Field utilities for menu-based struct editing.
|
|
15
|
+
* Provides required field counting and label building.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Count required fields in an object schema and how many are filled.
|
|
20
|
+
*
|
|
21
|
+
* @param type - The object schema
|
|
22
|
+
* @param state - Map of field names to their current state
|
|
23
|
+
* @returns Count of total required fields and how many are filled
|
|
24
|
+
*/
|
|
25
|
+
function countRequiredFields(type, state) {
|
|
26
|
+
const fields = type.properties;
|
|
27
|
+
let total = 0;
|
|
28
|
+
let filled = 0;
|
|
29
|
+
for (const [fieldName, fieldType] of Object.entries(fields)) {
|
|
30
|
+
// Skip optional fields - they're not required
|
|
31
|
+
if ((0, _typeGuards.isOptional)(fieldType)) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Non-nullable fields with defaults don't require user input
|
|
36
|
+
if ((0, _typeGuards.hasDefault)(fieldType) && !(0, _typeGuards.isNullable)(fieldType)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Literal fields auto-fill, so they're not required from the user
|
|
41
|
+
if ((0, _typeGuards.isLiteral)(fieldType)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// This is a required field
|
|
46
|
+
total++;
|
|
47
|
+
|
|
48
|
+
// Check if it's filled
|
|
49
|
+
const fieldState = state.get(fieldName);
|
|
50
|
+
if (fieldState?.status === "set" || fieldState?.status === "null") {
|
|
51
|
+
filled++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
total,
|
|
56
|
+
filled
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Determine if a field is required (must have a value to submit).
|
|
62
|
+
*
|
|
63
|
+
* @param fieldType - The field's schema
|
|
64
|
+
* @returns true if the field is required
|
|
65
|
+
*/
|
|
66
|
+
function isFieldRequired(fieldType) {
|
|
67
|
+
// Optional fields are not required
|
|
68
|
+
if ((0, _typeGuards.isOptional)(fieldType)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Literal fields auto-fill, so they're not required from the user
|
|
73
|
+
if ((0, _typeGuards.isLiteral)(fieldType)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Non-nullable fields with defaults are not required (default will be used)
|
|
78
|
+
if ((0, _typeGuards.hasDefault)(fieldType) && !(0, _typeGuards.isNullable)(fieldType)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Build a display label for a field in the menu.
|
|
86
|
+
*
|
|
87
|
+
* @param fieldName - The field name
|
|
88
|
+
* @param fieldType - The field's schema
|
|
89
|
+
* @param state - The current state of the field
|
|
90
|
+
* @returns Formatted label string
|
|
91
|
+
*/
|
|
92
|
+
function buildFieldLabel(fieldName, fieldType, state) {
|
|
93
|
+
const required = isFieldRequired(fieldType);
|
|
94
|
+
const requiredMarker = required ? " *" : "";
|
|
95
|
+
switch (state.status) {
|
|
96
|
+
case "unset":
|
|
97
|
+
{
|
|
98
|
+
// Check for default value
|
|
99
|
+
if ((0, _typeGuards.hasDefault)(fieldType)) {
|
|
100
|
+
const defaultVal = (0, _typeGuards.getDefault)(fieldType);
|
|
101
|
+
const preview = (0, _formatting.formatValuePreview)(defaultVal, 30);
|
|
102
|
+
return `${fieldName}: [default: ${preview}]${requiredMarker}`;
|
|
103
|
+
}
|
|
104
|
+
return `${fieldName}: [not set]${requiredMarker}`;
|
|
105
|
+
}
|
|
106
|
+
case "null":
|
|
107
|
+
return `${fieldName}: null${requiredMarker}`;
|
|
108
|
+
case "set":
|
|
109
|
+
{
|
|
110
|
+
const preview = (0, _formatting.formatValuePreview)(state.value, 40);
|
|
111
|
+
return `${fieldName}: ${preview}${requiredMarker}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get the initial FieldState for a field based on its type and any existing value.
|
|
118
|
+
*
|
|
119
|
+
* @param _fieldType - The field's schema (reserved for future logic)
|
|
120
|
+
* @param existingValue - Existing value if editing
|
|
121
|
+
* @returns Initial FieldState
|
|
122
|
+
*/
|
|
123
|
+
function getInitialFieldState(_fieldType, existingValue) {
|
|
124
|
+
if (existingValue === undefined) {
|
|
125
|
+
return {
|
|
126
|
+
status: "unset"
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (existingValue === null) {
|
|
130
|
+
return {
|
|
131
|
+
status: "null"
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
status: "set",
|
|
136
|
+
value: existingValue
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Check if all required fields are filled in the state map.
|
|
142
|
+
*
|
|
143
|
+
* @param type - The object schema
|
|
144
|
+
* @param state - Map of field names to their current state
|
|
145
|
+
* @returns true if all required fields have values
|
|
146
|
+
*/
|
|
147
|
+
function allRequiredFieldsFilled(type, state) {
|
|
148
|
+
const {
|
|
149
|
+
total,
|
|
150
|
+
filled
|
|
151
|
+
} = countRequiredFields(type, state);
|
|
152
|
+
return filled >= total;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=field-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-utils.js","names":["_typeGuards","require","_formatting","countRequiredFields","type","state","fields","properties","total","filled","fieldName","fieldType","Object","entries","isOptional","hasDefault","isNullable","isLiteral","fieldState","get","status","isFieldRequired","buildFieldLabel","required","requiredMarker","defaultVal","getDefault","preview","formatValuePreview","value","getInitialFieldState","_fieldType","existingValue","undefined","allRequiredFieldsFilled"],"sources":["../../../../src/Sprinkle/utils/field-utils.ts"],"sourcesContent":["/**\n * Field utilities for menu-based struct editing.\n * Provides required field counting and label building.\n */\n\nimport type { TObject, TSchema } from \"@sinclair/typebox\";\nimport type { FieldState, RequiredFieldCount } from \"../types.js\";\nimport {\n isOptional,\n isNullable,\n hasDefault,\n getDefault,\n isLiteral,\n} from \"../type-guards.js\";\nimport { formatValuePreview } from \"./formatting.js\";\n\n/**\n * Count required fields in an object schema and how many are filled.\n *\n * @param type - The object schema\n * @param state - Map of field names to their current state\n * @returns Count of total required fields and how many are filled\n */\nexport function countRequiredFields(\n type: TObject,\n state: Map<string, FieldState>,\n): RequiredFieldCount {\n const fields = type.properties as Record<string, TSchema>;\n let total = 0;\n let filled = 0;\n\n for (const [fieldName, fieldType] of Object.entries(fields)) {\n // Skip optional fields - they're not required\n if (isOptional(fieldType)) {\n continue;\n }\n\n // Non-nullable fields with defaults don't require user input\n if (hasDefault(fieldType) && !isNullable(fieldType)) {\n continue;\n }\n\n // Literal fields auto-fill, so they're not required from the user\n if (isLiteral(fieldType)) {\n continue;\n }\n\n // This is a required field\n total++;\n\n // Check if it's filled\n const fieldState = state.get(fieldName);\n if (fieldState?.status === \"set\" || fieldState?.status === \"null\") {\n filled++;\n }\n }\n\n return { total, filled };\n}\n\n/**\n * Determine if a field is required (must have a value to submit).\n *\n * @param fieldType - The field's schema\n * @returns true if the field is required\n */\nexport function isFieldRequired(fieldType: TSchema): boolean {\n // Optional fields are not required\n if (isOptional(fieldType)) {\n return false;\n }\n\n // Literal fields auto-fill, so they're not required from the user\n if (isLiteral(fieldType)) {\n return false;\n }\n\n // Non-nullable fields with defaults are not required (default will be used)\n if (hasDefault(fieldType) && !isNullable(fieldType)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Build a display label for a field in the menu.\n *\n * @param fieldName - The field name\n * @param fieldType - The field's schema\n * @param state - The current state of the field\n * @returns Formatted label string\n */\nexport function buildFieldLabel(\n fieldName: string,\n fieldType: TSchema,\n state: FieldState,\n): string {\n const required = isFieldRequired(fieldType);\n const requiredMarker = required ? \" *\" : \"\";\n\n switch (state.status) {\n case \"unset\": {\n // Check for default value\n if (hasDefault(fieldType)) {\n const defaultVal = getDefault(fieldType);\n const preview = formatValuePreview(defaultVal, 30);\n return `${fieldName}: [default: ${preview}]${requiredMarker}`;\n }\n return `${fieldName}: [not set]${requiredMarker}`;\n }\n\n case \"null\":\n return `${fieldName}: null${requiredMarker}`;\n\n case \"set\": {\n const preview = formatValuePreview(state.value, 40);\n return `${fieldName}: ${preview}${requiredMarker}`;\n }\n }\n}\n\n/**\n * Get the initial FieldState for a field based on its type and any existing value.\n *\n * @param _fieldType - The field's schema (reserved for future logic)\n * @param existingValue - Existing value if editing\n * @returns Initial FieldState\n */\nexport function getInitialFieldState<T>(\n _fieldType: TSchema,\n existingValue?: T,\n): FieldState<T> {\n if (existingValue === undefined) {\n return { status: \"unset\" };\n }\n\n if (existingValue === null) {\n return { status: \"null\" };\n }\n\n return { status: \"set\", value: existingValue };\n}\n\n/**\n * Check if all required fields are filled in the state map.\n *\n * @param type - The object schema\n * @param state - Map of field names to their current state\n * @returns true if all required fields have values\n */\nexport function allRequiredFieldsFilled(\n type: TObject,\n state: Map<string, FieldState>,\n): boolean {\n const { total, filled } = countRequiredFields(type, state);\n return filled >= total;\n}\n"],"mappings":"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","ignoreList":[]}
|