import { Component } from "./component.js";
import { Style } from "./style.js";
/**
* Creates a single line input field for entering text.
* <div><img src="https://www.minicomps.org/images/textinput.png"/></div>
* @example
* const panel = new Panel(document.body, 20, 20, 200, 200);
* new TextInput(panel, 20, 20, "Hello", event => console.log(event.target.text));
* @extends Component
*/
export class TextInput extends Component {
/**
* Constructor
* @param {HTMLElement} parent - The element to add this text input to.
* @param {number} x - The x position of the text input. Default 0.
* @param {number} y - The y position of the text input. Default 0.
* @param {string} text - The initial text to display in the text input. Default empty string.
* @param {function} defaultHandler - A function that will handle the "input" event.
*/
constructor(parent, x, y, text, defaultHandler) {
super(parent, x, y);
this._maxLength = 0;
this._text = text || "";
this._createStyle();
this._createChildren();
this._createListeners();
this.setSize(100, 20);
this.addEventListener("input", defaultHandler);
this._addToParent();
}
//////////////////////////////////
// Core
//////////////////////////////////
_createChildren() {
this._input = this._createInput(this.shadowRoot, "MinimalTextInput");
this._input.value = this._text;
}
_createStyle() {
const style = document.createElement("style");
style.textContent = Style.textinput;
this.shadowRoot.append(style);
}
_createListeners() {
this._onInput = this._onInput.bind(this);
this._input.addEventListener("input", this._onInput);
}
//////////////////////////////////
// Handlers
//////////////////////////////////
_onInput(event) {
event.stopPropagation();
this._text = this._input.value;
this.dispatchEvent(new CustomEvent("input", { detail: this._text }));
}
//////////////////////////////////
// Public
//////////////////////////////////
/**
* Adds a handler function for the "input" event on this component.
* @param {function} handler - A function that will handle the "input" event.
* @returns This instance, suitable for chaining.
*/
addHandler(handler) {
this.addEventListener("input", handler);
return this;
}
/**
* Automatically changes the value of a property on a target object with the main value of this component changes.
* @param {object} target - The target object to change.
* @param {string} prop - The string name of a property on the target object.
* @return This instance, suitable for chaining.
*/
bind(target, prop) {
this.addEventListener("input", event => {
target[prop] = event.detail;
});
return this;
}
/**
* @returns the maximum number of characters that can be entered in this text input.
*/
getMaxLength() {
return this._maxLength;
}
/**
* @returns the text in the input.
*/
getText() {
return this._text;
}
setEnabled(enabled) {
if (this._enabled === enabled) {
return this;
}
super.setEnabled(enabled);
this._input.disabled = !this._enabled;
if (this._enabled) {
this._input.addEventListener("input", this._onInput);
} else {
this._input.removeEventListener("input", this._onInput);
}
return this;
}
/**
* Sets the text of this text input.
* @param {string} text - The text of this text input.
* @returns This instance, suitable for chaining.
*/
setText(text) {
this._text = text;
this._input.value = text;
return this;
}
/**
* Sets the maximum number of characters in this text input.
* @param {number} maxLength - The max number of chars.
* @returns This instance, suitable for chaining.
*/
setMaxLength(maxLength) {
this._maxLength = maxLength;
this._input.maxLength = maxLength;
return this;
}
//////////////////////////////////
// Getters/Setters
// alphabetical. getter first.
//////////////////////////////////
/**
* Gets and sets the maximum length of the string that can be typed into the input.
*/
get maxLength() {
return this.getMaxLength();
}
set maxLength(maxLength) {
this.setMaxLength(maxLength);
}
/**
* Gets and sets the text in the input.
*/
get text() {
return this.getText();
}
set text(text) {
this.setText(text);
}
}
customElements.define("minimal-textinput", TextInput);