react-modal-sheet 5.5.0 → 5.7.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.
- package/README.md +305 -89
- package/dist/index.d.mts +16 -7
- package/dist/index.d.ts +16 -7
- package/dist/index.js +604 -558
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +581 -535
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/context.tsx +16 -6
- package/src/hooks/use-modal-effect.ts +147 -85
- package/src/index.tsx +11 -16
- package/src/{SheetBackdrop.tsx → sheet-backdrop.tsx} +3 -12
- package/src/{SheetContainer.tsx → sheet-container.tsx} +2 -2
- package/src/{SheetContent.tsx → sheet-content.tsx} +9 -3
- package/src/{SheetDragIndicator.tsx → sheet-drag-indicator.tsx} +2 -2
- package/src/{SheetHeader.tsx → sheet-header.tsx} +3 -3
- package/src/sheet.tsx +38 -29
- package/src/snap.ts +1 -5
- package/src/types.tsx +13 -1
- package/src/utils.ts +4 -0
package/dist/index.mjs
CHANGED
|
@@ -1,122 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import React, { createContext, forwardRef, useRef, useState, useMemo, useImperativeHandle, useEffect, useLayoutEffect, useCallback, useContext } from 'react';
|
|
2
|
+
import { useMotionValue, useTransform, useReducedMotion, motion, animate } from 'motion/react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import useMeasure from 'react-use-measure';
|
|
5
5
|
import { transform } from 'motion';
|
|
6
6
|
|
|
7
|
-
// src/
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
// src/context.tsx
|
|
8
|
+
var InternalSheetContext = createContext(void 0);
|
|
9
|
+
var ExposedSheetContext = createContext(void 0);
|
|
10
|
+
function useInternalContext() {
|
|
11
|
+
const context = useContext(InternalSheetContext);
|
|
12
|
+
if (!context) throw new Error("Sheet context error");
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
function useExposedContext() {
|
|
16
|
+
const context = useContext(ExposedSheetContext);
|
|
13
17
|
if (!context) throw new Error("Sheet context error");
|
|
14
18
|
return context;
|
|
15
19
|
}
|
|
16
|
-
|
|
17
|
-
// src/styles.ts
|
|
18
|
-
var styles = {
|
|
19
|
-
root: {
|
|
20
|
-
base: {
|
|
21
|
-
position: "fixed",
|
|
22
|
-
top: 0,
|
|
23
|
-
bottom: 0,
|
|
24
|
-
left: 0,
|
|
25
|
-
right: 0,
|
|
26
|
-
overflow: "hidden",
|
|
27
|
-
pointerEvents: "none"
|
|
28
|
-
},
|
|
29
|
-
decorative: {}
|
|
30
|
-
},
|
|
31
|
-
backdrop: {
|
|
32
|
-
base: {
|
|
33
|
-
zIndex: 1,
|
|
34
|
-
position: "fixed",
|
|
35
|
-
top: 0,
|
|
36
|
-
left: 0,
|
|
37
|
-
width: "100%",
|
|
38
|
-
height: "100%",
|
|
39
|
-
touchAction: "none",
|
|
40
|
-
userSelect: "none"
|
|
41
|
-
},
|
|
42
|
-
decorative: {
|
|
43
|
-
backgroundColor: "rgba(0, 0, 0, 0.2)",
|
|
44
|
-
border: "none",
|
|
45
|
-
WebkitTapHighlightColor: "transparent"
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
container: {
|
|
49
|
-
base: {
|
|
50
|
-
zIndex: 2,
|
|
51
|
-
position: "absolute",
|
|
52
|
-
left: 0,
|
|
53
|
-
bottom: 0,
|
|
54
|
-
width: "100%",
|
|
55
|
-
pointerEvents: "auto",
|
|
56
|
-
display: "flex",
|
|
57
|
-
flexDirection: "column"
|
|
58
|
-
},
|
|
59
|
-
decorative: {
|
|
60
|
-
backgroundColor: "#fff",
|
|
61
|
-
borderTopRightRadius: "8px",
|
|
62
|
-
borderTopLeftRadius: "8px",
|
|
63
|
-
boxShadow: "0px -2px 16px rgba(0, 0, 0, 0.3)"
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
headerWrapper: {
|
|
67
|
-
base: {
|
|
68
|
-
width: "100%"
|
|
69
|
-
},
|
|
70
|
-
decorative: {}
|
|
71
|
-
},
|
|
72
|
-
header: {
|
|
73
|
-
base: {
|
|
74
|
-
width: "100%",
|
|
75
|
-
position: "relative"
|
|
76
|
-
},
|
|
77
|
-
decorative: {
|
|
78
|
-
height: "40px",
|
|
79
|
-
display: "flex",
|
|
80
|
-
alignItems: "center",
|
|
81
|
-
justifyContent: "center"
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
indicatorWrapper: {
|
|
85
|
-
base: {
|
|
86
|
-
display: "flex"
|
|
87
|
-
},
|
|
88
|
-
decorative: {}
|
|
89
|
-
},
|
|
90
|
-
indicator: {
|
|
91
|
-
base: {
|
|
92
|
-
display: "inline-block"
|
|
93
|
-
},
|
|
94
|
-
decorative: {
|
|
95
|
-
width: "18px",
|
|
96
|
-
height: "4px",
|
|
97
|
-
borderRadius: "99px",
|
|
98
|
-
backgroundColor: "#ddd"
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
content: {
|
|
102
|
-
base: {
|
|
103
|
-
minHeight: "0px",
|
|
104
|
-
position: "relative",
|
|
105
|
-
flexGrow: 1,
|
|
106
|
-
display: "flex",
|
|
107
|
-
flexDirection: "column"
|
|
108
|
-
},
|
|
109
|
-
decorative: {}
|
|
110
|
-
},
|
|
111
|
-
scroller: {
|
|
112
|
-
base: {
|
|
113
|
-
height: "100%",
|
|
114
|
-
overflowY: "auto",
|
|
115
|
-
overscrollBehaviorY: "none"
|
|
116
|
-
},
|
|
117
|
-
decorative: {}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
20
|
|
|
121
21
|
// src/constants.ts
|
|
122
22
|
var DEFAULT_HEIGHT = "calc(100% - env(safe-area-inset-top) - 34px)";
|
|
@@ -131,6 +31,29 @@ var REDUCED_MOTION_TWEEN_CONFIG = {
|
|
|
131
31
|
};
|
|
132
32
|
var DEFAULT_DRAG_CLOSE_THRESHOLD = 0.6;
|
|
133
33
|
var DEFAULT_DRAG_VELOCITY_THRESHOLD = 1200;
|
|
34
|
+
var useIsomorphicLayoutEffect = IS_SSR ? useEffect : useLayoutEffect;
|
|
35
|
+
|
|
36
|
+
// src/hooks/use-dimensions.ts
|
|
37
|
+
function useDimensions() {
|
|
38
|
+
const [dimensions, setDimensions] = useState(() => ({
|
|
39
|
+
windowHeight: !IS_SSR ? window.innerHeight : 0,
|
|
40
|
+
windowWidth: !IS_SSR ? window.innerWidth : 0
|
|
41
|
+
}));
|
|
42
|
+
useIsomorphicLayoutEffect(() => {
|
|
43
|
+
function handler() {
|
|
44
|
+
setDimensions({
|
|
45
|
+
windowHeight: window.innerHeight,
|
|
46
|
+
windowWidth: window.innerWidth
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
handler();
|
|
50
|
+
window.addEventListener("resize", handler);
|
|
51
|
+
return () => {
|
|
52
|
+
window.removeEventListener("resize", handler);
|
|
53
|
+
};
|
|
54
|
+
}, []);
|
|
55
|
+
return dimensions;
|
|
56
|
+
}
|
|
134
57
|
|
|
135
58
|
// src/utils.ts
|
|
136
59
|
function applyStyles(styles2, unstyled) {
|
|
@@ -213,86 +136,9 @@ function willOpenKeyboard(target) {
|
|
|
213
136
|
function isHTTPS() {
|
|
214
137
|
return typeof window !== "undefined" && window.isSecureContext;
|
|
215
138
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
var isClickable = (props) => !!props.onClick || !!props.onTap;
|
|
219
|
-
var SheetBackdrop = forwardRef(
|
|
220
|
-
({ style, className = "", unstyled, ...rest }, ref) => {
|
|
221
|
-
const sheetContext = useSheetContext();
|
|
222
|
-
const clickable = isClickable(rest);
|
|
223
|
-
const Comp = clickable ? motion.button : motion.div;
|
|
224
|
-
const pointerEvents = clickable ? "auto" : "none";
|
|
225
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
226
|
-
const backdropStyle = {
|
|
227
|
-
...applyStyles(styles.backdrop, isUnstyled),
|
|
228
|
-
...style,
|
|
229
|
-
pointerEvents
|
|
230
|
-
};
|
|
231
|
-
const animationProps = sheetContext.prefersReducedMotion ? {} : {
|
|
232
|
-
initial: { opacity: 0 },
|
|
233
|
-
animate: { opacity: 1 },
|
|
234
|
-
exit: { opacity: 0 },
|
|
235
|
-
transition: { duration: 1 }
|
|
236
|
-
};
|
|
237
|
-
return /* @__PURE__ */ React4.createElement(
|
|
238
|
-
Comp,
|
|
239
|
-
{
|
|
240
|
-
...animationProps,
|
|
241
|
-
...rest,
|
|
242
|
-
ref,
|
|
243
|
-
className: `react-modal-sheet-backdrop ${className}`,
|
|
244
|
-
style: backdropStyle
|
|
245
|
-
}
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
);
|
|
249
|
-
SheetBackdrop.displayName = "SheetBackdrop";
|
|
250
|
-
var SheetContainer = forwardRef(
|
|
251
|
-
({ children, style, className = "", unstyled, ...rest }, ref) => {
|
|
252
|
-
const sheetContext = useSheetContext();
|
|
253
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
254
|
-
const containerStyle = {
|
|
255
|
-
...applyStyles(styles.container, isUnstyled),
|
|
256
|
-
...style,
|
|
257
|
-
y: sheetContext.y
|
|
258
|
-
};
|
|
259
|
-
if (sheetContext.detent === "default") {
|
|
260
|
-
containerStyle.height = DEFAULT_HEIGHT;
|
|
261
|
-
}
|
|
262
|
-
if (sheetContext.detent === "full") {
|
|
263
|
-
containerStyle.height = "100%";
|
|
264
|
-
containerStyle.maxHeight = "100%";
|
|
265
|
-
}
|
|
266
|
-
if (sheetContext.detent === "content") {
|
|
267
|
-
containerStyle.height = "auto";
|
|
268
|
-
containerStyle.maxHeight = DEFAULT_HEIGHT;
|
|
269
|
-
}
|
|
270
|
-
return /* @__PURE__ */ React4.createElement(
|
|
271
|
-
motion.div,
|
|
272
|
-
{
|
|
273
|
-
...rest,
|
|
274
|
-
ref: mergeRefs([
|
|
275
|
-
ref,
|
|
276
|
-
sheetContext.sheetRef,
|
|
277
|
-
sheetContext.sheetBoundsRef
|
|
278
|
-
]),
|
|
279
|
-
className: `react-modal-sheet-container ${className}`,
|
|
280
|
-
style: containerStyle
|
|
281
|
-
},
|
|
282
|
-
children
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
);
|
|
286
|
-
SheetContainer.displayName = "SheetContainer";
|
|
287
|
-
var constraints = { bottom: 0, top: 0, left: 0, right: 0 };
|
|
288
|
-
function useDragConstraints() {
|
|
289
|
-
const ref = useRef(null);
|
|
290
|
-
const onMeasure = useCallback(() => constraints, []);
|
|
291
|
-
return { ref, onMeasure };
|
|
139
|
+
function clamp(value, min, max) {
|
|
140
|
+
return Math.min(Math.max(value, min), max);
|
|
292
141
|
}
|
|
293
|
-
var useIsomorphicLayoutEffect = IS_SSR ? useEffect : useLayoutEffect;
|
|
294
|
-
|
|
295
|
-
// src/hooks/use-stable-callback.ts
|
|
296
142
|
function useStableCallback(handler) {
|
|
297
143
|
const handlerRef = useRef(void 0);
|
|
298
144
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -303,251 +149,18 @@ function useStableCallback(handler) {
|
|
|
303
149
|
return fn == null ? void 0 : fn(...args);
|
|
304
150
|
}, []);
|
|
305
151
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
function
|
|
309
|
-
const {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
);
|
|
319
|
-
const determineScrollPosition = useStableCallback((element2) => {
|
|
320
|
-
const { scrollTop, scrollHeight, clientHeight } = element2;
|
|
321
|
-
const isScrollable2 = scrollHeight > clientHeight;
|
|
322
|
-
if (!isScrollable2) {
|
|
323
|
-
if (scrollPosition) setScrollPosition(void 0);
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
const isAtTop = scrollTop <= 0;
|
|
327
|
-
const isAtBottom = Math.ceil(scrollHeight) - Math.ceil(scrollTop) === Math.ceil(clientHeight);
|
|
328
|
-
let position;
|
|
329
|
-
if (isAtTop) {
|
|
330
|
-
position = "top";
|
|
331
|
-
} else if (isAtBottom) {
|
|
332
|
-
position = "bottom";
|
|
333
|
-
} else {
|
|
334
|
-
position = "middle";
|
|
335
|
-
}
|
|
336
|
-
element2.style.touchAction = isAtTop ? "pan-down" : "";
|
|
337
|
-
if (position === scrollPosition) return;
|
|
338
|
-
setScrollPosition(position);
|
|
339
|
-
});
|
|
340
|
-
const onScroll = useStableCallback((event) => {
|
|
341
|
-
if (event.currentTarget instanceof HTMLElement) {
|
|
342
|
-
const el = event.currentTarget;
|
|
343
|
-
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
344
|
-
if (debounceDelay === 0) {
|
|
345
|
-
determineScrollPosition(el);
|
|
346
|
-
} else {
|
|
347
|
-
scrollTimeoutRef.current = setTimeout(
|
|
348
|
-
() => determineScrollPosition(el),
|
|
349
|
-
debounceDelay
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
const onTouchStart = useStableCallback((event) => {
|
|
355
|
-
if (event.currentTarget instanceof HTMLElement) {
|
|
356
|
-
const element2 = event.currentTarget;
|
|
357
|
-
requestAnimationFrame(() => {
|
|
358
|
-
determineScrollPosition(element2);
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
useEffect(() => {
|
|
363
|
-
if (!element || !isEnabled) return;
|
|
364
|
-
determineScrollPosition(element);
|
|
365
|
-
element.addEventListener("scroll", onScroll);
|
|
366
|
-
element.addEventListener("touchstart", onTouchStart);
|
|
367
|
-
return () => {
|
|
368
|
-
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
369
|
-
element.removeEventListener("scroll", onScroll);
|
|
370
|
-
element.removeEventListener("touchstart", onTouchStart);
|
|
371
|
-
};
|
|
372
|
-
}, [element, isEnabled]);
|
|
373
|
-
return {
|
|
374
|
-
scrollRef,
|
|
375
|
-
scrollPosition
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// src/SheetContent.tsx
|
|
380
|
-
var SheetContent = forwardRef(
|
|
381
|
-
({
|
|
382
|
-
disableScroll: disableScrollProp,
|
|
383
|
-
disableDrag: disableDragProp,
|
|
384
|
-
children,
|
|
385
|
-
style: styleProp,
|
|
386
|
-
className = "",
|
|
387
|
-
scrollClassName = "",
|
|
388
|
-
scrollStyle: scrollStyleProp,
|
|
389
|
-
scrollRef: scrollRefProp = null,
|
|
390
|
-
unstyled,
|
|
391
|
-
...rest
|
|
392
|
-
}, ref) => {
|
|
393
|
-
const sheetContext = useSheetContext();
|
|
394
|
-
const dragConstraints = useDragConstraints();
|
|
395
|
-
const scroll = useScrollPosition({
|
|
396
|
-
isEnabled: typeof disableScrollProp === "function" ? true : !disableScrollProp
|
|
397
|
-
});
|
|
398
|
-
const disableScroll = typeof disableScrollProp === "function" ? disableScrollProp({
|
|
399
|
-
scrollPosition: scroll.scrollPosition,
|
|
400
|
-
currentSnap: sheetContext.currentSnap
|
|
401
|
-
}) : Boolean(disableScrollProp);
|
|
402
|
-
const disableDragDueToScroll = !disableScroll && scroll.scrollPosition && scroll.scrollPosition !== "top";
|
|
403
|
-
const disableDragDueToProp = typeof disableDragProp === "function" ? disableDragProp({
|
|
404
|
-
scrollPosition: scroll.scrollPosition,
|
|
405
|
-
currentSnap: sheetContext.currentSnap
|
|
406
|
-
}) : Boolean(disableDragProp);
|
|
407
|
-
const disableDrag = disableDragDueToProp || disableDragDueToScroll || sheetContext.disableDrag;
|
|
408
|
-
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
409
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
410
|
-
const contentStyle = {
|
|
411
|
-
...applyStyles(styles.content, isUnstyled),
|
|
412
|
-
...styleProp
|
|
413
|
-
};
|
|
414
|
-
const scrollStyle = applyStyles(styles.scroller, isUnstyled);
|
|
415
|
-
if (sheetContext.avoidKeyboard) {
|
|
416
|
-
scrollStyle.paddingBottom = isHTTPS() ? "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))" : "var(--keyboard-inset-height, 0px)";
|
|
417
|
-
}
|
|
418
|
-
if (disableScroll) {
|
|
419
|
-
scrollStyle.overflowY = "hidden";
|
|
420
|
-
}
|
|
421
|
-
if (dragProps !== void 0) {
|
|
422
|
-
scrollStyle.touchAction = "pan-down";
|
|
423
|
-
}
|
|
424
|
-
return /* @__PURE__ */ React4.createElement(
|
|
425
|
-
motion.div,
|
|
426
|
-
{
|
|
427
|
-
...rest,
|
|
428
|
-
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
429
|
-
className: `react-modal-sheet-content ${className}`,
|
|
430
|
-
style: contentStyle,
|
|
431
|
-
...dragProps,
|
|
432
|
-
dragConstraints: dragConstraints.ref,
|
|
433
|
-
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
434
|
-
},
|
|
435
|
-
/* @__PURE__ */ React4.createElement(
|
|
436
|
-
motion.div,
|
|
437
|
-
{
|
|
438
|
-
ref: mergeRefs([scroll.scrollRef, scrollRefProp]),
|
|
439
|
-
style: { ...scrollStyle, ...scrollStyleProp },
|
|
440
|
-
className: `react-modal-sheet-content-scroller ${scrollClassName}`
|
|
441
|
-
},
|
|
442
|
-
children
|
|
443
|
-
)
|
|
444
|
-
);
|
|
445
|
-
}
|
|
446
|
-
);
|
|
447
|
-
SheetContent.displayName = "SheetContent";
|
|
448
|
-
function SheetDragIndicator({
|
|
449
|
-
style,
|
|
450
|
-
className = "",
|
|
451
|
-
unstyled,
|
|
452
|
-
...rest
|
|
453
|
-
}) {
|
|
454
|
-
const sheetContext = useSheetContext();
|
|
455
|
-
const indicator1Transform = useTransform(
|
|
456
|
-
sheetContext.indicatorRotation,
|
|
457
|
-
(r) => `translateX(2px) rotate(${r}deg)`
|
|
458
|
-
);
|
|
459
|
-
const indicator2Transform = useTransform(
|
|
460
|
-
sheetContext.indicatorRotation,
|
|
461
|
-
(r) => `translateX(-2px) rotate(${ -1 * r}deg)`
|
|
462
|
-
);
|
|
463
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
464
|
-
const indicatorWrapperStyle = {
|
|
465
|
-
...applyStyles(styles.indicatorWrapper, isUnstyled),
|
|
466
|
-
...style
|
|
467
|
-
};
|
|
468
|
-
const indicatorStyle = applyStyles(styles.indicator, isUnstyled);
|
|
469
|
-
return /* @__PURE__ */ React4.createElement(
|
|
470
|
-
"div",
|
|
471
|
-
{
|
|
472
|
-
className: `react-modal-sheet-drag-indicator-container ${className}`,
|
|
473
|
-
style: indicatorWrapperStyle,
|
|
474
|
-
...rest
|
|
475
|
-
},
|
|
476
|
-
/* @__PURE__ */ React4.createElement(
|
|
477
|
-
motion.span,
|
|
478
|
-
{
|
|
479
|
-
className: "react-modal-sheet-drag-indicator",
|
|
480
|
-
style: { ...indicatorStyle, transform: indicator1Transform }
|
|
481
|
-
}
|
|
482
|
-
),
|
|
483
|
-
/* @__PURE__ */ React4.createElement(
|
|
484
|
-
motion.span,
|
|
485
|
-
{
|
|
486
|
-
className: "react-modal-sheet-drag-indicator",
|
|
487
|
-
style: { ...indicatorStyle, transform: indicator2Transform }
|
|
488
|
-
}
|
|
489
|
-
)
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
var SheetHeader = forwardRef(
|
|
493
|
-
({ children, style, disableDrag, unstyled, className = "", ...rest }, ref) => {
|
|
494
|
-
const sheetContext = useSheetContext();
|
|
495
|
-
const dragConstraints = useDragConstraints();
|
|
496
|
-
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
497
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
498
|
-
const headerWrapperStyle = {
|
|
499
|
-
...applyStyles(styles.headerWrapper, isUnstyled),
|
|
500
|
-
...style
|
|
501
|
-
};
|
|
502
|
-
const headerStyle = applyStyles(styles.header, isUnstyled);
|
|
503
|
-
return /* @__PURE__ */ React4.createElement(
|
|
504
|
-
motion.div,
|
|
505
|
-
{
|
|
506
|
-
...rest,
|
|
507
|
-
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
508
|
-
style: headerWrapperStyle,
|
|
509
|
-
className: `react-modal-sheet-header-container ${className}`,
|
|
510
|
-
...dragProps,
|
|
511
|
-
dragConstraints: dragConstraints.ref,
|
|
512
|
-
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
513
|
-
},
|
|
514
|
-
children || /* @__PURE__ */ React4.createElement("div", { className: "react-modal-sheet-header", style: headerStyle }, /* @__PURE__ */ React4.createElement(SheetDragIndicator, null))
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
);
|
|
518
|
-
SheetHeader.displayName = "SheetHeader";
|
|
519
|
-
function useDimensions() {
|
|
520
|
-
const [dimensions, setDimensions] = useState(() => ({
|
|
521
|
-
windowHeight: !IS_SSR ? window.innerHeight : 0,
|
|
522
|
-
windowWidth: !IS_SSR ? window.innerWidth : 0
|
|
523
|
-
}));
|
|
524
|
-
useIsomorphicLayoutEffect(() => {
|
|
525
|
-
function handler() {
|
|
526
|
-
setDimensions({
|
|
527
|
-
windowHeight: window.innerHeight,
|
|
528
|
-
windowWidth: window.innerWidth
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
handler();
|
|
532
|
-
window.addEventListener("resize", handler);
|
|
533
|
-
return () => {
|
|
534
|
-
window.removeEventListener("resize", handler);
|
|
535
|
-
};
|
|
536
|
-
}, []);
|
|
537
|
-
return dimensions;
|
|
538
|
-
}
|
|
539
|
-
var virtualKeyboardOverlayUsers = 0;
|
|
540
|
-
var initialVirtualKeyboardOverlaysContent = null;
|
|
541
|
-
function useVirtualKeyboard(options = {}) {
|
|
542
|
-
const {
|
|
543
|
-
containerRef,
|
|
544
|
-
isEnabled = true,
|
|
545
|
-
debounceDelay = 100,
|
|
546
|
-
visualViewportThreshold = 100
|
|
547
|
-
} = options;
|
|
548
|
-
const [state, setState] = useState({
|
|
549
|
-
isVisible: false,
|
|
550
|
-
height: 0
|
|
152
|
+
var virtualKeyboardOverlayUsers = 0;
|
|
153
|
+
var initialVirtualKeyboardOverlaysContent = null;
|
|
154
|
+
function useVirtualKeyboard(options = {}) {
|
|
155
|
+
const {
|
|
156
|
+
containerRef,
|
|
157
|
+
isEnabled = true,
|
|
158
|
+
debounceDelay = 100,
|
|
159
|
+
visualViewportThreshold = 100
|
|
160
|
+
} = options;
|
|
161
|
+
const [state, setState] = useState({
|
|
162
|
+
isVisible: false,
|
|
163
|
+
height: 0
|
|
551
164
|
});
|
|
552
165
|
const focusedElementRef = useRef(null);
|
|
553
166
|
const debounceTimer = useRef(null);
|
|
@@ -768,77 +381,109 @@ function useModalEffect({
|
|
|
768
381
|
console.warn('Using "full" detent with modal effect is not supported.');
|
|
769
382
|
rootId = void 0;
|
|
770
383
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
384
|
+
const handleYChange = useStableCallback((yValue) => {
|
|
385
|
+
if (!rootId) return;
|
|
386
|
+
let progress = Math.max(0, 1 - yValue / sheetHeight);
|
|
387
|
+
const snapThresholdPoint = snapPoints.length > 1 ? snapPoints[snapPoints.length - 2] : void 0;
|
|
388
|
+
if (snapThresholdPoint !== void 0) {
|
|
389
|
+
const snapThresholdValue = snapThresholdPoint.snapValueY;
|
|
390
|
+
if (yValue <= snapThresholdValue) {
|
|
391
|
+
progress = (snapThresholdValue - yValue) / snapThresholdValue;
|
|
392
|
+
} else {
|
|
393
|
+
progress = 0;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (startThreshold !== void 0) {
|
|
397
|
+
const startThresholdValue = sheetHeight - Math.min(Math.floor(startThreshold * sheetHeight), sheetHeight);
|
|
398
|
+
if (yValue <= startThresholdValue) {
|
|
399
|
+
progress = (startThresholdValue - yValue) / startThresholdValue;
|
|
400
|
+
} else {
|
|
401
|
+
progress = 0;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
progress = Math.max(0, Math.min(1, progress));
|
|
405
|
+
updateModalEffect(rootId, { progress, insetTop });
|
|
406
|
+
});
|
|
407
|
+
const handleYComplete = useStableCallback(() => {
|
|
408
|
+
if (!rootId) return;
|
|
409
|
+
if (y.get() + 5 >= sheetHeight) {
|
|
410
|
+
cleanupModalEffect(rootId);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
useEffect(() => {
|
|
777
414
|
if (!rootId) return;
|
|
778
|
-
const root = document.querySelector(`#${rootId}`);
|
|
779
|
-
if (!root) return;
|
|
780
415
|
const removeStartListener = y.on("animationStart", () => {
|
|
781
|
-
setupModalEffect(rootId);
|
|
416
|
+
if (rootId) setupModalEffect(rootId);
|
|
782
417
|
});
|
|
783
418
|
const removeChangeListener = y.on("change", (yValue) => {
|
|
784
|
-
|
|
785
|
-
let progress = Math.max(0, 1 - yValue / sheetHeight);
|
|
786
|
-
const snapThresholdPoint = snapPoints.length > 1 ? snapPoints[snapPoints.length - 2] : void 0;
|
|
787
|
-
if (snapThresholdPoint !== void 0) {
|
|
788
|
-
const snapThresholdValue = snapThresholdPoint.snapValueY;
|
|
789
|
-
if (yValue <= snapThresholdValue) {
|
|
790
|
-
progress = (snapThresholdValue - yValue) / snapThresholdValue;
|
|
791
|
-
} else {
|
|
792
|
-
progress = 0;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
if (startThreshold !== void 0) {
|
|
796
|
-
const startThresholdValue = sheetHeight - Math.min(Math.floor(startThreshold * sheetHeight), sheetHeight);
|
|
797
|
-
if (yValue <= startThresholdValue) {
|
|
798
|
-
progress = (startThresholdValue - yValue) / startThresholdValue;
|
|
799
|
-
} else {
|
|
800
|
-
progress = 0;
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
progress = Math.max(0, Math.min(1, progress));
|
|
804
|
-
const pageWidth = window.innerWidth;
|
|
805
|
-
const ty = transform(progress, [0, 1], [0, 24 + insetTop]);
|
|
806
|
-
const s = transform(progress, [0, 1], [1, (pageWidth - 16) / pageWidth]);
|
|
807
|
-
const borderRadius = transform(progress, [0, 1], [0, 10]);
|
|
808
|
-
root.style.transform = `scale(${s}) translate3d(0, ${ty}px, 0)`;
|
|
809
|
-
root.style.borderTopRightRadius = `${borderRadius}px`;
|
|
810
|
-
root.style.borderTopLeftRadius = `${borderRadius}px`;
|
|
419
|
+
handleYChange(yValue);
|
|
811
420
|
});
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
cleanupModalEffect(rootId);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
const removeCompleteListener = y.on("animationComplete", onCompleted);
|
|
818
|
-
const removeCancelListener = y.on("animationCancel", onCompleted);
|
|
421
|
+
const removeCompleteListener = y.on("animationComplete", handleYComplete);
|
|
422
|
+
const removeCancelListener = y.on("animationCancel", handleYComplete);
|
|
819
423
|
return () => {
|
|
424
|
+
if (rootId) cleanupModalEffect(rootId);
|
|
820
425
|
removeStartListener();
|
|
821
426
|
removeChangeListener();
|
|
822
427
|
removeCompleteListener();
|
|
823
428
|
removeCancelListener();
|
|
824
429
|
};
|
|
825
|
-
}, [
|
|
430
|
+
}, [rootId]);
|
|
826
431
|
}
|
|
827
432
|
function setupModalEffect(rootId) {
|
|
828
|
-
const
|
|
433
|
+
const target = getModalEffectTarget(rootId);
|
|
434
|
+
if (!target) return;
|
|
435
|
+
if (target.type === "sheet") {
|
|
436
|
+
const sheet = target.element;
|
|
437
|
+
sheet.style.transformOrigin = "center top";
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const root = target.element;
|
|
829
441
|
const body = document.querySelector("body");
|
|
830
|
-
|
|
831
|
-
body.style.backgroundColor = "#000";
|
|
442
|
+
body.style.backgroundColor = "#000000";
|
|
832
443
|
root.style.overflow = "hidden";
|
|
833
444
|
root.style.transitionTimingFunction = "cubic-bezier(0.32, 0.72, 0, 1)";
|
|
834
445
|
root.style.transitionProperty = "transform, border-radius";
|
|
835
446
|
root.style.transitionDuration = "0.5s";
|
|
836
447
|
root.style.transformOrigin = "center top";
|
|
837
448
|
}
|
|
449
|
+
function updateModalEffect(rootId, opts) {
|
|
450
|
+
const target = getModalEffectTarget(rootId);
|
|
451
|
+
if (!target) return;
|
|
452
|
+
const { progress, insetTop } = opts;
|
|
453
|
+
if (target.type === "sheet") {
|
|
454
|
+
const sheet = target.element;
|
|
455
|
+
const sheetWidth = sheet.offsetWidth;
|
|
456
|
+
const sheetTop = sheet.offsetTop;
|
|
457
|
+
const scaleEnd2 = (sheetWidth - 16) / sheetWidth;
|
|
458
|
+
const scale2 = transform(progress, [0, 1], [1, scaleEnd2]);
|
|
459
|
+
const translateYEnd = clamp(scaleEnd2 * (24 + insetTop) - sheetTop, -10, 0);
|
|
460
|
+
const translateY2 = transform(progress, [0, 1], [0, translateYEnd]);
|
|
461
|
+
sheet.style.scale = `${scale2}`;
|
|
462
|
+
sheet.style.translate = `0 ${translateY2}px`;
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const root = target.element;
|
|
466
|
+
const pageWidth = window.innerWidth;
|
|
467
|
+
const scaleEnd = (pageWidth - 16) / pageWidth;
|
|
468
|
+
const scale = transform(progress, [0, 1], [1, scaleEnd]);
|
|
469
|
+
const translateY = transform(progress, [0, 1], [0, 24 + insetTop]);
|
|
470
|
+
const borderRadius = transform(progress, [0, 1], [0, 10]);
|
|
471
|
+
root.style.transform = `scale(${scale}) translate3d(0, ${translateY}px, 0)`;
|
|
472
|
+
root.style.borderTopRightRadius = `${borderRadius}px`;
|
|
473
|
+
root.style.borderTopLeftRadius = `${borderRadius}px`;
|
|
474
|
+
}
|
|
838
475
|
function cleanupModalEffect(rootId) {
|
|
839
|
-
const
|
|
476
|
+
const target = getModalEffectTarget(rootId);
|
|
477
|
+
if (!target) return;
|
|
478
|
+
if (target.type === "sheet") {
|
|
479
|
+
const sheet = target.element;
|
|
480
|
+
sheet.style.removeProperty("transform-origin");
|
|
481
|
+
sheet.style.removeProperty("scale");
|
|
482
|
+
sheet.style.removeProperty("translate");
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
const root = target.element;
|
|
840
486
|
const body = document.querySelector("body");
|
|
841
|
-
if (!root) return;
|
|
842
487
|
body.style.removeProperty("background-color");
|
|
843
488
|
root.style.removeProperty("overflow");
|
|
844
489
|
root.style.removeProperty("transition-timing-function");
|
|
@@ -849,6 +494,19 @@ function cleanupModalEffect(rootId) {
|
|
|
849
494
|
root.style.removeProperty("border-top-right-radius");
|
|
850
495
|
root.style.removeProperty("border-top-left-radius");
|
|
851
496
|
}
|
|
497
|
+
function getModalEffectTarget(rootId) {
|
|
498
|
+
const root = document.getElementById(rootId);
|
|
499
|
+
if (!root) return null;
|
|
500
|
+
const sheetRoot = root.closest(".react-modal-sheet-root");
|
|
501
|
+
if (sheetRoot) {
|
|
502
|
+
const container = sheetRoot.querySelector(
|
|
503
|
+
".react-modal-sheet-container"
|
|
504
|
+
);
|
|
505
|
+
if (!container) return null;
|
|
506
|
+
return { type: "sheet", element: container };
|
|
507
|
+
}
|
|
508
|
+
return { type: "root", element: root };
|
|
509
|
+
}
|
|
852
510
|
|
|
853
511
|
// src/hooks/use-prevent-scroll.ts
|
|
854
512
|
var KEYBOARD_BUFFER = 24;
|
|
@@ -1150,9 +808,6 @@ function computeSnapPoints({
|
|
|
1150
808
|
// Y value is inverted as `y = 0` means sheet is at the top
|
|
1151
809
|
}));
|
|
1152
810
|
}
|
|
1153
|
-
function clamp(value, min, max) {
|
|
1154
|
-
return Math.min(Math.max(value, min), max);
|
|
1155
|
-
}
|
|
1156
811
|
function sign(value) {
|
|
1157
812
|
if (value > 0) return 1;
|
|
1158
813
|
if (value < 0) return -1;
|
|
@@ -1292,48 +947,152 @@ function classifyDragEnd({
|
|
|
1292
947
|
};
|
|
1293
948
|
}
|
|
1294
949
|
|
|
1295
|
-
// src/
|
|
1296
|
-
var
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
950
|
+
// src/styles.ts
|
|
951
|
+
var styles = {
|
|
952
|
+
root: {
|
|
953
|
+
base: {
|
|
954
|
+
position: "fixed",
|
|
955
|
+
top: 0,
|
|
956
|
+
bottom: 0,
|
|
957
|
+
left: 0,
|
|
958
|
+
right: 0,
|
|
959
|
+
overflow: "hidden",
|
|
960
|
+
pointerEvents: "none"
|
|
961
|
+
},
|
|
962
|
+
decorative: {}
|
|
963
|
+
},
|
|
964
|
+
backdrop: {
|
|
965
|
+
base: {
|
|
966
|
+
zIndex: 1,
|
|
967
|
+
position: "fixed",
|
|
968
|
+
top: 0,
|
|
969
|
+
left: 0,
|
|
970
|
+
width: "100%",
|
|
971
|
+
height: "100%",
|
|
972
|
+
touchAction: "none",
|
|
973
|
+
userSelect: "none"
|
|
974
|
+
},
|
|
975
|
+
decorative: {
|
|
976
|
+
backgroundColor: "rgba(0, 0, 0, 0.2)",
|
|
977
|
+
border: "none",
|
|
978
|
+
WebkitTapHighlightColor: "transparent"
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
container: {
|
|
982
|
+
base: {
|
|
983
|
+
zIndex: 2,
|
|
984
|
+
position: "absolute",
|
|
985
|
+
left: 0,
|
|
986
|
+
bottom: 0,
|
|
987
|
+
width: "100%",
|
|
988
|
+
pointerEvents: "auto",
|
|
989
|
+
display: "flex",
|
|
990
|
+
flexDirection: "column"
|
|
991
|
+
},
|
|
992
|
+
decorative: {
|
|
993
|
+
backgroundColor: "#fff",
|
|
994
|
+
borderTopRightRadius: "8px",
|
|
995
|
+
borderTopLeftRadius: "8px",
|
|
996
|
+
boxShadow: "0px -2px 16px rgba(0, 0, 0, 0.3)"
|
|
997
|
+
}
|
|
998
|
+
},
|
|
999
|
+
headerWrapper: {
|
|
1000
|
+
base: {
|
|
1001
|
+
width: "100%"
|
|
1002
|
+
},
|
|
1003
|
+
decorative: {}
|
|
1004
|
+
},
|
|
1005
|
+
header: {
|
|
1006
|
+
base: {
|
|
1007
|
+
width: "100%",
|
|
1008
|
+
position: "relative"
|
|
1009
|
+
},
|
|
1010
|
+
decorative: {
|
|
1011
|
+
height: "40px",
|
|
1012
|
+
display: "flex",
|
|
1013
|
+
alignItems: "center",
|
|
1014
|
+
justifyContent: "center"
|
|
1015
|
+
}
|
|
1016
|
+
},
|
|
1017
|
+
indicatorWrapper: {
|
|
1018
|
+
base: {
|
|
1019
|
+
display: "flex"
|
|
1020
|
+
},
|
|
1021
|
+
decorative: {}
|
|
1022
|
+
},
|
|
1023
|
+
indicator: {
|
|
1024
|
+
base: {
|
|
1025
|
+
display: "inline-block"
|
|
1026
|
+
},
|
|
1027
|
+
decorative: {
|
|
1028
|
+
width: "18px",
|
|
1029
|
+
height: "4px",
|
|
1030
|
+
borderRadius: "99px",
|
|
1031
|
+
backgroundColor: "#ddd"
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
content: {
|
|
1035
|
+
base: {
|
|
1036
|
+
minHeight: "0px",
|
|
1037
|
+
position: "relative",
|
|
1038
|
+
flexGrow: 1,
|
|
1039
|
+
display: "flex",
|
|
1040
|
+
flexDirection: "column"
|
|
1041
|
+
},
|
|
1042
|
+
decorative: {}
|
|
1043
|
+
},
|
|
1044
|
+
scroller: {
|
|
1045
|
+
base: {
|
|
1046
|
+
height: "100%",
|
|
1047
|
+
overflowY: "auto",
|
|
1048
|
+
overscrollBehaviorY: "none"
|
|
1049
|
+
},
|
|
1050
|
+
decorative: {}
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
|
|
1054
|
+
// src/sheet.tsx
|
|
1055
|
+
var Sheet = forwardRef(
|
|
1056
|
+
({
|
|
1057
|
+
avoidKeyboard = true,
|
|
1058
|
+
children,
|
|
1059
|
+
className = "",
|
|
1060
|
+
detent = "default",
|
|
1061
|
+
disableDismiss = false,
|
|
1062
|
+
disableDrag: disableDragProp = false,
|
|
1063
|
+
disableScrollLocking = false,
|
|
1064
|
+
dragCloseThreshold = DEFAULT_DRAG_CLOSE_THRESHOLD,
|
|
1065
|
+
dragVelocityThreshold = DEFAULT_DRAG_VELOCITY_THRESHOLD,
|
|
1066
|
+
initialSnap,
|
|
1067
|
+
isOpen,
|
|
1068
|
+
modalEffectRootId,
|
|
1069
|
+
modalEffectThreshold,
|
|
1070
|
+
mountPoint,
|
|
1071
|
+
prefersReducedMotion = false,
|
|
1072
|
+
snapPoints: snapPointsProp,
|
|
1073
|
+
style,
|
|
1074
|
+
tweenConfig = DEFAULT_TWEEN_CONFIG,
|
|
1075
|
+
unstyled = false,
|
|
1076
|
+
onOpenStart,
|
|
1077
|
+
onOpenEnd,
|
|
1078
|
+
onClose,
|
|
1079
|
+
onCloseStart,
|
|
1080
|
+
onCloseEnd,
|
|
1081
|
+
onSnap,
|
|
1082
|
+
onDrag: onDragProp,
|
|
1083
|
+
onDragStart: onDragStartProp,
|
|
1084
|
+
onDragEnd: onDragEndProp,
|
|
1085
|
+
...rest
|
|
1327
1086
|
}, ref) => {
|
|
1328
|
-
const [sheetBoundsRef, sheetBounds] = useMeasure();
|
|
1087
|
+
const [sheetBoundsRef, sheetBounds] = useMeasure({ offsetSize: true });
|
|
1329
1088
|
const sheetRef = useRef(null);
|
|
1330
1089
|
const sheetHeight = Math.round(sheetBounds.height);
|
|
1331
1090
|
const [currentSnap, setCurrentSnap] = useState(initialSnap);
|
|
1332
|
-
const snapPoints = snapPointsProp && sheetHeight > 0 ? computeSnapPoints({ sheetHeight, snapPointsProp }) : [];
|
|
1333
1091
|
const { windowHeight } = useDimensions();
|
|
1334
1092
|
const closedY = sheetHeight > 0 ? sheetHeight : windowHeight;
|
|
1335
1093
|
const y = useMotionValue(closedY);
|
|
1336
1094
|
const yInverted = useTransform(y, (val) => Math.max(sheetHeight - val, 0));
|
|
1095
|
+
const yProgress = useTransform(y, (val) => clamp(1 - val / closedY, 0, 1));
|
|
1337
1096
|
const indicatorRotation = useMotionValue(0);
|
|
1338
1097
|
const shouldReduceMotion = useReducedMotion();
|
|
1339
1098
|
const reduceMotion = Boolean(prefersReducedMotion || shouldReduceMotion);
|
|
@@ -1349,6 +1108,9 @@ var Sheet = forwardRef(
|
|
|
1349
1108
|
y,
|
|
1350
1109
|
(val) => val + 2 >= closedY ? "hidden" : "visible"
|
|
1351
1110
|
);
|
|
1111
|
+
const snapPoints = useMemo(() => {
|
|
1112
|
+
return snapPointsProp && sheetHeight > 0 ? computeSnapPoints({ sheetHeight, snapPointsProp }) : [];
|
|
1113
|
+
}, [sheetHeight, snapPointsProp == null ? void 0 : snapPointsProp.join("")]);
|
|
1352
1114
|
const updateSnap = useStableCallback((snapIndex) => {
|
|
1353
1115
|
setCurrentSnap(snapIndex);
|
|
1354
1116
|
onSnap == null ? void 0 : onSnap(snapIndex);
|
|
@@ -1461,12 +1223,6 @@ var Sheet = forwardRef(
|
|
|
1461
1223
|
}
|
|
1462
1224
|
indicatorRotation.set(0);
|
|
1463
1225
|
});
|
|
1464
|
-
useImperativeHandle(ref, () => ({
|
|
1465
|
-
y,
|
|
1466
|
-
yInverted,
|
|
1467
|
-
height: sheetHeight,
|
|
1468
|
-
snapTo
|
|
1469
|
-
}));
|
|
1470
1226
|
useModalEffect({
|
|
1471
1227
|
y,
|
|
1472
1228
|
detent,
|
|
@@ -1486,9 +1242,7 @@ var Sheet = forwardRef(
|
|
|
1486
1242
|
const initialSnapPoint = initialSnap !== void 0 ? getSnapPoint(initialSnap) : null;
|
|
1487
1243
|
const yTo = (initialSnapPoint == null ? void 0 : initialSnapPoint.snapValueY) ?? 0;
|
|
1488
1244
|
await animate(y, yTo, animationOptions);
|
|
1489
|
-
if (initialSnap !== void 0)
|
|
1490
|
-
updateSnap(initialSnap);
|
|
1491
|
-
}
|
|
1245
|
+
if (initialSnap !== void 0) updateSnap(initialSnap);
|
|
1492
1246
|
onOpenEnd == null ? void 0 : onOpenEnd();
|
|
1493
1247
|
},
|
|
1494
1248
|
onClosing: async () => {
|
|
@@ -1506,7 +1260,7 @@ var Sheet = forwardRef(
|
|
|
1506
1260
|
onDragStart,
|
|
1507
1261
|
onDragEnd
|
|
1508
1262
|
};
|
|
1509
|
-
const
|
|
1263
|
+
const internalContext = {
|
|
1510
1264
|
currentSnap,
|
|
1511
1265
|
detent,
|
|
1512
1266
|
disableDrag,
|
|
@@ -1517,9 +1271,20 @@ var Sheet = forwardRef(
|
|
|
1517
1271
|
sheetBoundsRef,
|
|
1518
1272
|
sheetRef,
|
|
1519
1273
|
unstyled,
|
|
1274
|
+
yProgress,
|
|
1520
1275
|
y
|
|
1521
1276
|
};
|
|
1522
|
-
const
|
|
1277
|
+
const exposedContext = {
|
|
1278
|
+
height: sheetHeight,
|
|
1279
|
+
currentSnap,
|
|
1280
|
+
snapPoints,
|
|
1281
|
+
snapTo,
|
|
1282
|
+
y,
|
|
1283
|
+
yInverted,
|
|
1284
|
+
yProgress
|
|
1285
|
+
};
|
|
1286
|
+
useImperativeHandle(ref, () => exposedContext);
|
|
1287
|
+
const sheet = /* @__PURE__ */ React.createElement(InternalSheetContext.Provider, { value: internalContext }, /* @__PURE__ */ React.createElement(
|
|
1523
1288
|
motion.div,
|
|
1524
1289
|
{
|
|
1525
1290
|
...rest,
|
|
@@ -1533,13 +1298,293 @@ var Sheet = forwardRef(
|
|
|
1533
1298
|
...style
|
|
1534
1299
|
}
|
|
1535
1300
|
},
|
|
1536
|
-
state !== "closed" ? children : null
|
|
1301
|
+
/* @__PURE__ */ React.createElement(ExposedSheetContext.Provider, { value: exposedContext }, state !== "closed" ? children : null)
|
|
1537
1302
|
));
|
|
1538
1303
|
if (IS_SSR) return sheet;
|
|
1539
1304
|
return createPortal(sheet, mountPoint ?? document.body);
|
|
1540
1305
|
}
|
|
1541
1306
|
);
|
|
1542
1307
|
Sheet.displayName = "Sheet";
|
|
1308
|
+
var isClickable = (props) => !!props.onClick || !!props.onTap;
|
|
1309
|
+
var SheetBackdrop = forwardRef(
|
|
1310
|
+
({ style, className = "", unstyled, ...rest }, ref) => {
|
|
1311
|
+
const sheetContext = useInternalContext();
|
|
1312
|
+
const clickable = isClickable(rest);
|
|
1313
|
+
const Comp = clickable ? motion.button : motion.div;
|
|
1314
|
+
const pointerEvents = clickable ? "auto" : "none";
|
|
1315
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1316
|
+
const backdropStyle = {
|
|
1317
|
+
opacity: sheetContext.yProgress,
|
|
1318
|
+
...applyStyles(styles.backdrop, isUnstyled),
|
|
1319
|
+
...style,
|
|
1320
|
+
pointerEvents
|
|
1321
|
+
};
|
|
1322
|
+
return /* @__PURE__ */ React.createElement(
|
|
1323
|
+
Comp,
|
|
1324
|
+
{
|
|
1325
|
+
...rest,
|
|
1326
|
+
ref,
|
|
1327
|
+
className: `react-modal-sheet-backdrop ${className}`,
|
|
1328
|
+
style: backdropStyle
|
|
1329
|
+
}
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1332
|
+
);
|
|
1333
|
+
SheetBackdrop.displayName = "SheetBackdrop";
|
|
1334
|
+
var SheetContainer = forwardRef(
|
|
1335
|
+
({ children, style, className = "", unstyled, ...rest }, ref) => {
|
|
1336
|
+
const sheetContext = useInternalContext();
|
|
1337
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1338
|
+
const containerStyle = {
|
|
1339
|
+
...applyStyles(styles.container, isUnstyled),
|
|
1340
|
+
...style,
|
|
1341
|
+
y: sheetContext.y
|
|
1342
|
+
};
|
|
1343
|
+
if (sheetContext.detent === "default") {
|
|
1344
|
+
containerStyle.height = DEFAULT_HEIGHT;
|
|
1345
|
+
}
|
|
1346
|
+
if (sheetContext.detent === "full") {
|
|
1347
|
+
containerStyle.height = "100%";
|
|
1348
|
+
containerStyle.maxHeight = "100%";
|
|
1349
|
+
}
|
|
1350
|
+
if (sheetContext.detent === "content") {
|
|
1351
|
+
containerStyle.height = "auto";
|
|
1352
|
+
containerStyle.maxHeight = DEFAULT_HEIGHT;
|
|
1353
|
+
}
|
|
1354
|
+
return /* @__PURE__ */ React.createElement(
|
|
1355
|
+
motion.div,
|
|
1356
|
+
{
|
|
1357
|
+
...rest,
|
|
1358
|
+
ref: mergeRefs([
|
|
1359
|
+
ref,
|
|
1360
|
+
sheetContext.sheetRef,
|
|
1361
|
+
sheetContext.sheetBoundsRef
|
|
1362
|
+
]),
|
|
1363
|
+
className: `react-modal-sheet-container ${className}`,
|
|
1364
|
+
style: containerStyle
|
|
1365
|
+
},
|
|
1366
|
+
children
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
SheetContainer.displayName = "SheetContainer";
|
|
1371
|
+
var constraints = { bottom: 0, top: 0, left: 0, right: 0 };
|
|
1372
|
+
function useDragConstraints() {
|
|
1373
|
+
const ref = useRef(null);
|
|
1374
|
+
const onMeasure = useCallback(() => constraints, []);
|
|
1375
|
+
return { ref, onMeasure };
|
|
1376
|
+
}
|
|
1377
|
+
function useScrollPosition(options = {}) {
|
|
1378
|
+
const { debounceDelay = 32, isEnabled = true } = options;
|
|
1379
|
+
const scrollTimeoutRef = useRef(null);
|
|
1380
|
+
const [element, setElement] = useState(null);
|
|
1381
|
+
const [scrollPosition, setScrollPosition] = useState(void 0);
|
|
1382
|
+
const scrollRef = useMemo(
|
|
1383
|
+
() => (element2) => {
|
|
1384
|
+
setElement(element2);
|
|
1385
|
+
},
|
|
1386
|
+
[]
|
|
1387
|
+
);
|
|
1388
|
+
const determineScrollPosition = useStableCallback((element2) => {
|
|
1389
|
+
const { scrollTop, scrollHeight, clientHeight } = element2;
|
|
1390
|
+
const isScrollable2 = scrollHeight > clientHeight;
|
|
1391
|
+
if (!isScrollable2) {
|
|
1392
|
+
if (scrollPosition) setScrollPosition(void 0);
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
const isAtTop = scrollTop <= 0;
|
|
1396
|
+
const isAtBottom = Math.ceil(scrollHeight) - Math.ceil(scrollTop) === Math.ceil(clientHeight);
|
|
1397
|
+
let position;
|
|
1398
|
+
if (isAtTop) {
|
|
1399
|
+
position = "top";
|
|
1400
|
+
} else if (isAtBottom) {
|
|
1401
|
+
position = "bottom";
|
|
1402
|
+
} else {
|
|
1403
|
+
position = "middle";
|
|
1404
|
+
}
|
|
1405
|
+
element2.style.touchAction = isAtTop ? "pan-down" : "";
|
|
1406
|
+
if (position === scrollPosition) return;
|
|
1407
|
+
setScrollPosition(position);
|
|
1408
|
+
});
|
|
1409
|
+
const onScroll = useStableCallback((event) => {
|
|
1410
|
+
if (event.currentTarget instanceof HTMLElement) {
|
|
1411
|
+
const el = event.currentTarget;
|
|
1412
|
+
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
1413
|
+
if (debounceDelay === 0) {
|
|
1414
|
+
determineScrollPosition(el);
|
|
1415
|
+
} else {
|
|
1416
|
+
scrollTimeoutRef.current = setTimeout(
|
|
1417
|
+
() => determineScrollPosition(el),
|
|
1418
|
+
debounceDelay
|
|
1419
|
+
);
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
const onTouchStart = useStableCallback((event) => {
|
|
1424
|
+
if (event.currentTarget instanceof HTMLElement) {
|
|
1425
|
+
const element2 = event.currentTarget;
|
|
1426
|
+
requestAnimationFrame(() => {
|
|
1427
|
+
determineScrollPosition(element2);
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
});
|
|
1431
|
+
useEffect(() => {
|
|
1432
|
+
if (!element || !isEnabled) return;
|
|
1433
|
+
determineScrollPosition(element);
|
|
1434
|
+
element.addEventListener("scroll", onScroll);
|
|
1435
|
+
element.addEventListener("touchstart", onTouchStart);
|
|
1436
|
+
return () => {
|
|
1437
|
+
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
1438
|
+
element.removeEventListener("scroll", onScroll);
|
|
1439
|
+
element.removeEventListener("touchstart", onTouchStart);
|
|
1440
|
+
};
|
|
1441
|
+
}, [element, isEnabled]);
|
|
1442
|
+
return {
|
|
1443
|
+
scrollRef,
|
|
1444
|
+
scrollPosition
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
// src/sheet-content.tsx
|
|
1449
|
+
var SheetContent = forwardRef(
|
|
1450
|
+
({
|
|
1451
|
+
disableScroll: disableScrollProp,
|
|
1452
|
+
disableDrag: disableDragProp,
|
|
1453
|
+
children,
|
|
1454
|
+
style: styleProp,
|
|
1455
|
+
className = "",
|
|
1456
|
+
scrollClassName = "",
|
|
1457
|
+
scrollStyle: scrollStyleProp,
|
|
1458
|
+
scrollRef: scrollRefProp = null,
|
|
1459
|
+
unstyled,
|
|
1460
|
+
...rest
|
|
1461
|
+
}, ref) => {
|
|
1462
|
+
const sheetContext = useInternalContext();
|
|
1463
|
+
const dragConstraints = useDragConstraints();
|
|
1464
|
+
const scroll = useScrollPosition({
|
|
1465
|
+
isEnabled: typeof disableScrollProp === "function" ? true : !disableScrollProp
|
|
1466
|
+
});
|
|
1467
|
+
const disableScroll = typeof disableScrollProp === "function" ? disableScrollProp({
|
|
1468
|
+
scrollPosition: scroll.scrollPosition,
|
|
1469
|
+
currentSnap: sheetContext.currentSnap
|
|
1470
|
+
}) : Boolean(disableScrollProp);
|
|
1471
|
+
const disableDragDueToScroll = !disableScroll && scroll.scrollPosition && scroll.scrollPosition !== "top";
|
|
1472
|
+
const disableDragDueToProp = typeof disableDragProp === "function" ? disableDragProp({
|
|
1473
|
+
scrollPosition: scroll.scrollPosition,
|
|
1474
|
+
currentSnap: sheetContext.currentSnap
|
|
1475
|
+
}) : Boolean(disableDragProp);
|
|
1476
|
+
const disableDrag = disableDragDueToProp || disableDragDueToScroll || sheetContext.disableDrag;
|
|
1477
|
+
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
1478
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1479
|
+
const contentStyle = {
|
|
1480
|
+
...applyStyles(styles.content, isUnstyled),
|
|
1481
|
+
...styleProp
|
|
1482
|
+
};
|
|
1483
|
+
const scrollStyle = applyStyles(styles.scroller, isUnstyled);
|
|
1484
|
+
if (sheetContext.avoidKeyboard) {
|
|
1485
|
+
scrollStyle.paddingBottom = isHTTPS() ? "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))" : "var(--keyboard-inset-height, 0px)";
|
|
1486
|
+
}
|
|
1487
|
+
if (disableScroll) {
|
|
1488
|
+
scrollStyle.overflowY = "clip";
|
|
1489
|
+
}
|
|
1490
|
+
if (dragProps !== void 0) {
|
|
1491
|
+
scrollStyle.touchAction = "pan-down";
|
|
1492
|
+
}
|
|
1493
|
+
return /* @__PURE__ */ React.createElement(
|
|
1494
|
+
motion.div,
|
|
1495
|
+
{
|
|
1496
|
+
...rest,
|
|
1497
|
+
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
1498
|
+
className: `react-modal-sheet-content ${className}`,
|
|
1499
|
+
style: contentStyle,
|
|
1500
|
+
...dragProps,
|
|
1501
|
+
dragConstraints: dragConstraints.ref,
|
|
1502
|
+
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
1503
|
+
},
|
|
1504
|
+
/* @__PURE__ */ React.createElement(
|
|
1505
|
+
motion.div,
|
|
1506
|
+
{
|
|
1507
|
+
ref: mergeRefs([scroll.scrollRef, scrollRefProp]),
|
|
1508
|
+
style: { ...scrollStyle, ...scrollStyleProp },
|
|
1509
|
+
className: `react-modal-sheet-content-scroller ${scrollClassName}`
|
|
1510
|
+
},
|
|
1511
|
+
children
|
|
1512
|
+
)
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
);
|
|
1516
|
+
SheetContent.displayName = "SheetContent";
|
|
1517
|
+
function SheetDragIndicator({
|
|
1518
|
+
style,
|
|
1519
|
+
className = "",
|
|
1520
|
+
unstyled,
|
|
1521
|
+
...rest
|
|
1522
|
+
}) {
|
|
1523
|
+
const sheetContext = useInternalContext();
|
|
1524
|
+
const indicator1Transform = useTransform(
|
|
1525
|
+
sheetContext.indicatorRotation,
|
|
1526
|
+
(r) => `translateX(2px) rotate(${r}deg)`
|
|
1527
|
+
);
|
|
1528
|
+
const indicator2Transform = useTransform(
|
|
1529
|
+
sheetContext.indicatorRotation,
|
|
1530
|
+
(r) => `translateX(-2px) rotate(${ -1 * r}deg)`
|
|
1531
|
+
);
|
|
1532
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1533
|
+
const indicatorWrapperStyle = {
|
|
1534
|
+
...applyStyles(styles.indicatorWrapper, isUnstyled),
|
|
1535
|
+
...style
|
|
1536
|
+
};
|
|
1537
|
+
const indicatorStyle = applyStyles(styles.indicator, isUnstyled);
|
|
1538
|
+
return /* @__PURE__ */ React.createElement(
|
|
1539
|
+
"div",
|
|
1540
|
+
{
|
|
1541
|
+
className: `react-modal-sheet-drag-indicator-container ${className}`,
|
|
1542
|
+
style: indicatorWrapperStyle,
|
|
1543
|
+
...rest
|
|
1544
|
+
},
|
|
1545
|
+
/* @__PURE__ */ React.createElement(
|
|
1546
|
+
motion.span,
|
|
1547
|
+
{
|
|
1548
|
+
className: "react-modal-sheet-drag-indicator",
|
|
1549
|
+
style: { ...indicatorStyle, transform: indicator1Transform }
|
|
1550
|
+
}
|
|
1551
|
+
),
|
|
1552
|
+
/* @__PURE__ */ React.createElement(
|
|
1553
|
+
motion.span,
|
|
1554
|
+
{
|
|
1555
|
+
className: "react-modal-sheet-drag-indicator",
|
|
1556
|
+
style: { ...indicatorStyle, transform: indicator2Transform }
|
|
1557
|
+
}
|
|
1558
|
+
)
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
var SheetHeader = forwardRef(
|
|
1562
|
+
({ children, style, disableDrag, unstyled, className = "", ...rest }, ref) => {
|
|
1563
|
+
const sheetContext = useInternalContext();
|
|
1564
|
+
const dragConstraints = useDragConstraints();
|
|
1565
|
+
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
1566
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1567
|
+
const headerWrapperStyle = {
|
|
1568
|
+
...applyStyles(styles.headerWrapper, isUnstyled),
|
|
1569
|
+
...style
|
|
1570
|
+
};
|
|
1571
|
+
const headerStyle = applyStyles(styles.header, isUnstyled);
|
|
1572
|
+
return /* @__PURE__ */ React.createElement(
|
|
1573
|
+
motion.div,
|
|
1574
|
+
{
|
|
1575
|
+
...rest,
|
|
1576
|
+
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
1577
|
+
style: headerWrapperStyle,
|
|
1578
|
+
className: `react-modal-sheet-header-container ${className}`,
|
|
1579
|
+
...dragProps,
|
|
1580
|
+
dragConstraints: dragConstraints.ref,
|
|
1581
|
+
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
1582
|
+
},
|
|
1583
|
+
children || /* @__PURE__ */ React.createElement("div", { className: "react-modal-sheet-header", style: headerStyle }, /* @__PURE__ */ React.createElement(SheetDragIndicator, null))
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
);
|
|
1587
|
+
SheetHeader.displayName = "SheetHeader";
|
|
1543
1588
|
|
|
1544
1589
|
// src/index.tsx
|
|
1545
1590
|
var Sheet2 = Object.assign(Sheet, {
|
|
@@ -1547,7 +1592,8 @@ var Sheet2 = Object.assign(Sheet, {
|
|
|
1547
1592
|
Header: SheetHeader,
|
|
1548
1593
|
DragIndicator: SheetDragIndicator,
|
|
1549
1594
|
Content: SheetContent,
|
|
1550
|
-
Backdrop: SheetBackdrop
|
|
1595
|
+
Backdrop: SheetBackdrop,
|
|
1596
|
+
useContext: useExposedContext
|
|
1551
1597
|
});
|
|
1552
1598
|
|
|
1553
1599
|
export { Sheet2 as Sheet, useScrollPosition, useVirtualKeyboard };
|