From d90edb1126e2f1384259705907a9aaadfb716bb9 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Sun, 5 May 2024 16:17:34 +0800 Subject: [PATCH 01/12] feat(ui/otpInput): add OTP input component --- packages/varlet-ui/src/otp-input/OtpInput.vue | 235 ++++++++++++++++++ .../varlet-ui/src/otp-input/docs/en-US.md | 127 ++++++++++ .../varlet-ui/src/otp-input/docs/zh-CN.md | 127 ++++++++++ .../varlet-ui/src/otp-input/example/index.vue | 39 +++ .../src/otp-input/example/locale/en-US.ts | 9 + .../src/otp-input/example/locale/index.ts | 17 ++ .../src/otp-input/example/locale/zh-CN.ts | 9 + packages/varlet-ui/src/otp-input/index.ts | 12 + .../varlet-ui/src/otp-input/otpInput.less | 16 ++ packages/varlet-ui/src/otp-input/props.ts | 41 +++ packages/varlet-ui/src/otp-input/provide.ts | 3 + packages/varlet-ui/src/utils/elements.ts | 39 +++ packages/varlet-ui/types/otpInput.d.ts | 45 ++++ packages/varlet-ui/varlet.config.mjs | 8 + 14 files changed, 727 insertions(+) create mode 100644 packages/varlet-ui/src/otp-input/OtpInput.vue create mode 100644 packages/varlet-ui/src/otp-input/docs/en-US.md create mode 100644 packages/varlet-ui/src/otp-input/docs/zh-CN.md create mode 100644 packages/varlet-ui/src/otp-input/example/index.vue create mode 100644 packages/varlet-ui/src/otp-input/example/locale/en-US.ts create mode 100644 packages/varlet-ui/src/otp-input/example/locale/index.ts create mode 100644 packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts create mode 100644 packages/varlet-ui/src/otp-input/index.ts create mode 100644 packages/varlet-ui/src/otp-input/otpInput.less create mode 100644 packages/varlet-ui/src/otp-input/props.ts create mode 100644 packages/varlet-ui/src/otp-input/provide.ts create mode 100644 packages/varlet-ui/types/otpInput.d.ts diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue new file mode 100644 index 00000000000..0287b02f587 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -0,0 +1,235 @@ + + + + + diff --git a/packages/varlet-ui/src/otp-input/docs/en-US.md b/packages/varlet-ui/src/otp-input/docs/en-US.md new file mode 100644 index 00000000000..ea8864804bd --- /dev/null +++ b/packages/varlet-ui/src/otp-input/docs/en-US.md @@ -0,0 +1,127 @@ +# Input + +### Intro + +The OTP input is used to authenticate users with a one-time password. + +### Standard Usage + +```html + + + +``` + +### Readonly + +```html + + + +``` + +### Disabled + +```html + + + +``` + +### Validate + +```html + + + +``` + +### Smaller size + +```html + + + +``` + +### Variant Appearance + +```html + + + +``` + +## API + +### Props + +| Prop | Description | Type | Default | +| --- |----------------------------------------------------------------------------------------------------------------------------------------| --- | --- | +| `v-model` | The value of the binding | _string\|number_ | `-` | +| `size` | Input size, The optional value is `normal` `small` | _string_ | `normal` | +| `variant` | Whether to use variant appearance | _boolean_ | `false` | +| `text-color` | Text color | _string_ | `-` | +| `focus-color` | The primary color in focus | _string_ | `-` | +| `blur-color` | The primary color in blur | _string_ | `-` | +| `readonly` | Whether the readonly | _boolean_ | `false` | +| `disabled` | Whether the disabled | _boolean_ | `false` | +| `autofocus` | Whether the autofocus the first input component | _boolean_ | `false` | +| `validate-trigger` | Timing to trigger validation, The optional value is `onFocus` `onBlur` `onChange` `onClick` `onInput` | _ValidateTriggers[]_ | `['onInput']` | +| `rules` | The validation rules, return `true` to indicate that the validation passed,The remaining values are converted to text as user prompts | _Array<(v: string) => any>_ | `-` | + +### Methods + +| Method | Description | Arguments | Return | +| --- | --- | --- | --- | +| `focus` | Focus | `-` | `-` | +| `blur` | Blur | `-` | `-` | +| `validate` | Trigger validate | `-` | `valid: Promise` | +| `resetValidation` | Clear validate messages | `-` | `-` | +| `reset` | Clear the value of the binding and validate messages | `-` | `-` | + +### Events + +| Event | Description | Arguments | +| --- | --- | --- | +| `focus` | Triggered while focusing | `event: Event` | +| `blur` | Triggered when out of focus | `event: Event` | +| `click` | Triggered on Click | `event: Event` | +| `input` | Triggered on input | `value: string`, `event: Event` | +| `change` | Triggered on change | `value: string`, `event: Event` | diff --git a/packages/varlet-ui/src/otp-input/docs/zh-CN.md b/packages/varlet-ui/src/otp-input/docs/zh-CN.md new file mode 100644 index 00000000000..d39bcf750f6 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/docs/zh-CN.md @@ -0,0 +1,127 @@ +# 验证码输入框 + +### 介绍 + +验证码输入框,用于通过一次性密码对用户进行认证。 + +### 基本使用 + +```html + + + +``` + +### 只读状态 + +```html + + + +``` + +### 禁用状态 + +```html + + + +``` + +### 字段校验 + +```html + + + +``` + +### 小尺寸外观 + +```html + + + +``` + +### 变体外观 + +```html + + + +``` + +## API + +### 属性 + +| 参数 | 说明 | 类型 | 默认值 | +| --- |--------------------------------------------------------------------------| --- | --- | +| `v-model` | 绑定的值 | _string\|number_ | `-` | +| `size` | 输入框尺寸,可选值 `normal` `small` | _string_ | `normal` | +| `variant` | 是否采用变体外观 | _boolean_ | `false` | +| `text-color` | 文字颜色 | _string_ | `-` | +| `focus-color` | 聚焦时的主要颜色 | _string_ | `-` | +| `blur-color` | 失焦时的主要颜色 | _string_ | `-` | +| `readonly` | 是否只读 | _boolean_ | `false` | +| `disabled` | 是否禁用 | _boolean_ | `false` | +| `autofocus` | 是否自动聚焦第一个输入框 | _boolean_ | `false` | +| `validate-trigger` | 触发验证的时机,可选值为 `onFocus` `onBlur` `onChange` `onClick` `onInput` | _ValidateTriggers[]_ | `['onInput']` | +| `rules` | 验证规则,返回 `true` 表示验证通过,其余的值则转换为文本作为用户提示 | _Array<(v: string) => any>_ | `-` | + +### 方法 + +| 方法名 | 说明 | 参数 | 返回值 | +| --- | --- | --- | --- | +| `focus` | 聚焦 | `-` | `-` | +| `blur` | 失焦 | `-` | `-` | +| `validate` | 触发校验 | `-` | `valid: Promise` | +| `resetValidation` | 清空校验信息 | `-` | `-` | +| `reset` | 清空绑定的值和校验信息 | `-` | `-` | + +### 事件 + +| 事件名 | 说明 | 参数 | +| --- | --- | --- | +| `focus` | 聚焦时触发 | `index: Number` | +| `blur` | 失焦时触发 | `index: Number` | +| `click` | 点击时触发 | `index: Number` | +| `input` | 输入时触发 | `value: string` | +| `change` | 更新时触发 | `value: string` | diff --git a/packages/varlet-ui/src/otp-input/example/index.vue b/packages/varlet-ui/src/otp-input/example/index.vue new file mode 100644 index 00000000000..c134468c81e --- /dev/null +++ b/packages/varlet-ui/src/otp-input/example/index.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/packages/varlet-ui/src/otp-input/example/locale/en-US.ts b/packages/varlet-ui/src/otp-input/example/locale/en-US.ts new file mode 100644 index 00000000000..14d528d29d9 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/example/locale/en-US.ts @@ -0,0 +1,9 @@ +export default { + errorMessage: 'Must enter a 6-digit verification code.', + variant: 'Variant Appearance', + standard: 'Standard Variant', + smallSize: 'Small Size', + disabled: 'Disabled', + readonly: 'Readonly', + validate: 'Validate', +} diff --git a/packages/varlet-ui/src/otp-input/example/locale/index.ts b/packages/varlet-ui/src/otp-input/example/locale/index.ts new file mode 100644 index 00000000000..8855457aa5c --- /dev/null +++ b/packages/varlet-ui/src/otp-input/example/locale/index.ts @@ -0,0 +1,17 @@ +import { Locale } from '@varlet/ui' +import zhCN from './zh-CN' +import enUS from './en-US' + +const { add, use: exampleUse, t, merge } = Locale.useLocale() + +const use = (lang: string) => { + Locale.use(lang) + exampleUse(lang) +} + +Locale.add('zh-CN', Locale.zhCN) +Locale.add('en-US', Locale.enUS) +add('zh-CN', zhCN) +add('en-US', enUS) + +export { add, t, merge, use } diff --git a/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts b/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts new file mode 100644 index 00000000000..25b81c6d3d2 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts @@ -0,0 +1,9 @@ +export default { + errorMessage: '必须输入6位验证码', + variant: '变体外观', + standard: '标准外观', + smallSize: '小尺寸', + disabled: '禁用', + readonly: '只读', + validate: '字段校验', +} diff --git a/packages/varlet-ui/src/otp-input/index.ts b/packages/varlet-ui/src/otp-input/index.ts new file mode 100644 index 00000000000..63a4dcf8604 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/index.ts @@ -0,0 +1,12 @@ +import OtpInput from './OtpInput.vue' +import { withInstall, withPropsDefaultsSetter } from '../utils/components' +import { props as otpInputProps } from './props' + +withInstall(OtpInput) +withPropsDefaultsSetter(OtpInput, otpInputProps) + +export { otpInputProps } + +export const _OtpInputComponent = OtpInput + +export default OtpInput diff --git a/packages/varlet-ui/src/otp-input/otpInput.less b/packages/varlet-ui/src/otp-input/otpInput.less new file mode 100644 index 00000000000..27c991c1f54 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/otpInput.less @@ -0,0 +1,16 @@ +.var-otp-input { + &__container { + display: flex; + .var-input { + .var-form-details { + display: none; + } + &__input { + text-align: center; + } + } + .var-input + .var-input { + margin-left: 8px; + } + } +} diff --git a/packages/varlet-ui/src/otp-input/props.ts b/packages/varlet-ui/src/otp-input/props.ts new file mode 100644 index 00000000000..94b4e694009 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/props.ts @@ -0,0 +1,41 @@ +import { type PropType } from 'vue' +import { defineListenerProp, pickProps } from '../utils/components' +import { inputProps } from '../input' + +export type OptInputValidateTrigger = 'onFocus' | 'onBlur' | 'onChange' | 'onClick' | 'onInput' + +export const props = { + modelValue: { + type: [Number, String], + default: undefined, + }, + length: { + type: Number, + default: 6, + }, + validateTrigger: { + type: Array as PropType, + default: () => ['onInput'], + }, + variant: { + type: Boolean, + default: false, + }, + rules: Array as PropType any>>, + onFocus: defineListenerProp<(i: number) => void>(), + onBlur: defineListenerProp<(i: number) => void>(), + onClick: defineListenerProp<(i: number) => void>(), + onInput: defineListenerProp<(value: string) => void>(), + onChange: defineListenerProp<(value: string) => void>(), + 'onUpdate:modelValue': defineListenerProp<(value: string) => void>(), + ...pickProps(inputProps, [ + 'size', + 'readonly', + 'autofocus', + 'disabled', + 'readonly', + 'textColor', + 'focusColor', + 'blurColor', + ]), +} diff --git a/packages/varlet-ui/src/otp-input/provide.ts b/packages/varlet-ui/src/otp-input/provide.ts new file mode 100644 index 00000000000..7b1472f08df --- /dev/null +++ b/packages/varlet-ui/src/otp-input/provide.ts @@ -0,0 +1,3 @@ +import { Validation } from '../form/provide' + +export type OtpInputProvider = Validation diff --git a/packages/varlet-ui/src/utils/elements.ts b/packages/varlet-ui/src/utils/elements.ts index 65fcb570c95..9d0b1ccdc7f 100644 --- a/packages/varlet-ui/src/utils/elements.ts +++ b/packages/varlet-ui/src/utils/elements.ts @@ -293,3 +293,42 @@ export function focusChildElementByKey( } } } + +function focusableChildren(el: Element, filterByTabIndex = true) { + const targets = ['button', '[href]', 'input:not([type="hidden"])', 'select', 'textarea', '[tabindex]'] + .map((s) => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled])`) + .join(', ') + + return Array.from(el.querySelectorAll(targets)) as HTMLElement[] +} + +function getNextElement(elements: HTMLElement[], location?: 'next' | 'prev', condition?: (el: HTMLElement) => boolean) { + let _el + let idx = elements.indexOf(document.activeElement as HTMLElement) + const inc = location === 'next' ? 1 : -1 + do { + idx += inc + _el = elements[idx] + } while ((!_el || _el.offsetParent == null || !(condition?.(_el) ?? true)) && idx < elements.length && idx >= 0) + return _el +} + +export function focusChild(el: Element, location?: 'next' | 'prev' | 'first' | 'last' | number) { + const focusable = focusableChildren(el) + + if (!location) { + if (el === document.activeElement || !el.contains(document.activeElement)) { + focusable[0]?.focus() + } + } else if (location === 'first') { + focusable[0]?.focus() + } else if (location === 'last') { + focusable.at(-1)?.focus() + } else if (typeof location === 'number') { + focusable[location]?.focus() + } else { + const _el = getNextElement(focusable, location) + if (_el) _el.focus() + else focusChild(el, location === 'next' ? 'first' : 'last') + } +} diff --git a/packages/varlet-ui/types/otpInput.d.ts b/packages/varlet-ui/types/otpInput.d.ts new file mode 100644 index 00000000000..9ada3f10334 --- /dev/null +++ b/packages/varlet-ui/types/otpInput.d.ts @@ -0,0 +1,45 @@ +import { VarComponent, BasicAttributes, ListenerProp, SetPropsDefaults } from './varComponent' +import { InputSize } from './input' + +export declare const inputProps: Record + +export type OptInputValidateTrigger = 'onFocus' | 'onBlur' | 'onChange' | 'onClick' | 'onInput' + +export interface OtpInputProps extends BasicAttributes { + modelValue?: string | number + size?: InputSize + length?: number + variant?: boolean + textColor?: string + focusColor?: string + blurColor?: string + disabled?: boolean + readonly?: boolean + autofocus?: boolean + validateTrigger?: OptInputValidateTrigger[] + rules?: Array<(v: string) => any> + onFocus?: ListenerProp<(e: Event) => void> + onBlur?: ListenerProp<(e: Event) => void> + onClick?: ListenerProp<(e: Event) => void> + onInput?: ListenerProp<(value: string, e: Event) => void> + onChange?: ListenerProp<(value: string, e: Event) => void> + 'onUpdate:modelValue'?: ListenerProp<(value: string) => void> +} + +export class OtpInput extends VarComponent { + static setPropsDefaults: SetPropsDefaults + + $props: OtpInputProps + + focus(): void + + blur(): void + + validate(): Promise + + resetValidation(): void + + reset(): void +} + +export class _OtpInputComponent extends OtpInput {} diff --git a/packages/varlet-ui/varlet.config.mjs b/packages/varlet-ui/varlet.config.mjs index 3799744e687..044f6116e58 100644 --- a/packages/varlet-ui/varlet.config.mjs +++ b/packages/varlet-ui/varlet.config.mjs @@ -630,6 +630,14 @@ export default defineConfig({ doc: 'input', type: 2, }, + { + text: { + 'zh-CN': 'OtpInput 验证码输入框', + 'en-US': 'OtpInput', + }, + doc: 'otp-input', + type: 2, + }, { text: { 'zh-CN': 'Select 选择框', From bc05023e87ec2cbd4e935e87ca83fd2421fd3b63 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Mon, 6 May 2024 10:11:41 +0800 Subject: [PATCH 02/12] feat(ui/otpInput): add OTP input component --- packages/varlet-ui/src/otp-input/OtpInput.vue | 40 +++++++++++-------- .../varlet-ui/src/otp-input/docs/en-US.md | 2 +- .../varlet-ui/src/otp-input/docs/zh-CN.md | 2 +- .../varlet-ui/src/otp-input/example/index.vue | 12 +++--- .../src/otp-input/example/locale/en-US.ts | 3 +- .../src/otp-input/example/locale/zh-CN.ts | 3 +- packages/varlet-ui/src/otp-input/props.ts | 5 +-- packages/varlet-ui/src/utils/elements.ts | 39 ------------------ 8 files changed, 36 insertions(+), 70 deletions(-) diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue index 0287b02f587..9a2f44baefb 100644 --- a/packages/varlet-ui/src/otp-input/OtpInput.vue +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -2,20 +2,20 @@
import VarInput from '../input' +import VarFormDetails from '../form-details' import { defineComponent, ref, computed, nextTick, watch } from 'vue' import { props, type OptInputValidateTrigger } from './props' import { call, preventDefault, raf } from '@varlet/shared' import { useValidation, createNamespace } from '../utils/components' import { useForm } from '../form/provide' -import { focusChild } from '../utils/elements' import { type OtpInputProvider } from './provide' const { name, n, classes } = createNamespace('otp-input') @@ -49,6 +49,7 @@ export default defineComponent({ name, components: { VarInput, + VarFormDetails, }, props, setup(props) { @@ -113,6 +114,14 @@ export default defineComponent({ }) } + function focusInput(target: number | 'next' | 'prev') { + const newIndex = target === 'next' ? focusIndex.value + 1 : target === 'prev' ? focusIndex.value - 1 : target + if (inputRefs.value && inputRefs.value[newIndex]) { + focusIndex.value = newIndex + inputRefs.value[newIndex].focus() + } + } + function handleFocus(index: number) { focusIndex.value = index valueWhenFocus.value = model.value[index] @@ -138,7 +147,7 @@ export default defineComponent({ call(props.onInput, model.value.join('')) if (target) { - focusChild(contentRef.value!, target) + focusInput(target) } validateWithTrigger('onInput') } @@ -171,7 +180,7 @@ export default defineComponent({ if (!target) return await raf() - focusChild(contentRef.value!, target) + focusInput(target) } function handleClick(index: number) { @@ -205,9 +214,6 @@ export default defineComponent({ model, contentRef, inputRefs, - formDisabled: form?.disabled, - formReadonly: form?.readonly, - length, errorMessage, focusIndex, variant: props.variant, diff --git a/packages/varlet-ui/src/otp-input/docs/en-US.md b/packages/varlet-ui/src/otp-input/docs/en-US.md index ea8864804bd..3d838a226e3 100644 --- a/packages/varlet-ui/src/otp-input/docs/en-US.md +++ b/packages/varlet-ui/src/otp-input/docs/en-US.md @@ -96,7 +96,7 @@ const value = ref('') | --- |----------------------------------------------------------------------------------------------------------------------------------------| --- | --- | | `v-model` | The value of the binding | _string\|number_ | `-` | | `size` | Input size, The optional value is `normal` `small` | _string_ | `normal` | -| `variant` | Whether to use variant appearance | _boolean_ | `false` | +| `variant` | Input variants, The optional value is `standard` `outlined` | _string_ | `standard` | | `text-color` | Text color | _string_ | `-` | | `focus-color` | The primary color in focus | _string_ | `-` | | `blur-color` | The primary color in blur | _string_ | `-` | diff --git a/packages/varlet-ui/src/otp-input/docs/zh-CN.md b/packages/varlet-ui/src/otp-input/docs/zh-CN.md index d39bcf750f6..ea1672c8aa4 100644 --- a/packages/varlet-ui/src/otp-input/docs/zh-CN.md +++ b/packages/varlet-ui/src/otp-input/docs/zh-CN.md @@ -96,7 +96,7 @@ const value = ref('') | --- |--------------------------------------------------------------------------| --- | --- | | `v-model` | 绑定的值 | _string\|number_ | `-` | | `size` | 输入框尺寸,可选值 `normal` `small` | _string_ | `normal` | -| `variant` | 是否采用变体外观 | _boolean_ | `false` | +| `variant` | 输入框风格, 可选值为 `standard` `outlined` | _string_ | `standard` | | `text-color` | 文字颜色 | _string_ | `-` | | `focus-color` | 聚焦时的主要颜色 | _string_ | `-` | | `blur-color` | 失焦时的主要颜色 | _string_ | `-` | diff --git a/packages/varlet-ui/src/otp-input/example/index.vue b/packages/varlet-ui/src/otp-input/example/index.vue index c134468c81e..980288f649a 100644 --- a/packages/varlet-ui/src/otp-input/example/index.vue +++ b/packages/varlet-ui/src/otp-input/example/index.vue @@ -7,15 +7,15 @@ const standardValue = ref('') const standardValue2 = ref('123') const standardValue3 = ref('123') const standardValue4 = ref('') -const standardValue5 = ref('') const variantValue = ref('') +const variantValue2 = ref('') watchLang(use) onThemeChange() diff --git a/packages/varlet-ui/src/otp-input/example/locale/en-US.ts b/packages/varlet-ui/src/otp-input/example/locale/en-US.ts index 14d528d29d9..96f4bb6c0e0 100644 --- a/packages/varlet-ui/src/otp-input/example/locale/en-US.ts +++ b/packages/varlet-ui/src/otp-input/example/locale/en-US.ts @@ -1,8 +1,9 @@ export default { + basicUsage: 'Basic Usage', errorMessage: 'Must enter a 6-digit verification code.', variant: 'Variant Appearance', standard: 'Standard Variant', - smallSize: 'Small Size', + smallSize: 'Small Size Variant Appearance', disabled: 'Disabled', readonly: 'Readonly', validate: 'Validate', diff --git a/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts b/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts index 25b81c6d3d2..0b02ec37846 100644 --- a/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts +++ b/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts @@ -1,8 +1,9 @@ export default { + basicUsage: '基本使用', errorMessage: '必须输入6位验证码', variant: '变体外观', standard: '标准外观', - smallSize: '小尺寸', + smallSize: '小尺寸变体外观', disabled: '禁用', readonly: '只读', validate: '字段校验', diff --git a/packages/varlet-ui/src/otp-input/props.ts b/packages/varlet-ui/src/otp-input/props.ts index 94b4e694009..2a993132160 100644 --- a/packages/varlet-ui/src/otp-input/props.ts +++ b/packages/varlet-ui/src/otp-input/props.ts @@ -17,10 +17,6 @@ export const props = { type: Array as PropType, default: () => ['onInput'], }, - variant: { - type: Boolean, - default: false, - }, rules: Array as PropType any>>, onFocus: defineListenerProp<(i: number) => void>(), onBlur: defineListenerProp<(i: number) => void>(), @@ -29,6 +25,7 @@ export const props = { onChange: defineListenerProp<(value: string) => void>(), 'onUpdate:modelValue': defineListenerProp<(value: string) => void>(), ...pickProps(inputProps, [ + 'variant', 'size', 'readonly', 'autofocus', diff --git a/packages/varlet-ui/src/utils/elements.ts b/packages/varlet-ui/src/utils/elements.ts index 9d0b1ccdc7f..65fcb570c95 100644 --- a/packages/varlet-ui/src/utils/elements.ts +++ b/packages/varlet-ui/src/utils/elements.ts @@ -293,42 +293,3 @@ export function focusChildElementByKey( } } } - -function focusableChildren(el: Element, filterByTabIndex = true) { - const targets = ['button', '[href]', 'input:not([type="hidden"])', 'select', 'textarea', '[tabindex]'] - .map((s) => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled])`) - .join(', ') - - return Array.from(el.querySelectorAll(targets)) as HTMLElement[] -} - -function getNextElement(elements: HTMLElement[], location?: 'next' | 'prev', condition?: (el: HTMLElement) => boolean) { - let _el - let idx = elements.indexOf(document.activeElement as HTMLElement) - const inc = location === 'next' ? 1 : -1 - do { - idx += inc - _el = elements[idx] - } while ((!_el || _el.offsetParent == null || !(condition?.(_el) ?? true)) && idx < elements.length && idx >= 0) - return _el -} - -export function focusChild(el: Element, location?: 'next' | 'prev' | 'first' | 'last' | number) { - const focusable = focusableChildren(el) - - if (!location) { - if (el === document.activeElement || !el.contains(document.activeElement)) { - focusable[0]?.focus() - } - } else if (location === 'first') { - focusable[0]?.focus() - } else if (location === 'last') { - focusable.at(-1)?.focus() - } else if (typeof location === 'number') { - focusable[location]?.focus() - } else { - const _el = getNextElement(focusable, location) - if (_el) _el.focus() - else focusChild(el, location === 'next' ? 'first' : 'last') - } -} From 71e004dd3e61f267e3d315e5ea76bfebec8434f2 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Mon, 6 May 2024 10:18:50 +0800 Subject: [PATCH 03/12] feat(ui/otpInput): add OTP input component --- packages/varlet-ui/src/otp-input/OtpInput.vue | 7 ++++--- .../varlet-ui/src/otp-input/docs/en-US.md | 20 +++++++++---------- .../varlet-ui/src/otp-input/docs/zh-CN.md | 16 +++++++-------- .../varlet-ui/src/otp-input/example/index.vue | 2 -- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue index 9a2f44baefb..29daefaf6d1 100644 --- a/packages/varlet-ui/src/otp-input/OtpInput.vue +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -153,12 +153,13 @@ export default defineComponent({ } async function handleKeydown(event: KeyboardEvent) { - if (props.readonly) return + if (props.readonly || !['ArrowLeft', 'ArrowRight', 'Backspace', 'Delete'].includes(event.key)) { + return + } + const array = model.value.slice() let target: 'next' | 'prev' | 'first' | 'last' | number | null = null - if (!['ArrowLeft', 'ArrowRight', 'Backspace', 'Delete'].includes(event.key)) return - preventDefault(event) if (event.key === 'ArrowLeft') { diff --git a/packages/varlet-ui/src/otp-input/docs/en-US.md b/packages/varlet-ui/src/otp-input/docs/en-US.md index 3d838a226e3..2b64f2099ae 100644 --- a/packages/varlet-ui/src/otp-input/docs/en-US.md +++ b/packages/varlet-ui/src/otp-input/docs/en-US.md @@ -14,7 +14,7 @@ const value = ref('') ``` @@ -28,7 +28,7 @@ const value = ref('') ``` @@ -42,7 +42,7 @@ const value = ref('') ``` @@ -56,7 +56,7 @@ const value = ref('') ``` @@ -70,7 +70,7 @@ const value = ref('') ``` @@ -120,8 +120,8 @@ const value = ref('') | Event | Description | Arguments | | --- | --- | --- | -| `focus` | Triggered while focusing | `event: Event` | -| `blur` | Triggered when out of focus | `event: Event` | -| `click` | Triggered on Click | `event: Event` | -| `input` | Triggered on input | `value: string`, `event: Event` | -| `change` | Triggered on change | `value: string`, `event: Event` | +| `focus` | Triggered while focusing | `index: number` | +| `blur` | Triggered when out of focus | `index: number` | +| `click` | Triggered on Click | `index: number` | +| `input` | Triggered on input | `value: string` | +| `change` | Triggered on change | `value: string` | diff --git a/packages/varlet-ui/src/otp-input/docs/zh-CN.md b/packages/varlet-ui/src/otp-input/docs/zh-CN.md index ea1672c8aa4..2c9a1a46014 100644 --- a/packages/varlet-ui/src/otp-input/docs/zh-CN.md +++ b/packages/varlet-ui/src/otp-input/docs/zh-CN.md @@ -14,7 +14,7 @@ const value = ref('') ``` @@ -28,7 +28,7 @@ const value = ref('') ``` @@ -42,7 +42,7 @@ const value = ref('') ``` @@ -56,7 +56,7 @@ const value = ref('') ``` @@ -70,7 +70,7 @@ const value = ref('') ``` @@ -120,8 +120,8 @@ const value = ref('') | 事件名 | 说明 | 参数 | | --- | --- | --- | -| `focus` | 聚焦时触发 | `index: Number` | -| `blur` | 失焦时触发 | `index: Number` | -| `click` | 点击时触发 | `index: Number` | +| `focus` | 聚焦时触发 | `index: number` | +| `blur` | 失焦时触发 | `index: number` | +| `click` | 点击时触发 | `index: number` | | `input` | 输入时触发 | `value: string` | | `change` | 更新时触发 | `value: string` | diff --git a/packages/varlet-ui/src/otp-input/example/index.vue b/packages/varlet-ui/src/otp-input/example/index.vue index 980288f649a..227ab23bce9 100644 --- a/packages/varlet-ui/src/otp-input/example/index.vue +++ b/packages/varlet-ui/src/otp-input/example/index.vue @@ -35,5 +35,3 @@ onThemeChange()
- - From a903a8b17574b512ebe0c492cea38e09078374ff Mon Sep 17 00:00:00 2001 From: Aybrea Date: Mon, 6 May 2024 16:11:50 +0800 Subject: [PATCH 04/12] feat(ui/otp-input): add otp-input component --- packages/varlet-ui/src/otp-input/OtpInput.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue index 29daefaf6d1..03472d9250d 100644 --- a/packages/varlet-ui/src/otp-input/OtpInput.vue +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -185,6 +185,7 @@ export default defineComponent({ } function handleClick(index: number) { + focusInput(index) call(props.onClick, index) } From 38f8f0802c391b6c15e8d3675c6f6f95029e9fa8 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Mon, 6 May 2024 16:12:07 +0800 Subject: [PATCH 05/12] feat(ui/otp-input): update test case --- .../__snapshots__/index.spec.js.snap | 1985 +++++++++++++++++ .../src/otp-input/__tests__/index.spec.js | 98 + 2 files changed, 2083 insertions(+) create mode 100644 packages/varlet-ui/src/otp-input/__tests__/__snapshots__/index.spec.js.snap create mode 100644 packages/varlet-ui/src/otp-input/__tests__/index.spec.js diff --git a/packages/varlet-ui/src/otp-input/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-ui/src/otp-input/__tests__/__snapshots__/index.spec.js.snap new file mode 100644 index 00000000000..1922cd08433 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/__tests__/__snapshots__/index.spec.js.snap @@ -0,0 +1,1985 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`test otp-input > enters value and moves to next input 1`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otp-input > test otp-input 1`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otp-input 1`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otp-input size 1`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otp-input size 2`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otp-input variant 1`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otp-input variant 2`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otpInput size 1`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otpInput variant 1`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+ + + +
" +`; + +exports[`test otpInput variant 2`] = ` +"
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
1/1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ +
0 / 1
+
+
+
+
+
+
+ + + +
" +`; diff --git a/packages/varlet-ui/src/otp-input/__tests__/index.spec.js b/packages/varlet-ui/src/otp-input/__tests__/index.spec.js new file mode 100644 index 00000000000..7dc89e0e18c --- /dev/null +++ b/packages/varlet-ui/src/otp-input/__tests__/index.spec.js @@ -0,0 +1,98 @@ +import OtpInput from '..' +import VarOtpInput from '../OtpInput' +import { mount } from '@vue/test-utils' +import { createApp, h } from 'vue' +// import { trigger, triggerKeyboard } from '../../utils/test' +import { expect, vi, describe, test } from 'vitest' + +test('test otp-input plugin', () => { + const app = createApp({}).use(OtpInput) + expect(app.component(OtpInput.name)).toBeTruthy() +}) + +describe('test otp-input', () => { + test('enters value and moves to next input', async () => { + const onUpdateModelValue = vi.fn() + const onFocus = vi.fn() + + const wrapper = mount(VarOtpInput, { + props: { + modelValue: '', + 'onUpdate:modelValue': onUpdateModelValue, + onFocus, + }, + }) + + const children = wrapper.findAllComponents({ name: 'var-input' }) + + let val = '' + for (let i = 0; i < children.length; ++i) { + const input = children[i].find('.var-input__input') + if (i === 0) { + await input.trigger('click') + } + await input.setValue(String(i)) + expect(onUpdateModelValue).lastCalledWith((val += String(i))) + if (i !== 0 && i < children.length - 1) { + expect(onFocus).lastCalledWith(i + 1) + } + } + + wrapper.unmount() + }) + + test('enters value and moves to next input when focused index is not next', async () => { + const onUpdateModelValue = vi.fn() + const onFocus = vi.fn() + + const wrapper = mount(VarOtpInput, { + props: { + modelValue: '', + 'onUpdate:modelValue': onUpdateModelValue, + onFocus, + }, + }) + + const children = wrapper.findAllComponents({ name: 'var-input' }) + const input = children[3].find('.var-input__input') + await input.trigger('click') + await input.setValue(String(0)) + + expect(onUpdateModelValue).lastCalledWith('0') + expect(onFocus).lastCalledWith(1) + + wrapper.unmount() + }) + + // test('removes value and goes back when using backspace', async () => { + // const onUpdateModelValue = vi.fn() + // const onFocus = vi.fn() + // const onChange = vi.fn() + // const onKeydown = vi.fn() + + // const wrapper = mount(VarOtpInput, { + // props: { + // modelValue: '123', + // 'onUpdate:modelValue': onUpdateModelValue, + // onFocus: onFocus, + // onChange: onChange, + // onKeydown: onKeydown + // } + // }) + + // const children = wrapper.findAllComponents({ name: 'var-input' }) + // const input = children[2].find('.var-input__input') + // trigger(input, 'click') + + // await triggerKeyboard(wrapper, 'keydown', { key: 'Backspace' }) + // await triggerKeyboard(wrapper, 'keydown', { key: 'Backspace' }) + // await triggerKeyboard(wrapper, 'keydown', { key: 'Backspace' }) + // await triggerKeyboard(wrapper, 'keydown', { key: 'Backspace' }) + // await triggerKeyboard(wrapper, 'keydown', { key: 'Backspace' }) + + // expect(onKeydown).toHaveBeenCalledTimes(5) + // expect(onUpdateModelValue).lastCalledWith('') + + // wrapper.unmount() + // }) +}) From 7fd08cb140fa973ea080b585333f1322025ab2cc Mon Sep 17 00:00:00 2001 From: Aybrea Date: Thu, 9 May 2024 23:11:24 +0800 Subject: [PATCH 06/12] feat(ui/otp-input): add otp-input component --- packages/varlet-ui/src/otp-input/docs/en-US.md | 14 +++++++------- packages/varlet-ui/src/otp-input/docs/zh-CN.md | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/varlet-ui/src/otp-input/docs/en-US.md b/packages/varlet-ui/src/otp-input/docs/en-US.md index 2b64f2099ae..8bbc9582560 100644 --- a/packages/varlet-ui/src/otp-input/docs/en-US.md +++ b/packages/varlet-ui/src/otp-input/docs/en-US.md @@ -28,7 +28,7 @@ const value = ref('') ``` @@ -42,7 +42,7 @@ const value = ref('') ``` @@ -56,11 +56,11 @@ const value = ref('') ``` -### Smaller size +### Variant Appearance ```html ``` -### Variant Appearance +### Smaller Size Variant Appearance ```html ``` diff --git a/packages/varlet-ui/src/otp-input/docs/zh-CN.md b/packages/varlet-ui/src/otp-input/docs/zh-CN.md index 2c9a1a46014..64f652092f2 100644 --- a/packages/varlet-ui/src/otp-input/docs/zh-CN.md +++ b/packages/varlet-ui/src/otp-input/docs/zh-CN.md @@ -28,7 +28,7 @@ const value = ref('') ``` @@ -42,7 +42,7 @@ const value = ref('') ``` @@ -56,11 +56,11 @@ const value = ref('') ``` -### 小尺寸外观 +### 变体外观 ```html ``` -### 变体外观 +### 小尺寸变体外观 ```html ``` From f9c889a2a09764964e5d52e48403cc1e040b2099 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Fri, 10 May 2024 10:29:40 +0800 Subject: [PATCH 07/12] feat(ui/otp-input): add otp-input component --- packages/varlet-ui/src/otp-input/OtpInput.vue | 4 +--- packages/varlet-ui/src/otp-input/__tests__/index.spec.js | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue index 03472d9250d..4bf5b3dd708 100644 --- a/packages/varlet-ui/src/otp-input/OtpInput.vue +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -55,6 +55,7 @@ export default defineComponent({ setup(props) { const contentRef = ref() const inputRefs = ref | null>([]) + const { bindForm } = useForm() const { errorMessage, validateWithTrigger: vt, @@ -63,8 +64,6 @@ export default defineComponent({ resetValidation, } = useValidation() - const { bindForm, form } = useForm() - const model = computed({ get() { return String(props.modelValue).split('') @@ -218,7 +217,6 @@ export default defineComponent({ inputRefs, errorMessage, focusIndex, - variant: props.variant, n, classes, handleInput, diff --git a/packages/varlet-ui/src/otp-input/__tests__/index.spec.js b/packages/varlet-ui/src/otp-input/__tests__/index.spec.js index 7dc89e0e18c..bace246f0f8 100644 --- a/packages/varlet-ui/src/otp-input/__tests__/index.spec.js +++ b/packages/varlet-ui/src/otp-input/__tests__/index.spec.js @@ -1,7 +1,7 @@ import OtpInput from '..' import VarOtpInput from '../OtpInput' import { mount } from '@vue/test-utils' -import { createApp, h } from 'vue' +import { createApp } from 'vue' // import { trigger, triggerKeyboard } from '../../utils/test' import { expect, vi, describe, test } from 'vitest' From 9982c998b271569cef68951ebb431af18aa329e5 Mon Sep 17 00:00:00 2001 From: Aybrea Date: Sat, 1 Jun 2024 13:48:06 +0800 Subject: [PATCH 08/12] feat(ui/otp-input): add otp-input component --- packages/varlet-ui/src/otp-input/OtpInput.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue index 4bf5b3dd708..092ce872975 100644 --- a/packages/varlet-ui/src/otp-input/OtpInput.vue +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -137,7 +137,7 @@ export default defineComponent({ array[focusIndex.value] = value let target: any = null const modelLength = model.value.filter(Boolean).length - if (focusIndex.value > modelLength) { + if (focusIndex.value >= modelLength) { target = modelLength } else if (focusIndex.value + 1 !== props.length) { target = 'next' From bd1b4f4345fbe61f7b741baae2809675e41a3b2e Mon Sep 17 00:00:00 2001 From: chouchouji <1305974212@qq.com> Date: Sun, 2 Jun 2024 17:34:09 +0800 Subject: [PATCH 09/12] fix(otp-input): add missing css file import --- packages/varlet-ui/src/otp-input/OtpInput.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue index 092ce872975..916460dc0ea 100644 --- a/packages/varlet-ui/src/otp-input/OtpInput.vue +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -237,5 +237,7 @@ export default defineComponent({ From 058d48a1a087652747529933f35427b9008b2f16 Mon Sep 17 00:00:00 2001 From: chouchouji <1305974212@qq.com> Date: Sun, 2 Jun 2024 19:20:39 +0800 Subject: [PATCH 10/12] refactor(otp-input): optimize code --- packages/varlet-ui/src/otp-input/OtpInput.vue | 109 ++++++++---------- .../varlet-ui/src/otp-input/docs/en-US.md | 4 +- .../varlet-ui/src/otp-input/docs/zh-CN.md | 4 +- packages/varlet-ui/src/otp-input/props.ts | 4 +- 4 files changed, 56 insertions(+), 65 deletions(-) diff --git a/packages/varlet-ui/src/otp-input/OtpInput.vue b/packages/varlet-ui/src/otp-input/OtpInput.vue index 916460dc0ea..899d03192b8 100644 --- a/packages/varlet-ui/src/otp-input/OtpInput.vue +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -1,5 +1,5 @@