@zfqh/uview-x 0.0.6 → 0.0.8

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +52 -9
  3. package/components/uv-badge/uv-badge.vue +4 -4
  4. package/components/uv-button/uv-button.vue +11 -11
  5. package/components/uv-checkbox/uv-checkbox.vue +11 -9
  6. package/components/uv-checkbox-group/uv-checkbox-group.vue +2 -2
  7. package/components/uv-code/uv-code.vue +2 -2
  8. package/components/uv-dialog/uv-dialog.vue +10 -11
  9. package/components/uv-form/uv-form.vue +244 -246
  10. package/components/uv-form-item/uv-form-item.vue +10 -9
  11. package/components/uv-icon/uv-icon.vue +13 -13
  12. package/components/uv-input/uv-input.vue +6 -5
  13. package/components/uv-line/uv-line.vue +7 -6
  14. package/components/uv-line-progress/uv-line-progress.vue +5 -5
  15. package/components/uv-loading-icon/uv-loading-icon.vue +9 -8
  16. package/components/uv-overlay/uv-overlay.vue +3 -2
  17. package/components/uv-popup/uv-popup.vue +6 -5
  18. package/components/uv-safe-bottom/uv-safe-bottom.vue +4 -3
  19. package/components/uv-status-bar/uv-status-bar.vue +4 -3
  20. package/components/uv-tabs/uv-tabs.vue +15 -12
  21. package/components/uv-transition/uv-transition.vue +2 -2
  22. package/hooks/index.ts +5 -5
  23. package/hooks/useDebounce.ts +33 -35
  24. package/hooks/useI18n.ts +4 -3
  25. package/hooks/useThrottle.ts +36 -38
  26. package/index.ts +50 -29
  27. package/locales/en.ts +56 -0
  28. package/locales/es.ts +57 -0
  29. package/locales/fr.ts +57 -0
  30. package/locales/index.ts +15 -159
  31. package/locales/ru.ts +57 -0
  32. package/locales/zh-Hans.ts +57 -0
  33. package/locales/zh-Hant.ts +57 -0
  34. package/package.json +2 -2
  35. package/types/index.d.ts +68 -59
  36. package/utils/color.ts +139 -0
  37. package/utils/compress.ts +28 -28
  38. package/utils/config.ts +46 -11
  39. package/utils/debounce.ts +4 -4
  40. package/utils/function.ts +11 -89
  41. package/utils/locale.ts +444 -270
  42. package/utils/merge.ts +74 -0
  43. package/utils/platform.ts +28 -28
  44. package/utils/route.ts +123 -129
  45. package/utils/scrollbar.ts +19 -19
  46. package/utils/throttle.ts +4 -4
  47. package/locales/en-US.ts +0 -79
  48. package/locales/es-ES.ts +0 -79
  49. package/locales/fr-FR.ts +0 -79
  50. package/locales/ru-RU.ts +0 -79
  51. package/locales/zh-CN.ts +0 -79
  52. package/locales/zh-TW.ts +0 -79
  53. package/utils/colorGradient.ts +0 -139
  54. package/utils/index.ts +0 -58
  55. /package/components/uv-form/{valid.ts → validator.ts} +0 -0
package/types/index.d.ts CHANGED
@@ -1,59 +1,68 @@
1
- /**
2
- * @zfqh/uview-x 全局注入类型声明。
3
- *
4
- * 入口 `index.ts` 会把 `$uv` 挂到 `uni.$uv` 与 `app.config.globalProperties.$uv`;
5
- * `utils/locale.ts` 的 `createI18n` 会把 i18n 实例挂到 `uni.$i18n`。
6
- * 本文件为 uni 全局对象与 Vue 组件实例补充类型,并声明入口默认插件类型与 i18n 公共 API。
7
- */
8
- import type { App } from 'vue';
9
- import type { I18n, I18nOptions } from 'vue-i18n';
10
-
11
- type UviewX$uv = (typeof import('../utils'))['$uv'];
12
-
13
- declare global {
14
- interface Uni {
15
- $uv: UviewX$uv;
16
- /** `createI18n` 创建的全局 i18n 实例 */
17
- $i18n?: I18n;
18
- }
19
- }
20
-
21
- declare module '*.ttf' {
22
- const src: string;
23
- export default src;
24
- }
25
-
26
- declare module '*.otf' {
27
- const src: string;
28
- export default src;
29
- }
30
-
31
- declare module 'vue' {
32
- interface ComponentCustomProperties {
33
- $uv: UviewX$uv;
34
- }
35
- }
36
-
37
- /**
38
- * 入口模块声明:包内 `types` 指向本文件时,消费者仍可从入口
39
- * `import { config, createI18n, useI18n, setLocale, ... } from '@zfqh/uview-x'` 获得类型提示。
40
- *
41
- * 这里声明 `config` 与 4 个 i18n 公共函数 + `useI18n`;包内其余 helper、内部状态与 default/fallback 语言均不对外导出。
42
- */
43
- declare module '@zfqh/uview-x' {
44
- /** 运行时配置;颜色通过 `config.color` 访问(键为 camelCase,如 `primary`);H5 滚动条通过 `config.scrollbar` 控制(默认隐藏) */
45
- export const config: (typeof import('../utils'))['config'];
46
- /** 创建 i18n 实例并挂到 `uni.$i18n`(仅注入并深合并默认中文 `zh-CN`;其他语言需自行 import 语言包后合并) */
47
- export function createI18n(opts: I18nOptions): I18n;
48
- /** 获取当前语言(storage `UNI_LOCALE` → `getAppBaseInfo` 的 `language` / `osLanguage` / `hostLanguage` → `zh-CN`) */
49
- export function getLocale(): string;
50
- /** 按当前语言取词(优先全局语言包,其次默认中文语言包;支持 `a.b.c` 路径与 `{name}` 占位符) */
51
- export function getLocaleMessage(key: string, values?: Record<string, string | number>): string;
52
- /** 设置当前语言:更新内部 localeState 与 `uni.$i18n.global.locale`,写 storage `UNI_LOCALE`,最后调用 `uni.setLocale` */
53
- export function setLocale(locale: string): void;
54
- /** i18n hook:未创建 i18n 实例时降级读默认中文语言包,不会抛错 */
55
- export const useI18n: typeof import('vue-i18n').useI18n;
56
- }
57
-
58
- declare const plugin: { install: (app: App) => void };
59
- export default plugin;
1
+ /**
2
+ * @zfqh/uview-x 全局注入类型声明。
3
+ *
4
+ * 入口不再注入 `$uv`;仅 `utils/locale.ts` 的 `createI18n` 会把 i18n 实例挂到 `uni.$i18n`。
5
+ * 本文件为 uni 全局对象补充类型,并声明入口插件、公共 API 与公共类型。
6
+ */
7
+ import type { App } from 'vue';
8
+ import type { I18n } from 'vue-i18n';
9
+
10
+ declare global {
11
+ interface Uni {
12
+ /** `createI18n` 创建的全局 i18n 实例 */
13
+ $i18n?: I18n;
14
+ }
15
+ }
16
+
17
+ declare module '*.ttf' {
18
+ const src: string;
19
+ export default src;
20
+ }
21
+
22
+ declare module '*.otf' {
23
+ const src: string;
24
+ export default src;
25
+ }
26
+
27
+ declare module '@zfqh/uview-x' {
28
+ export type { UViewConfigOptions, UViewColor, UViewConfig } from '../utils/config';
29
+ export type { UViewI18nMessages, UViewCreateI18nOptions, UViewI18nOptions } from '../utils/locale';
30
+ export type { UViewCompressOptions } from '../utils/compress';
31
+ export type { UViewDebounceFunction } from '../hooks/useDebounce';
32
+ export type { UViewThrottleFunction } from '../hooks/useThrottle';
33
+
34
+ /** 运行时配置;颜色通过 `config.color` 访问(键为 camelCase,如 `primary`);H5 滚动条通过 `config.scrollbar` 控制(默认隐藏) */
35
+ export const config: (typeof import('../utils/config'))['default'];
36
+ /** 修改运行时配置;可同时传 `i18n` 初始化组件多语言 */
37
+ export function setConfig(options?: import('../utils/config').UViewConfigOptions): void;
38
+
39
+ export { default as compress } from '../utils/compress';
40
+ export { default as debounce } from '../utils/debounce';
41
+ export { default as http } from '../utils/http';
42
+ export { default as throttle } from '../utils/throttle';
43
+ export * from '../utils/route';
44
+ export const test: typeof import('../utils/test');
45
+
46
+ /** 创建 i18n 实例并挂到 `uni.$i18n`(默认注入并合并内置英文 `en`;messages 使用扁平 locale 包,可覆盖初始化配置) */
47
+ export function createI18n(opts?: import('../utils/locale').UViewCreateI18nOptions): I18n;
48
+ /** 获取当前语言(storage `UNI_LOCALE` → `uni.getLocale` → `getAppBaseInfo.appLanguage` → `en`) */
49
+ export function getLocale(): string;
50
+ /** 按当前语言取词(优先全局语言包,其次内置/初始化语言包;支持扁平 `uv.*` key 与 `{name}` 占位符) */
51
+ export function getLocaleMessage(key: string, values?: Record<string, string | number>): string;
52
+ /** 设置当前语言:更新内部 localeState 与 `uni.$i18n.global.locale`,写 storage `UNI_LOCALE`,最后调用 `uni.setLocale` */
53
+ export function setLocale(locale: string): void;
54
+
55
+ /** 实例级防抖 */
56
+ export { default as useDebounce } from '../hooks/useDebounce';
57
+ /** 实例级节流 */
58
+ export { default as useThrottle } from '../hooks/useThrottle';
59
+ /** i18n hook:未创建 i18n 实例时降级读内置/初始化语言包,不会抛错 */
60
+ export { default as useI18n } from '../hooks/useI18n';
61
+
62
+ export interface UViewPlugin {
63
+ install(app: App, options?: import('../utils/config').UViewConfigOptions): void;
64
+ }
65
+ }
66
+
67
+ declare const plugin: UViewPlugin;
68
+ export default plugin;
package/utils/color.ts ADDED
@@ -0,0 +1,139 @@
1
+ /**
2
+ * 求两个颜色之间的渐变值
3
+ * @param {string} startColor 开始的颜色
4
+ * @param {string} endColor 结束的颜色
5
+ * @param {number} step 颜色等分的份额
6
+ * */
7
+ export function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10): string[] {
8
+ const startRGB = hexToRgb(startColor, false) as number[]; // 转换为rgb数组模式
9
+ const startR = startRGB[0];
10
+ const startG = startRGB[1];
11
+ const startB = startRGB[2];
12
+
13
+ const endRGB = hexToRgb(endColor, false) as number[];
14
+ const endR = endRGB[0];
15
+ const endG = endRGB[1];
16
+ const endB = endRGB[2];
17
+
18
+ const sR = (endR - startR) / step; // 总差值
19
+ const sG = (endG - startG) / step;
20
+ const sB = (endB - startB) / step;
21
+ const colorArr = [];
22
+ for (let i = 0; i < step; i++) {
23
+ // 计算每一步的hex值
24
+ let hex = rgbToHex(
25
+ `rgb(${Math.round(sR * i + startR)},${Math.round(sG * i + startG)},${Math.round(sB * i + startB)})`,
26
+ );
27
+ // 确保第一个颜色值为startColor的值
28
+ if (i === 0) hex = rgbToHex(startColor);
29
+ // 确保最后一个颜色值为endColor的值
30
+ if (i === step - 1) hex = rgbToHex(endColor);
31
+ colorArr.push(hex);
32
+ }
33
+ return colorArr;
34
+ }
35
+
36
+ /**
37
+ * 将颜色转换为 RGB。
38
+ *
39
+ * @param sColor 颜色字符串,支持 `#rgb`、`#rrggbb`、`rgb(...)`。
40
+ * @param str 为 `true`(默认)时返回 `rgb(r,g,b)` 字符串;为 `false` 时返回 `[r,g,b]` 数组。
41
+ * @returns `str=false` 时返回 RGB 数组;否则返回 rgb 字符串;无法识别的颜色原样返回。
42
+ */
43
+ export function hexToRgb(sColor: string, str = true): string | number[] {
44
+ const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
45
+ sColor = String(sColor).toLowerCase();
46
+ if (sColor && reg.test(sColor)) {
47
+ if (sColor.length === 4) {
48
+ let sColorNew = '#';
49
+ for (let i = 1; i < 4; i += 1) {
50
+ sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
51
+ }
52
+ sColor = sColorNew;
53
+ }
54
+ // 处理六位的颜色值
55
+ const sColorChange = [];
56
+ for (let i = 1; i < 7; i += 2) {
57
+ sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`));
58
+ }
59
+ if (!str) {
60
+ return sColorChange;
61
+ }
62
+ return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`;
63
+ }
64
+ if (/^(rgb|RGB)/.test(sColor)) {
65
+ const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',');
66
+ return arr.map((val) => Number(val));
67
+ }
68
+ return sColor;
69
+ }
70
+
71
+ // 将rgb表示方式转换为hex表示方式
72
+ export function rgbToHex(rgb: string): string {
73
+ const _this = rgb;
74
+ const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
75
+ if (/^(rgb|RGB)/.test(_this)) {
76
+ const aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',');
77
+ let strHex = '#';
78
+ for (let i = 0; i < aColor.length; i++) {
79
+ let hex = Number(aColor[i]).toString(16);
80
+ hex = String(hex).length == 1 ? `${0}${hex}` : hex; // 保证每个rgb的值为2位
81
+ if (hex === '0') {
82
+ hex += hex;
83
+ }
84
+ strHex += hex;
85
+ }
86
+ if (strHex.length !== 7) {
87
+ strHex = _this;
88
+ }
89
+ return strHex;
90
+ }
91
+ if (reg.test(_this)) {
92
+ const aNum = _this.replace(/#/, '').split('');
93
+ if (aNum.length === 6) {
94
+ return _this;
95
+ }
96
+ if (aNum.length === 3) {
97
+ let numHex = '#';
98
+ for (let i = 0; i < aNum.length; i += 1) {
99
+ numHex += aNum[i] + aNum[i];
100
+ }
101
+ return numHex;
102
+ }
103
+ } else {
104
+ return _this;
105
+ }
106
+ // 合法 hex 但长度不是 3/6 时保持原值返回,保证返回类型为 string
107
+ return _this;
108
+ }
109
+
110
+ /**
111
+ * JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
112
+ * sHex为传入的十六进制的色值
113
+ * alpha为rgba的透明度
114
+ */
115
+ export function colorToRgba(color: string, alpha: number): string {
116
+ color = rgbToHex(color);
117
+ // 十六进制颜色值的正则表达式
118
+ const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
119
+ /* 16进制颜色转为RGB格式 */
120
+ let sColor = String(color).toLowerCase();
121
+ if (sColor && reg.test(sColor)) {
122
+ if (sColor.length === 4) {
123
+ let sColorNew = '#';
124
+ for (let i = 1; i < 4; i += 1) {
125
+ sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
126
+ }
127
+ sColor = sColorNew;
128
+ }
129
+ // 处理六位的颜色值
130
+ const sColorChange = [];
131
+ for (let i = 1; i < 7; i += 2) {
132
+ sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`));
133
+ }
134
+ // return sColorChange.join(',')
135
+ return `rgba(${sColorChange.join(',')},${alpha})`;
136
+ }
137
+
138
+ return sColor;
139
+ }
package/utils/compress.ts CHANGED
@@ -1,34 +1,34 @@
1
- export interface CompressOptions {
2
- width?: number | string
3
- height?: number | string
1
+ export interface UViewCompressOptions {
2
+ width?: number | string;
3
+ height?: number | string;
4
4
  }
5
5
 
6
- function image(url: string, style?: CompressOptions): string {
7
- url = String(url || '')
8
- if (/^https?:\/\//.test(url)) {
9
- const { width, height } = style || {}
10
- let params = ''
11
- if (/\d+(r?px)?$/.test(String(width))) {
12
- const size = Number.parseFloat(String(width))
13
- params = `imageMogr2/thumbnail/${size}x/format/webp`
14
- } else if (/\d+(r?px)?$/.test(String(height))) {
15
- const size = Number.parseFloat(String(height))
16
- params = `imageMogr2/thumbnail/x${size}/format/webp`
17
- }
18
- if (params) {
19
- if (url.lastIndexOf('?') === -1) {
20
- return `${url}?${params}`
21
- }
22
- if (url.lastIndexOf('imageMogr2/') === -1) {
23
- return `${url}&${params}`
24
- }
25
- }
26
- }
27
- return url
6
+ function image(url: string, style?: UViewCompressOptions): string {
7
+ url = String(url || '');
8
+ if (/^https?:\/\//.test(url)) {
9
+ const { width, height } = style || {};
10
+ let params = '';
11
+ if (/\d+(r?px)?$/.test(String(width))) {
12
+ const size = Number.parseFloat(String(width));
13
+ params = `imageMogr2/thumbnail/${size}x/format/webp`;
14
+ } else if (/\d+(r?px)?$/.test(String(height))) {
15
+ const size = Number.parseFloat(String(height));
16
+ params = `imageMogr2/thumbnail/x${size}/format/webp`;
17
+ }
18
+ if (params) {
19
+ if (url.lastIndexOf('?') === -1) {
20
+ return `${url}?${params}`;
21
+ }
22
+ if (url.lastIndexOf('imageMogr2/') === -1) {
23
+ return `${url}&${params}`;
24
+ }
25
+ }
26
+ }
27
+ return url;
28
28
  }
29
29
 
30
30
  const compress: { image: typeof image } = {
31
- image
32
- }
31
+ image,
32
+ };
33
33
 
34
- export default compress
34
+ export default compress;
package/utils/config.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  // #ifndef APP-NVUE
2
2
  import vars from '../styles/var.module.scss';
3
3
  // #endif
4
- import type { UviewXScrollbar } from './scrollbar';
4
+ import { deepMerge } from './merge';
5
+ import type { UViewI18nOptions } from './locale';
6
+ import type { Scrollbar } from './scrollbar';
5
7
 
6
- export interface UviewXColor {
8
+ export interface UViewColor {
7
9
  primary: string;
8
10
  primaryDark: string;
9
11
  primaryDisabled: string;
@@ -35,26 +37,42 @@ export interface UviewXColor {
35
37
  [key: string]: string;
36
38
  }
37
39
 
38
- export type UviewXProps = Record<string, Record<string, unknown>>;
40
+ export type Props = Record<string, Record<string, unknown>>;
39
41
 
40
- export interface UviewXConfig {
42
+ export interface UViewConfig {
41
43
  // 主题名称
42
44
  type: string[];
43
45
  // 颜色部分,本来可以通过 scss 的 :export 导出供 js 使用,但是 nvue 不支持
44
- color: UviewXColor;
46
+ color: UViewColor;
45
47
  // 组件默认 props,一次性合并进各组件的 props 定义
46
- props: UviewXProps;
48
+ props: Props;
47
49
  // 默认单位,可以通过配置为 rpx,那么在用于传入组件大小参数为数值时,就默认为 rpx
48
50
  unit: string;
49
51
  // H5 全局滚动条:false 隐藏(默认);true 使用默认样式;对象在默认样式上自定义
50
- scrollbar: UviewXScrollbar;
52
+ scrollbar: Scrollbar;
51
53
  }
52
54
 
53
- export type UviewXColorConfig = Partial<UviewXColor>;
55
+ export type UViewConfigOptions = Omit<Partial<UViewConfig>, 'color' | 'props'> & {
56
+ /** 修改内置 color 属性(与默认色板深合并) */
57
+ color?: Partial<UViewColor>;
58
+ /** 修改组件默认 props(与已有 props 深合并) */
59
+ props?: Props;
60
+ /** 组件多语言初始化配置 */
61
+ i18n?: UViewI18nOptions;
62
+ };
63
+
64
+ type I18nConfigHandler = (options: UViewI18nOptions) => void;
65
+
66
+ let i18nConfigHandler: I18nConfigHandler | undefined;
67
+
68
+ /** 由 utils/locale.ts 注册 i18n 配置处理器,避免 config ↔ locale 的值循环 */
69
+ export function registerI18nConfigHandler(handler: I18nConfigHandler): void {
70
+ i18nConfigHandler = handler;
71
+ }
54
72
 
55
73
  // 兜底色板与 styles/theme.scss 默认值保持一致(nvue 无法读取 SCSS,使用常量兜底);
56
74
  // 非 nvue 端会由 var.module.scss 覆盖为实际主题色。
57
- const color: UviewXColor = {
75
+ const color: UViewColor = {
58
76
  primary: '#3c9cff',
59
77
  primaryDark: '#398ade',
60
78
  primaryDisabled: '#9acafc',
@@ -88,8 +106,8 @@ const color: UviewXColor = {
88
106
  // #ifndef APP-NVUE
89
107
  Object.assign(color, vars);
90
108
  // #endif
91
-
92
- const config: UviewXConfig = {
109
+ console.log(vars)
110
+ const config: UViewConfig = {
93
111
  type: ['primary', 'success', 'info', 'error', 'warning'],
94
112
  color,
95
113
  props: {},
@@ -97,4 +115,21 @@ const config: UviewXConfig = {
97
115
  scrollbar: false,
98
116
  };
99
117
 
118
+ /**
119
+ * 修改 uview-x 运行时配置。
120
+ *
121
+ * - 运行时字段按现有深合并语义写入 config;
122
+ * - `i18n` 交给 utils/locale.ts 注册的处理器;
123
+ * - 与 `app.use(UviewX, options)` 共用同一实现。
124
+ */
125
+ export function setConfig(options: UViewConfigOptions = {}): void {
126
+ const { i18n, ...configOptions } = options;
127
+ if (Object.keys(configOptions).length > 0) {
128
+ Object.assign(config, deepMerge(config, configOptions as Partial<UViewConfig>));
129
+ }
130
+ if (i18n && i18nConfigHandler) {
131
+ i18nConfigHandler(i18n);
132
+ }
133
+ }
134
+
100
135
  export default config;
package/utils/debounce.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { useDebounce } from '../hooks/useDebounce'
2
- import type { DebounceFunction } from '../hooks/useDebounce'
1
+ import useDebounce from '../hooks/useDebounce';
2
+ import type { UViewDebounceFunction } from '../hooks/useDebounce';
3
3
 
4
4
  // 兼容旧用法:模块级共享实例,复用 useDebounce 实现
5
- const debounce: DebounceFunction = useDebounce()
5
+ const debounce: UViewDebounceFunction = useDebounce();
6
6
 
7
- export default debounce
7
+ export default debounce;
package/utils/function.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { number, empty } from './test';
2
2
  import { round } from './digit';
3
3
  import config from './config';
4
- import type { UviewXColor, UviewXConfig, UviewXProps } from './config';
5
4
  import { appTranslate } from './locale';
5
+
6
+ export { deepClone, deepMerge } from './merge';
6
7
  /**
7
8
  * @description 如果value小于min,取min;如果value大于max,取max
8
9
  * @param {number} min
@@ -189,15 +190,22 @@ export function $parent(this: any, name?: string): any | false {
189
190
  * 对象转字符串,或者字符串转对象
190
191
  * @param {object | string} customStyle 需要转换的目标
191
192
  * @param {String} target 转换的目的,object-转为对象,string-转为字符串
192
- * @returns {object|string}
193
+ * @returns {object|string} target 为 object 时返回对象,为 string 时返回字符串
193
194
  */
195
+ export function addStyle(customStyle: string | Record<string, any>, target: 'string'): string;
196
+ export function addStyle(customStyle: string | Record<string, any>, target?: 'object'): Record<string, any>;
197
+ export function addStyle(
198
+ customStyle: string | Record<string, any>,
199
+ target: 'object' | 'string',
200
+ ): Record<string, any> | string;
194
201
  export function addStyle(
195
202
  customStyle: string | Record<string, any>,
196
203
  target: 'object' | 'string' = 'object',
197
204
  ): Record<string, any> | string {
205
+ // 空值按目标类型归一,保证 target=object 时始终返回对象、target=string 时始终返回字符串
206
+ if (empty(customStyle)) return target === 'string' ? '' : {};
198
207
  // 字符串转字符串,对象转对象情形,直接返回
199
208
  if (
200
- empty(customStyle) ||
201
209
  (typeof customStyle === 'object' && target === 'object') ||
202
210
  (target === 'string' && typeof customStyle === 'string')
203
211
  ) {
@@ -243,75 +251,6 @@ export function addUnit(value: string | number = 'auto', unit: string = config.u
243
251
  return number(value) ? `${value}${unit}` : value;
244
252
  }
245
253
 
246
- /**
247
- * @description 深度克隆
248
- * @param {object} obj 需要深度克隆的对象
249
- * @param cache 缓存
250
- * @returns {*} 克隆后的对象或者原值(不是对象)
251
- */
252
- export function deepClone<T>(obj: T, cache: WeakMap<object, any> = new WeakMap()): T {
253
- if (obj === null || typeof obj !== 'object') return obj;
254
- if (cache.has(obj)) return cache.get(obj);
255
- let clone;
256
- if (obj instanceof Date) {
257
- clone = new Date(obj.getTime());
258
- } else if (obj instanceof RegExp) {
259
- clone = new RegExp(obj);
260
- } else if (obj instanceof Map) {
261
- clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
262
- } else if (obj instanceof Set) {
263
- clone = new Set(Array.from(obj, (value) => deepClone(value, cache)));
264
- } else if (Array.isArray(obj)) {
265
- clone = obj.map((value) => deepClone(value, cache));
266
- } else if (Object.prototype.toString.call(obj) === '[object Object]') {
267
- clone = Object.create(Object.getPrototypeOf(obj));
268
- cache.set(obj, clone);
269
- for (const [key, value] of Object.entries(obj)) {
270
- clone[key] = deepClone(value, cache);
271
- }
272
- } else {
273
- clone = Object.assign({}, obj);
274
- }
275
- cache.set(obj, clone);
276
- return clone;
277
- }
278
-
279
- /**
280
- * @description JS对象深度合并
281
- * @param {object} target 需要拷贝的对象
282
- * @param {object} source 拷贝的来源对象
283
- * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
284
- */
285
- export function deepMerge<T extends object>(target: T = {} as T, source: Partial<T> = {}): T {
286
- target = deepClone(target);
287
- if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
288
- const merged: Record<string, any> = Array.isArray(target)
289
- ? (target.slice() as unknown as Record<string, any>)
290
- : Object.assign({}, target);
291
- const sourceRecord = source as Record<string, any>;
292
- for (const prop in sourceRecord) {
293
- if (!Object.prototype.hasOwnProperty.call(sourceRecord, prop)) continue;
294
- const sourceValue = sourceRecord[prop];
295
- const targetValue = merged[prop];
296
- if (sourceValue instanceof Date) {
297
- merged[prop] = new Date(sourceValue);
298
- } else if (sourceValue instanceof RegExp) {
299
- merged[prop] = new RegExp(sourceValue);
300
- } else if (sourceValue instanceof Map) {
301
- merged[prop] = new Map(sourceValue);
302
- } else if (sourceValue instanceof Set) {
303
- merged[prop] = new Set(sourceValue);
304
- } else if (typeof sourceValue === 'object' && sourceValue !== null) {
305
- // 目标是原始值 / null 时,用对象源替换;避免 `false`、`undefined` 等无法被深合并
306
- const mergedTarget = typeof targetValue === 'object' && targetValue !== null ? targetValue : {};
307
- merged[prop] = deepMerge(mergedTarget, sourceValue);
308
- } else {
309
- merged[prop] = sourceValue;
310
- }
311
- }
312
- return merged as T;
313
- }
314
-
315
254
  /**
316
255
  * @description error提示
317
256
  * @param {*} err 错误内容
@@ -753,20 +692,3 @@ export function getHistoryPage(back = 0): ReturnType<typeof getCurrentPages>[num
753
692
  const len = pages.length;
754
693
  return pages[len - 1 + back];
755
694
  }
756
-
757
- /**
758
- * @description 修改 uview-x 运行时内置属性值
759
- *
760
- * 直接传 config 字段:
761
- * `setConfig({ unit: 'rpx', type: [...], scrollbar: true, color: {...}, props: {...} })`
762
- */
763
- export type SetConfigOptions = Omit<Partial<UviewXConfig>, 'color' | 'props'> & {
764
- /** 修改内置 color 属性(与默认色板深合并) */
765
- color?: Partial<UviewXColor>;
766
- /** 修改组件默认 props(与已有 props 深合并) */
767
- props?: UviewXProps;
768
- };
769
-
770
- export function setConfig(options: SetConfigOptions = {}): void {
771
- Object.assign(config, deepMerge(config, options as Partial<UviewXConfig>));
772
- }