| 94 | }; |
| 95 | |
| 96 | export const select = <Value>(opts: SelectOptions<Value>) => { |
| 97 | const opt = ( |
| 98 | option: Option<Value>, |
| 99 | state: 'inactive' | 'active' | 'selected' | 'cancelled' | 'disabled' |
| 100 | ) => { |
| 101 | const label = option.label ?? String(option.value); |
| 102 | switch (state) { |
| 103 | case 'disabled': |
| 104 | return `${styleText('gray', S_RADIO_INACTIVE)} ${computeLabel(label, (text) => styleText('gray', text))}${ |
| 105 | option.hint ? ` ${styleText('dim', `(${option.hint ?? 'disabled'})`)}` : '' |
| 106 | }`; |
| 107 | case 'selected': |
| 108 | return `${computeLabel(label, (text) => styleText('dim', text))}`; |
| 109 | case 'active': |
| 110 | return `${styleText('green', S_RADIO_ACTIVE)} ${label}${ |
| 111 | option.hint ? ` ${styleText('dim', `(${option.hint})`)}` : '' |
| 112 | }`; |
| 113 | case 'cancelled': |
| 114 | return `${computeLabel(label, (str) => styleText(['strikethrough', 'dim'], str))}`; |
| 115 | default: |
| 116 | return `${styleText('dim', S_RADIO_INACTIVE)} ${computeLabel(label, (text) => styleText('dim', text))}`; |
| 117 | } |
| 118 | }; |
| 119 | |
| 120 | const showInstructions = opts.showInstructions ?? true; |
| 121 | |
| 122 | return new SelectPrompt({ |
| 123 | options: opts.options, |
| 124 | signal: opts.signal, |
| 125 | input: opts.input, |
| 126 | output: opts.output, |
| 127 | initialValue: opts.initialValue, |
| 128 | render() { |
| 129 | const hasGuide = opts.withGuide ?? settings.withGuide; |
| 130 | const titlePrefix = `${symbol(this.state)} `; |
| 131 | const titlePrefixBar = `${symbolBar(this.state)} `; |
| 132 | const messageLines = wrapTextWithPrefix( |
| 133 | opts.output, |
| 134 | opts.message, |
| 135 | titlePrefixBar, |
| 136 | titlePrefix |
| 137 | ); |
| 138 | const title = `${hasGuide ? `${styleText('gray', S_BAR)}\n` : ''}${messageLines}\n`; |
| 139 | |
| 140 | switch (this.state) { |
| 141 | case 'submit': { |
| 142 | const submitPrefix = hasGuide ? `${styleText('gray', S_BAR)} ` : ''; |
| 143 | const wrappedLines = wrapTextWithPrefix( |
| 144 | opts.output, |
| 145 | opt(this.options[this.cursor], 'selected'), |
| 146 | submitPrefix |
| 147 | ); |
| 148 | return `${title}${wrappedLines}`; |
| 149 | } |
| 150 | case 'cancel': { |
| 151 | const cancelPrefix = hasGuide ? `${styleText('gray', S_BAR)} ` : ''; |
| 152 | const wrappedLines = wrapTextWithPrefix( |
| 153 | opts.output, |