sard-uniapp 1.25.6 → 1.25.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 CHANGED
@@ -1,3 +1,18 @@
1
+ ## [1.25.7](https://github.com/sutras/sard-uniapp/compare/v1.25.6...v1.25.7) (2026-01-01)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * 修复notice-bar错位问题 ([f4a7e6b](https://github.com/sutras/sard-uniapp/commit/f4a7e6ba0840c9723d51f0add89677c1fe985b07))
7
+
8
+
9
+ ### Features
10
+
11
+ * app端允许页面返回时关闭弹出框 ([c538d7f](https://github.com/sutras/sard-uniapp/commit/c538d7fd35ade7bb07f192f35aed2db2515456b9))
12
+ * 小程序端允许页面返回操作关闭弹出框 ([a4fdc64](https://github.com/sutras/sard-uniapp/commit/a4fdc647ae5425ea5c4302493ca00852a7cc3a7a))
13
+
14
+
15
+
1
16
  ## [1.25.6](https://github.com/sutras/sard-uniapp/compare/v1.25.5...v1.25.6) (2025-12-27)
2
17
 
3
18
 
@@ -3,8 +3,10 @@
3
3
  effect="slide-bottom"
4
4
  :visible="innerVisible"
5
5
  :duration="duration"
6
+ back-press="close"
6
7
  @overlay-click="onOverlayClick"
7
8
  @visible-hook="onVisibleHook"
9
+ @back-press="onBackPress"
8
10
  >
9
11
  <view :class="actionSheetClass" :style="actionSheetStyle">
10
12
  <view v-if="description" :class="bem.e('description')">
@@ -188,6 +190,10 @@ export default _defineComponent({
188
190
  emit("visible-hook", name);
189
191
  emit(name);
190
192
  };
193
+ const onBackPress = () => {
194
+ innerVisible.value = false;
195
+ emit("update:visible", false);
196
+ };
191
197
  const actionSheetClass = computed(() => {
192
198
  return classNames(
193
199
  bem.b(),
@@ -198,7 +204,7 @@ export default _defineComponent({
198
204
  const actionSheetStyle = computed(() => {
199
205
  return stringifyStyle(props.rootStyle);
200
206
  });
201
- const __returned__ = { props, emit, bem, t, innerVisible, mergedShowCancel, loading, readonlyLoading, asyncSet, perhapsClose, onOverlayClick, onSelect, onCancel, onVisibleHook, actionSheetClass, actionSheetStyle, get classNames() {
207
+ const __returned__ = { props, emit, bem, t, innerVisible, mergedShowCancel, loading, readonlyLoading, asyncSet, perhapsClose, onOverlayClick, onSelect, onCancel, onVisibleHook, onBackPress, actionSheetClass, actionSheetStyle, get classNames() {
202
208
  return classNames;
203
209
  }, get stringifyStyle() {
204
210
  return stringifyStyle;
@@ -280,6 +280,7 @@ export const defaultConfig = {
280
280
  overlay: true,
281
281
  overlayClosable: true,
282
282
  duration: 250,
283
+ backPress: 'close',
283
284
  },
284
285
  popoutInput: {
285
286
  arrow: 'caret-right',
@@ -300,6 +301,7 @@ export const defaultConfig = {
300
301
  overlay: true,
301
302
  overlayClosable: true,
302
303
  lockScroll: true,
304
+ backPress: 'close',
303
305
  },
304
306
  progressBar: {
305
307
  percent: 0,
@@ -4,8 +4,10 @@
4
4
  :visible="visible"
5
5
  :duration="duration"
6
6
  :overlay="false"
7
+ back-press="close"
7
8
  @after-enter="onAfterEnter"
8
9
  @visible-hook="onVisibleHook"
10
+ @back-press="onBackPress"
9
11
  >
10
12
  <view :class="cropImageClass" :style="cropImageStyle">
11
13
  <view
@@ -197,6 +199,10 @@ export default _defineComponent({
197
199
  emit("visible-hook", name);
198
200
  emit(name);
199
201
  };
202
+ const onBackPress = () => {
203
+ innerVisible.value = false;
204
+ emit("update:visible", false);
205
+ };
200
206
  const { windowWidth, windowHeight, pixelRatio } = getWindowInfo();
201
207
  const aspectRatio = computed(() => {
202
208
  const [w, h] = props.cropScale.split(":").map(Number);
@@ -679,7 +685,7 @@ export default _defineComponent({
679
685
  return stringifyStyle(props.rootStyle);
680
686
  });
681
687
  __expose({});
682
- const __returned__ = { props, emit, bem, t, innerVisible, close, onVisibleHook, windowWidth, windowHeight, pixelRatio, aspectRatio, minGapY, minGapX, focusRect, rotate, actualRotate, onRotateEnd, isRotating, isStillRotating, stopRotateLater, cancelStopRotate, maskStyle, focusStyle, imageOrigSize, imageCoverSize, reversedCoverSize, imgLeft, imgTop, imgWidth, imgHeight, isCaptured, inInertia, puppetStyle, imageStyle, onImageTouchStart, bounceCoeff, maxScale, get stopInertialAnimate() {
688
+ const __returned__ = { props, emit, bem, t, innerVisible, close, onVisibleHook, onBackPress, windowWidth, windowHeight, pixelRatio, aspectRatio, minGapY, minGapX, focusRect, rotate, actualRotate, onRotateEnd, isRotating, isStillRotating, stopRotateLater, cancelStopRotate, maskStyle, focusStyle, imageOrigSize, imageCoverSize, reversedCoverSize, imgLeft, imgTop, imgWidth, imgHeight, isCaptured, inInertia, puppetStyle, imageStyle, onImageTouchStart, bounceCoeff, maxScale, get stopInertialAnimate() {
683
689
  return stopInertialAnimate;
684
690
  }, set stopInertialAnimate(v) {
685
691
  stopInertialAnimate = v;
@@ -5,8 +5,10 @@
5
5
  :duration="duration"
6
6
  :root-class="popupClass"
7
7
  :root-style="mergedPopupStyle"
8
+ back-press="close"
8
9
  @overlay-click="onOverlayClick"
9
10
  @visible-hook="onVisibleHook"
11
+ @back-press="onBackPress"
10
12
  >
11
13
  <view :class="dialogClass" :style="dialogStyle">
12
14
  <view v-if="headed" :class="bem.e('header')">
@@ -241,6 +243,10 @@ export default _defineComponent({
241
243
  emit("visible-hook", name);
242
244
  emit(name);
243
245
  };
246
+ const onBackPress = () => {
247
+ innerVisible.value = false;
248
+ emit("update:visible", false);
249
+ };
244
250
  const buttonProps = computed(() => {
245
251
  return {
246
252
  text: {
@@ -287,7 +293,7 @@ export default _defineComponent({
287
293
  props.popupStyle
288
294
  );
289
295
  });
290
- const __returned__ = { props, emit, bem, t, innerVisible, loading, readonlyLoading, asyncSet, perhapsClose, onOverlayClick, onClose, onConfirm, onCancel, onVisibleHook, buttonProps, dialogClass, dialogStyle, mergedPopupStyle, SarPopup, SarButton, SarIcon };
296
+ const __returned__ = { props, emit, bem, t, innerVisible, loading, readonlyLoading, asyncSet, perhapsClose, onOverlayClick, onClose, onConfirm, onCancel, onVisibleHook, onBackPress, buttonProps, dialogClass, dialogStyle, mergedPopupStyle, SarPopup, SarButton, SarIcon };
291
297
  return __returned__;
292
298
  }
293
299
  });
@@ -128,9 +128,11 @@ export default _defineComponent({
128
128
  shouldScroll.value = nextShouldScroll;
129
129
  };
130
130
  const firstLap = ref(true);
131
- const onAnimationEnd = () => {
132
- if (firstLap.value) {
133
- firstLap.value = false;
131
+ const onAnimationEnd = (event) => {
132
+ if (event.target.id === wrapperId) {
133
+ if (firstLap.value) {
134
+ firstLap.value = false;
135
+ }
134
136
  }
135
137
  };
136
138
  const { start: updateLater } = useTimeout(
@@ -5,6 +5,7 @@
5
5
  :effect="effect"
6
6
  :duration="duration"
7
7
  :lock-scroll="false"
8
+ back-press="back"
8
9
  @visible-hook="onVisibleHook"
9
10
  >
10
11
  <view :class="notifyClass" :style="notifyStyle" @click="onClick">
@@ -9,6 +9,8 @@ group: 数据展示
9
9
 
10
10
  底部弹出框,可以控制组件的展示与交互,可作为其他组件的弹出框容器。
11
11
 
12
+ Popout 组件基于 Popup 组件。
13
+
12
14
  ## 引入
13
15
 
14
16
  ```ts
@@ -39,28 +41,29 @@ import Popout from 'sard-uniapp/components/popout/popout.vue'
39
41
 
40
42
  ### PopoutProps
41
43
 
42
- | 属性 | 描述 | 类型 | 默认值 |
43
- | -------------------------------- | -------------------------------------------------------------------------------------- | -------------------- | ------- |
44
- | root-class | 组件根元素类名 | string | - |
45
- | root-style | 组件根元素样式 | StyleValue | - |
46
- | title | 弹出框标题 | string | - |
47
- | show-cancel | 是否显示取消按钮,适用 `loose` 类型 | boolean | false |
48
- | cancel-text | 取消按钮文案 | string | '取消' |
49
- | show-confirm | 是否显示确定按钮,适用 `loose` 类型 | boolean | true |
50
- | confirm-text | 确定按钮文案 | string | '确定' |
51
- | show-close | 是否显示关闭按钮,适用 `loose` 类型 | boolean | true |
52
- | show-footer | 是否显示底部按钮 | boolean | true |
53
- | type | 弹出框按钮排版方式 | 'compact' \| 'loose' | 'loose' |
54
- | visible (v-model) | 是否显示弹出框 | boolean | - |
55
- | before-close | 关闭前的回调,返回 `false` 或 `rejected` 状态的 `Promise` 可阻止关闭 | PopoutBeforeClose | - |
56
- | duration | 显隐动画时长,单位 ms | number | 300 |
57
- | overlay <sup>1.25.1+</sup> | 是否显示遮罩 | boolean | true |
58
- | overlay-class <sup>1.25.1+</sup> | 添加到遮罩的类名 | string | - |
59
- | overlay-style <sup>1.25.1+</sup> | 添加到遮罩的样式 | string | - |
60
- | background <sup>1.25.1+</sup> | 遮罩背景色 | string | - |
61
- | transparent <sup>1.25.1+</sup> | 透明遮罩 | boolean | false |
62
- | overlay-closable | 点击遮罩是否关闭 | boolean | true |
63
- | keep-render <sup>1.24.3+</sup> | 无论刚挂载还是隐藏,都始终不设置 display 为 none,一般用于内部包含计算尺寸的组件的情况 | boolean | false |
44
+ | 属性 | 描述 | 类型 | 默认值 |
45
+ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------- | ------- |
46
+ | root-class | 组件根元素类名 | string | - |
47
+ | root-style | 组件根元素样式 | StyleValue | - |
48
+ | title | 弹出框标题 | string | - |
49
+ | show-cancel | 是否显示取消按钮,适用 `loose` 类型 | boolean | false |
50
+ | cancel-text | 取消按钮文案 | string | '取消' |
51
+ | show-confirm | 是否显示确定按钮,适用 `loose` 类型 | boolean | true |
52
+ | confirm-text | 确定按钮文案 | string | '确定' |
53
+ | show-close | 是否显示关闭按钮,适用 `loose` 类型 | boolean | true |
54
+ | show-footer | 是否显示底部按钮 | boolean | true |
55
+ | type | 弹出框按钮排版方式 | 'compact' \| 'loose' | 'loose' |
56
+ | visible (v-model) | 是否显示弹出框 | boolean | - |
57
+ | before-close | 关闭前的回调,返回 `false` 或 `rejected` 状态的 `Promise` 可阻止关闭 | PopoutBeforeClose | - |
58
+ | duration | 显隐动画时长,单位 ms | number | 300 |
59
+ | overlay <sup>1.25.1+</sup> | 是否显示遮罩 | boolean | true |
60
+ | overlay-class <sup>1.25.1+</sup> | 添加到遮罩的类名 | string | - |
61
+ | overlay-style <sup>1.25.1+</sup> | 添加到遮罩的样式 | string | - |
62
+ | background <sup>1.25.1+</sup> | 遮罩背景色 | string | - |
63
+ | transparent <sup>1.25.1+</sup> | 透明遮罩 | boolean | false |
64
+ | overlay-closable | 点击遮罩是否关闭 | boolean | true |
65
+ | keep-render <sup>1.24.3+</sup> | 无论刚挂载还是隐藏,都始终不设置 display 为 none,一般用于内部包含计算尺寸的组件的情况 | boolean | false |
66
+ | back-press <sup>1.25.7+</sup> | 弹出框显示时,劫持用户的返回操作,`close`: 关闭弹出框、`back`: 返回上一页、`stop`: 不关闭也不返回(仅小程序支持) | 'close' \| 'back' \| 'stop' | 'close' |
64
67
 
65
68
  ### PopoutBeforeClose
66
69
 
@@ -94,21 +97,22 @@ type PopoutBeforeClose = (
94
97
 
95
98
  ### PopoutEmits
96
99
 
97
- | 事件 | 描述 | 类型 |
98
- | -------------------------------- | --------------------------- | ---------------------------------- |
99
- | update:visible | 显隐时触发 | (visible: boolean) => void |
100
- | close | 点击关闭按钮或遮罩时触发 | () => void |
101
- | cancel | 点击取消按钮时触发 | () => void |
102
- | confirm | 点击确定按钮时触发 | () => void |
103
- | visible-hook | 入场/退场动画状态改变时触发 | (name: TransitionHookName) => void |
104
- | before-enter <sup>1.12+</sup> | 入场动画开始前触发 | () => void |
105
- | enter <sup>1.12+</sup> | 入场动画开始时触发 | () => void |
106
- | after-enter <sup>1.12+</sup> | 入场动画结束时触发 | () => void |
107
- | enter-cancelled <sup>1.12+</sup> | 入场动画取消时触发 | () => void |
108
- | before-leave <sup>1.12+</sup> | 退场动画开始前触发 | () => void |
109
- | leave <sup>1.12+</sup> | 退场动画开始时触发 | () => void |
110
- | after-leave <sup>1.12+</sup> | 退场动画结束时触发 | () => void |
111
- | leave-cancelled <sup>1.12+</sup> | 退场动画取消时触发 | () => void |
100
+ | 事件 | 描述 | 类型 |
101
+ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------- |
102
+ | update:visible | 显隐时触发 | (visible: boolean) => void |
103
+ | close | 点击关闭按钮或遮罩时触发 | () => void |
104
+ | cancel | 点击取消按钮时触发 | () => void |
105
+ | confirm | 点击确定按钮时触发 | () => void |
106
+ | back-press <sup>1.25.7+</sup> | 弹出框显示时,劫持用户的返回操作,`close`: 关闭弹出框、`back`: 返回上一页、`stop`: 不关闭也不返回(仅小程序支持) | 'close' \| 'back' \| 'stop' | 'close' |
107
+ | visible-hook | 入场/退场动画状态改变时触发 | (name: TransitionHookName) => void |
108
+ | before-enter <sup>1.12+</sup> | 入场动画开始前触发 | () => void |
109
+ | enter <sup>1.12+</sup> | 入场动画开始时触发 | () => void |
110
+ | after-enter <sup>1.12+</sup> | 入场动画结束时触发 | () => void |
111
+ | enter-cancelled <sup>1.12+</sup> | 入场动画取消时触发 | () => void |
112
+ | before-leave <sup>1.12+</sup> | 退场动画开始前触发 | () => void |
113
+ | leave <sup>1.12+</sup> | 退场动画开始时触发 | () => void |
114
+ | after-leave <sup>1.12+</sup> | 退场动画结束时触发 | () => void |
115
+ | leave-cancelled <sup>1.12+</sup> | 退场动画取消时触发 | () => void |
112
116
 
113
117
  ## 主题定制
114
118
 
@@ -27,6 +27,7 @@ export interface PopoutProps {
27
27
  overlayClosable?: boolean;
28
28
  beforeClose?: PopoutBeforeClose;
29
29
  keepRender?: boolean;
30
+ backPress?: 'close' | 'back' | 'stop';
30
31
  }
31
32
  export declare const defaultPopoutProps: {
32
33
  rootStyle?: (string | false | ((props: {
@@ -51,6 +52,7 @@ export declare const defaultPopoutProps: {
51
52
  overlayClosable: boolean;
52
53
  beforeClose: PopoutBeforeClose;
53
54
  keepRender: boolean;
55
+ backPress: "close" | "back" | "stop";
54
56
  }) => string | false | import("vue").CSSProperties | StyleValue[]) | null) | undefined;
55
57
  rootClass?: (string | ((props: {
56
58
  rootStyle: StyleValue;
@@ -74,6 +76,7 @@ export declare const defaultPopoutProps: {
74
76
  overlayClosable: boolean;
75
77
  beforeClose: PopoutBeforeClose;
76
78
  keepRender: boolean;
79
+ backPress: "close" | "back" | "stop";
77
80
  }) => string)) | undefined;
78
81
  visible?: (boolean | ((props: {
79
82
  rootStyle: StyleValue;
@@ -97,6 +100,7 @@ export declare const defaultPopoutProps: {
97
100
  overlayClosable: boolean;
98
101
  beforeClose: PopoutBeforeClose;
99
102
  keepRender: boolean;
103
+ backPress: "close" | "back" | "stop";
100
104
  }) => boolean)) | undefined;
101
105
  duration?: (number | ((props: {
102
106
  rootStyle: StyleValue;
@@ -120,6 +124,7 @@ export declare const defaultPopoutProps: {
120
124
  overlayClosable: boolean;
121
125
  beforeClose: PopoutBeforeClose;
122
126
  keepRender: boolean;
127
+ backPress: "close" | "back" | "stop";
123
128
  }) => number)) | undefined;
124
129
  title?: (string | ((props: {
125
130
  rootStyle: StyleValue;
@@ -143,6 +148,7 @@ export declare const defaultPopoutProps: {
143
148
  overlayClosable: boolean;
144
149
  beforeClose: PopoutBeforeClose;
145
150
  keepRender: boolean;
151
+ backPress: "close" | "back" | "stop";
146
152
  }) => string)) | undefined;
147
153
  type?: ("compact" | "loose" | ((props: {
148
154
  rootStyle: StyleValue;
@@ -166,6 +172,7 @@ export declare const defaultPopoutProps: {
166
172
  overlayClosable: boolean;
167
173
  beforeClose: PopoutBeforeClose;
168
174
  keepRender: boolean;
175
+ backPress: "close" | "back" | "stop";
169
176
  }) => "compact" | "loose")) | undefined;
170
177
  showCancel?: (boolean | ((props: {
171
178
  rootStyle: StyleValue;
@@ -189,6 +196,7 @@ export declare const defaultPopoutProps: {
189
196
  overlayClosable: boolean;
190
197
  beforeClose: PopoutBeforeClose;
191
198
  keepRender: boolean;
199
+ backPress: "close" | "back" | "stop";
192
200
  }) => boolean)) | undefined;
193
201
  cancelText?: (string | ((props: {
194
202
  rootStyle: StyleValue;
@@ -212,6 +220,7 @@ export declare const defaultPopoutProps: {
212
220
  overlayClosable: boolean;
213
221
  beforeClose: PopoutBeforeClose;
214
222
  keepRender: boolean;
223
+ backPress: "close" | "back" | "stop";
215
224
  }) => string)) | undefined;
216
225
  showConfirm?: (boolean | ((props: {
217
226
  rootStyle: StyleValue;
@@ -235,6 +244,7 @@ export declare const defaultPopoutProps: {
235
244
  overlayClosable: boolean;
236
245
  beforeClose: PopoutBeforeClose;
237
246
  keepRender: boolean;
247
+ backPress: "close" | "back" | "stop";
238
248
  }) => boolean)) | undefined;
239
249
  confirmText?: (string | ((props: {
240
250
  rootStyle: StyleValue;
@@ -258,6 +268,7 @@ export declare const defaultPopoutProps: {
258
268
  overlayClosable: boolean;
259
269
  beforeClose: PopoutBeforeClose;
260
270
  keepRender: boolean;
271
+ backPress: "close" | "back" | "stop";
261
272
  }) => string)) | undefined;
262
273
  confirmDisabled?: (boolean | ((props: {
263
274
  rootStyle: StyleValue;
@@ -281,6 +292,7 @@ export declare const defaultPopoutProps: {
281
292
  overlayClosable: boolean;
282
293
  beforeClose: PopoutBeforeClose;
283
294
  keepRender: boolean;
295
+ backPress: "close" | "back" | "stop";
284
296
  }) => boolean)) | undefined;
285
297
  showClose?: (boolean | ((props: {
286
298
  rootStyle: StyleValue;
@@ -304,6 +316,7 @@ export declare const defaultPopoutProps: {
304
316
  overlayClosable: boolean;
305
317
  beforeClose: PopoutBeforeClose;
306
318
  keepRender: boolean;
319
+ backPress: "close" | "back" | "stop";
307
320
  }) => boolean)) | undefined;
308
321
  showFooter?: (boolean | ((props: {
309
322
  rootStyle: StyleValue;
@@ -327,6 +340,7 @@ export declare const defaultPopoutProps: {
327
340
  overlayClosable: boolean;
328
341
  beforeClose: PopoutBeforeClose;
329
342
  keepRender: boolean;
343
+ backPress: "close" | "back" | "stop";
330
344
  }) => boolean)) | undefined;
331
345
  overlay?: (boolean | ((props: {
332
346
  rootStyle: StyleValue;
@@ -350,6 +364,7 @@ export declare const defaultPopoutProps: {
350
364
  overlayClosable: boolean;
351
365
  beforeClose: PopoutBeforeClose;
352
366
  keepRender: boolean;
367
+ backPress: "close" | "back" | "stop";
353
368
  }) => boolean)) | undefined;
354
369
  overlayClass?: (string | ((props: {
355
370
  rootStyle: StyleValue;
@@ -373,6 +388,7 @@ export declare const defaultPopoutProps: {
373
388
  overlayClosable: boolean;
374
389
  beforeClose: PopoutBeforeClose;
375
390
  keepRender: boolean;
391
+ backPress: "close" | "back" | "stop";
376
392
  }) => string)) | undefined;
377
393
  overlayStyle?: (string | ((props: {
378
394
  rootStyle: StyleValue;
@@ -396,6 +412,7 @@ export declare const defaultPopoutProps: {
396
412
  overlayClosable: boolean;
397
413
  beforeClose: PopoutBeforeClose;
398
414
  keepRender: boolean;
415
+ backPress: "close" | "back" | "stop";
399
416
  }) => string)) | undefined;
400
417
  background?: (string | ((props: {
401
418
  rootStyle: StyleValue;
@@ -419,6 +436,7 @@ export declare const defaultPopoutProps: {
419
436
  overlayClosable: boolean;
420
437
  beforeClose: PopoutBeforeClose;
421
438
  keepRender: boolean;
439
+ backPress: "close" | "back" | "stop";
422
440
  }) => string)) | undefined;
423
441
  transparent?: (boolean | ((props: {
424
442
  rootStyle: StyleValue;
@@ -442,6 +460,7 @@ export declare const defaultPopoutProps: {
442
460
  overlayClosable: boolean;
443
461
  beforeClose: PopoutBeforeClose;
444
462
  keepRender: boolean;
463
+ backPress: "close" | "back" | "stop";
445
464
  }) => boolean)) | undefined;
446
465
  overlayClosable?: (boolean | ((props: {
447
466
  rootStyle: StyleValue;
@@ -465,6 +484,7 @@ export declare const defaultPopoutProps: {
465
484
  overlayClosable: boolean;
466
485
  beforeClose: PopoutBeforeClose;
467
486
  keepRender: boolean;
487
+ backPress: "close" | "back" | "stop";
468
488
  }) => boolean)) | undefined;
469
489
  beforeClose?: (PopoutBeforeClose | ((props: {
470
490
  rootStyle: StyleValue;
@@ -488,6 +508,7 @@ export declare const defaultPopoutProps: {
488
508
  overlayClosable: boolean;
489
509
  beforeClose: PopoutBeforeClose;
490
510
  keepRender: boolean;
511
+ backPress: "close" | "back" | "stop";
491
512
  }) => PopoutBeforeClose)) | undefined;
492
513
  keepRender?: (boolean | ((props: {
493
514
  rootStyle: StyleValue;
@@ -511,7 +532,32 @@ export declare const defaultPopoutProps: {
511
532
  overlayClosable: boolean;
512
533
  beforeClose: PopoutBeforeClose;
513
534
  keepRender: boolean;
535
+ backPress: "close" | "back" | "stop";
514
536
  }) => boolean)) | undefined;
537
+ backPress?: ("close" | "stop" | "back" | ((props: {
538
+ rootStyle: StyleValue;
539
+ rootClass: string;
540
+ visible: boolean;
541
+ duration: number;
542
+ title: string;
543
+ type: "compact" | "loose";
544
+ showCancel: boolean;
545
+ cancelText: string;
546
+ showConfirm: boolean;
547
+ confirmText: string;
548
+ confirmDisabled: boolean;
549
+ showClose: boolean;
550
+ showFooter: boolean;
551
+ overlay: boolean;
552
+ overlayClass: string;
553
+ overlayStyle: string;
554
+ background: string;
555
+ transparent: boolean;
556
+ overlayClosable: boolean;
557
+ beforeClose: PopoutBeforeClose;
558
+ keepRender: boolean;
559
+ backPress: "close" | "back" | "stop";
560
+ }) => "close" | "stop" | "back")) | undefined;
515
561
  };
516
562
  export interface PopoutSlots {
517
563
  default?(props: Record<string, never>): any;
@@ -540,4 +586,5 @@ export interface PopoutEmits extends TransitionHookEmits {
540
586
  (e: 'close'): void;
541
587
  (e: 'cancel'): void;
542
588
  (e: 'confirm'): void;
589
+ (e: 'back-press'): void;
543
590
  }
@@ -20,6 +20,7 @@ declare const __VLS_component: import("vue").DefineComponent<PopoutProps, {}, {}
20
20
  transparent: boolean;
21
21
  keepRender: boolean;
22
22
  overlayClosable: boolean;
23
+ backPress: "close" | "back" | "stop";
23
24
  showCancel: boolean;
24
25
  beforeClose: import("./common").PopoutBeforeClose;
25
26
  showConfirm: boolean;
@@ -9,10 +9,12 @@
9
9
  :overlay-style="overlayStyle"
10
10
  :background="background"
11
11
  :transparent="transparent"
12
+ :back-press="backPress"
12
13
  @overlay-click="onOverlayClick"
13
14
  @before-enter="onBeforeEnter"
14
15
  @after-leave="onAfterLeave"
15
16
  @visible-hook="onVisibleHook"
17
+ @back-press="onBackPress"
16
18
  >
17
19
  <view :class="popoutClass" :style="popoutStyle" @transitionend.stop>
18
20
  <view :class="classNames(bem.e('header'), bem.em('header', props.type))">
@@ -163,10 +165,12 @@ import {
163
165
  * @property {boolean} transparent 透明遮罩,默认值:false。
164
166
  * @property {boolean} overlayClosable 点击遮罩是否关闭,默认值:true。
165
167
  * @property {boolean} keepRender 无论刚挂载还是隐藏,都始终不设置 display 为 none,一般用于内部包含计算尺寸的组件的情况,默认值:false。
168
+ * @property {'close' | 'back' | 'stop'} backPress 弹出框显示时,劫持用户的返回操作,`close`: 关闭弹出框、`back`: 返回上一页、`stop`: 不关闭也不返回(仅小程序支持),默认值:'close'。
166
169
  * @event {(visible: boolean) => void} update 显隐时触发
167
170
  * @event {() => void} close 点击关闭按钮或遮罩时触发
168
171
  * @event {() => void} cancel 点击取消按钮时触发
169
172
  * @event {() => void} confirm 点击确定按钮时触发
173
+ * @event {'close' | 'back' | 'stop'} back-press 弹出框显示时,劫持用户的返回操作,`close`: 关闭弹出框、`back`: 返回上一页、`stop`: 不关闭也不返回(仅小程序支持)
170
174
  * @event {(name: TransitionHookName) => void} visible-hook 入场/退场动画状态改变时触发
171
175
  * @event {() => void} before-enter 入场动画开始前触发
172
176
  * @event {() => void} enter 入场动画开始时触发
@@ -211,9 +215,10 @@ export default _defineComponent({
211
215
  transparent: { type: Boolean, required: false },
212
216
  overlayClosable: { type: Boolean, required: false },
213
217
  beforeClose: { type: Function, required: false },
214
- keepRender: { type: Boolean, required: false }
218
+ keepRender: { type: Boolean, required: false },
219
+ backPress: { type: String, required: false }
215
220
  }, defaultPopoutProps),
216
- emits: ["update:visible", "close", "cancel", "confirm", "before-enter", "enter", "after-enter", "enter-cancelled", "before-leave", "leave", "after-leave", "leave-cancelled", "visible-hook"],
221
+ emits: ["update:visible", "close", "cancel", "confirm", "back-press", "before-enter", "enter", "after-enter", "enter-cancelled", "before-leave", "leave", "after-leave", "leave-cancelled", "visible-hook"],
217
222
  setup(__props, { expose: __expose, emit: __emit }) {
218
223
  __expose();
219
224
  const props = __props;
@@ -246,6 +251,13 @@ export default _defineComponent({
246
251
  emit("visible-hook", name);
247
252
  emit(name);
248
253
  };
254
+ const onBackPress = () => {
255
+ emit("back-press");
256
+ if (props.backPress === "close") {
257
+ innerVisible.value = false;
258
+ emit("update:visible", false);
259
+ }
260
+ };
249
261
  const loading = reactive({
250
262
  cancel: false,
251
263
  confirm: false,
@@ -323,7 +335,7 @@ export default _defineComponent({
323
335
  const popoutStyle = computed(() => {
324
336
  return stringifyStyle(props.rootStyle);
325
337
  });
326
- const __returned__ = { props, emit, bem, t, innerVisible, already, wholeVisible, onBeforeEnter, onAfterLeave, callVisibleHook, onVisibleHook, loading, readonlyLoading, asyncSet, perhapsClose, onOverlayClick, onCloseClick, onConfirm, onCancel, mergedConfirmText, mergedCancelText, popoutClass, popoutStyle, get classNames() {
338
+ const __returned__ = { props, emit, bem, t, innerVisible, already, wholeVisible, onBeforeEnter, onAfterLeave, callVisibleHook, onVisibleHook, onBackPress, loading, readonlyLoading, asyncSet, perhapsClose, onOverlayClick, onCloseClick, onConfirm, onCancel, mergedConfirmText, mergedCancelText, popoutClass, popoutStyle, get classNames() {
327
339
  return classNames;
328
340
  }, SarPopup, SarButton, SarIcon };
329
341
  return __returned__;
@@ -28,21 +28,22 @@ import Popup from 'sard-uniapp/components/popup/popup.vue'
28
28
 
29
29
  ### PopupProps
30
30
 
31
- | 属性 | 描述 | 类型 | 默认值 |
32
- | --------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------ |
33
- | root-class | 组件根元素类名 | string | - |
34
- | root-style | 组件根元素样式 | StyleValue | - |
35
- | visible (v-model) | 是否可见 | boolean | false |
36
- | duration | 显隐动画时长,单位 ms | number | 300 |
37
- | effect | 显隐效果 | 'slide-top' \| 'slide-right' \| 'slide-bottom' \| 'slide-left' \| 'zoom' \| 'fade' | 'fade' |
38
- | overlay | 是否显示遮罩 | boolean | true |
39
- | overlay-class | 添加到遮罩的类名 | string | - |
40
- | overlay-style | 添加到遮罩的样式 | string | - |
41
- | background | 遮罩背景色 | string | - |
42
- | transparent | 透明遮罩 | boolean | false |
43
- | overlay-closable <sup>1.22+</sup> | 是否在点击遮罩层后关闭 | boolean | true |
44
- | keep-render <sup>1.24.3+</sup> | 无论刚挂载还是隐藏,都始终不设置 display 为 none,一般用于内部包含计算尺寸的组件的情况 | boolean | false |
45
- | lock-scroll <sup>1.25.5+</sup> | 弹出框显示时,是否阻止页面滚动 | boolean | true |
31
+ | 属性 | 描述 | 类型 | 默认值 |
32
+ | --------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------- |
33
+ | root-class | 组件根元素类名 | string | - |
34
+ | root-style | 组件根元素样式 | StyleValue | - |
35
+ | visible (v-model) | 是否可见 | boolean | false |
36
+ | duration | 显隐动画时长,单位 ms | number | 300 |
37
+ | effect | 显隐效果 | 'slide-top' \| 'slide-right' \| 'slide-bottom' \| 'slide-left' \| 'zoom' \| 'fade' | 'fade' |
38
+ | overlay | 是否显示遮罩 | boolean | true |
39
+ | overlay-class | 添加到遮罩的类名 | string | - |
40
+ | overlay-style | 添加到遮罩的样式 | string | - |
41
+ | background | 遮罩背景色 | string | - |
42
+ | transparent | 透明遮罩 | boolean | false |
43
+ | overlay-closable <sup>1.22+</sup> | 是否在点击遮罩层后关闭 | boolean | true |
44
+ | keep-render <sup>1.24.3+</sup> | 无论刚挂载还是隐藏,都始终不设置 display 为 none,一般用于内部包含计算尺寸的组件的情况 | boolean | false |
45
+ | lock-scroll <sup>1.25.5+</sup> | 弹出框显示时,是否阻止页面滚动 | boolean | true |
46
+ | back-press <sup>1.25.7+</sup> | 弹出框显示时,劫持用户的返回操作,`close`: 关闭弹出框、`back`: 返回上一页、`stop`: 不关闭也不返回(仅小程序支持) | 'close' \| 'back' \| 'stop' | 'close' |
46
47
 
47
48
  ### PopupSlots
48
49
 
@@ -52,19 +53,20 @@ import Popup from 'sard-uniapp/components/popup/popup.vue'
52
53
 
53
54
  ### PopupEmits
54
55
 
55
- | 事件 | 描述 | 类型 |
56
- | ------------------------------- | --------------------------- | ---------------------------------- |
57
- | overlay-click | 点击遮罩时触发 | (event: any) => void |
58
- | visible-hook | 入场/退场动画状态改变时触发 | (name: TransitionHookName) => void |
59
- | before-enter | 入场动画开始前触发 | () => void |
60
- | enter | 入场动画开始时触发 | () => void |
61
- | after-enter | 入场动画结束时触发 | () => void |
62
- | enter-cancelled | 入场动画取消时触发 | () => void |
63
- | before-leave | 退场动画开始前触发 | () => void |
64
- | leave | 退场动画开始时触发 | () => void |
65
- | after-leave | 退场动画结束时触发 | () => void |
66
- | leave-cancelled | 退场动画取消时触发 | () => void |
67
- | update:visible <sup>1.22+</sup> | 显隐时触发 | (visible: boolean) => void |
56
+ | 事件 | 描述 | 类型 |
57
+ | ------------------------------- | ---------------------------------------------------------------- | ---------------------------------- |
58
+ | overlay-click | 点击遮罩时触发 | (event: any) => void |
59
+ | update:visible <sup>1.22+</sup> | 显隐时触发 | (visible: boolean) => void |
60
+ | back-press <sup>1.25.7+</sup> | 用户进行返回操作时触发,仅限于 `close` 和 `stop`(仅小程序支持) | () => void |
61
+ | visible-hook | 入场/退场动画状态改变时触发 | (name: TransitionHookName) => void |
62
+ | before-enter | 入场动画开始前触发 | () => void |
63
+ | enter | 入场动画开始时触发 | () => void |
64
+ | after-enter | 入场动画结束时触发 | () => void |
65
+ | enter-cancelled | 入场动画取消时触发 | () => void |
66
+ | before-leave | 退场动画开始前触发 | () => void |
67
+ | leave | 退场动画开始时触发 | () => void |
68
+ | after-leave | 退场动画结束时触发 | () => void |
69
+ | leave-cancelled | 退场动画取消时触发 | () => void |
68
70
 
69
71
  ## 主题定制
70
72
 
@@ -14,6 +14,7 @@ export interface PopupProps {
14
14
  keepRender?: boolean;
15
15
  overlayClosable?: boolean;
16
16
  lockScroll?: boolean;
17
+ backPress?: 'close' | 'back' | 'stop';
17
18
  }
18
19
  export declare const defaultPopupProps: {
19
20
  rootStyle?: (string | false | ((props: {
@@ -30,6 +31,7 @@ export declare const defaultPopupProps: {
30
31
  keepRender: boolean;
31
32
  overlayClosable: boolean;
32
33
  lockScroll: boolean;
34
+ backPress: "close" | "back" | "stop";
33
35
  }) => string | false | import("vue").CSSProperties | StyleValue[]) | null) | undefined;
34
36
  rootClass?: (string | ((props: {
35
37
  rootStyle: StyleValue;
@@ -45,6 +47,7 @@ export declare const defaultPopupProps: {
45
47
  keepRender: boolean;
46
48
  overlayClosable: boolean;
47
49
  lockScroll: boolean;
50
+ backPress: "close" | "back" | "stop";
48
51
  }) => string)) | undefined;
49
52
  visible?: (boolean | ((props: {
50
53
  rootStyle: StyleValue;
@@ -60,6 +63,7 @@ export declare const defaultPopupProps: {
60
63
  keepRender: boolean;
61
64
  overlayClosable: boolean;
62
65
  lockScroll: boolean;
66
+ backPress: "close" | "back" | "stop";
63
67
  }) => boolean)) | undefined;
64
68
  duration?: (number | ((props: {
65
69
  rootStyle: StyleValue;
@@ -75,6 +79,7 @@ export declare const defaultPopupProps: {
75
79
  keepRender: boolean;
76
80
  overlayClosable: boolean;
77
81
  lockScroll: boolean;
82
+ backPress: "close" | "back" | "stop";
78
83
  }) => number)) | undefined;
79
84
  effect?: ("slide-top" | "slide-right" | "slide-bottom" | "slide-left" | "zoom" | "fade" | "full-fade" | ((props: {
80
85
  rootStyle: StyleValue;
@@ -90,6 +95,7 @@ export declare const defaultPopupProps: {
90
95
  keepRender: boolean;
91
96
  overlayClosable: boolean;
92
97
  lockScroll: boolean;
98
+ backPress: "close" | "back" | "stop";
93
99
  }) => "slide-top" | "slide-right" | "slide-bottom" | "slide-left" | "zoom" | "fade" | "full-fade")) | undefined;
94
100
  overlay?: (boolean | ((props: {
95
101
  rootStyle: StyleValue;
@@ -105,6 +111,7 @@ export declare const defaultPopupProps: {
105
111
  keepRender: boolean;
106
112
  overlayClosable: boolean;
107
113
  lockScroll: boolean;
114
+ backPress: "close" | "back" | "stop";
108
115
  }) => boolean)) | undefined;
109
116
  overlayClass?: (string | ((props: {
110
117
  rootStyle: StyleValue;
@@ -120,6 +127,7 @@ export declare const defaultPopupProps: {
120
127
  keepRender: boolean;
121
128
  overlayClosable: boolean;
122
129
  lockScroll: boolean;
130
+ backPress: "close" | "back" | "stop";
123
131
  }) => string)) | undefined;
124
132
  overlayStyle?: (string | ((props: {
125
133
  rootStyle: StyleValue;
@@ -135,6 +143,7 @@ export declare const defaultPopupProps: {
135
143
  keepRender: boolean;
136
144
  overlayClosable: boolean;
137
145
  lockScroll: boolean;
146
+ backPress: "close" | "back" | "stop";
138
147
  }) => string)) | undefined;
139
148
  background?: (string | ((props: {
140
149
  rootStyle: StyleValue;
@@ -150,6 +159,7 @@ export declare const defaultPopupProps: {
150
159
  keepRender: boolean;
151
160
  overlayClosable: boolean;
152
161
  lockScroll: boolean;
162
+ backPress: "close" | "back" | "stop";
153
163
  }) => string)) | undefined;
154
164
  transparent?: (boolean | ((props: {
155
165
  rootStyle: StyleValue;
@@ -165,6 +175,7 @@ export declare const defaultPopupProps: {
165
175
  keepRender: boolean;
166
176
  overlayClosable: boolean;
167
177
  lockScroll: boolean;
178
+ backPress: "close" | "back" | "stop";
168
179
  }) => boolean)) | undefined;
169
180
  keepRender?: (boolean | ((props: {
170
181
  rootStyle: StyleValue;
@@ -180,6 +191,7 @@ export declare const defaultPopupProps: {
180
191
  keepRender: boolean;
181
192
  overlayClosable: boolean;
182
193
  lockScroll: boolean;
194
+ backPress: "close" | "back" | "stop";
183
195
  }) => boolean)) | undefined;
184
196
  overlayClosable?: (boolean | ((props: {
185
197
  rootStyle: StyleValue;
@@ -195,6 +207,7 @@ export declare const defaultPopupProps: {
195
207
  keepRender: boolean;
196
208
  overlayClosable: boolean;
197
209
  lockScroll: boolean;
210
+ backPress: "close" | "back" | "stop";
198
211
  }) => boolean)) | undefined;
199
212
  lockScroll?: (boolean | ((props: {
200
213
  rootStyle: StyleValue;
@@ -210,7 +223,24 @@ export declare const defaultPopupProps: {
210
223
  keepRender: boolean;
211
224
  overlayClosable: boolean;
212
225
  lockScroll: boolean;
226
+ backPress: "close" | "back" | "stop";
213
227
  }) => boolean)) | undefined;
228
+ backPress?: ("close" | "stop" | "back" | ((props: {
229
+ rootStyle: StyleValue;
230
+ rootClass: string;
231
+ visible: boolean;
232
+ duration: number;
233
+ effect: "slide-top" | "slide-right" | "slide-bottom" | "slide-left" | "zoom" | "fade" | "full-fade";
234
+ overlay: boolean;
235
+ overlayClass: string;
236
+ overlayStyle: string;
237
+ background: string;
238
+ transparent: boolean;
239
+ keepRender: boolean;
240
+ overlayClosable: boolean;
241
+ lockScroll: boolean;
242
+ backPress: "close" | "back" | "stop";
243
+ }) => "close" | "stop" | "back")) | undefined;
214
244
  };
215
245
  export interface PopupSlots {
216
246
  default?(props: Record<string, never>): any;
@@ -240,6 +270,7 @@ export interface TransitionHookCallbacks {
240
270
  export interface PopupEmits extends TransitionHookEmits {
241
271
  (e: 'overlay-click', event: any): void;
242
272
  (e: 'update:visible', visible: boolean): void;
273
+ (e: 'back-press'): void;
243
274
  }
244
275
  export interface PopupContext {
245
276
  visibleState: TransitionHookName | undefined;
@@ -23,6 +23,7 @@ declare const _default_1: __VLS_WithTemplateSlots<import("vue").DefineComponent<
23
23
  keepRender: boolean;
24
24
  overlayClosable: boolean;
25
25
  lockScroll: boolean;
26
+ backPress: "close" | "back" | "stop";
26
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, Readonly<PopupSlots> & PopupSlots>;
27
28
  export default _default_1;
28
29
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -1,4 +1,17 @@
1
1
  <template>
2
+ <!-- #ifdef MP -->
3
+ <page-container
4
+ v-if="backPress !== 'back' && isTopLayer && backPressVisible"
5
+ :show="visible"
6
+ :duration="0"
7
+ :z-index="0"
8
+ :overlay="false"
9
+ custom-style="display: none"
10
+ @beforeleave="onBeforeLeave"
11
+ @before-leave="onBeforeLeave"
12
+ ></page-container>
13
+ <!-- #endif -->
14
+
2
15
  <!-- #ifdef WEB -->
3
16
  <teleport to="body">
4
17
  <!-- #endif -->
@@ -52,11 +65,13 @@
52
65
 
53
66
  <script>
54
67
  import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from "vue";
55
- import { computed, reactive, ref, toRef } from "vue";
68
+ import { computed, reactive, ref, toRef, watch } from "vue";
56
69
  import { onHide, onShow } from "@dcloudio/uni-app";
57
70
  import { classNames, stringifyStyle, createBem } from "../../utils";
58
71
  import {
59
72
  useLockScroll,
73
+ useTimeout,
74
+ useTopPopup,
60
75
  useTransition,
61
76
  useZIndex
62
77
  } from "../../use";
@@ -79,7 +94,10 @@ import {
79
94
  * @property {boolean} overlayClosable 是否在点击遮罩层后关闭,默认值:true。
80
95
  * @property {boolean} keepRender 无论刚挂载还是隐藏,都始终不设置 display 为 none,一般用于内部包含计算尺寸的组件的情况,默认值:false。
81
96
  * @property {boolean} lockScroll 弹出框显示时,是否阻止页面滚动,默认值:true。
97
+ * @property {'close' | 'back' | 'stop'} backPress 弹出框显示时,劫持用户的返回操作,`close`: 关闭弹出框、`back`: 返回上一页、`stop`: 不关闭也不返回(仅小程序支持),默认值:'close'。
82
98
  * @event {(event: any) => void} overlay-click 点击遮罩时触发
99
+ * @event {(visible: boolean) => void} update 显隐时触发
100
+ * @event {() => void} back-press 用户进行返回操作时触发,仅限于 `close` 和 `stop`(仅小程序支持)
83
101
  * @event {(name: TransitionHookName) => void} visible-hook 入场/退场动画状态改变时触发
84
102
  * @event {() => void} before-enter 入场动画开始前触发
85
103
  * @event {() => void} enter 入场动画开始时触发
@@ -89,7 +107,6 @@ import {
89
107
  * @event {() => void} leave 退场动画开始时触发
90
108
  * @event {() => void} after-leave 退场动画结束时触发
91
109
  * @event {() => void} leave-cancelled 退场动画取消时触发
92
- * @event {(visible: boolean) => void} update 显隐时触发
93
110
  */
94
111
  export default _defineComponent({
95
112
  components: {
@@ -116,9 +133,10 @@ export default _defineComponent({
116
133
  transparent: { type: Boolean, required: false },
117
134
  keepRender: { type: Boolean, required: false },
118
135
  overlayClosable: { type: Boolean, required: false },
119
- lockScroll: { type: Boolean, required: false }
136
+ lockScroll: { type: Boolean, required: false },
137
+ backPress: { type: String, required: false }
120
138
  }, defaultPopupProps),
121
- emits: ["overlay-click", "update:visible", "before-enter", "enter", "after-enter", "enter-cancelled", "before-leave", "leave", "after-leave", "leave-cancelled", "visible-hook"],
139
+ emits: ["overlay-click", "update:visible", "back-press", "before-enter", "enter", "after-enter", "enter-cancelled", "before-leave", "leave", "after-leave", "leave-cancelled", "visible-hook"],
122
140
  setup(__props, { expose: __expose, emit: __emit }) {
123
141
  __expose();
124
142
  const props = __props;
@@ -154,6 +172,42 @@ export default _defineComponent({
154
172
  emit("update:visible", false);
155
173
  }
156
174
  };
175
+ // #ifndef WEB
176
+ const { isTopLayer } = useTopPopup(
177
+ () => props.visible,
178
+ () => props.backPress === "back",
179
+ () => {
180
+ emit("back-press");
181
+ emit("update:visible", false);
182
+ }
183
+ );
184
+ const onBeforeLeave = () => {
185
+ emit("back-press");
186
+ if (props.backPress === "stop") {
187
+ backPressVisible.value = false;
188
+ setTimeout(() => {
189
+ backPressVisible.value = true;
190
+ }, 50);
191
+ } else {
192
+ emit("update:visible", false);
193
+ }
194
+ };
195
+ const backPressVisible = ref(false);
196
+ const { start: setVisibleLater, stop: cancelDelayVisible } = useTimeout(() => {
197
+ backPressVisible.value = true;
198
+ }, 50);
199
+ watch(
200
+ () => props.visible,
201
+ (visible) => {
202
+ if (visible) {
203
+ setVisibleLater();
204
+ } else {
205
+ backPressVisible.value = false;
206
+ cancelDelayVisible();
207
+ }
208
+ }
209
+ );
210
+ // #endif
157
211
  const pageVisible = ref(true);
158
212
  // #ifdef WEB
159
213
  onShow(() => {
@@ -180,7 +234,7 @@ export default _defineComponent({
180
234
  transitionDuration: props.duration + "ms"
181
235
  });
182
236
  });
183
- const __returned__ = { props, emit, bem, zIndex, increaseZIndex, callVisibleHook, keepRenderClass, onVisibleHook, realVisible, transitionClass, onTransitionEnd, onOverlayClick, pageVisible, popupClass, popupStyle, SarOverlay };
237
+ const __returned__ = { props, emit, bem, zIndex, increaseZIndex, callVisibleHook, keepRenderClass, onVisibleHook, realVisible, transitionClass, onTransitionEnd, onOverlayClick, isTopLayer, onBeforeLeave, backPressVisible, setVisibleLater, cancelDelayVisible, pageVisible, popupClass, popupStyle, SarOverlay };
184
238
  return __returned__;
185
239
  }
186
240
  });
@@ -232,7 +286,7 @@ export default {
232
286
  const lockable = el.getAttribute("data-lock") === 'lockable'
233
287
 
234
288
  if (lockable) {
235
- hiddenCls = 'sar-popup-hidden-' + (~~(Math.random() * 10e8)).toString(36)
289
+ hiddenCls = 'sar-popup-hidden-' + (Math.floor(Math.random() * 10e10)).toString(36)
236
290
  addStyle()
237
291
  toggleLock(el.getAttribute("data-visible"))
238
292
 
@@ -2,7 +2,7 @@
2
2
  <view
3
3
  :class="resizeClass"
4
4
  :style="resizeStyle"
5
- @animationend="onAnimationEnd"
5
+ @animationend.stop="onAnimationEnd"
6
6
  >
7
7
  <scroll-view
8
8
  :class="bem.e('scroll-view')"
@@ -3,8 +3,10 @@
3
3
  effect="slide-bottom"
4
4
  :visible="innerVisible"
5
5
  :duration="duration"
6
+ back-press="close"
6
7
  @overlay-click="onOverlayClick"
7
8
  @visible-hook="onVisibleHook"
9
+ @back-press="onBackPress"
8
10
  >
9
11
  <view :class="shareSheetClass" :style="shareSheetStyle">
10
12
  <view v-if="title || description" :class="bem.e('header')">
@@ -101,6 +103,7 @@ import {
101
103
  * @property {boolean} overlayClosable 点击遮罩后是否关闭,默认值:true。
102
104
  * @property {boolean} keepRender 无论刚挂载还是隐藏,都始终不设置 display 为 none,一般用于内部包含计算尺寸的组件的情况,默认值:false。
103
105
  * @property {boolean} lockScroll 弹出框显示时,是否阻止页面滚动,默认值:true。
106
+ * @property {'close' | 'back' | 'stop'} backPress 弹出框显示时,劫持用户的返回操作,`close`: 关闭弹出框、`back`: 返回上一页、`stop`: 不关闭也不返回(仅小程序支持),默认值:'close'。
104
107
  * @property {ShareSheetItem[] | ShareSheetItem[][]} itemList 面板选项列表,默认值:[]。
105
108
  * @property {string} title 面板标题,默认值:-。
106
109
  * @property {string} description 面板描述,默认值:-。
@@ -202,6 +205,10 @@ export default _defineComponent({
202
205
  emit("visible-hook", name);
203
206
  emit(name);
204
207
  };
208
+ const onBackPress = () => {
209
+ innerVisible.value = false;
210
+ emit("update:visible", false);
211
+ };
205
212
  const isImg = (url) => {
206
213
  return typeof url === "string" && isFileUrl(url);
207
214
  };
@@ -211,7 +218,7 @@ export default _defineComponent({
211
218
  const shareSheetStyle = computed(() => {
212
219
  return stringifyStyle(props.rootStyle);
213
220
  });
214
- const __returned__ = { props, emit, bem, finalItemList, innerVisible, perhapsClose, onOverlayClick, onSelect, onCancel, onVisibleHook, isImg, shareSheetClass, shareSheetStyle, get classNames() {
221
+ const __returned__ = { props, emit, bem, finalItemList, innerVisible, perhapsClose, onOverlayClick, onSelect, onCancel, onVisibleHook, onBackPress, isImg, shareSheetClass, shareSheetStyle, get classNames() {
215
222
  return classNames;
216
223
  }, get stringifyStyle() {
217
224
  return stringifyStyle;
@@ -6,6 +6,7 @@
6
6
  :transparent="transparent"
7
7
  :root-style="popupStyle"
8
8
  :lock-scroll="false"
9
+ back-press="back"
9
10
  effect="fade"
10
11
  @visible-hook="onVisibleHook"
11
12
  >
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "sard-uniapp",
3
3
  "name": "sard-uniapp",
4
4
  "displayName": "sard-uniapp",
5
- "version": "1.25.6",
5
+ "version": "1.25.7",
6
6
  "description": "sard-uniapp 是一套基于 Uniapp + Vue3 框架开发的兼容多端的 UI 组件库",
7
7
  "main": "index.js",
8
8
  "scripts": {
@@ -76,26 +76,26 @@
76
76
  "@commitlint/config-conventional": "^17.8.1",
77
77
  "@commitlint/prompt-cli": "^17.8.1",
78
78
  "@dcloudio/types": "^3.4.8",
79
- "@dcloudio/uni-app": "3.0.0-4060420250429001",
80
- "@dcloudio/uni-app-harmony": "3.0.0-4060420250429001",
81
- "@dcloudio/uni-app-plus": "3.0.0-4060420250429001",
82
- "@dcloudio/uni-automator": "3.0.0-4060420250429001",
83
- "@dcloudio/uni-cli-shared": "3.0.0-4060420250429001",
84
- "@dcloudio/uni-components": "3.0.0-4060420250429001",
85
- "@dcloudio/uni-h5": "3.0.0-4060420250429001",
86
- "@dcloudio/uni-mp-alipay": "3.0.0-4060420250429001",
87
- "@dcloudio/uni-mp-baidu": "3.0.0-4060420250429001",
88
- "@dcloudio/uni-mp-harmony": "3.0.0-4060420250429001",
89
- "@dcloudio/uni-mp-jd": "3.0.0-4060420250429001",
90
- "@dcloudio/uni-mp-kuaishou": "3.0.0-4060420250429001",
91
- "@dcloudio/uni-mp-lark": "3.0.0-4060420250429001",
92
- "@dcloudio/uni-mp-qq": "3.0.0-4060420250429001",
93
- "@dcloudio/uni-mp-toutiao": "3.0.0-4060420250429001",
94
- "@dcloudio/uni-mp-weixin": "3.0.0-4060420250429001",
95
- "@dcloudio/uni-mp-xhs": "3.0.0-4060420250429001",
96
- "@dcloudio/uni-quickapp-webview": "3.0.0-4060420250429001",
97
- "@dcloudio/uni-stacktracey": "3.0.0-4060420250429001",
98
- "@dcloudio/vite-plugin-uni": "3.0.0-4060420250429001",
79
+ "@dcloudio/uni-app": "3.0.0-4080720251210001",
80
+ "@dcloudio/uni-app-harmony": "3.0.0-4080720251210001",
81
+ "@dcloudio/uni-app-plus": "3.0.0-4080720251210001",
82
+ "@dcloudio/uni-automator": "3.0.0-4080720251210001",
83
+ "@dcloudio/uni-cli-shared": "3.0.0-4080720251210001",
84
+ "@dcloudio/uni-components": "3.0.0-4080720251210001",
85
+ "@dcloudio/uni-h5": "3.0.0-4080720251210001",
86
+ "@dcloudio/uni-mp-alipay": "3.0.0-4080720251210001",
87
+ "@dcloudio/uni-mp-baidu": "3.0.0-4080720251210001",
88
+ "@dcloudio/uni-mp-harmony": "3.0.0-4080720251210001",
89
+ "@dcloudio/uni-mp-jd": "3.0.0-4080720251210001",
90
+ "@dcloudio/uni-mp-kuaishou": "3.0.0-4080720251210001",
91
+ "@dcloudio/uni-mp-lark": "3.0.0-4080720251210001",
92
+ "@dcloudio/uni-mp-qq": "3.0.0-4080720251210001",
93
+ "@dcloudio/uni-mp-toutiao": "3.0.0-4080720251210001",
94
+ "@dcloudio/uni-mp-weixin": "3.0.0-4080720251210001",
95
+ "@dcloudio/uni-mp-xhs": "3.0.0-4080720251210001",
96
+ "@dcloudio/uni-quickapp-webview": "3.0.0-4080720251210001",
97
+ "@dcloudio/uni-stacktracey": "3.0.0-4080720251210001",
98
+ "@dcloudio/vite-plugin-uni": "3.0.0-4080720251210001",
99
99
  "@esbuild/darwin-x64": "0.25.4",
100
100
  "@eslint/js": "^9.33.0",
101
101
  "@gunny/perf-test": "^0.1.3",
@@ -124,7 +124,7 @@
124
124
  "lodash-es": "^4.17.21",
125
125
  "prettier": "^3.5.3",
126
126
  "region-data": "^1.2.3",
127
- "sard-cli": "^1.3.7",
127
+ "sard-cli": "^1.3.8",
128
128
  "sass": "^1.90.0",
129
129
  "tailwindcss": "^3.4.17",
130
130
  "tel-area-code": "^1.1.0",
@@ -136,7 +136,7 @@
136
136
  "vite-plugin-eslint": "^1.8.1",
137
137
  "vitest": "^3.1.3",
138
138
  "vue": "^3.4.21",
139
- "vue-i18n": "^9.14.4",
139
+ "vue-i18n": "^9.1.9",
140
140
  "vue-tsc": "^2.0.29"
141
141
  },
142
142
  "author": "wuzhitao",
package/use/index.d.ts CHANGED
@@ -24,3 +24,4 @@ export * from './useSingleTask';
24
24
  export * from './useIntersectionObserver';
25
25
  export * from './useKeyList';
26
26
  export * from './useLockScroll';
27
+ export * from './useTopPopup';
package/use/index.js CHANGED
@@ -24,3 +24,4 @@ export * from './useSingleTask';
24
24
  export * from './useIntersectionObserver';
25
25
  export * from './useKeyList';
26
26
  export * from './useLockScroll';
27
+ export * from './useTopPopup';
@@ -0,0 +1,8 @@
1
+ import { MaybeRefOrGetter } from 'vue';
2
+ export declare function useTopPopup(visible: MaybeRefOrGetter<boolean>, disabled?: MaybeRefOrGetter<boolean>, callback?: () => void): {
3
+ isTopLayer: import("vue").ComputedRef<boolean>;
4
+ };
5
+ export declare function usePageTopPopup(): {
6
+ shouldStopBack: import("vue").ComputedRef<boolean>;
7
+ hidePopup: () => void;
8
+ };
@@ -0,0 +1,82 @@
1
+ import { computed, onMounted, onUnmounted, reactive, ref, toValue, watch, } from 'vue';
2
+ import { isApp, uniqid } from '../utils';
3
+ const popupStack = ref([]);
4
+ const pagesPopupStack = reactive({});
5
+ export function useTopPopup(visible, disabled, callback) {
6
+ const uid = uniqid();
7
+ const isDisabled = computed(() => toValue(disabled));
8
+ const pages = getCurrentPages();
9
+ const currentPath = pages[pages.length - 1].route;
10
+ if (!pagesPopupStack[currentPath]) {
11
+ pagesPopupStack[currentPath] = [];
12
+ }
13
+ const add = () => {
14
+ if (!popupStack.value.includes(uid)) {
15
+ popupStack.value.push(uid);
16
+ }
17
+ if (!pagesPopupStack[currentPath].includes(uid)) {
18
+ pagesPopupStack[currentPath].push(uid);
19
+ }
20
+ };
21
+ const remove = () => {
22
+ const index = popupStack.value.indexOf(uid);
23
+ if (index !== -1) {
24
+ popupStack.value.splice(index, 1);
25
+ }
26
+ const pIndex = pagesPopupStack[currentPath].indexOf(uid);
27
+ if (pIndex !== -1) {
28
+ pagesPopupStack[currentPath].splice(pIndex, 1);
29
+ }
30
+ };
31
+ watch(() => toValue(visible), (visible) => {
32
+ if (isDisabled.value)
33
+ return;
34
+ if (visible) {
35
+ add();
36
+ }
37
+ else {
38
+ remove();
39
+ }
40
+ }, {
41
+ immediate: true,
42
+ });
43
+ const hidePopup = () => {
44
+ if (!isDisabled.value && toValue(visible) && isApp) {
45
+ callback?.();
46
+ }
47
+ };
48
+ onMounted(() => {
49
+ uni.$on(uid, hidePopup);
50
+ });
51
+ onUnmounted(() => {
52
+ remove();
53
+ uni.$off(uid, hidePopup);
54
+ });
55
+ const isTopLayer = computed(() => {
56
+ return popupStack.value[popupStack.value.length - 1] === uid;
57
+ });
58
+ return {
59
+ isTopLayer,
60
+ };
61
+ }
62
+ export function usePageTopPopup() {
63
+ const pages = getCurrentPages();
64
+ const currentPath = pages[pages.length - 1].route;
65
+ if (!pagesPopupStack[currentPath]) {
66
+ pagesPopupStack[currentPath] = [];
67
+ }
68
+ const shouldStopBack = computed(() => {
69
+ return pagesPopupStack[currentPath].length > 0;
70
+ });
71
+ const hidePopup = () => {
72
+ const popupStack = pagesPopupStack[currentPath];
73
+ const uid = popupStack[popupStack.length - 1];
74
+ if (uid) {
75
+ uni.$emit(uid);
76
+ }
77
+ };
78
+ return {
79
+ shouldStopBack,
80
+ hidePopup,
81
+ };
82
+ }
package/utils/string.d.ts CHANGED
@@ -30,9 +30,6 @@ export declare function snakeCase(string: string): string;
30
30
  * 每n位数字添加一个分隔符
31
31
  */
32
32
  export declare function addSeparator(num: number | string, separator?: string, digit?: number): string;
33
- /**
34
- * 生成唯一ID,用于设置元素的ID,以便获取
35
- */
36
33
  export declare function uniqid(prefix?: string): string;
37
34
  export type ClassProp = string | number | null | undefined | Record<string, any> | ClassProp[];
38
35
  /**
package/utils/string.js CHANGED
@@ -60,10 +60,14 @@ export function addSeparator(num, separator = ',', digit = 3) {
60
60
  return String(num).replace(new RegExp(`\\B(?=(\\d{${digit}})+(?!\\d))`, 'g'), separator);
61
61
  }
62
62
  /**
63
- * 生成唯一ID,用于设置元素的ID,以便获取
63
+ * 生成唯一ID,可作为元素选择器,或者用于表示全局唯一字符串,仅限于当前应用生命周期
64
64
  */
65
+ let counter = 0;
65
66
  export function uniqid(prefix = '__sar_') {
66
- return prefix + (~~(Math.random() * 10e8)).toString(36);
67
+ return (prefix +
68
+ (~~(Math.random() * 10e8)).toString(36) +
69
+ '-' +
70
+ (++counter).toString(36));
67
71
  }
68
72
  /**
69
73
  * 把各种类型的参数拼接成字符串类名,以便解决小程序不支持 classObject 的问题