@zfqh/uview-x 0.0.6 → 0.0.7
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/CHANGELOG.md +8 -0
- package/README.md +52 -9
- package/components/uv-badge/uv-badge.vue +4 -4
- package/components/uv-button/uv-button.vue +10 -10
- package/components/uv-checkbox/uv-checkbox.vue +11 -9
- package/components/uv-checkbox-group/uv-checkbox-group.vue +2 -2
- package/components/uv-code/uv-code.vue +2 -2
- package/components/uv-dialog/uv-dialog.vue +11 -10
- package/components/uv-form/uv-form.vue +244 -246
- package/components/uv-form-item/uv-form-item.vue +10 -9
- package/components/uv-icon/uv-icon.vue +13 -13
- package/components/uv-input/uv-input.vue +6 -5
- package/components/uv-line/uv-line.vue +7 -6
- package/components/uv-line-progress/uv-line-progress.vue +5 -5
- package/components/uv-loading-icon/uv-loading-icon.vue +9 -8
- package/components/uv-overlay/uv-overlay.vue +3 -2
- package/components/uv-popup/uv-popup.vue +7 -5
- package/components/uv-safe-bottom/uv-safe-bottom.vue +4 -3
- package/components/uv-status-bar/uv-status-bar.vue +4 -3
- package/components/uv-tabs/uv-tabs.vue +15 -12
- package/components/uv-transition/uv-transition.vue +2 -2
- package/hooks/index.ts +5 -5
- package/hooks/useDebounce.ts +33 -35
- package/hooks/useI18n.ts +4 -3
- package/hooks/useThrottle.ts +36 -38
- package/index.ts +50 -29
- package/locales/en.ts +56 -0
- package/locales/es.ts +57 -0
- package/locales/fr.ts +57 -0
- package/locales/index.ts +15 -159
- package/locales/ru.ts +57 -0
- package/locales/zh-Hans.ts +57 -0
- package/locales/zh-Hant.ts +57 -0
- package/package.json +2 -2
- package/types/index.d.ts +68 -59
- package/utils/color.ts +139 -0
- package/utils/compress.ts +28 -28
- package/utils/config.ts +45 -10
- package/utils/debounce.ts +4 -4
- package/utils/function.ts +2 -87
- package/utils/locale.ts +444 -270
- package/utils/merge.ts +74 -0
- package/utils/platform.ts +28 -28
- package/utils/route.ts +123 -129
- package/utils/scrollbar.ts +19 -19
- package/utils/throttle.ts +4 -4
- package/locales/en-US.ts +0 -79
- package/locales/es-ES.ts +0 -79
- package/locales/fr-FR.ts +0 -79
- package/locales/ru-RU.ts +0 -79
- package/locales/zh-CN.ts +0 -79
- package/locales/zh-TW.ts +0 -79
- package/utils/colorGradient.ts +0 -139
- package/utils/index.ts +0 -58
package/utils/merge.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通用对象深拷贝 / 深合并工具。
|
|
3
|
+
*
|
|
4
|
+
* 独立成模块,避免 `utils/config.ts` 与 `utils/function.ts` 之间产生循环依赖。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @description 深度克隆
|
|
9
|
+
* @param {object} obj 需要深度克隆的对象
|
|
10
|
+
* @param cache 缓存
|
|
11
|
+
* @returns {*} 克隆后的对象或者原值(不是对象)
|
|
12
|
+
*/
|
|
13
|
+
export function deepClone<T>(obj: T, cache: WeakMap<object, any> = new WeakMap()): T {
|
|
14
|
+
if (obj === null || typeof obj !== 'object') return obj;
|
|
15
|
+
if (cache.has(obj)) return cache.get(obj);
|
|
16
|
+
let clone;
|
|
17
|
+
if (obj instanceof Date) {
|
|
18
|
+
clone = new Date(obj.getTime());
|
|
19
|
+
} else if (obj instanceof RegExp) {
|
|
20
|
+
clone = new RegExp(obj);
|
|
21
|
+
} else if (obj instanceof Map) {
|
|
22
|
+
clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
|
|
23
|
+
} else if (obj instanceof Set) {
|
|
24
|
+
clone = new Set(Array.from(obj, (value) => deepClone(value, cache)));
|
|
25
|
+
} else if (Array.isArray(obj)) {
|
|
26
|
+
clone = obj.map((value) => deepClone(value, cache));
|
|
27
|
+
} else if (Object.prototype.toString.call(obj) === '[object Object]') {
|
|
28
|
+
clone = Object.create(Object.getPrototypeOf(obj));
|
|
29
|
+
cache.set(obj, clone);
|
|
30
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
31
|
+
clone[key] = deepClone(value, cache);
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
clone = Object.assign({}, obj);
|
|
35
|
+
}
|
|
36
|
+
cache.set(obj, clone);
|
|
37
|
+
return clone;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @description JS对象深度合并
|
|
42
|
+
* @param {object} target 需要拷贝的对象
|
|
43
|
+
* @param {object} source 拷贝的来源对象
|
|
44
|
+
* @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
|
|
45
|
+
*/
|
|
46
|
+
export function deepMerge<T extends object>(target: T = {} as T, source: Partial<T> = {}): T {
|
|
47
|
+
target = deepClone(target);
|
|
48
|
+
if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
|
|
49
|
+
const merged: Record<string, any> = Array.isArray(target)
|
|
50
|
+
? (target.slice() as unknown as Record<string, any>)
|
|
51
|
+
: Object.assign({}, target);
|
|
52
|
+
const sourceRecord = source as Record<string, any>;
|
|
53
|
+
for (const prop in sourceRecord) {
|
|
54
|
+
if (!Object.prototype.hasOwnProperty.call(sourceRecord, prop)) continue;
|
|
55
|
+
const sourceValue = sourceRecord[prop];
|
|
56
|
+
const targetValue = merged[prop];
|
|
57
|
+
if (sourceValue instanceof Date) {
|
|
58
|
+
merged[prop] = new Date(sourceValue);
|
|
59
|
+
} else if (sourceValue instanceof RegExp) {
|
|
60
|
+
merged[prop] = new RegExp(sourceValue);
|
|
61
|
+
} else if (sourceValue instanceof Map) {
|
|
62
|
+
merged[prop] = new Map(sourceValue);
|
|
63
|
+
} else if (sourceValue instanceof Set) {
|
|
64
|
+
merged[prop] = new Set(sourceValue);
|
|
65
|
+
} else if (typeof sourceValue === 'object' && sourceValue !== null) {
|
|
66
|
+
// 目标是原始值 / null 时,用对象源替换;避免 `false`、`undefined` 等无法被深合并
|
|
67
|
+
const mergedTarget = typeof targetValue === 'object' && targetValue !== null ? targetValue : {};
|
|
68
|
+
merged[prop] = deepMerge(mergedTarget, sourceValue);
|
|
69
|
+
} else {
|
|
70
|
+
merged[prop] = sourceValue;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return merged as T;
|
|
74
|
+
}
|
package/utils/platform.ts
CHANGED
|
@@ -3,69 +3,69 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 仅保留 x 支持的平台条件;旧版 VUE2、APP-PLUS、APP-NVUE、H5 宏不再使用。
|
|
5
5
|
*/
|
|
6
|
-
export type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
export type Platform =
|
|
7
|
+
| 'none'
|
|
8
|
+
| 'vue3'
|
|
9
|
+
| 'app'
|
|
10
|
+
| 'app-nvue'
|
|
11
|
+
| 'h5'
|
|
12
|
+
| 'mp'
|
|
13
|
+
| 'weixin'
|
|
14
|
+
| 'alipay'
|
|
15
|
+
| 'baidu'
|
|
16
|
+
| 'toutiao'
|
|
17
|
+
| 'qq'
|
|
18
|
+
| 'kuaishou'
|
|
19
|
+
| '360';
|
|
20
20
|
|
|
21
|
-
let platform:
|
|
21
|
+
let platform: Platform = 'none';
|
|
22
22
|
|
|
23
23
|
// #ifdef VUE3
|
|
24
|
-
platform = 'vue3'
|
|
24
|
+
platform = 'vue3';
|
|
25
25
|
// #endif
|
|
26
26
|
|
|
27
27
|
// #ifdef APP
|
|
28
|
-
platform = 'app'
|
|
28
|
+
platform = 'app';
|
|
29
29
|
// #endif
|
|
30
30
|
|
|
31
31
|
// #ifdef APP-NVUE
|
|
32
|
-
platform = 'app-nvue'
|
|
32
|
+
platform = 'app-nvue';
|
|
33
33
|
// #endif
|
|
34
34
|
|
|
35
35
|
// #ifdef WEB || H5
|
|
36
|
-
platform = 'h5'
|
|
36
|
+
platform = 'h5';
|
|
37
37
|
// #endif
|
|
38
38
|
|
|
39
39
|
// #ifdef MP
|
|
40
|
-
platform = 'mp'
|
|
40
|
+
platform = 'mp';
|
|
41
41
|
// #endif
|
|
42
42
|
|
|
43
43
|
// #ifdef MP-WEIXIN
|
|
44
|
-
platform = 'weixin'
|
|
44
|
+
platform = 'weixin';
|
|
45
45
|
// #endif
|
|
46
46
|
|
|
47
47
|
// #ifdef MP-ALIPAY
|
|
48
|
-
platform = 'alipay'
|
|
48
|
+
platform = 'alipay';
|
|
49
49
|
// #endif
|
|
50
50
|
|
|
51
51
|
// #ifdef MP-BAIDU
|
|
52
|
-
platform = 'baidu'
|
|
52
|
+
platform = 'baidu';
|
|
53
53
|
// #endif
|
|
54
54
|
|
|
55
55
|
// #ifdef MP-TOUTIAO
|
|
56
|
-
platform = 'toutiao'
|
|
56
|
+
platform = 'toutiao';
|
|
57
57
|
// #endif
|
|
58
58
|
|
|
59
59
|
// #ifdef MP-QQ
|
|
60
|
-
platform = 'qq'
|
|
60
|
+
platform = 'qq';
|
|
61
61
|
// #endif
|
|
62
62
|
|
|
63
63
|
// #ifdef MP-KUAISHOU
|
|
64
|
-
platform = 'kuaishou'
|
|
64
|
+
platform = 'kuaishou';
|
|
65
65
|
// #endif
|
|
66
66
|
|
|
67
67
|
// #ifdef MP-360
|
|
68
|
-
platform = '360'
|
|
68
|
+
platform = '360';
|
|
69
69
|
// #endif
|
|
70
70
|
|
|
71
|
-
export default platform
|
|
71
|
+
export default platform;
|
package/utils/route.ts
CHANGED
|
@@ -2,141 +2,135 @@
|
|
|
2
2
|
* 路由跳转方法,该方法相对于直接使用 uni.xxx 更简单快捷,
|
|
3
3
|
* 并支持路由拦截。
|
|
4
4
|
*/
|
|
5
|
-
import { queryParams, deepMerge, page } from './function'
|
|
6
|
-
|
|
7
|
-
export type
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export interface
|
|
20
|
-
|
|
21
|
-
|
|
5
|
+
import { queryParams, deepMerge, page } from './function';
|
|
6
|
+
|
|
7
|
+
export type UViewRouteType =
|
|
8
|
+
| 'navigateTo'
|
|
9
|
+
| 'to'
|
|
10
|
+
| 'redirectTo'
|
|
11
|
+
| 'redirect'
|
|
12
|
+
| 'switchTab'
|
|
13
|
+
| 'tab'
|
|
14
|
+
| 'reLaunch'
|
|
15
|
+
| 'launch'
|
|
16
|
+
| 'navigateBack'
|
|
17
|
+
| 'back';
|
|
18
|
+
|
|
19
|
+
export interface UViewRouteParams {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
intercept?: boolean | ((config: UViewRouteOptions, resolve: (next: boolean) => void) => void);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export interface
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
export interface UViewRouteOptions {
|
|
25
|
+
type?: UViewRouteType;
|
|
26
|
+
url?: string;
|
|
27
|
+
delta?: number;
|
|
28
|
+
params?: UViewRouteParams;
|
|
29
|
+
animationType?: string;
|
|
30
|
+
animationDuration?: number;
|
|
31
|
+
intercept?: boolean | ((config: UViewRouteOptions, resolve: (next: boolean) => void) => void);
|
|
32
|
+
events?: Record<string, (...args: any[]) => void>;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export type
|
|
36
|
-
options?: string | RouteOptions,
|
|
37
|
-
params?: RouteParams
|
|
38
|
-
) => Promise<void>
|
|
35
|
+
export type UViewRouteFunction = (options?: string | UViewRouteOptions, params?: UViewRouteParams) => Promise<void>;
|
|
39
36
|
|
|
40
|
-
type RouterConfig = Required<
|
|
41
|
-
|
|
37
|
+
type RouterConfig = Required<
|
|
38
|
+
Pick<
|
|
39
|
+
UViewRouteOptions,
|
|
40
|
+
'type' | 'url' | 'delta' | 'params' | 'animationType' | 'animationDuration' | 'intercept' | 'events'
|
|
41
|
+
>
|
|
42
|
+
>;
|
|
42
43
|
|
|
43
44
|
class Router {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (type == 'reLaunch' || type == 'launch') {
|
|
134
|
-
uni.reLaunch({ url })
|
|
135
|
-
}
|
|
136
|
-
if (type == 'navigateBack' || type == 'back') {
|
|
137
|
-
uni.navigateBack({ delta })
|
|
138
|
-
}
|
|
139
|
-
}
|
|
45
|
+
config: RouterConfig;
|
|
46
|
+
|
|
47
|
+
constructor() {
|
|
48
|
+
this.config = {
|
|
49
|
+
type: 'navigateTo',
|
|
50
|
+
url: '',
|
|
51
|
+
delta: 1,
|
|
52
|
+
params: {},
|
|
53
|
+
animationType: 'pop-in',
|
|
54
|
+
animationDuration: 300,
|
|
55
|
+
intercept: false,
|
|
56
|
+
events: {},
|
|
57
|
+
};
|
|
58
|
+
// route 需要作为独立方法传递,先绑定 this
|
|
59
|
+
this.route = this.route.bind(this);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 判断 url 前面是否有 "/",如果没有则加上,否则无法跳转
|
|
63
|
+
addRootPath(url: string): string {
|
|
64
|
+
return url[0] === '/' ? url : `/${url}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 整合路由参数
|
|
68
|
+
mixinParam(url: string, params: UViewRouteParams): string {
|
|
69
|
+
url = url && this.addRootPath(url);
|
|
70
|
+
|
|
71
|
+
let query = '';
|
|
72
|
+
if (/.*\/.*\?.*=.*/.test(url)) {
|
|
73
|
+
query = queryParams(params, false);
|
|
74
|
+
return (url += `&${query}`);
|
|
75
|
+
}
|
|
76
|
+
query = queryParams(params);
|
|
77
|
+
return (url += query);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 对外的方法名称
|
|
81
|
+
async route(options: string | UViewRouteOptions = {}, params: UViewRouteParams = {}): Promise<void> {
|
|
82
|
+
let mergeConfig: UViewRouteOptions = {};
|
|
83
|
+
|
|
84
|
+
if (typeof options === 'string') {
|
|
85
|
+
mergeConfig.url = this.mixinParam(options, params);
|
|
86
|
+
mergeConfig.type = 'navigateTo';
|
|
87
|
+
} else {
|
|
88
|
+
mergeConfig = deepMerge(this.config as UViewRouteOptions, options);
|
|
89
|
+
mergeConfig.url = this.mixinParam(options.url as string, options.params as UViewRouteParams);
|
|
90
|
+
}
|
|
91
|
+
if (mergeConfig.url === page()) return;
|
|
92
|
+
|
|
93
|
+
if (params.intercept) {
|
|
94
|
+
mergeConfig.intercept = params.intercept;
|
|
95
|
+
}
|
|
96
|
+
mergeConfig.params = params;
|
|
97
|
+
mergeConfig = deepMerge(this.config as UViewRouteOptions, mergeConfig);
|
|
98
|
+
|
|
99
|
+
if (typeof mergeConfig.intercept === 'function') {
|
|
100
|
+
const interceptor = mergeConfig.intercept;
|
|
101
|
+
const isNext = await new Promise<boolean>((resolve) => {
|
|
102
|
+
interceptor(mergeConfig, resolve);
|
|
103
|
+
});
|
|
104
|
+
isNext && this.openPage(mergeConfig);
|
|
105
|
+
} else {
|
|
106
|
+
this.openPage(mergeConfig);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 执行路由跳转
|
|
111
|
+
openPage(config: UViewRouteOptions): void {
|
|
112
|
+
const { url = '', type, delta, animationType, animationDuration, events } = config;
|
|
113
|
+
if (type == 'navigateTo' || type == 'to') {
|
|
114
|
+
uni.navigateTo({
|
|
115
|
+
url,
|
|
116
|
+
animationType: animationType as any,
|
|
117
|
+
animationDuration,
|
|
118
|
+
events: events as any,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (type == 'redirectTo' || type == 'redirect') {
|
|
122
|
+
uni.redirectTo({ url });
|
|
123
|
+
}
|
|
124
|
+
if (type == 'switchTab' || type == 'tab') {
|
|
125
|
+
uni.switchTab({ url });
|
|
126
|
+
}
|
|
127
|
+
if (type == 'reLaunch' || type == 'launch') {
|
|
128
|
+
uni.reLaunch({ url });
|
|
129
|
+
}
|
|
130
|
+
if (type == 'navigateBack' || type == 'back') {
|
|
131
|
+
uni.navigateBack({ delta });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
140
134
|
}
|
|
141
135
|
|
|
142
|
-
export const route:
|
|
136
|
+
export const route: UViewRouteFunction = new Router().route;
|
package/utils/scrollbar.ts
CHANGED
|
@@ -9,25 +9,25 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
/** 单组滚动条 CSS 样式:camelCase / kebab-case 均可;number 默认按 px 处理(无单位属性除外) */
|
|
12
|
-
export type
|
|
12
|
+
export type ScrollbarStyle = Record<string, string | number>;
|
|
13
13
|
|
|
14
14
|
/** 滚动条自定义样式:默认合并 / 扩展 ::-webkit-scrollbar 及其 thumb / track */
|
|
15
|
-
export interface
|
|
15
|
+
export interface ScrollbarOptions {
|
|
16
16
|
/** ::-webkit-scrollbar-thumb 样式,覆盖默认 thumb 样式 */
|
|
17
|
-
thumb?:
|
|
17
|
+
thumb?: ScrollbarStyle;
|
|
18
18
|
/** ::-webkit-scrollbar-track 样式,覆盖默认 track 样式 */
|
|
19
|
-
track?:
|
|
19
|
+
track?: ScrollbarStyle;
|
|
20
20
|
/** 其余键作为 ::-webkit-scrollbar 样式,覆盖默认宽高 */
|
|
21
|
-
[property: string]: string | number |
|
|
21
|
+
[property: string]: string | number | ScrollbarStyle | undefined;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export type
|
|
24
|
+
export type Scrollbar = boolean | ScrollbarOptions;
|
|
25
25
|
|
|
26
26
|
/** 注入到 `<style>` 的元素 id;重复设置时替换同一节点 */
|
|
27
27
|
const SCROLLBAR_STYLE_ID = 'uv-scrollbar-style';
|
|
28
28
|
|
|
29
29
|
/** `false`:隐藏滚动条 */
|
|
30
|
-
const HIDDEN_SCROLLBAR_STYLE:
|
|
30
|
+
const HIDDEN_SCROLLBAR_STYLE: ScrollbarStyle = {
|
|
31
31
|
display: 'none',
|
|
32
32
|
width: '0 !important',
|
|
33
33
|
height: '0 !important',
|
|
@@ -36,17 +36,17 @@ const HIDDEN_SCROLLBAR_STYLE: UviewXScrollbarStyle = {
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
/** `true` / 对象的默认基础样式 */
|
|
39
|
-
const DEFAULT_SCROLLBAR_STYLE:
|
|
39
|
+
const DEFAULT_SCROLLBAR_STYLE: ScrollbarStyle = {
|
|
40
40
|
width: 6,
|
|
41
41
|
height: 6,
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
const DEFAULT_SCROLLBAR_THUMB_STYLE:
|
|
44
|
+
const DEFAULT_SCROLLBAR_THUMB_STYLE: ScrollbarStyle = {
|
|
45
45
|
background: '#c0c4cc',
|
|
46
46
|
borderRadius: 3,
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
const DEFAULT_SCROLLBAR_TRACK_STYLE:
|
|
49
|
+
const DEFAULT_SCROLLBAR_TRACK_STYLE: ScrollbarStyle = {
|
|
50
50
|
background: 'transparent',
|
|
51
51
|
};
|
|
52
52
|
|
|
@@ -79,7 +79,7 @@ function formatStyleValue(property: string, value: string | number): string {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/** 把样式对象转换为 CSS 声明串 */
|
|
82
|
-
function styleToDeclarations(style:
|
|
82
|
+
function styleToDeclarations(style: ScrollbarStyle): string {
|
|
83
83
|
const declarations: string[] = [];
|
|
84
84
|
for (const property of Object.keys(style)) {
|
|
85
85
|
const value = style[property];
|
|
@@ -91,16 +91,16 @@ function styleToDeclarations(style: UviewXScrollbarStyle): string {
|
|
|
91
91
|
return declarations.join(' ');
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
function toRule(selector: string, style:
|
|
94
|
+
function toRule(selector: string, style: ScrollbarStyle): string {
|
|
95
95
|
const declarations = styleToDeclarations(style);
|
|
96
96
|
return declarations ? `${selector} { ${declarations} }` : '';
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
function isScrollbarStyle(value: unknown): value is
|
|
99
|
+
function isScrollbarStyle(value: unknown): value is ScrollbarStyle {
|
|
100
100
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
function mergeScrollbarStyle(base:
|
|
103
|
+
function mergeScrollbarStyle(base: ScrollbarStyle, override?: ScrollbarStyle): ScrollbarStyle {
|
|
104
104
|
return override ? { ...base, ...override } : { ...base };
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -111,7 +111,7 @@ function mergeScrollbarStyle(base: UviewXScrollbarStyle, override?: UviewXScroll
|
|
|
111
111
|
* - `true`:默认滚动条样式;
|
|
112
112
|
* - 对象:默认样式 + 用户覆盖;空对象等价 `true`。
|
|
113
113
|
*/
|
|
114
|
-
export function buildScrollbarCss(scrollbar:
|
|
114
|
+
export function buildScrollbarCss(scrollbar: Scrollbar): string {
|
|
115
115
|
if (!scrollbar) {
|
|
116
116
|
return toRule('::-webkit-scrollbar', HIDDEN_SCROLLBAR_STYLE);
|
|
117
117
|
}
|
|
@@ -126,9 +126,9 @@ export function buildScrollbarCss(scrollbar: UviewXScrollbar): string {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// 自定义样式:`thumb` / `track` 之外的键作为基础样式
|
|
129
|
-
const baseOverride:
|
|
130
|
-
let thumbOverride:
|
|
131
|
-
let trackOverride:
|
|
129
|
+
const baseOverride: ScrollbarStyle = {};
|
|
130
|
+
let thumbOverride: ScrollbarStyle | undefined;
|
|
131
|
+
let trackOverride: ScrollbarStyle | undefined;
|
|
132
132
|
for (const property of Object.keys(scrollbar)) {
|
|
133
133
|
const value = scrollbar[property];
|
|
134
134
|
if (property === 'thumb' || property === 'track') {
|
|
@@ -160,7 +160,7 @@ export function buildScrollbarCss(scrollbar: UviewXScrollbar): string {
|
|
|
160
160
|
*
|
|
161
161
|
* `document` 不存在(SSR / Node 单测)时静默返回。
|
|
162
162
|
*/
|
|
163
|
-
export function applyScrollbar(scrollbar:
|
|
163
|
+
export function applyScrollbar(scrollbar: Scrollbar): void {
|
|
164
164
|
// #ifdef WEB || H5
|
|
165
165
|
if (typeof document === 'undefined' || !document.head) {
|
|
166
166
|
return;
|
package/utils/throttle.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {
|
|
1
|
+
import useThrottle from '../hooks/useThrottle';
|
|
2
|
+
import type { UViewThrottleFunction } from '../hooks/useThrottle';
|
|
3
3
|
|
|
4
4
|
// 兼容旧用法:模块级共享实例,复用 useThrottle 实现
|
|
5
|
-
const throttle:
|
|
5
|
+
const throttle: UViewThrottleFunction = useThrottle();
|
|
6
6
|
|
|
7
|
-
export default throttle
|
|
7
|
+
export default throttle;
|
package/locales/en-US.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* uview-x 可选组件语言包:英文(en-US)。
|
|
3
|
-
*
|
|
4
|
-
* 不参与内部聚合、不会被 `createI18n` 自动合并;需要英文时由使用方显式引入并合并:
|
|
5
|
-
* `import enUS from '@zfqh/uview-x/locales/en-US'`,再在 `createI18n({ messages: { 'en-US': enUS } })` 中使用。
|
|
6
|
-
* 键空间固定为 `uv.*`,`uv.form.*` 与 async-validator 默认 messages 完全对齐,`%s` 占位符由校验器替换。
|
|
7
|
-
*/
|
|
8
|
-
const enUS = {
|
|
9
|
-
uv: {
|
|
10
|
-
dialog: {
|
|
11
|
-
title: 'Tips',
|
|
12
|
-
cancel: 'Cancel',
|
|
13
|
-
confirm: 'OK',
|
|
14
|
-
},
|
|
15
|
-
code: {
|
|
16
|
-
start: 'Get code',
|
|
17
|
-
// 组件会把 x / X 替换为剩余秒数
|
|
18
|
-
change: 'X seconds to resend',
|
|
19
|
-
end: 'Resend',
|
|
20
|
-
},
|
|
21
|
-
time: {
|
|
22
|
-
justNow: 'Just now',
|
|
23
|
-
minutesAgo: '{n} minutes ago',
|
|
24
|
-
hoursAgo: '{n} hours ago',
|
|
25
|
-
daysAgo: '{n} days ago',
|
|
26
|
-
monthsAgo: '{n} months ago',
|
|
27
|
-
yearsAgo: '{n} years ago',
|
|
28
|
-
},
|
|
29
|
-
form: {
|
|
30
|
-
default: 'Validation error on field %s',
|
|
31
|
-
required: '%s is required',
|
|
32
|
-
enum: '%s must be one of %s',
|
|
33
|
-
whitespace: '%s cannot be empty',
|
|
34
|
-
date: {
|
|
35
|
-
format: '%s date %s is invalid for format %s',
|
|
36
|
-
parse: '%s date could not be parsed, %s is invalid ',
|
|
37
|
-
invalid: '%s date %s is invalid',
|
|
38
|
-
},
|
|
39
|
-
types: {
|
|
40
|
-
string: '%s is not a %s',
|
|
41
|
-
method: '%s is not a %s (function)',
|
|
42
|
-
array: '%s is not an %s',
|
|
43
|
-
object: '%s is not an %s',
|
|
44
|
-
number: '%s is not a %s',
|
|
45
|
-
date: '%s is not a %s',
|
|
46
|
-
boolean: '%s is not a %s',
|
|
47
|
-
integer: '%s is not an %s',
|
|
48
|
-
float: '%s is not a %s',
|
|
49
|
-
regexp: '%s is not a valid %s',
|
|
50
|
-
email: '%s is not a valid %s',
|
|
51
|
-
url: '%s is not a valid %s',
|
|
52
|
-
hex: '%s is not a valid %s',
|
|
53
|
-
},
|
|
54
|
-
string: {
|
|
55
|
-
len: '%s must be exactly %s characters',
|
|
56
|
-
min: '%s must be at least %s characters',
|
|
57
|
-
max: '%s cannot be longer than %s characters',
|
|
58
|
-
range: '%s must be between %s and %s characters',
|
|
59
|
-
},
|
|
60
|
-
number: {
|
|
61
|
-
len: '%s must equal %s',
|
|
62
|
-
min: '%s cannot be less than %s',
|
|
63
|
-
max: '%s cannot be greater than %s',
|
|
64
|
-
range: '%s must be between %s and %s',
|
|
65
|
-
},
|
|
66
|
-
array: {
|
|
67
|
-
len: '%s must be exactly %s in length',
|
|
68
|
-
min: '%s cannot be less than %s in length',
|
|
69
|
-
max: '%s cannot be greater than %s in length',
|
|
70
|
-
range: '%s must be between %s and %s in length',
|
|
71
|
-
},
|
|
72
|
-
pattern: {
|
|
73
|
-
mismatch: '%s value %s does not match pattern %s',
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export default enUS;
|