v-uni-app-ui 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/config/css/basic.scss +19 -0
- package/components/config/interface/basic-type.ts +17 -0
- package/components/config/interface/components-interface.ts +0 -0
- package/components/config/interface/monitor/components/input-monitor.js +0 -0
- package/components/config/interface/monitor/property-monitor.ts +136 -0
- package/components/config/interface/props/basic-props.ts +88 -0
- package/components/config/interface/props/components/button-props.ts +85 -0
- package/components/config/interface/props/components/input-props.ts +97 -0
- package/components/config/interface/props/components/uni-input-props.ts +30 -0
- package/components/config/interface/props/props-tools.ts +64 -0
- package/components/config/style/basic.js +346 -0
- package/components/config/style/component-registry.js +137 -0
- package/components/config/style/components/button-style.js +155 -0
- package/components/config/style/components/input-style.js +99 -0
- package/components/config/style/components/uni-input-style.js +93 -0
- package/components/config/style/components-style.js +619 -0
- package/components/config/style/property-mapper.js +372 -0
- package/components/config/style/pseudo-processor.js +212 -0
- package/components/config/style/skip-props.js +34 -0
- package/components/config.js +123 -0
- package/components/icon/iconfont.css +86 -0
- package/components/icon/iconfont.js +1 -0
- package/components/icon/iconfont.json +135 -0
- package/components/icon/iconfont.ttf +0 -0
- package/components/icon/iconfont.woff +0 -0
- package/components/icon/iconfont.woff2 +0 -0
- package/components/layout/v-card/v-card.vue +108 -0
- package/components/layout/v-grid/v-grid.vue +162 -0
- package/components/layout/v-icon-grid/v-icon-grid.vue +195 -0
- package/components/layout/v-infinite-scroll/v-infinite-scroll.vue +172 -0
- package/components/layout/v-list/v-list.vue +43 -0
- package/components/layout/v-row/v-row.vue +142 -0
- package/components/layout/v-waterfall/v-waterfall.vue +79 -0
- package/components/model/compound/v-checkbox-group/v-checkbox-group.vue +96 -0
- package/components/model/compound/v-console/v-console.js +20 -0
- package/components/model/compound/v-console/v-console.vue +299 -0
- package/components/model/compound/v-date-time/v-date-time.vue +261 -0
- package/components/model/compound/v-dialog/v-dialog.vue +178 -0
- package/components/model/compound/v-drum-select-picker/v-drum-select-picker.vue +83 -0
- package/components/model/compound/v-form/v-form.vue +226 -0
- package/components/model/compound/v-form-item/v-form-item.vue +255 -0
- package/components/model/compound/v-image/v-image.vue +357 -0
- package/components/model/compound/v-input-desensitize/v-input-desensitize.vue +101 -0
- package/components/model/compound/v-page/v-page.vue +11 -0
- package/components/model/compound/v-pages/v-pages.vue +141 -0
- package/components/model/compound/v-picker-list/v-picker-list.vue +109 -0
- package/components/model/compound/v-popup/v-popup.vue +151 -0
- package/components/model/compound/v-radio-group/v-radio-group.vue +86 -0
- package/components/model/compound/v-select-picker/v-select-picker.vue +202 -0
- package/components/model/compound/v-series-picker-list/v-series-picker-list.vue +221 -0
- package/components/model/compound/v-series-select-picker/v-series-select-picker.vue +203 -0
- package/components/model/compound/v-switch/v-switch.vue +136 -0
- package/components/model/compound/v-tabs-page/v-tabs-page.vue +138 -0
- package/components/model/native/v-badge/v-badge.vue +143 -0
- package/components/model/native/v-button/v-button.vue +81 -0
- package/components/model/native/v-carousel/v-carousel.vue +138 -0
- package/components/model/native/v-checkbox/v-checkbox.vue +215 -0
- package/components/model/native/v-collapse/v-collapse.vue +190 -0
- package/components/model/native/v-header-navigation-bar/v-header-navigation-bar.vue +92 -0
- package/components/model/native/v-input/v-input.vue +276 -0
- package/components/model/native/v-input/v-uni-input.vue +119 -0
- package/components/model/native/v-input-code/v-input-code.vue +146 -0
- package/components/model/native/v-loading/v-loading.vue +206 -0
- package/components/model/native/v-menu/v-menu.vue +222 -0
- package/components/model/native/v-menu-slide/v-menu-slide.vue +364 -0
- package/components/model/native/v-min-loading/v-min-loading.vue +80 -0
- package/components/model/native/v-null/v-null.vue +97 -0
- package/components/model/native/v-overlay/v-overlay.vue +96 -0
- package/components/model/native/v-pull-up-refresh/v-pull-up-refresh.vue +157 -0
- package/components/model/native/v-radio/v-radio.vue +138 -0
- package/components/model/native/v-scroll-list/v-scroll-list.vue +169 -0
- package/components/model/native/v-steps/v-steps.vue +253 -0
- package/components/model/native/v-table/v-table.vue +203 -0
- package/components/model/native/v-tabs/v-tabs.vue +235 -0
- package/components/model/native/v-tag/v-tag.vue +206 -0
- package/components/model/native/v-text/v-text.vue +187 -0
- package/components/model/native/v-textarea/v-textarea.vue +178 -0
- package/components/model/native/v-title/v-title.vue +91 -0
- package/components/model/native/v-toast/info.png +0 -0
- package/components/model/native/v-toast/success.png +0 -0
- package/components/model/native/v-toast/v-toast.vue +198 -0
- package/components/model/native/v-toast/warn.png +0 -0
- package/components/model/native/v-upload-file-button/v-upload-file-button.vue +296 -0
- package/components/model/native/v-video/v-video.vue +175 -0
- package/components/model/native/v-window/v-window.vue +158 -0
- package/components/utils/event-modifiers.ts +139 -0
- package/components/utils/validator.ts +451 -0
- package/index.js +221 -0
- package/package.json +8 -13
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.loading-icon {
|
|
2
|
+
margin: 0 8rpx 0 0;
|
|
3
|
+
.spinner {
|
|
4
|
+
width: 20rpx;
|
|
5
|
+
height: 20rpx;
|
|
6
|
+
border: 1rpx solid;
|
|
7
|
+
border-radius: 50%;
|
|
8
|
+
border-top-color: white;
|
|
9
|
+
animation: spin 1s ease-in-out infinite;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@keyframes spin {
|
|
16
|
+
to {
|
|
17
|
+
transform: rotate(360deg);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// 基础类型定义
|
|
2
|
+
export type BasicType = 'default' | 'delete' | 'success' | 'info' | 'warning'
|
|
3
|
+
export type BasicSize = 'small' | 'medium' | 'large'
|
|
4
|
+
export type BasicDetailedSize = 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large'
|
|
5
|
+
export type BasicShape = 'semicircle' | 'square' | 'round'
|
|
6
|
+
export type BasicHorizontallyPosition = 'left' | 'right' | 'center'
|
|
7
|
+
export type BasicVerticalPosition = 'top' | 'bottom' | 'center'
|
|
8
|
+
export type BasicPosition = 'left' | 'right' | 'top' | 'bottom' | 'center'
|
|
9
|
+
|
|
10
|
+
// 交互类型
|
|
11
|
+
export type InteractionMode = 'hover' | 'active' | 'focus' | 'disabled'
|
|
12
|
+
|
|
13
|
+
//组件类型定义
|
|
14
|
+
export type ButtonShape = 'default' | 'none' | 'circle'
|
|
15
|
+
export type InputType = 'text' | 'id' | 'safe-password' | 'password' | 'number' | 'digit' | 'numeric' | 'decimal' |
|
|
16
|
+
'email' | 'phone' | 'url' | 'textarea' | 'name' | 'search' | 'none'
|
|
17
|
+
export type validateTriggerType = 'input' | 'blur' | 'change'
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { watch, onUnmounted, WatchStopHandle, WatchSource, Ref } from 'vue';
|
|
2
|
+
|
|
3
|
+
type EmitFn = (event: string, ...args: any[]) => void;
|
|
4
|
+
|
|
5
|
+
interface MonitorOptions<T = any> {
|
|
6
|
+
deep?: boolean;
|
|
7
|
+
immediate?: boolean;
|
|
8
|
+
onChange?: (newValue: T, oldValue: T) => void;
|
|
9
|
+
emitEvent?: string;
|
|
10
|
+
lazy?: boolean;
|
|
11
|
+
enabled?: Ref<boolean>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface MonitorInstance extends WatchStopHandle {
|
|
15
|
+
start: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface BaseConfig<T = any> extends MonitorOptions<T> {
|
|
19
|
+
propertyName: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface PropsConfig<T = any> extends BaseConfig<T> {
|
|
23
|
+
source?: never; // 明确禁止source
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface SourceConfig<T = any> extends BaseConfig<T> {
|
|
27
|
+
source: WatchSource<T>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type ConfigItem<T = any> = PropsConfig<T> | SourceConfig<T>;
|
|
31
|
+
|
|
32
|
+
function isSourceConfig<T = any>(config: ConfigItem<T>): config is SourceConfig<T> {
|
|
33
|
+
return 'source' in config && config.source !== undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function usePropertyMonitor<T = any>(props: Record<string, any>, propertyName: string, emit: EmitFn, options?: MonitorOptions<T>): MonitorInstance;
|
|
37
|
+
|
|
38
|
+
export function usePropertyMonitor<T = any>(config: SourceConfig<T>, emit: EmitFn): MonitorInstance;
|
|
39
|
+
|
|
40
|
+
export function usePropertyMonitor<T = any>(configs: ConfigItem<T>[], emit: EmitFn): MonitorInstance;
|
|
41
|
+
|
|
42
|
+
export function usePropertyMonitor<T = any>(
|
|
43
|
+
propsOrConfigs: any,
|
|
44
|
+
propertyNameOrEmit: string | EmitFn,
|
|
45
|
+
emitOrOptions?: EmitFn | MonitorOptions<T>,
|
|
46
|
+
options?: MonitorOptions<T>
|
|
47
|
+
): MonitorInstance {
|
|
48
|
+
// 参数解析
|
|
49
|
+
const isBatch = Array.isArray(propsOrConfigs);
|
|
50
|
+
const emitFn = typeof propertyNameOrEmit === 'function' ? propertyNameOrEmit : (emitOrOptions as EmitFn);
|
|
51
|
+
|
|
52
|
+
const configs: ConfigItem<T>[] = [];
|
|
53
|
+
|
|
54
|
+
if (isBatch) {
|
|
55
|
+
configs.push(...propsOrConfigs);
|
|
56
|
+
} else if (typeof propsOrConfigs === 'object' && !('source' in propsOrConfigs)) {
|
|
57
|
+
// Props模式:提取 propertyName 和 options
|
|
58
|
+
const propertyName = propertyNameOrEmit as string;
|
|
59
|
+
const monitorOptions = typeof emitOrOptions === 'function' ? options : (emitOrOptions as MonitorOptions<T>);
|
|
60
|
+
|
|
61
|
+
configs.push({
|
|
62
|
+
propertyName,
|
|
63
|
+
...(monitorOptions || {})
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
// 单配置模式
|
|
67
|
+
configs.push(propsOrConfigs as ConfigItem<T>);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let stopHandles: WatchStopHandle[] = [];
|
|
71
|
+
let started = false;
|
|
72
|
+
|
|
73
|
+
const createWatchers = () => {
|
|
74
|
+
if (stopHandles.length) {
|
|
75
|
+
stopHandles.forEach((stop) => stop());
|
|
76
|
+
stopHandles = [];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
configs.forEach((config) => {
|
|
80
|
+
const { propertyName, onChange, emitEvent, enabled, ...watchOpts } = config;
|
|
81
|
+
|
|
82
|
+
const shouldWatch = enabled ? enabled.value : true;
|
|
83
|
+
if (!shouldWatch) return;
|
|
84
|
+
|
|
85
|
+
const watchSource = isSourceConfig(config) ? config.source : () => (propsOrConfigs as Record<string, any>)[propertyName!];
|
|
86
|
+
|
|
87
|
+
const stop = watch(
|
|
88
|
+
watchSource,
|
|
89
|
+
(newValue, oldValue) => {
|
|
90
|
+
onChange?.(newValue, oldValue);
|
|
91
|
+
emitFn(emitEvent ?? `update:${propertyName}`, newValue);
|
|
92
|
+
},
|
|
93
|
+
watchOpts
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
stopHandles.push(stop);
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// 监听enabled变化
|
|
101
|
+
configs.forEach((config) => {
|
|
102
|
+
if (config.enabled) {
|
|
103
|
+
watch(
|
|
104
|
+
config.enabled,
|
|
105
|
+
() => {
|
|
106
|
+
if (started) {
|
|
107
|
+
createWatchers();
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{ immediate: false }
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const start = () => {
|
|
116
|
+
if (!started) {
|
|
117
|
+
started = true;
|
|
118
|
+
createWatchers();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const stop = () => {
|
|
123
|
+
stopHandles.forEach((handle) => handle());
|
|
124
|
+
stopHandles = [];
|
|
125
|
+
started = false;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const isLazy = configs.some((c) => c.lazy);
|
|
129
|
+
if (!isLazy) {
|
|
130
|
+
start();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
onUnmounted(stop);
|
|
134
|
+
|
|
135
|
+
return Object.assign(stop, { start });
|
|
136
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// 简化 BasicPropsDefinition 类型
|
|
2
|
+
type VuePropDefinition = {
|
|
3
|
+
type: any;
|
|
4
|
+
default?: any;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
validator?: (value: any) => boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 通用组件基础 props 定义
|
|
11
|
+
* 所有组件都会自动继承这些 props
|
|
12
|
+
*/
|
|
13
|
+
export const BasicProps = {
|
|
14
|
+
id: {
|
|
15
|
+
type: String,
|
|
16
|
+
default: ''
|
|
17
|
+
},
|
|
18
|
+
className: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: ''
|
|
21
|
+
},
|
|
22
|
+
boxStyle: {
|
|
23
|
+
type: Object,
|
|
24
|
+
default: () => ({})
|
|
25
|
+
},
|
|
26
|
+
style: {
|
|
27
|
+
type: Object,
|
|
28
|
+
default: () => ({})
|
|
29
|
+
},
|
|
30
|
+
accessibility:{
|
|
31
|
+
type:Object,
|
|
32
|
+
default:()=>({})
|
|
33
|
+
}
|
|
34
|
+
} as const;
|
|
35
|
+
|
|
36
|
+
// 获取基础属性的键名类型
|
|
37
|
+
type BasicPropsKeys = keyof typeof BasicProps;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 创建扩展基础 props 的验证器
|
|
41
|
+
*/
|
|
42
|
+
export function extendWithBasicProps<T extends Record<string, VuePropDefinition>>(
|
|
43
|
+
componentProps: T,
|
|
44
|
+
options: {
|
|
45
|
+
exclude?: BasicPropsKeys[];
|
|
46
|
+
override?: Partial<Record<BasicPropsKeys, any>>;
|
|
47
|
+
} = {}
|
|
48
|
+
): Record<string, VuePropDefinition> {
|
|
49
|
+
const { exclude = [], override = {} } = options;
|
|
50
|
+
const mergedProps: Record<string, VuePropDefinition> = {};
|
|
51
|
+
|
|
52
|
+
// 添加基础 props
|
|
53
|
+
Object.entries(BasicProps).forEach(([key, value]) => {
|
|
54
|
+
if (!exclude.includes(key as BasicPropsKeys)) {
|
|
55
|
+
const propKey = key as BasicPropsKeys;
|
|
56
|
+
if (override[propKey] !== undefined) {
|
|
57
|
+
// 修复:正确处理覆盖值
|
|
58
|
+
mergedProps[key] = {
|
|
59
|
+
...value,
|
|
60
|
+
default: typeof override[propKey] === 'object' && override[propKey] !== null && 'default' in override[propKey] ? override[propKey].default : override[propKey]
|
|
61
|
+
};
|
|
62
|
+
} else {
|
|
63
|
+
mergedProps[key] = value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// 添加组件特定 props
|
|
69
|
+
Object.entries(componentProps).forEach(([key, value]) => {
|
|
70
|
+
mergedProps[key] = value;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return mergedProps;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 从 props 配置中提取类型
|
|
78
|
+
*/
|
|
79
|
+
export type ExtractPropTypes<T> = {
|
|
80
|
+
[K in keyof T]: T[K] extends { type: any } ? (T[K] extends { default?: infer D } ? (D extends () => infer R ? R : D) : any) : any;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 创建 Vue 兼容的 props 定义
|
|
85
|
+
*/
|
|
86
|
+
export function createVueProps<T extends Record<string, VuePropDefinition>>(props: T): T {
|
|
87
|
+
return props;
|
|
88
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { PropType } from 'vue';
|
|
2
|
+
import { extendWithBasicProps, ExtractPropTypes } from '@/components/config/interface/props/basic-props';
|
|
3
|
+
import { BasicType, ButtonShape, BasicSize } from '@/components/config/interface/basic-type.js';
|
|
4
|
+
import { Validators } from '@/components/utils/validator';
|
|
5
|
+
import { PropTools } from '@/components/config/interface/props/props-tools';
|
|
6
|
+
/**
|
|
7
|
+
* 按钮组件 props 定义
|
|
8
|
+
*/
|
|
9
|
+
const buttonProps = extendWithBasicProps(
|
|
10
|
+
{
|
|
11
|
+
//使用PropTools简写
|
|
12
|
+
shape: PropTools.enum<ButtonShape>(['default', 'none', 'circle'], 'default', 'buttonShape'),
|
|
13
|
+
type: {
|
|
14
|
+
type: String as PropType<BasicType>,
|
|
15
|
+
default: 'default',
|
|
16
|
+
validator: Validators.enum(['default', 'success', 'warning', 'info', 'delete'], 'buttonType')
|
|
17
|
+
},
|
|
18
|
+
size: PropTools.enum<BasicSize>(['small', 'medium', 'large'], 'medium', 'buttonSize'),
|
|
19
|
+
disabled: PropTools.boolean(false),
|
|
20
|
+
loading: PropTools.boolean(false),
|
|
21
|
+
plain: PropTools.boolean(false),
|
|
22
|
+
text: PropTools.boolean(false),
|
|
23
|
+
stabilizationTime: {
|
|
24
|
+
type: Number,
|
|
25
|
+
default: 0,
|
|
26
|
+
validator: Validators.numberRange(0, 1_000_000, 'Stabilization time must be between 0 and 1,000,000 ms.')
|
|
27
|
+
},
|
|
28
|
+
debounceTime: {
|
|
29
|
+
type: Number,
|
|
30
|
+
default: 0,
|
|
31
|
+
validator: Validators.numberRange(0, 1_000_000, 'The anti-shake waiting time must be between 0 and 1,000,000 milliseconds.')
|
|
32
|
+
},
|
|
33
|
+
intervalUpdateTime: {
|
|
34
|
+
type: Number,
|
|
35
|
+
default: 1000,
|
|
36
|
+
validator: Validators.numberRange(100, 100_000, 'Interval must be between 100 and 100,000 ms.')
|
|
37
|
+
},
|
|
38
|
+
degressionTime: {
|
|
39
|
+
type: Number,
|
|
40
|
+
default: 1000,
|
|
41
|
+
validator: Validators.numberRange(100, 10_000, 'Degression time must be between 100 and 10,000 ms.')
|
|
42
|
+
},
|
|
43
|
+
resetOnClick: PropTools.boolean(false),
|
|
44
|
+
hoverStartTime: {
|
|
45
|
+
type: Number,
|
|
46
|
+
default: 20,
|
|
47
|
+
validator: Validators.numberRange(10, 10_000, 'hover start time must be between 10 and 10,000 ms.')
|
|
48
|
+
},
|
|
49
|
+
hoverStayTime: {
|
|
50
|
+
type: Number,
|
|
51
|
+
default: 70,
|
|
52
|
+
validator: Validators.numberRange(10, 10_000, 'hover stay time must be between 10 and 10,000 ms.')
|
|
53
|
+
},
|
|
54
|
+
//组合校验
|
|
55
|
+
// customProp: {
|
|
56
|
+
// type: String,
|
|
57
|
+
// default: '',
|
|
58
|
+
// validator: Validators.combine(
|
|
59
|
+
// Validators.required('This field is required.'),
|
|
60
|
+
// Validators.length(3, 20, 'Length must be 3-20 characters.'),
|
|
61
|
+
// Validators.pattern(/^[a-zA-Z0-9_]+$/, 'Only letters, numbers and underscore are allowed.')
|
|
62
|
+
// )
|
|
63
|
+
// }
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
override: {
|
|
67
|
+
id: {
|
|
68
|
+
default: 'VButton'
|
|
69
|
+
},
|
|
70
|
+
className: {
|
|
71
|
+
default: 'v-button'
|
|
72
|
+
},
|
|
73
|
+
boxStyle: {
|
|
74
|
+
default: {
|
|
75
|
+
width: 'auto',
|
|
76
|
+
height: '50rpx',
|
|
77
|
+
padding: '14rpx 2rpx'
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
accessibility: {}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
export default buttonProps;
|
|
85
|
+
export type ButtonProps = ExtractPropTypes<typeof buttonProps>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { extendWithBasicProps, ExtractPropTypes } from '@/components/config/interface/props/basic-props';
|
|
2
|
+
import {
|
|
3
|
+
InputType,
|
|
4
|
+
BasicSize,
|
|
5
|
+
BasicHorizontallyPosition,
|
|
6
|
+
validateTriggerType
|
|
7
|
+
} from '@/components/config/interface/basic-type';
|
|
8
|
+
import { Validators } from '@/components/utils/validator';
|
|
9
|
+
import { PropTools } from '@/components/config/interface/props/props-tools';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 文本框组件 props 定义
|
|
13
|
+
*/
|
|
14
|
+
const inputProps = extendWithBasicProps(
|
|
15
|
+
{
|
|
16
|
+
value: PropTools.string(),
|
|
17
|
+
size: PropTools.enum<BasicSize>(['small', 'medium', 'large'], 'medium', 'inputSize'),
|
|
18
|
+
placeholder: PropTools.array(),
|
|
19
|
+
placeholderStyle: PropTools.object(),
|
|
20
|
+
placeholderTimeNumber: {
|
|
21
|
+
type: Number,
|
|
22
|
+
default: 0,
|
|
23
|
+
validator: Validators.numberRange(
|
|
24
|
+
0,
|
|
25
|
+
1_000_000,
|
|
26
|
+
'The prompt switching time must be between 0 and 1,000,000 milliseconds.'
|
|
27
|
+
)
|
|
28
|
+
},
|
|
29
|
+
maxlength: {
|
|
30
|
+
type: Number,
|
|
31
|
+
default: 150,
|
|
32
|
+
validator: Validators.numberRange(-1, 1_0000_0000, 'maxlength must be between -1 and 100,000,000.')
|
|
33
|
+
},
|
|
34
|
+
disabled: PropTools.boolean(false),
|
|
35
|
+
type: PropTools.enum<InputType>(
|
|
36
|
+
[
|
|
37
|
+
'text',
|
|
38
|
+
'id',
|
|
39
|
+
'safe-password',
|
|
40
|
+
'password',
|
|
41
|
+
'number',
|
|
42
|
+
'digit',
|
|
43
|
+
'numeric',
|
|
44
|
+
'decimal',
|
|
45
|
+
'email',
|
|
46
|
+
'phone',
|
|
47
|
+
'url',
|
|
48
|
+
'textarea',
|
|
49
|
+
'name',
|
|
50
|
+
'search',
|
|
51
|
+
'none'
|
|
52
|
+
],
|
|
53
|
+
'text',
|
|
54
|
+
'inputType'
|
|
55
|
+
),
|
|
56
|
+
isWordCounter: PropTools.boolean(false),
|
|
57
|
+
textPosition: PropTools.enum<BasicHorizontallyPosition>(
|
|
58
|
+
['left', 'right', 'center'],
|
|
59
|
+
'left',
|
|
60
|
+
'inputTextPosition'
|
|
61
|
+
),
|
|
62
|
+
focus: PropTools.boolean(false),
|
|
63
|
+
validators: PropTools.string(),
|
|
64
|
+
validateTrigger: PropTools.enum<validateTriggerType>(['input', 'blur', 'change'], 'input', 'validateTrigger'),
|
|
65
|
+
selectionStart: {
|
|
66
|
+
type: Number,
|
|
67
|
+
default: -1,
|
|
68
|
+
validator: Validators.numberRange(-1, 10_000, 'selection start must be between -1 and 10,000 milliseconds.')
|
|
69
|
+
},
|
|
70
|
+
isIcon: PropTools.boolean(false),
|
|
71
|
+
selectionEnd: {
|
|
72
|
+
type: Number,
|
|
73
|
+
default: -1,
|
|
74
|
+
validator: Validators.numberRange(-1, 10_000, 'selection end must be between -1 and 10,000 milliseconds.')
|
|
75
|
+
},
|
|
76
|
+
randomNumber: PropTools.boolean(false),
|
|
77
|
+
cursorColor: PropTools.string(),
|
|
78
|
+
autoBlur: PropTools.boolean(false),
|
|
79
|
+
cursorSpacing: PropTools.number(0),
|
|
80
|
+
autocomplete: PropTools.boolean(true),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
override: {
|
|
84
|
+
id: {
|
|
85
|
+
default: 'VInput'
|
|
86
|
+
},
|
|
87
|
+
className: {
|
|
88
|
+
default: 'v-input'
|
|
89
|
+
},
|
|
90
|
+
boxStyle: {
|
|
91
|
+
default: {}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
export default inputProps;
|
|
97
|
+
export type inputProps = ExtractPropTypes<typeof inputProps>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ExtractPropTypes } from '@/components/config/interface/props/basic-props';
|
|
2
|
+
import { PropTools } from '@/components/config/interface/props/props-tools';
|
|
3
|
+
import { Validators } from '@/components/utils/validator';
|
|
4
|
+
import { BasicSize, BasicHorizontallyPosition } from '@/components/config/interface/basic-type';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* uni-input 包装组件 props 定义
|
|
8
|
+
*/
|
|
9
|
+
const uniInputProps = {
|
|
10
|
+
value: PropTools.string(),
|
|
11
|
+
type: PropTools.string('text'),
|
|
12
|
+
size: PropTools.enum<BasicSize>(['small', 'medium', 'large'], 'medium', 'inputSize'),
|
|
13
|
+
placeholder: PropTools.string(),
|
|
14
|
+
fontStyle: PropTools.object(),
|
|
15
|
+
placeholderStyle: PropTools.object(),
|
|
16
|
+
placeholderClass: PropTools.string(),
|
|
17
|
+
disabled: PropTools.boolean(false),
|
|
18
|
+
maxlength: {
|
|
19
|
+
type: Number,
|
|
20
|
+
default: -1,
|
|
21
|
+
validator: Validators.numberRange(-1, 1_0000_0000, 'maxlength must be between -1 and 100,000,000.')
|
|
22
|
+
},
|
|
23
|
+
autocomplete: PropTools.boolean(false),
|
|
24
|
+
focus: PropTools.boolean(false),
|
|
25
|
+
textPosition: PropTools.enum<BasicHorizontallyPosition>(['left', 'right', 'center'], 'left', 'inputTextPosition'),
|
|
26
|
+
isAppPlus: PropTools.boolean(false)
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default uniInputProps;
|
|
30
|
+
export type UniInputProps = ExtractPropTypes<typeof uniInputProps>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Validators } from '@/components/utils/validator';
|
|
2
|
+
|
|
3
|
+
// 简化类型定义
|
|
4
|
+
type SimplePropDefinition = {
|
|
5
|
+
type: any;
|
|
6
|
+
default?: any;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
validator?: (value: any) => boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// 简化的属性创建函数
|
|
12
|
+
export function createProp<T>(type: any, defaultValue?: T, validator?: (value: any) => boolean): SimplePropDefinition {
|
|
13
|
+
const prop: SimplePropDefinition = { type };
|
|
14
|
+
|
|
15
|
+
if (defaultValue !== undefined) {
|
|
16
|
+
prop.default = defaultValue;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (validator) {
|
|
20
|
+
prop.validator = validator;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return prop;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 快捷方法
|
|
27
|
+
export const PropTools = {
|
|
28
|
+
// 基础类型
|
|
29
|
+
string: (defaultValue: string = '', validator?: (value: string) => boolean) => createProp(String, defaultValue, validator),
|
|
30
|
+
|
|
31
|
+
number: (defaultValue: number = 0, validator?: (value: number) => boolean) => createProp(Number, defaultValue, validator),
|
|
32
|
+
|
|
33
|
+
boolean: (defaultValue: boolean = false) => createProp(Boolean, defaultValue),
|
|
34
|
+
|
|
35
|
+
array: <T>(defaultValue: T[] = []) => createProp(Array, () => defaultValue),
|
|
36
|
+
|
|
37
|
+
object: <T extends Record<string, any>>(defaultValue: T = {} as T) => createProp(Object, () => defaultValue),
|
|
38
|
+
|
|
39
|
+
function: <T extends Function>(defaultValue?: T) => createProp(Function, defaultValue),
|
|
40
|
+
|
|
41
|
+
// 枚举类型
|
|
42
|
+
enum: <T extends string>(allowedValues: readonly T[], defaultValue: T, displayName?: string) =>
|
|
43
|
+
createProp(String, defaultValue, Validators.enum(allowedValues, `${displayName || '属性'}必须是以下值之一: ${allowedValues.join(', ')}`)),
|
|
44
|
+
|
|
45
|
+
// 任意类型
|
|
46
|
+
any: (defaultValue: any = null) => createProp(null, defaultValue),
|
|
47
|
+
|
|
48
|
+
// 常用属性
|
|
49
|
+
id: () => createProp(String, ''),
|
|
50
|
+
className: () => createProp(String, ''),
|
|
51
|
+
style: () => createProp(Object, () => ({})),
|
|
52
|
+
|
|
53
|
+
// 带验证的属性
|
|
54
|
+
stringLength: (defaultValue: string = '', min?: number, max?: number) => createProp(String, defaultValue, Validators.length(min, max)),
|
|
55
|
+
|
|
56
|
+
numberRange: (defaultValue: number, min: number, max: number) => createProp(Number, defaultValue, Validators.numberRange(min, max)),
|
|
57
|
+
|
|
58
|
+
// 格式验证
|
|
59
|
+
email: (defaultValue: string = '') => createProp(String, defaultValue, Validators.email()),
|
|
60
|
+
|
|
61
|
+
phoneNumber: (defaultValue: string = '') => createProp(String, defaultValue, Validators.phoneNumber()),
|
|
62
|
+
|
|
63
|
+
url: (defaultValue: string = '') => createProp(String, defaultValue, Validators.url())
|
|
64
|
+
};
|