Compare commits

...

2 Commits

10 changed files with 231 additions and 60 deletions

View File

@ -209,6 +209,7 @@ const handleBeforeToggle: DropMenuItemBeforeToggle = ({ status, resolve }) => {
| value-key | 选项对象中value 对应的 key | string | - | value | - |
| label-key | 选项对象中,展示的文本对应的 key | string | - | label | - |
| tip-key | 选项对象中,选项说明对应的 key | string | - | tip | - |
| popup-height | popup弹出容器的高度不设置默认为80% | string | - | - | $LOWEST_VERSION$ |
| root-portal | 是否从页面中脱离出来,用于解决各种 fixed 失效问题 | boolean | - | false | 1.11.0 |
## DropdownItem Events

View File

@ -1,6 +1,7 @@
---
version: 1.3.10
---
# Keyboard 虚拟键盘
虚拟数字键盘,用于输入数字、密码、身份证或车牌号等场景。
@ -93,6 +94,42 @@ const onInput = (value) => showToast(`${value}`)
const onDelete = () => showToast('删除')
```
## 车牌号键盘语言控制
通过 `car-lang` 属性可以控制车牌键盘的语言模式,支持中文省份(`zh`)和英文字母(`en`)。通过 `auto-switch-lang` 属性可以控制是否自动切换语言。
```html
<!-- 受控模式:手动控制语言切换 -->
<wd-cell title="车牌号键盘(受控)" :value="value" is-link @click="showKeyBoard" />
<wd-keyboard v-model="value" v-model:visible="visible" v-model:car-lang="lang" mode="car" @input="onInput" @delete="onDelete"></wd-keyboard>
<!-- 非受控模式:禁用自动切换 -->
<wd-cell title="车牌号键盘(非自动切换)" :value="value2" is-link @click="showKeyBoard2" />
<wd-keyboard v-model="value2" v-model:visible="visible2" mode="car" :auto-switch-lang="false" @input="onInput" @delete="onDelete"></wd-keyboard>
```
```ts
const { show: showToast } = useToast()
const visible = ref<boolean>(false)
const visible2 = ref<boolean>(false)
const value = ref<string>('')
const value2 = ref<string>('')
const lang = ref<'zh' | 'en'>('zh')
function showKeyBoard() {
visible.value = true
}
function showKeyBoard2() {
visible2.value = true
}
const onInput = (value) => showToast(`${value}`)
const onDelete = () => showToast('删除')
```
## 带标题的键盘
通过 `title` 属性可以设置键盘标题。
@ -242,25 +279,27 @@ const onDelete = () => showToast('删除')
## Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
| ------------------- | ------------------------ | --------------------- | -------------------------- | ---------- | ---------------- |
| v-model:visible | 是否展开 | `boolean` | - | `false` | 1.3.10 |
| v-model | 绑定的值 | `string` | - | - | 1.3.10 |
| title | 标题 | `string` | - | - | 1.3.10 |
| mode | 键盘模式 | `string` | `default`, `car`, `custom` | `default` | 1.3.10 |
| zIndex | 层级 | `number` | - | `100` | 1.3.10 |
| maxlength | 最大长度 | `number` | - | `Infinity` | 1.3.10 |
| showDeleteKey | 是否显示删除键 | `boolean` | - | `true` | 1.3.10 |
| randomKeyOrder | 是否随机键盘按键顺序 | `boolean` | - | `false` | 1.3.10 |
| closeText | 确认按钮文本 | `string` | - | - | 1.3.10 |
| deleteText | 删除按钮文本 | `string` | - | - | 1.3.10 |
| closeButtonLoading | 关闭按钮是否显示加载状态 | `boolean` | - | `false` | 1.3.10 |
| modal | 是否显示蒙层遮罩 | `boolean` | - | `false` | 1.3.10 |
| hideOnClickOutside | 是否在点击外部时收起键盘 | `boolean` | - | `true` | 1.3.10 |
| lockScroll | 是否锁定背景滚动,锁定时蒙层里的内容也将无法滚动 | `boolean` | - | `true` | 1.3.10 |
| safeAreaInsetBottom | 是否在底部安全区域内 | `boolean` | - | `true` | 1.3.10 |
| extraKey | 额外按键 | `string` / `string[]` | - | - | 1.3.10 |
| root-portal | 是否从页面中脱离出来,用于解决各种 fixed 失效问题 | `boolean` | - | `false` | 1.11.0 |
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
| ------------------- | -------------------------------------------------------------------- | --------------------- | -------------------------- | ---------- | -------- |
| v-model:visible | 是否展开 | `boolean` | - | `false` | 1.3.10 |
| v-model | 绑定的值 | `string` | - | - | 1.3.10 |
| title | 标题 | `string` | - | - | 1.3.10 |
| mode | 键盘模式 | `string` | `default`, `car`, `custom` | `default` | 1.3.10 |
| zIndex | 层级 | `number` | - | `100` | 1.3.10 |
| maxlength | 最大长度 | `number` | - | `Infinity` | 1.3.10 |
| showDeleteKey | 是否显示删除键 | `boolean` | - | `true` | 1.3.10 |
| randomKeyOrder | 是否随机键盘按键顺序 | `boolean` | - | `false` | 1.3.10 |
| closeText | 确认按钮文本 | `string` | - | - | 1.3.10 |
| deleteText | 删除按钮文本 | `string` | - | - | 1.3.10 |
| closeButtonLoading | 关闭按钮是否显示加载状态 | `boolean` | - | `false` | 1.3.10 |
| modal | 是否显示蒙层遮罩 | `boolean` | - | `false` | 1.3.10 |
| hideOnClickOutside | 是否在点击外部时收起键盘 | `boolean` | - | `true` | 1.3.10 |
| lockScroll | 是否锁定背景滚动,锁定时蒙层里的内容也将无法滚动 | `boolean` | - | `true` | 1.3.10 |
| safeAreaInsetBottom | 是否在底部安全区域内 | `boolean` | - | `true` | 1.3.10 |
| extraKey | 额外按键 | `string` / `string[]` | - | - | 1.3.10 |
| root-portal | 是否从页面中脱离出来,用于解决各种 fixed 失效问题 | `boolean` | - | `false` | 1.11.0 |
| v-model:carLang | 车牌键盘语言模式,当 mode=car 时生效 | `string` | `zh`, `en` | - | 1.12.4 |
| autoSwitchLang | 是否自动切换车牌键盘语言,当 mode=car 且 car-lang 是非受控状态时生效 | `boolean` | - | `false` | 1.12.4 |
## Slot

View File

@ -1,6 +1,7 @@
---
version: 1.3.10
---
# Keyboard
Virtual keyboard for inputting numbers, passwords, ID cards, or license plate numbers.
@ -93,6 +94,42 @@ const onInput = (value) => showToast(`${value}`)
const onDelete = () => showToast('Delete')
```
## License Plate Keyboard Language Control
You can control the language mode of the license plate keyboard through the `car-lang` property, supporting Chinese provinces (`zh`) and English letters (`en`). Use the `auto-switch-lang` property to control whether to automatically switch languages.
```html
<!-- Controlled mode: Manual language switching -->
<wd-cell title="License Plate Keyboard (Controlled)" :value="value" is-link @click="showKeyBoard" />
<wd-keyboard v-model="value" v-model:visible="visible" v-model:car-lang="lang" mode="car" @input="onInput" @delete="onDelete"></wd-keyboard>
<!-- Uncontrolled mode: Disable auto-switching -->
<wd-cell title="License Plate Keyboard (No Auto-switch)" :value="value2" is-link @click="showKeyBoard2" />
<wd-keyboard v-model="value2" v-model:visible="visible2" mode="car" :auto-switch-lang="false" @input="onInput" @delete="onDelete"></wd-keyboard>
```
```ts
const { show: showToast } = useToast()
const visible = ref<boolean>(false)
const visible2 = ref<boolean>(false)
const value = ref<string>('')
const value2 = ref<string>('')
const lang = ref<'zh' | 'en'>('zh')
function showKeyBoard() {
visible.value = true
}
function showKeyBoard2() {
visible2.value = true
}
const onInput = (value) => showToast(`${value}`)
const onDelete = () => showToast('Delete')
```
## Keyboard with Title
You can set the keyboard title through the `title` property.
@ -201,33 +238,86 @@ You can bind the keyboard's current input value through `v-model` and limit the
></wd-keyboard>
```
```ts
const { show: showToast } = useToast()
const visible = ref<boolean>(false)
const value1 = ref<string>('')
function showKeyBoard() {
visible.value = true
}
const onInput = (value) => showToast(`${value}`)
const onDelete = () => showToast('Delete')
```
## Display Modal Overlay
`hideOnClickOutside` controls whether the keyboard popup has an overlay, and `modal` controls whether the overlay is transparent.
::: tip
Currently `modal` only controls whether the overlay is transparent, `hideOnClickOutside` controls whether the popup has an overlay. When there is an overlay, clicking the overlay can close the keyboard, but when the keyboard is open, you must click the overlay to close the current keyboard before you can click other buttons. You can also disable `hideOnClickOutside` and manually control whether the keyboard is displayed to implement closing the keyboard when clicking outside, which is more flexible.
:::
```html
<wd-cell title="Two-way Binding" :value="value1" is-link @click="showKeyBoard" />
<wd-keyboard :modal="true" :hide-on-click-outside="true" v-model:visible="visible" @input="onInput" @delete="onDelete" />
```
```ts
const { show: showToast } = useToast()
const visible = ref<boolean>(false)
const value1 = ref<string>('')
function showKeyBoard() {
visible.value = true
}
const onInput = (value) => showToast(`${value}`)
const onDelete = () => showToast('Delete')
```
## Attributes
| Attribute | Description | Type | Default | Version |
|---------|-------------|------|---------|------|
| v-model:visible | Whether to display keyboard | boolean | false | - |
| v-model | Keyboard input value | string | - | - |
| maxlength | Maximum input length | number | - | - |
| title | Keyboard title | string | - | - |
| mode | Keyboard mode, can be set to `custom` or `car` | string | - | - |
| close-text | Text of close button | string | - | - |
| extra-key | Content of extra key | string / string[] | - | - |
| random-key-order | Whether to randomly arrange number keys | boolean | false | - |
| show-close-button | Whether to show close button | boolean | true | - |
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | boolean | true | - |
| z-index | Keyboard z-index | number | 100 | - |
| root-portal | Whether to detach from the page, used to solve various fixed positioning issues | boolean | false | 1.11.0 |
| Parameter | Description | Type | Options | Default | Version |
| ------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------- | -------------------------- | ---------- | ------- |
| v-model:visible | Whether to display | `boolean` | - | `false` | 1.3.10 |
| v-model | Bound value | `string` | - | - | 1.3.10 |
| title | Title | `string` | - | - | 1.3.10 |
| mode | Keyboard mode | `string` | `default`, `car`, `custom` | `default` | 1.3.10 |
| zIndex | Z-index | `number` | - | `100` | 1.3.10 |
| maxlength | Maximum length | `number` | - | `Infinity` | 1.3.10 |
| showDeleteKey | Whether to show delete key | `boolean` | - | `true` | 1.3.10 |
| randomKeyOrder | Whether to randomize keyboard key order | `boolean` | - | `false` | 1.3.10 |
| closeText | Confirm button text | `string` | - | - | 1.3.10 |
| deleteText | Delete button text | `string` | - | - | 1.3.10 |
| closeButtonLoading | Whether close button shows loading state | `boolean` | - | `false` | 1.3.10 |
| modal | Whether to show modal overlay | `boolean` | - | `false` | 1.3.10 |
| hideOnClickOutside | Whether to close keyboard when clicking outside | `boolean` | - | `true` | 1.3.10 |
| lockScroll | Whether to lock background scroll, when locked, content in the overlay will also not scroll | `boolean` | - | `true` | 1.3.10 |
| safeAreaInsetBottom | Whether to enable bottom safe area | `boolean` | - | `true` | 1.3.10 |
| extraKey | Extra key | `string` / `string[]` | - | - | 1.3.10 |
| root-portal | Whether to detach from the page, used to solve various fixed positioning issues | `boolean` | - | `false` | 1.11.0 |
| v-model:carLang | License plate keyboard language mode, effective when mode=car | `string` | `zh`, `en` | - | 1.12.4 |
| autoSwitchLang | Whether to automatically switch license plate keyboard language, effective when mode=car and car-lang is uncontrolled | `boolean` | - | `false` | 1.12.4 |
## Slot
| name | Description | Type | Version |
| ----- | ----------- | ---- | ------- |
| title | Title | - | 1.2.12 |
## Events
| Event | Description | Parameters |
|-------|-------------|------------|
| input | Triggered when a key is pressed | key: The pressed key |
| delete | Triggered when delete key is pressed | - |
| close | Triggered when keyboard is closed | - |
| Event Name | Description | Parameters | Version |
| ---------- | ------------------------------------------------- | ----------- | ------- |
| input | Triggered when a key is pressed | key: string | - |
| delete | Triggered when delete key is pressed | - | - |
| close | Triggered when close button or outside is clicked | - | - |
## Slots
## External Style Classes
| Name | Description |
|------|-------------|
| title | Custom title content |
| Class Name | Description | Version |
| ------------ | --------------------- | ------- |
| custom-class | Root node style class | 1.3.10 |
| custom-style | Root node style | 1.3.10 |

View File

@ -234,7 +234,8 @@
"chao-hu": "Chaohu Lake",
"chao-zhou": "Chaozhou",
"che-hui": "withdraw",
"che-pai-hao-jian-pan": "License plate number keyboard",
"che-pai-hao-jian-pan-fei-shou-kong": "License plate keyboard (Uncontrolled)",
"che-pai-hao-jian-pan-shou-kong": "License plate keyboard (Controlled)",
"checkbox-fu-xuan-kuang": "Checkbox",
"checkbox-title": "Checkbox",
"chen-zhou": "Chenzhou",

View File

@ -234,7 +234,8 @@
"chao-hu": "巢湖",
"chao-zhou": "潮州",
"che-hui": "撤回",
"che-pai-hao-jian-pan": "车牌号键盘",
"che-pai-hao-jian-pan-fei-shou-kong": "车牌号键盘(非受控)",
"che-pai-hao-jian-pan-shou-kong": "车牌号键盘(受控)",
"checkbox-fu-xuan-kuang": "Checkbox 复选框",
"checkbox-title": "Checkbox 复选框",
"chen-zhou": "郴州",

View File

@ -11,7 +11,8 @@
<wd-cell :title="$t('slot-zi-ding-yi-biao-ti')" is-link @click="showKeyBoard(9)" />
<wd-cell :title="$t('duo-geewai-an-jian')" is-link @click="showKeyBoard(5)" />
<wd-cell :title="$t('sui-ji-shu-zi-jian-pan')" is-link @click="showKeyBoard(6)" />
<wd-cell :title="$t('che-pai-hao-jian-pan')" is-link @click="showKeyBoard(10)" />
<wd-cell :title="$t('che-pai-hao-jian-pan-fei-shou-kong')" :value="value10" is-link @click="showKeyBoard(10)" />
<wd-cell :title="$t('che-pai-hao-jian-pan-shou-kong')" :value="value11" is-link @click="showKeyBoard(11)" />
<wd-cell :title="$t('shuang-xiang-bang-ding')" clickable :value="value1" @click="showKeyBoard(7)" />
<wd-cell :title="$t('zhan-shi-meng-ceng')" clickable @click="showKeyBoard(8)" />
</wd-cell-group>
@ -65,7 +66,8 @@
<wd-keyboard :modal="true" v-model:visible="visible8" @input="onInput" @delete="onDelete" />
<wd-keyboard v-model:visible="visible10" mode="car" @input="onInput" @delete="onDelete" />
<wd-keyboard v-model="value10" v-model:visible="visible10" mode="car" @input="onInput" @delete="onDelete" :autoSwitchLang="false" />
<wd-keyboard v-model="value11" v-model:visible="visible11" v-model:carLang="carLang" mode="car" @input="onInput" @delete="onDelete" />
</page-wraper>
</template>
<script lang="ts" setup>
@ -84,11 +86,14 @@ const visible7 = ref<boolean>(false)
const visible8 = ref<boolean>(false)
const visible9 = ref<boolean>(false)
const visible10 = ref<boolean>(false)
const visible11 = ref<boolean>(false)
const visibleArr = [visible1, visible2, visible3, visible4, visible5, visible6, visible7, visible8, visible9, visible10]
const visibleArr = [visible1, visible2, visible3, visible4, visible5, visible6, visible7, visible8, visible9, visible10, visible11]
const value1 = ref<string>('')
const value10 = ref<string>('')
const value11 = ref<string>('')
const carLang = ref<'zh' | 'en'>('zh')
function showKeyBoard(index: number) {
visibleArr.forEach((item, i) => (i === index - 1 ? (item.value = true) : (item.value = false)))
}

View File

@ -72,6 +72,10 @@ export const dorpMenuItemProps = {
* popup样式
*/
customPopupStyle: makeStringProp(''),
/**
*
*/
popupHeight: makeStringProp(''),
/**
* fixed (H5: teleport, APP: renderjs, 小程序: root-portal)
*/

View File

@ -9,7 +9,7 @@
:z-index="zIndex"
:duration="duration"
:position="position"
:custom-style="`position: absolute; pointer-events: auto; max-height: 80%;${customPopupStyle}`"
:custom-style="`position: absolute; pointer-events: auto; max-height: ${popupHeight ? popupHeight : '80%'}; ${customPopupStyle}`"
:custom-class="customPopupClass"
:modal="false"
:close-on-click-modal="false"
@ -19,7 +19,7 @@
@before-leave="beforeLeave"
@after-leave="afterLeave"
>
<view v-if="options.length">
<scroll-view v-if="options.length" :style="popupHeight ? { height: popupHeight } : ''" scroll-y scroll-with-animation :show-scrollbar="true">
<view
v-for="(item, index) in options"
:key="index"
@ -36,7 +36,7 @@
:custom-class="`wd-drop-item__icon ${customIcon}`"
/>
</view>
</view>
</scroll-view>
<slot v-else />
</wd-popup>
</view>

View File

@ -3,6 +3,7 @@ import { baseProps, makeBooleanProp, makeNumberProp, makeStringProp } from '../c
export type KeyboardMode = 'default' | 'custom' | 'car'
export type KeyType = '' | 'delete' | 'extra' | 'close'
export type CarKeyboardLang = 'zh' | 'en'
export interface Key {
text?: number | string // key文本
@ -79,5 +80,13 @@ export const keyboardProps = {
/**
* fixed (H5: teleport, APP: renderjs, 小程序: root-portal)
*/
rootPortal: makeBooleanProp(false)
rootPortal: makeBooleanProp(false),
/**
* mode=car时生效
*/
carLang: String as PropType<CarKeyboardLang>,
/**
* mode=car且carLang是非受控状态时生效
*/
autoSwitchLang: makeBooleanProp(false)
}

View File

@ -55,12 +55,12 @@ export default {
import { computed, ref, watch, useSlots } from 'vue'
import wdPopup from '../wd-popup/wd-popup.vue'
import WdKey from './key/index.vue'
import { keyboardProps, type Key } from './types'
import { keyboardProps, type Key, type CarKeyboardLang } from './types'
import type { NumberKeyType } from './key/types'
import { CAR_KEYBOARD_AREAS, CAR_KEYBOARD_KEYS } from './constants'
const props = defineProps(keyboardProps)
const emit = defineEmits(['update:visible', 'input', 'close', 'delete', 'update:modelValue'])
const emit = defineEmits(['update:visible', 'input', 'close', 'delete', 'update:modelValue', 'update:carLang'])
const slots = useSlots()
const show = ref(props.visible)
@ -71,7 +71,14 @@ watch(
}
)
const carKeyboardLang = ref('zh')
const carLang = ref<CarKeyboardLang>('zh')
const carKeyboardLang = computed({
get: () => (props.carLang ? props.carLang : carLang.value),
set: (value: CarKeyboardLang) => {
carLang.value = value
}
})
const keys = computed(() => (props.mode !== 'car' ? (props.mode === 'custom' ? genCustomKeys() : genDefaultKeys()) : genCarKeys()))
const showClose = computed(() => {
@ -141,7 +148,7 @@ function genCarKeys(): Array<Key> {
const [keys, remainKeys] = splitCarKeys()
return [
...keys,
{ text: carKeyboardLang.value === 'zh' ? 'ABC' : '返回', type: 'extra', wider: true },
{ text: carKeyboardLang.value === 'zh' ? 'ABC' : '省份', type: 'extra', wider: true },
...remainKeys,
{ text: props.deleteText, type: 'delete', wider: true }
]
@ -161,8 +168,13 @@ const handlePress = (text: string, type: NumberKeyType) => {
if (type === 'extra') {
if (text === '') {
return handleClose()
} else if (text === 'ABC' || text === '返回') {
carKeyboardLang.value = carKeyboardLang.value === 'zh' ? 'en' : 'zh'
} else if (text === 'ABC' || text === '省份') {
const newLang = carKeyboardLang.value === 'zh' ? 'en' : 'zh'
if (props.carLang) {
emit('update:carLang', newLang)
} else {
carKeyboardLang.value = newLang
}
return
}
}
@ -170,12 +182,21 @@ const handlePress = (text: string, type: NumberKeyType) => {
const value = props.modelValue
if (type === 'delete') {
emit('delete')
emit('update:modelValue', value.slice(0, value.length - 1))
const newValue = value.slice(0, value.length - 1)
emit('update:modelValue', newValue)
if (props.mode === 'car' && newValue.length === 0 && props.autoSwitchLang) {
carKeyboardLang.value = 'zh'
}
} else if (type === 'close') {
handleClose()
} else if (value.length < +props.maxlength) {
emit('input', text)
emit('update:modelValue', value + text)
const newValue = value + text
emit('update:modelValue', newValue)
if (props.mode === 'car' && newValue.length === 1 && props.autoSwitchLang) {
//
carKeyboardLang.value = 'en'
}
}
}
</script>