From d274d15aaaf36ac3d6b25d1c0c5063038ee0d231 Mon Sep 17 00:00:00 2001 From: Simon Boudrias Date: Wed, 17 Jul 2024 17:34:39 -0400 Subject: [PATCH] Feat(@inquirer/checkbox) Add property to choices (matching inquirer API) --- packages/checkbox/README.md | 18 ++++++------ packages/checkbox/checkbox.test.mts | 45 +++++++++++++++++++++++++++++ packages/checkbox/src/index.mts | 5 +++- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/packages/checkbox/README.md b/packages/checkbox/README.md index 77fe5eb57..964a225be 100644 --- a/packages/checkbox/README.md +++ b/packages/checkbox/README.md @@ -52,15 +52,15 @@ const answer = await checkbox({ ## Options -| Property | Type | Required | Description | -| -------- | ------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| message | `string` | yes | The question to ask | -| choices | `Array<{ value: string, name?: string, disabled?: boolean \| string, checked?: boolean } \| Separator>` | yes | List of the available choices. The `value` will be returned as the answer, and used as display if no `name` is defined. Choices who're `disabled` will be displayed, but not selectable. | -| pageSize | `number` | no | By default, lists of choice longer than 7 will be paginated. Use this option to control how many choices will appear on the screen at once. | -| loop | `boolean` | no | Defaults to `true`. When set to `false`, the cursor will be constrained to the top and bottom of the choice list without looping. | -| required | `boolean` | no | When set to `true`, ensures at least one choice must be selected. | -| validate | `string\[\] => boolean \| string \| Promise` | no | On submit, validate the choices. When returning a string, it'll be used as the error message displayed to the user. Note: returning a rejected promise, we'll assume a code error happened and crash. | -| theme | [See Theming](#Theming) | no | Customize look of the prompt. | +| Property | Type | Required | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| message | `string` | yes | The question to ask | +| choices | `Array<{ value: string, name?: string, short?: string, disabled?: boolean \| string, checked?: boolean } \| Separator>` | yes | List of the available choices. The `value` will be returned as the answer, and used as display if no `name` is defined. Choices who're `disabled` will be displayed, but not selectable. `short` if defined will be used instead of `name` once submitted. | +| pageSize | `number` | no | By default, lists of choice longer than 7 will be paginated. Use this option to control how many choices will appear on the screen at once. | +| loop | `boolean` | no | Defaults to `true`. When set to `false`, the cursor will be constrained to the top and bottom of the choice list without looping. | +| required | `boolean` | no | When set to `true`, ensures at least one choice must be selected. | +| validate | `string\[\] => boolean \| string \| Promise` | no | On submit, validate the choices. When returning a string, it'll be used as the error message displayed to the user. Note: returning a rejected promise, we'll assume a code error happened and crash. | +| theme | [See Theming](#Theming) | no | Customize look of the prompt. | The `Separator` object can be used to render non-selectable lines in the choice list. By default it'll render a line, but you can provide the text as argument (`new Separator('-- Dependencies --')`). This option is often used to add labels to groups within long list of options. diff --git a/packages/checkbox/checkbox.test.mts b/packages/checkbox/checkbox.test.mts index cf5b67279..b207936de 100644 --- a/packages/checkbox/checkbox.test.mts +++ b/packages/checkbox/checkbox.test.mts @@ -758,6 +758,51 @@ describe('checkbox prompt', () => { ); }); + it('allow customizing short names after selection', async () => { + const { answer, events, getScreen } = await render(checkbox, { + message: 'Select a commit', + choices: [ + { + name: '2cc9e311 (HEAD -> main) Fix(inquirer): Ensure no mutation of the question', + value: '2cc9e311', + short: '2cc9e311', + }, + { + name: '3272b94a (origin/main) Fix(inquirer): Fix close method not required', + value: '3272b94a', + short: '3272b94a', + }, + { + name: 'e4e10545 Chore(dev-deps): Bump dev-deps', + value: 'e4e10545', + short: 'e4e10545', + }, + ], + }); + + expect(getScreen()).toMatchInlineSnapshot(` + "? Select a commit (Press to select, to toggle all, to invert + selection, and to proceed) + ❯◯ 2cc9e311 (HEAD -> main) Fix(inquirer): Ensure no mutation of the question + ◯ 3272b94a (origin/main) Fix(inquirer): Fix close method not required + ◯ e4e10545 Chore(dev-deps): Bump dev-deps" + `); + + events.keypress('space'); + events.keypress('down'); + events.keypress('space'); + expect(getScreen()).toMatchInlineSnapshot(` + "? Select a commit + ◉ 2cc9e311 (HEAD -> main) Fix(inquirer): Ensure no mutation of the question + ❯◉ 3272b94a (origin/main) Fix(inquirer): Fix close method not required + ◯ e4e10545 Chore(dev-deps): Bump dev-deps" + `); + + events.keypress('enter'); + await expect(answer).resolves.toEqual(['2cc9e311', '3272b94a']); + expect(getScreen()).toMatchInlineSnapshot(`"? Select a commit 2cc9e311, 3272b94a"`); + }); + it('using allChoices parameter', async () => { const { answer, events, getScreen } = await render(checkbox, { message: 'Select your favourite number.', diff --git a/packages/checkbox/src/index.mts b/packages/checkbox/src/index.mts index c80d00aa8..8177cd581 100644 --- a/packages/checkbox/src/index.mts +++ b/packages/checkbox/src/index.mts @@ -46,7 +46,9 @@ const checkboxTheme: CheckboxTheme = { style: { disabledChoice: (text: string) => colors.dim(`- ${text}`), renderSelectedChoices: (selectedChoices) => - selectedChoices.map((choice) => choice.name || choice.value).join(', '), + selectedChoices + .map((choice) => choice.short ?? choice.name ?? choice.value) + .join(', '), }, helpMode: 'auto', }; @@ -54,6 +56,7 @@ const checkboxTheme: CheckboxTheme = { type Choice = { name?: string; value: Value; + short?: string; disabled?: boolean | string; checked?: boolean; type?: never;