uview-pro 0.5.2 → 0.5.4

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 (72) hide show
  1. package/changelog.md +40 -0
  2. package/components/u-action-sheet/types.ts +1 -1
  3. package/components/u-action-sheet/u-action-sheet.vue +5 -5
  4. package/components/u-action-sheet-item/types.ts +1 -1
  5. package/components/u-alert-tips/types.ts +1 -1
  6. package/components/u-alert-tips/u-alert-tips.vue +1 -1
  7. package/components/u-avatar/types.ts +1 -1
  8. package/components/u-avatar-cropper/types.ts +1 -1
  9. package/components/u-back-top/types.ts +1 -1
  10. package/components/u-badge/types.ts +1 -1
  11. package/components/u-button/u-button.vue +4 -3
  12. package/components/u-calendar/types.ts +1 -1
  13. package/components/u-calendar/u-calendar.vue +1 -1
  14. package/components/u-car-keyboard/types.ts +1 -1
  15. package/components/u-card/types.ts +1 -1
  16. package/components/u-cell-group/types.ts +1 -1
  17. package/components/u-cell-item/types.ts +1 -1
  18. package/components/u-checkbox/types.ts +1 -1
  19. package/components/u-checkbox-group/types.ts +1 -1
  20. package/components/u-circle-progress/types.ts +1 -1
  21. package/components/u-circle-progress/u-circle-progress.vue +1 -1
  22. package/components/u-dropdown-item/u-dropdown-item.vue +1 -1
  23. package/components/u-empty/u-empty.vue +1 -1
  24. package/components/u-fab/u-fab.vue +1 -1
  25. package/components/u-field/types.ts +9 -9
  26. package/components/u-field/u-field.vue +8 -7
  27. package/components/u-form-item/u-form-item.vue +1 -1
  28. package/components/u-image/types.ts +1 -1
  29. package/components/u-index-anchor/u-index-anchor.vue +5 -5
  30. package/components/u-input/u-input.vue +8 -7
  31. package/components/u-loading/types.ts +2 -0
  32. package/components/u-loading/u-loading.vue +3 -2
  33. package/components/u-loadmore/types.ts +2 -0
  34. package/components/u-loadmore/u-loadmore.vue +11 -8
  35. package/components/u-message-input/u-message-input.vue +4 -3
  36. package/components/u-navbar/u-navbar.vue +4 -4
  37. package/components/u-notice-bar/u-notice-bar.vue +1 -1
  38. package/components/u-pagination/u-pagination.vue +1 -1
  39. package/components/u-picker/u-picker.vue +13 -5
  40. package/components/u-popup/u-popup.vue +2 -2
  41. package/components/u-rate/u-rate.vue +4 -4
  42. package/components/u-safe-bottom/u-safe-bottom.vue +4 -1
  43. package/components/u-search/u-search.vue +1 -1
  44. package/components/u-section/types.ts +1 -1
  45. package/components/u-select/u-select.vue +17 -3
  46. package/components/u-switch/u-switch.vue +1 -1
  47. package/components/u-tabbar/types.ts +4 -1
  48. package/components/u-tabbar/u-tabbar.vue +4 -4
  49. package/components/u-text/u-text.vue +17 -16
  50. package/components/u-textarea/types.ts +1 -1
  51. package/components/u-textarea/u-textarea.vue +5 -4
  52. package/components/u-toast/service.ts +21 -0
  53. package/components/u-toast/types.ts +7 -2
  54. package/components/u-toast/u-toast.vue +82 -19
  55. package/components/u-upload/types.ts +2 -2
  56. package/components/u-upload/u-upload.vue +1 -1
  57. package/index.ts +1 -1
  58. package/libs/css/style.theme.scss +23 -0
  59. package/libs/function/clipboard.ts +5 -5
  60. package/libs/function/color.ts +3 -1
  61. package/libs/function/styleUtils.ts +5 -5
  62. package/libs/function/test.ts +6 -6
  63. package/libs/function/type2icon.ts +3 -4
  64. package/libs/hooks/index.ts +1 -0
  65. package/libs/hooks/useCompRelation.ts +4 -4
  66. package/libs/hooks/useRect.ts +9 -4
  67. package/libs/hooks/useToast.ts +90 -0
  68. package/libs/index.ts +1 -1
  69. package/libs/request/index.ts +4 -4
  70. package/libs/util/config-provider.ts +10 -1
  71. package/package.json +1 -1
  72. package/types/global.d.ts +1 -1
@@ -25,7 +25,7 @@ function cssStrToObj(str: string): object {
25
25
  const value = values.join(':');
26
26
  if (prop && value) {
27
27
  const camelProp = prop.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
28
- result[camelProp] = value;
28
+ (result as Record<string, string>)[camelProp] = value;
29
29
  }
30
30
  });
31
31
  return result;
@@ -53,16 +53,16 @@ function cssObjToStr(obj: object): string {
53
53
  * 合并多个 CSS 输入(对象或字符串),返回一个 CSS 对象
54
54
  */
55
55
  export function mergeStyles(...args: (object | string)[]): CSSProperties {
56
- const result = {};
56
+ const result = {} as Record<string, any>;
57
57
  for (let i = 0; i < args.length; i++) {
58
58
  const arg = args[i];
59
- if (!isValidValue(arg)) return;
59
+ if (!isValidValue(arg)) return result as CSSProperties;
60
60
  if (typeof arg === 'string') {
61
61
  Object.assign(result, cssStrToObj(arg));
62
62
  } else if (test.object(arg)) {
63
- const cleanedObj = {};
63
+ const cleanedObj: Record<string, any> = {};
64
64
  Object.keys(arg).forEach(key => {
65
- const value = arg[key];
65
+ const value = (arg as Record<string, any>)[key];
66
66
  if (isValidValue(value)) {
67
67
  // 有效
68
68
  cleanedObj[key] = value;
@@ -210,7 +210,7 @@ function code(value: string, len: number = 6): boolean {
210
210
  * 是否函数方法
211
211
  * @param {Object} value
212
212
  */
213
- function func(value) {
213
+ function func(value: any) {
214
214
  return typeof value === 'function';
215
215
  }
216
216
 
@@ -218,14 +218,14 @@ function func(value) {
218
218
  * 是否promise对象
219
219
  * @param {Object} value
220
220
  */
221
- function promise(value) {
221
+ function promise(value: any) {
222
222
  return object(value) && func(value.then) && func(value.catch);
223
223
  }
224
224
 
225
225
  /** 是否图片格式
226
226
  * @param {Object} value
227
227
  */
228
- function image(value) {
228
+ function image(value: any) {
229
229
  const newValue = value.split('?')[0];
230
230
  const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
231
231
  return IMAGE_REGEXP.test(newValue);
@@ -235,7 +235,7 @@ function image(value) {
235
235
  * 是否视频格式
236
236
  * @param {Object} value
237
237
  */
238
- function video(value) {
238
+ function video(value: any) {
239
239
  const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i;
240
240
  return VIDEO_REGEXP.test(value);
241
241
  }
@@ -245,14 +245,14 @@ function video(value) {
245
245
  * @param {Object}
246
246
  * @return {Boolean}
247
247
  */
248
- function regExp(o) {
248
+ function regExp(o: any) {
249
249
  return o && Object.prototype.toString.call(o) === '[object RegExp]';
250
250
  }
251
251
 
252
252
  /**
253
253
  * 验证字符串
254
254
  */
255
- function string(value) {
255
+ function string(value: any) {
256
256
  return typeof value === 'string';
257
257
  }
258
258
 
@@ -1,13 +1,12 @@
1
+ import type { ThemeType } from '../../types/global';
2
+
1
3
  /**
2
4
  * 根据主题type值,获取对应的图标
3
5
  * @param type 主题名称, primary|info|error|warning|success,默认success
4
6
  * @param fill 是否使用fill填充实体的图标,默认false
5
7
  * @returns 图标名称字符串
6
8
  */
7
- function type2icon(
8
- type: 'primary' | 'info' | 'error' | 'warning' | 'success' = 'success',
9
- fill: boolean = false
10
- ): string {
9
+ function type2icon(type: ThemeType = 'success', fill: boolean = false): string {
11
10
  // 如果非预置值,默认为success
12
11
  if (!['primary', 'info', 'error', 'warning', 'success'].includes(type)) type = 'success';
13
12
  let iconName = '';
@@ -6,3 +6,4 @@ export * from './useColor';
6
6
  export * from './useLocale';
7
7
  export * from './useDebounce';
8
8
  export * from './useThrottle';
9
+ export * from './useToast';
@@ -199,13 +199,13 @@ export function useParent(componentName?: string) {
199
199
  };
200
200
 
201
201
  if (instance.proxy) {
202
- instance.proxy[PARENT_CONTEXT_SYMBOL] = parentContext;
202
+ (instance.proxy as any)[PARENT_CONTEXT_SYMBOL] = parentContext;
203
203
  }
204
204
 
205
205
  onUnmounted(() => {
206
206
  childrenMap.forEach((_, childId) => parentContext.removeChild(childId));
207
207
  if (instance.proxy) {
208
- delete instance.proxy[PARENT_CONTEXT_SYMBOL];
208
+ delete (instance.proxy as any)[PARENT_CONTEXT_SYMBOL];
209
209
  }
210
210
  logger.log(`Parent ${name} unmounted and cleaned up`);
211
211
  });
@@ -279,7 +279,7 @@ export function useChildren(componentName?: string, parentName?: string) {
279
279
 
280
280
  let current = instance.parent;
281
281
  while (current) {
282
- const context = current.proxy?.[PARENT_CONTEXT_SYMBOL];
282
+ const context = (current.proxy as any)?.[PARENT_CONTEXT_SYMBOL];
283
283
  if (context) {
284
284
  if (!context.getInstance) {
285
285
  context.getInstance = () => current;
@@ -384,7 +384,7 @@ export function hasParent(parentName?: string): boolean {
384
384
 
385
385
  let current = instance.parent;
386
386
  while (current) {
387
- if (current.proxy?.[PARENT_CONTEXT_SYMBOL]) return true;
387
+ if ((current.proxy as any)?.[PARENT_CONTEXT_SYMBOL]) return true;
388
388
  current = current.parent;
389
389
  }
390
390
  return false;
@@ -6,11 +6,11 @@ import { getCurrentInstance, nextTick, ref } from 'vue';
6
6
  * @param all 是否获取所有匹配元素
7
7
  * @returns rect 响应式的节点信息,refresh 主动刷新方法
8
8
  */
9
- export function useRect(selector: string = null, all = false) {
9
+ export function useRect(selector: string | null = null, all = false) {
10
10
  const rect = ref<any>(all ? [] : null);
11
11
  const instance = getCurrentInstance();
12
12
 
13
- async function getRect(realSelector: string = null, delay = 0): Promise<any> {
13
+ async function getRect(realSelector: string | null = null, delay = 0): Promise<any> {
14
14
  realSelector = realSelector || selector;
15
15
  if (!realSelector) return rect.value;
16
16
  await nextTick();
@@ -18,7 +18,7 @@ export function useRect(selector: string = null, all = false) {
18
18
  setTimeout(() => {
19
19
  uni.createSelectorQuery()
20
20
  .in(instance?.proxy)
21
- [all ? 'selectAll' : 'select'](realSelector)
21
+ [all ? 'selectAll' : 'select'](realSelector as string)
22
22
  .boundingClientRect((res: any) => {
23
23
  rect.value = res;
24
24
  resolve(res);
@@ -28,8 +28,13 @@ export function useRect(selector: string = null, all = false) {
28
28
  });
29
29
  }
30
30
 
31
+ function refresh(selector?: string | null, delay?: number): Promise<any> {
32
+ return getRect(selector, delay);
33
+ }
34
+
31
35
  return {
32
36
  rect,
33
- getRect
37
+ getRect,
38
+ refresh
34
39
  };
35
40
  }
@@ -0,0 +1,90 @@
1
+ import {
2
+ U_TOAST_EVENT_HIDE,
3
+ U_TOAST_EVENT_SHOW,
4
+ U_TOAST_GLOBAL_EVENT_HIDE,
5
+ U_TOAST_GLOBAL_EVENT_SHOW,
6
+ type ToastPayload
7
+ } from '../../components/u-toast/service';
8
+ import type { ThemeType } from '../../types/global';
9
+
10
+ export type UseToastShowOptions = ToastPayload;
11
+
12
+ export type UseToast = {
13
+ /**
14
+ * 显示 toast
15
+ * - show('文本')
16
+ * - show({ title, type, duration, ... })
17
+ */
18
+ show: (titleOrOptions: string | UseToastShowOptions) => void;
19
+ /** 关闭 toast */
20
+ close: () => void;
21
+ /** 成功 */
22
+ success: (titleOrOptions: string | UseToastShowOptions) => void;
23
+ /** 错误 */
24
+ error: (titleOrOptions: string | UseToastShowOptions) => void;
25
+ /** 警告 */
26
+ warning: (titleOrOptions: string | UseToastShowOptions) => void;
27
+ /** 信息 */
28
+ info: (titleOrOptions: string | UseToastShowOptions) => void;
29
+ /** 加载中(默认常驻,需 close 关闭) */
30
+ loading: (titleOrOptions: string | UseToastShowOptions) => void;
31
+ };
32
+
33
+ export type UseToastOptions = {
34
+ /** 是否使用全局根部 <u-toast global />,默认 true;为 false 时走页面级 <u-toast /> */
35
+ global?: boolean;
36
+ };
37
+
38
+ function normalize(titleOrOptions: string | UseToastShowOptions): UseToastShowOptions {
39
+ if (typeof titleOrOptions === 'string') return { title: titleOrOptions };
40
+ return titleOrOptions || {};
41
+ }
42
+
43
+ /**
44
+ * Toast 函数式调用
45
+ * @description 需要页面/应用中至少存在一个 <u-toast /> 实例用于承接事件;不影响原 ref 调用方式。
46
+ * 支持两种调用方式:useToast() / useToast({ global: false }) / useToast(false)
47
+ */
48
+ export function useToast(): UseToast;
49
+ export function useToast(options: UseToastOptions): UseToast;
50
+ export function useToast(global: boolean): UseToast;
51
+ export function useToast(optionsOrGlobal: UseToastOptions | boolean = {}): UseToast {
52
+ const isGlobal =
53
+ typeof optionsOrGlobal === 'boolean' ? optionsOrGlobal !== false : optionsOrGlobal.global !== false;
54
+ const showEvent = isGlobal ? U_TOAST_GLOBAL_EVENT_SHOW : U_TOAST_EVENT_SHOW;
55
+ const hideEvent = isGlobal ? U_TOAST_GLOBAL_EVENT_HIDE : U_TOAST_EVENT_HIDE;
56
+
57
+ function emitShow(payload: UseToastShowOptions) {
58
+ uni?.$emit && uni.$emit(showEvent, payload);
59
+ }
60
+
61
+ function emitHide() {
62
+ uni?.$emit && uni.$emit(hideEvent);
63
+ }
64
+ function show(titleOrOptions: string | UseToastShowOptions) {
65
+ emitShow(normalize(titleOrOptions));
66
+ }
67
+
68
+ function close() {
69
+ emitHide();
70
+ }
71
+
72
+ function withType(type: ThemeType, titleOrOptions: string | UseToastShowOptions) {
73
+ const options = normalize(titleOrOptions);
74
+ emitShow({ ...options, type });
75
+ }
76
+
77
+ return {
78
+ show,
79
+ close,
80
+ success: (v: any) => withType('success', v),
81
+ error: (v: any) => withType('error', v),
82
+ warning: (v: any) => withType('warning', v),
83
+ info: (v: any) => withType('info', v),
84
+ loading: (v: any) => {
85
+ const options = normalize(v);
86
+ // loading 通常需要常驻,除非用户显式传 duration
87
+ emitShow({ ...options, loading: true, duration: options.duration ?? 1e9 });
88
+ }
89
+ };
90
+ }
package/libs/index.ts CHANGED
@@ -248,7 +248,7 @@ export function kebabCase(word: string): string {
248
248
  * @param {number} value 堵塞时间 单位ms 毫秒
249
249
  * @returns {Promise} 返回promise
250
250
  */
251
- export function sleep(value: number = 30) {
251
+ export function sleep(value: number = 30): Promise<boolean> {
252
252
  return new Promise(resolve => {
253
253
  setTimeout(() => {
254
254
  resolve(true);
@@ -223,7 +223,7 @@ export class Request {
223
223
  method: 'GET',
224
224
  url,
225
225
  data,
226
- header: options.header,
226
+ header: options.header || {},
227
227
  meta: options.meta
228
228
  });
229
229
  }
@@ -237,7 +237,7 @@ export class Request {
237
237
  url,
238
238
  method: 'POST',
239
239
  data,
240
- header: options.header,
240
+ header: options.header || {},
241
241
  meta: options.meta
242
242
  });
243
243
  }
@@ -251,7 +251,7 @@ export class Request {
251
251
  url,
252
252
  method: 'PUT',
253
253
  data,
254
- header: options.header,
254
+ header: options.header || {},
255
255
  meta: options.meta
256
256
  });
257
257
  }
@@ -265,7 +265,7 @@ export class Request {
265
265
  url,
266
266
  method: 'DELETE',
267
267
  data,
268
- header: options.header,
268
+ header: options.header || {},
269
269
  meta: options.meta
270
270
  });
271
271
  }
@@ -67,7 +67,7 @@ export class ConfigProvider {
67
67
  private debug: boolean = false;
68
68
  private systemDarkModeMediaQuery: MediaQueryList | null = null;
69
69
  private lastAppliedCssKeys: string[] = [];
70
- private interval = 0;
70
+ private interval: ReturnType<typeof setInterval> | number = 0;
71
71
 
72
72
  constructor() {
73
73
  // 默认不自动初始化,调用 init 以传入主题列表
@@ -334,6 +334,15 @@ export class ConfigProvider {
334
334
  * replacements 支持数组或对象替换占位符 {0} 或 {name}
335
335
  */
336
336
  t(key: string, replacements?: any, localeName?: string): string {
337
+ // 如果 locales 尚未初始化,尝试懒初始化,使用内置语言包作为回退
338
+ try {
339
+ if (!Array.isArray(this.localesRef.value) || this.localesRef.value.length === 0) {
340
+ this.initLocales();
341
+ }
342
+ } catch (e) {
343
+ if (this.debug) console.warn('[ConfigProvider] lazy initLocales failed', e);
344
+ }
345
+
337
346
  const localeObj =
338
347
  (localeName && this.localesRef.value.find(l => l.name === localeName)) || this.currentLocaleRef.value;
339
348
  if (!localeObj) return key;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "uview-pro",
3
3
  "name": "uview-pro",
4
4
  "displayName": "【支持鸿蒙】uView Pro|基于Vue3+TS的高质量UI组件库,支持多主题、暗黑模式、多语言",
5
- "version": "0.5.2",
5
+ "version": "0.5.4",
6
6
  "description": "uView Pro是基于Vue3+TS的多平台UI框架,提供80+高质量组件、便捷工具和常用模板,支持多主题、暗黑模式、多语言,支持H5/APP/鸿蒙/小程序多端开发。已在鸿蒙应用商店上架,欢迎体验!",
7
7
  "main": "index.ts",
8
8
  "module": "index.ts",
package/types/global.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type ThemeType = 'primary' | 'info' | 'error' | 'warning' | 'success';
1
+ export type ThemeType = 'primary' | 'info' | 'error' | 'warning' | 'success' | 'default';
2
2
 
3
3
  export type ImgMode = 'aspectFit' | 'aspectFill' | 'widthFix' | 'top' | 'bottom' | 'center' | 'scaleToFill';
4
4