diff --git a/.changeset/calm-feet-lead.md b/.changeset/calm-feet-lead.md new file mode 100644 index 00000000..3d312945 --- /dev/null +++ b/.changeset/calm-feet-lead.md @@ -0,0 +1,5 @@ +--- +"@clack/prompts": minor +--- + +Add keyboard instruction footers to `select`, `multiselect`, and `groupMultiselect` in the active state, matching autocomplete. No option — always shown. diff --git a/packages/prompts/src/common.ts b/packages/prompts/src/common.ts index cf348b38..e4a0c379 100644 --- a/packages/prompts/src/common.ts +++ b/packages/prompts/src/common.ts @@ -73,3 +73,12 @@ export interface CommonOptions { signal?: AbortSignal; withGuide?: boolean; } + +export function formatInstructionFooter(instructions: string[], hasGuide: boolean): string[] { + const guidePrefix = hasGuide ? `${styleText('cyan', S_BAR)} ` : ''; + const footerLines = [`${guidePrefix}${instructions.join(' • ')}`]; + if (hasGuide) { + footerLines.push(styleText('cyan', S_BAR_END)); + } + return footerLines; +} diff --git a/packages/prompts/src/group-multi-select.ts b/packages/prompts/src/group-multi-select.ts index 4ddc3d3f..054228f6 100644 --- a/packages/prompts/src/group-multi-select.ts +++ b/packages/prompts/src/group-multi-select.ts @@ -2,6 +2,7 @@ import { styleText } from 'node:util'; import { GroupMultiSelectPrompt, settings, wrapTextWithPrefix } from '@clack/core'; import { type CommonOptions, + formatInstructionFooter, S_BAR, S_BAR_END, S_CHECKBOX_ACTIVE, @@ -10,6 +11,7 @@ import { symbol, } from './common.js'; import { limitOptions } from './limit-options.js'; +import { MULTISELECT_INSTRUCTIONS } from './multi-select.js'; import type { Option } from './select.js'; /** @@ -285,9 +287,10 @@ export const groupMultiselect = (opts: GroupMultiSelectOptions) => } default: { const guidePrefix = hasGuide ? `${styleText('cyan', S_BAR)} ` : ''; - // Calculate rowPadding: title lines + footer lines (S_BAR_END + trailing newline) const titleLineCount = title.split('\n').length; - const footerLineCount = (hasGuide ? 1 : 0) + 1; // guide line + trailing newline + const footerLines = formatInstructionFooter(MULTISELECT_INSTRUCTIONS, hasGuide); + const footerText = footerLines.join('\n'); + const footerLineCount = footerLines.length + 1; const optionsText = limitOptions({ output: opts.output, options: this.options, @@ -297,9 +300,7 @@ export const groupMultiselect = (opts: GroupMultiSelectOptions) => rowPadding: titleLineCount + footerLineCount, style: styleOption, }).join(`\n${guidePrefix}`); - return `${title}${guidePrefix}${optionsText}\n${ - hasGuide ? styleText('cyan', S_BAR_END) : '' - }\n`; + return `${title}${guidePrefix}${optionsText}\n${footerText}\n`; } } }, diff --git a/packages/prompts/src/multi-select.ts b/packages/prompts/src/multi-select.ts index 28b27aab..a04df770 100644 --- a/packages/prompts/src/multi-select.ts +++ b/packages/prompts/src/multi-select.ts @@ -2,6 +2,7 @@ import { styleText } from 'node:util'; import { MultiSelectPrompt, settings, wrapTextWithPrefix } from '@clack/core'; import { type CommonOptions, + formatInstructionFooter, S_BAR, S_BAR_END, S_CHECKBOX_ACTIVE, @@ -13,6 +14,12 @@ import { import { limitOptions } from './limit-options.js'; import type { Option } from './select.js'; +export const MULTISELECT_INSTRUCTIONS = [ + `${styleText('dim', '↑/↓')} to navigate`, + `${styleText('dim', 'Space:')} select`, + `${styleText('dim', 'Enter:')} confirm`, +]; + export interface MultiSelectOptions extends CommonOptions { message: string; options: Option[]; @@ -171,9 +178,10 @@ export const multiselect = (opts: MultiSelectOptions) => { } default: { const prefix = hasGuide ? `${styleText('cyan', S_BAR)} ` : ''; - // Calculate rowPadding: title lines + footer lines (S_BAR_END + trailing newline) const titleLineCount = title.split('\n').length; - const footerLineCount = hasGuide ? 2 : 1; // S_BAR_END + trailing newline + const footerLines = formatInstructionFooter(MULTISELECT_INSTRUCTIONS, hasGuide); + const footerText = footerLines.join('\n'); + const footerLineCount = footerLines.length + 1; return `${title}${prefix}${limitOptions({ output: opts.output, options: this.options, @@ -182,7 +190,7 @@ export const multiselect = (opts: MultiSelectOptions) => { columnPadding: prefix.length, rowPadding: titleLineCount + footerLineCount, style: styleOption, - }).join(`\n${prefix}`)}\n${hasGuide ? styleText('cyan', S_BAR_END) : ''}\n`; + }).join(`\n${prefix}`)}\n${footerText}\n`; } } }, diff --git a/packages/prompts/src/select.ts b/packages/prompts/src/select.ts index a3407cdb..5d012b13 100644 --- a/packages/prompts/src/select.ts +++ b/packages/prompts/src/select.ts @@ -2,8 +2,8 @@ import { styleText } from 'node:util'; import { SelectPrompt, settings, wrapTextWithPrefix } from '@clack/core'; import { type CommonOptions, + formatInstructionFooter, S_BAR, - S_BAR_END, S_RADIO_ACTIVE, S_RADIO_INACTIVE, symbol, @@ -11,6 +11,11 @@ import { } from './common.js'; import { limitOptions } from './limit-options.js'; +export const SELECT_INSTRUCTIONS = [ + `${styleText('dim', '↑/↓')} to navigate`, + `${styleText('dim', 'Enter:')} confirm`, +]; + type Primitive = Readonly; export type Option = Value extends Primitive @@ -145,10 +150,10 @@ export const select = (opts: SelectOptions) => { } default: { const prefix = hasGuide ? `${styleText('cyan', S_BAR)} ` : ''; - const prefixEnd = hasGuide ? styleText('cyan', S_BAR_END) : ''; - // Calculate rowPadding: title lines + footer lines (S_BAR_END + trailing newline) const titleLineCount = title.split('\n').length; - const footerLineCount = hasGuide ? 2 : 1; // S_BAR_END + trailing newline (or just trailing newline) + const footerLines = formatInstructionFooter(SELECT_INSTRUCTIONS, hasGuide); + const footerText = footerLines.join('\n'); + const footerLineCount = footerLines.length + 1; return `${title}${prefix}${limitOptions({ output: opts.output, cursor: this.cursor, @@ -158,7 +163,7 @@ export const select = (opts: SelectOptions) => { rowPadding: titleLineCount + footerLineCount, style: (item, active) => opt(item, item.disabled ? 'disabled' : active ? 'active' : 'inactive'), - }).join(`\n${prefix}`)}\n${prefixEnd}\n`; + }).join(`\n${prefix}`)}\n${footerText}\n`; } } }, diff --git a/packages/prompts/test/__snapshots__/group-multi-select.test.ts.snap b/packages/prompts/test/__snapshots__/group-multi-select.test.ts.snap index d6537c17..2319ef31 100644 --- a/packages/prompts/test/__snapshots__/group-multi-select.test.ts.snap +++ b/packages/prompts/test/__snapshots__/group-multi-select.test.ts.snap @@ -9,6 +9,7 @@ exports[`groupMultiselect (isCI = false) > can be aborted by a signal 1`] = ` │ └ ◻ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", " @@ -25,45 +26,50 @@ exports[`groupMultiselect (isCI = false) > can deselect an option 1`] = ` │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "│ │ ◼ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ │ ◼ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◼ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -82,17 +88,19 @@ exports[`groupMultiselect (isCI = false) > can select a group 1`] = ` │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ │ ◼ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -111,37 +119,41 @@ exports[`groupMultiselect (isCI = false) > can select a group by selecting all m │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "│ │ ◼ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ │ ◼ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -161,36 +173,39 @@ exports[`groupMultiselect (isCI = false) > can select multiple options 1`] = ` │ │ ◻ group1value0 │ │ ◻ group1value1 │ └ ◻ group1value2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ group1value0 │ │ ◻ group1value1 │ └ ◻ group1value2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "│ │ ◼ group1value0 │ │ ◻ group1value1 │ └ ◻ group1value2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value1", - "", - "", + "", + "", "", "", "◇ foo @@ -209,9 +224,10 @@ exports[`groupMultiselect (isCI = false) > can submit empty selection when requi │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -230,14 +246,15 @@ exports[`groupMultiselect (isCI = false) > cursorAt sets initial selection 1`] = │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◼ group1value1", - "", - "", + "", + "", "", "", "◇ foo @@ -255,7 +272,7 @@ exports[`groupMultiselect (isCI = false) > global withGuide: false removes guide ◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -263,7 +280,7 @@ exports[`groupMultiselect (isCI = false) > global withGuide: false removes guide "◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -289,27 +306,30 @@ exports[`groupMultiselect (isCI = false) > groupSpacing > negative spacing is ig │ └ ◻ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ └ ◻ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ └ ◼ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -333,9 +353,10 @@ exports[`groupMultiselect (isCI = false) > groupSpacing > renders spaced groups │ │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -344,9 +365,10 @@ exports[`groupMultiselect (isCI = false) > groupSpacing > renders spaced groups │ │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 @@ -355,9 +377,10 @@ exports[`groupMultiselect (isCI = false) > groupSpacing > renders spaced groups │ │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -376,9 +399,10 @@ exports[`groupMultiselect (isCI = false) > initial values can be set 1`] = ` │ ◻ group1 │ │ ◻ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -400,9 +424,10 @@ exports[`groupMultiselect (isCI = false) > maxItems renders a sliding window 1`] │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -411,9 +436,10 @@ exports[`groupMultiselect (isCI = false) > maxItems renders a sliding window 1`] │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value0 @@ -421,18 +447,20 @@ exports[`groupMultiselect (isCI = false) > maxItems renders a sliding window 1`] │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value1 │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -441,9 +469,10 @@ exports[`groupMultiselect (isCI = false) > maxItems renders a sliding window 1`] │ │ ◻ group1value3 │ │ ◻ group1value4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value2 @@ -451,9 +480,10 @@ exports[`groupMultiselect (isCI = false) > maxItems renders a sliding window 1`] │ │ ◻ group1value4 │ └ ◻ group1value5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value3 @@ -461,14 +491,15 @@ exports[`groupMultiselect (isCI = false) > maxItems renders a sliding window 1`] │ └ ◻ group1value5 │ ◻ group2 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◼ group1value5", - "", - "", + "", + "", "", "", "◇ foo @@ -487,9 +518,10 @@ exports[`groupMultiselect (isCI = false) > renders error when nothing selected 1 │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "▲ foo @@ -506,14 +538,15 @@ exports[`groupMultiselect (isCI = false) > renders error when nothing selected 1 │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -534,9 +567,10 @@ exports[`groupMultiselect (isCI = false) > renders message with options 1`] = ` │ └ ◻ group1value1 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -544,14 +578,15 @@ exports[`groupMultiselect (isCI = false) > renders message with options 1`] = ` │ └ ◻ group1value1 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -570,14 +605,15 @@ exports[`groupMultiselect (isCI = false) > selectableGroups = false > cannot sel │  group1 │  ◻ group1value0 │  ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│  ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -596,26 +632,28 @@ exports[`groupMultiselect (isCI = false) > selectableGroups = false > selecting │  group1 │  ◻ group1value0 │  ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│  ◼ group1value0", - "", - "", + "", + "", "", "", "│  ◼ group1value0 │  ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│  ◼ group1value1", - "", - "", + "", + "", "", "", "◇ foo @@ -637,9 +675,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -648,9 +687,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value0 @@ -658,18 +698,20 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value1 │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -678,9 +720,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group1value3 │ │ ◻ group1value4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value2 @@ -688,9 +731,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group1value4 │ └ ◻ group1value5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value3 @@ -698,9 +742,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ └ ◻ group1value5 │ ◻ group2 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value4 @@ -708,9 +753,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ ◻ group2 │ │ ◻ group2value0 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◻ group1value5 @@ -718,9 +764,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group2value0 │ │ ◻ group2value1 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group2 @@ -728,9 +775,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group2value1 │ │ ◻ group2value2 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value0 @@ -738,9 +786,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group2value2 │ │ ◻ group2value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value1 @@ -748,24 +797,27 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group2value3 │ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value3 │ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -774,9 +826,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -785,14 +838,15 @@ exports[`groupMultiselect (isCI = false) > sliding window loops downwards 1`] = │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -814,9 +868,10 @@ exports[`groupMultiselect (isCI = false) > sliding window loops upwards 1`] = ` │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -825,14 +880,15 @@ exports[`groupMultiselect (isCI = false) > sliding window loops upwards 1`] = ` │ │ ◻ group2value3 │ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◼ group2value5", - "", - "", + "", + "", "", "", "◇ foo @@ -851,22 +907,24 @@ exports[`groupMultiselect (isCI = false) > values can be non-primitive 1`] = ` │ ◻ group1 │ │ ◻ value0 │ └ ◻ value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ value0 │ └ ◻ value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ value0", - "", - "", + "", + "", "", "", "◇ foo @@ -884,7 +942,7 @@ exports[`groupMultiselect (isCI = false) > withGuide: false removes guide 1`] = ◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -892,7 +950,7 @@ exports[`groupMultiselect (isCI = false) > withGuide: false removes guide 1`] = "◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -918,6 +976,7 @@ exports[`groupMultiselect (isCI = true) > can be aborted by a signal 1`] = ` │ └ ◻ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", " @@ -934,45 +993,50 @@ exports[`groupMultiselect (isCI = true) > can deselect an option 1`] = ` │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "│ │ ◼ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ │ ◼ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◼ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -991,17 +1055,19 @@ exports[`groupMultiselect (isCI = true) > can select a group 1`] = ` │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ │ ◼ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1020,37 +1086,41 @@ exports[`groupMultiselect (isCI = true) > can select a group by selecting all me │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "│ │ ◼ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ │ ◼ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1070,36 +1140,39 @@ exports[`groupMultiselect (isCI = true) > can select multiple options 1`] = ` │ │ ◻ group1value0 │ │ ◻ group1value1 │ └ ◻ group1value2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ group1value0 │ │ ◻ group1value1 │ └ ◻ group1value2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "│ │ ◼ group1value0 │ │ ◻ group1value1 │ └ ◻ group1value2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value1", - "", - "", + "", + "", "", "", "◇ foo @@ -1118,9 +1191,10 @@ exports[`groupMultiselect (isCI = true) > can submit empty selection when requir │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1139,14 +1213,15 @@ exports[`groupMultiselect (isCI = true) > cursorAt sets initial selection 1`] = │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◼ group1value1", - "", - "", + "", + "", "", "", "◇ foo @@ -1164,7 +1239,7 @@ exports[`groupMultiselect (isCI = true) > global withGuide: false removes guide ◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -1172,7 +1247,7 @@ exports[`groupMultiselect (isCI = true) > global withGuide: false removes guide "◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -1198,27 +1273,30 @@ exports[`groupMultiselect (isCI = true) > groupSpacing > negative spacing is ign │ └ ◻ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ └ ◻ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 │ └ ◼ group1value0 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1242,9 +1320,10 @@ exports[`groupMultiselect (isCI = true) > groupSpacing > renders spaced groups 1 │ │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -1253,9 +1332,10 @@ exports[`groupMultiselect (isCI = true) > groupSpacing > renders spaced groups 1 │ │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ group1 @@ -1264,9 +1344,10 @@ exports[`groupMultiselect (isCI = true) > groupSpacing > renders spaced groups 1 │ │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1285,9 +1366,10 @@ exports[`groupMultiselect (isCI = true) > initial values can be set 1`] = ` │ ◻ group1 │ │ ◻ group1value0 │ └ ◼ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1309,9 +1391,10 @@ exports[`groupMultiselect (isCI = true) > maxItems renders a sliding window 1`] │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -1320,9 +1403,10 @@ exports[`groupMultiselect (isCI = true) > maxItems renders a sliding window 1`] │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value0 @@ -1330,18 +1414,20 @@ exports[`groupMultiselect (isCI = true) > maxItems renders a sliding window 1`] │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value1 │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -1350,9 +1436,10 @@ exports[`groupMultiselect (isCI = true) > maxItems renders a sliding window 1`] │ │ ◻ group1value3 │ │ ◻ group1value4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value2 @@ -1360,9 +1447,10 @@ exports[`groupMultiselect (isCI = true) > maxItems renders a sliding window 1`] │ │ ◻ group1value4 │ └ ◻ group1value5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value3 @@ -1370,14 +1458,15 @@ exports[`groupMultiselect (isCI = true) > maxItems renders a sliding window 1`] │ └ ◻ group1value5 │ ◻ group2 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◼ group1value5", - "", - "", + "", + "", "", "", "◇ foo @@ -1396,9 +1485,10 @@ exports[`groupMultiselect (isCI = true) > renders error when nothing selected 1` │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "▲ foo @@ -1415,14 +1505,15 @@ exports[`groupMultiselect (isCI = true) > renders error when nothing selected 1` │ ◻ group1 │ │ ◻ group1value0 │ └ ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -1443,9 +1534,10 @@ exports[`groupMultiselect (isCI = true) > renders message with options 1`] = ` │ └ ◻ group1value1 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -1453,14 +1545,15 @@ exports[`groupMultiselect (isCI = true) > renders message with options 1`] = ` │ └ ◻ group1value1 │ ◻ group2 │ └ ◻ group2value0 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -1479,14 +1572,15 @@ exports[`groupMultiselect (isCI = true) > selectableGroups = false > cannot sele │  group1 │  ◻ group1value0 │  ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│  ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -1505,26 +1599,28 @@ exports[`groupMultiselect (isCI = true) > selectableGroups = false > selecting a │  group1 │  ◻ group1value0 │  ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│  ◼ group1value0", - "", - "", + "", + "", "", "", "│  ◼ group1value0 │  ◻ group1value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│  ◼ group1value1", - "", - "", + "", + "", "", "", "◇ foo @@ -1546,9 +1642,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -1557,9 +1654,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value0 @@ -1567,18 +1665,20 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value1 │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -1587,9 +1687,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group1value3 │ │ ◻ group1value4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value2 @@ -1597,9 +1698,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group1value4 │ └ ◻ group1value5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value3 @@ -1607,9 +1709,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ └ ◻ group1value5 │ ◻ group2 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group1value4 @@ -1617,9 +1720,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ group2 │ │ ◻ group2value0 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◻ group1value5 @@ -1627,9 +1731,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group2value0 │ │ ◻ group2value1 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group2 @@ -1637,9 +1742,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group2value1 │ │ ◻ group2value2 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value0 @@ -1647,9 +1753,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group2value2 │ │ ◻ group2value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value1 @@ -1657,24 +1764,27 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group2value3 │ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value3 │ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -1683,9 +1793,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 @@ -1694,14 +1805,15 @@ exports[`groupMultiselect (isCI = true) > sliding window loops downwards 1`] = ` │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ group1value0", - "", - "", + "", + "", "", "", "◇ foo @@ -1723,9 +1835,10 @@ exports[`groupMultiselect (isCI = true) > sliding window loops upwards 1`] = ` │ │ ◻ group1value2 │ │ ◻ group1value3 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -1734,14 +1847,15 @@ exports[`groupMultiselect (isCI = true) > sliding window loops upwards 1`] = ` │ │ ◻ group2value3 │ │ ◻ group2value4 │ └ ◻ group2value5 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ └ ◼ group2value5", - "", - "", + "", + "", "", "", "◇ foo @@ -1760,22 +1874,24 @@ exports[`groupMultiselect (isCI = true) > values can be non-primitive 1`] = ` │ ◻ group1 │ │ ◻ value0 │ └ ◻ value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ group1 │ │ ◻ value0 │ └ ◻ value1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ │ ◼ value0", - "", - "", + "", + "", "", "", "◇ foo @@ -1793,7 +1909,7 @@ exports[`groupMultiselect (isCI = true) > withGuide: false removes guide 1`] = ` ◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -1801,7 +1917,7 @@ exports[`groupMultiselect (isCI = true) > withGuide: false removes guide 1`] = ` "◻ group1 │ ◻ group1value0 └ ◻ group1value1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", diff --git a/packages/prompts/test/__snapshots__/multi-select.test.ts.snap b/packages/prompts/test/__snapshots__/multi-select.test.ts.snap index 38714036..40aeb081 100644 --- a/packages/prompts/test/__snapshots__/multi-select.test.ts.snap +++ b/packages/prompts/test/__snapshots__/multi-select.test.ts.snap @@ -7,6 +7,7 @@ exports[`multiselect (isCI = false) > can be aborted by a signal 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", " @@ -22,9 +23,10 @@ exports[`multiselect (isCI = false) > can cancel 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "■ foo @@ -42,14 +44,15 @@ exports[`multiselect (isCI = false) > can render option hints 1`] = ` ◆ foo │ ◻ opt0 (Hint 0) │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0 (Hint 0)", - "", - "", + "", + "", "", "", "◇ foo @@ -67,14 +70,15 @@ exports[`multiselect (isCI = false) > can set cursorAt to preselect an option 1` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "◇ foo @@ -92,14 +96,15 @@ exports[`multiselect (isCI = false) > can set custom labels 1`] = ` ◆ foo │ ◻ Option 0 │ ◻ Option 1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ Option 0", - "", - "", + "", + "", "", "", "◇ foo @@ -117,9 +122,10 @@ exports[`multiselect (isCI = false) > can set initial values 1`] = ` ◆ foo │ ◻ opt0 │ ◼ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -137,9 +143,10 @@ exports[`multiselect (isCI = false) > can submit without selection when required ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -156,7 +163,7 @@ exports[`multiselect (isCI = false) > global withGuide: false removes guide 1`] "◆ foo ◻ opt0 ◻ opt1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -173,7 +180,7 @@ exports[`multiselect (isCI = false) > global withGuide: false removes guide 1`] ] `; -exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` +exports[`multiselect (isCI = false) > maxItems accounts for instruction footer 1`] = ` [ "", "│ @@ -184,9 +191,10 @@ exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt0 @@ -195,9 +203,10 @@ exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt1 @@ -205,18 +214,20 @@ exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt2 │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -225,9 +236,10 @@ exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` │ ◻ opt4 │ ◻ opt5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt3 @@ -235,9 +247,10 @@ exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` │ ◻ opt5 │ ◻ opt6 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt4 @@ -245,14 +258,112 @@ exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` │ ◻ opt6 │ ◻ opt7 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt6", + "", + "", + "", + "", + "◇ foo +│ opt6", + " +", + "", +] +`; + +exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` +[ + "", + "│ +◆ foo +│ ◻ opt0 +│ ◻ opt1 +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt0 +│ ◻ opt1 +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt1 +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", "", - "", + "", + "│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ... +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ◻ opt5 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt3 +│ ◻ opt4 +│ ◻ opt5 +│ ◻ opt6 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt4 +│ ◻ opt5 +│ ◻ opt6 +│ ◻ opt7 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◼ opt6", + "", + "", "", "", "◇ foo @@ -271,14 +382,15 @@ exports[`multiselect (isCI = false) > renders disabled options 1`] = ` │ ◻ opt0 │ ◻ opt1 │ ◻ opt2 (Hint 2) +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "◇ foo @@ -289,6 +401,24 @@ exports[`multiselect (isCI = false) > renders disabled options 1`] = ` ] `; +exports[`multiselect (isCI = false) > renders instructions without guide 1`] = ` +[ + "", + "◆ foo +◻ opt0 +◻ opt1 +↑/↓ to navigate • Space: select • Enter: confirm +", + "", + "", + "◇ foo +none", + " +", + "", +] +`; + exports[`multiselect (isCI = false) > renders message 1`] = ` [ "", @@ -296,14 +426,15 @@ exports[`multiselect (isCI = false) > renders message 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "◇ foo @@ -322,27 +453,29 @@ exports[`multiselect (isCI = false) > renders multiple cancelled values 1`] = ` │ ◻ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "│ ◼ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "■ foo @@ -362,34 +495,37 @@ exports[`multiselect (isCI = false) > renders multiple selected options 1`] = ` │ ◻ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "│ ◼ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "│ ◼ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -407,9 +543,10 @@ exports[`multiselect (isCI = false) > renders validation errors 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "▲ foo @@ -424,9 +561,10 @@ exports[`multiselect (isCI = false) > renders validation errors 1`] = ` "◆ foo │ ◼ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -445,24 +583,27 @@ exports[`multiselect (isCI = false) > shows hints for all selected options 1`] = │ ◼ opt0 (Hint 0) │ ◼ opt1 (Hint 1) │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0 (Hint 0) │ ◼ opt1 (Hint 1) │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1 (Hint 1) │ ◻ opt2 (Hint 2) +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -484,9 +625,10 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt0 @@ -495,9 +637,10 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt1 @@ -505,18 +648,20 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt2 │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -525,9 +670,10 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt4 │ ◻ opt5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt3 @@ -535,9 +681,10 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt5 │ ◻ opt6 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt4 @@ -545,9 +692,10 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt6 │ ◻ opt7 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt5 @@ -555,9 +703,10 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt7 │ ◻ opt8 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt6 @@ -565,9 +714,10 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt8 │ ◻ opt9 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt7 @@ -575,24 +725,27 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt9 │ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt9 │ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt0 @@ -601,14 +754,15 @@ exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "◇ foo @@ -630,9 +784,10 @@ exports[`multiselect (isCI = false) > sliding window loops upwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -641,14 +796,15 @@ exports[`multiselect (isCI = false) > sliding window loops upwards 1`] = ` │ ◻ opt9 │ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt11", - "", - "", + "", + "", "", "", "◇ foo @@ -665,7 +821,7 @@ exports[`multiselect (isCI = false) > withGuide: false removes guide 1`] = ` "◆ foo ◻ opt0 ◻ opt1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -695,14 +851,15 @@ exports[`multiselect (isCI = false) > wraps cancelled state with long options 1` │ 1 Option 1 Option 1 Option  │ 1 Option 1 Option 1 Option  │ 1 Option 1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ Option 0 Option 0 Option ", - "", - "", + "", + "", "", "", "■ foo @@ -726,14 +883,15 @@ exports[`multiselect (isCI = false) > wraps long messages 1`] = ` │ foo foo foo foo foo foo foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "◇ foo foo foo foo foo foo foo @@ -759,14 +917,15 @@ exports[`multiselect (isCI = false) > wraps success state with long options 1`] │ 1 Option 1 Option 1 Option  │ 1 Option 1 Option 1 Option  │ 1 Option 1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ Option 0 Option 0 Option ", - "", - "", + "", + "", "", "", "◇ foo @@ -787,6 +946,7 @@ exports[`multiselect (isCI = true) > can be aborted by a signal 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", " @@ -802,9 +962,10 @@ exports[`multiselect (isCI = true) > can cancel 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "■ foo @@ -822,14 +983,15 @@ exports[`multiselect (isCI = true) > can render option hints 1`] = ` ◆ foo │ ◻ opt0 (Hint 0) │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0 (Hint 0)", - "", - "", + "", + "", "", "", "◇ foo @@ -847,14 +1009,15 @@ exports[`multiselect (isCI = true) > can set cursorAt to preselect an option 1`] ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "◇ foo @@ -872,14 +1035,15 @@ exports[`multiselect (isCI = true) > can set custom labels 1`] = ` ◆ foo │ ◻ Option 0 │ ◻ Option 1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ Option 0", - "", - "", + "", + "", "", "", "◇ foo @@ -897,9 +1061,10 @@ exports[`multiselect (isCI = true) > can set initial values 1`] = ` ◆ foo │ ◻ opt0 │ ◼ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -917,9 +1082,10 @@ exports[`multiselect (isCI = true) > can submit without selection when required ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -936,7 +1102,7 @@ exports[`multiselect (isCI = true) > global withGuide: false removes guide 1`] = "◆ foo ◻ opt0 ◻ opt1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -953,7 +1119,7 @@ exports[`multiselect (isCI = true) > global withGuide: false removes guide 1`] = ] `; -exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` +exports[`multiselect (isCI = true) > maxItems accounts for instruction footer 1`] = ` [ "", "│ @@ -964,9 +1130,10 @@ exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt0 @@ -975,9 +1142,10 @@ exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt1 @@ -985,18 +1153,20 @@ exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt2 │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -1005,9 +1175,10 @@ exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` │ ◻ opt4 │ ◻ opt5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt3 @@ -1015,9 +1186,10 @@ exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` │ ◻ opt5 │ ◻ opt6 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt4 @@ -1025,14 +1197,112 @@ exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` │ ◻ opt6 │ ◻ opt7 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt6", + "", + "", + "", + "", + "◇ foo +│ opt6", + " +", + "", +] +`; + +exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` +[ + "", + "│ +◆ foo +│ ◻ opt0 +│ ◻ opt1 +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt0 +│ ◻ opt1 +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt1 +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", "", - "", + "", + "│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ... +│ ◻ opt2 +│ ◻ opt3 +│ ◻ opt4 +│ ◻ opt5 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt3 +│ ◻ opt4 +│ ◻ opt5 +│ ◻ opt6 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◻ opt4 +│ ◻ opt5 +│ ◻ opt6 +│ ◻ opt7 +│ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm +└ +", + "", + "", + "", + "│ ◼ opt6", + "", + "", "", "", "◇ foo @@ -1051,14 +1321,15 @@ exports[`multiselect (isCI = true) > renders disabled options 1`] = ` │ ◻ opt0 │ ◻ opt1 │ ◻ opt2 (Hint 2) +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "◇ foo @@ -1069,6 +1340,24 @@ exports[`multiselect (isCI = true) > renders disabled options 1`] = ` ] `; +exports[`multiselect (isCI = true) > renders instructions without guide 1`] = ` +[ + "", + "◆ foo +◻ opt0 +◻ opt1 +↑/↓ to navigate • Space: select • Enter: confirm +", + "", + "", + "◇ foo +none", + " +", + "", +] +`; + exports[`multiselect (isCI = true) > renders message 1`] = ` [ "", @@ -1076,14 +1365,15 @@ exports[`multiselect (isCI = true) > renders message 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "◇ foo @@ -1102,27 +1392,29 @@ exports[`multiselect (isCI = true) > renders multiple cancelled values 1`] = ` │ ◻ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "│ ◼ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "■ foo @@ -1142,34 +1434,37 @@ exports[`multiselect (isCI = true) > renders multiple selected options 1`] = ` │ ◻ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "│ ◼ opt0 │ ◻ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1", - "", - "", + "", + "", "", "", "│ ◼ opt1 │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1187,9 +1482,10 @@ exports[`multiselect (isCI = true) > renders validation errors 1`] = ` ◆ foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "▲ foo @@ -1204,9 +1500,10 @@ exports[`multiselect (isCI = true) > renders validation errors 1`] = ` "◆ foo │ ◼ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1225,24 +1522,27 @@ exports[`multiselect (isCI = true) > shows hints for all selected options 1`] = │ ◼ opt0 (Hint 0) │ ◼ opt1 (Hint 1) │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0 (Hint 0) │ ◼ opt1 (Hint 1) │ ◻ opt2 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt1 (Hint 1) │ ◻ opt2 (Hint 2) +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -1264,9 +1564,10 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt0 @@ -1275,9 +1576,10 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt1 @@ -1285,18 +1587,20 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt2 │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -1305,9 +1609,10 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt4 │ ◻ opt5 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt3 @@ -1315,9 +1620,10 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt5 │ ◻ opt6 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt4 @@ -1325,9 +1631,10 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt6 │ ◻ opt7 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt5 @@ -1335,9 +1642,10 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt7 │ ◻ opt8 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt6 @@ -1345,9 +1653,10 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt8 │ ◻ opt9 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt7 @@ -1355,24 +1664,27 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt9 │ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt9 │ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◻ opt0 @@ -1381,14 +1693,15 @@ exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "◇ foo @@ -1410,9 +1723,10 @@ exports[`multiselect (isCI = true) > sliding window loops upwards 1`] = ` │ ◻ opt3 │ ◻ opt4 │ ... +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ... @@ -1421,14 +1735,15 @@ exports[`multiselect (isCI = true) > sliding window loops upwards 1`] = ` │ ◻ opt9 │ ◻ opt10 │ ◻ opt11 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt11", - "", - "", + "", + "", "", "", "◇ foo @@ -1445,7 +1760,7 @@ exports[`multiselect (isCI = true) > withGuide: false removes guide 1`] = ` "◆ foo ◻ opt0 ◻ opt1 - +↑/↓ to navigate • Space: select • Enter: confirm ", "", "", @@ -1475,14 +1790,15 @@ exports[`multiselect (isCI = true) > wraps cancelled state with long options 1`] │ 1 Option 1 Option 1 Option  │ 1 Option 1 Option 1 Option  │ 1 Option 1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ Option 0 Option 0 Option ", - "", - "", + "", + "", "", "", "■ foo @@ -1506,14 +1822,15 @@ exports[`multiselect (isCI = true) > wraps long messages 1`] = ` │ foo foo foo foo foo foo foo │ ◻ opt0 │ ◻ opt1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ opt0", - "", - "", + "", + "", "", "", "◇ foo foo foo foo foo foo foo @@ -1539,14 +1856,15 @@ exports[`multiselect (isCI = true) > wraps success state with long options 1`] = │ 1 Option 1 Option 1 Option  │ 1 Option 1 Option 1 Option  │ 1 Option 1 +│ ↑/↓ to navigate • Space: select • Enter: confirm └ ", - "", + "", "", "", "│ ◼ Option 0 Option 0 Option ", - "", - "", + "", + "", "", "", "◇ foo diff --git a/packages/prompts/test/__snapshots__/select.test.ts.snap b/packages/prompts/test/__snapshots__/select.test.ts.snap index b213bff7..4bc53b46 100644 --- a/packages/prompts/test/__snapshots__/select.test.ts.snap +++ b/packages/prompts/test/__snapshots__/select.test.ts.snap @@ -7,6 +7,7 @@ exports[`select (isCI = false) > can be aborted by a signal 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", " @@ -22,9 +23,10 @@ exports[`select (isCI = false) > can cancel 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "■ foo @@ -46,8 +48,8 @@ exports[`select (isCI = false) > correctly limits options when message wraps to │ multiple lines │ ● Option 0 │ ○ Option 1 -│ ○ Option 2 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -55,35 +57,29 @@ exports[`select (isCI = false) > correctly limits options when message wraps to "", "│ ○ Option 0 │ ● Option 1 -│ ○ Option 2 -│ ... -└ -", - "", - "", - "", - "│ ○ Option 1 -│ ● Option 2 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", "", "", "│ ... -│ ● Option 3 -│ ○ Option 4 +│ ● Option 2 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", "", - "", - "│ ● Option 4 -│ ○ Option 5 -│ ... -└ -", + "", + "│ ● Option 3", + "", + "", + "", + "", + "│ ● Option 4", + "", "", "", "", @@ -108,8 +104,8 @@ exports[`select (isCI = false) > correctly limits options with explicit multilin │ ● Option 0 │ ○ Option 1 │ ○ Option 2 -│ ○ Option 3 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -118,8 +114,8 @@ exports[`select (isCI = false) > correctly limits options with explicit multilin "│ ○ Option 0 │ ● Option 1 │ ○ Option 2 -│ ○ Option 3 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -127,18 +123,18 @@ exports[`select (isCI = false) > correctly limits options with explicit multilin "", "│ ○ Option 1 │ ● Option 2 -│ ○ Option 3 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", "", "", "│ ... -│ ○ Option 2 │ ● Option 3 │ ○ Option 4 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -161,16 +157,18 @@ exports[`select (isCI = false) > down arrow selects next option 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ○ opt0 │ ● opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -187,7 +185,7 @@ exports[`select (isCI = false) > global withGuide: false removes guide 1`] = ` "◆ foo ● opt0 ○ opt1 - +↑/↓ to navigate • Enter: confirm ", "", "", @@ -213,16 +211,17 @@ exports[`select (isCI = false) > handles mixed size re-renders 1`] = ` │ Long Option │ Long Option │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "│ ◆ Whatever │ ... -│ ○ Option 1 │ ○ Option 2 │ ● Option 3 +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -236,6 +235,98 @@ exports[`select (isCI = false) > handles mixed size re-renders 1`] = ` ] `; +exports[`select (isCI = false) > maxItems accounts for instruction footer 1`] = ` +[ + "", + "│ +◆ foo +│ ● opt0 +│ ○ opt1 +│ ○ opt2 +│ ○ opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt0 +│ ● opt1 +│ ○ opt2 +│ ○ opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt1 +│ ● opt2 +│ ○ opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt2 +│ ● opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ... +│ ○ opt2 +│ ○ opt3 +│ ● opt4 +│ ○ opt5 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt3 +│ ○ opt4 +│ ● opt5 +│ ○ opt6 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt4 +│ ○ opt5 +│ ● opt6 +│ ○ opt7 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "◇ foo +│ opt6", + " +", + "", +] +`; + exports[`select (isCI = false) > renders disabled options 1`] = ` [ "", @@ -244,9 +335,10 @@ exports[`select (isCI = false) > renders disabled options 1`] = ` │ ○ Option 0 │ ● Option 1 │ ○ Option 2 (Hint 2) +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -257,6 +349,24 @@ exports[`select (isCI = false) > renders disabled options 1`] = ` ] `; +exports[`select (isCI = false) > renders instructions without guide 1`] = ` +[ + "", + "◆ foo +● opt0 +○ opt1 +↑/↓ to navigate • Enter: confirm +", + "", + "", + "◇ foo +opt0", + " +", + "", +] +`; + exports[`select (isCI = false) > renders multi-line option labels 1`] = ` [ "", @@ -265,17 +375,19 @@ exports[`select (isCI = false) > renders multi-line option labels 1`] = ` │ ● Option 0 │ with multiple lines │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ○ Option 0 │ with multiple lines │ ● Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -293,9 +405,10 @@ exports[`select (isCI = false) > renders option hints 1`] = ` ◆ foo │ ● opt0 (Hint 0) │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -313,9 +426,10 @@ exports[`select (isCI = false) > renders option labels 1`] = ` ◆ foo │ ● Option 0 │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -333,9 +447,10 @@ exports[`select (isCI = false) > renders options and message 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -353,23 +468,26 @@ exports[`select (isCI = false) > up arrow selects previous option 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ○ opt0 │ ● opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -386,7 +504,7 @@ exports[`select (isCI = false) > withGuide: false removes guide 1`] = ` "◆ foo ● opt0 ○ opt1 - +↑/↓ to navigate • Enter: confirm ", "", "", @@ -409,9 +527,10 @@ exports[`select (isCI = false) > wraps long cancelled message 1`] = ` │ foo foo foo foo foo foo foo │ foo foo foo foo │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "■ foo @@ -436,9 +555,10 @@ exports[`select (isCI = false) > wraps long messages 1`] = ` │ foo foo foo foo foo foo foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo foo foo foo foo foo foo @@ -462,9 +582,10 @@ exports[`select (isCI = false) > wraps long results 1`] = ` │ foo foo foo foo foo foo foo │ foo foo foo foo │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -486,6 +607,7 @@ exports[`select (isCI = true) > can be aborted by a signal 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", " @@ -501,9 +623,10 @@ exports[`select (isCI = true) > can cancel 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "■ foo @@ -525,8 +648,8 @@ exports[`select (isCI = true) > correctly limits options when message wraps to m │ multiple lines │ ● Option 0 │ ○ Option 1 -│ ○ Option 2 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -534,35 +657,29 @@ exports[`select (isCI = true) > correctly limits options when message wraps to m "", "│ ○ Option 0 │ ● Option 1 -│ ○ Option 2 -│ ... -└ -", - "", - "", - "", - "│ ○ Option 1 -│ ● Option 2 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", "", "", "│ ... -│ ● Option 3 -│ ○ Option 4 +│ ● Option 2 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", "", - "", - "│ ● Option 4 -│ ○ Option 5 -│ ... -└ -", + "", + "│ ● Option 3", + "", + "", + "", + "", + "│ ● Option 4", + "", "", "", "", @@ -587,8 +704,8 @@ exports[`select (isCI = true) > correctly limits options with explicit multiline │ ● Option 0 │ ○ Option 1 │ ○ Option 2 -│ ○ Option 3 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -597,8 +714,8 @@ exports[`select (isCI = true) > correctly limits options with explicit multiline "│ ○ Option 0 │ ● Option 1 │ ○ Option 2 -│ ○ Option 3 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -606,18 +723,18 @@ exports[`select (isCI = true) > correctly limits options with explicit multiline "", "│ ○ Option 1 │ ● Option 2 -│ ○ Option 3 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", "", "", "│ ... -│ ○ Option 2 │ ● Option 3 │ ○ Option 4 │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -640,16 +757,18 @@ exports[`select (isCI = true) > down arrow selects next option 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ○ opt0 │ ● opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -666,7 +785,7 @@ exports[`select (isCI = true) > global withGuide: false removes guide 1`] = ` "◆ foo ● opt0 ○ opt1 - +↑/↓ to navigate • Enter: confirm ", "", "", @@ -692,16 +811,17 @@ exports[`select (isCI = true) > handles mixed size re-renders 1`] = ` │ Long Option │ Long Option │ ... +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "│ ◆ Whatever │ ... -│ ○ Option 1 │ ○ Option 2 │ ● Option 3 +│ ↑/↓ to navigate • Enter: confirm └ ", "", @@ -715,6 +835,98 @@ exports[`select (isCI = true) > handles mixed size re-renders 1`] = ` ] `; +exports[`select (isCI = true) > maxItems accounts for instruction footer 1`] = ` +[ + "", + "│ +◆ foo +│ ● opt0 +│ ○ opt1 +│ ○ opt2 +│ ○ opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt0 +│ ● opt1 +│ ○ opt2 +│ ○ opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt1 +│ ● opt2 +│ ○ opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt2 +│ ● opt3 +│ ○ opt4 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ... +│ ○ opt2 +│ ○ opt3 +│ ● opt4 +│ ○ opt5 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt3 +│ ○ opt4 +│ ● opt5 +│ ○ opt6 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "│ ○ opt4 +│ ○ opt5 +│ ● opt6 +│ ○ opt7 +│ ... +│ ↑/↓ to navigate • Enter: confirm +└ +", + "", + "", + "", + "◇ foo +│ opt6", + " +", + "", +] +`; + exports[`select (isCI = true) > renders disabled options 1`] = ` [ "", @@ -723,9 +935,10 @@ exports[`select (isCI = true) > renders disabled options 1`] = ` │ ○ Option 0 │ ● Option 1 │ ○ Option 2 (Hint 2) +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -736,6 +949,24 @@ exports[`select (isCI = true) > renders disabled options 1`] = ` ] `; +exports[`select (isCI = true) > renders instructions without guide 1`] = ` +[ + "", + "◆ foo +● opt0 +○ opt1 +↑/↓ to navigate • Enter: confirm +", + "", + "", + "◇ foo +opt0", + " +", + "", +] +`; + exports[`select (isCI = true) > renders multi-line option labels 1`] = ` [ "", @@ -744,17 +975,19 @@ exports[`select (isCI = true) > renders multi-line option labels 1`] = ` │ ● Option 0 │ with multiple lines │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ○ Option 0 │ with multiple lines │ ● Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -772,9 +1005,10 @@ exports[`select (isCI = true) > renders option hints 1`] = ` ◆ foo │ ● opt0 (Hint 0) │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -792,9 +1026,10 @@ exports[`select (isCI = true) > renders option labels 1`] = ` ◆ foo │ ● Option 0 │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -812,9 +1047,10 @@ exports[`select (isCI = true) > renders options and message 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -832,23 +1068,26 @@ exports[`select (isCI = true) > up arrow selects previous option 1`] = ` ◆ foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ○ opt0 │ ● opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "│ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo @@ -865,7 +1104,7 @@ exports[`select (isCI = true) > withGuide: false removes guide 1`] = ` "◆ foo ● opt0 ○ opt1 - +↑/↓ to navigate • Enter: confirm ", "", "", @@ -888,9 +1127,10 @@ exports[`select (isCI = true) > wraps long cancelled message 1`] = ` │ foo foo foo foo foo foo foo │ foo foo foo foo │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "■ foo @@ -915,9 +1155,10 @@ exports[`select (isCI = true) > wraps long messages 1`] = ` │ foo foo foo foo foo foo foo │ ● opt0 │ ○ opt1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo foo foo foo foo foo foo @@ -941,9 +1182,10 @@ exports[`select (isCI = true) > wraps long results 1`] = ` │ foo foo foo foo foo foo foo │ foo foo foo foo │ ○ Option 1 +│ ↑/↓ to navigate • Enter: confirm └ ", - "", + "", "", "", "◇ foo diff --git a/packages/prompts/test/multi-select.test.ts b/packages/prompts/test/multi-select.test.ts index 3f79555b..4f05598c 100644 --- a/packages/prompts/test/multi-select.test.ts +++ b/packages/prompts/test/multi-select.test.ts @@ -437,4 +437,43 @@ describe.each(['true', 'false'])('multiselect (isCI = %s)', (isCI) => { expect(value).toEqual(['opt0']); expect(output.buffer).toMatchSnapshot(); }); + + test('renders instructions without guide', async () => { + const result = prompts.multiselect({ + message: 'foo', + options: [{ value: 'opt0' }, { value: 'opt1' }], + required: false, + withGuide: false, + input, + output, + }); + + input.emit('keypress', '', { name: 'return' }); + + await result; + expect(output.buffer).toMatchSnapshot(); + }); + + test('maxItems accounts for instruction footer', async () => { + const result = prompts.multiselect({ + message: 'foo', + options: [...Array(12).keys()].map((k) => ({ + value: `opt${k}`, + })), + maxItems: 6, + input, + output, + }); + + for (let i = 0; i < 6; i++) { + input.emit('keypress', '', { name: 'down' }); + } + input.emit('keypress', '', { name: 'space' }); + input.emit('keypress', '', { name: 'return' }); + + const value = await result; + + expect(value).toEqual(['opt6']); + expect(output.buffer).toMatchSnapshot(); + }); }); diff --git a/packages/prompts/test/select.test.ts b/packages/prompts/test/select.test.ts index 447a0e1b..f0c92ce9 100644 --- a/packages/prompts/test/select.test.ts +++ b/packages/prompts/test/select.test.ts @@ -340,6 +340,43 @@ describe.each(['true', 'false'])('select (isCI = %s)', (isCI) => { expect(output.buffer).toMatchSnapshot(); }); + test('renders instructions without guide', async () => { + const result = prompts.select({ + message: 'foo', + options: [{ value: 'opt0' }, { value: 'opt1' }], + withGuide: false, + input, + output, + }); + + input.emit('keypress', '', { name: 'return' }); + + await result; + expect(output.buffer).toMatchSnapshot(); + }); + + test('maxItems accounts for instruction footer', async () => { + const result = prompts.select({ + message: 'foo', + options: [...Array(12).keys()].map((k) => ({ + value: `opt${k}`, + })), + maxItems: 6, + input, + output, + }); + + for (let i = 0; i < 6; i++) { + input.emit('keypress', '', { name: 'down' }); + } + input.emit('keypress', '', { name: 'return' }); + + const value = await result; + + expect(value).toEqual('opt6'); + expect(output.buffer).toMatchSnapshot(); + }); + test('correctly limits options with explicit multiline message', async () => { output.rows = 12;