UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

462 lines (461 loc) 14.6 kB
import { VALIDATION_MESSAGE_TYPES as C, DESCRIPTION_SIZE_TYPES as b } from "../../common/constants/index.js"; import { INPUT_TYPES as o, DESCRIPTION_SIZE_CLASSES as I, LABEL_SIZE_CLASSES as _, INPUT_STATE_CLASSES as E, INPUT_SIZE_CLASSES as V, INPUT_SIZES as m, INPUT_ICON_SIZES as z } from "./input-constants.js"; import { addClassStyleAttrs as M, removeClassStyleAttrs as P, getValidationState as T, getUniqueString as A, hasSlotContent as w } from "../../common/utils/index.js"; import { MessagesMixin as N } from "../../common/mixins/input.js"; import { resolveComponent as x, createElementBlock as a, openBlock as n, mergeProps as h, createElementVNode as p, createVNode as B, renderSlot as c, createCommentVNode as g, normalizeClass as f, toDisplayString as S, createTextVNode as O, toHandlers as y } from "vue"; import { _ as D } from "../../_plugin-vue_export-helper-CHgC5LLL.js"; import q from "../validation-messages/validation-messages.js"; const k = { compatConfig: { MODE: 3 }, name: "DtInput", components: { DtValidationMessages: q }, mixins: [N], inheritAttrs: !1, props: { /** * Name property of the input element */ name: { type: String, default: "" }, /** * Type of the input. * When `textarea` a `<textarea>` element will be rendered instead of an `<input>` element. * @values text, password, email, number, textarea, date, time, file, tel, search * @default 'text' */ type: { type: String, default: o.TEXT, validator: (t) => Object.values(o).includes(t) }, /** * Value of the input */ modelValue: { type: [String, Number], default: "" }, /** * Disables the input * @values true, false */ disabled: { type: Boolean, default: !1 }, /** * Label for the input */ label: { type: String, default: "" }, /** * Determines visibility of input label. * @values true, false */ labelVisible: { type: Boolean, default: !0 }, /** * Description for the input */ description: { type: String, default: "" }, /** * Size of the input, one of `xs`, `sm`, `md`, `lg`, `xl` * @values xs, sm, md, lg, xl */ size: { type: String, default: "md", validator: (t) => Object.values(m).includes(t) }, /** * Additional class name for the input element. * Can accept String, Object, and Array, i.e. has the * same API as Vue's built-in handling of the class attribute. */ inputClass: { type: [String, Object, Array], default: "" }, /** * Additional class name for the input wrapper element. * Can accept all of String, Object, and Array, i.e. has the * same api as Vue's built-in handling of the class attribute. */ inputWrapperClass: { type: [String, Object, Array], default: "" }, /** * The current character length that the user has entered into the input. * This will only need to be used if you are using `validate.length` and * the string contains abnormal characters. * For example, an emoji could take up many characters in the input, but should only count as 1 character. * If no number is provided, a built-in length calculation will be used for the length validation. */ currentLength: { type: Number, default: null }, /** * Whether the input will continue to display a warning validation message even if the input has lost focus. */ retainWarning: { type: Boolean, default: !1 }, /** * Validation for the input. Supports maximum length validation with the structure: * `{ "length": {"description": string, "max": number, "warn": number, "message": string, * "limitMaxLength": boolean }}` */ validate: { type: Object, default: null }, /** * hidden allows to use input without the element visually present in DOM */ hidden: { type: Boolean, default: !1 } }, emits: [ /** * Native input event * * @event input * @type {String} */ "input", /** * Native input blur event * * @event blur * @type {FocusEvent} */ "blur", /** * Input clear event * * @event clear */ "clear", /** * Native input focus event * * @event focus * @type {FocusEvent} */ "focus", /** * Native input focusin event * * @event focusin * @type {FocusEvent} */ "focusin", /** * Native input focusout event * * @event focusout * @type {FocusEvent} */ "focusout", /** * Event fired to sync the modelValue prop with the parent component * @event update:modelValue */ "update:modelValue", /** * Length of the input when currentLength prop is not passed * * @event update:length * @type {Number} */ "update:length", /** * Result of the input validation * * @event update:invalid * @type {Boolean} */ "update:invalid" ], data() { return { isInputFocused: !1, isInvalid: !1, defaultLength: 0, hasSlotContent: w }; }, computed: { isTextarea() { return this.type === o.TEXTAREA; }, isDefaultSize() { return this.size === m.DEFAULT; }, iconSize() { return z[this.size]; }, isValidSize() { return Object.values(m).includes(this.size); }, isValidDescriptionSize() { return Object.values(b).includes(this.size); }, inputComponent() { return this.isTextarea ? "textarea" : "input"; }, inputListeners() { return { input: async (t) => { let s = t.target.value; this.type === o.FILE && (s = Array.from(t.target.files).map((r) => r.name)), this.$emit("input", s), this.$emit("update:modelValue", s); }, blur: (t) => { this.isInputFocused = !1, this.onBlur(t); }, focus: (t) => { this.isInputFocused = !0, this.$emit("focus", t); }, focusin: (t) => this.$emit("focusin", t), focusout: (t) => this.$emit("focusout", t) }; }, descriptionKey() { return `input-description-${A()}`; }, inputState() { return T(this.validationMessages); }, defaultLengthCalculation() { return this.calculateLength(this.modelValue); }, validationProps() { var t, s, i, r, u, e, d, l, v, L; return { length: { description: (s = (t = this == null ? void 0 : this.validate) == null ? void 0 : t.length) == null ? void 0 : s.description, max: (r = (i = this == null ? void 0 : this.validate) == null ? void 0 : i.length) == null ? void 0 : r.max, warn: (e = (u = this == null ? void 0 : this.validate) == null ? void 0 : u.length) == null ? void 0 : e.warn, message: (l = (d = this == null ? void 0 : this.validate) == null ? void 0 : d.length) == null ? void 0 : l.message, limitMaxLength: (L = (v = this == null ? void 0 : this.validate) == null ? void 0 : v.length) != null && L.limitMaxLength ? this.validate.length.limitMaxLength : !1 } }; }, validationMessages() { return this.showLengthLimitValidation ? this.formattedMessages.concat([this.inputLengthErrorMessage()]) : this.formattedMessages; }, showInputState() { return this.showMessages && this.inputState; }, inputLength() { return this.currentLength ? this.currentLength : this.defaultLengthCalculation; }, inputLengthState() { return this.inputLength < this.validationProps.length.warn ? null : this.inputLength <= this.validationProps.length.max ? this.validationProps.length.warn ? C.WARNING : null : C.ERROR; }, shouldValidateLength() { return !!(this.validationProps.length.description && this.validationProps.length.max); }, shouldLimitMaxLength() { return this.shouldValidateLength && this.validationProps.length.limitMaxLength; }, // eslint-disable-next-line complexity showLengthLimitValidation() { return this.shouldValidateLength && this.inputLengthState !== null && this.validationProps.length.message && (this.retainWarning || this.isInputFocused || this.isInvalid); }, sizeModifierClass() { return this.isDefaultSize || !this.isValidSize ? "" : V[this.inputComponent][this.size]; }, stateClass() { return [E[this.inputState]]; } }, watch: { isInvalid(t) { this.$emit("update:invalid", t); }, modelValue: { immediate: !0, handler(t) { this.shouldValidateLength && this.validateLength(this.inputLength), this.currentLength == null && this.$emit("update:length", this.calculateLength(t)); } } }, beforeMount() { this.descriptionSizeClasses = I, this.labelSizeClasses = _; }, methods: { removeClassStyleAttrs: P, addClassStyleAttrs: M, inputClasses() { return [ "d-input__input", this.inputComponent === "input" ? "d-input" : "d-textarea", { [this.stateClass]: this.showInputState, "d-input-icon--left": this.$slots.leftIcon, "d-input-icon--right": this.$slots.rightIcon }, this.sizeModifierClass, this.inputClass ]; }, inputWrapperClasses() { return this.hidden ? [] : [ "d-input__wrapper", { [this.stateClass]: this.showInputState }, this.inputWrapperClass ]; }, calculateLength(t) { return typeof t != "string" ? 0 : [...t].length; }, inputLengthErrorMessage() { return { message: this.validationProps.length.message, type: this.inputLengthState }; }, onBlur(t) { var s; (s = this.$refs.container) != null && s.contains(t.relatedTarget) || this.$emit("blur", t); }, emitClearEvents() { this.$emit("input", ""), this.$emit("clear"), this.$emit("update:modelValue", ""); }, blur() { this.$refs.input.blur(); }, focus() { this.$refs.input.focus(); }, select() { this.$refs.input.select(); }, getMessageKey(t, s) { return `message-${t}-${s}`; }, validateLength(t) { this.isInvalid = t > this.validationProps.length.max; }, clearInput() { this.$refs.input.value = "", this.$refs.input.focus(), this.emitClearEvents(); } } }, F = ["aria-details"], j = ["id"], R = { key: 0 }, U = { key: 1, "data-qa": "dt-input-length-description", class: "d-input__length-description" }, W = ["read-only"], Z = ["value", "name", "disabled", "autocomplete", "maxlength"], K = ["value", "name", "type", "disabled", "autocomplete", "maxlength"]; function Y(t, s, i, r, u, e) { const d = x("dt-validation-messages"); return n(), a("div", h({ ref: "container", class: ["d-input__root", { "d-input--hidden": i.hidden }] }, e.addClassStyleAttrs(t.$attrs), { "data-qa": "dt-input" }), [ p("label", { class: "d-input__label", "aria-details": t.$slots.description || i.description ? e.descriptionKey : void 0, "data-qa": "dt-input-label-wrapper" }, [ c(t.$slots, "labelSlot", {}, () => [ i.labelVisible && i.label ? (n(), a("div", { key: 0, ref: "label", "data-qa": "dt-input-label", class: f([ "d-input__label-text", "d-label", t.labelSizeClasses[i.size] ]) }, S(i.label), 3)) : g("", !0) ]), u.hasSlotContent(t.$slots.description) || i.description || e.shouldValidateLength ? (n(), a("div", { key: 0, id: e.descriptionKey, ref: "description", class: f([ "d-input__description", "d-description", t.descriptionSizeClasses[i.size] ]), "data-qa": "dt-input-description" }, [ u.hasSlotContent(t.$slots.description) || i.description ? (n(), a("div", R, [ c(t.$slots, "description", {}, () => [ O(S(i.description), 1) ]) ])) : g("", !0), e.shouldValidateLength ? (n(), a("div", U, S(e.validationProps.length.description), 1)) : g("", !0) ], 10, j)) : g("", !0), p("div", { class: f(e.inputWrapperClasses()), "read-only": i.disabled === !0 ? !0 : void 0 }, [ p("span", { class: "d-input-icon d-input-icon--left", "data-qa": "dt-input-left-icon-wrapper", onFocusout: s[0] || (s[0] = (...l) => e.onBlur && e.onBlur(...l)) }, [ c(t.$slots, "leftIcon", { iconSize: e.iconSize }) ], 32), e.isTextarea ? (n(), a("textarea", h({ key: 0, ref: "input", value: i.modelValue, name: i.name, disabled: i.disabled, autocomplete: t.$attrs.autocomplete ?? "off", class: e.inputClasses(), maxlength: e.shouldLimitMaxLength ? e.validationProps.length.max : null, "data-qa": "dt-input-input" }, e.removeClassStyleAttrs(t.$attrs), y(e.inputListeners, !0)), null, 16, Z)) : (n(), a("input", h({ key: 1, ref: "input", value: i.modelValue, name: i.name, type: i.type, disabled: i.disabled, autocomplete: t.$attrs.autocomplete ?? "off", class: e.inputClasses(), maxlength: e.shouldLimitMaxLength ? e.validationProps.length.max : null, "data-qa": "dt-input-input" }, e.removeClassStyleAttrs(t.$attrs), y(e.inputListeners, !0)), null, 16, K)), p("span", { class: "d-input-icon d-input-icon--right", "data-qa": "dt-input-right-icon-wrapper", onFocusout: s[1] || (s[1] = (...l) => e.onBlur && e.onBlur(...l)) }, [ c(t.$slots, "rightIcon", { iconSize: e.iconSize, clear: e.clearInput }) ], 32) ], 10, W) ], 8, F), B(d, h({ "validation-messages": e.validationMessages, "show-messages": t.showMessages, class: t.messagesClass }, t.messagesChildProps, { "data-qa": "dt-input-messages" }), null, 16, ["validation-messages", "show-messages", "class"]) ], 16); } const et = /* @__PURE__ */ D(k, [["render", Y]]); export { et as default }; //# sourceMappingURL=input.js.map