react-modal-sheet 5.5.0 → 5.6.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 +263 -88
- package/dist/index.d.mts +16 -7
- package/dist/index.d.ts +16 -7
- package/dist/index.js +560 -554
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +537 -531
- 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 +87 -82
- 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 +37 -28
- 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,82 @@ function useModalEffect({
|
|
|
768
381
|
console.warn('Using "full" detent with modal effect is not supported.');
|
|
769
382
|
rootId = void 0;
|
|
770
383
|
}
|
|
771
|
-
|
|
772
|
-
return () => {
|
|
773
|
-
if (rootId) cleanupModalEffect(rootId);
|
|
774
|
-
};
|
|
775
|
-
}, []);
|
|
776
|
-
useIsomorphicLayoutEffect(() => {
|
|
384
|
+
const handleYChange = useStableCallback((yValue) => {
|
|
777
385
|
if (!rootId) return;
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
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
|
-
}
|
|
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;
|
|
794
394
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
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;
|
|
802
402
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
root.style.borderTopLeftRadius = `${borderRadius}px`;
|
|
403
|
+
}
|
|
404
|
+
progress = Math.max(0, Math.min(1, progress));
|
|
405
|
+
const pageWidth = window.innerWidth;
|
|
406
|
+
updateModalEffect(rootId, {
|
|
407
|
+
scale: transform(progress, [0, 1], [1, (pageWidth - 16) / pageWidth]),
|
|
408
|
+
translateY: transform(progress, [0, 1], [0, 24 + insetTop]),
|
|
409
|
+
borderRadius: transform(progress, [0, 1], [0, 10])
|
|
811
410
|
});
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
411
|
+
});
|
|
412
|
+
const handleYComplete = useStableCallback(() => {
|
|
413
|
+
if (!rootId) return;
|
|
414
|
+
if (y.get() + 5 >= sheetHeight) {
|
|
415
|
+
cleanupModalEffect(rootId);
|
|
816
416
|
}
|
|
817
|
-
|
|
818
|
-
|
|
417
|
+
});
|
|
418
|
+
useEffect(() => {
|
|
419
|
+
if (!rootId) return;
|
|
420
|
+
const removeStartListener = y.on("animationStart", () => {
|
|
421
|
+
if (rootId) setupModalEffect(rootId);
|
|
422
|
+
});
|
|
423
|
+
const removeChangeListener = y.on("change", (yValue) => {
|
|
424
|
+
handleYChange(yValue);
|
|
425
|
+
});
|
|
426
|
+
const removeCompleteListener = y.on("animationComplete", handleYComplete);
|
|
427
|
+
const removeCancelListener = y.on("animationCancel", handleYComplete);
|
|
819
428
|
return () => {
|
|
429
|
+
if (rootId) cleanupModalEffect(rootId);
|
|
820
430
|
removeStartListener();
|
|
821
431
|
removeChangeListener();
|
|
822
432
|
removeCompleteListener();
|
|
823
433
|
removeCancelListener();
|
|
824
434
|
};
|
|
825
|
-
}, [
|
|
435
|
+
}, [rootId]);
|
|
826
436
|
}
|
|
827
437
|
function setupModalEffect(rootId) {
|
|
828
438
|
const root = document.querySelector(`#${rootId}`);
|
|
829
|
-
const body = document.querySelector("body");
|
|
830
439
|
if (!root) return;
|
|
831
|
-
body
|
|
440
|
+
const body = document.querySelector("body");
|
|
441
|
+
body.style.backgroundColor = "#000000";
|
|
832
442
|
root.style.overflow = "hidden";
|
|
833
443
|
root.style.transitionTimingFunction = "cubic-bezier(0.32, 0.72, 0, 1)";
|
|
834
444
|
root.style.transitionProperty = "transform, border-radius";
|
|
835
445
|
root.style.transitionDuration = "0.5s";
|
|
836
446
|
root.style.transformOrigin = "center top";
|
|
837
447
|
}
|
|
448
|
+
function updateModalEffect(rootId, opts) {
|
|
449
|
+
const root = document.querySelector(`#${rootId}`);
|
|
450
|
+
if (!root) return;
|
|
451
|
+
const { scale, translateY, borderRadius } = opts;
|
|
452
|
+
root.style.transform = `scale(${scale}) translate3d(0, ${translateY}px, 0)`;
|
|
453
|
+
root.style.borderTopRightRadius = `${borderRadius}px`;
|
|
454
|
+
root.style.borderTopLeftRadius = `${borderRadius}px`;
|
|
455
|
+
}
|
|
838
456
|
function cleanupModalEffect(rootId) {
|
|
839
457
|
const root = document.querySelector(`#${rootId}`);
|
|
840
|
-
const body = document.querySelector("body");
|
|
841
458
|
if (!root) return;
|
|
459
|
+
const body = document.querySelector("body");
|
|
842
460
|
body.style.removeProperty("background-color");
|
|
843
461
|
root.style.removeProperty("overflow");
|
|
844
462
|
root.style.removeProperty("transition-timing-function");
|
|
@@ -1150,9 +768,6 @@ function computeSnapPoints({
|
|
|
1150
768
|
// Y value is inverted as `y = 0` means sheet is at the top
|
|
1151
769
|
}));
|
|
1152
770
|
}
|
|
1153
|
-
function clamp(value, min, max) {
|
|
1154
|
-
return Math.min(Math.max(value, min), max);
|
|
1155
|
-
}
|
|
1156
771
|
function sign(value) {
|
|
1157
772
|
if (value > 0) return 1;
|
|
1158
773
|
if (value < 0) return -1;
|
|
@@ -1292,48 +907,152 @@ function classifyDragEnd({
|
|
|
1292
907
|
};
|
|
1293
908
|
}
|
|
1294
909
|
|
|
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
|
-
|
|
910
|
+
// src/styles.ts
|
|
911
|
+
var styles = {
|
|
912
|
+
root: {
|
|
913
|
+
base: {
|
|
914
|
+
position: "fixed",
|
|
915
|
+
top: 0,
|
|
916
|
+
bottom: 0,
|
|
917
|
+
left: 0,
|
|
918
|
+
right: 0,
|
|
919
|
+
overflow: "hidden",
|
|
920
|
+
pointerEvents: "none"
|
|
921
|
+
},
|
|
922
|
+
decorative: {}
|
|
923
|
+
},
|
|
924
|
+
backdrop: {
|
|
925
|
+
base: {
|
|
926
|
+
zIndex: 1,
|
|
927
|
+
position: "fixed",
|
|
928
|
+
top: 0,
|
|
929
|
+
left: 0,
|
|
930
|
+
width: "100%",
|
|
931
|
+
height: "100%",
|
|
932
|
+
touchAction: "none",
|
|
933
|
+
userSelect: "none"
|
|
934
|
+
},
|
|
935
|
+
decorative: {
|
|
936
|
+
backgroundColor: "rgba(0, 0, 0, 0.2)",
|
|
937
|
+
border: "none",
|
|
938
|
+
WebkitTapHighlightColor: "transparent"
|
|
939
|
+
}
|
|
940
|
+
},
|
|
941
|
+
container: {
|
|
942
|
+
base: {
|
|
943
|
+
zIndex: 2,
|
|
944
|
+
position: "absolute",
|
|
945
|
+
left: 0,
|
|
946
|
+
bottom: 0,
|
|
947
|
+
width: "100%",
|
|
948
|
+
pointerEvents: "auto",
|
|
949
|
+
display: "flex",
|
|
950
|
+
flexDirection: "column"
|
|
951
|
+
},
|
|
952
|
+
decorative: {
|
|
953
|
+
backgroundColor: "#fff",
|
|
954
|
+
borderTopRightRadius: "8px",
|
|
955
|
+
borderTopLeftRadius: "8px",
|
|
956
|
+
boxShadow: "0px -2px 16px rgba(0, 0, 0, 0.3)"
|
|
957
|
+
}
|
|
958
|
+
},
|
|
959
|
+
headerWrapper: {
|
|
960
|
+
base: {
|
|
961
|
+
width: "100%"
|
|
962
|
+
},
|
|
963
|
+
decorative: {}
|
|
964
|
+
},
|
|
965
|
+
header: {
|
|
966
|
+
base: {
|
|
967
|
+
width: "100%",
|
|
968
|
+
position: "relative"
|
|
969
|
+
},
|
|
970
|
+
decorative: {
|
|
971
|
+
height: "40px",
|
|
972
|
+
display: "flex",
|
|
973
|
+
alignItems: "center",
|
|
974
|
+
justifyContent: "center"
|
|
975
|
+
}
|
|
976
|
+
},
|
|
977
|
+
indicatorWrapper: {
|
|
978
|
+
base: {
|
|
979
|
+
display: "flex"
|
|
980
|
+
},
|
|
981
|
+
decorative: {}
|
|
982
|
+
},
|
|
983
|
+
indicator: {
|
|
984
|
+
base: {
|
|
985
|
+
display: "inline-block"
|
|
986
|
+
},
|
|
987
|
+
decorative: {
|
|
988
|
+
width: "18px",
|
|
989
|
+
height: "4px",
|
|
990
|
+
borderRadius: "99px",
|
|
991
|
+
backgroundColor: "#ddd"
|
|
992
|
+
}
|
|
993
|
+
},
|
|
994
|
+
content: {
|
|
995
|
+
base: {
|
|
996
|
+
minHeight: "0px",
|
|
997
|
+
position: "relative",
|
|
998
|
+
flexGrow: 1,
|
|
999
|
+
display: "flex",
|
|
1000
|
+
flexDirection: "column"
|
|
1001
|
+
},
|
|
1002
|
+
decorative: {}
|
|
1003
|
+
},
|
|
1004
|
+
scroller: {
|
|
1005
|
+
base: {
|
|
1006
|
+
height: "100%",
|
|
1007
|
+
overflowY: "auto",
|
|
1008
|
+
overscrollBehaviorY: "none"
|
|
1009
|
+
},
|
|
1010
|
+
decorative: {}
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
1013
|
+
|
|
1014
|
+
// src/sheet.tsx
|
|
1015
|
+
var Sheet = forwardRef(
|
|
1016
|
+
({
|
|
1017
|
+
avoidKeyboard = true,
|
|
1018
|
+
children,
|
|
1019
|
+
className = "",
|
|
1020
|
+
detent = "default",
|
|
1021
|
+
disableDismiss = false,
|
|
1022
|
+
disableDrag: disableDragProp = false,
|
|
1023
|
+
disableScrollLocking = false,
|
|
1024
|
+
dragCloseThreshold = DEFAULT_DRAG_CLOSE_THRESHOLD,
|
|
1025
|
+
dragVelocityThreshold = DEFAULT_DRAG_VELOCITY_THRESHOLD,
|
|
1026
|
+
initialSnap,
|
|
1027
|
+
isOpen,
|
|
1028
|
+
modalEffectRootId,
|
|
1029
|
+
modalEffectThreshold,
|
|
1030
|
+
mountPoint,
|
|
1031
|
+
prefersReducedMotion = false,
|
|
1032
|
+
snapPoints: snapPointsProp,
|
|
1033
|
+
style,
|
|
1034
|
+
tweenConfig = DEFAULT_TWEEN_CONFIG,
|
|
1035
|
+
unstyled = false,
|
|
1036
|
+
onOpenStart,
|
|
1037
|
+
onOpenEnd,
|
|
1038
|
+
onClose,
|
|
1039
|
+
onCloseStart,
|
|
1040
|
+
onCloseEnd,
|
|
1041
|
+
onSnap,
|
|
1042
|
+
onDrag: onDragProp,
|
|
1043
|
+
onDragStart: onDragStartProp,
|
|
1044
|
+
onDragEnd: onDragEndProp,
|
|
1326
1045
|
...rest
|
|
1327
1046
|
}, ref) => {
|
|
1328
1047
|
const [sheetBoundsRef, sheetBounds] = useMeasure();
|
|
1329
1048
|
const sheetRef = useRef(null);
|
|
1330
1049
|
const sheetHeight = Math.round(sheetBounds.height);
|
|
1331
1050
|
const [currentSnap, setCurrentSnap] = useState(initialSnap);
|
|
1332
|
-
const snapPoints = snapPointsProp && sheetHeight > 0 ? computeSnapPoints({ sheetHeight, snapPointsProp }) : [];
|
|
1333
1051
|
const { windowHeight } = useDimensions();
|
|
1334
1052
|
const closedY = sheetHeight > 0 ? sheetHeight : windowHeight;
|
|
1335
1053
|
const y = useMotionValue(closedY);
|
|
1336
1054
|
const yInverted = useTransform(y, (val) => Math.max(sheetHeight - val, 0));
|
|
1055
|
+
const yProgress = useTransform(y, (val) => clamp(1 - val / closedY, 0, 1));
|
|
1337
1056
|
const indicatorRotation = useMotionValue(0);
|
|
1338
1057
|
const shouldReduceMotion = useReducedMotion();
|
|
1339
1058
|
const reduceMotion = Boolean(prefersReducedMotion || shouldReduceMotion);
|
|
@@ -1349,6 +1068,9 @@ var Sheet = forwardRef(
|
|
|
1349
1068
|
y,
|
|
1350
1069
|
(val) => val + 2 >= closedY ? "hidden" : "visible"
|
|
1351
1070
|
);
|
|
1071
|
+
const snapPoints = useMemo(() => {
|
|
1072
|
+
return snapPointsProp && sheetHeight > 0 ? computeSnapPoints({ sheetHeight, snapPointsProp }) : [];
|
|
1073
|
+
}, [sheetHeight, snapPointsProp == null ? void 0 : snapPointsProp.join("")]);
|
|
1352
1074
|
const updateSnap = useStableCallback((snapIndex) => {
|
|
1353
1075
|
setCurrentSnap(snapIndex);
|
|
1354
1076
|
onSnap == null ? void 0 : onSnap(snapIndex);
|
|
@@ -1461,12 +1183,6 @@ var Sheet = forwardRef(
|
|
|
1461
1183
|
}
|
|
1462
1184
|
indicatorRotation.set(0);
|
|
1463
1185
|
});
|
|
1464
|
-
useImperativeHandle(ref, () => ({
|
|
1465
|
-
y,
|
|
1466
|
-
yInverted,
|
|
1467
|
-
height: sheetHeight,
|
|
1468
|
-
snapTo
|
|
1469
|
-
}));
|
|
1470
1186
|
useModalEffect({
|
|
1471
1187
|
y,
|
|
1472
1188
|
detent,
|
|
@@ -1486,9 +1202,7 @@ var Sheet = forwardRef(
|
|
|
1486
1202
|
const initialSnapPoint = initialSnap !== void 0 ? getSnapPoint(initialSnap) : null;
|
|
1487
1203
|
const yTo = (initialSnapPoint == null ? void 0 : initialSnapPoint.snapValueY) ?? 0;
|
|
1488
1204
|
await animate(y, yTo, animationOptions);
|
|
1489
|
-
if (initialSnap !== void 0)
|
|
1490
|
-
updateSnap(initialSnap);
|
|
1491
|
-
}
|
|
1205
|
+
if (initialSnap !== void 0) updateSnap(initialSnap);
|
|
1492
1206
|
onOpenEnd == null ? void 0 : onOpenEnd();
|
|
1493
1207
|
},
|
|
1494
1208
|
onClosing: async () => {
|
|
@@ -1506,7 +1220,7 @@ var Sheet = forwardRef(
|
|
|
1506
1220
|
onDragStart,
|
|
1507
1221
|
onDragEnd
|
|
1508
1222
|
};
|
|
1509
|
-
const
|
|
1223
|
+
const internalContext = {
|
|
1510
1224
|
currentSnap,
|
|
1511
1225
|
detent,
|
|
1512
1226
|
disableDrag,
|
|
@@ -1517,9 +1231,20 @@ var Sheet = forwardRef(
|
|
|
1517
1231
|
sheetBoundsRef,
|
|
1518
1232
|
sheetRef,
|
|
1519
1233
|
unstyled,
|
|
1234
|
+
yProgress,
|
|
1520
1235
|
y
|
|
1521
1236
|
};
|
|
1522
|
-
const
|
|
1237
|
+
const exposedContext = {
|
|
1238
|
+
height: sheetHeight,
|
|
1239
|
+
currentSnap,
|
|
1240
|
+
snapPoints,
|
|
1241
|
+
snapTo,
|
|
1242
|
+
y,
|
|
1243
|
+
yInverted,
|
|
1244
|
+
yProgress
|
|
1245
|
+
};
|
|
1246
|
+
useImperativeHandle(ref, () => exposedContext);
|
|
1247
|
+
const sheet = /* @__PURE__ */ React.createElement(InternalSheetContext.Provider, { value: internalContext }, /* @__PURE__ */ React.createElement(
|
|
1523
1248
|
motion.div,
|
|
1524
1249
|
{
|
|
1525
1250
|
...rest,
|
|
@@ -1533,13 +1258,293 @@ var Sheet = forwardRef(
|
|
|
1533
1258
|
...style
|
|
1534
1259
|
}
|
|
1535
1260
|
},
|
|
1536
|
-
state !== "closed" ? children : null
|
|
1261
|
+
/* @__PURE__ */ React.createElement(ExposedSheetContext.Provider, { value: exposedContext }, state !== "closed" ? children : null)
|
|
1537
1262
|
));
|
|
1538
1263
|
if (IS_SSR) return sheet;
|
|
1539
1264
|
return createPortal(sheet, mountPoint ?? document.body);
|
|
1540
1265
|
}
|
|
1541
1266
|
);
|
|
1542
1267
|
Sheet.displayName = "Sheet";
|
|
1268
|
+
var isClickable = (props) => !!props.onClick || !!props.onTap;
|
|
1269
|
+
var SheetBackdrop = forwardRef(
|
|
1270
|
+
({ style, className = "", unstyled, ...rest }, ref) => {
|
|
1271
|
+
const sheetContext = useInternalContext();
|
|
1272
|
+
const clickable = isClickable(rest);
|
|
1273
|
+
const Comp = clickable ? motion.button : motion.div;
|
|
1274
|
+
const pointerEvents = clickable ? "auto" : "none";
|
|
1275
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1276
|
+
const backdropStyle = {
|
|
1277
|
+
opacity: sheetContext.yProgress,
|
|
1278
|
+
...applyStyles(styles.backdrop, isUnstyled),
|
|
1279
|
+
...style,
|
|
1280
|
+
pointerEvents
|
|
1281
|
+
};
|
|
1282
|
+
return /* @__PURE__ */ React.createElement(
|
|
1283
|
+
Comp,
|
|
1284
|
+
{
|
|
1285
|
+
...rest,
|
|
1286
|
+
ref,
|
|
1287
|
+
className: `react-modal-sheet-backdrop ${className}`,
|
|
1288
|
+
style: backdropStyle
|
|
1289
|
+
}
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
);
|
|
1293
|
+
SheetBackdrop.displayName = "SheetBackdrop";
|
|
1294
|
+
var SheetContainer = forwardRef(
|
|
1295
|
+
({ children, style, className = "", unstyled, ...rest }, ref) => {
|
|
1296
|
+
const sheetContext = useInternalContext();
|
|
1297
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1298
|
+
const containerStyle = {
|
|
1299
|
+
...applyStyles(styles.container, isUnstyled),
|
|
1300
|
+
...style,
|
|
1301
|
+
y: sheetContext.y
|
|
1302
|
+
};
|
|
1303
|
+
if (sheetContext.detent === "default") {
|
|
1304
|
+
containerStyle.height = DEFAULT_HEIGHT;
|
|
1305
|
+
}
|
|
1306
|
+
if (sheetContext.detent === "full") {
|
|
1307
|
+
containerStyle.height = "100%";
|
|
1308
|
+
containerStyle.maxHeight = "100%";
|
|
1309
|
+
}
|
|
1310
|
+
if (sheetContext.detent === "content") {
|
|
1311
|
+
containerStyle.height = "auto";
|
|
1312
|
+
containerStyle.maxHeight = DEFAULT_HEIGHT;
|
|
1313
|
+
}
|
|
1314
|
+
return /* @__PURE__ */ React.createElement(
|
|
1315
|
+
motion.div,
|
|
1316
|
+
{
|
|
1317
|
+
...rest,
|
|
1318
|
+
ref: mergeRefs([
|
|
1319
|
+
ref,
|
|
1320
|
+
sheetContext.sheetRef,
|
|
1321
|
+
sheetContext.sheetBoundsRef
|
|
1322
|
+
]),
|
|
1323
|
+
className: `react-modal-sheet-container ${className}`,
|
|
1324
|
+
style: containerStyle
|
|
1325
|
+
},
|
|
1326
|
+
children
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
);
|
|
1330
|
+
SheetContainer.displayName = "SheetContainer";
|
|
1331
|
+
var constraints = { bottom: 0, top: 0, left: 0, right: 0 };
|
|
1332
|
+
function useDragConstraints() {
|
|
1333
|
+
const ref = useRef(null);
|
|
1334
|
+
const onMeasure = useCallback(() => constraints, []);
|
|
1335
|
+
return { ref, onMeasure };
|
|
1336
|
+
}
|
|
1337
|
+
function useScrollPosition(options = {}) {
|
|
1338
|
+
const { debounceDelay = 32, isEnabled = true } = options;
|
|
1339
|
+
const scrollTimeoutRef = useRef(null);
|
|
1340
|
+
const [element, setElement] = useState(null);
|
|
1341
|
+
const [scrollPosition, setScrollPosition] = useState(void 0);
|
|
1342
|
+
const scrollRef = useMemo(
|
|
1343
|
+
() => (element2) => {
|
|
1344
|
+
setElement(element2);
|
|
1345
|
+
},
|
|
1346
|
+
[]
|
|
1347
|
+
);
|
|
1348
|
+
const determineScrollPosition = useStableCallback((element2) => {
|
|
1349
|
+
const { scrollTop, scrollHeight, clientHeight } = element2;
|
|
1350
|
+
const isScrollable2 = scrollHeight > clientHeight;
|
|
1351
|
+
if (!isScrollable2) {
|
|
1352
|
+
if (scrollPosition) setScrollPosition(void 0);
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
const isAtTop = scrollTop <= 0;
|
|
1356
|
+
const isAtBottom = Math.ceil(scrollHeight) - Math.ceil(scrollTop) === Math.ceil(clientHeight);
|
|
1357
|
+
let position;
|
|
1358
|
+
if (isAtTop) {
|
|
1359
|
+
position = "top";
|
|
1360
|
+
} else if (isAtBottom) {
|
|
1361
|
+
position = "bottom";
|
|
1362
|
+
} else {
|
|
1363
|
+
position = "middle";
|
|
1364
|
+
}
|
|
1365
|
+
element2.style.touchAction = isAtTop ? "pan-down" : "";
|
|
1366
|
+
if (position === scrollPosition) return;
|
|
1367
|
+
setScrollPosition(position);
|
|
1368
|
+
});
|
|
1369
|
+
const onScroll = useStableCallback((event) => {
|
|
1370
|
+
if (event.currentTarget instanceof HTMLElement) {
|
|
1371
|
+
const el = event.currentTarget;
|
|
1372
|
+
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
1373
|
+
if (debounceDelay === 0) {
|
|
1374
|
+
determineScrollPosition(el);
|
|
1375
|
+
} else {
|
|
1376
|
+
scrollTimeoutRef.current = setTimeout(
|
|
1377
|
+
() => determineScrollPosition(el),
|
|
1378
|
+
debounceDelay
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1383
|
+
const onTouchStart = useStableCallback((event) => {
|
|
1384
|
+
if (event.currentTarget instanceof HTMLElement) {
|
|
1385
|
+
const element2 = event.currentTarget;
|
|
1386
|
+
requestAnimationFrame(() => {
|
|
1387
|
+
determineScrollPosition(element2);
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
useEffect(() => {
|
|
1392
|
+
if (!element || !isEnabled) return;
|
|
1393
|
+
determineScrollPosition(element);
|
|
1394
|
+
element.addEventListener("scroll", onScroll);
|
|
1395
|
+
element.addEventListener("touchstart", onTouchStart);
|
|
1396
|
+
return () => {
|
|
1397
|
+
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
1398
|
+
element.removeEventListener("scroll", onScroll);
|
|
1399
|
+
element.removeEventListener("touchstart", onTouchStart);
|
|
1400
|
+
};
|
|
1401
|
+
}, [element, isEnabled]);
|
|
1402
|
+
return {
|
|
1403
|
+
scrollRef,
|
|
1404
|
+
scrollPosition
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
// src/sheet-content.tsx
|
|
1409
|
+
var SheetContent = forwardRef(
|
|
1410
|
+
({
|
|
1411
|
+
disableScroll: disableScrollProp,
|
|
1412
|
+
disableDrag: disableDragProp,
|
|
1413
|
+
children,
|
|
1414
|
+
style: styleProp,
|
|
1415
|
+
className = "",
|
|
1416
|
+
scrollClassName = "",
|
|
1417
|
+
scrollStyle: scrollStyleProp,
|
|
1418
|
+
scrollRef: scrollRefProp = null,
|
|
1419
|
+
unstyled,
|
|
1420
|
+
...rest
|
|
1421
|
+
}, ref) => {
|
|
1422
|
+
const sheetContext = useInternalContext();
|
|
1423
|
+
const dragConstraints = useDragConstraints();
|
|
1424
|
+
const scroll = useScrollPosition({
|
|
1425
|
+
isEnabled: typeof disableScrollProp === "function" ? true : !disableScrollProp
|
|
1426
|
+
});
|
|
1427
|
+
const disableScroll = typeof disableScrollProp === "function" ? disableScrollProp({
|
|
1428
|
+
scrollPosition: scroll.scrollPosition,
|
|
1429
|
+
currentSnap: sheetContext.currentSnap
|
|
1430
|
+
}) : Boolean(disableScrollProp);
|
|
1431
|
+
const disableDragDueToScroll = !disableScroll && scroll.scrollPosition && scroll.scrollPosition !== "top";
|
|
1432
|
+
const disableDragDueToProp = typeof disableDragProp === "function" ? disableDragProp({
|
|
1433
|
+
scrollPosition: scroll.scrollPosition,
|
|
1434
|
+
currentSnap: sheetContext.currentSnap
|
|
1435
|
+
}) : Boolean(disableDragProp);
|
|
1436
|
+
const disableDrag = disableDragDueToProp || disableDragDueToScroll || sheetContext.disableDrag;
|
|
1437
|
+
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
1438
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1439
|
+
const contentStyle = {
|
|
1440
|
+
...applyStyles(styles.content, isUnstyled),
|
|
1441
|
+
...styleProp
|
|
1442
|
+
};
|
|
1443
|
+
const scrollStyle = applyStyles(styles.scroller, isUnstyled);
|
|
1444
|
+
if (sheetContext.avoidKeyboard) {
|
|
1445
|
+
scrollStyle.paddingBottom = isHTTPS() ? "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))" : "var(--keyboard-inset-height, 0px)";
|
|
1446
|
+
}
|
|
1447
|
+
if (disableScroll) {
|
|
1448
|
+
scrollStyle.overflowY = "clip";
|
|
1449
|
+
}
|
|
1450
|
+
if (dragProps !== void 0) {
|
|
1451
|
+
scrollStyle.touchAction = "pan-down";
|
|
1452
|
+
}
|
|
1453
|
+
return /* @__PURE__ */ React.createElement(
|
|
1454
|
+
motion.div,
|
|
1455
|
+
{
|
|
1456
|
+
...rest,
|
|
1457
|
+
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
1458
|
+
className: `react-modal-sheet-content ${className}`,
|
|
1459
|
+
style: contentStyle,
|
|
1460
|
+
...dragProps,
|
|
1461
|
+
dragConstraints: dragConstraints.ref,
|
|
1462
|
+
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
1463
|
+
},
|
|
1464
|
+
/* @__PURE__ */ React.createElement(
|
|
1465
|
+
motion.div,
|
|
1466
|
+
{
|
|
1467
|
+
ref: mergeRefs([scroll.scrollRef, scrollRefProp]),
|
|
1468
|
+
style: { ...scrollStyle, ...scrollStyleProp },
|
|
1469
|
+
className: `react-modal-sheet-content-scroller ${scrollClassName}`
|
|
1470
|
+
},
|
|
1471
|
+
children
|
|
1472
|
+
)
|
|
1473
|
+
);
|
|
1474
|
+
}
|
|
1475
|
+
);
|
|
1476
|
+
SheetContent.displayName = "SheetContent";
|
|
1477
|
+
function SheetDragIndicator({
|
|
1478
|
+
style,
|
|
1479
|
+
className = "",
|
|
1480
|
+
unstyled,
|
|
1481
|
+
...rest
|
|
1482
|
+
}) {
|
|
1483
|
+
const sheetContext = useInternalContext();
|
|
1484
|
+
const indicator1Transform = useTransform(
|
|
1485
|
+
sheetContext.indicatorRotation,
|
|
1486
|
+
(r) => `translateX(2px) rotate(${r}deg)`
|
|
1487
|
+
);
|
|
1488
|
+
const indicator2Transform = useTransform(
|
|
1489
|
+
sheetContext.indicatorRotation,
|
|
1490
|
+
(r) => `translateX(-2px) rotate(${ -1 * r}deg)`
|
|
1491
|
+
);
|
|
1492
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1493
|
+
const indicatorWrapperStyle = {
|
|
1494
|
+
...applyStyles(styles.indicatorWrapper, isUnstyled),
|
|
1495
|
+
...style
|
|
1496
|
+
};
|
|
1497
|
+
const indicatorStyle = applyStyles(styles.indicator, isUnstyled);
|
|
1498
|
+
return /* @__PURE__ */ React.createElement(
|
|
1499
|
+
"div",
|
|
1500
|
+
{
|
|
1501
|
+
className: `react-modal-sheet-drag-indicator-container ${className}`,
|
|
1502
|
+
style: indicatorWrapperStyle,
|
|
1503
|
+
...rest
|
|
1504
|
+
},
|
|
1505
|
+
/* @__PURE__ */ React.createElement(
|
|
1506
|
+
motion.span,
|
|
1507
|
+
{
|
|
1508
|
+
className: "react-modal-sheet-drag-indicator",
|
|
1509
|
+
style: { ...indicatorStyle, transform: indicator1Transform }
|
|
1510
|
+
}
|
|
1511
|
+
),
|
|
1512
|
+
/* @__PURE__ */ React.createElement(
|
|
1513
|
+
motion.span,
|
|
1514
|
+
{
|
|
1515
|
+
className: "react-modal-sheet-drag-indicator",
|
|
1516
|
+
style: { ...indicatorStyle, transform: indicator2Transform }
|
|
1517
|
+
}
|
|
1518
|
+
)
|
|
1519
|
+
);
|
|
1520
|
+
}
|
|
1521
|
+
var SheetHeader = forwardRef(
|
|
1522
|
+
({ children, style, disableDrag, unstyled, className = "", ...rest }, ref) => {
|
|
1523
|
+
const sheetContext = useInternalContext();
|
|
1524
|
+
const dragConstraints = useDragConstraints();
|
|
1525
|
+
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
1526
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1527
|
+
const headerWrapperStyle = {
|
|
1528
|
+
...applyStyles(styles.headerWrapper, isUnstyled),
|
|
1529
|
+
...style
|
|
1530
|
+
};
|
|
1531
|
+
const headerStyle = applyStyles(styles.header, isUnstyled);
|
|
1532
|
+
return /* @__PURE__ */ React.createElement(
|
|
1533
|
+
motion.div,
|
|
1534
|
+
{
|
|
1535
|
+
...rest,
|
|
1536
|
+
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
1537
|
+
style: headerWrapperStyle,
|
|
1538
|
+
className: `react-modal-sheet-header-container ${className}`,
|
|
1539
|
+
...dragProps,
|
|
1540
|
+
dragConstraints: dragConstraints.ref,
|
|
1541
|
+
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
1542
|
+
},
|
|
1543
|
+
children || /* @__PURE__ */ React.createElement("div", { className: "react-modal-sheet-header", style: headerStyle }, /* @__PURE__ */ React.createElement(SheetDragIndicator, null))
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
);
|
|
1547
|
+
SheetHeader.displayName = "SheetHeader";
|
|
1543
1548
|
|
|
1544
1549
|
// src/index.tsx
|
|
1545
1550
|
var Sheet2 = Object.assign(Sheet, {
|
|
@@ -1547,7 +1552,8 @@ var Sheet2 = Object.assign(Sheet, {
|
|
|
1547
1552
|
Header: SheetHeader,
|
|
1548
1553
|
DragIndicator: SheetDragIndicator,
|
|
1549
1554
|
Content: SheetContent,
|
|
1550
|
-
Backdrop: SheetBackdrop
|
|
1555
|
+
Backdrop: SheetBackdrop,
|
|
1556
|
+
useContext: useExposedContext
|
|
1551
1557
|
});
|
|
1552
1558
|
|
|
1553
1559
|
export { Sheet2 as Sheet, useScrollPosition, useVirtualKeyboard };
|