From aea4573c36afd7efdc7dce70e77f5888bb6e3399 Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Tue, 23 Sep 2025 09:33:17 +0100 Subject: [PATCH] fix: hard wrap and clamp lines in limit-options (#398) --- .changeset/better-hotels-fall.md | 5 +++++ packages/prompts/package.json | 2 +- packages/prompts/src/limit-options.ts | 7 +++++-- packages/prompts/test/limit-options.test.ts | 2 +- packages/prompts/vitest.config.ts | 3 +++ 5 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 .changeset/better-hotels-fall.md diff --git a/.changeset/better-hotels-fall.md b/.changeset/better-hotels-fall.md new file mode 100644 index 0000000..b12ce57 --- /dev/null +++ b/.changeset/better-hotels-fall.md @@ -0,0 +1,5 @@ +--- +"@clack/prompts": patch +--- + +Clamp scrolling windows to 5 rows. diff --git a/packages/prompts/package.json b/packages/prompts/package.json index 4e735d5..48d0ee5 100644 --- a/packages/prompts/package.json +++ b/packages/prompts/package.json @@ -50,7 +50,7 @@ "scripts": { "build": "unbuild", "prepack": "pnpm build", - "test": "FORCE_COLOR=1 vitest run" + "test": "vitest run" }, "dependencies": { "@clack/core": "workspace:*", diff --git a/packages/prompts/src/limit-options.ts b/packages/prompts/src/limit-options.ts index 7f0f56f..11d8f6d 100644 --- a/packages/prompts/src/limit-options.ts +++ b/packages/prompts/src/limit-options.ts @@ -46,7 +46,7 @@ export const limitOptions = (params: LimitOptionsParams): stri const paramMaxItems = params.maxItems ?? Number.POSITIVE_INFINITY; const outputMaxItems = Math.max(rows - rowPadding, 0); // We clamp to minimum 5 because anything less doesn't make sense UX wise - const maxItems = Math.max(paramMaxItems, 5); + const maxItems = Math.max(Math.min(paramMaxItems, outputMaxItems), 5); let slidingWindowLocation = 0; if (cursor >= maxItems - 3) { @@ -73,7 +73,10 @@ export const limitOptions = (params: LimitOptionsParams): stri slidingWindowLocationEnd - (shouldRenderBottomEllipsis ? 1 : 0); for (let i = slidingWindowLocationWithEllipsis; i < slidingWindowLocationEndWithEllipsis; i++) { - const wrappedLines = wrapAnsi(style(options[i], i === cursor), maxWidth).split('\n'); + const wrappedLines = wrapAnsi(style(options[i], i === cursor), maxWidth, { + hard: true, + trim: false, + }).split('\n'); lineGroups.push(wrappedLines); lineCount += wrappedLines.length; } diff --git a/packages/prompts/test/limit-options.test.ts b/packages/prompts/test/limit-options.test.ts index 95d1397..f48f4a7 100644 --- a/packages/prompts/test/limit-options.test.ts +++ b/packages/prompts/test/limit-options.test.ts @@ -103,7 +103,7 @@ describe('limitOptions', () => { output.rows = 7; options.maxItems = 10; const result = limitOptions(options); - expect(result).toEqual(['Item 1', 'Item 2', 'Item 3', color.dim('...')]); + expect(result).toEqual(['Item 1', 'Item 2', color.dim('...')]); }); test('handle multi-line item clamping (start)', async () => { diff --git a/packages/prompts/vitest.config.ts b/packages/prompts/vitest.config.ts index bfd9650..fd3a35a 100644 --- a/packages/prompts/vitest.config.ts +++ b/packages/prompts/vitest.config.ts @@ -2,6 +2,9 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { + env: { + FORCE_COLOR: '1', + }, snapshotSerializers: ['vitest-ansi-serializer'], }, }); -- 2.51.2