Source: xui/Prompt.js

/**
 * A prompt dialog box.
 * <p>Part of the XUI module which, for now, has an undocumented API.
 */
export class Prompt extends Dialog {
    static showPrompt(title, prompt,
                      columns=40, initialValue=null,
                      valueList=null, inputValueChecker=null, 
                      reference=null) {
        return new Promise((resolve, reject) => { 
            let dialog = new Prompt(title, prompt, columns, initialValue,
                                    valueList, inputValueChecker, resolve);
            dialog.open("center", reference);
        });
    }
    
    constructor(title, prompt, columns, initialValue,
                valueList, inputValueChecker, resolve) {
        super({ movable: true, title: title, closeable: true,
                template: Prompt.TEMPLATE,
                buttons: [ { label: "Cancel", action: "cancelAction" },
                           { label: "OK", action: "okAction",
                             default: true } ]});
        
        this._resolve = resolve;
        
        let pane = this.contentPane.firstElementChild;
        let icon = pane.firstElementChild;
        icon.textContent = StockIcon["question"];
        
        let form = pane.lastElementChild;
        let question = form.firstElementChild;
        if (prompt.startsWith("<html>")) {
            prompt = prompt.substring(6);
        } else {
            prompt = Util.escapeHTML(prompt);
            if (prompt.indexOf('\n') >= 0) {
                prompt = prompt.replaceAll('\n', "<br>");
            }
        }
        question.innerHTML = prompt;
            
        this._input = form.lastElementChild;
        if (columns < 10) {
            columns = 10;
        }
        this._input.size = columns;

        if (initialValue !== null) {
            this._input.value = initialValue;
            this.selectInputValue();
        }

        this._input.autocomplete = "off";
        if (valueList !== null && Array.isArray(valueList) &&
            valueList.length > 0) {
            let allValues = [];
            for (let value of valueList) {
                value = value.toString().trim();
                if (value.length > 0) {
                    allValues.push(value);
                }
            }

            if (allValues.length > 0) {
                // valueList is assumed to have been sorted by client code.
                // (This may be easily done using valueList.sort().)
                
                let datalistId = Util.uid();
                Util.appendDatalist(datalistId, allValues, form);
                this._input.setAttribute("list", datalistId);
            } 
        }
        
        this._checkInputValue = inputValueChecker;
        
        this._input.addEventListener("keydown", (e) => {
            if (e.key === "Enter") {
                Util.consumeEvent(e);
                
                this.okAction();
            }
        });
    }

    dialogClosed(result) {
        // Close button clicked ==> null result, which is just fine.
        this._resolve(result);
    }
    
    cancelAction() {
        this.close(null);
    }
    
    okAction() {
        let inputValue = this.getInputValue();
        if (this._checkInputValue !== null) {
            // checkInputValue may or may not accept null.
            if (!this._checkInputValue(inputValue)) {
                this.selectInputValue();
                return;
            }
        }
        
        this.close(inputValue);
    }

    // -----------------------------------
    // Validation helpers
    // -----------------------------------
    
    getInputValue() {
        let result = this._input.value;
        if (result !== null && (result = result.trim()).length === 0) {
            result = null;
        }
        return result;
    }

    selectInputValue() {
        this._input.focus();
        this._input.select();
    }
}

Prompt.TEMPLATE = document.createElement("template");
Prompt.TEMPLATE.innerHTML = `
<div class="xui-prompt-pane">
  <div class="xui-prompt-icon"></div>
  <div class="xui-prompt-form">
    <div class="xui-prompt-question"></div>
    <input class="xui-prompt-input" type="text" spellcheck="false" />
  </div>
</div>
`;