1+ import { styleText } from 'node:util' ;
12import { AutocompletePrompt } from '@clack/core' ;
2- import color from 'picocolors' ;
33import {
44 type CommonOptions ,
55 S_BAR ,
@@ -89,7 +89,7 @@ export const autocomplete = <Value>(opts: AutocompleteOptions<Value>) => {
8989 validate : opts . validate ,
9090 render ( ) {
9191 // Title and message display
92- const headings = [ `${ color . gray ( S_BAR ) } ` , `${ symbol ( this . state ) } ${ opts . message } ` ] ;
92+ const headings = [ `${ styleText ( 'gray' , S_BAR ) } ` , `${ symbol ( this . state ) } ${ opts . message } ` ] ;
9393 const userInput = this . userInput ;
9494 const valueAsString = String ( this . value ?? '' ) ;
9595 const options = this . options ;
@@ -102,59 +102,64 @@ export const autocomplete = <Value>(opts: AutocompleteOptions<Value>) => {
102102 // Show selected value
103103 const selected = getSelectedOptions ( this . selectedValues , options ) ;
104104 const label =
105- selected . length > 0 ? ` ${ color . dim ( selected . map ( getLabel ) . join ( ', ' ) ) } ` : '' ;
106- return `${ headings . join ( '\n' ) } \n${ color . gray ( S_BAR ) } ${ label } ` ;
105+ selected . length > 0 ? ` ${ styleText ( 'dim' , selected . map ( getLabel ) . join ( ', ' ) ) } ` : '' ;
106+ return `${ headings . join ( '\n' ) } \n${ styleText ( 'gray' , S_BAR ) } ${ label } ` ;
107107 }
108108
109109 case 'cancel' : {
110- const userInputText = userInput ? ` ${ color . strikethrough ( color . dim ( userInput ) ) } ` : '' ;
111- return `${ headings . join ( '\n' ) } \n${ color . gray ( S_BAR ) } ${ userInputText } ` ;
110+ const userInputText = userInput
111+ ? ` ${ styleText ( 'strikethrough' , styleText ( 'dim' , userInput ) ) } `
112+ : '' ;
113+ return `${ headings . join ( '\n' ) } \n${ styleText ( 'gray' , S_BAR ) } ${ userInputText } ` ;
112114 }
113115
114116 default : {
115117 // Display cursor position - show plain text in navigation mode
116118 let searchText = '' ;
117119 if ( this . isNavigating || showPlaceholder ) {
118120 const searchTextValue = showPlaceholder ? placeholder : userInput ;
119- searchText = searchTextValue !== '' ? ` ${ color . dim ( searchTextValue ) } ` : '' ;
121+ searchText = searchTextValue !== '' ? ` ${ styleText ( 'dim' , searchTextValue ) } ` : '' ;
120122 } else {
121123 searchText = ` ${ this . userInputWithCursor } ` ;
122124 }
123125
124126 // Show match count if filtered
125127 const matches =
126128 this . filteredOptions . length !== options . length
127- ? color . dim (
129+ ? styleText (
130+ 'dim' ,
128131 ` (${ this . filteredOptions . length } match${ this . filteredOptions . length === 1 ? '' : 'es' } )`
129132 )
130133 : '' ;
131134
132135 // No matches message
133136 const noResults =
134137 this . filteredOptions . length === 0 && userInput
135- ? [ `${ color . cyan ( S_BAR ) } ${ color . yellow ( 'No matches found' ) } ` ]
138+ ? [ `${ styleText ( 'cyan' , S_BAR ) } ${ styleText ( 'yellow' , 'No matches found' ) } ` ]
136139 : [ ] ;
137140
138141 const validationError =
139- this . state === 'error' ? [ `${ color . yellow ( S_BAR ) } ${ color . yellow ( this . error ) } ` ] : [ ] ;
142+ this . state === 'error'
143+ ? [ `${ styleText ( 'yellow' , S_BAR ) } ${ styleText ( 'yellow' , this . error ) } ` ]
144+ : [ ] ;
140145
141146 headings . push (
142- `${ color . cyan ( S_BAR ) } ` ,
143- `${ color . cyan ( S_BAR ) } ${ color . dim ( 'Search:' ) } ${ searchText } ${ matches } ` ,
147+ `${ styleText ( 'cyan' , S_BAR ) } ` ,
148+ `${ styleText ( 'cyan' , S_BAR ) } ${ styleText ( 'dim' , 'Search:' ) } ${ searchText } ${ matches } ` ,
144149 ...noResults ,
145150 ...validationError
146151 ) ;
147152
148153 // Show instructions
149154 const instructions = [
150- `${ color . dim ( '↑/↓' ) } to select` ,
151- `${ color . dim ( 'Enter:' ) } confirm` ,
152- `${ color . dim ( 'Type:' ) } to search` ,
155+ `${ styleText ( 'dim' , '↑/↓' ) } to select` ,
156+ `${ styleText ( 'dim' , 'Enter:' ) } confirm` ,
157+ `${ styleText ( 'dim' , 'Type:' ) } to search` ,
153158 ] ;
154159
155160 const footers = [
156- `${ color . cyan ( S_BAR ) } ${ color . dim ( instructions . join ( ' • ' ) ) } ` ,
157- `${ color . cyan ( S_BAR_END ) } ` ,
161+ `${ styleText ( 'cyan' , S_BAR ) } ${ styleText ( 'dim' , instructions . join ( ' • ' ) ) } ` ,
162+ `${ styleText ( 'cyan' , S_BAR_END ) } ` ,
158163 ] ;
159164
160165 // Render options with selection
@@ -170,12 +175,12 @@ export const autocomplete = <Value>(opts: AutocompleteOptions<Value>) => {
170175 const label = getLabel ( option ) ;
171176 const hint =
172177 option . hint && option . value === this . focusedValue
173- ? color . dim ( ` (${ option . hint } )` )
178+ ? styleText ( 'dim' , ` (${ option . hint } )` )
174179 : '' ;
175180
176181 return active
177- ? `${ color . green ( S_RADIO_ACTIVE ) } ${ label } ${ hint } `
178- : `${ color . dim ( S_RADIO_INACTIVE ) } ${ color . dim ( label ) } ${ hint } ` ;
182+ ? `${ styleText ( 'green' , S_RADIO_ACTIVE ) } ${ label } ${ hint } `
183+ : `${ styleText ( 'dim' , S_RADIO_INACTIVE ) } ${ styleText ( 'dim' , label ) } ${ hint } ` ;
179184 } ,
180185 maxItems : opts . maxItems ,
181186 output : opts . output ,
@@ -184,7 +189,7 @@ export const autocomplete = <Value>(opts: AutocompleteOptions<Value>) => {
184189 // Return the formatted prompt
185190 return [
186191 ...headings ,
187- ...displayOptions . map ( ( option ) => `${ color . cyan ( S_BAR ) } ${ option } ` ) ,
192+ ...displayOptions . map ( ( option ) => `${ styleText ( 'cyan' , S_BAR ) } ${ option } ` ) ,
188193 ...footers ,
189194 ] . join ( '\n' ) ;
190195 }
@@ -222,14 +227,16 @@ export const autocompleteMultiselect = <Value>(opts: AutocompleteMultiSelectOpti
222227 const label = option . label ?? String ( option . value ?? '' ) ;
223228 const hint =
224229 option . hint && focusedValue !== undefined && option . value === focusedValue
225- ? color . dim ( ` (${ option . hint } )` )
230+ ? styleText ( 'dim' , ` (${ option . hint } )` )
226231 : '' ;
227- const checkbox = isSelected ? color . green ( S_CHECKBOX_SELECTED ) : color . dim ( S_CHECKBOX_INACTIVE ) ;
232+ const checkbox = isSelected
233+ ? styleText ( 'green' , S_CHECKBOX_SELECTED )
234+ : styleText ( 'dim' , S_CHECKBOX_INACTIVE ) ;
228235
229236 if ( active ) {
230237 return `${ checkbox } ${ label } ${ hint } ` ;
231238 }
232- return `${ checkbox } ${ color . dim ( label ) } ` ;
239+ return `${ checkbox } ${ styleText ( 'dim' , label ) } ` ;
233240 } ;
234241
235242 // Create text prompt which we'll use as foundation
@@ -251,7 +258,7 @@ export const autocompleteMultiselect = <Value>(opts: AutocompleteMultiSelectOpti
251258 output : opts . output ,
252259 render ( ) {
253260 // Title and symbol
254- const title = `${ color . gray ( S_BAR ) } \n${ symbol ( this . state ) } ${ opts . message } \n` ;
261+ const title = `${ styleText ( 'gray' , S_BAR ) } \n${ symbol ( this . state ) } ${ opts . message } \n` ;
255262
256263 // Selection counter
257264 const userInput = this . userInput ;
@@ -261,43 +268,46 @@ export const autocompleteMultiselect = <Value>(opts: AutocompleteMultiSelectOpti
261268 // Search input display
262269 const searchText =
263270 this . isNavigating || showPlaceholder
264- ? color . dim ( showPlaceholder ? placeholder : userInput ) // Just show plain text when in navigation mode
271+ ? styleText ( 'dim' , showPlaceholder ? placeholder : userInput ) // Just show plain text when in navigation mode
265272 : this . userInputWithCursor ;
266273
267274 const options = this . options ;
268275
269276 const matches =
270277 this . filteredOptions . length !== options . length
271- ? color . dim (
278+ ? styleText (
279+ 'dim' ,
272280 ` (${ this . filteredOptions . length } match${ this . filteredOptions . length === 1 ? '' : 'es' } )`
273281 )
274282 : '' ;
275283
276284 // Render prompt state
277285 switch ( this . state ) {
278286 case 'submit' : {
279- return `${ title } ${ color . gray ( S_BAR ) } ${ color . dim ( `${ this . selectedValues . length } items selected` ) } ` ;
287+ return `${ title } ${ styleText ( 'gray' , S_BAR ) } ${ styleText ( 'dim' , `${ this . selectedValues . length } items selected` ) } ` ;
280288 }
281289 case 'cancel' : {
282- return `${ title } ${ color . gray ( S_BAR ) } ${ color . strikethrough ( color . dim ( userInput ) ) } ` ;
290+ return `${ title } ${ styleText ( 'gray' , S_BAR ) } ${ styleText ( ' strikethrough' , styleText ( ' dim' , userInput ) ) } ` ;
283291 }
284292 default : {
285293 // Instructions
286294 const instructions = [
287- `${ color . dim ( '↑/↓' ) } to navigate` ,
288- `${ color . dim ( this . isNavigating ? 'Space/Tab:' : 'Tab:' ) } select` ,
289- `${ color . dim ( 'Enter:' ) } confirm` ,
290- `${ color . dim ( 'Type:' ) } to search` ,
295+ `${ styleText ( 'dim' , '↑/↓' ) } to navigate` ,
296+ `${ styleText ( 'dim' , this . isNavigating ? 'Space/Tab:' : 'Tab:' ) } select` ,
297+ `${ styleText ( 'dim' , 'Enter:' ) } confirm` ,
298+ `${ styleText ( 'dim' , 'Type:' ) } to search` ,
291299 ] ;
292300
293301 // No results message
294302 const noResults =
295303 this . filteredOptions . length === 0 && userInput
296- ? [ `${ color . cyan ( S_BAR ) } ${ color . yellow ( 'No matches found' ) } ` ]
304+ ? [ `${ styleText ( 'cyan' , S_BAR ) } ${ styleText ( 'yellow' , 'No matches found' ) } ` ]
297305 : [ ] ;
298306
299307 const errorMessage =
300- this . state === 'error' ? [ `${ color . cyan ( S_BAR ) } ${ color . yellow ( this . error ) } ` ] : [ ] ;
308+ this . state === 'error'
309+ ? [ `${ styleText ( 'cyan' , S_BAR ) } ${ styleText ( 'yellow' , this . error ) } ` ]
310+ : [ ] ;
301311
302312 // Get limited options for display
303313 const displayOptions = limitOptions ( {
@@ -312,12 +322,12 @@ export const autocompleteMultiselect = <Value>(opts: AutocompleteMultiSelectOpti
312322 // Build the prompt display
313323 return [
314324 title ,
315- `${ color . cyan ( S_BAR ) } ${ color . dim ( 'Search:' ) } ${ searchText } ${ matches } ` ,
325+ `${ styleText ( 'cyan' , S_BAR ) } ${ styleText ( 'dim' , 'Search:' ) } ${ searchText } ${ matches } ` ,
316326 ...noResults ,
317327 ...errorMessage ,
318- ...displayOptions . map ( ( option ) => `${ color . cyan ( S_BAR ) } ${ option } ` ) ,
319- `${ color . cyan ( S_BAR ) } ${ color . dim ( instructions . join ( ' • ' ) ) } ` ,
320- `${ color . cyan ( S_BAR_END ) } ` ,
328+ ...displayOptions . map ( ( option ) => `${ styleText ( 'cyan' , S_BAR ) } ${ option } ` ) ,
329+ `${ styleText ( 'cyan' , S_BAR ) } ${ styleText ( 'dim' , instructions . join ( ' • ' ) ) } ` ,
330+ `${ styleText ( 'cyan' , S_BAR_END ) } ` ,
321331 ] . join ( '\n' ) ;
322332 }
323333 }
0 commit comments