sard-uniapp 1.20.1 → 1.21.0

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 (81) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +3 -2
  3. package/components/config/index.d.ts +5 -0
  4. package/components/config/index.js +5 -0
  5. package/components/crop-image-agent/common.js +1 -1
  6. package/components/crop-image-agent/crop-image-agent.vue +1 -1
  7. package/components/dialog/README.md +19 -3
  8. package/components/dialog/common.d.ts +0 -1
  9. package/components/dialog/dialog.vue +1 -2
  10. package/components/dialog-agent/common.d.ts +5 -2
  11. package/components/dialog-agent/common.js +2 -2
  12. package/components/dialog-agent/dialog-agent.d.ts +7 -1
  13. package/components/dialog-agent/dialog-agent.vue +123 -9
  14. package/components/dialog-agent/index.d.ts +1 -1
  15. package/components/dialog-agent/index.js +1 -1
  16. package/components/fab/README.md +6 -0
  17. package/components/fab/fab.vue +1 -1
  18. package/components/list/README.md +19 -12
  19. package/components/list/common.d.ts +6 -1
  20. package/components/list/common.js +1 -0
  21. package/components/list/index.scss +8 -0
  22. package/components/list/list.vue +12 -2
  23. package/components/list-item/index.scss +6 -0
  24. package/components/list-item/list-item.vue +6 -3
  25. package/components/locale/lang/en-US.js +1 -1
  26. package/components/locale/lang/zh-CN.js +1 -1
  27. package/components/notify/README.md +38 -3
  28. package/components/notify/common.d.ts +5 -1
  29. package/components/notify/index.d.ts +1 -1
  30. package/components/notify/notify.d.ts +14 -7
  31. package/components/notify/notify.vue +25 -4
  32. package/components/notify-agent/common.d.ts +5 -2
  33. package/components/notify-agent/common.js +2 -2
  34. package/components/notify-agent/index.d.ts +1 -1
  35. package/components/notify-agent/index.js +1 -1
  36. package/components/notify-agent/notify-agent.d.ts +7 -1
  37. package/components/notify-agent/notify-agent.vue +90 -5
  38. package/components/popup/common.d.ts +11 -0
  39. package/components/toast/README.md +28 -6
  40. package/components/toast/common.d.ts +2 -1
  41. package/components/toast/toast.d.ts +5 -3
  42. package/components/toast/toast.vue +17 -3
  43. package/components/toast-agent/common.d.ts +5 -2
  44. package/components/toast-agent/common.js +2 -2
  45. package/components/toast-agent/index.d.ts +1 -1
  46. package/components/toast-agent/index.js +1 -1
  47. package/components/toast-agent/toast-agent.d.ts +7 -1
  48. package/components/toast-agent/toast-agent.vue +85 -5
  49. package/components/upload/README.md +31 -23
  50. package/components/upload/common.d.ts +4 -1
  51. package/components/upload/upload.vue +4 -4
  52. package/components/waterfall/README.md +162 -0
  53. package/components/waterfall/common.d.ts +32 -0
  54. package/components/waterfall/common.js +3 -0
  55. package/components/waterfall/index.d.ts +1 -0
  56. package/components/waterfall/index.js +1 -0
  57. package/components/waterfall/index.scss +7 -0
  58. package/components/waterfall/test/SimulatedImage.vue +53 -0
  59. package/components/waterfall/variables.scss +6 -0
  60. package/components/waterfall/waterfall.d.ts +23 -0
  61. package/components/waterfall/waterfall.vue +182 -0
  62. package/components/waterfall-item/common.d.ts +23 -0
  63. package/components/waterfall-item/common.js +1 -0
  64. package/components/waterfall-item/index.d.ts +1 -0
  65. package/components/waterfall-item/index.js +1 -0
  66. package/components/waterfall-item/index.scss +18 -0
  67. package/components/waterfall-item/waterfall-item.d.ts +10 -0
  68. package/components/waterfall-item/waterfall-item.vue +115 -0
  69. package/components/waterfall-load/common.d.ts +19 -0
  70. package/components/waterfall-load/common.js +1 -0
  71. package/components/waterfall-load/index.d.ts +1 -0
  72. package/components/waterfall-load/index.js +1 -0
  73. package/components/waterfall-load/index.scss +12 -0
  74. package/components/waterfall-load/waterfall-load.d.ts +14 -0
  75. package/components/waterfall-load/waterfall-load.vue +87 -0
  76. package/global.d.ts +3 -0
  77. package/index.d.ts +3 -0
  78. package/index.js +3 -0
  79. package/index.scss +1 -0
  80. package/package.json +1 -1
  81. package/utils/utils.d.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <sar-toast
3
3
  ref="elRef"
4
- v-model:visible="innerProps.visible"
4
+ :visible="innerProps.visible"
5
5
  :root-style="innerProps.rootStyle"
6
6
  :root-class="innerProps.rootClass"
7
7
  :type="innerProps.type"
@@ -11,6 +11,16 @@
11
11
  :transparent="innerProps.transparent"
12
12
  :timeout="innerProps.timeout"
13
13
  :duration="innerProps.duration"
14
+ @update:visible="onUpdateVisible"
15
+ @visible-hook="onVisibleHook"
16
+ @before-enter="onBeforeEnter"
17
+ @enter="onEnter"
18
+ @after-enter="onAfterEnter"
19
+ @enter-cancelled="onEnterCancelled"
20
+ @before-leave="onBeforeLeave"
21
+ @leave="onLeave"
22
+ @after-leave="onAfterLeave"
23
+ @leave-cancelled="onLeaveCancelled"
14
24
  />
15
25
  </template>
16
26
 
@@ -22,7 +32,7 @@ import {
22
32
  imperativeName,
23
33
  defaultToastAgentProps
24
34
  } from "./common";
25
- import { useImperative } from "../../use/useImperative";
35
+ import { useImperative } from "../../use";
26
36
  /**
27
37
  * @property {'text' | 'loading' | 'success' | 'fail'} type 提示框类型,默认值:'text'。
28
38
  * @property {string | number} title 标题,默认值:-。
@@ -33,6 +43,25 @@ import { useImperative } from "../../use/useImperative";
33
43
  * @property {number} timeout 提示的延迟时间,单位 ms,默认值:1500。
34
44
  * @property {number} duration 显隐动画时长,单位 ms,默认值:300。
35
45
  * @property {string} id 提示组件的 id,默认值:'toast'。
46
+ * @property {(name: TransitionHookName) => void} onVisibleHook 入场/退场动画状态改变时调用,默认值:undefined。
47
+ * @property {() => void} onBeforeEnter 入场动画开始前调用,默认值:undefined。
48
+ * @property {() => void} onEnter 入场动画开始时调用,默认值:undefined。
49
+ * @property {() => void} onAfterEnter 入场动画结束时调用,默认值:undefined。
50
+ * @property {() => void} onEnterCancelled 入场动画取消时调用,默认值:undefined。
51
+ * @property {() => void} onBeforeLeave 退场动画开始前调用,默认值:undefined。
52
+ * @property {() => void} onLeave 退场动画开始时调用,默认值:undefined。
53
+ * @property {() => void} onAfterLeave 退场动画结束时调用,默认值:undefined。
54
+ * @property {() => void} onLeaveCancelled 退场动画取消时调用,默认值:undefined。
55
+ * @event {(visible: boolean) => void} update 提示框显隐时触发
56
+ * @event {(name: TransitionHookName) => void} visible-hook 入场/退场动画状态改变时触发
57
+ * @event {() => void} before-enter 入场动画开始前触发
58
+ * @event {() => void} enter 入场动画开始时触发
59
+ * @event {() => void} after-enter 入场动画结束时触发
60
+ * @event {() => void} enter-cancelled 入场动画取消时触发
61
+ * @event {() => void} before-leave 退场动画开始前触发
62
+ * @event {() => void} leave 退场动画开始时触发
63
+ * @event {() => void} after-leave 退场动画结束时触发
64
+ * @event {() => void} leave-cancelled 退场动画取消时触发
36
65
  */
37
66
  export default _defineComponent({
38
67
  components: {
@@ -56,11 +85,22 @@ export default _defineComponent({
56
85
  overlay: { type: Boolean, required: false },
57
86
  transparent: { type: Boolean, required: false },
58
87
  timeout: { type: Number, required: false },
59
- duration: { type: Number, required: false }
88
+ duration: { type: Number, required: false },
89
+ onVisibleHook: { type: Function, required: false },
90
+ onBeforeEnter: { type: Function, required: false },
91
+ onEnter: { type: Function, required: false },
92
+ onAfterEnter: { type: Function, required: false },
93
+ onEnterCancelled: { type: Function, required: false },
94
+ onBeforeLeave: { type: Function, required: false },
95
+ onLeave: { type: Function, required: false },
96
+ onAfterLeave: { type: Function, required: false },
97
+ onLeaveCancelled: { type: Function, required: false }
60
98
  }, defaultToastAgentProps()),
61
- setup(__props, { expose: __expose }) {
99
+ emits: ["update:visible", "before-enter", "enter", "after-enter", "enter-cancelled", "before-leave", "leave", "after-leave", "leave-cancelled", "visible-hook"],
100
+ setup(__props, { expose: __expose, emit: __emit }) {
62
101
  __expose();
63
102
  const props = __props;
103
+ const emit = __emit;
64
104
  const innerProps = ref({ ...props });
65
105
  const elRef = ref();
66
106
  const imperative = {
@@ -80,12 +120,52 @@ export default _defineComponent({
80
120
  elRef.value?.cancelHide();
81
121
  }
82
122
  };
123
+ const onUpdateVisible = (visible) => {
124
+ innerProps.value.visible = visible;
125
+ emit("update:visible", visible);
126
+ };
127
+ const onVisibleHook = (name) => {
128
+ emit("visible-hook", name);
129
+ innerProps.value.onVisibleHook?.(name);
130
+ };
131
+ const onBeforeEnter = () => {
132
+ emit("before-enter");
133
+ innerProps.value.onBeforeEnter?.();
134
+ };
135
+ const onEnter = () => {
136
+ emit("enter");
137
+ innerProps.value.onEnter?.();
138
+ };
139
+ const onAfterEnter = () => {
140
+ emit("after-enter");
141
+ innerProps.value.onAfterEnter?.();
142
+ };
143
+ const onEnterCancelled = () => {
144
+ emit("enter-cancelled");
145
+ innerProps.value.onEnterCancelled?.();
146
+ };
147
+ const onBeforeLeave = () => {
148
+ emit("before-leave");
149
+ innerProps.value.onBeforeLeave?.();
150
+ };
151
+ const onLeave = () => {
152
+ emit("leave");
153
+ innerProps.value.onLeave?.();
154
+ };
155
+ const onAfterLeave = () => {
156
+ emit("after-leave");
157
+ innerProps.value.onAfterLeave?.();
158
+ };
159
+ const onLeaveCancelled = () => {
160
+ emit("leave-cancelled");
161
+ innerProps.value.onLeaveCancelled?.();
162
+ };
83
163
  useImperative(
84
164
  imperativeName,
85
165
  imperative,
86
166
  computed(() => innerProps.value.id)
87
167
  );
88
- const __returned__ = { props, innerProps, elRef, imperative, SarToast };
168
+ const __returned__ = { props, emit, innerProps, elRef, imperative, onUpdateVisible, onVisibleHook, onBeforeEnter, onEnter, onAfterEnter, onEnterCancelled, onBeforeLeave, onLeave, onAfterLeave, onLeaveCancelled, SarToast };
89
169
  return __returned__;
90
170
  }
91
171
  });
@@ -43,7 +43,7 @@ import Upload from 'sard-uniapp/components/upload/upload.vue'
43
43
 
44
44
  ### 选择文件前置处理 <sup>1.19.2+</sup>
45
45
 
46
- 通过传入 `beforeChoose` 函数可以在选择之前做处理,接受当前文件列表和 `next` 函数作参数,调用 `next(true)` 允许选择,调用 `next(false)` 不允许选择。
46
+ 通过传入 `beforeChoose` 函数可以在选择之前做处理,接受当前文件列表和 `next` 函数作参数,调用 `next(true)` 允许选择,调用 `next(false)` 不允许选择,也可传入一个配置对象自定义选择。
47
47
 
48
48
  @code('${DEMO_PATH}/upload/demo/BeforeChoose.vue')
49
49
 
@@ -87,28 +87,36 @@ import Upload from 'sard-uniapp/components/upload/upload.vue'
87
87
 
88
88
  ### UploadProps
89
89
 
90
- | 属性 | 描述 | 类型 | 默认值 |
91
- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------------------------- |
92
- | root-class | 组件根元素类名 | string | - |
93
- | root-style | 组件根元素样式 | StyleValue | - |
94
- | accept | 允许上传的文件类型 | 'image' \| 'video' | 'image' |
95
- | multiple | 是否开启图片多选 | boolean | false |
96
- | source-type | 文件选择来源 | ('album' \| 'camera')[] | ['album', 'camera'] |
97
- | size-type | 所选的图片的尺寸 | ('original' \| 'compressed')[] | ['original', 'compressed'] |
98
- | max-duration | 拍摄视频最长拍摄时间,单位秒 | number | 60 |
99
- | camera | 默认拉起的是前置或者后置摄像头。部分 Android 手机下由于系统 ROM 不支持无法生效 | 'back' \| 'front' | 'back' |
100
- | model-value (v-model) | 已上传的文件列表 | UploadFileItem[] | - |
101
- | max-count | 文件上传数量限制 | number | Number.MAX_SAFE_INTEGER |
102
- | max-size | 文件大小限制,单位为 `byte` | number \| ((file: File) => boolean) | Number.MAX_SAFE_INTEGER |
103
- | over-size | 文件大小超过限制时触发 | (fileItem: UploadFileItem \| UploadFileItem[]) => void | - |
104
- | disabled | 是否禁用文件上传 | boolean | false |
105
- | readonly | 是否将上传区域设置为只读状态 | boolean | false |
106
- | before-choose <sup>1.19.2+</sup> | 文件选择前的回调,接受当前文件列表和 `next` 函数作参数,调用 `next(true)` 允许选择,调用 `next(false)` 不允许选择 | (fileList: UploadFileItem[], next: (allowed: boolean) => void) => void | - |
107
- | before-read | 文件读取前的回调,返回 false 可终止文件读取,支持返回 Promise | (file: File) => boolean \| Promise\<File> | - |
108
- | after-read | 文件读取完成后的回调 | (fileItem: UploadFileItem \| UploadFileItem[]) => void | - |
109
- | removable | 是否可删除 | boolean | true |
110
- | before-remove | 文件删除前的回调,返回 false 可终止文件删除,支持返回 Promise | (index: number, fileItem: UploadFileItem) => boolean \| Promise\<any> | - |
111
- | validate-event | 是否触发表单验证 | boolean | true |
90
+ | 属性 | 描述 | 类型 | 默认值 |
91
+ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------------------------- |
92
+ | root-class | 组件根元素类名 | string | - |
93
+ | root-style | 组件根元素样式 | StyleValue | - |
94
+ | accept | 允许上传的文件类型 | 'image' \| 'video' | 'image' |
95
+ | multiple | 是否开启图片多选 | boolean | false |
96
+ | source-type | 文件选择来源 | ('album' \| 'camera')[] | ['album', 'camera'] |
97
+ | size-type | 所选的图片的尺寸 | ('original' \| 'compressed')[] | ['original', 'compressed'] |
98
+ | max-duration | 拍摄视频最长拍摄时间,单位秒 | number | 60 |
99
+ | camera | 默认拉起的是前置或者后置摄像头。部分 Android 手机下由于系统 ROM 不支持无法生效 | 'back' \| 'front' | 'back' |
100
+ | model-value (v-model) | 已上传的文件列表 | UploadFileItem[] | - |
101
+ | max-count | 文件上传数量限制 | number | Number.MAX_SAFE_INTEGER |
102
+ | max-size | 文件大小限制,单位为 `byte` | number \| ((file: File) => boolean) | Number.MAX_SAFE_INTEGER |
103
+ | over-size | 文件大小超过限制时触发 | (fileItem: UploadFileItem \| UploadFileItem[]) => void | - |
104
+ | disabled | 是否禁用文件上传 | boolean | false |
105
+ | readonly | 是否将上传区域设置为只读状态 | boolean | false |
106
+ | before-choose <sup>1.19.2+</sup> | 文件选择前的回调,接受当前文件列表和 `next` 函数作参数,调用 `next(true)` 允许选择,调用 `next(false)` 不允许选择,或者传入一个配置对象自定义选择 | (fileList: UploadFileItem[], next: (allowed: boolean \| UploadSelectOptions) => void) => void | - |
107
+ | before-read | 文件读取前的回调,返回 false 可终止文件读取,支持返回 Promise | (file: File) => boolean \| Promise\<File> | - |
108
+ | after-read | 文件读取完成后的回调 | (fileItem: UploadFileItem \| UploadFileItem[]) => void | - |
109
+ | removable | 是否可删除 | boolean | true |
110
+ | before-remove | 文件删除前的回调,返回 false 可终止文件删除,支持返回 Promise | (index: number, fileItem: UploadFileItem) => boolean \| Promise\<any> | - |
111
+ | validate-event | 是否触发表单验证 | boolean | true |
112
+
113
+ ### UploadSelectOptions <sup>1.21.0+</sup>
114
+
115
+ ```ts
116
+ interface UploadSelectOptions {
117
+ sourceType?: ('album' | 'camera')[]
118
+ }
119
+ ```
112
120
 
113
121
  ### UploadSlots
114
122
 
@@ -20,6 +20,9 @@ export interface UploadFileItem {
20
20
  message?: string;
21
21
  [key: PropertyKey]: any;
22
22
  }
23
+ export interface UploadSelectOptions {
24
+ sourceType?: ('album' | 'camera')[];
25
+ }
23
26
  export interface UploadProps {
24
27
  rootStyle?: StyleValue;
25
28
  rootClass?: string;
@@ -35,7 +38,7 @@ export interface UploadProps {
35
38
  overSize?: (fileItem: UploadFileItem[]) => void;
36
39
  disabled?: boolean;
37
40
  readonly?: boolean;
38
- beforeChoose?: (fileList: UploadFileItem[], next: (allowed: boolean) => void) => void;
41
+ beforeChoose?: (fileList: UploadFileItem[], next: (allowed: boolean | UploadSelectOptions) => void) => void;
39
42
  beforeRead?: (file: UploadFile) => boolean | Promise<UploadFile>;
40
43
  afterRead?: (fileItem: UploadFileItem) => void;
41
44
  removable?: boolean;
@@ -69,7 +69,7 @@ import { useFormContext, useFormItemContext } from "../form/common";
69
69
  * @property {(fileItem: UploadFileItem | UploadFileItem[]) => void} overSize 文件大小超过限制时触发,默认值:-。
70
70
  * @property {boolean} disabled 是否禁用文件上传,默认值:false。
71
71
  * @property {boolean} readonly 是否将上传区域设置为只读状态,默认值:false。
72
- * @property {(fileList: UploadFileItem[], next: (allowed: boolean) => void) => void} beforeChoose 文件选择前的回调,接受当前文件列表和 `next` 函数作参数,调用 `next(true)` 允许选择,调用 `next(false)` 不允许选择,默认值:-。
72
+ * @property {(fileList: UploadFileItem[], next: (allowed: boolean | UploadSelectOptions) => void) => void} beforeChoose 文件选择前的回调,接受当前文件列表和 `next` 函数作参数,调用 `next(true)` 允许选择,调用 `next(false)` 不允许选择,或者传入一个配置对象自定义选择,默认值:-。
73
73
  * @property {(file: File) => boolean | Promise\<File>} beforeRead 文件读取前的回调,返回 false 可终止文件读取,支持返回 Promise,默认值:-。
74
74
  * @property {(fileItem: UploadFileItem | UploadFileItem[]) => void} afterRead 文件读取完成后的回调,默认值:-。
75
75
  * @property {boolean} removable 是否可删除,默认值:true。
@@ -233,12 +233,12 @@ export default _defineComponent({
233
233
  if (isSelectPending || isDisabled.value || isReadonly.value || innerValue.value.length >= props.maxCount) {
234
234
  return;
235
235
  }
236
- const next = () => {
236
+ const next = (options = {}) => {
237
237
  chooseMedia({
238
238
  mediaType: props.accept,
239
239
  count: props.multiple ? 9999 : 1,
240
240
  sizeType: props.sizeType,
241
- sourceType: props.sourceType,
241
+ sourceType: options.sourceType || props.sourceType,
242
242
  maxDuration: props.maxDuration,
243
243
  camera: props.camera,
244
244
  success(result) {
@@ -264,7 +264,7 @@ export default _defineComponent({
264
264
  props.beforeChoose?.(innerValue.value, (allowed) => {
265
265
  isSelectPending = false;
266
266
  if (allowed) {
267
- next();
267
+ next(typeof allowed === "object" ? allowed : void 0);
268
268
  }
269
269
  });
270
270
  } else {
@@ -0,0 +1,162 @@
1
+ ---
2
+ nav: 组件
3
+ title: Waterfall
4
+ subtitle: 瀑布流
5
+ group: 布局
6
+ version: 1.21.0+
7
+ ---
8
+
9
+ ## 介绍
10
+
11
+ 按照元素高度自适应排列,形成参差不齐的多列布局。
12
+
13
+ ## 引入
14
+
15
+ ```ts
16
+ import Waterfall from 'sard-uniapp/components/waterfall/waterfall.vue'
17
+ ```
18
+
19
+ ## 代码演示
20
+
21
+ ### 基础使用
22
+
23
+ 瀑布流布局是使用绝对定位实现的,每一项内容需放置在 `WaterfallItem` 组件里面以便控制其位置;可放置任意内容,并不限定为具体模板。
24
+
25
+ 如果里面包含图片或其他使其在挂载后仍然不确定高度的组件时,需在加载完后调用瀑布流项的 `load` 插槽中的 `onLoad` 回调,以便计算其渲染后的高度并进行准确定位。
26
+
27
+ 瀑布流会按照渲染的顺序逐一将加载好的瀑布流项渲染出来;如果后面比前面要先加载完,也得等前面加载完才能渲染。因此,如果前面有一张很大的图片需要很久才能加载完,则会堵塞后面的渲染。
28
+
29
+ 因此,一次性不要加载太多图片,图片的尺寸也要有所限制。
30
+
31
+ 瀑布流组件的 `load` 事件会在所有项都加载完后触发,可以用来处理加载状态。
32
+
33
+ @code('${DEMO_PATH}/waterfall/demo/Basic.vue')
34
+
35
+ `SimulatedImage.vue`
36
+
37
+ @code('${DEMO_PATH}/waterfall/demo/SimulatedImage.vue')
38
+
39
+ ### 已知宽高
40
+
41
+ 如果接口已将图片宽高信息返回,可以使用 `WaterfallLoad` 组件处理 `onLoad` 回调,会在挂载时调用,无需等待图片加载完即可渲染,可极大提高用户体验。
42
+
43
+ `WaterfallLoad` 会根据 `width`、`height` 属性计算占用的空间。
44
+
45
+ @code('${DEMO_PATH}/waterfall/demo/KnownSize.vue')
46
+
47
+ ### 真实案例
48
+
49
+ 需同时监听 `image` 组件的 `load` 和 `error` 事件,确保 `onLoad` 回调函数能调用,无论图片加载成功或失败。
50
+
51
+ @code('${DEMO_PATH}/waterfall/demo/TrueCase.vue')
52
+
53
+ ### 最大等待时间
54
+
55
+ 为了避免因图片太大导致渲染阻塞,`WaterfallLoad` 组件提供了 `max-wait` 属性,在超过等待时间后取自定义的宽高进行渲染,无需等待图片加载完;加载时间小于等待时间时,则取图片实际的宽高进行渲染。
56
+
57
+ 宽高只用于计算比例来进行等比缩放,而不是最终的展示尺寸。
58
+
59
+ @code('${DEMO_PATH}/waterfall/demo/MaxWait.vue')
60
+
61
+ ### 大图
62
+
63
+ 可使用 `column-gap` 和 `row-gap` 设置瀑布流项的间隔大小,单位为 px。
64
+
65
+ @code('${DEMO_PATH}/waterfall/demo/BigImage.vue')
66
+
67
+ ### 自定义列数
68
+
69
+ 可使用 `columns` 属性设置任意的列数。
70
+
71
+ @code('${DEMO_PATH}/waterfall/demo/Columns.vue')
72
+
73
+ ### 结合下拉刷新与触底加载
74
+
75
+ 可配合 `LoadMore` 和 `PullDownRefresh` 组件实现数据动态增减。
76
+
77
+ 因瀑布流在数据加载完后仍需等待图片加载,因此提供了 `onLoad` 方法,传递到此方法中的函数会在图片加载完后调用,可用于取消加载状态。
78
+
79
+ @code('${DEMO_PATH}/waterfall/demo/Dynamic.vue')
80
+
81
+ ## API
82
+
83
+ ### WaterfallProps
84
+
85
+ | 属性 | 描述 | 类型 | 默认值 |
86
+ | ---------- | -------------- | ---------- | ------ |
87
+ | root-class | 组件根元素类名 | string | - |
88
+ | root-style | 组件根元素样式 | StyleValue | - |
89
+ | columns | 自定义列数 | number | 2 |
90
+ | column-gap | 列间距,单位px | number | 16 |
91
+ | row-gap | 行间距,单位px | number | 16 |
92
+
93
+ ### WaterfallSlots
94
+
95
+ | 插槽 | 描述 | 属性 |
96
+ | ------- | -------------- | ---- |
97
+ | default | 自定义默认内容 | - |
98
+
99
+ ### WaterfallEmits
100
+
101
+ | 事件 | 描述 | 类型 |
102
+ | --------- | ------------------------ | ---------- |
103
+ | load | 所有瀑布流项加载完时触发 | () => void |
104
+ | loadstart | 瀑布流项项开始加载时触发 | () => void |
105
+
106
+ ### WaterfallExpose
107
+
108
+ | 属性 | 描述 | 类型 |
109
+ | ------ | -------------------------------- | ----------------------------- |
110
+ | reflow | 重新排版 | () => void |
111
+ | onLoad | 添加回调,会在所有项加载完时调用 | (handler: () => void) => void |
112
+
113
+ ### WaterfallItemProps
114
+
115
+ | 属性 | 描述 | 类型 | 默认值 |
116
+ | ---------- | -------------- | ---------- | ------ |
117
+ | root-class | 组件根元素类名 | string | - |
118
+ | root-style | 组件根元素样式 | StyleValue | - |
119
+
120
+ ### WaterfallItemSlots
121
+
122
+ | 插槽 | 描述 | 属性 |
123
+ | ------- | -------------- | ------------------------------------------- |
124
+ | default | 自定义默认内容 | { onLoad: () => void; columnWidth: number } |
125
+
126
+ default 插槽属性说明:
127
+
128
+ - `onLoad`: 图片加载完后(无论成功或失败)需要调用此方法。
129
+ - `columnWidth`: 列宽。
130
+
131
+ ### WaterfallLoadProps
132
+
133
+ | 属性 | 描述 | 类型 | 默认值 |
134
+ | ---------- | -------------------- | ---------- | ------ |
135
+ | root-class | 组件根元素类名 | string | - |
136
+ | root-style | 组件根元素样式 | StyleValue | - |
137
+ | max-wait | 最大等待时间,单位ms | number | 0 |
138
+ | width | 自定义宽度 | number | 320 |
139
+ | height | 自定义高度 | number | 240 |
140
+
141
+ ### WaterfallLoadSlots
142
+
143
+ | 插槽 | 描述 | 属性 |
144
+ | ------- | -------------- | --------------------------------------------------- |
145
+ | default | 自定义默认内容 | { onLoad: (event: any) => void; overtime: boolean } |
146
+
147
+ default 插槽属性说明:
148
+
149
+ - `onLoad`: 图片加载完后(成功和失败)可以调用此方法,加载完时间比 `max-wait` 要大则超时。
150
+ - `overtime`: 是否超时。
151
+
152
+ ### WaterfallEmits
153
+
154
+ | 事件 | 描述 | 类型 |
155
+ | ---- | ---------------------------------------- | ---------- |
156
+ | load | 加载完时触发,无论是正常加载完,还是超时 | () => void |
157
+
158
+ ## 主题定制
159
+
160
+ ### CSS 变量
161
+
162
+ @code('./variables.scss#variables')
@@ -0,0 +1,32 @@
1
+ import { InjectionKey, type StyleValue } from 'vue';
2
+ import { type WaterfallItemInfo } from '../waterfall-item/common';
3
+ export interface WaterfallProps {
4
+ rootStyle?: StyleValue;
5
+ rootClass?: string;
6
+ columns?: number;
7
+ columnGap?: number;
8
+ rowGap?: number;
9
+ }
10
+ export declare const defaultWaterfallProps: {
11
+ columns: number;
12
+ columnGap: number;
13
+ rowGap: number;
14
+ };
15
+ export interface WaterfallSlots {
16
+ default?(props: Record<string, never>): any;
17
+ }
18
+ export interface WaterfallEmits {
19
+ (e: 'load'): void;
20
+ (e: 'loadstart'): void;
21
+ }
22
+ export interface WaterfallExpose {
23
+ reflow: () => void;
24
+ onLoad: (handler: () => void) => void;
25
+ }
26
+ export interface WaterfallContext {
27
+ columnWidth: number;
28
+ addItem: (item: WaterfallItemInfo) => void;
29
+ removeItem: (item: WaterfallItemInfo) => void;
30
+ onItemLoad: () => void;
31
+ }
32
+ export declare const waterfallContextKey: InjectionKey<WaterfallContext>;
@@ -0,0 +1,3 @@
1
+ import { defaultConfig } from '../config';
2
+ export const defaultWaterfallProps = defaultConfig.waterfall;
3
+ export const waterfallContextKey = Symbol('waterfall-context');
@@ -0,0 +1 @@
1
+ export type { WaterfallProps, WaterfallSlots, WaterfallEmits, WaterfallExpose, } from './common';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ @use '../style/base' as *;
2
+
3
+ @include bem(waterfall) {
4
+ @include b() {
5
+ @include universal;
6
+ }
7
+ }
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <view class="relative box-border" :style="{ paddingTop }">
3
+ <view class="absolute inset-0 flex justify-center items-center sbg-fourth">
4
+ <text>{{ meta.width }}</text>
5
+ <text>x</text>
6
+ <text>{{ meta.height }}</text>
7
+ </view>
8
+ </view>
9
+ </template>
10
+
11
+ <script>
12
+ import { defineComponent as _defineComponent } from "vue";
13
+ import { useTimeout } from "../../../use";
14
+ import { random } from "../../../utils";
15
+ import { computed, onMounted, ref } from "vue";
16
+ export default _defineComponent({
17
+ __name: "SimulatedImage",
18
+ props: {
19
+ meta: { type: Object, required: true }
20
+ },
21
+ emits: ["load"],
22
+ setup(__props, { expose: __expose, emit: __emit }) {
23
+ __expose();
24
+ const props = __props;
25
+ const emit = __emit;
26
+ const internalWidth = ref(320);
27
+ const internalHeight = ref(240);
28
+ const currWidth = computed(() => internalWidth.value);
29
+ const currHeight = computed(() => internalHeight.value);
30
+ const paddingTop = computed(
31
+ () => currHeight.value / currWidth.value * 100 + "%"
32
+ );
33
+ const { start } = useTimeout(
34
+ () => {
35
+ internalWidth.value = props.meta.width;
36
+ internalHeight.value = props.meta.height;
37
+ emit("load", {
38
+ detail: {
39
+ width: props.meta.width,
40
+ height: props.meta.height
41
+ }
42
+ });
43
+ },
44
+ random(50, 150)
45
+ );
46
+ onMounted(() => {
47
+ start();
48
+ });
49
+ const __returned__ = { props, emit, internalWidth, internalHeight, currWidth, currHeight, paddingTop, start };
50
+ return __returned__;
51
+ }
52
+ });
53
+ </script>
@@ -0,0 +1,6 @@
1
+ // #variables
2
+ page,
3
+ .sar-portal {
4
+ --sar-waterfall-duration: var(--sar-duration);
5
+ }
6
+ // #endvariables
@@ -0,0 +1,23 @@
1
+ import { type WaterfallProps, type WaterfallSlots } from './common';
2
+ declare function __VLS_template(): Readonly<WaterfallSlots> & WaterfallSlots;
3
+ declare const __VLS_component: import("vue").DefineComponent<WaterfallProps, {
4
+ reflow: () => void;
5
+ onLoad: (handler: () => void) => void;
6
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
7
+ load: () => any;
8
+ loadstart: () => any;
9
+ }, string, import("vue").PublicProps, Readonly<WaterfallProps> & Readonly<{
10
+ onLoad?: (() => any) | undefined;
11
+ onLoadstart?: (() => any) | undefined;
12
+ }>, {
13
+ columns: number;
14
+ columnGap: number;
15
+ rowGap: number;
16
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
18
+ export default _default;
19
+ type __VLS_WithTemplateSlots<T, S> = T & {
20
+ new (): {
21
+ $slots: S;
22
+ };
23
+ };