Skip to content

Commit

Permalink
Feat (select): Allow default config in Select prompt (#1329)
Browse files Browse the repository at this point in the history
* Feature: allow default on select

---------

Co-authored-by: sakulstra <[email protected]>
  • Loading branch information
SBoudrias and sakulstra authored Nov 5, 2023
1 parent 1c4c80a commit 1b3df3a
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/select/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const answer = await select({
| -------- | ---------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| message | `string` | yes | The question to ask |
| choices | `Array<{ value: string, name?: string, description?: string, disabled?: boolean \| string } \| 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. The `description` will be displayed under the prompt when the cursor land over the choice. |
| default | `string` | no | Defines in front of which item the cursor will initially appear. When omitted, the cursor will appear on the first selectable item. |
| 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. |

Expand Down
23 changes: 23 additions & 0 deletions packages/select/select.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,27 @@ describe('select prompt', () => {

await expect(answer).resolves.toEqual('pineapple');
});

it('Allows setting a default value', async () => {
const { answer, events, getScreen } = await render(select, {
message: 'Select a number',
choices: numberedChoices,
default: numberedChoices[3].value,
});

expect(getScreen()).toMatchInlineSnapshot(`
"? Select a number (Use arrow keys)
1
2
3
❯ 4
5
6
7
(Use arrow keys to reveal more choices)"
`);

events.keypress('enter');
await expect(answer).resolves.toEqual(4);
});
});
12 changes: 11 additions & 1 deletion packages/select/src/index.mts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type SelectConfig<Value> = PromptConfig<{
choices: ReadonlyArray<Choice<Value> | Separator>;
pageSize?: number;
loop?: boolean;
default?: Value;
}>;

type Item<Value> = Separator | Choice<Value>;
Expand Down Expand Up @@ -76,7 +77,16 @@ export default createPrompt(
return { first, last };
}, [items]);

const [active, setActive] = useState(bounds.first);
const defaultItemIndex = useMemo(() => {
if (!('default' in config)) return -1;
return items.findIndex(
(item) => isSelectable(item) && item.value === config.default,
);
}, [config.default, items]);

const [active, setActive] = useState(
defaultItemIndex === -1 ? bounds.first : defaultItemIndex,
);

// Safe to assume the cursor position always point to a Choice.
const selectedChoice = items[active] as Choice<Value>;
Expand Down

0 comments on commit 1b3df3a

Please sign in to comment.