@aplus-frontend/antdv
Version:
Vue basic component library maintained based on ant-design-vue
162 lines • 5.23 kB
JavaScript
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import { createVNode as _createVNode } from "vue";
import _extends from "@babel/runtime/helpers/esm/extends";
import { computed, defineComponent, ref, watchEffect } from 'vue';
import inputProps from '../inputProps';
import { FormItemInputContext } from '../../form/FormItemContext';
import useConfigInject from '../../config-provider/hooks/useConfigInject';
import classNames from '../../_util/classNames';
import useStyle from '../style/otp';
import OTPInput from './OTPInput';
import { getMergedStatus } from '../../_util/statusUtils';
import warning from '../../_util/warning';
export default defineComponent({
compatConfig: {
MODE: 3
},
name: 'AOTP',
inheritAttrs: false,
props: _extends(_extends({}, inputProps()), {
length: {
type: Number,
default: 6
},
onChange: {
type: Function,
default: undefined
},
onInput: {
type: Function,
default: undefined
},
formatter: {
type: Function,
default: undefined
},
defaultValue: {
type: String,
default: undefined
},
mask: {
type: [String, Boolean],
default: false
},
status: {
type: String,
default: undefined
}
}),
setup(props, _ref) {
let {
attrs
} = _ref;
const {
prefixCls,
direction,
size
} = useConfigInject('otp', props);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
// ==================== Provider =========================
const formItemInputContext = FormItemInputContext.useInject();
const mergedStatus = computed(() => getMergedStatus(formItemInputContext.status, props.status));
const refs = ref([]);
const strToArr = str => (str || '').split('');
// keep reactive
const internalFormatter = txt => props.formatter ? props.formatter(txt) : txt;
const valueCells = ref(strToArr(internalFormatter(props.defaultValue || '')));
watchEffect(() => {
if (typeof props.value !== 'undefined' && props.value !== null) {
valueCells.value = strToArr(String(props.value));
}
});
const patchValue = (index, txt) => {
let nextCells = valueCells.value.slice();
for (let i = 0; i < index; i += 1) {
if (!nextCells[i]) {
nextCells[i] = '';
}
}
if (txt.length <= 1) {
nextCells[index] = txt;
} else {
nextCells = nextCells.slice(0, index).concat(strToArr(txt));
}
nextCells = nextCells.slice(0, props.length);
for (let i = nextCells.length - 1; i >= 0; i -= 1) {
if (nextCells[i]) {
break;
}
nextCells.pop();
}
const formattedValue = internalFormatter(nextCells.map(c => c || ' ').join(''));
nextCells = strToArr(formattedValue).map((c, i) => {
if (c === ' ' && !nextCells[i]) {
return nextCells[i];
}
return c;
});
return nextCells;
};
// ======================= Change handlers =================
const onInputActiveChange = nextIndex => {
var _a;
(_a = refs.value[nextIndex]) === null || _a === void 0 ? void 0 : _a.focus();
};
const onInputChange = (index, value) => {
var _a;
const nextValueCells = patchValue(index, value);
const nextIndex = Math.min(index + value.length, props.length);
if (nextIndex !== index) {
(_a = refs.value[nextIndex]) === null || _a === void 0 ? void 0 : _a.focus();
}
if (props.onInput) {
props.onInput(nextValueCells);
}
if (props.onChange && nextValueCells.length === props.length && nextValueCells.every(v => v) && nextValueCells.some((v, i) => v !== valueCells.value[i])) {
props.onChange(nextValueCells.join(''));
}
valueCells.value = nextValueCells.slice();
};
return () => {
const cls = classNames(prefixCls.value, {
[`${prefixCls}-sm`]: size.value === 'small',
[`${prefixCls}-lg`]: size.value === 'large',
[`${prefixCls.value}-rtl`]: direction.value === 'rtl'
}, attrs.class, hashId.value);
const {
length,
autofocus,
disabled,
mask
} = props;
const inputShardProps = {
disabled,
mask
};
if (process.env.NODE_ENV !== 'production') {
warning(!(typeof mask === 'string' && mask.length > 1), 'Input.OTP', '`mask` prop should be a single character.');
}
return wrapSSR(_createVNode("div", {
"class": cls
}, [Array.from({
length
}).map((_, index) => {
const key = `opt-${index}`;
const singleValue = valueCells.value[index];
return _createVNode(OTPInput, _objectSpread({
"ref": ref => refs.value[index] = ref,
"key": key,
"index": index,
"class": `${prefixCls.value}-input`,
"value": singleValue,
"htmlSize": 1,
"onChange": onInputChange,
"status": mergedStatus.value,
"onActiveChange": onInputActiveChange,
"autofocus": index === 0 && autofocus
}, inputShardProps), null);
})]));
};
}
});