| 'use strict'; | 
|   | 
| const colors = require('ansi-colors'); | 
| const SelectPrompt = require('./select'); | 
| const placeholder = require('../placeholder'); | 
|   | 
| class FormPrompt extends SelectPrompt { | 
|   constructor(options) { | 
|     super({ ...options, multiple: true }); | 
|     this.type = 'form'; | 
|     this.initial = this.options.initial; | 
|     this.align = [this.options.align, 'right'].find(v => v != null); | 
|     this.emptyError = ''; | 
|     this.values = {}; | 
|   } | 
|   | 
|   async reset(first) { | 
|     await super.reset(); | 
|     if (first === true) this._index = this.index; | 
|     this.index = this._index; | 
|     this.values = {}; | 
|     this.choices.forEach(choice => choice.reset && choice.reset()); | 
|     return this.render(); | 
|   } | 
|   | 
|   dispatch(char) { | 
|     return !!char && this.append(char); | 
|   } | 
|   | 
|   append(char) { | 
|     let choice = this.focused; | 
|     if (!choice) return this.alert(); | 
|     let { cursor, input } = choice; | 
|     choice.value = choice.input = input.slice(0, cursor) + char + input.slice(cursor); | 
|     choice.cursor++; | 
|     return this.render(); | 
|   } | 
|   | 
|   delete() { | 
|     let choice = this.focused; | 
|     if (!choice || choice.cursor <= 0) return this.alert(); | 
|     let { cursor, input } = choice; | 
|     choice.value = choice.input = input.slice(0, cursor - 1) + input.slice(cursor); | 
|     choice.cursor--; | 
|     return this.render(); | 
|   } | 
|   | 
|   deleteForward() { | 
|     let choice = this.focused; | 
|     if (!choice) return this.alert(); | 
|     let { cursor, input } = choice; | 
|     if (input[cursor] === void 0) return this.alert(); | 
|     let str = `${input}`.slice(0, cursor) + `${input}`.slice(cursor + 1); | 
|     choice.value = choice.input = str; | 
|     return this.render(); | 
|   } | 
|   | 
|   right() { | 
|     let choice = this.focused; | 
|     if (!choice) return this.alert(); | 
|     if (choice.cursor >= choice.input.length) return this.alert(); | 
|     choice.cursor++; | 
|     return this.render(); | 
|   } | 
|   | 
|   left() { | 
|     let choice = this.focused; | 
|     if (!choice) return this.alert(); | 
|     if (choice.cursor <= 0) return this.alert(); | 
|     choice.cursor--; | 
|     return this.render(); | 
|   } | 
|   | 
|   space(ch, key) { | 
|     return this.dispatch(ch, key); | 
|   } | 
|   | 
|   number(ch, key) { | 
|     return this.dispatch(ch, key); | 
|   } | 
|   | 
|   next() { | 
|     let ch = this.focused; | 
|     if (!ch) return this.alert(); | 
|     let { initial, input } = ch; | 
|     if (initial && initial.startsWith(input) && input !== initial) { | 
|       ch.value = ch.input = initial; | 
|       ch.cursor = ch.value.length; | 
|       return this.render(); | 
|     } | 
|     return super.next(); | 
|   } | 
|   | 
|   prev() { | 
|     let ch = this.focused; | 
|     if (!ch) return this.alert(); | 
|     if (ch.cursor === 0) return super.prev(); | 
|     ch.value = ch.input = ''; | 
|     ch.cursor = 0; | 
|     return this.render(); | 
|   } | 
|   | 
|   separator() { | 
|     return ''; | 
|   } | 
|   | 
|   format(value) { | 
|     return !this.state.submitted ? super.format(value) : ''; | 
|   } | 
|   | 
|   pointer() { | 
|     return ''; | 
|   } | 
|   | 
|   indicator(choice) { | 
|     return choice.input ? '⦿' : '⊙'; | 
|   } | 
|   | 
|   async choiceSeparator(choice, i) { | 
|     let sep = await this.resolve(choice.separator, this.state, choice, i) || ':'; | 
|     return sep ? ' ' + this.styles.disabled(sep) : ''; | 
|   } | 
|   | 
|   async renderChoice(choice, i) { | 
|     await this.onChoice(choice, i); | 
|   | 
|     let { state, styles } = this; | 
|     let { cursor, initial = '', name, hint, input = '' } = choice; | 
|     let { muted, submitted, primary, danger } = styles; | 
|   | 
|     let help = hint; | 
|     let focused = this.index === i; | 
|     let validate = choice.validate || (() => true); | 
|     let sep = await this.choiceSeparator(choice, i); | 
|     let msg = choice.message; | 
|   | 
|     if (this.align === 'right') msg = msg.padStart(this.longest + 1, ' '); | 
|     if (this.align === 'left') msg = msg.padEnd(this.longest + 1, ' '); | 
|   | 
|     // re-populate the form values (answers) object | 
|     let value = this.values[name] = (input || initial); | 
|     let color = input ? 'success' : 'dark'; | 
|   | 
|     if ((await validate.call(choice, value, this.state)) !== true) { | 
|       color = 'danger'; | 
|     } | 
|   | 
|     let style = styles[color]; | 
|     let indicator = style(await this.indicator(choice, i)) + (choice.pad || ''); | 
|   | 
|     let indent = this.indent(choice); | 
|     let line = () => [indent, indicator, msg + sep, input, help].filter(Boolean).join(' '); | 
|   | 
|     if (state.submitted) { | 
|       msg = colors.unstyle(msg); | 
|       input = submitted(input); | 
|       help = ''; | 
|       return line(); | 
|     } | 
|   | 
|     if (choice.format) { | 
|       input = await choice.format.call(this, input, choice, i); | 
|     } else { | 
|       let color = this.styles.muted; | 
|       let options = { input, initial, pos: cursor, showCursor: focused, color }; | 
|       input = placeholder(this, options); | 
|     } | 
|   | 
|     if (!this.isValue(input)) { | 
|       input = this.styles.muted(this.symbols.ellipsis); | 
|     } | 
|   | 
|     if (choice.result) { | 
|       this.values[name] = await choice.result.call(this, value, choice, i); | 
|     } | 
|   | 
|     if (focused) { | 
|       msg = primary(msg); | 
|     } | 
|   | 
|     if (choice.error) { | 
|       input += (input ? ' ' : '') + danger(choice.error.trim()); | 
|     } else if (choice.hint) { | 
|       input += (input ? ' ' : '') + muted(choice.hint.trim()); | 
|     } | 
|   | 
|     return line(); | 
|   } | 
|   | 
|   async submit() { | 
|     this.value = this.values; | 
|     return super.base.submit.call(this); | 
|   } | 
| } | 
|   | 
| module.exports = FormPrompt; |