From 7f2d5c049b12a4754c9912157360834bae2e6e5e Mon Sep 17 00:00:00 2001 From: Paul Valladares <85648028+dreyfus92@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:04:31 -0500 Subject: [PATCH 1/3] fix(prompts): respect directory option in path prompt --- packages/prompts/src/path.ts | 2 +- packages/prompts/test/path.test.ts | 36 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/prompts/src/path.ts b/packages/prompts/src/path.ts index b630c7cc..d575ab33 100644 --- a/packages/prompts/src/path.ts +++ b/packages/prompts/src/path.ts @@ -63,7 +63,7 @@ export const path = (opts: PathOptions) => { }) .filter( ({ path, isDirectory }) => - path.startsWith(userInput) && (opts.directory || !isDirectory) + path.startsWith(userInput) && (isDirectory || !opts.directory) ); return items.map((item) => ({ value: item.path, diff --git a/packages/prompts/test/path.test.ts b/packages/prompts/test/path.test.ts index 0e15ec34..24f7d76d 100644 --- a/packages/prompts/test/path.test.ts +++ b/packages/prompts/test/path.test.ts @@ -146,6 +146,42 @@ describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => { expect(output.buffer).toMatchSnapshot(); }); + test('directory mode only allows selecting directories', async () => { + const result = prompts.path({ + message: 'foo', + root: '/tmp/', + directory: true, + input, + output, + }); + + input.emit('keypress', 'f', { name: 'f' }); + input.emit('keypress', '', { name: 'return' }); + + const value = await result; + + expect(value).toBe('/tmp/foo'); + }); + + test('default mode allows selecting files', async () => { + const result = prompts.path({ + message: 'foo', + root: '/tmp/', + input, + output, + }); + + input.emit('keypress', 'r', { name: 'r' }); + input.emit('keypress', 'o', { name: 'o' }); + input.emit('keypress', 'o', { name: 'o' }); + input.emit('keypress', 't', { name: 't' }); + input.emit('keypress', '', { name: 'return' }); + + const value = await result; + + expect(value).toBe('/tmp/root.zip'); + }); + test('validation errors render and clear', async () => { const result = prompts.path({ message: 'foo', From be5f7830e3dcc0cec0893f2585e65c4a2d7e8873 Mon Sep 17 00:00:00 2001 From: Paul Valladares <85648028+dreyfus92@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:08:09 -0500 Subject: [PATCH 2/3] add: changeset --- .changeset/big-pants-invite.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/big-pants-invite.md diff --git a/.changeset/big-pants-invite.md b/.changeset/big-pants-invite.md new file mode 100644 index 00000000..43f13e6b --- /dev/null +++ b/.changeset/big-pants-invite.md @@ -0,0 +1,5 @@ +--- +"@clack/prompts": patch +--- + +Fix the `path` prompt so `directory: true` correctly enforces directory-only selection while still allowing directory navigation, and add regression tests for both directory and default file selection behavior. From ee5482a3103ee3d7693b12b733570e86618b79a8 Mon Sep 17 00:00:00 2001 From: Paul Valladares <85648028+dreyfus92@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:09:54 -0500 Subject: [PATCH 3/3] update: snapshots --- .../test/__snapshots__/path.test.ts.snap | 80 ++++++++++++++----- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/packages/prompts/test/__snapshots__/path.test.ts.snap b/packages/prompts/test/__snapshots__/path.test.ts.snap index 9d81f118..0153e166 100644 --- a/packages/prompts/test/__snapshots__/path.test.ts.snap +++ b/packages/prompts/test/__snapshots__/path.test.ts.snap @@ -8,10 +8,12 @@ exports[`text (isCI = false) > can cancel 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "■ foo @@ -30,10 +32,12 @@ exports[`text (isCI = false) > cannot submit unknown value 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/_█ @@ -57,10 +61,12 @@ exports[`text (isCI = false) > cannot submit unknown value 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█ @@ -107,10 +113,12 @@ exports[`text (isCI = false) > renders cancelled value if one set 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/x█ @@ -141,10 +149,12 @@ exports[`text (isCI = false) > renders message 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "◇ foo @@ -163,10 +173,12 @@ exports[`text (isCI = false) > renders submitted value 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█ @@ -197,10 +209,12 @@ exports[`text (isCI = false) > validation errors render and clear (using Error) │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/r█ @@ -224,10 +238,12 @@ exports[`text (isCI = false) > validation errors render and clear (using Error) │ │ Search: /tmp/█ │ ○ /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ● /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█ @@ -253,10 +269,12 @@ exports[`text (isCI = false) > validation errors render and clear 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/r█ @@ -280,10 +298,12 @@ exports[`text (isCI = false) > validation errors render and clear 1`] = ` │ │ Search: /tmp/█ │ ○ /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ● /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█ @@ -309,10 +329,12 @@ exports[`text (isCI = true) > can cancel 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "■ foo @@ -331,10 +353,12 @@ exports[`text (isCI = true) > cannot submit unknown value 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/_█ @@ -358,10 +382,12 @@ exports[`text (isCI = true) > cannot submit unknown value 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█ @@ -408,10 +434,12 @@ exports[`text (isCI = true) > renders cancelled value if one set 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/x█ @@ -442,10 +470,12 @@ exports[`text (isCI = true) > renders message 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "◇ foo @@ -464,10 +494,12 @@ exports[`text (isCI = true) > renders submitted value 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█ @@ -498,10 +530,12 @@ exports[`text (isCI = true) > validation errors render and clear (using Error) 1 │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/r█ @@ -525,10 +559,12 @@ exports[`text (isCI = true) > validation errors render and clear (using Error) 1 │ │ Search: /tmp/█ │ ○ /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ● /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█ @@ -554,10 +590,12 @@ exports[`text (isCI = true) > validation errors render and clear 1`] = ` │ │ Search: /tmp/█ │ ● /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ○ /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/r█ @@ -581,10 +619,12 @@ exports[`text (isCI = true) > validation errors render and clear 1`] = ` │ │ Search: /tmp/█ │ ○ /tmp/bar +│ ○ /tmp/foo +│ ○ /tmp/hello │ ● /tmp/root.zip │ ↑/↓ to select • Enter: confirm • Type: to search └", - "", + "", "", "", "│ Search: /tmp/b█