diff --git a/.changeset/modern-dots-make.md b/.changeset/modern-dots-make.md new file mode 100644 index 00000000..8e22853a --- /dev/null +++ b/.changeset/modern-dots-make.md @@ -0,0 +1,5 @@ +--- +"@clack/prompts": patch +--- + +Add `withGuide` support to selectKey prompt diff --git a/packages/prompts/src/select-key.ts b/packages/prompts/src/select-key.ts index 832c44d0..8fb9712f 100644 --- a/packages/prompts/src/select-key.ts +++ b/packages/prompts/src/select-key.ts @@ -1,4 +1,4 @@ -import { SelectKeyPrompt, wrapTextWithPrefix } from '@clack/core'; +import { SelectKeyPrompt, settings, wrapTextWithPrefix } from '@clack/core'; import color from 'picocolors'; import { type CommonOptions, S_BAR, S_BAR_END, symbol } from './common.js'; import type { Option } from './select.js'; @@ -40,11 +40,12 @@ export const selectKey = (opts: SelectKeyOptions) = initialValue: opts.initialValue, caseSensitive: opts.caseSensitive, render() { - const title = `${color.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; + const hasGuide = (opts.withGuide ?? settings.withGuide) !== false; + const title = `${hasGuide ? `${color.gray(S_BAR)}\n` : ''}${symbol(this.state)} ${opts.message}\n`; switch (this.state) { case 'submit': { - const submitPrefix = `${color.gray(S_BAR)} `; + const submitPrefix = hasGuide ? `${color.gray(S_BAR)} ` : ''; const selectedOption = this.options.find((opt) => opt.value === this.value) ?? opts.options[0]; const wrapped = wrapTextWithPrefix( @@ -55,16 +56,17 @@ export const selectKey = (opts: SelectKeyOptions) = return `${title}${wrapped}`; } case 'cancel': { - const cancelPrefix = `${color.gray(S_BAR)} `; + const cancelPrefix = hasGuide ? `${color.gray(S_BAR)} ` : ''; const wrapped = wrapTextWithPrefix( opts.output, opt(this.options[0], 'cancelled'), cancelPrefix ); - return `${title}${wrapped}\n${color.gray(S_BAR)}`; + return `${title}${wrapped}${hasGuide ? `\n${color.gray(S_BAR)}` : ''}`; } default: { - const defaultPrefix = `${color.cyan(S_BAR)} `; + const defaultPrefix = hasGuide ? `${color.cyan(S_BAR)} ` : ''; + const defaultPrefixEnd = hasGuide ? color.cyan(S_BAR_END) : ''; const wrapped = this.options .map((option, i) => wrapTextWithPrefix( @@ -74,7 +76,7 @@ export const selectKey = (opts: SelectKeyOptions) = ) ) .join('\n'); - return `${title}${wrapped}\n${color.cyan(S_BAR_END)}\n`; + return `${title}${wrapped}\n${defaultPrefixEnd}\n`; } } }, diff --git a/packages/prompts/test/__snapshots__/select-key.test.ts.snap b/packages/prompts/test/__snapshots__/select-key.test.ts.snap index c08c98b8..fe08336f 100644 --- a/packages/prompts/test/__snapshots__/select-key.test.ts.snap +++ b/packages/prompts/test/__snapshots__/select-key.test.ts.snap @@ -63,6 +63,24 @@ exports[`text (isCI = false) > caseSensitive: true makes options case-sensitive ] `; +exports[`text (isCI = false) > global withGuide: false removes guide 1`] = ` +[ + "", + "◆ foo + a  Option A + b  Option B + +", + "", + "", + "", + "◇ foo +Option A", + " +", +] +`; + exports[`text (isCI = false) > input is case-insensitive by default 1`] = ` [ "", @@ -270,6 +288,24 @@ exports[`text (isCI = false) > selects option by keypress 1`] = ` ] `; +exports[`text (isCI = false) > withGuide: false removes guide 1`] = ` +[ + "", + "◆ foo + a  Option A + b  Option B + +", + "", + "", + "", + "◇ foo +Option A", + " +", +] +`; + exports[`text (isCI = true) > can cancel by pressing escape 1`] = ` [ "", @@ -333,6 +369,24 @@ exports[`text (isCI = true) > caseSensitive: true makes options case-sensitive 1 ] `; +exports[`text (isCI = true) > global withGuide: false removes guide 1`] = ` +[ + "", + "◆ foo + a  Option A + b  Option B + +", + "", + "", + "", + "◇ foo +Option A", + " +", +] +`; + exports[`text (isCI = true) > input is case-insensitive by default 1`] = ` [ "", @@ -539,3 +593,21 @@ exports[`text (isCI = true) > selects option by keypress 1`] = ` ", ] `; + +exports[`text (isCI = true) > withGuide: false removes guide 1`] = ` +[ + "", + "◆ foo + a  Option A + b  Option B + +", + "", + "", + "", + "◇ foo +Option A", + " +", +] +`; diff --git a/packages/prompts/test/select-key.test.ts b/packages/prompts/test/select-key.test.ts index d676729a..2e143a88 100644 --- a/packages/prompts/test/select-key.test.ts +++ b/packages/prompts/test/select-key.test.ts @@ -211,6 +211,45 @@ describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => { expect(output.buffer).toMatchSnapshot(); }); + test('withGuide: false removes guide', async () => { + const result = prompts.selectKey({ + message: 'foo', + options: [ + { label: 'Option A', value: 'a' }, + { label: 'Option B', value: 'b' }, + ], + withGuide: false, + input, + output, + }); + + input.emit('keypress', 'a', { name: 'a' }); + + await result; + + expect(output.buffer).toMatchSnapshot(); + }); + + test('global withGuide: false removes guide', async () => { + updateSettings({ withGuide: false }); + + const result = prompts.selectKey({ + message: 'foo', + options: [ + { label: 'Option A', value: 'a' }, + { label: 'Option B', value: 'b' }, + ], + input, + output, + }); + + input.emit('keypress', 'a', { name: 'a' }); + + await result; + + expect(output.buffer).toMatchSnapshot(); + }); + test('long submitted labels are wrapped correctly', async () => { output.columns = 40;