@@ -16,6 +16,7 @@ import type { Option } from './select.js';
1616export interface MultiSelectOptions < Value > extends CommonOptions {
1717 message : string ;
1818 options : Option < Value > [ ] ;
19+ usage ?: boolean | string ;
1920 initialValues ?: Value [ ] ;
2021 maxItems ?: number ;
2122 required ?: boolean ;
@@ -69,6 +70,18 @@ export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
6970 }
7071 return `${ color . dim ( S_CHECKBOX_INACTIVE ) } ${ computeLabel ( label , color . dim ) } ` ;
7172 } ;
73+
74+ const defaultUsageMessage = `${ color . reset (
75+ color . dim (
76+ `Press ${ color . gray ( color . bgWhite ( color . inverse ( ' space ' ) ) ) } to select, ${ color . gray (
77+ color . bgWhite ( color . inverse ( ' enter ' ) )
78+ ) } to submit`
79+ )
80+ ) } `;
81+
82+ const usage = opts . usage ?? false ;
83+ const usageMessage = typeof usage === 'string' ? usage : defaultUsageMessage ;
84+
7285 const required = opts . required ?? true ;
7386
7487 return new MultiSelectPrompt ( {
@@ -81,13 +94,7 @@ export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
8194 cursorAt : opts . cursorAt ,
8295 validate ( selected : Value [ ] | undefined ) {
8396 if ( required && ( selected === undefined || selected . length === 0 ) )
84- return `Please select at least one option.\n${ color . reset (
85- color . dim (
86- `Press ${ color . gray ( color . bgWhite ( color . inverse ( ' space ' ) ) ) } to select, ${ color . gray (
87- color . bgWhite ( color . inverse ( ' enter ' ) )
88- ) } to submit`
89- )
90- ) } `;
97+ return `Please select at least one option.\n${ defaultUsageMessage } ` ;
9198 } ,
9299 render ( ) {
93100 const wrappedMessage = wrapTextWithPrefix (
@@ -161,6 +168,13 @@ export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
161168 }
162169 default : {
163170 const prefix = `${ color . cyan ( S_BAR ) } ` ;
171+ const footer =
172+ this . state === 'initial' && usage
173+ ? usageMessage
174+ . split ( '\n' )
175+ . map ( ( ln , i ) => ( i === 0 ? `${ color . cyan ( S_BAR_END ) } ${ ln } ` : ` ${ ln } ` ) )
176+ . join ( '\n' )
177+ : color . cyan ( S_BAR_END ) ;
164178 // Calculate rowPadding: title lines + footer lines (S_BAR_END + trailing newline)
165179 const titleLineCount = title . split ( '\n' ) . length ;
166180 const footerLineCount = 2 ; // S_BAR_END + trailing newline
@@ -172,7 +186,7 @@ export const multiselect = <Value>(opts: MultiSelectOptions<Value>) => {
172186 columnPadding : prefix . length ,
173187 rowPadding : titleLineCount + footerLineCount ,
174188 style : styleOption ,
175- } ) . join ( `\n${ prefix } ` ) } \n${ color . cyan ( S_BAR_END ) } \n`;
189+ } ) . join ( `\n${ prefix } ` ) } \n${ footer } \n`;
176190 }
177191 }
178192 } ,
0 commit comments