From c548e141562d9d3df75234fc16b9bd5fcae84385 Mon Sep 17 00:00:00 2001 From: Simon Boudrias Date: Sat, 21 Oct 2023 19:44:19 +0200 Subject: [PATCH] Feat: Add basic theming to all prompts --- packages/checkbox/src/index.mts | 73 +++++++++++++++++----------- packages/confirm/package.json | 3 +- packages/confirm/src/index.mts | 13 +++-- packages/core/src/lib/make-theme.mts | 13 +++-- packages/core/src/lib/theme.mts | 31 +++++++++++- packages/core/src/lib/use-prefix.mts | 10 +--- packages/editor/package.json | 1 - packages/editor/src/index.mts | 25 ++++++---- packages/expand/src/index.mts | 13 ++--- packages/input/package.json | 3 +- packages/input/src/index.mts | 16 +++--- packages/password/package.json | 3 +- packages/password/src/index.mts | 18 ++++--- packages/rawlist/src/index.mts | 12 +++-- packages/select/src/index.mts | 62 +++++++++++++---------- yarn.lock | 4 -- 16 files changed, 179 insertions(+), 121 deletions(-) diff --git a/packages/checkbox/src/index.mts b/packages/checkbox/src/index.mts index 587ca98643..de247c65b1 100644 --- a/packages/checkbox/src/index.mts +++ b/packages/checkbox/src/index.mts @@ -5,6 +5,7 @@ import { usePrefix, usePagination, useMemo, + makeTheme, isUpKey, isDownKey, isSpaceKey, @@ -18,6 +19,20 @@ import chalk from 'chalk'; import figures from 'figures'; import ansiEscapes from 'ansi-escapes'; +type CheckboxTheme = { + checkedIcon: string; + uncheckedIcon: string; + cursorIcon: string; + disabled: (text: string) => string; +}; + +const checkboxTheme: CheckboxTheme = { + checkedIcon: chalk.green(figures.circleFilled), + uncheckedIcon: figures.circle, + cursorIcon: figures.pointer, + disabled: (text: string) => chalk.dim(`- ${text}`), +}; + type Choice = { name?: string; value: Value; @@ -37,7 +52,11 @@ type Config = { validate?: ( items: ReadonlyArray>, ) => boolean | string | Promise; - theme?: Partial; + theme?: Partial< + Theme & { + style: Partial['style']>; + } + >; }; type Item = Separator | Choice; @@ -60,24 +79,6 @@ function check(checked: boolean) { }; } -function renderItem({ item, isActive }: { item: Item; isActive: boolean }) { - if (Separator.isSeparator(item)) { - return ` ${item.separator}`; - } - - const line = item.name || item.value; - if (item.disabled) { - const disabledLabel = - typeof item.disabled === 'string' ? item.disabled : '(disabled)'; - return chalk.dim(`- ${line} ${disabledLabel}`); - } - - const checkbox = item.checked ? chalk.green(figures.circleFilled) : figures.circle; - const color = isActive ? chalk.cyan : (x: string) => x; - const prefix = isActive ? figures.pointer : ' '; - return color(`${prefix}${checkbox} ${line}`); -} - export default createPrompt( (config: Config, done: (value: Array) => void) => { const { @@ -87,8 +88,8 @@ export default createPrompt( choices, required, validate = () => true, - theme, } = config; + const theme = makeTheme(checkboxTheme, config.theme); const prefix = usePrefix({ theme }); const [status, setStatus] = useState('pending'); const [items, setItems] = useState>>( @@ -160,12 +161,28 @@ export default createPrompt( } }); - const message = chalk.bold(config.message); + const message = theme.style.message(config.message); const page = usePagination>({ items, active, - renderItem, + renderItem({ item, isActive }: { item: Item; isActive: boolean }) { + if (Separator.isSeparator(item)) { + return ` ${item.separator}`; + } + + const line = item.name || item.value; + if (item.disabled) { + const disabledLabel = + typeof item.disabled === 'string' ? item.disabled : '(disabled)'; + return theme.disabled(`${line} ${disabledLabel}`); + } + + const checkbox = item.checked ? theme.checkedIcon : theme.uncheckedIcon; + const color = isActive ? theme.style.highlight : (x: string) => x; + const cursor = isActive ? theme.cursorIcon : ' '; + return color(`${cursor}${checkbox} ${line}`); + }, pageSize, loop, }); @@ -174,7 +191,7 @@ export default createPrompt( const selection = items .filter(isChecked) .map((choice) => choice.name || choice.value); - return `${prefix} ${message} ${chalk.cyan(selection.join(', '))}`; + return `${prefix} ${message} ${theme.style.answer(selection.join(', '))}`; } let helpTip = ''; @@ -183,10 +200,10 @@ export default createPrompt( helpTip = instructions; } else { const keys = [ - `${chalk.cyan.bold('')} to select`, - `${chalk.cyan.bold('')} to toggle all`, - `${chalk.cyan.bold('')} to invert selection`, - `and ${chalk.cyan.bold('')} to proceed`, + `${theme.style.key('space')} to select`, + `${theme.style.key('a')} to toggle all`, + `${theme.style.key('i')} to invert selection`, + `and ${theme.style.key('enter')} to proceed`, ]; helpTip = ` (Press ${keys.join(', ')})`; } @@ -194,7 +211,7 @@ export default createPrompt( let error = ''; if (errorMsg) { - error = chalk.red(`> ${errorMsg}`); + error = theme.style.error(errorMsg); } return `${prefix} ${message}${helpTip}\n${page}\n${error}${ansiEscapes.cursorHide}`; diff --git a/packages/confirm/package.json b/packages/confirm/package.json index 8a1fc87dd8..f38c69f904 100644 --- a/packages/confirm/package.json +++ b/packages/confirm/package.json @@ -55,8 +55,7 @@ "homepage": "https://github.com/SBoudrias/Inquirer.js/blob/master/packages/confirm/README.md", "dependencies": { "@inquirer/core": "^5.1.2", - "@inquirer/type": "^1.1.6", - "chalk": "^4.1.2" + "@inquirer/type": "^1.1.6" }, "devDependencies": { "@inquirer/testing": "^2.1.10" diff --git a/packages/confirm/src/index.mts b/packages/confirm/src/index.mts index f22dfd6da9..6bcb157410 100644 --- a/packages/confirm/src/index.mts +++ b/packages/confirm/src/index.mts @@ -1,10 +1,10 @@ -import chalk from 'chalk'; import { createPrompt, useState, useKeypress, isEnterKey, usePrefix, + makeTheme, type Theme, } from '@inquirer/core'; import type {} from '@inquirer/type'; @@ -17,9 +17,10 @@ type ConfirmConfig = { }; export default createPrompt((config, done) => { - const { transformer = (answer) => (answer ? 'yes' : 'no'), theme } = config; + const { transformer = (answer) => (answer ? 'yes' : 'no') } = config; const [status, setStatus] = useState('pending'); const [value, setValue] = useState(''); + const theme = makeTheme(config.theme); const prefix = usePrefix({ theme }); useKeypress((key, rl) => { @@ -39,11 +40,13 @@ export default createPrompt((config, done) => { let formattedValue = value; let defaultValue = ''; if (status === 'done') { - formattedValue = chalk.cyan(value); + formattedValue = theme.style.answer(value); } else { - defaultValue = chalk.dim(config.default === false ? ' (y/N)' : ' (Y/n)'); + defaultValue = ` ${theme.style.defaultAnswer( + config.default === false ? 'y/N' : 'Y/n', + )}`; } - const message = chalk.bold(config.message); + const message = theme.style.message(config.message); return `${prefix} ${message}${defaultValue} ${formattedValue}`; }); diff --git a/packages/core/src/lib/make-theme.mts b/packages/core/src/lib/make-theme.mts index 7d86a9f85a..1a49df1fd9 100644 --- a/packages/core/src/lib/make-theme.mts +++ b/packages/core/src/lib/make-theme.mts @@ -1,11 +1,10 @@ import type { Prettify } from '@inquirer/type'; +import { defaultTheme, type Theme } from './theme.mjs'; export function makeTheme( - defaultSpecificTheme: SpecificTheme, - theme: Partial = {}, -): Prettify { - return { - ...defaultSpecificTheme, - ...theme, - }; + ...themes: ReadonlyArray>> +): Prettify> { + return Object.assign({}, defaultTheme, ...themes, { + style: Object.assign({}, defaultTheme.style, ...themes.map((theme) => theme?.style)), + }); } diff --git a/packages/core/src/lib/theme.mts b/packages/core/src/lib/theme.mts index 2fdbba84b6..b2f300fc7c 100644 --- a/packages/core/src/lib/theme.mts +++ b/packages/core/src/lib/theme.mts @@ -1,7 +1,36 @@ -export type Theme = { +import chalk from 'chalk'; +import spinners from 'cli-spinners'; +import type { Prettify } from '@inquirer/type'; + +export type DefaultTheme = { prefix: string; spinner: { interval: number; frames: string[]; }; + style: { + answer: (text: string) => string; + message: (text: string) => string; + error: (text: string) => string; + defaultAnswer: (text: string) => string; + help: (text: string) => string; + highlight: (text: string) => string; + key: (text: string) => string; + }; +}; + +export type Theme = Prettify; + +export const defaultTheme: DefaultTheme = { + prefix: chalk.green('?'), + spinner: spinners.dots, + style: { + answer: chalk.cyan, + message: chalk.bold, + error: (text) => chalk.red(`> ${text}`), + defaultAnswer: (text) => chalk.dim(`(${text})`), + help: (text) => chalk.dim(text), + highlight: chalk.cyan, + key: (text: string) => chalk.cyan.bold(`<${text}>`), + }, }; diff --git a/packages/core/src/lib/use-prefix.mts b/packages/core/src/lib/use-prefix.mts index dd503d9b8e..e77202933e 100644 --- a/packages/core/src/lib/use-prefix.mts +++ b/packages/core/src/lib/use-prefix.mts @@ -1,14 +1,8 @@ import chalk from 'chalk'; -import spinners from 'cli-spinners'; import { useState } from './use-state.mjs'; import { useEffect } from './use-effect.mjs'; import { makeTheme } from './make-theme.mjs'; -import type { Theme } from './theme.mjs'; - -const prefixTheme = { - prefix: chalk.green('?'), - spinner: spinners.dots, -} satisfies Partial; +import { type Theme } from './theme.mjs'; export function usePrefix({ isLoading = false, @@ -18,7 +12,7 @@ export function usePrefix({ theme?: Partial; }): string { const [tick, setTick] = useState(0); - const { prefix, spinner } = makeTheme(prefixTheme, theme); + const { prefix, spinner } = makeTheme(theme); useEffect((): void | (() => unknown) => { if (isLoading) { diff --git a/packages/editor/package.json b/packages/editor/package.json index 998612ecbf..3a4b308f41 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -56,7 +56,6 @@ "dependencies": { "@inquirer/core": "^5.1.2", "@inquirer/type": "^1.1.6", - "chalk": "^4.1.2", "external-editor": "^3.1.0" }, "scripts": { diff --git a/packages/editor/src/index.mts b/packages/editor/src/index.mts index 3f32d67d47..361721271c 100644 --- a/packages/editor/src/index.mts +++ b/packages/editor/src/index.mts @@ -1,4 +1,3 @@ -import chalk from 'chalk'; import { editAsync } from 'external-editor'; import { createPrompt, @@ -7,6 +6,7 @@ import { useKeypress, usePrefix, isEnterKey, + makeTheme, type InquirerReadline, type Theme, } from '@inquirer/core'; @@ -22,11 +22,15 @@ type EditorConfig = { }; export default createPrompt((config, done) => { - const { waitForUseInput = true, validate = () => true, theme } = config; + const { waitForUseInput = true, validate = () => true } = config; const [status, setStatus] = useState('pending'); const [value, setValue] = useState(config.default || ''); const [errorMsg, setError] = useState(undefined); + const theme = makeTheme(config.theme); + const isLoading = status === 'loading'; + const prefix = usePrefix({ isLoading, theme }); + function startEditor(rl: InquirerReadline) { rl.pause(); editAsync( @@ -72,20 +76,21 @@ export default createPrompt((config, done) => { } }); - const isLoading = status === 'loading'; - const prefix = usePrefix({ isLoading, theme }); - - let message = chalk.bold(config.message); + const message = theme.style.message(config.message); + let helpTip = ''; if (status === 'loading') { - message += chalk.dim(' Received'); + helpTip = theme.style.defaultAnswer('Received'); } else if (status === 'pending') { - message += chalk.dim(' Press to launch your preferred editor.'); + const enterKey = theme.style.key('enter'); + helpTip = theme.style.defaultAnswer( + `Press ${enterKey} to launch your preferred editor.`, + ); } let error = ''; if (errorMsg) { - error = chalk.red(`> ${errorMsg}`); + error = theme.style.error(errorMsg); } - return [`${prefix} ${message}`, error]; + return [`${prefix} ${message} ${helpTip}`, error]; }); diff --git a/packages/expand/src/index.mts b/packages/expand/src/index.mts index aee31c773c..af148c7a12 100644 --- a/packages/expand/src/index.mts +++ b/packages/expand/src/index.mts @@ -4,6 +4,7 @@ import { useKeypress, usePrefix, isEnterKey, + makeTheme, type Theme, } from '@inquirer/core'; import type {} from '@inquirer/type'; @@ -43,12 +44,12 @@ export default createPrompt((config, done) => { choices, default: defaultKey = 'h', expanded: defaultExpandState = false, - theme, } = config; const [status, setStatus] = useState('pending'); const [value, setValue] = useState(''); const [expanded, setExpanded] = useState(defaultExpandState); const [errorMsg, setError] = useState(undefined); + const theme = makeTheme(config.theme); const prefix = usePrefix({ theme }); useKeypress((event, rl) => { @@ -75,11 +76,11 @@ export default createPrompt((config, done) => { } }); - const message = chalk.bold(config.message); + const message = theme.style.message(config.message); if (status === 'done') { // TODO: `value` should be the display name instead of the raw value. - return `${prefix} ${message} ${chalk.cyan(value)}`; + return `${prefix} ${message} ${theme.style.answer(value)}`; } const allChoices = expanded ? choices : [...choices, helpChoice]; @@ -95,7 +96,7 @@ export default createPrompt((config, done) => { return choice.key; }) .join(''); - shortChoices = chalk.dim(` (${shortChoices})`); + shortChoices = ` ${theme.style.defaultAnswer(shortChoices)}`; // Expanded display style if (expanded) { @@ -104,7 +105,7 @@ export default createPrompt((config, done) => { .map((choice) => { const line = ` ${choice.key}) ${getChoiceKey(choice, 'name')}`; if (choice.key === value.toLowerCase()) { - return chalk.cyan(line); + return theme.style.highlight(line); } return line; @@ -120,7 +121,7 @@ export default createPrompt((config, done) => { let error = ''; if (errorMsg) { - error = chalk.red(`> ${errorMsg}`); + error = theme.style.error(errorMsg); } return [ diff --git a/packages/input/package.json b/packages/input/package.json index 863986f98c..089460d4f3 100644 --- a/packages/input/package.json +++ b/packages/input/package.json @@ -55,8 +55,7 @@ "homepage": "https://github.com/SBoudrias/Inquirer.js/blob/master/packages/input/README.md", "dependencies": { "@inquirer/core": "^5.1.2", - "@inquirer/type": "^1.1.6", - "chalk": "^4.1.2" + "@inquirer/type": "^1.1.6" }, "devDependencies": { "@inquirer/testing": "^2.1.10" diff --git a/packages/input/src/index.mts b/packages/input/src/index.mts index 7ff5617953..d325ec160c 100644 --- a/packages/input/src/index.mts +++ b/packages/input/src/index.mts @@ -5,10 +5,10 @@ import { usePrefix, isEnterKey, isBackspaceKey, + makeTheme, type Theme, } from '@inquirer/core'; import type {} from '@inquirer/type'; -import chalk from 'chalk'; type InputConfig = { message: string; @@ -19,7 +19,8 @@ type InputConfig = { }; export default createPrompt((config, done) => { - const { validate = () => true, theme } = config; + const { validate = () => true } = config; + const theme = makeTheme(config.theme); const [status, setStatus] = useState('pending'); const [defaultValue = '', setDefaultValue] = useState( config.default, @@ -64,23 +65,22 @@ export default createPrompt((config, done) => { } }); - const message = chalk.bold(config.message); + const message = theme.style.message(config.message); let formattedValue = value; if (typeof config.transformer === 'function') { formattedValue = config.transformer(value, { isFinal: status === 'done' }); - } - if (status === 'done') { - formattedValue = chalk.cyan(formattedValue); + } else if (status === 'done') { + formattedValue = theme.style.answer(formattedValue); } let defaultStr = ''; if (defaultValue && status !== 'done' && !value) { - defaultStr = chalk.dim(` (${defaultValue})`); + defaultStr = ` ${theme.style.defaultAnswer(defaultValue)}`; } let error = ''; if (errorMsg) { - error = chalk.red(`> ${errorMsg}`); + error = theme.style.error(errorMsg); } return [`${prefix} ${message}${defaultStr} ${formattedValue}`, error]; diff --git a/packages/password/package.json b/packages/password/package.json index 26c440a014..446ac8c78f 100644 --- a/packages/password/package.json +++ b/packages/password/package.json @@ -59,8 +59,7 @@ "dependencies": { "@inquirer/core": "^5.1.2", "@inquirer/type": "^1.1.6", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2" + "ansi-escapes": "^4.3.2" }, "devDependencies": { "@inquirer/testing": "^2.1.10" diff --git a/packages/password/src/index.mts b/packages/password/src/index.mts index ea86502c21..f8d506899d 100644 --- a/packages/password/src/index.mts +++ b/packages/password/src/index.mts @@ -4,24 +4,28 @@ import { useKeypress, usePrefix, isEnterKey, + makeTheme, + type Theme, } from '@inquirer/core'; -import chalk from 'chalk'; import ansiEscapes from 'ansi-escapes'; type PasswordConfig = { message: string; mask?: boolean | string; validate?: (value: string) => boolean | string | Promise; + theme?: Partial; }; export default createPrompt((config, done) => { const { validate = () => true } = config; + const theme = makeTheme(config.theme); + const [status, setStatus] = useState('pending'); const [errorMsg, setError] = useState(undefined); const [value, setValue] = useState(''); const isLoading = status === 'loading'; - const prefix = usePrefix(isLoading); + const prefix = usePrefix({ isLoading, theme }); useKeypress(async (key, rl) => { // Ignore keypress while our prompt is doing other processing. @@ -50,23 +54,23 @@ export default createPrompt((config, done) => { } }); - const message = chalk.bold(config.message); - let formattedValue = ''; + const message = theme.style.message(config.message); + let formattedValue = ''; if (config.mask) { const maskChar = typeof config.mask === 'string' ? config.mask : '*'; formattedValue = maskChar.repeat(value.length); } else if (status !== 'done') { - formattedValue = `${chalk.dim('[input is masked]')}${ansiEscapes.cursorHide}`; + formattedValue = `${theme.style.help('[input is masked]')}${ansiEscapes.cursorHide}`; } if (status === 'done') { - formattedValue = chalk.cyan(formattedValue); + formattedValue = theme.style.answer(formattedValue); } let error = ''; if (errorMsg) { - error = chalk.red(`> ${errorMsg}`); + error = theme.style.error(errorMsg); } return [`${prefix} ${message} ${formattedValue}`, error]; diff --git a/packages/rawlist/src/index.mts b/packages/rawlist/src/index.mts index 03aae8727a..d61a6a990a 100644 --- a/packages/rawlist/src/index.mts +++ b/packages/rawlist/src/index.mts @@ -5,6 +5,7 @@ import { usePrefix, isEnterKey, Separator, + makeTheme, type Theme, } from '@inquirer/core'; import type {} from '@inquirer/type'; @@ -32,10 +33,11 @@ function isSelectableChoice( export default createPrompt( (config: RawlistConfig, done: (value: Value) => void) => { - const { choices, theme } = config; + const { choices } = config; const [status, setStatus] = useState('pending'); const [value, setValue] = useState(''); const [errorMsg, setError] = useState(undefined); + const theme = makeTheme(config.theme); const prefix = usePrefix({ theme }); useKeypress((key, rl) => { @@ -66,10 +68,10 @@ export default createPrompt( } }); - const message = chalk.bold(config.message); + const message = theme.style.message(config.message); if (status === 'done') { - return `${prefix} ${message} ${chalk.cyan(value)}`; + return `${prefix} ${message} ${theme.style.answer(value)}`; } let index = 0; @@ -83,7 +85,7 @@ export default createPrompt( const line = ` ${choice.key || index}) ${choice.name || choice.value}`; if (choice.key === value.toLowerCase() || String(index) === value) { - return chalk.cyan(line); + return theme.style.highlight(line); } return line; @@ -92,7 +94,7 @@ export default createPrompt( let error = ''; if (errorMsg) { - error = chalk.red(`> ${errorMsg}`); + error = theme.style.error(errorMsg); } return [ diff --git a/packages/select/src/index.mts b/packages/select/src/index.mts index cdb777c48e..9a1d989afe 100644 --- a/packages/select/src/index.mts +++ b/packages/select/src/index.mts @@ -11,6 +11,7 @@ import { isDownKey, isNumberKey, Separator, + makeTheme, type Theme, } from '@inquirer/core'; import type {} from '@inquirer/type'; @@ -18,6 +19,16 @@ import chalk from 'chalk'; import figures from 'figures'; import ansiEscapes from 'ansi-escapes'; +type SelectTheme = { + cursorIcon: string; + disabled: (text: string) => string; +}; + +const selectTheme: SelectTheme = { + cursorIcon: figures.pointer, + disabled: (text: string) => chalk.dim(`- ${text}`), +}; + type Choice = { value: Value; name?: string; @@ -41,30 +52,14 @@ function isSelectable(item: Item): item is Choice { return !Separator.isSeparator(item) && !item.disabled; } -function renderItem({ item, isActive }: { item: Item; isActive: boolean }) { - if (Separator.isSeparator(item)) { - return ` ${item.separator}`; - } - - const line = item.name || item.value; - if (item.disabled) { - const disabledLabel = - typeof item.disabled === 'string' ? item.disabled : '(disabled)'; - return chalk.dim(`- ${line} ${disabledLabel}`); - } - - const color = isActive ? chalk.cyan : (x: string) => x; - const prefix = isActive ? figures.pointer : ` `; - return color(`${prefix} ${line}`); -} - export default createPrompt( ( - config: SelectConfig, + config: SelectConfig & { message: string }, done: (value: Value) => void, ): string => { - const { choices: items, loop = true, pageSize, theme } = config; + const { choices: items, loop = true, pageSize } = config; const firstRender = useRef(true); + const theme = makeTheme(selectTheme, config.theme); const prefix = usePrefix({ theme }); const [status, setStatus] = useState('pending'); @@ -119,24 +114,41 @@ export default createPrompt( } }); - let message = chalk.bold(config.message); + let message = theme.style.message(config.message); if (firstRender.current) { firstRender.current = false; - message += chalk.dim(' (Use arrow keys)'); + message += ` ${theme.style.help('(Use arrow keys)')}`; } const page = usePagination>({ items, active, - renderItem, + renderItem({ item, isActive }: { item: Item; isActive: boolean }) { + if (Separator.isSeparator(item)) { + return ` ${item.separator}`; + } + + const line = item.name || item.value; + if (item.disabled) { + const disabledLabel = + typeof item.disabled === 'string' ? item.disabled : '(disabled)'; + return theme.disabled(`${line} ${disabledLabel}`); + } + + const color = isActive ? theme.style.highlight : (x: string) => x; + const cursor = isActive ? theme.cursorIcon : ` `; + return color(`${cursor} ${line}`); + }, pageSize, loop, }); if (status === 'done') { - return `${prefix} ${message} ${chalk.cyan( - selectedChoice.name || selectedChoice.value, - )}`; + const answer = + selectedChoice.name || + // TODO: Could we enforce that at the type level? Name should be defined for non-string values. + String(selectedChoice.value); + return `${prefix} ${message} ${theme.style.answer(answer)}`; } const choiceDescription = selectedChoice.description diff --git a/yarn.lock b/yarn.lock index 8270e611e1..0588d38bc6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -373,7 +373,6 @@ __metadata: "@inquirer/core": ^5.1.2 "@inquirer/testing": ^2.1.10 "@inquirer/type": ^1.1.6 - chalk: ^4.1.2 languageName: unknown linkType: soft @@ -416,7 +415,6 @@ __metadata: dependencies: "@inquirer/core": ^5.1.2 "@inquirer/type": ^1.1.6 - chalk: ^4.1.2 external-editor: ^3.1.0 languageName: unknown linkType: soft @@ -448,7 +446,6 @@ __metadata: "@inquirer/core": ^5.1.2 "@inquirer/testing": ^2.1.10 "@inquirer/type": ^1.1.6 - chalk: ^4.1.2 languageName: unknown linkType: soft @@ -460,7 +457,6 @@ __metadata: "@inquirer/testing": ^2.1.10 "@inquirer/type": ^1.1.6 ansi-escapes: ^4.3.2 - chalk: ^4.1.2 languageName: unknown linkType: soft