shiftui
v0.1.2
Published
A Vue 3 component library
Maintainers
Readme
shiftui
shiftui 是一个基于 Vue 3 的组件库。当前包含 ValuePicker、DateTimePicker 与 NumberKeyboard 三个组件。
安装
npm i shiftui
shiftui将vue作为peerDependencies,请确保你的项目已安装 Vue 3。
快速开始
方式 1:全局注册(推荐)
import { createApp } from 'vue'
import App from './App.vue'
import ShiftUI from 'shiftui'
import 'shiftui/style.css'
createApp(App).use(ShiftUI).mount('#app')方式 2:按需引入
<script setup lang="ts">
import { ref } from 'vue'
import { ValuePicker, DateTimePicker, NumberKeyboard } from 'shiftui'
import 'shiftui/style.css'
const value = ref(30)
const dateTime = ref('2026-05-08 17:30:00')
const amount = ref('')
</script>
<template>
<ValuePicker v-model="value" :min="0" :max="120" suffix=" 秒" />
<DateTimePicker v-model="dateTime" theme="light" />
<input v-model="amount" data-number-keyboard readonly inputmode="none" placeholder="点击输入金额" />
<NumberKeyboard />
</template>组件:ValuePicker
一个支持拖拽惯性滚动的数字选择器,适合时间、计数等场景。
Props
modelValue?: number- 当前值(默认0)min?: number- 最小值(默认0)max?: number- 最大值(默认59)step?: number- 步长(默认1)width?: number- 组件宽度(像素,默认200)height?: number- 组件高度(像素,默认50)prefix?: string- 数值前缀(默认空字符串)suffix?: string- 数值后缀(默认空字符串)
Events
update:modelValue- 当值变化时触发
样式细粒度定制
ValuePicker 支持两种方式做细粒度样式覆盖:
- 通过 CSS 变量快速改主题色
- 通过
classNames/styles精确覆盖内部结构样式
1) CSS 变量(主题令牌)
<template>
<ValuePicker v-model="value" class="demo-picker-theme" />
</template>
<style>
.demo-picker-theme {
--shiftui-picker-bg: #0b1220;
--shiftui-picker-border: rgba(125, 211, 252, 0.25);
--shiftui-item-color: rgba(255, 255, 255, 0.5);
--shiftui-item-active-color: #7dd3fc;
--shiftui-item-active-shadow: 0 0 10px rgba(125, 211, 252, 0.45);
--shiftui-focus-line-color: rgba(125, 211, 252, 0.3);
}
</style>常用变量包括:
--shiftui-picker-bg--shiftui-picker-color--shiftui-picker-border--shiftui-picker-radius--shiftui-mask-top--shiftui-mask-mid--shiftui-mask-bottom--shiftui-item-color--shiftui-item-active-color--shiftui-item-active-weight--shiftui-item-active-shadow--shiftui-focus-line-color--shiftui-font-size--shiftui-item-gap
2) classNames / styles(结构级覆盖)
<script setup lang="ts">
import { ref } from 'vue'
import { ValuePicker } from 'shiftui'
const value = ref(30)
</script>
<template>
<ValuePicker
v-model="value"
:class-names="{
root: 'my-picker',
itemActive: 'my-picker-active',
focusLine: 'my-picker-line'
}"
:styles="{
item: { letterSpacing: '0.04em' },
focusLine: { height: '2px', borderRadius: '2px' }
}"
/>
</template>示例
<script setup lang="ts">
import { ref } from 'vue'
import { ValuePicker } from 'shiftui'
const remain = ref(45)
</script>
<template>
<ValuePicker
v-model="remain"
:min="0"
:max="120"
:step="1"
:width="220"
:height="56"
prefix="剩余 "
suffix=" 秒"
/>
</template>组件:DateTimePicker
用于日期+时间选择(精确到秒),支持浅色/深色主题,同时支持手动输入与自定义事件监听。
Props
modelValue?: string | Date- 当前值,字符串建议格式YYYY-MM-DD HH:mm:sstheme?: 'light' | 'dark'- 主题样式(默认dark)label?: string- 标题文案placeholder?: string- 输入框占位符hint?: string- 提示文案disabled?: boolean- 是否禁用allowInput?: boolean- 是否展示手动输入框(默认true)min?: string- 最小允许时间(格式同modelValue)max?: string- 最大允许时间(格式同modelValue)classNames?: Partial<Record<'root' | 'label' | 'row' | 'input' | 'textInput' | 'hint' | 'error', string>>styles?: Partial<Record<'root' | 'label' | 'row' | 'input' | 'textInput' | 'hint' | 'error', CSSProperties>>
Events
update:modelValue- 值变更时触发change(value, date, source)- 选择或手动输入成功后触发,source为picker | inputinput(value)- 手动输入时实时触发invalid(rawValue, reason)- 输入或选择不合法时触发
示例
<script setup lang="ts">
import { ref } from 'vue'
import { DateTimePicker } from 'shiftui'
const executeAt = ref('2026-05-08 18:00:00')
const onDateTimeChange = (value: string) => {
console.log('选中时间:', value)
}
</script>
<template>
<DateTimePicker
v-model="executeAt"
label="执行时间"
theme="dark"
hint="支持格式:YYYY-MM-DD HH:mm:ss"
min="2026-01-01 00:00:00"
@change="onDateTimeChange"
@invalid="(_, reason) => console.warn(reason)"
/>
</template>组件:NumberKeyboard
触控数字键盘组件(不内置输入框),默认会自动绑定 input[data-number-keyboard]。键盘默认尺寸 463 * 552,包含 0-9、.、退格和确认按键,适合工业触屏、收银输入等场景。
特性
- 单例可见:同一时刻最多只显示一个键盘实例
- 悬浮布局:按输入框位置自动上下避让并做视窗边缘钳制
- 键盘输入:数字、小数点、退格
- 确认回调:支持在确认键触发时通知外层环境
- 无第三方依赖:仅用 Vue + TypeScript + CSS 实现
Props
modelValue?: string- 初始值(默认空字符串)disabled?: boolean- 是否禁用allowDecimal?: boolean- 是否允许输入小数点(默认true)maxLength?: number- 最大输入长度(默认16)confirmText?: string- 确认键文案(默认确认)autoBind?: boolean- 是否自动绑定输入框(默认true)targetSelector?: string- 自动绑定选择器(默认input[data-number-keyboard])
Events
update:modelValue- 值变化时触发confirm(value, target)- 点击确认键时触发(可作为回调通知)open(target)- 键盘展开时触发close- 键盘收起时触发
暴露方法(可选,手动控制时使用)
open(targetInput, initialValue?)- 绑定并打开到任意输入框close()- 关闭键盘updatePosition()- 触发重定位isOpen- 当前是否展开
示例(最少代码,推荐)
<script setup lang="ts">
import { ref } from 'vue'
import { NumberKeyboard } from 'shiftui'
const amount = ref('')
</script>
<template>
<input v-model="amount" data-number-keyboard readonly inputmode="none" placeholder="点击输入金额" />
<NumberKeyboard :allow-decimal="true" :max-length="12" />
</template>示例(手动调用 open)
<script setup lang="ts">
import { ref } from 'vue'
import { NumberKeyboard } from 'shiftui'
const amount = ref('')
type NumberKeyboardInstance = {
open: (target: HTMLInputElement, initialValue?: string) => void
}
const keyboardRef = ref<NumberKeyboardInstance | null>(null)
const openKeyboardForInput = (event: FocusEvent | MouseEvent) => {
const target = event.target
if (target instanceof HTMLInputElement) {
keyboardRef.value?.open(target)
}
}
</script>
<template>
<input v-model="amount" readonly inputmode="none" @focus="openKeyboardForInput" @click="openKeyboardForInput" />
<NumberKeyboard ref="keyboardRef" :auto-bind="false" />
</template>本地开发
npm install
npm run dev构建组件库
npm run build构建后产物位于 dist/,包含:
shiftui.js(ESM)shiftui.umd.cjs(UMD/CJS)shiftui.css(样式)index.d.ts(类型声明)
发布到 npm
npm run build
npm login
npm publish --access public发布前请确认
package.json中的name与版本号是否符合你的计划。
