Skip to content

Commit 8409f2c

Browse files
hyperz11143081j
andauthored
feat: add style function option to spinner (bombshell-dev#400)
Co-authored-by: James Garbutt <[email protected]>
1 parent aea4573 commit 8409f2c

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

.changeset/crazy-ducks-shine.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clack/prompts": minor
3+
---
4+
5+
feat: add styleFrame option for spinner

packages/prompts/src/spinner.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface SpinnerOptions extends CommonOptions {
1919
errorMessage?: string;
2020
frames?: string[];
2121
delay?: number;
22+
styleFrame?: (frame: string) => string;
2223
}
2324

2425
export interface SpinnerResult {
@@ -28,6 +29,8 @@ export interface SpinnerResult {
2829
readonly isCancelled: boolean;
2930
}
3031

32+
const defaultStyleFn: SpinnerOptions['styleFrame'] = color.magenta;
33+
3134
export const spinner = ({
3235
indicator = 'dots',
3336
onCancel,
@@ -37,6 +40,7 @@ export const spinner = ({
3740
frames = unicode ? ['◒', '◐', '◓', '◑'] : ['•', 'o', 'O', '0'],
3841
delay = unicode ? 80 : 120,
3942
signal,
43+
...opts
4044
}: SpinnerOptions = {}): SpinnerResult => {
4145
const isCI = isCIFn();
4246

@@ -48,6 +52,7 @@ export const spinner = ({
4852
let _prevMessage: string | undefined;
4953
let _origin: number = performance.now();
5054
const columns = getColumns(output);
55+
const styleFn = opts?.styleFrame ?? defaultStyleFn;
5156

5257
const handleExit = (code: number) => {
5358
const msg =
@@ -134,7 +139,7 @@ export const spinner = ({
134139
}
135140
clearPrevMessage();
136141
_prevMessage = _message;
137-
const frame = color.magenta(frames[frameIndex]);
142+
const frame = styleFn(frames[frameIndex]);
138143
let outputMessage: string;
139144

140145
if (isCI) {

packages/prompts/test/__snapshots__/spinner.test.ts.snap

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@ exports[`spinner (isCI = false) > indicator customization > custom delay 1`] = `
3434
]
3535
`;
3636
37+
exports[`spinner (isCI = false) > indicator customization > custom frame style 1`] = `
38+
[
39+
"<cursor.hide>",
40+
"│
41+
",
42+
"◒ ",
43+
"<cursor.left count=1>",
44+
"<erase.down>",
45+
"◐ ",
46+
"<cursor.left count=1>",
47+
"<erase.down>",
48+
"◓ ",
49+
"<cursor.left count=1>",
50+
"<erase.down>",
51+
"◑ ",
52+
"<cursor.left count=1>",
53+
"<erase.down>",
54+
"◇
55+
",
56+
"<cursor.show>",
57+
]
58+
`;
59+
3760
exports[`spinner (isCI = false) > indicator customization > custom frames 1`] = `
3861
[
3962
"<cursor.hide>",
@@ -535,6 +558,22 @@ exports[`spinner (isCI = true) > indicator customization > custom delay 1`] = `
535558
]
536559
`;
537560
561+
exports[`spinner (isCI = true) > indicator customization > custom frame style 1`] = `
562+
[
563+
"<cursor.hide>",
564+
"│
565+
",
566+
"◒ ...",
567+
"
568+
",
569+
"<cursor.left count=1>",
570+
"<erase.down>",
571+
"◇
572+
",
573+
"<cursor.show>",
574+
]
575+
`;
576+
538577
exports[`spinner (isCI = true) > indicator customization > custom frames 1`] = `
539578
[
540579
"<cursor.hide>",

packages/prompts/test/spinner.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { EventEmitter } from 'node:stream';
22
import { getColumns } from '@clack/core';
3+
import color from 'picocolors';
34
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
45
import * as prompts from '../src/index.js';
56
import { MockWritable } from './test-utils.js';
@@ -233,6 +234,20 @@ describe.each(['true', 'false'])('spinner (isCI = %s)', (isCI) => {
233234

234235
expect(output.buffer).toMatchSnapshot();
235236
});
237+
238+
test('custom frame style', () => {
239+
const result = prompts.spinner({ output, styleFrame: color.red });
240+
241+
result.start();
242+
243+
for (let i = 0; i < 4; i++) {
244+
vi.advanceTimersByTime(80);
245+
}
246+
247+
result.stop();
248+
249+
expect(output.buffer).toMatchSnapshot();
250+
});
236251
});
237252

238253
describe('process exit handling', () => {

0 commit comments

Comments
 (0)