Skip to content

Commit

Permalink
Feat(confirm): Toggle value on tab keypress. Fix #731
Browse files Browse the repository at this point in the history
  • Loading branch information
SBoudrias committed Dec 7, 2024
1 parent fca7524 commit e625f21
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
35 changes: 28 additions & 7 deletions packages/confirm/confirm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('confirm prompt', () => {
events.keypress('enter');

await expect(answer).resolves.toEqual(true);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? yes"');
expect(getScreen()).toMatchInlineSnapshot(`"✔ Do you want to proceed? Yes"`);
});

it('handles "no"', async () => {
Expand All @@ -32,7 +32,7 @@ describe('confirm prompt', () => {
events.keypress('enter');

await expect(answer).resolves.toEqual(false);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? no"');
expect(getScreen()).toMatchInlineSnapshot(`"✔ Do you want to proceed? No"`);
});

it('handles "y"', async () => {
Expand All @@ -48,7 +48,7 @@ describe('confirm prompt', () => {
events.keypress('enter');

await expect(answer).resolves.toEqual(true);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? yes"');
expect(getScreen()).toMatchInlineSnapshot(`"✔ Do you want to proceed? Yes"`);
});

it('handles "n"', async () => {
Expand All @@ -64,7 +64,7 @@ describe('confirm prompt', () => {
events.keypress('enter');

await expect(answer).resolves.toEqual(false);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? no"');
expect(getScreen()).toMatchInlineSnapshot(`"✔ Do you want to proceed? No"`);
});

it('uses default (yes) on empty input', async () => {
Expand All @@ -78,7 +78,7 @@ describe('confirm prompt', () => {
events.keypress('enter');

await expect(answer).resolves.toEqual(true);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? yes"');
expect(getScreen()).toMatchInlineSnapshot(`"✔ Do you want to proceed? Yes"`);
});

it('uses default (no) on empty input', async () => {
Expand All @@ -92,7 +92,7 @@ describe('confirm prompt', () => {
events.keypress('enter');

await expect(answer).resolves.toEqual(false);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? no"');
expect(getScreen()).toMatchInlineSnapshot(`"✔ Do you want to proceed? No"`);
});

it('uses default on gibberish input', async () => {
Expand All @@ -107,7 +107,7 @@ describe('confirm prompt', () => {
events.keypress('enter');

await expect(answer).resolves.toEqual(true);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? yes"');
expect(getScreen()).toMatchInlineSnapshot(`"✔ Do you want to proceed? Yes"`);
});

it('supports transformer option', async () => {
Expand All @@ -123,4 +123,25 @@ describe('confirm prompt', () => {
await expect(answer).resolves.toEqual(true);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? Oui!"');
});

it('toggle between values with the tab key', async () => {
const { answer, events, getScreen } = await render(confirm, {
message: 'Do you want to proceed?',
});

expect(getScreen()).toMatchInlineSnapshot('"? Do you want to proceed? (Y/n)"');

events.keypress('tab');
expect(getScreen()).toMatchInlineSnapshot(`"? Do you want to proceed? (Y/n) No"`);

events.keypress('tab');
expect(getScreen()).toMatchInlineSnapshot(`"? Do you want to proceed? (Y/n) Yes"`);

events.keypress('tab');
expect(getScreen()).toMatchInlineSnapshot(`"? Do you want to proceed? (Y/n) No"`);

events.keypress('enter');
await expect(answer).resolves.toEqual(false);
expect(getScreen()).toMatchInlineSnapshot('"✔ Do you want to proceed? No"');
});
});
23 changes: 18 additions & 5 deletions packages/confirm/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,35 @@ type ConfirmConfig = {
theme?: PartialDeep<Theme>;
};

function getBooleanValue(value: string, defaultValue?: boolean): boolean {
let answer = defaultValue !== false;
if (/^(y|yes)/i.test(value)) answer = true;
else if (/^(n|no)/i.test(value)) answer = false;
return answer;
}

function boolToString(value: boolean): string {
return value ? 'Yes' : 'No';
}

export default createPrompt<boolean, ConfirmConfig>((config, done) => {
const { transformer = (answer) => (answer ? 'yes' : 'no') } = config;
const { transformer = boolToString } = config;
const [status, setStatus] = useState<Status>('idle');
const [value, setValue] = useState('');
const theme = makeTheme(config.theme);
const prefix = usePrefix({ status, theme });

useKeypress((key, rl) => {
if (isEnterKey(key)) {
let answer = config.default !== false;
if (/^(y|yes)/i.test(value)) answer = true;
else if (/^(n|no)/i.test(value)) answer = false;

const answer = getBooleanValue(value, config.default);
setValue(transformer(answer));
setStatus('done');
done(answer);
} else if (key.name === 'tab') {
const answer = boolToString(!getBooleanValue(value, config.default));
rl.clearLine(0); // Remove the tab character.
rl.write(answer);
setValue(answer);
} else {
setValue(rl.line);
}
Expand Down

0 comments on commit e625f21

Please sign in to comment.