Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cool-parrots-throw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clack/prompts": patch
---

destruct `limitOption` param for better code readability, tweak types definitions
30 changes: 16 additions & 14 deletions packages/prompts/src/limit-options.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import type { Writable } from 'node:stream';
import { getColumns, getRows } from '@clack/core';
import { wrapAnsi } from 'fast-wrap-ansi';
import color from 'picocolors';
import type { CommonOptions } from './common.js';

export interface LimitOptionsParams<TOption> extends CommonOptions {
options: TOption[];
maxItems: number | undefined;
cursor: number;
style: (option: TOption, active: boolean) => string;
maxItems?: number;
columnPadding?: number;
rowPadding?: number;
}
Expand All @@ -33,31 +32,34 @@ const trimLines = (
return { lineCount, removals };
};

export const limitOptions = <TOption>(params: LimitOptionsParams<TOption>): string[] => {
const { cursor, options, style } = params;
const output: Writable = params.output ?? process.stdout;
export const limitOptions = <TOption>({
cursor,
options,
style,
output = process.stdout,
maxItems = Number.POSITIVE_INFINITY,
columnPadding = 0,
rowPadding = 4
}: LimitOptionsParams<TOption>): string[] => {
const columns = getColumns(output);
const columnPadding = params.columnPadding ?? 0;
const rowPadding = params.rowPadding ?? 4;
const maxWidth = columns - columnPadding;
const rows = getRows(output);
const overflowFormat = color.dim('...');

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(Math.min(paramMaxItems, outputMaxItems), 5);
const computedMaxItems = Math.max(Math.min(maxItems, outputMaxItems), 5);
let slidingWindowLocation = 0;

if (cursor >= maxItems - 3) {
slidingWindowLocation = Math.max(Math.min(cursor - maxItems + 3, options.length - maxItems), 0);
if (cursor >= computedMaxItems - 3) {
slidingWindowLocation = Math.max(Math.min(cursor - computedMaxItems + 3, options.length - computedMaxItems), 0);
}

let shouldRenderTopEllipsis = maxItems < options.length && slidingWindowLocation > 0;
let shouldRenderTopEllipsis = computedMaxItems < options.length && slidingWindowLocation > 0;
let shouldRenderBottomEllipsis =
maxItems < options.length && slidingWindowLocation + maxItems < options.length;
computedMaxItems < options.length && slidingWindowLocation + computedMaxItems < options.length;

const slidingWindowLocationEnd = Math.min(slidingWindowLocation + maxItems, options.length);
const slidingWindowLocationEnd = Math.min(slidingWindowLocation + computedMaxItems, options.length);
const lineGroups: Array<string[]> = [];
let lineCount = 0;
if (shouldRenderTopEllipsis) {
Expand Down
Loading