@scania/tegel
Version:
Tegel Design System
754 lines (753 loc) • 30.4 kB
JavaScript
import { h } from "@stencil/core";
import hasSlot from "../../utils/hasSlot";
import generateUniqueId from "../../utils/generateUniqueId";
import { getAriaInvalid } from "../../utils/getAriaInvalid";
/**
* @slot prefix - Slot for the prefix in the component.
* @slot suffix - Slot for the suffix in the component. Suffix is hidden when the input is in readonly state.
*/
export class TdsTextField {
constructor() {
this.uuid = generateUniqueId();
/** Which input type, text, password or similar */
this.type = 'text';
/** Position of the label for the Text Field. */
this.labelPosition = 'no-label';
/** Label text */
this.label = '';
/** Placeholder text */
this.placeholder = '';
/** Value of the input text */
this.value = '';
/** Set input in disabled state */
this.disabled = false;
/** Set input in readonly state */
this.readOnly = false;
/** Hides the read-only icon in the Text Field. Requires Read Only to be enabled. */
this.hideReadOnlyIcon = false;
/** Size of the input */
this.size = 'lg';
/** Mode variant of the Text Field */
this.modeVariant = null;
/** Unset minimum width of 208px. */
this.noMinWidth = false;
/** Name property */
this.name = '';
/** Error state of input */
this.state = 'default';
/** Autofocus for input */
this.autofocus = false;
/** Makes the text field required */
this.required = false;
/** Value to be used for the text field's autocomplete attribute */
this.autocomplete = 'off';
/** Hides the native arrows on number input type */
this.hideNumberArrows = false;
/** Listen to the focus state of the input */
this.focusInput = false;
}
handleChange(event) {
this.tdsChange.emit(event);
}
/** Data input event in value prop */
handleInput(event) {
const inputEl = event.target;
const { value } = inputEl;
this.value = value;
this.tdsInput.emit(event);
}
/** Set the input as focus when clicking the whole Text Field with suffix/prefix */
handleFocus(event) {
var _a;
(_a = this.textInput) === null || _a === void 0 ? void 0 : _a.focus();
this.focusInput = true;
this.tdsFocus.emit(event);
}
/** Set the input as focus when clicking the whole Text Field with suffix/prefix */
handleBlur(event) {
this.focusInput = false;
/** Custom handling of number inputs when min/max are set */
if (this.type === 'number' && this.textInput) {
const numericValue = this.textInput.valueAsNumber;
const minNum = this.min !== undefined ? Number(this.min) : undefined;
const maxNum = this.max !== undefined ? Number(this.max) : undefined;
if (minNum !== undefined && maxNum !== undefined && minNum > maxNum) {
console.warn('tds-text-field: min value is greater than max value');
return;
}
if (!isNaN(numericValue)) {
const originalValue = this.textInput.value;
let clampedValue = originalValue;
let clampReason = null;
if (minNum !== undefined && numericValue < minNum) {
clampedValue = String(this.min);
clampReason = 'min';
}
if (maxNum !== undefined && numericValue > maxNum) {
clampedValue = String(this.max);
clampReason = 'max';
}
if (clampedValue !== originalValue && clampReason) {
this.textInput.value = clampedValue;
this.value = clampedValue;
this.tdsError.emit({
originalValue,
clampedValue,
reason: clampReason,
});
}
}
}
this.tdsBlur.emit(event);
}
/** Method to handle focus */
async focusElement() {
if (this.textInput) {
this.textInput.focus();
}
}
render() {
var _a, _b, _c, _d;
const usesPrefixSlot = hasSlot('prefix', this.host);
const usesSuffixSlot = hasSlot('suffix', this.host);
return (h("div", { key: 'f16b01caa6aab76ff91b1bbd339726bc091073b4', class: {
'form-text-field': true,
'form-text-field-nomin': this.noMinWidth,
'text-field-focus': this.focusInput && !this.disabled,
'text-field-data': this.value !== '' && this.value !== null,
'text-field-container-label-inside': this.labelPosition === 'inside' && this.size !== 'sm',
'form-text-field-disabled': this.disabled,
'form-text-field-readonly': this.disabled ? false : this.readOnly,
'tds-mode-variant-primary': this.readOnly
? this.modeVariant === 'secondary'
: this.modeVariant === 'primary',
'tds-mode-variant-secondary': this.readOnly
? this.modeVariant === 'primary'
: this.modeVariant === 'secondary',
'form-text-field-md': this.size === 'md',
'form-text-field-sm': this.size === 'sm',
'form-text-field-error': this.state === 'error',
'form-text-field-success': this.state === 'success',
} }, this.labelPosition === 'outside' && (h("div", { key: '05a6ee014f2d3e6e4394050423282d18cf5908b0', class: "text-field-label-outside" }, h("label", { key: 'cf3b333f2a898c048a1d456c6b7f6c65390615f0', htmlFor: `text-field-input-element-${this.uuid}` }, this.label))), h("div", { key: 'fc4a03cf20e81fa191ba536d2b79a0f1b0c535dd', onClick: () => { var _a; return (_a = this.textInput) === null || _a === void 0 ? void 0 : _a.focus(); }, class: "text-field-container" }, usesPrefixSlot && (h("div", { key: '3638c5a1acde4ad2eabc403d74a551d6185985a8', class: {
'text-field-slot-wrap-prefix': true,
'text-field-error': this.state === 'error',
'text-field-success': this.state === 'success',
'text-field-default': this.state === 'default',
} }, h("slot", { key: 'aa86f986720a076698b3193009eb8ebc5022e531', name: "prefix" }))), h("div", { key: '5b884728b755f3c604b233f706da028dc12ab0f8', class: "text-field-input-container" }, h("input", { key: 'a04b70515c8ea73d3435292249fb3aea9a43663a', ref: (inputEl) => {
this.textInput = inputEl;
}, class: {
'text-field-input': true,
'text-field-input-sm': this.size === 'sm',
'text-field-input-md': this.size === 'md',
'text-field-input-lg': this.size === 'lg',
'text-field-input-no-arrows': this.hideNumberArrows,
}, type: this.type, disabled: this.disabled, readonly: this.disabled ? false : this.readOnly, placeholder: this.placeholder, value: this.value, autofocus: this.autofocus, maxlength: this.maxLength, name: this.name, min: this.min, max: this.max, step: this.step, onInput: (event) => this.handleInput(event), onChange: (event) => this.handleChange(event), onFocus: (event) => {
if (!this.readOnly) {
this.handleFocus(event);
}
}, onBlur: (event) => {
if (!this.readOnly) {
this.handleBlur(event);
}
}, "aria-invalid": getAriaInvalid(this.host, this.state), "aria-label": this.tdsAriaLabel ? this.tdsAriaLabel : this.label, "aria-describedby": `text-field-helper-element-${this.uuid}`, "aria-readonly": this.readOnly, id: `text-field-input-element-${this.uuid}`, required: this.required, autocomplete: this.autocomplete }), this.labelPosition === 'inside' && this.size !== 'sm' && (h("label", { key: '2b4adf151e255ac983027b61b43f18e81399f11a', class: "text-field-label-inside", htmlFor: `text-field-input-element-${this.uuid}` }, this.label))), usesSuffixSlot && (h("div", { key: '70fccd2b3ffcab91b2537ef1512d2bbe86c4a1e5', class: {
'text-field-slot-wrap-suffix': true,
'text-field-error': this.state === 'error',
'text-field-success': this.state === 'success',
'text-field-default': this.state === 'default',
'tds-u-display-none': this.readOnly,
} }, h("slot", { key: '631a64c5239415bbf8449e90d046a3a2eb8fdf3c', name: "suffix" }))), this.readOnly && !this.hideReadOnlyIcon && (h("span", { key: '975a0d8877d271c45c6b5f210537b11b5b70004e', class: "text-field-icon__readonly" }, h("tds-tooltip", { key: 'e0aa565b62e640afcf13f270187269dbe79b9a48', placement: "top-end", text: "This field is non-editable", selector: "#readonly-tooltip" }), h("tds-icon", { key: '9dadaaa674e0ef4f47e24889ff9e418e7ff3a168', id: "readonly-tooltip", name: "edit_inactive", size: "20px" })))), h("div", { key: '787ae2f6f83ff667885adec7b30ac31c3d99a8e4', "aria-live": "assertive" }, (this.helper || ((_a = this.maxLength) !== null && _a !== void 0 ? _a : 0) > 0) && (h("div", { key: 'f655beff3ed7f0a3441c790fce325ce830770707', class: "text-field-helper", id: `text-field-helper-element-${this.uuid}` }, this.state === 'error' && (h("div", { key: '1e2ec411ebb607637b0584a54c1c19ff6d0e031e', class: "text-field-helper-error-state" }, !this.readOnly && h("tds-icon", { key: 'ce34402f70808ab965669863d46c9d84fb66609d', name: "error", size: "16px" }), this.helper)), this.state !== 'error' && this.helper, !this.readOnly && ((_b = this.maxLength) !== null && _b !== void 0 ? _b : 0) > 0 && (h("span", { key: '17945ce6d01531279d561fc2115cc8461b59b6ea', class: {
'text-field-textcounter-divider': true,
'text-field-textcounter-disabled': this.disabled,
} }, this.value === null ? 0 : (_c = this.value) === null || _c === void 0 ? void 0 : _c.length, " / ", (_d = this.maxLength) !== null && _d !== void 0 ? _d : 0)))))));
}
static get is() { return "tds-text-field"; }
static get encapsulation() { return "scoped"; }
static get originalStyleUrls() {
return {
"$": ["text-field.scss"]
};
}
static get styleUrls() {
return {
"$": ["text-field.css"]
};
}
static get properties() {
return {
"type": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'text' | 'password' | 'number' | 'email' | 'tel'",
"resolved": "\"email\" | \"number\" | \"password\" | \"tel\" | \"text\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Which input type, text, password or similar"
},
"getter": false,
"setter": false,
"reflect": true,
"attribute": "type",
"defaultValue": "'text'"
},
"labelPosition": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'inside' | 'outside' | 'no-label'",
"resolved": "\"inside\" | \"no-label\" | \"outside\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Position of the label for the Text Field."
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "label-position",
"defaultValue": "'no-label'"
},
"label": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Label text"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "label",
"defaultValue": "''"
},
"min": {
"type": "any",
"mutable": false,
"complexType": {
"original": "string | number",
"resolved": "number | string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Min allowed value for input type number"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "min"
},
"max": {
"type": "any",
"mutable": false,
"complexType": {
"original": "string | number",
"resolved": "number | string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Max allowed value for input type number"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "max"
},
"step": {
"type": "any",
"mutable": false,
"complexType": {
"original": "string | number",
"resolved": "number | string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Step value for input type number"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "step"
},
"helper": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Helper text"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "helper"
},
"placeholder": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Placeholder text"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "placeholder",
"defaultValue": "''"
},
"value": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Value of the input text"
},
"getter": false,
"setter": false,
"reflect": true,
"attribute": "value",
"defaultValue": "''"
},
"disabled": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Set input in disabled state"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "disabled",
"defaultValue": "false"
},
"readOnly": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Set input in readonly state"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "read-only",
"defaultValue": "false"
},
"hideReadOnlyIcon": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Hides the read-only icon in the Text Field. Requires Read Only to be enabled."
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "hide-read-only-icon",
"defaultValue": "false"
},
"size": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'sm' | 'md' | 'lg'",
"resolved": "\"lg\" | \"md\" | \"sm\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Size of the input"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "size",
"defaultValue": "'lg'"
},
"modeVariant": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'primary' | 'secondary' | null",
"resolved": "\"primary\" | \"secondary\" | null",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Mode variant of the Text Field"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "mode-variant",
"defaultValue": "null"
},
"noMinWidth": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Unset minimum width of 208px."
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "no-min-width",
"defaultValue": "false"
},
"name": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Name property"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "name",
"defaultValue": "''"
},
"state": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'error' | 'success' | 'default'",
"resolved": "\"default\" | \"error\" | \"success\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Error state of input"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "state",
"defaultValue": "'default'"
},
"maxLength": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Max length of input"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "max-length"
},
"autofocus": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Autofocus for input"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "autofocus",
"defaultValue": "false"
},
"tdsAriaLabel": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Value to be used for the aria-label attribute. Can be used for announcing that readOnly prop is set to true."
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "tds-aria-label"
},
"required": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Makes the text field required"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "required",
"defaultValue": "false"
},
"autocomplete": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Value to be used for the text field's autocomplete attribute"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "autocomplete",
"defaultValue": "'off'"
},
"hideNumberArrows": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Hides the native arrows on number input type"
},
"getter": false,
"setter": false,
"reflect": false,
"attribute": "hide-number-arrows",
"defaultValue": "false"
}
};
}
static get states() {
return {
"focusInput": {}
};
}
static get events() {
return [{
"method": "tdsChange",
"name": "tdsChange",
"bubbles": true,
"cancelable": false,
"composed": true,
"docs": {
"tags": [],
"text": "Change event for the Text Field"
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}, {
"method": "tdsInput",
"name": "tdsInput",
"bubbles": true,
"cancelable": false,
"composed": true,
"docs": {
"tags": [],
"text": "Input event for the Text Field"
},
"complexType": {
"original": "InputEvent",
"resolved": "InputEvent",
"references": {
"InputEvent": {
"location": "global",
"id": "global::InputEvent"
}
}
}
}, {
"method": "tdsFocus",
"name": "tdsFocus",
"bubbles": true,
"cancelable": false,
"composed": true,
"docs": {
"tags": [],
"text": "Focus event for the Text Field"
},
"complexType": {
"original": "FocusEvent",
"resolved": "FocusEvent",
"references": {
"FocusEvent": {
"location": "global",
"id": "global::FocusEvent"
}
}
}
}, {
"method": "tdsBlur",
"name": "tdsBlur",
"bubbles": true,
"cancelable": false,
"composed": true,
"docs": {
"tags": [],
"text": "Blur event for the Text Field"
},
"complexType": {
"original": "FocusEvent",
"resolved": "FocusEvent",
"references": {
"FocusEvent": {
"location": "global",
"id": "global::FocusEvent"
}
}
}
}, {
"method": "tdsError",
"name": "tdsError",
"bubbles": true,
"cancelable": false,
"composed": true,
"docs": {
"tags": [],
"text": "Error event for the Text Field - emitted when value is clamped to min/max"
},
"complexType": {
"original": "{ originalValue: string; clampedValue: string; reason: 'min' | 'max' }",
"resolved": "{ originalValue: string; clampedValue: string; reason: \"min\" | \"max\"; }",
"references": {}
}
}];
}
static get methods() {
return {
"focusElement": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "Method to handle focus",
"tags": []
}
}
};
}
static get elementRef() { return "host"; }
}