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.js
CHANGED
|
@@ -1,129 +1,29 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var React = require('react');
|
|
3
4
|
var react = require('motion/react');
|
|
4
|
-
var React4 = require('react');
|
|
5
5
|
var reactDom = require('react-dom');
|
|
6
6
|
var useMeasure = require('react-use-measure');
|
|
7
7
|
var motion = require('motion');
|
|
8
8
|
|
|
9
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
|
|
11
|
-
var
|
|
11
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
12
12
|
var useMeasure__default = /*#__PURE__*/_interopDefault(useMeasure);
|
|
13
13
|
|
|
14
|
-
// src/
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
// src/context.tsx
|
|
15
|
+
var InternalSheetContext = React.createContext(void 0);
|
|
16
|
+
var ExposedSheetContext = React.createContext(void 0);
|
|
17
|
+
function useInternalContext() {
|
|
18
|
+
const context = React.useContext(InternalSheetContext);
|
|
19
|
+
if (!context) throw new Error("Sheet context error");
|
|
20
|
+
return context;
|
|
21
|
+
}
|
|
22
|
+
function useExposedContext() {
|
|
23
|
+
const context = React.useContext(ExposedSheetContext);
|
|
20
24
|
if (!context) throw new Error("Sheet context error");
|
|
21
25
|
return context;
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
// src/styles.ts
|
|
25
|
-
var styles = {
|
|
26
|
-
root: {
|
|
27
|
-
base: {
|
|
28
|
-
position: "fixed",
|
|
29
|
-
top: 0,
|
|
30
|
-
bottom: 0,
|
|
31
|
-
left: 0,
|
|
32
|
-
right: 0,
|
|
33
|
-
overflow: "hidden",
|
|
34
|
-
pointerEvents: "none"
|
|
35
|
-
},
|
|
36
|
-
decorative: {}
|
|
37
|
-
},
|
|
38
|
-
backdrop: {
|
|
39
|
-
base: {
|
|
40
|
-
zIndex: 1,
|
|
41
|
-
position: "fixed",
|
|
42
|
-
top: 0,
|
|
43
|
-
left: 0,
|
|
44
|
-
width: "100%",
|
|
45
|
-
height: "100%",
|
|
46
|
-
touchAction: "none",
|
|
47
|
-
userSelect: "none"
|
|
48
|
-
},
|
|
49
|
-
decorative: {
|
|
50
|
-
backgroundColor: "rgba(0, 0, 0, 0.2)",
|
|
51
|
-
border: "none",
|
|
52
|
-
WebkitTapHighlightColor: "transparent"
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
container: {
|
|
56
|
-
base: {
|
|
57
|
-
zIndex: 2,
|
|
58
|
-
position: "absolute",
|
|
59
|
-
left: 0,
|
|
60
|
-
bottom: 0,
|
|
61
|
-
width: "100%",
|
|
62
|
-
pointerEvents: "auto",
|
|
63
|
-
display: "flex",
|
|
64
|
-
flexDirection: "column"
|
|
65
|
-
},
|
|
66
|
-
decorative: {
|
|
67
|
-
backgroundColor: "#fff",
|
|
68
|
-
borderTopRightRadius: "8px",
|
|
69
|
-
borderTopLeftRadius: "8px",
|
|
70
|
-
boxShadow: "0px -2px 16px rgba(0, 0, 0, 0.3)"
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
headerWrapper: {
|
|
74
|
-
base: {
|
|
75
|
-
width: "100%"
|
|
76
|
-
},
|
|
77
|
-
decorative: {}
|
|
78
|
-
},
|
|
79
|
-
header: {
|
|
80
|
-
base: {
|
|
81
|
-
width: "100%",
|
|
82
|
-
position: "relative"
|
|
83
|
-
},
|
|
84
|
-
decorative: {
|
|
85
|
-
height: "40px",
|
|
86
|
-
display: "flex",
|
|
87
|
-
alignItems: "center",
|
|
88
|
-
justifyContent: "center"
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
indicatorWrapper: {
|
|
92
|
-
base: {
|
|
93
|
-
display: "flex"
|
|
94
|
-
},
|
|
95
|
-
decorative: {}
|
|
96
|
-
},
|
|
97
|
-
indicator: {
|
|
98
|
-
base: {
|
|
99
|
-
display: "inline-block"
|
|
100
|
-
},
|
|
101
|
-
decorative: {
|
|
102
|
-
width: "18px",
|
|
103
|
-
height: "4px",
|
|
104
|
-
borderRadius: "99px",
|
|
105
|
-
backgroundColor: "#ddd"
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
content: {
|
|
109
|
-
base: {
|
|
110
|
-
minHeight: "0px",
|
|
111
|
-
position: "relative",
|
|
112
|
-
flexGrow: 1,
|
|
113
|
-
display: "flex",
|
|
114
|
-
flexDirection: "column"
|
|
115
|
-
},
|
|
116
|
-
decorative: {}
|
|
117
|
-
},
|
|
118
|
-
scroller: {
|
|
119
|
-
base: {
|
|
120
|
-
height: "100%",
|
|
121
|
-
overflowY: "auto",
|
|
122
|
-
overscrollBehaviorY: "none"
|
|
123
|
-
},
|
|
124
|
-
decorative: {}
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
27
|
|
|
128
28
|
// src/constants.ts
|
|
129
29
|
var DEFAULT_HEIGHT = "calc(100% - env(safe-area-inset-top) - 34px)";
|
|
@@ -138,6 +38,29 @@ var REDUCED_MOTION_TWEEN_CONFIG = {
|
|
|
138
38
|
};
|
|
139
39
|
var DEFAULT_DRAG_CLOSE_THRESHOLD = 0.6;
|
|
140
40
|
var DEFAULT_DRAG_VELOCITY_THRESHOLD = 1200;
|
|
41
|
+
var useIsomorphicLayoutEffect = IS_SSR ? React.useEffect : React.useLayoutEffect;
|
|
42
|
+
|
|
43
|
+
// src/hooks/use-dimensions.ts
|
|
44
|
+
function useDimensions() {
|
|
45
|
+
const [dimensions, setDimensions] = React.useState(() => ({
|
|
46
|
+
windowHeight: !IS_SSR ? window.innerHeight : 0,
|
|
47
|
+
windowWidth: !IS_SSR ? window.innerWidth : 0
|
|
48
|
+
}));
|
|
49
|
+
useIsomorphicLayoutEffect(() => {
|
|
50
|
+
function handler() {
|
|
51
|
+
setDimensions({
|
|
52
|
+
windowHeight: window.innerHeight,
|
|
53
|
+
windowWidth: window.innerWidth
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
handler();
|
|
57
|
+
window.addEventListener("resize", handler);
|
|
58
|
+
return () => {
|
|
59
|
+
window.removeEventListener("resize", handler);
|
|
60
|
+
};
|
|
61
|
+
}, []);
|
|
62
|
+
return dimensions;
|
|
63
|
+
}
|
|
141
64
|
|
|
142
65
|
// src/utils.ts
|
|
143
66
|
function applyStyles(styles2, unstyled) {
|
|
@@ -220,356 +143,46 @@ function willOpenKeyboard(target) {
|
|
|
220
143
|
function isHTTPS() {
|
|
221
144
|
return typeof window !== "undefined" && window.isSecureContext;
|
|
222
145
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
var isClickable = (props) => !!props.onClick || !!props.onTap;
|
|
226
|
-
var SheetBackdrop = React4.forwardRef(
|
|
227
|
-
({ style, className = "", unstyled, ...rest }, ref) => {
|
|
228
|
-
const sheetContext = useSheetContext();
|
|
229
|
-
const clickable = isClickable(rest);
|
|
230
|
-
const Comp = clickable ? react.motion.button : react.motion.div;
|
|
231
|
-
const pointerEvents = clickable ? "auto" : "none";
|
|
232
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
233
|
-
const backdropStyle = {
|
|
234
|
-
...applyStyles(styles.backdrop, isUnstyled),
|
|
235
|
-
...style,
|
|
236
|
-
pointerEvents
|
|
237
|
-
};
|
|
238
|
-
const animationProps = sheetContext.prefersReducedMotion ? {} : {
|
|
239
|
-
initial: { opacity: 0 },
|
|
240
|
-
animate: { opacity: 1 },
|
|
241
|
-
exit: { opacity: 0 },
|
|
242
|
-
transition: { duration: 1 }
|
|
243
|
-
};
|
|
244
|
-
return /* @__PURE__ */ React4__default.default.createElement(
|
|
245
|
-
Comp,
|
|
246
|
-
{
|
|
247
|
-
...animationProps,
|
|
248
|
-
...rest,
|
|
249
|
-
ref,
|
|
250
|
-
className: `react-modal-sheet-backdrop ${className}`,
|
|
251
|
-
style: backdropStyle
|
|
252
|
-
}
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
);
|
|
256
|
-
SheetBackdrop.displayName = "SheetBackdrop";
|
|
257
|
-
var SheetContainer = React4.forwardRef(
|
|
258
|
-
({ children, style, className = "", unstyled, ...rest }, ref) => {
|
|
259
|
-
const sheetContext = useSheetContext();
|
|
260
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
261
|
-
const containerStyle = {
|
|
262
|
-
...applyStyles(styles.container, isUnstyled),
|
|
263
|
-
...style,
|
|
264
|
-
y: sheetContext.y
|
|
265
|
-
};
|
|
266
|
-
if (sheetContext.detent === "default") {
|
|
267
|
-
containerStyle.height = DEFAULT_HEIGHT;
|
|
268
|
-
}
|
|
269
|
-
if (sheetContext.detent === "full") {
|
|
270
|
-
containerStyle.height = "100%";
|
|
271
|
-
containerStyle.maxHeight = "100%";
|
|
272
|
-
}
|
|
273
|
-
if (sheetContext.detent === "content") {
|
|
274
|
-
containerStyle.height = "auto";
|
|
275
|
-
containerStyle.maxHeight = DEFAULT_HEIGHT;
|
|
276
|
-
}
|
|
277
|
-
return /* @__PURE__ */ React4__default.default.createElement(
|
|
278
|
-
react.motion.div,
|
|
279
|
-
{
|
|
280
|
-
...rest,
|
|
281
|
-
ref: mergeRefs([
|
|
282
|
-
ref,
|
|
283
|
-
sheetContext.sheetRef,
|
|
284
|
-
sheetContext.sheetBoundsRef
|
|
285
|
-
]),
|
|
286
|
-
className: `react-modal-sheet-container ${className}`,
|
|
287
|
-
style: containerStyle
|
|
288
|
-
},
|
|
289
|
-
children
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
);
|
|
293
|
-
SheetContainer.displayName = "SheetContainer";
|
|
294
|
-
var constraints = { bottom: 0, top: 0, left: 0, right: 0 };
|
|
295
|
-
function useDragConstraints() {
|
|
296
|
-
const ref = React4.useRef(null);
|
|
297
|
-
const onMeasure = React4.useCallback(() => constraints, []);
|
|
298
|
-
return { ref, onMeasure };
|
|
146
|
+
function clamp(value, min, max) {
|
|
147
|
+
return Math.min(Math.max(value, min), max);
|
|
299
148
|
}
|
|
300
|
-
var useIsomorphicLayoutEffect = IS_SSR ? React4.useEffect : React4.useLayoutEffect;
|
|
301
|
-
|
|
302
|
-
// src/hooks/use-stable-callback.ts
|
|
303
149
|
function useStableCallback(handler) {
|
|
304
|
-
const handlerRef =
|
|
150
|
+
const handlerRef = React.useRef(void 0);
|
|
305
151
|
useIsomorphicLayoutEffect(() => {
|
|
306
152
|
handlerRef.current = handler;
|
|
307
153
|
});
|
|
308
|
-
return
|
|
154
|
+
return React.useCallback((...args) => {
|
|
309
155
|
const fn = handlerRef.current;
|
|
310
156
|
return fn == null ? void 0 : fn(...args);
|
|
311
157
|
}, []);
|
|
312
158
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
function
|
|
316
|
-
const {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
);
|
|
326
|
-
const determineScrollPosition = useStableCallback((element2) => {
|
|
327
|
-
const { scrollTop, scrollHeight, clientHeight } = element2;
|
|
328
|
-
const isScrollable2 = scrollHeight > clientHeight;
|
|
329
|
-
if (!isScrollable2) {
|
|
330
|
-
if (scrollPosition) setScrollPosition(void 0);
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
const isAtTop = scrollTop <= 0;
|
|
334
|
-
const isAtBottom = Math.ceil(scrollHeight) - Math.ceil(scrollTop) === Math.ceil(clientHeight);
|
|
335
|
-
let position;
|
|
336
|
-
if (isAtTop) {
|
|
337
|
-
position = "top";
|
|
338
|
-
} else if (isAtBottom) {
|
|
339
|
-
position = "bottom";
|
|
340
|
-
} else {
|
|
341
|
-
position = "middle";
|
|
342
|
-
}
|
|
343
|
-
element2.style.touchAction = isAtTop ? "pan-down" : "";
|
|
344
|
-
if (position === scrollPosition) return;
|
|
345
|
-
setScrollPosition(position);
|
|
159
|
+
var virtualKeyboardOverlayUsers = 0;
|
|
160
|
+
var initialVirtualKeyboardOverlaysContent = null;
|
|
161
|
+
function useVirtualKeyboard(options = {}) {
|
|
162
|
+
const {
|
|
163
|
+
containerRef,
|
|
164
|
+
isEnabled = true,
|
|
165
|
+
debounceDelay = 100,
|
|
166
|
+
visualViewportThreshold = 100
|
|
167
|
+
} = options;
|
|
168
|
+
const [state, setState] = React.useState({
|
|
169
|
+
isVisible: false,
|
|
170
|
+
height: 0
|
|
346
171
|
});
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
172
|
+
const focusedElementRef = React.useRef(null);
|
|
173
|
+
const debounceTimer = React.useRef(null);
|
|
174
|
+
React.useEffect(() => {
|
|
175
|
+
const vv = window.visualViewport;
|
|
176
|
+
const vk = getVirtualKeyboardApi();
|
|
177
|
+
function setKeyboardInsetHeightEnv(height) {
|
|
178
|
+
const element = (containerRef == null ? void 0 : containerRef.current) || document.documentElement;
|
|
179
|
+
if (vk) {
|
|
180
|
+
element.style.setProperty(
|
|
181
|
+
"--keyboard-inset-height",
|
|
182
|
+
`env(keyboard-inset-height, ${height}px)`
|
|
357
183
|
);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
});
|
|
361
|
-
const onTouchStart = useStableCallback((event) => {
|
|
362
|
-
if (event.currentTarget instanceof HTMLElement) {
|
|
363
|
-
const element2 = event.currentTarget;
|
|
364
|
-
requestAnimationFrame(() => {
|
|
365
|
-
determineScrollPosition(element2);
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
React4.useEffect(() => {
|
|
370
|
-
if (!element || !isEnabled) return;
|
|
371
|
-
determineScrollPosition(element);
|
|
372
|
-
element.addEventListener("scroll", onScroll);
|
|
373
|
-
element.addEventListener("touchstart", onTouchStart);
|
|
374
|
-
return () => {
|
|
375
|
-
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
376
|
-
element.removeEventListener("scroll", onScroll);
|
|
377
|
-
element.removeEventListener("touchstart", onTouchStart);
|
|
378
|
-
};
|
|
379
|
-
}, [element, isEnabled]);
|
|
380
|
-
return {
|
|
381
|
-
scrollRef,
|
|
382
|
-
scrollPosition
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// src/SheetContent.tsx
|
|
387
|
-
var SheetContent = React4.forwardRef(
|
|
388
|
-
({
|
|
389
|
-
disableScroll: disableScrollProp,
|
|
390
|
-
disableDrag: disableDragProp,
|
|
391
|
-
children,
|
|
392
|
-
style: styleProp,
|
|
393
|
-
className = "",
|
|
394
|
-
scrollClassName = "",
|
|
395
|
-
scrollStyle: scrollStyleProp,
|
|
396
|
-
scrollRef: scrollRefProp = null,
|
|
397
|
-
unstyled,
|
|
398
|
-
...rest
|
|
399
|
-
}, ref) => {
|
|
400
|
-
const sheetContext = useSheetContext();
|
|
401
|
-
const dragConstraints = useDragConstraints();
|
|
402
|
-
const scroll = useScrollPosition({
|
|
403
|
-
isEnabled: typeof disableScrollProp === "function" ? true : !disableScrollProp
|
|
404
|
-
});
|
|
405
|
-
const disableScroll = typeof disableScrollProp === "function" ? disableScrollProp({
|
|
406
|
-
scrollPosition: scroll.scrollPosition,
|
|
407
|
-
currentSnap: sheetContext.currentSnap
|
|
408
|
-
}) : Boolean(disableScrollProp);
|
|
409
|
-
const disableDragDueToScroll = !disableScroll && scroll.scrollPosition && scroll.scrollPosition !== "top";
|
|
410
|
-
const disableDragDueToProp = typeof disableDragProp === "function" ? disableDragProp({
|
|
411
|
-
scrollPosition: scroll.scrollPosition,
|
|
412
|
-
currentSnap: sheetContext.currentSnap
|
|
413
|
-
}) : Boolean(disableDragProp);
|
|
414
|
-
const disableDrag = disableDragDueToProp || disableDragDueToScroll || sheetContext.disableDrag;
|
|
415
|
-
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
416
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
417
|
-
const contentStyle = {
|
|
418
|
-
...applyStyles(styles.content, isUnstyled),
|
|
419
|
-
...styleProp
|
|
420
|
-
};
|
|
421
|
-
const scrollStyle = applyStyles(styles.scroller, isUnstyled);
|
|
422
|
-
if (sheetContext.avoidKeyboard) {
|
|
423
|
-
scrollStyle.paddingBottom = isHTTPS() ? "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))" : "var(--keyboard-inset-height, 0px)";
|
|
424
|
-
}
|
|
425
|
-
if (disableScroll) {
|
|
426
|
-
scrollStyle.overflowY = "hidden";
|
|
427
|
-
}
|
|
428
|
-
if (dragProps !== void 0) {
|
|
429
|
-
scrollStyle.touchAction = "pan-down";
|
|
430
|
-
}
|
|
431
|
-
return /* @__PURE__ */ React4__default.default.createElement(
|
|
432
|
-
react.motion.div,
|
|
433
|
-
{
|
|
434
|
-
...rest,
|
|
435
|
-
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
436
|
-
className: `react-modal-sheet-content ${className}`,
|
|
437
|
-
style: contentStyle,
|
|
438
|
-
...dragProps,
|
|
439
|
-
dragConstraints: dragConstraints.ref,
|
|
440
|
-
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
441
|
-
},
|
|
442
|
-
/* @__PURE__ */ React4__default.default.createElement(
|
|
443
|
-
react.motion.div,
|
|
444
|
-
{
|
|
445
|
-
ref: mergeRefs([scroll.scrollRef, scrollRefProp]),
|
|
446
|
-
style: { ...scrollStyle, ...scrollStyleProp },
|
|
447
|
-
className: `react-modal-sheet-content-scroller ${scrollClassName}`
|
|
448
|
-
},
|
|
449
|
-
children
|
|
450
|
-
)
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
);
|
|
454
|
-
SheetContent.displayName = "SheetContent";
|
|
455
|
-
function SheetDragIndicator({
|
|
456
|
-
style,
|
|
457
|
-
className = "",
|
|
458
|
-
unstyled,
|
|
459
|
-
...rest
|
|
460
|
-
}) {
|
|
461
|
-
const sheetContext = useSheetContext();
|
|
462
|
-
const indicator1Transform = react.useTransform(
|
|
463
|
-
sheetContext.indicatorRotation,
|
|
464
|
-
(r) => `translateX(2px) rotate(${r}deg)`
|
|
465
|
-
);
|
|
466
|
-
const indicator2Transform = react.useTransform(
|
|
467
|
-
sheetContext.indicatorRotation,
|
|
468
|
-
(r) => `translateX(-2px) rotate(${ -1 * r}deg)`
|
|
469
|
-
);
|
|
470
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
471
|
-
const indicatorWrapperStyle = {
|
|
472
|
-
...applyStyles(styles.indicatorWrapper, isUnstyled),
|
|
473
|
-
...style
|
|
474
|
-
};
|
|
475
|
-
const indicatorStyle = applyStyles(styles.indicator, isUnstyled);
|
|
476
|
-
return /* @__PURE__ */ React4__default.default.createElement(
|
|
477
|
-
"div",
|
|
478
|
-
{
|
|
479
|
-
className: `react-modal-sheet-drag-indicator-container ${className}`,
|
|
480
|
-
style: indicatorWrapperStyle,
|
|
481
|
-
...rest
|
|
482
|
-
},
|
|
483
|
-
/* @__PURE__ */ React4__default.default.createElement(
|
|
484
|
-
react.motion.span,
|
|
485
|
-
{
|
|
486
|
-
className: "react-modal-sheet-drag-indicator",
|
|
487
|
-
style: { ...indicatorStyle, transform: indicator1Transform }
|
|
488
|
-
}
|
|
489
|
-
),
|
|
490
|
-
/* @__PURE__ */ React4__default.default.createElement(
|
|
491
|
-
react.motion.span,
|
|
492
|
-
{
|
|
493
|
-
className: "react-modal-sheet-drag-indicator",
|
|
494
|
-
style: { ...indicatorStyle, transform: indicator2Transform }
|
|
495
|
-
}
|
|
496
|
-
)
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
var SheetHeader = React4.forwardRef(
|
|
500
|
-
({ children, style, disableDrag, unstyled, className = "", ...rest }, ref) => {
|
|
501
|
-
const sheetContext = useSheetContext();
|
|
502
|
-
const dragConstraints = useDragConstraints();
|
|
503
|
-
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
504
|
-
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
505
|
-
const headerWrapperStyle = {
|
|
506
|
-
...applyStyles(styles.headerWrapper, isUnstyled),
|
|
507
|
-
...style
|
|
508
|
-
};
|
|
509
|
-
const headerStyle = applyStyles(styles.header, isUnstyled);
|
|
510
|
-
return /* @__PURE__ */ React4__default.default.createElement(
|
|
511
|
-
react.motion.div,
|
|
512
|
-
{
|
|
513
|
-
...rest,
|
|
514
|
-
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
515
|
-
style: headerWrapperStyle,
|
|
516
|
-
className: `react-modal-sheet-header-container ${className}`,
|
|
517
|
-
...dragProps,
|
|
518
|
-
dragConstraints: dragConstraints.ref,
|
|
519
|
-
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
520
|
-
},
|
|
521
|
-
children || /* @__PURE__ */ React4__default.default.createElement("div", { className: "react-modal-sheet-header", style: headerStyle }, /* @__PURE__ */ React4__default.default.createElement(SheetDragIndicator, null))
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
);
|
|
525
|
-
SheetHeader.displayName = "SheetHeader";
|
|
526
|
-
function useDimensions() {
|
|
527
|
-
const [dimensions, setDimensions] = React4.useState(() => ({
|
|
528
|
-
windowHeight: !IS_SSR ? window.innerHeight : 0,
|
|
529
|
-
windowWidth: !IS_SSR ? window.innerWidth : 0
|
|
530
|
-
}));
|
|
531
|
-
useIsomorphicLayoutEffect(() => {
|
|
532
|
-
function handler() {
|
|
533
|
-
setDimensions({
|
|
534
|
-
windowHeight: window.innerHeight,
|
|
535
|
-
windowWidth: window.innerWidth
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
handler();
|
|
539
|
-
window.addEventListener("resize", handler);
|
|
540
|
-
return () => {
|
|
541
|
-
window.removeEventListener("resize", handler);
|
|
542
|
-
};
|
|
543
|
-
}, []);
|
|
544
|
-
return dimensions;
|
|
545
|
-
}
|
|
546
|
-
var virtualKeyboardOverlayUsers = 0;
|
|
547
|
-
var initialVirtualKeyboardOverlaysContent = null;
|
|
548
|
-
function useVirtualKeyboard(options = {}) {
|
|
549
|
-
const {
|
|
550
|
-
containerRef,
|
|
551
|
-
isEnabled = true,
|
|
552
|
-
debounceDelay = 100,
|
|
553
|
-
visualViewportThreshold = 100
|
|
554
|
-
} = options;
|
|
555
|
-
const [state, setState] = React4.useState({
|
|
556
|
-
isVisible: false,
|
|
557
|
-
height: 0
|
|
558
|
-
});
|
|
559
|
-
const focusedElementRef = React4.useRef(null);
|
|
560
|
-
const debounceTimer = React4.useRef(null);
|
|
561
|
-
React4.useEffect(() => {
|
|
562
|
-
const vv = window.visualViewport;
|
|
563
|
-
const vk = getVirtualKeyboardApi();
|
|
564
|
-
function setKeyboardInsetHeightEnv(height) {
|
|
565
|
-
const element = (containerRef == null ? void 0 : containerRef.current) || document.documentElement;
|
|
566
|
-
if (vk) {
|
|
567
|
-
element.style.setProperty(
|
|
568
|
-
"--keyboard-inset-height",
|
|
569
|
-
`env(keyboard-inset-height, ${height}px)`
|
|
570
|
-
);
|
|
571
|
-
} else {
|
|
572
|
-
element.style.setProperty("--keyboard-inset-height", `${height}px`);
|
|
184
|
+
} else {
|
|
185
|
+
element.style.setProperty("--keyboard-inset-height", `${height}px`);
|
|
573
186
|
}
|
|
574
187
|
}
|
|
575
188
|
function setKeyboardState(nextState) {
|
|
@@ -691,7 +304,7 @@ function useKeyboardAvoidance({
|
|
|
691
304
|
onWillOpenKeyboard,
|
|
692
305
|
onDidOpenKeyboard
|
|
693
306
|
}) {
|
|
694
|
-
const [focusedElement, setFocusedElement] =
|
|
307
|
+
const [focusedElement, setFocusedElement] = React.useState(
|
|
695
308
|
null
|
|
696
309
|
);
|
|
697
310
|
const keyboard = useVirtualKeyboard({
|
|
@@ -712,7 +325,7 @@ function useKeyboardAvoidance({
|
|
|
712
325
|
setFocusedElement(null);
|
|
713
326
|
}
|
|
714
327
|
});
|
|
715
|
-
|
|
328
|
+
React.useEffect(() => {
|
|
716
329
|
if (!isEnabled) return;
|
|
717
330
|
document.addEventListener("focusin", handleFocusIn);
|
|
718
331
|
document.addEventListener("focusout", handleFocusOut);
|
|
@@ -721,7 +334,7 @@ function useKeyboardAvoidance({
|
|
|
721
334
|
document.removeEventListener("focusout", handleFocusOut);
|
|
722
335
|
};
|
|
723
336
|
}, [isEnabled]);
|
|
724
|
-
|
|
337
|
+
React.useEffect(() => {
|
|
725
338
|
const containerElement = containerRef.current;
|
|
726
339
|
if (!isEnabled || !focusedElement || !containerElement || !keyboard.isKeyboardOpen) {
|
|
727
340
|
return;
|
|
@@ -733,7 +346,7 @@ function useKeyboardAvoidance({
|
|
|
733
346
|
return keyboard;
|
|
734
347
|
}
|
|
735
348
|
function useSafeAreaInsets() {
|
|
736
|
-
const [insets] =
|
|
349
|
+
const [insets] = React.useState(() => {
|
|
737
350
|
const fallback = { top: 0, left: 0, right: 0, bottom: 0 };
|
|
738
351
|
if (IS_SSR) return fallback;
|
|
739
352
|
const root = document.querySelector(":root");
|
|
@@ -775,77 +388,82 @@ function useModalEffect({
|
|
|
775
388
|
console.warn('Using "full" detent with modal effect is not supported.');
|
|
776
389
|
rootId = void 0;
|
|
777
390
|
}
|
|
778
|
-
|
|
779
|
-
return () => {
|
|
780
|
-
if (rootId) cleanupModalEffect(rootId);
|
|
781
|
-
};
|
|
782
|
-
}, []);
|
|
783
|
-
useIsomorphicLayoutEffect(() => {
|
|
391
|
+
const handleYChange = useStableCallback((yValue) => {
|
|
784
392
|
if (!rootId) return;
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
const snapThresholdPoint = snapPoints.length > 1 ? snapPoints[snapPoints.length - 2] : void 0;
|
|
794
|
-
if (snapThresholdPoint !== void 0) {
|
|
795
|
-
const snapThresholdValue = snapThresholdPoint.snapValueY;
|
|
796
|
-
if (yValue <= snapThresholdValue) {
|
|
797
|
-
progress = (snapThresholdValue - yValue) / snapThresholdValue;
|
|
798
|
-
} else {
|
|
799
|
-
progress = 0;
|
|
800
|
-
}
|
|
393
|
+
let progress = Math.max(0, 1 - yValue / sheetHeight);
|
|
394
|
+
const snapThresholdPoint = snapPoints.length > 1 ? snapPoints[snapPoints.length - 2] : void 0;
|
|
395
|
+
if (snapThresholdPoint !== void 0) {
|
|
396
|
+
const snapThresholdValue = snapThresholdPoint.snapValueY;
|
|
397
|
+
if (yValue <= snapThresholdValue) {
|
|
398
|
+
progress = (snapThresholdValue - yValue) / snapThresholdValue;
|
|
399
|
+
} else {
|
|
400
|
+
progress = 0;
|
|
801
401
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
402
|
+
}
|
|
403
|
+
if (startThreshold !== void 0) {
|
|
404
|
+
const startThresholdValue = sheetHeight - Math.min(Math.floor(startThreshold * sheetHeight), sheetHeight);
|
|
405
|
+
if (yValue <= startThresholdValue) {
|
|
406
|
+
progress = (startThresholdValue - yValue) / startThresholdValue;
|
|
407
|
+
} else {
|
|
408
|
+
progress = 0;
|
|
809
409
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
root.style.borderTopLeftRadius = `${borderRadius}px`;
|
|
410
|
+
}
|
|
411
|
+
progress = Math.max(0, Math.min(1, progress));
|
|
412
|
+
const pageWidth = window.innerWidth;
|
|
413
|
+
updateModalEffect(rootId, {
|
|
414
|
+
scale: motion.transform(progress, [0, 1], [1, (pageWidth - 16) / pageWidth]),
|
|
415
|
+
translateY: motion.transform(progress, [0, 1], [0, 24 + insetTop]),
|
|
416
|
+
borderRadius: motion.transform(progress, [0, 1], [0, 10])
|
|
818
417
|
});
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
418
|
+
});
|
|
419
|
+
const handleYComplete = useStableCallback(() => {
|
|
420
|
+
if (!rootId) return;
|
|
421
|
+
if (y.get() + 5 >= sheetHeight) {
|
|
422
|
+
cleanupModalEffect(rootId);
|
|
823
423
|
}
|
|
824
|
-
|
|
825
|
-
|
|
424
|
+
});
|
|
425
|
+
React.useEffect(() => {
|
|
426
|
+
if (!rootId) return;
|
|
427
|
+
const removeStartListener = y.on("animationStart", () => {
|
|
428
|
+
if (rootId) setupModalEffect(rootId);
|
|
429
|
+
});
|
|
430
|
+
const removeChangeListener = y.on("change", (yValue) => {
|
|
431
|
+
handleYChange(yValue);
|
|
432
|
+
});
|
|
433
|
+
const removeCompleteListener = y.on("animationComplete", handleYComplete);
|
|
434
|
+
const removeCancelListener = y.on("animationCancel", handleYComplete);
|
|
826
435
|
return () => {
|
|
436
|
+
if (rootId) cleanupModalEffect(rootId);
|
|
827
437
|
removeStartListener();
|
|
828
438
|
removeChangeListener();
|
|
829
439
|
removeCompleteListener();
|
|
830
440
|
removeCancelListener();
|
|
831
441
|
};
|
|
832
|
-
}, [
|
|
442
|
+
}, [rootId]);
|
|
833
443
|
}
|
|
834
444
|
function setupModalEffect(rootId) {
|
|
835
445
|
const root = document.querySelector(`#${rootId}`);
|
|
836
|
-
const body = document.querySelector("body");
|
|
837
446
|
if (!root) return;
|
|
838
|
-
body
|
|
447
|
+
const body = document.querySelector("body");
|
|
448
|
+
body.style.backgroundColor = "#000000";
|
|
839
449
|
root.style.overflow = "hidden";
|
|
840
450
|
root.style.transitionTimingFunction = "cubic-bezier(0.32, 0.72, 0, 1)";
|
|
841
451
|
root.style.transitionProperty = "transform, border-radius";
|
|
842
452
|
root.style.transitionDuration = "0.5s";
|
|
843
453
|
root.style.transformOrigin = "center top";
|
|
844
454
|
}
|
|
455
|
+
function updateModalEffect(rootId, opts) {
|
|
456
|
+
const root = document.querySelector(`#${rootId}`);
|
|
457
|
+
if (!root) return;
|
|
458
|
+
const { scale, translateY, borderRadius } = opts;
|
|
459
|
+
root.style.transform = `scale(${scale}) translate3d(0, ${translateY}px, 0)`;
|
|
460
|
+
root.style.borderTopRightRadius = `${borderRadius}px`;
|
|
461
|
+
root.style.borderTopLeftRadius = `${borderRadius}px`;
|
|
462
|
+
}
|
|
845
463
|
function cleanupModalEffect(rootId) {
|
|
846
464
|
const root = document.querySelector(`#${rootId}`);
|
|
847
|
-
const body = document.querySelector("body");
|
|
848
465
|
if (!root) return;
|
|
466
|
+
const body = document.querySelector("body");
|
|
849
467
|
body.style.removeProperty("background-color");
|
|
850
468
|
root.style.removeProperty("overflow");
|
|
851
469
|
root.style.removeProperty("transition-timing-function");
|
|
@@ -1065,19 +683,19 @@ function useSheetState({
|
|
|
1065
683
|
onOpen: _onOpen,
|
|
1066
684
|
onClosing: _onClosing
|
|
1067
685
|
}) {
|
|
1068
|
-
const [state, setState] =
|
|
686
|
+
const [state, setState] = React.useState(isOpen ? "opening" : "closed");
|
|
1069
687
|
const onClosed = useStableCallback(() => _onClosed == null ? void 0 : _onClosed());
|
|
1070
688
|
const onOpening = useStableCallback(() => _onOpening == null ? void 0 : _onOpening());
|
|
1071
689
|
const onOpen = useStableCallback(() => _onOpen == null ? void 0 : _onOpen());
|
|
1072
690
|
const onClosing = useStableCallback(() => _onClosing == null ? void 0 : _onClosing());
|
|
1073
|
-
|
|
691
|
+
React.useEffect(() => {
|
|
1074
692
|
if (isOpen && state === "closed") {
|
|
1075
693
|
setState("opening");
|
|
1076
694
|
} else if (!isOpen && (state === "open" || state === "opening")) {
|
|
1077
695
|
setState("closing");
|
|
1078
696
|
}
|
|
1079
697
|
}, [isOpen, state]);
|
|
1080
|
-
|
|
698
|
+
React.useEffect(() => {
|
|
1081
699
|
async function handle() {
|
|
1082
700
|
switch (state) {
|
|
1083
701
|
case "closed":
|
|
@@ -1157,9 +775,6 @@ function computeSnapPoints({
|
|
|
1157
775
|
// Y value is inverted as `y = 0` means sheet is at the top
|
|
1158
776
|
}));
|
|
1159
777
|
}
|
|
1160
|
-
function clamp(value, min, max) {
|
|
1161
|
-
return Math.min(Math.max(value, min), max);
|
|
1162
|
-
}
|
|
1163
778
|
function sign(value) {
|
|
1164
779
|
if (value > 0) return 1;
|
|
1165
780
|
if (value < 0) return -1;
|
|
@@ -1299,48 +914,152 @@ function classifyDragEnd({
|
|
|
1299
914
|
};
|
|
1300
915
|
}
|
|
1301
916
|
|
|
1302
|
-
// src/
|
|
1303
|
-
var
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
917
|
+
// src/styles.ts
|
|
918
|
+
var styles = {
|
|
919
|
+
root: {
|
|
920
|
+
base: {
|
|
921
|
+
position: "fixed",
|
|
922
|
+
top: 0,
|
|
923
|
+
bottom: 0,
|
|
924
|
+
left: 0,
|
|
925
|
+
right: 0,
|
|
926
|
+
overflow: "hidden",
|
|
927
|
+
pointerEvents: "none"
|
|
928
|
+
},
|
|
929
|
+
decorative: {}
|
|
930
|
+
},
|
|
931
|
+
backdrop: {
|
|
932
|
+
base: {
|
|
933
|
+
zIndex: 1,
|
|
934
|
+
position: "fixed",
|
|
935
|
+
top: 0,
|
|
936
|
+
left: 0,
|
|
937
|
+
width: "100%",
|
|
938
|
+
height: "100%",
|
|
939
|
+
touchAction: "none",
|
|
940
|
+
userSelect: "none"
|
|
941
|
+
},
|
|
942
|
+
decorative: {
|
|
943
|
+
backgroundColor: "rgba(0, 0, 0, 0.2)",
|
|
944
|
+
border: "none",
|
|
945
|
+
WebkitTapHighlightColor: "transparent"
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
container: {
|
|
949
|
+
base: {
|
|
950
|
+
zIndex: 2,
|
|
951
|
+
position: "absolute",
|
|
952
|
+
left: 0,
|
|
953
|
+
bottom: 0,
|
|
954
|
+
width: "100%",
|
|
955
|
+
pointerEvents: "auto",
|
|
956
|
+
display: "flex",
|
|
957
|
+
flexDirection: "column"
|
|
958
|
+
},
|
|
959
|
+
decorative: {
|
|
960
|
+
backgroundColor: "#fff",
|
|
961
|
+
borderTopRightRadius: "8px",
|
|
962
|
+
borderTopLeftRadius: "8px",
|
|
963
|
+
boxShadow: "0px -2px 16px rgba(0, 0, 0, 0.3)"
|
|
964
|
+
}
|
|
965
|
+
},
|
|
966
|
+
headerWrapper: {
|
|
967
|
+
base: {
|
|
968
|
+
width: "100%"
|
|
969
|
+
},
|
|
970
|
+
decorative: {}
|
|
971
|
+
},
|
|
972
|
+
header: {
|
|
973
|
+
base: {
|
|
974
|
+
width: "100%",
|
|
975
|
+
position: "relative"
|
|
976
|
+
},
|
|
977
|
+
decorative: {
|
|
978
|
+
height: "40px",
|
|
979
|
+
display: "flex",
|
|
980
|
+
alignItems: "center",
|
|
981
|
+
justifyContent: "center"
|
|
982
|
+
}
|
|
983
|
+
},
|
|
984
|
+
indicatorWrapper: {
|
|
985
|
+
base: {
|
|
986
|
+
display: "flex"
|
|
987
|
+
},
|
|
988
|
+
decorative: {}
|
|
989
|
+
},
|
|
990
|
+
indicator: {
|
|
991
|
+
base: {
|
|
992
|
+
display: "inline-block"
|
|
993
|
+
},
|
|
994
|
+
decorative: {
|
|
995
|
+
width: "18px",
|
|
996
|
+
height: "4px",
|
|
997
|
+
borderRadius: "99px",
|
|
998
|
+
backgroundColor: "#ddd"
|
|
999
|
+
}
|
|
1000
|
+
},
|
|
1001
|
+
content: {
|
|
1002
|
+
base: {
|
|
1003
|
+
minHeight: "0px",
|
|
1004
|
+
position: "relative",
|
|
1005
|
+
flexGrow: 1,
|
|
1006
|
+
display: "flex",
|
|
1007
|
+
flexDirection: "column"
|
|
1008
|
+
},
|
|
1009
|
+
decorative: {}
|
|
1010
|
+
},
|
|
1011
|
+
scroller: {
|
|
1012
|
+
base: {
|
|
1013
|
+
height: "100%",
|
|
1014
|
+
overflowY: "auto",
|
|
1015
|
+
overscrollBehaviorY: "none"
|
|
1016
|
+
},
|
|
1017
|
+
decorative: {}
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
// src/sheet.tsx
|
|
1022
|
+
var Sheet = React.forwardRef(
|
|
1023
|
+
({
|
|
1024
|
+
avoidKeyboard = true,
|
|
1025
|
+
children,
|
|
1026
|
+
className = "",
|
|
1027
|
+
detent = "default",
|
|
1028
|
+
disableDismiss = false,
|
|
1029
|
+
disableDrag: disableDragProp = false,
|
|
1030
|
+
disableScrollLocking = false,
|
|
1031
|
+
dragCloseThreshold = DEFAULT_DRAG_CLOSE_THRESHOLD,
|
|
1032
|
+
dragVelocityThreshold = DEFAULT_DRAG_VELOCITY_THRESHOLD,
|
|
1033
|
+
initialSnap,
|
|
1034
|
+
isOpen,
|
|
1035
|
+
modalEffectRootId,
|
|
1036
|
+
modalEffectThreshold,
|
|
1037
|
+
mountPoint,
|
|
1038
|
+
prefersReducedMotion = false,
|
|
1039
|
+
snapPoints: snapPointsProp,
|
|
1040
|
+
style,
|
|
1041
|
+
tweenConfig = DEFAULT_TWEEN_CONFIG,
|
|
1042
|
+
unstyled = false,
|
|
1043
|
+
onOpenStart,
|
|
1044
|
+
onOpenEnd,
|
|
1045
|
+
onClose,
|
|
1046
|
+
onCloseStart,
|
|
1047
|
+
onCloseEnd,
|
|
1048
|
+
onSnap,
|
|
1049
|
+
onDrag: onDragProp,
|
|
1050
|
+
onDragStart: onDragStartProp,
|
|
1332
1051
|
onDragEnd: onDragEndProp,
|
|
1333
1052
|
...rest
|
|
1334
1053
|
}, ref) => {
|
|
1335
1054
|
const [sheetBoundsRef, sheetBounds] = useMeasure__default.default();
|
|
1336
|
-
const sheetRef =
|
|
1055
|
+
const sheetRef = React.useRef(null);
|
|
1337
1056
|
const sheetHeight = Math.round(sheetBounds.height);
|
|
1338
|
-
const [currentSnap, setCurrentSnap] =
|
|
1339
|
-
const snapPoints = snapPointsProp && sheetHeight > 0 ? computeSnapPoints({ sheetHeight, snapPointsProp }) : [];
|
|
1057
|
+
const [currentSnap, setCurrentSnap] = React.useState(initialSnap);
|
|
1340
1058
|
const { windowHeight } = useDimensions();
|
|
1341
1059
|
const closedY = sheetHeight > 0 ? sheetHeight : windowHeight;
|
|
1342
1060
|
const y = react.useMotionValue(closedY);
|
|
1343
1061
|
const yInverted = react.useTransform(y, (val) => Math.max(sheetHeight - val, 0));
|
|
1062
|
+
const yProgress = react.useTransform(y, (val) => clamp(1 - val / closedY, 0, 1));
|
|
1344
1063
|
const indicatorRotation = react.useMotionValue(0);
|
|
1345
1064
|
const shouldReduceMotion = react.useReducedMotion();
|
|
1346
1065
|
const reduceMotion = Boolean(prefersReducedMotion || shouldReduceMotion);
|
|
@@ -1356,6 +1075,9 @@ var Sheet = React4.forwardRef(
|
|
|
1356
1075
|
y,
|
|
1357
1076
|
(val) => val + 2 >= closedY ? "hidden" : "visible"
|
|
1358
1077
|
);
|
|
1078
|
+
const snapPoints = React.useMemo(() => {
|
|
1079
|
+
return snapPointsProp && sheetHeight > 0 ? computeSnapPoints({ sheetHeight, snapPointsProp }) : [];
|
|
1080
|
+
}, [sheetHeight, snapPointsProp == null ? void 0 : snapPointsProp.join("")]);
|
|
1359
1081
|
const updateSnap = useStableCallback((snapIndex) => {
|
|
1360
1082
|
setCurrentSnap(snapIndex);
|
|
1361
1083
|
onSnap == null ? void 0 : onSnap(snapIndex);
|
|
@@ -1468,12 +1190,6 @@ var Sheet = React4.forwardRef(
|
|
|
1468
1190
|
}
|
|
1469
1191
|
indicatorRotation.set(0);
|
|
1470
1192
|
});
|
|
1471
|
-
React4.useImperativeHandle(ref, () => ({
|
|
1472
|
-
y,
|
|
1473
|
-
yInverted,
|
|
1474
|
-
height: sheetHeight,
|
|
1475
|
-
snapTo
|
|
1476
|
-
}));
|
|
1477
1193
|
useModalEffect({
|
|
1478
1194
|
y,
|
|
1479
1195
|
detent,
|
|
@@ -1493,9 +1209,7 @@ var Sheet = React4.forwardRef(
|
|
|
1493
1209
|
const initialSnapPoint = initialSnap !== void 0 ? getSnapPoint(initialSnap) : null;
|
|
1494
1210
|
const yTo = (initialSnapPoint == null ? void 0 : initialSnapPoint.snapValueY) ?? 0;
|
|
1495
1211
|
await react.animate(y, yTo, animationOptions);
|
|
1496
|
-
if (initialSnap !== void 0)
|
|
1497
|
-
updateSnap(initialSnap);
|
|
1498
|
-
}
|
|
1212
|
+
if (initialSnap !== void 0) updateSnap(initialSnap);
|
|
1499
1213
|
onOpenEnd == null ? void 0 : onOpenEnd();
|
|
1500
1214
|
},
|
|
1501
1215
|
onClosing: async () => {
|
|
@@ -1513,7 +1227,7 @@ var Sheet = React4.forwardRef(
|
|
|
1513
1227
|
onDragStart,
|
|
1514
1228
|
onDragEnd
|
|
1515
1229
|
};
|
|
1516
|
-
const
|
|
1230
|
+
const internalContext = {
|
|
1517
1231
|
currentSnap,
|
|
1518
1232
|
detent,
|
|
1519
1233
|
disableDrag,
|
|
@@ -1524,9 +1238,20 @@ var Sheet = React4.forwardRef(
|
|
|
1524
1238
|
sheetBoundsRef,
|
|
1525
1239
|
sheetRef,
|
|
1526
1240
|
unstyled,
|
|
1241
|
+
yProgress,
|
|
1527
1242
|
y
|
|
1528
1243
|
};
|
|
1529
|
-
const
|
|
1244
|
+
const exposedContext = {
|
|
1245
|
+
height: sheetHeight,
|
|
1246
|
+
currentSnap,
|
|
1247
|
+
snapPoints,
|
|
1248
|
+
snapTo,
|
|
1249
|
+
y,
|
|
1250
|
+
yInverted,
|
|
1251
|
+
yProgress
|
|
1252
|
+
};
|
|
1253
|
+
React.useImperativeHandle(ref, () => exposedContext);
|
|
1254
|
+
const sheet = /* @__PURE__ */ React__default.default.createElement(InternalSheetContext.Provider, { value: internalContext }, /* @__PURE__ */ React__default.default.createElement(
|
|
1530
1255
|
react.motion.div,
|
|
1531
1256
|
{
|
|
1532
1257
|
...rest,
|
|
@@ -1540,13 +1265,293 @@ var Sheet = React4.forwardRef(
|
|
|
1540
1265
|
...style
|
|
1541
1266
|
}
|
|
1542
1267
|
},
|
|
1543
|
-
state !== "closed" ? children : null
|
|
1268
|
+
/* @__PURE__ */ React__default.default.createElement(ExposedSheetContext.Provider, { value: exposedContext }, state !== "closed" ? children : null)
|
|
1544
1269
|
));
|
|
1545
1270
|
if (IS_SSR) return sheet;
|
|
1546
1271
|
return reactDom.createPortal(sheet, mountPoint ?? document.body);
|
|
1547
1272
|
}
|
|
1548
1273
|
);
|
|
1549
1274
|
Sheet.displayName = "Sheet";
|
|
1275
|
+
var isClickable = (props) => !!props.onClick || !!props.onTap;
|
|
1276
|
+
var SheetBackdrop = React.forwardRef(
|
|
1277
|
+
({ style, className = "", unstyled, ...rest }, ref) => {
|
|
1278
|
+
const sheetContext = useInternalContext();
|
|
1279
|
+
const clickable = isClickable(rest);
|
|
1280
|
+
const Comp = clickable ? react.motion.button : react.motion.div;
|
|
1281
|
+
const pointerEvents = clickable ? "auto" : "none";
|
|
1282
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1283
|
+
const backdropStyle = {
|
|
1284
|
+
opacity: sheetContext.yProgress,
|
|
1285
|
+
...applyStyles(styles.backdrop, isUnstyled),
|
|
1286
|
+
...style,
|
|
1287
|
+
pointerEvents
|
|
1288
|
+
};
|
|
1289
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
1290
|
+
Comp,
|
|
1291
|
+
{
|
|
1292
|
+
...rest,
|
|
1293
|
+
ref,
|
|
1294
|
+
className: `react-modal-sheet-backdrop ${className}`,
|
|
1295
|
+
style: backdropStyle
|
|
1296
|
+
}
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
);
|
|
1300
|
+
SheetBackdrop.displayName = "SheetBackdrop";
|
|
1301
|
+
var SheetContainer = React.forwardRef(
|
|
1302
|
+
({ children, style, className = "", unstyled, ...rest }, ref) => {
|
|
1303
|
+
const sheetContext = useInternalContext();
|
|
1304
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1305
|
+
const containerStyle = {
|
|
1306
|
+
...applyStyles(styles.container, isUnstyled),
|
|
1307
|
+
...style,
|
|
1308
|
+
y: sheetContext.y
|
|
1309
|
+
};
|
|
1310
|
+
if (sheetContext.detent === "default") {
|
|
1311
|
+
containerStyle.height = DEFAULT_HEIGHT;
|
|
1312
|
+
}
|
|
1313
|
+
if (sheetContext.detent === "full") {
|
|
1314
|
+
containerStyle.height = "100%";
|
|
1315
|
+
containerStyle.maxHeight = "100%";
|
|
1316
|
+
}
|
|
1317
|
+
if (sheetContext.detent === "content") {
|
|
1318
|
+
containerStyle.height = "auto";
|
|
1319
|
+
containerStyle.maxHeight = DEFAULT_HEIGHT;
|
|
1320
|
+
}
|
|
1321
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
1322
|
+
react.motion.div,
|
|
1323
|
+
{
|
|
1324
|
+
...rest,
|
|
1325
|
+
ref: mergeRefs([
|
|
1326
|
+
ref,
|
|
1327
|
+
sheetContext.sheetRef,
|
|
1328
|
+
sheetContext.sheetBoundsRef
|
|
1329
|
+
]),
|
|
1330
|
+
className: `react-modal-sheet-container ${className}`,
|
|
1331
|
+
style: containerStyle
|
|
1332
|
+
},
|
|
1333
|
+
children
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
);
|
|
1337
|
+
SheetContainer.displayName = "SheetContainer";
|
|
1338
|
+
var constraints = { bottom: 0, top: 0, left: 0, right: 0 };
|
|
1339
|
+
function useDragConstraints() {
|
|
1340
|
+
const ref = React.useRef(null);
|
|
1341
|
+
const onMeasure = React.useCallback(() => constraints, []);
|
|
1342
|
+
return { ref, onMeasure };
|
|
1343
|
+
}
|
|
1344
|
+
function useScrollPosition(options = {}) {
|
|
1345
|
+
const { debounceDelay = 32, isEnabled = true } = options;
|
|
1346
|
+
const scrollTimeoutRef = React.useRef(null);
|
|
1347
|
+
const [element, setElement] = React.useState(null);
|
|
1348
|
+
const [scrollPosition, setScrollPosition] = React.useState(void 0);
|
|
1349
|
+
const scrollRef = React.useMemo(
|
|
1350
|
+
() => (element2) => {
|
|
1351
|
+
setElement(element2);
|
|
1352
|
+
},
|
|
1353
|
+
[]
|
|
1354
|
+
);
|
|
1355
|
+
const determineScrollPosition = useStableCallback((element2) => {
|
|
1356
|
+
const { scrollTop, scrollHeight, clientHeight } = element2;
|
|
1357
|
+
const isScrollable2 = scrollHeight > clientHeight;
|
|
1358
|
+
if (!isScrollable2) {
|
|
1359
|
+
if (scrollPosition) setScrollPosition(void 0);
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
const isAtTop = scrollTop <= 0;
|
|
1363
|
+
const isAtBottom = Math.ceil(scrollHeight) - Math.ceil(scrollTop) === Math.ceil(clientHeight);
|
|
1364
|
+
let position;
|
|
1365
|
+
if (isAtTop) {
|
|
1366
|
+
position = "top";
|
|
1367
|
+
} else if (isAtBottom) {
|
|
1368
|
+
position = "bottom";
|
|
1369
|
+
} else {
|
|
1370
|
+
position = "middle";
|
|
1371
|
+
}
|
|
1372
|
+
element2.style.touchAction = isAtTop ? "pan-down" : "";
|
|
1373
|
+
if (position === scrollPosition) return;
|
|
1374
|
+
setScrollPosition(position);
|
|
1375
|
+
});
|
|
1376
|
+
const onScroll = useStableCallback((event) => {
|
|
1377
|
+
if (event.currentTarget instanceof HTMLElement) {
|
|
1378
|
+
const el = event.currentTarget;
|
|
1379
|
+
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
1380
|
+
if (debounceDelay === 0) {
|
|
1381
|
+
determineScrollPosition(el);
|
|
1382
|
+
} else {
|
|
1383
|
+
scrollTimeoutRef.current = setTimeout(
|
|
1384
|
+
() => determineScrollPosition(el),
|
|
1385
|
+
debounceDelay
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
const onTouchStart = useStableCallback((event) => {
|
|
1391
|
+
if (event.currentTarget instanceof HTMLElement) {
|
|
1392
|
+
const element2 = event.currentTarget;
|
|
1393
|
+
requestAnimationFrame(() => {
|
|
1394
|
+
determineScrollPosition(element2);
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
});
|
|
1398
|
+
React.useEffect(() => {
|
|
1399
|
+
if (!element || !isEnabled) return;
|
|
1400
|
+
determineScrollPosition(element);
|
|
1401
|
+
element.addEventListener("scroll", onScroll);
|
|
1402
|
+
element.addEventListener("touchstart", onTouchStart);
|
|
1403
|
+
return () => {
|
|
1404
|
+
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
1405
|
+
element.removeEventListener("scroll", onScroll);
|
|
1406
|
+
element.removeEventListener("touchstart", onTouchStart);
|
|
1407
|
+
};
|
|
1408
|
+
}, [element, isEnabled]);
|
|
1409
|
+
return {
|
|
1410
|
+
scrollRef,
|
|
1411
|
+
scrollPosition
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
// src/sheet-content.tsx
|
|
1416
|
+
var SheetContent = React.forwardRef(
|
|
1417
|
+
({
|
|
1418
|
+
disableScroll: disableScrollProp,
|
|
1419
|
+
disableDrag: disableDragProp,
|
|
1420
|
+
children,
|
|
1421
|
+
style: styleProp,
|
|
1422
|
+
className = "",
|
|
1423
|
+
scrollClassName = "",
|
|
1424
|
+
scrollStyle: scrollStyleProp,
|
|
1425
|
+
scrollRef: scrollRefProp = null,
|
|
1426
|
+
unstyled,
|
|
1427
|
+
...rest
|
|
1428
|
+
}, ref) => {
|
|
1429
|
+
const sheetContext = useInternalContext();
|
|
1430
|
+
const dragConstraints = useDragConstraints();
|
|
1431
|
+
const scroll = useScrollPosition({
|
|
1432
|
+
isEnabled: typeof disableScrollProp === "function" ? true : !disableScrollProp
|
|
1433
|
+
});
|
|
1434
|
+
const disableScroll = typeof disableScrollProp === "function" ? disableScrollProp({
|
|
1435
|
+
scrollPosition: scroll.scrollPosition,
|
|
1436
|
+
currentSnap: sheetContext.currentSnap
|
|
1437
|
+
}) : Boolean(disableScrollProp);
|
|
1438
|
+
const disableDragDueToScroll = !disableScroll && scroll.scrollPosition && scroll.scrollPosition !== "top";
|
|
1439
|
+
const disableDragDueToProp = typeof disableDragProp === "function" ? disableDragProp({
|
|
1440
|
+
scrollPosition: scroll.scrollPosition,
|
|
1441
|
+
currentSnap: sheetContext.currentSnap
|
|
1442
|
+
}) : Boolean(disableDragProp);
|
|
1443
|
+
const disableDrag = disableDragDueToProp || disableDragDueToScroll || sheetContext.disableDrag;
|
|
1444
|
+
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
1445
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1446
|
+
const contentStyle = {
|
|
1447
|
+
...applyStyles(styles.content, isUnstyled),
|
|
1448
|
+
...styleProp
|
|
1449
|
+
};
|
|
1450
|
+
const scrollStyle = applyStyles(styles.scroller, isUnstyled);
|
|
1451
|
+
if (sheetContext.avoidKeyboard) {
|
|
1452
|
+
scrollStyle.paddingBottom = isHTTPS() ? "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))" : "var(--keyboard-inset-height, 0px)";
|
|
1453
|
+
}
|
|
1454
|
+
if (disableScroll) {
|
|
1455
|
+
scrollStyle.overflowY = "clip";
|
|
1456
|
+
}
|
|
1457
|
+
if (dragProps !== void 0) {
|
|
1458
|
+
scrollStyle.touchAction = "pan-down";
|
|
1459
|
+
}
|
|
1460
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
1461
|
+
react.motion.div,
|
|
1462
|
+
{
|
|
1463
|
+
...rest,
|
|
1464
|
+
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
1465
|
+
className: `react-modal-sheet-content ${className}`,
|
|
1466
|
+
style: contentStyle,
|
|
1467
|
+
...dragProps,
|
|
1468
|
+
dragConstraints: dragConstraints.ref,
|
|
1469
|
+
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
1470
|
+
},
|
|
1471
|
+
/* @__PURE__ */ React__default.default.createElement(
|
|
1472
|
+
react.motion.div,
|
|
1473
|
+
{
|
|
1474
|
+
ref: mergeRefs([scroll.scrollRef, scrollRefProp]),
|
|
1475
|
+
style: { ...scrollStyle, ...scrollStyleProp },
|
|
1476
|
+
className: `react-modal-sheet-content-scroller ${scrollClassName}`
|
|
1477
|
+
},
|
|
1478
|
+
children
|
|
1479
|
+
)
|
|
1480
|
+
);
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
SheetContent.displayName = "SheetContent";
|
|
1484
|
+
function SheetDragIndicator({
|
|
1485
|
+
style,
|
|
1486
|
+
className = "",
|
|
1487
|
+
unstyled,
|
|
1488
|
+
...rest
|
|
1489
|
+
}) {
|
|
1490
|
+
const sheetContext = useInternalContext();
|
|
1491
|
+
const indicator1Transform = react.useTransform(
|
|
1492
|
+
sheetContext.indicatorRotation,
|
|
1493
|
+
(r) => `translateX(2px) rotate(${r}deg)`
|
|
1494
|
+
);
|
|
1495
|
+
const indicator2Transform = react.useTransform(
|
|
1496
|
+
sheetContext.indicatorRotation,
|
|
1497
|
+
(r) => `translateX(-2px) rotate(${ -1 * r}deg)`
|
|
1498
|
+
);
|
|
1499
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1500
|
+
const indicatorWrapperStyle = {
|
|
1501
|
+
...applyStyles(styles.indicatorWrapper, isUnstyled),
|
|
1502
|
+
...style
|
|
1503
|
+
};
|
|
1504
|
+
const indicatorStyle = applyStyles(styles.indicator, isUnstyled);
|
|
1505
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
1506
|
+
"div",
|
|
1507
|
+
{
|
|
1508
|
+
className: `react-modal-sheet-drag-indicator-container ${className}`,
|
|
1509
|
+
style: indicatorWrapperStyle,
|
|
1510
|
+
...rest
|
|
1511
|
+
},
|
|
1512
|
+
/* @__PURE__ */ React__default.default.createElement(
|
|
1513
|
+
react.motion.span,
|
|
1514
|
+
{
|
|
1515
|
+
className: "react-modal-sheet-drag-indicator",
|
|
1516
|
+
style: { ...indicatorStyle, transform: indicator1Transform }
|
|
1517
|
+
}
|
|
1518
|
+
),
|
|
1519
|
+
/* @__PURE__ */ React__default.default.createElement(
|
|
1520
|
+
react.motion.span,
|
|
1521
|
+
{
|
|
1522
|
+
className: "react-modal-sheet-drag-indicator",
|
|
1523
|
+
style: { ...indicatorStyle, transform: indicator2Transform }
|
|
1524
|
+
}
|
|
1525
|
+
)
|
|
1526
|
+
);
|
|
1527
|
+
}
|
|
1528
|
+
var SheetHeader = React.forwardRef(
|
|
1529
|
+
({ children, style, disableDrag, unstyled, className = "", ...rest }, ref) => {
|
|
1530
|
+
const sheetContext = useInternalContext();
|
|
1531
|
+
const dragConstraints = useDragConstraints();
|
|
1532
|
+
const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
|
|
1533
|
+
const isUnstyled = unstyled ?? sheetContext.unstyled;
|
|
1534
|
+
const headerWrapperStyle = {
|
|
1535
|
+
...applyStyles(styles.headerWrapper, isUnstyled),
|
|
1536
|
+
...style
|
|
1537
|
+
};
|
|
1538
|
+
const headerStyle = applyStyles(styles.header, isUnstyled);
|
|
1539
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
1540
|
+
react.motion.div,
|
|
1541
|
+
{
|
|
1542
|
+
...rest,
|
|
1543
|
+
ref: mergeRefs([ref, dragConstraints.ref]),
|
|
1544
|
+
style: headerWrapperStyle,
|
|
1545
|
+
className: `react-modal-sheet-header-container ${className}`,
|
|
1546
|
+
...dragProps,
|
|
1547
|
+
dragConstraints: dragConstraints.ref,
|
|
1548
|
+
onMeasureDragConstraints: dragConstraints.onMeasure
|
|
1549
|
+
},
|
|
1550
|
+
children || /* @__PURE__ */ React__default.default.createElement("div", { className: "react-modal-sheet-header", style: headerStyle }, /* @__PURE__ */ React__default.default.createElement(SheetDragIndicator, null))
|
|
1551
|
+
);
|
|
1552
|
+
}
|
|
1553
|
+
);
|
|
1554
|
+
SheetHeader.displayName = "SheetHeader";
|
|
1550
1555
|
|
|
1551
1556
|
// src/index.tsx
|
|
1552
1557
|
var Sheet2 = Object.assign(Sheet, {
|
|
@@ -1554,7 +1559,8 @@ var Sheet2 = Object.assign(Sheet, {
|
|
|
1554
1559
|
Header: SheetHeader,
|
|
1555
1560
|
DragIndicator: SheetDragIndicator,
|
|
1556
1561
|
Content: SheetContent,
|
|
1557
|
-
Backdrop: SheetBackdrop
|
|
1562
|
+
Backdrop: SheetBackdrop,
|
|
1563
|
+
useContext: useExposedContext
|
|
1558
1564
|
});
|
|
1559
1565
|
|
|
1560
1566
|
exports.Sheet = Sheet2;
|