sard-uniapp 1.20.2 → 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 (48) hide show
  1. package/CHANGELOG.md +17 -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/fab/README.md +6 -0
  6. package/components/fab/fab.vue +1 -1
  7. package/components/list/README.md +19 -12
  8. package/components/list/common.d.ts +6 -1
  9. package/components/list/common.js +1 -0
  10. package/components/list/index.scss +8 -0
  11. package/components/list/list.vue +12 -2
  12. package/components/list-item/index.scss +6 -0
  13. package/components/list-item/list-item.vue +6 -3
  14. package/components/locale/lang/en-US.js +1 -1
  15. package/components/locale/lang/zh-CN.js +1 -1
  16. package/components/upload/README.md +31 -23
  17. package/components/upload/common.d.ts +4 -1
  18. package/components/upload/upload.vue +4 -4
  19. package/components/waterfall/README.md +162 -0
  20. package/components/waterfall/common.d.ts +32 -0
  21. package/components/waterfall/common.js +3 -0
  22. package/components/waterfall/index.d.ts +1 -0
  23. package/components/waterfall/index.js +1 -0
  24. package/components/waterfall/index.scss +7 -0
  25. package/components/waterfall/test/SimulatedImage.vue +53 -0
  26. package/components/waterfall/variables.scss +6 -0
  27. package/components/waterfall/waterfall.d.ts +23 -0
  28. package/components/waterfall/waterfall.vue +182 -0
  29. package/components/waterfall-item/common.d.ts +23 -0
  30. package/components/waterfall-item/common.js +1 -0
  31. package/components/waterfall-item/index.d.ts +1 -0
  32. package/components/waterfall-item/index.js +1 -0
  33. package/components/waterfall-item/index.scss +18 -0
  34. package/components/waterfall-item/waterfall-item.d.ts +10 -0
  35. package/components/waterfall-item/waterfall-item.vue +115 -0
  36. package/components/waterfall-load/common.d.ts +19 -0
  37. package/components/waterfall-load/common.js +1 -0
  38. package/components/waterfall-load/index.d.ts +1 -0
  39. package/components/waterfall-load/index.js +1 -0
  40. package/components/waterfall-load/index.scss +12 -0
  41. package/components/waterfall-load/waterfall-load.d.ts +14 -0
  42. package/components/waterfall-load/waterfall-load.vue +87 -0
  43. package/global.d.ts +3 -0
  44. package/index.d.ts +3 -0
  45. package/index.js +3 -0
  46. package/index.scss +1 -0
  47. package/package.json +1 -1
  48. package/utils/utils.d.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # [1.21.0](https://github.com/sutras/sard-uniapp/compare/v1.20.2...v1.21.0) (2025-07-04)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * upload组件修改beforeChoose,多返回一个参数sourceType,用于区分当前选择项 ([d440c7e](https://github.com/sutras/sard-uniapp/commit/d440c7e166db4987507e642bda8d3fb6aa2a4c9b))
7
+ * 修复 fab 图标设置失败问题 ([da00f11](https://github.com/sutras/sard-uniapp/commit/da00f11ce8cd19ab712572d106ce94856739a228))
8
+
9
+
10
+ ### Features
11
+
12
+ * list 新增隐藏边框属性 ([6fbab69](https://github.com/sutras/sard-uniapp/commit/6fbab69ad4e637bc1bb12dea360e12413e398c74))
13
+ * upload组件选择前置允许配置 ([5f2a753](https://github.com/sutras/sard-uniapp/commit/5f2a7538f985a85226e52c19aa11699fa1c6aa9f))
14
+ * 新增瀑布流组件 ([8da700b](https://github.com/sutras/sard-uniapp/commit/8da700b367a63725f074d4431ac72e26b3e64cae))
15
+
16
+
17
+
1
18
  ## [1.20.2](https://github.com/sutras/sard-uniapp/compare/v1.20.1...v1.20.2) (2025-07-02)
2
19
 
3
20
 
package/README.md CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
  ## 特性
27
27
 
28
- - 🧩 95+个高质量组件,覆盖移动端主流场景
28
+ - 🧩 96+个高质量组件,覆盖移动端主流场景
29
29
  - 💪 支持一套代码同时开发 H5 / 小程序 / App
30
30
  - 🌿 支持按需引入和 `Tree Shaking`
31
31
  - 📖 详尽的文档和案例展示
@@ -49,7 +49,8 @@
49
49
  ### 前提条件
50
50
 
51
51
  - 确保 node >= 20
52
- - 建议使用 pnpm
52
+ - 建议使用 pnpm 包管理器
53
+ - 建议使用 vscode 编辑器
53
54
 
54
55
  ### 克隆仓库到本地
55
56
 
@@ -479,6 +479,11 @@ export declare const defaultConfig: {
479
479
  uploadPreview: {
480
480
  status: UploadPreviewProps["status"];
481
481
  };
482
+ waterfall: {
483
+ columns: number;
484
+ columnGap: number;
485
+ rowGap: number;
486
+ };
482
487
  };
483
488
  export type ConfigOptions = typeof defaultConfig;
484
489
  export declare function setConfig(...optionsArgs: DeepPartial<ConfigOptions>[]): void;
@@ -433,6 +433,11 @@ export const defaultConfig = {
433
433
  uploadPreview: {
434
434
  status: 'pending',
435
435
  },
436
+ waterfall: {
437
+ columns: 2,
438
+ columnGap: 16,
439
+ rowGap: 16,
440
+ },
436
441
  };
437
442
  function extendProps(source, target) {
438
443
  Object.keys(target).forEach((key) => {
@@ -60,6 +60,12 @@ import Fab from 'sard-uniapp/components/fab/fab.vue'
60
60
 
61
61
  @code('${DEMO_PATH}/fab/demo/NonItemList.vue')
62
62
 
63
+ ### 自定义图标
64
+
65
+ 使用 `icon` 和 `icon-family` 可自定义悬浮按钮图标。
66
+
67
+ @code('${DEMO_PATH}/fab/demo/Icon.vue')
68
+
63
69
  ## API
64
70
 
65
71
  ### FabProps
@@ -33,7 +33,7 @@
33
33
  </view>
34
34
  <view :class="itemEntryClass" @click="onItemEntryClick">
35
35
  <view :class="bem.e('item-btn')" :style="itemEntryBtnStyle">
36
- <sar-icon family="sari" name="plus" />
36
+ <sar-icon :family="iconFamily || 'sari'" :name="icon || 'plus'" />
37
37
  </view>
38
38
  </view>
39
39
  </view>
@@ -32,15 +32,15 @@ import ListItem from 'sard-uniapp/components/list-item/list-item.vue'
32
32
 
33
33
  ### 图标
34
34
 
35
- 设置`icon`属性或插槽可以在左边显示图标。
35
+ 设置 `icon` 属性或插槽可以在左边显示图标。
36
36
 
37
37
  @code('${DEMO_PATH}/list/demo/Icon.vue')
38
38
 
39
39
  ### 自定义内容
40
40
 
41
- 列表项的`body`和`footer`默认平分水平空间,如果`footer`需要占据更多的空间,可以设置`body`不扩展。
41
+ 列表项的 `body` 和 `footer` 默认平分水平空间,如果 `footer` 需要占据更多的空间,可以设置 `body` 不扩展。
42
42
 
43
- `value`中的元素默认会向右边靠,如果有使用`footer`属性定义内容,则内容会纵向排列。
43
+ `value` 中的元素默认会向右边靠,如果有使用 `footer` 属性定义内容,则内容会纵向排列。
44
44
 
45
45
  @code('${DEMO_PATH}/list/demo/Slot.vue')
46
46
 
@@ -52,22 +52,29 @@ import ListItem from 'sard-uniapp/components/list-item/list-item.vue'
52
52
 
53
53
  ### 卡片风格
54
54
 
55
- 可以使用`card`属性让列表显示为卡片风格。
55
+ 可以使用 `card` 属性让列表显示为卡片风格。
56
56
 
57
57
  @code('${DEMO_PATH}/list/demo/Card.vue')
58
58
 
59
+ ### 隐藏边框 <sup>1.21.0+</sup>
60
+
61
+ 可以使用 `hide-border` 属性隐藏边框。
62
+
63
+ @code('${DEMO_PATH}/list/demo/HideBorder.vue')
64
+
59
65
  ## API
60
66
 
61
67
  ### ListProps
62
68
 
63
- | 属性 | 描述 | 类型 | 默认值 |
64
- | ----------- | -------------- | ---------------- | ------ |
65
- | root-class | 组件根元素类名 | string | - |
66
- | root-style | 组件根元素样式 | StyleValue | - |
67
- | title | 列表顶部标题 | string \| number | - |
68
- | description | 列表底部描述 | string \| number | - |
69
- | card | 卡片风格 | boolean | false |
70
- | inlaid | 嵌入式列表 | boolean | false |
69
+ | 属性 | 描述 | 类型 | 默认值 |
70
+ | ------------------------------ | -------------- | ---------------- | ------ |
71
+ | root-class | 组件根元素类名 | string | - |
72
+ | root-style | 组件根元素样式 | StyleValue | - |
73
+ | title | 列表顶部标题 | string \| number | - |
74
+ | description | 列表底部描述 | string \| number | - |
75
+ | card | 卡片风格 | boolean | false |
76
+ | inlaid | 嵌入式列表 | boolean | false |
77
+ | hide-border <sup>1.21.0+</sup> | 是否隐藏边框 | boolean | false |
71
78
 
72
79
  ### ListSlots
73
80
 
@@ -1,4 +1,4 @@
1
- import { type StyleValue } from 'vue';
1
+ import { InjectionKey, type StyleValue } from 'vue';
2
2
  export interface ListProps {
3
3
  rootStyle?: StyleValue;
4
4
  rootClass?: string;
@@ -6,6 +6,7 @@ export interface ListProps {
6
6
  description?: string | number;
7
7
  inlaid?: boolean;
8
8
  card?: boolean;
9
+ hideBorder?: boolean;
9
10
  }
10
11
  export interface ListSlots {
11
12
  default?(props: Record<string, never>): any;
@@ -40,3 +41,7 @@ export interface ListItemSlots {
40
41
  arrow?(props: Record<string, never>): any;
41
42
  icon?(props: Record<string, never>): any;
42
43
  }
44
+ export interface ListContext {
45
+ hideBorder?: boolean;
46
+ }
47
+ export declare const listContextKey: InjectionKey<ListContext>;
@@ -1,2 +1,3 @@
1
1
  import { defaultConfig } from '../config';
2
2
  export const defaultListItemProps = defaultConfig.listItem;
3
+ export const listContextKey = Symbol('list-context');
@@ -24,6 +24,14 @@
24
24
  }
25
25
  }
26
26
 
27
+ @include m(borderless) {
28
+ @include e(content) {
29
+ &::before {
30
+ display: none;
31
+ }
32
+ }
33
+ }
34
+
27
35
  @include e(description) {
28
36
  @include universal;
29
37
  margin-left: var(--sar-list-description-margin-x);
@@ -17,13 +17,14 @@
17
17
 
18
18
  <script>
19
19
  import { defineComponent as _defineComponent } from "vue";
20
- import { computed } from "vue";
20
+ import { computed, provide, reactive, toRef } from "vue";
21
21
  import {
22
22
  classNames,
23
23
  stringifyStyle,
24
24
  isRenderVisible,
25
25
  createBem
26
26
  } from "../../utils";
27
+ import { listContextKey } from "./common";
27
28
  /**
28
29
  * @property {string} rootClass 组件根元素类名,默认值:-。
29
30
  * @property {StyleValue} rootStyle 组件根元素样式,默认值:-。
@@ -31,6 +32,7 @@ import {
31
32
  * @property {string | number} description 列表底部描述,默认值:-。
32
33
  * @property {boolean} card 卡片风格,默认值:false。
33
34
  * @property {boolean} inlaid 嵌入式列表,默认值:false。
35
+ * @property {boolean} hideBorder 是否隐藏边框,默认值:false。
34
36
  */
35
37
  export default _defineComponent({
36
38
  ...{
@@ -46,18 +48,26 @@ export default _defineComponent({
46
48
  title: { type: [String, Number], required: false },
47
49
  description: { type: [String, Number], required: false },
48
50
  inlaid: { type: Boolean, required: false },
49
- card: { type: Boolean, required: false }
51
+ card: { type: Boolean, required: false },
52
+ hideBorder: { type: Boolean, required: false }
50
53
  },
51
54
  setup(__props, { expose: __expose }) {
52
55
  __expose();
53
56
  const props = __props;
54
57
  const bem = createBem("list");
58
+ provide(
59
+ listContextKey,
60
+ reactive({
61
+ hideBorder: toRef(() => props.hideBorder)
62
+ })
63
+ );
55
64
  const listClass = computed(() => {
56
65
  return classNames(
57
66
  bem.b(),
58
67
  bem.m("card", props.card),
59
68
  bem.m("not-card", !props.card),
60
69
  bem.m("inlaid", props.inlaid),
70
+ bem.m("borderless", props.hideBorder),
61
71
  props.rootClass
62
72
  );
63
73
  });
@@ -26,6 +26,12 @@
26
26
  right: var(--sar-list-item-padding-x);
27
27
  }
28
28
 
29
+ @include m(borderless) {
30
+ &::before {
31
+ display: none;
32
+ }
33
+ }
34
+
29
35
  &:first-child::before {
30
36
  display: none;
31
37
  }
@@ -42,7 +42,7 @@
42
42
 
43
43
  <script>
44
44
  import { useSlots as _useSlots, mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from "vue";
45
- import { computed } from "vue";
45
+ import { computed, inject } from "vue";
46
46
  import {
47
47
  classNames,
48
48
  stringifyStyle,
@@ -51,7 +51,8 @@ import {
51
51
  } from "../../utils";
52
52
  import SarIcon from "../icon/icon.vue";
53
53
  import {
54
- defaultListItemProps
54
+ defaultListItemProps,
55
+ listContextKey
55
56
  } from "../list/common";
56
57
  /**
57
58
  * @property {string} rootClass 组件根元素类名,默认值:-。
@@ -100,6 +101,7 @@ export default _defineComponent({
100
101
  const slots = _useSlots();
101
102
  const emit = __emit;
102
103
  const bem = createBem("list-item");
104
+ const context = inject(listContextKey);
103
105
  const onClick = (event) => {
104
106
  emit("click", event);
105
107
  };
@@ -108,10 +110,11 @@ export default _defineComponent({
108
110
  bem.b(),
109
111
  bem.m("hover", props.hover),
110
112
  bem.m("custom", !!slots.default),
113
+ bem.m("borderless", context?.hideBorder),
111
114
  props.rootClass
112
115
  );
113
116
  });
114
- const __returned__ = { props, slots, emit, bem, onClick, listItemClass, get stringifyStyle() {
117
+ const __returned__ = { props, slots, emit, bem, context, onClick, listItemClass, get stringifyStyle() {
115
118
  return stringifyStyle;
116
119
  }, get isRenderVisible() {
117
120
  return isRenderVisible;
@@ -91,7 +91,7 @@ export default {
91
91
  },
92
92
  },
93
93
  loadMore: {
94
- incompleteText: 'Load more',
94
+ incompleteText: 'Click to load more',
95
95
  loadingText: 'Loading...',
96
96
  errorText: 'Request failed. Click to reload',
97
97
  completeText: 'No more',
@@ -91,7 +91,7 @@ export default {
91
91
  },
92
92
  },
93
93
  loadMore: {
94
- incompleteText: '加载更多',
94
+ incompleteText: '点击加载更多',
95
95
  loadingText: '加载中...',
96
96
  completeText: '没有更多了',
97
97
  errorText: '请求失败,点击重新加载',
@@ -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>;