maz-ui
Version:
A standalone components library for Vue.Js 3 & Nuxt.Js 3
152 lines (151 loc) • 6.89 kB
JavaScript
import { defineComponent, ref, watch, computed, createElementBlock, openBlock, normalizeStyle, normalizeClass, createElementVNode, Fragment, renderList, mergeProps, toDisplayString } from "vue";
import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper.B--vMWp3.js";
import '../assets/MazInputCode.BYi64Mof.css';const _hoisted_1 = ["disabled"], _hoisted_2 = { class: "m-input-code__wrapper" }, _hoisted_3 = ["id", "name", "inputmode", "pattern", "required", "value", "onInput", "onKeydown", "onClick"], _sfc_main = /* @__PURE__ */ defineComponent({
inheritAttrs: !1,
__name: "MazInputCode",
props: {
style: { default: void 0 },
class: { default: void 0 },
modelValue: { default: void 0 },
codeLength: { default: 4 },
type: { default: "text" },
acceptAlpha: { type: Boolean, default: !1 },
required: { type: Boolean, default: !1 },
disabled: { type: Boolean, default: !1 },
error: { type: Boolean, default: !1 },
success: { type: Boolean, default: !1 },
warning: { type: Boolean, default: !1 },
size: { default: "md" },
color: { default: "primary" },
hint: {}
},
emits: ["update:model-value", "completed"],
setup(__props, { emit: __emit }) {
const props = __props, emits = __emit, inputList = ref([]), localMap = ref(/* @__PURE__ */ new Map());
watch(
() => props.modelValue,
(value, oldValue) => {
value !== oldValue && (localMap.value = getMapValues());
},
{ immediate: !0 }
);
const inputValues = computed({
get: () => localMap.value,
set: (value) => {
const emittedValue = getEmittedValue(value);
emits("update:model-value", emittedValue), emittedValue?.toString().length === props.codeLength && emits("completed");
}
});
function getMapValues(value = props.modelValue) {
const map = /* @__PURE__ */ new Map();
for (const item of Array.from({ length: props.codeLength }, (_, i) => i))
if (value === void 0)
map.set(item + 1, void 0);
else {
const values = [...value.toString()];
map.set(item + 1, values[item]);
}
return map;
}
function handleNewValue(event, item) {
const newValue = getValueSanitized(event.target?.value);
inputValues.value = localMap.value.set(item, newValue), newValue && focusAndSelectInputByIndex(item);
}
function getEmittedValue(map) {
const stringValue = [...map.values()].join("");
return props.type === "text" ? stringValue : stringValue && !Number.isNaN(Number(stringValue)) ? Number(stringValue) : void 0;
}
function getValueSanitized(value) {
return (props.acceptAlpha ? value.match(/^[\w.]$/) : value.match(/\d+/g))?.toString();
}
function handleKeydown(event, inputIndex) {
const currentInputValue = localMap.value.get(inputIndex);
if (event.key === "ArrowRight" && focusAndSelectInputByIndex(inputIndex), event.key === "ArrowLeft" && focusAndSelectInputByIndex(inputIndex - 2), event.key === "Backspace" && !currentInputValue) {
const previousInputIndexToFocus = inputIndex - 1 < 0 ? 0 : inputIndex - 1;
inputValues.value = localMap.value.set(previousInputIndexToFocus, void 0), focusAndSelectInputByIndex(previousInputIndexToFocus - 1);
}
}
function setValueOnPaste(event) {
const pasteData = event.clipboardData?.getData("text");
if (!pasteData)
return;
const indexInputsFromPastePlace = Array.from({ length: props.codeLength }, (_, i) => ({
index: i + 1,
value: [...pasteData.toString()][i] ?? void 0
}));
for (const { index, value } of indexInputsFromPastePlace) {
const sanitizedValue = value ? getValueSanitized(value) : void 0;
sanitizedValue && localMap.value.set(index, sanitizedValue);
}
setTimeout(() => {
const lastInputWithoutValueIndex = getLastInputWithoutValueIndex(), lastIndex = lastInputWithoutValueIndex >= props.codeLength ? props.codeLength - 1 : lastInputWithoutValueIndex;
focusAndSelectInputByIndex(lastIndex, !1);
}, 0);
}
function getLastInputWithoutValueIndex() {
return [...localMap.value.values()].filter(Boolean).length;
}
function focusAndSelectInputByIndex(index, selectValue = !0) {
setTimeout(() => {
const input = inputList.value[index];
index + 1 > props.codeLength || !input || (input.focus(), selectValue && selectInputByIndex(index));
}, 0);
}
function selectInputByIndex(index) {
const input = inputList.value[index];
index + 1 > props.codeLength || !input || input.select();
}
const borderColorState = computed(() => {
if (props.error)
return "!maz-border-destructive";
if (props.success)
return "!maz-border-success";
if (props.warning)
return "!maz-border-warning";
});
return (_ctx, _cache) => (openBlock(), createElementBlock("fieldset", {
class: normalizeClass(["m-input-code m-reset-css", [_ctx.size ? `--${_ctx.size}` : void 0, props.class]]),
disabled: _ctx.disabled,
style: normalizeStyle([_ctx.style, { "--input-border-color": `hsl(var(--maz-${props.color}))` }])
}, [
createElementVNode("div", _hoisted_2, [
(openBlock(!0), createElementBlock(Fragment, null, renderList(_ctx.codeLength, (item) => (openBlock(), createElementBlock("div", {
key: item,
class: normalizeClass(["input-wrapper", borderColorState.value])
}, [
createElementVNode("input", mergeProps({
id: `m-input-code-${item}`,
ref_for: !0,
ref: (el) => {
inputList.value[item - 1] = el;
},
type: "text",
name: `m-input-code-${item}`,
minlength: "1",
maxlength: "1",
inputmode: _ctx.acceptAlpha ? "text" : "numeric",
pattern: _ctx.acceptAlpha ? "[a-zA-Z0-9]{1}" : "[0-9]{1}",
autocomplete: "do-not-autofill",
required: _ctx.required
}, { ref_for: !0 }, _ctx.$attrs, {
value: inputValues.value.get(item),
onInput: ($event) => handleNewValue($event, item),
onKeydown: ($event) => handleKeydown($event, item),
onClick: ($event) => selectInputByIndex(item - 1),
onPaste: setValueOnPaste
}), null, 16, _hoisted_3)
], 2))), 128))
]),
createElementVNode("span", {
class: normalizeClass(["m-input-code__hint", {
"--error": _ctx.error,
"--success": _ctx.success,
"--warning": _ctx.warning
}])
}, toDisplayString(_ctx.hint), 3)
], 14, _hoisted_1));
}
}), MazInputCode = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-8599f1e6"]]);
export {
MazInputCode as default
};