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..16b43720652 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/OtpInput.vue @@ -0,0 +1,235 @@ + + + + + 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..bace246f0f8 --- /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 } 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() + // }) +}) 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..b9810178785 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/docs/en-US.md @@ -0,0 +1,136 @@ +# Input + +### Intro + +The OTP input is used to authenticate users with a one-time password. + +### Standard Usage + +```html + + + +``` + +### Readonly + +```html + + + +``` + +### Disabled + +```html + + + +``` + +### Validate + +```html + + + +``` + +### Variant Appearance + +```html + + + +``` + +### Smaller Size 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` | 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_ | `-` | +| `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 | `index: number` | +| `input` | Triggered on input | `value: string` | +| `change` | Triggered on change | `value: string` | + +### Style Variables + +Here are the CSS variables used by the component. Styles can be customized using [StyleProvider](#/en-US/style-provider). + +| Variable | Default | +| --- | --- | +| `--var-otp-input-text-align` | `center` | +| `--var-otp-input-margin-right` | `8px` | 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..a30e7987b1f --- /dev/null +++ b/packages/varlet-ui/src/otp-input/docs/zh-CN.md @@ -0,0 +1,136 @@ +# 验证码输入框 + +### 介绍 + +验证码输入框,用于通过一次性密码对用户进行认证。 + +### 基本使用 + +```html + + + +``` + +### 只读状态 + +```html + + + +``` + +### 禁用状态 + +```html + + + +``` + +### 字段校验 + +```html + + + +``` + +### 变体外观 + +```html + + + +``` + +### 小尺寸变体外观 + +```html + + + +``` + +## API + +### 属性 + +| 参数 | 说明 | 类型 | 默认值 | +| --- |--------------------------------------------------------------------------| --- | --- | +| `v-model` | 绑定的值 | _string\|number_ | `-` | +| `size` | 输入框尺寸,可选值 `normal` `small` | _string_ | `normal` | +| `variant` | 输入框风格, 可选值为 `standard` `outlined` | _string_ | `standard` | +| `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` | 聚焦时触发 | `event: Event` | +| `blur` | 失焦时触发 | `event: Event` | +| `click` | 点击时触发 | `index: number` | +| `input` | 输入时触发 | `value: string` | +| `change` | 更新时触发 | `value: string` | + +### 样式变量 + +以下为组件使用的 css 变量,可以使用 [StyleProvider 组件](#/zh-CN/style-provider) 进行样式定制。 + +| 变量名 | 默认值 | +| --- | --- | +| `--var-otp-input-text-align` | `center` | +| `--var-otp-input-margin-right` | `8px` | 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..227ab23bce9 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/example/index.vue @@ -0,0 +1,37 @@ + + + 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..96f4bb6c0e0 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/example/locale/en-US.ts @@ -0,0 +1,10 @@ +export default { + basicUsage: 'Basic Usage', + errorMessage: 'Must enter a 6-digit verification code.', + variant: 'Variant Appearance', + standard: 'Standard Variant', + smallSize: 'Small Size Variant Appearance', + 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..0b02ec37846 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/example/locale/zh-CN.ts @@ -0,0 +1,10 @@ +export default { + basicUsage: '基本使用', + 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..98727f345a3 --- /dev/null +++ b/packages/varlet-ui/src/otp-input/otpInput.less @@ -0,0 +1,24 @@ +:root { + --var-otp-input-text-align: center; + --var-otp-input-margin-right: 8px; +} + +.var-otp-input { + &__container { + display: flex; + + .var-input[var-otp-input-cover] { + .var-form-details { + display: none; + } + + .var-input__input { + text-align: var(--var-otp-input-text-align); + } + + &:not(:last-child) { + margin-right: var(--var-otp-input-margin-right); + } + } + } +} 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..1c4adb787df --- /dev/null +++ b/packages/varlet-ui/src/otp-input/props.ts @@ -0,0 +1,38 @@ +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'], + }, + rules: Array as PropType any>>, + onFocus: defineListenerProp<(event: Event) => void>(), + onBlur: defineListenerProp<(event: Event) => void>(), + onClick: defineListenerProp<(i: number) => void>(), + onInput: defineListenerProp<(value: string) => void>(), + onChange: defineListenerProp<(value: string) => void>(), + 'onUpdate:modelValue': defineListenerProp<(value: string) => void>(), + ...pickProps(inputProps, [ + 'variant', + '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/types/index.d.ts b/packages/varlet-ui/types/index.d.ts index 26a63bcc679..94dc70ae186 100644 --- a/packages/varlet-ui/types/index.d.ts +++ b/packages/varlet-ui/types/index.d.ts @@ -54,6 +54,7 @@ export * from './menu' export * from './menuOption' export * from './menuSelect' export * from './option' +export * from './otpInput' export * from './overlay' export * from './pagination' export * from './paper' @@ -144,6 +145,7 @@ declare module 'vue' { VarMenuOption: typeof import('@varlet/ui')['_MenuOptionComponent'] VarMenuSelect: typeof import('@varlet/ui')['_MenuSelectComponent'] VarOption: typeof import('@varlet/ui')['_OptionComponent'] + VarOtpInput: typeof import('@varlet/ui')['_OtpInputComponent'] VarOverlay: typeof import('@varlet/ui')['_OverlayComponent'] VarPagination: typeof import('@varlet/ui')['_PaginationComponent'] VarPaper: typeof import('@varlet/ui')['_PaperComponent'] 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/types/styleVars.d.ts b/packages/varlet-ui/types/styleVars.d.ts index 661b4a69e0d..1fab890ab97 100644 --- a/packages/varlet-ui/types/styleVars.d.ts +++ b/packages/varlet-ui/types/styleVars.d.ts @@ -837,6 +837,10 @@ export interface StyleVars { menuOptionTextColor?: string '--menu-option-disabled-color'?: string menuOptionDisabledColor?: string + '--var-otp-input-text-align'?: string + varOtpInputTextAlign?: string + '--var-otp-input-margin-right'?: string + varOtpInputMarginRight?: string '--overlay-background-color'?: string overlayBackgroundColor?: string '--pagination-text-color'?: string 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 选择框',