react-modal-sheet 2.2.1 → 3.1.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/dist/index.js CHANGED
@@ -1,8 +1,841 @@
1
+ 'use strict';
1
2
 
2
- 'use strict'
3
+ var React2 = require('react');
4
+ var reactDom = require('react-dom');
5
+ var framerMotion = require('framer-motion');
6
+ var utils = require('@react-aria/utils');
3
7
 
4
- if (process.env.NODE_ENV === 'production') {
5
- module.exports = require('./react-modal-sheet.cjs.production.min.js')
6
- } else {
7
- module.exports = require('./react-modal-sheet.cjs.development.js')
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var React2__default = /*#__PURE__*/_interopDefault(React2);
11
+
12
+ // src/sheet.tsx
13
+
14
+ // src/constants.ts
15
+ var MAX_HEIGHT = "calc(100% - env(safe-area-inset-top) - 34px)";
16
+ var IS_SSR = typeof window === "undefined";
17
+ var DEFAULT_TWEEN_CONFIG = {
18
+ ease: "easeOut",
19
+ duration: 0.2
20
+ };
21
+ var REDUCED_MOTION_TWEEN_CONFIG = {
22
+ ease: "linear",
23
+ duration: 0.01
24
+ };
25
+ var DRAG_CLOSE_THRESHOLD = 0.6;
26
+ var DRAG_VELOCITY_THRESHOLD = 500;
27
+
28
+ // src/utils.ts
29
+ function getClosest(nums, goal) {
30
+ let closest = nums[0];
31
+ let minDifference = Math.abs(nums[0] - goal);
32
+ for (let i = 1; i < nums.length; i++) {
33
+ const difference = Math.abs(nums[i] - goal);
34
+ if (difference < minDifference) {
35
+ closest = nums[i];
36
+ minDifference = difference;
37
+ }
38
+ }
39
+ return closest;
40
+ }
41
+ function applyRootStyles(rootId) {
42
+ const body = document.querySelector("body");
43
+ const root = document.querySelector(`#${rootId}`);
44
+ if (root) {
45
+ const p = 24;
46
+ const h = window.innerHeight;
47
+ const s = (h - p) / h;
48
+ body.style.backgroundColor = "#000";
49
+ root.style.overflow = "hidden";
50
+ root.style.willChange = "transform";
51
+ root.style.transition = "transform 200ms ease-in-out, border-radius 200ms linear";
52
+ root.style.transform = `translateY(calc(env(safe-area-inset-top) + ${p / 2}px)) scale(${s})`;
53
+ root.style.borderTopRightRadius = "10px";
54
+ root.style.borderTopLeftRadius = "10px";
55
+ }
56
+ }
57
+ function cleanupRootStyles(rootId) {
58
+ const body = document.querySelector("body");
59
+ const root = document.getElementById(rootId);
60
+ function onTransitionEnd() {
61
+ root.style.removeProperty("overflow");
62
+ root.style.removeProperty("will-change");
63
+ root.style.removeProperty("transition");
64
+ body.style.removeProperty("background-color");
65
+ root.removeEventListener("transitionend", onTransitionEnd);
66
+ }
67
+ if (root) {
68
+ root.style.removeProperty("border-top-right-radius");
69
+ root.style.removeProperty("border-top-left-radius");
70
+ root.style.removeProperty("transform");
71
+ root.addEventListener("transitionend", onTransitionEnd);
72
+ }
73
+ }
74
+ function inDescendingOrder(arr) {
75
+ for (let i = 0; i < arr.length; i++) {
76
+ if (arr[i + 1] > arr[i])
77
+ return false;
78
+ }
79
+ return true;
80
+ }
81
+ function validateSnapTo({
82
+ snapTo,
83
+ sheetHeight
84
+ }) {
85
+ if (snapTo < 0) {
86
+ console.warn(
87
+ `Snap point is out of bounds. Sheet height is ${sheetHeight} but snap point is ${sheetHeight + Math.abs(snapTo)}.`
88
+ );
89
+ }
90
+ return Math.max(Math.round(snapTo), 0);
91
+ }
92
+ function mergeRefs(refs) {
93
+ return (value) => {
94
+ refs.forEach((ref) => {
95
+ if (typeof ref === "function") {
96
+ ref(value);
97
+ } else if (ref) {
98
+ ref.current = value;
99
+ }
100
+ });
101
+ };
102
+ }
103
+ function isTouchDevice() {
104
+ if (typeof window === "undefined")
105
+ return false;
106
+ return "ontouchstart" in window || navigator.maxTouchPoints > 0;
107
+ }
108
+
109
+ // src/hooks.tsx
110
+ var useIsomorphicLayoutEffect = IS_SSR ? React2.useEffect : React2.useLayoutEffect;
111
+ function useModalEffect(isOpen, rootId) {
112
+ const prevOpen = usePrevious(isOpen);
113
+ React2.useEffect(() => {
114
+ if (rootId && !prevOpen && isOpen) {
115
+ applyRootStyles(rootId);
116
+ } else if (rootId && !isOpen && prevOpen) {
117
+ cleanupRootStyles(rootId);
118
+ }
119
+ }, [isOpen, prevOpen]);
120
+ React2.useEffect(() => {
121
+ return () => {
122
+ if (rootId && isOpen)
123
+ cleanupRootStyles(rootId);
124
+ };
125
+ }, [isOpen]);
126
+ }
127
+ function useEventCallbacks(isOpen, callbacks) {
128
+ const prevOpen = usePrevious(isOpen);
129
+ const didOpen = React2.useRef(false);
130
+ const handleAnimationComplete = React2.useCallback(() => {
131
+ var _a, _b, _c, _d;
132
+ if (!didOpen.current) {
133
+ (_b = (_a = callbacks.current).onOpenEnd) == null ? void 0 : _b.call(_a);
134
+ didOpen.current = true;
135
+ } else {
136
+ (_d = (_c = callbacks.current).onCloseEnd) == null ? void 0 : _d.call(_c);
137
+ didOpen.current = false;
138
+ }
139
+ }, [isOpen, prevOpen]);
140
+ React2.useEffect(() => {
141
+ var _a, _b, _c, _d;
142
+ if (!prevOpen && isOpen) {
143
+ (_b = (_a = callbacks.current).onOpenStart) == null ? void 0 : _b.call(_a);
144
+ } else if (!isOpen && prevOpen) {
145
+ (_d = (_c = callbacks.current).onCloseStart) == null ? void 0 : _d.call(_c);
146
+ }
147
+ }, [isOpen, prevOpen]);
148
+ return { handleAnimationComplete };
149
+ }
150
+ function useDimensions() {
151
+ const [dimensions, setDimensions] = React2.useState({ height: 0, width: 0 });
152
+ useIsomorphicLayoutEffect(() => {
153
+ function handler() {
154
+ setDimensions({
155
+ height: window.innerHeight,
156
+ width: window.innerWidth
157
+ });
158
+ }
159
+ handler();
160
+ window.addEventListener("resize", handler);
161
+ return () => {
162
+ window.removeEventListener("resize", handler);
163
+ };
164
+ }, []);
165
+ return dimensions;
166
+ }
167
+ function usePrevious(state) {
168
+ const ref = React2.useRef();
169
+ React2.useEffect(() => {
170
+ ref.current = state;
171
+ });
172
+ return ref.current;
8
173
  }
174
+ function useEffectEvent(handler) {
175
+ const handlerRef = React2.useRef();
176
+ useIsomorphicLayoutEffect(() => {
177
+ handlerRef.current = handler;
178
+ });
179
+ return React2.useCallback((...args) => {
180
+ const fn = handlerRef.current;
181
+ return fn == null ? void 0 : fn(...args);
182
+ }, []);
183
+ }
184
+ var constraints = { bottom: 0, top: 0, left: 0, right: 0 };
185
+ function useDragConstraints() {
186
+ const constraintsRef = React2.useRef(null);
187
+ const onMeasureDragConstraints = React2.useCallback(() => constraints, []);
188
+ return { constraintsRef, onMeasureDragConstraints };
189
+ }
190
+ var SheetContext = React2.createContext(
191
+ void 0
192
+ );
193
+ var useSheetContext = () => {
194
+ const context = React2.useContext(SheetContext);
195
+ if (!context)
196
+ throw Error("Sheet context error");
197
+ return context;
198
+ };
199
+ var SheetScrollerContext = React2.createContext(void 0);
200
+ function SheetScrollerContextProvider({
201
+ children
202
+ }) {
203
+ const sheetContext = useSheetContext();
204
+ const [disableDrag, setDisableDrag] = React2.useState(!!sheetContext.disableDrag);
205
+ function setDragEnabled() {
206
+ if (!sheetContext.disableDrag)
207
+ setDisableDrag(false);
208
+ }
209
+ function setDragDisabled() {
210
+ if (!disableDrag)
211
+ setDisableDrag(true);
212
+ }
213
+ return /* @__PURE__ */ React2__default.default.createElement(
214
+ SheetScrollerContext.Provider,
215
+ {
216
+ value: { disableDrag, setDragEnabled, setDragDisabled }
217
+ },
218
+ children
219
+ );
220
+ }
221
+ var useSheetScrollerContext = () => {
222
+ const context = React2.useContext(SheetScrollerContext);
223
+ if (!context)
224
+ throw Error("Sheet scroller context error");
225
+ return context;
226
+ };
227
+ var visualViewport = typeof window !== "undefined" ? window.visualViewport : void 0;
228
+ var nonTextInputTypes = /* @__PURE__ */ new Set([
229
+ "checkbox",
230
+ "radio",
231
+ "range",
232
+ "color",
233
+ "file",
234
+ "image",
235
+ "button",
236
+ "submit",
237
+ "reset"
238
+ ]);
239
+ var preventScrollCount = 0;
240
+ var restore;
241
+ function usePreventScroll(options = {}) {
242
+ const { isDisabled } = options;
243
+ utils.useLayoutEffect(() => {
244
+ if (isDisabled) {
245
+ return;
246
+ }
247
+ preventScrollCount++;
248
+ if (preventScrollCount === 1) {
249
+ if (utils.isIOS()) {
250
+ restore = preventScrollMobileSafari();
251
+ } else {
252
+ restore = preventScrollStandard();
253
+ }
254
+ }
255
+ return () => {
256
+ preventScrollCount--;
257
+ if (preventScrollCount === 0) {
258
+ restore();
259
+ }
260
+ };
261
+ }, [isDisabled]);
262
+ }
263
+ function preventScrollStandard() {
264
+ return utils.chain(
265
+ setStyle(
266
+ document.documentElement,
267
+ "paddingRight",
268
+ `${window.innerWidth - document.documentElement.clientWidth}px`
269
+ ),
270
+ setStyle(document.documentElement, "overflow", "hidden")
271
+ );
272
+ }
273
+ function preventScrollMobileSafari() {
274
+ let scrollable;
275
+ let lastY = 0;
276
+ const onTouchStart = (e) => {
277
+ scrollable = utils.getScrollParent(e.target);
278
+ if (scrollable === document.documentElement && scrollable === document.body) {
279
+ return;
280
+ }
281
+ lastY = e.changedTouches[0].pageY;
282
+ };
283
+ const onTouchMove = (e) => {
284
+ if (scrollable === void 0) {
285
+ return;
286
+ }
287
+ if (scrollable === document.documentElement || scrollable === document.body) {
288
+ e.preventDefault();
289
+ return;
290
+ }
291
+ const y = e.changedTouches[0].pageY;
292
+ const scrollTop = scrollable.scrollTop;
293
+ const bottom = scrollable.scrollHeight - scrollable.clientHeight;
294
+ if (bottom === 0) {
295
+ return;
296
+ }
297
+ if (scrollTop <= 0 && y > lastY || scrollTop >= bottom && y < lastY) {
298
+ e.preventDefault();
299
+ }
300
+ lastY = y;
301
+ };
302
+ const onTouchEnd = (e) => {
303
+ const target = e.target;
304
+ if (willOpenKeyboard(target) && target !== document.activeElement) {
305
+ e.preventDefault();
306
+ target.style.transform = "translateY(-2000px)";
307
+ target.focus();
308
+ requestAnimationFrame(() => {
309
+ target.style.transform = "";
310
+ });
311
+ }
312
+ };
313
+ const onFocus = (e) => {
314
+ const target = e.target;
315
+ if (willOpenKeyboard(target)) {
316
+ target.style.transform = "translateY(-2000px)";
317
+ requestAnimationFrame(() => {
318
+ target.style.transform = "";
319
+ if (visualViewport) {
320
+ if (visualViewport.height < window.innerHeight) {
321
+ requestAnimationFrame(() => {
322
+ scrollIntoView(target);
323
+ });
324
+ } else {
325
+ visualViewport.addEventListener(
326
+ "resize",
327
+ () => {
328
+ scrollIntoView(target);
329
+ },
330
+ { once: true }
331
+ );
332
+ }
333
+ }
334
+ });
335
+ }
336
+ };
337
+ const onWindowScroll = () => {
338
+ window.scrollTo(0, 0);
339
+ };
340
+ const scrollX = window.pageXOffset;
341
+ const scrollY = window.pageYOffset;
342
+ const restoreStyles = utils.chain(
343
+ setStyle(
344
+ document.documentElement,
345
+ "paddingRight",
346
+ `${window.innerWidth - document.documentElement.clientWidth}px`
347
+ ),
348
+ setStyle(document.documentElement, "overflow", "hidden"),
349
+ setStyle(document.body, "marginTop", `-${scrollY}px`)
350
+ );
351
+ window.scrollTo(0, 0);
352
+ const removeEvents = utils.chain(
353
+ addEvent(document, "touchstart", onTouchStart, {
354
+ passive: false,
355
+ capture: true
356
+ }),
357
+ addEvent(document, "touchmove", onTouchMove, {
358
+ passive: false,
359
+ capture: true
360
+ }),
361
+ addEvent(document, "touchend", onTouchEnd, {
362
+ passive: false,
363
+ capture: true
364
+ }),
365
+ addEvent(document, "focus", onFocus, true),
366
+ addEvent(window, "scroll", onWindowScroll)
367
+ );
368
+ return () => {
369
+ restoreStyles();
370
+ removeEvents();
371
+ window.scrollTo(scrollX, scrollY);
372
+ };
373
+ }
374
+ function setStyle(element, style, value) {
375
+ const cur = element.style[style];
376
+ element.style[style] = value;
377
+ return () => {
378
+ element.style[style] = cur;
379
+ };
380
+ }
381
+ function addEvent(target, event, handler, options) {
382
+ target.addEventListener(event, handler, options);
383
+ return () => {
384
+ target.removeEventListener(event, handler, options);
385
+ };
386
+ }
387
+ function scrollIntoView(target) {
388
+ const root = document.scrollingElement || document.documentElement;
389
+ while (target && target !== root) {
390
+ const scrollable = utils.getScrollParent(target);
391
+ if (scrollable !== document.documentElement && scrollable !== document.body && scrollable !== target) {
392
+ const scrollableTop = scrollable.getBoundingClientRect().top;
393
+ const targetTop = target.getBoundingClientRect().top;
394
+ if (targetTop > scrollableTop + target.clientHeight) {
395
+ scrollable.scrollTop += targetTop - scrollableTop;
396
+ }
397
+ }
398
+ target = scrollable.parentElement;
399
+ }
400
+ }
401
+ function willOpenKeyboard(target) {
402
+ return target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type) || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable;
403
+ }
404
+
405
+ // src/styles.ts
406
+ var styles = {
407
+ wrapper: {
408
+ position: "fixed",
409
+ top: 0,
410
+ bottom: 0,
411
+ left: 0,
412
+ right: 0,
413
+ overflow: "hidden",
414
+ pointerEvents: "none"
415
+ },
416
+ backdrop: {
417
+ zIndex: 1,
418
+ position: "fixed",
419
+ top: 0,
420
+ left: 0,
421
+ width: "100%",
422
+ height: "100%",
423
+ backgroundColor: "rgba(0, 0, 0, 0.2)",
424
+ touchAction: "none",
425
+ // Disable iOS body scrolling
426
+ border: "none"
427
+ },
428
+ container: {
429
+ zIndex: 2,
430
+ position: "absolute",
431
+ left: 0,
432
+ bottom: 0,
433
+ width: "100%",
434
+ backgroundColor: "#fff",
435
+ borderTopRightRadius: "8px",
436
+ borderTopLeftRadius: "8px",
437
+ boxShadow: "0px -2px 16px rgba(0, 0, 0, 0.3)",
438
+ display: "flex",
439
+ flexDirection: "column",
440
+ pointerEvents: "auto"
441
+ },
442
+ headerWrapper: {
443
+ width: "100%"
444
+ },
445
+ header: {
446
+ height: "40px",
447
+ width: "100%",
448
+ position: "relative",
449
+ display: "flex",
450
+ alignItems: "center",
451
+ justifyContent: "center"
452
+ },
453
+ indicator: {
454
+ width: "18px",
455
+ height: "4px",
456
+ borderRadius: "99px",
457
+ backgroundColor: "#ddd"
458
+ },
459
+ content: {
460
+ flexGrow: 1,
461
+ display: "flex",
462
+ flexDirection: "column",
463
+ minHeight: "0px",
464
+ position: "relative"
465
+ },
466
+ scroller: {
467
+ height: "100%",
468
+ overflowY: "auto"
469
+ }
470
+ };
471
+ var styles_default = styles;
472
+
473
+ // src/sheet.tsx
474
+ var Sheet = React2.forwardRef(
475
+ ({
476
+ onOpenStart,
477
+ onOpenEnd,
478
+ onClose,
479
+ onCloseStart,
480
+ onCloseEnd,
481
+ onSnap,
482
+ children,
483
+ disableScrollLocking = false,
484
+ isOpen,
485
+ snapPoints,
486
+ rootId,
487
+ mountPoint,
488
+ style,
489
+ detent = "full-height",
490
+ initialSnap = 0,
491
+ disableDrag = false,
492
+ prefersReducedMotion = false,
493
+ tweenConfig = DEFAULT_TWEEN_CONFIG,
494
+ ...rest
495
+ }, ref) => {
496
+ const sheetRef = React2.useRef(null);
497
+ const indicatorRotation = framerMotion.useMotionValue(0);
498
+ const { height: windowHeight } = useDimensions();
499
+ const shouldReduceMotion = framerMotion.useReducedMotion();
500
+ const reduceMotion = Boolean(prefersReducedMotion || shouldReduceMotion);
501
+ const animationOptions = {
502
+ type: "tween",
503
+ ...reduceMotion ? REDUCED_MOTION_TWEEN_CONFIG : tweenConfig
504
+ };
505
+ const y = framerMotion.useMotionValue(0);
506
+ const zIndex = framerMotion.useTransform(
507
+ y,
508
+ (value) => value + 2 >= windowHeight ? -1 : 9999999
509
+ );
510
+ const visibility = framerMotion.useTransform(
511
+ y,
512
+ (value) => value + 2 >= windowHeight ? "hidden" : "visible"
513
+ );
514
+ const callbacks = React2.useRef({
515
+ onOpenStart,
516
+ onOpenEnd,
517
+ onCloseStart,
518
+ onCloseEnd
519
+ });
520
+ useIsomorphicLayoutEffect(() => {
521
+ callbacks.current = {
522
+ onOpenStart,
523
+ onOpenEnd,
524
+ onCloseStart,
525
+ onCloseEnd
526
+ };
527
+ });
528
+ if (snapPoints) {
529
+ snapPoints = snapPoints.map((point) => {
530
+ if (point > 0 && point <= 1)
531
+ return Math.round(point * windowHeight);
532
+ return point < 0 ? windowHeight + point : point;
533
+ });
534
+ console.assert(
535
+ inDescendingOrder(snapPoints) || windowHeight === 0,
536
+ `Snap points need to be in descending order got: [${snapPoints.join(
537
+ ", "
538
+ )}]`
539
+ );
540
+ }
541
+ const onDrag = useEffectEvent((_, { delta }) => {
542
+ const velocity = y.getVelocity();
543
+ if (velocity > 0)
544
+ indicatorRotation.set(10);
545
+ if (velocity < 0)
546
+ indicatorRotation.set(-10);
547
+ y.set(Math.max(y.get() + delta.y, 0));
548
+ });
549
+ const onDragStart = useEffectEvent(() => {
550
+ const focusedElement = document.activeElement;
551
+ if (!focusedElement || !sheetRef.current)
552
+ return;
553
+ const isInput = focusedElement.tagName === "INPUT" || focusedElement.tagName === "TEXTAREA";
554
+ if (isInput && sheetRef.current.contains(focusedElement)) {
555
+ focusedElement.blur();
556
+ }
557
+ });
558
+ const onDragEnd = useEffectEvent((_, { velocity }) => {
559
+ if (velocity.y > DRAG_VELOCITY_THRESHOLD) {
560
+ onClose();
561
+ } else {
562
+ const sheetHeight = sheetRef.current.getBoundingClientRect().height;
563
+ const currentY = y.get();
564
+ let snapTo = 0;
565
+ if (snapPoints) {
566
+ const snapToValues = snapPoints.map(
567
+ (p) => sheetHeight - Math.min(p, sheetHeight)
568
+ );
569
+ if (detent === "content-height" && !snapToValues.includes(0)) {
570
+ snapToValues.unshift(0);
571
+ }
572
+ snapTo = getClosest(snapToValues, currentY);
573
+ } else if (currentY / sheetHeight > DRAG_CLOSE_THRESHOLD) {
574
+ snapTo = sheetHeight;
575
+ }
576
+ snapTo = validateSnapTo({ snapTo, sheetHeight });
577
+ void framerMotion.animate(y, snapTo, animationOptions);
578
+ if (snapPoints && onSnap) {
579
+ const snapValue = Math.abs(Math.round(snapPoints[0] - snapTo));
580
+ const snapIndex = snapPoints.indexOf(getClosest(snapPoints, snapValue));
581
+ onSnap(snapIndex);
582
+ }
583
+ const roundedSheetHeight = Math.round(sheetHeight);
584
+ const shouldClose = snapTo + 2 >= roundedSheetHeight;
585
+ if (shouldClose)
586
+ onClose();
587
+ }
588
+ indicatorRotation.set(0);
589
+ });
590
+ React2.useEffect(() => {
591
+ if (!snapPoints || !onSnap)
592
+ return;
593
+ const snapIndex = isOpen ? initialSnap : snapPoints.length - 1;
594
+ onSnap(snapIndex);
595
+ }, [isOpen]);
596
+ React2.useImperativeHandle(ref, () => ({
597
+ y,
598
+ snapTo: (snapIndex) => {
599
+ const sheetEl = sheetRef.current;
600
+ if ((snapPoints == null ? void 0 : snapPoints[snapIndex]) !== void 0 && sheetEl) {
601
+ const sheetHeight = sheetEl.getBoundingClientRect().height;
602
+ const snapPoint = snapPoints[snapIndex];
603
+ const snapTo = validateSnapTo({
604
+ snapTo: sheetHeight - snapPoint,
605
+ sheetHeight
606
+ });
607
+ void framerMotion.animate(y, snapTo, animationOptions);
608
+ if (onSnap)
609
+ onSnap(snapIndex);
610
+ if (snapTo >= sheetHeight)
611
+ onClose();
612
+ }
613
+ }
614
+ }));
615
+ useModalEffect(isOpen, rootId);
616
+ usePreventScroll({ isDisabled: disableScrollLocking || !isOpen });
617
+ const dragProps = React2.useMemo(() => {
618
+ const dragProps2 = {
619
+ drag: "y",
620
+ dragElastic: 0,
621
+ dragMomentum: false,
622
+ dragPropagation: false,
623
+ onDrag,
624
+ onDragStart,
625
+ onDragEnd
626
+ };
627
+ return disableDrag ? void 0 : dragProps2;
628
+ }, [disableDrag, windowHeight]);
629
+ const context = {
630
+ y,
631
+ sheetRef,
632
+ isOpen,
633
+ initialSnap,
634
+ snapPoints,
635
+ detent,
636
+ indicatorRotation,
637
+ callbacks,
638
+ dragProps,
639
+ windowHeight,
640
+ animationOptions,
641
+ reduceMotion,
642
+ disableDrag
643
+ };
644
+ const sheet = /* @__PURE__ */ React2__default.default.createElement(SheetContext.Provider, { value: context }, /* @__PURE__ */ React2__default.default.createElement(
645
+ framerMotion.motion.div,
646
+ {
647
+ ...rest,
648
+ ref,
649
+ style: { ...styles_default.wrapper, zIndex, visibility, ...style }
650
+ },
651
+ /* @__PURE__ */ React2__default.default.createElement(framerMotion.AnimatePresence, null, isOpen ? /* @__PURE__ */ React2__default.default.createElement(SheetScrollerContextProvider, null, React2.Children.map(
652
+ children,
653
+ (child, i) => React2.cloneElement(child, { key: `sheet-child-${i}` })
654
+ )) : null)
655
+ ));
656
+ if (IS_SSR)
657
+ return sheet;
658
+ return reactDom.createPortal(sheet, mountPoint ?? document.body);
659
+ }
660
+ );
661
+ Sheet.displayName = "Sheet";
662
+ var sheet_default = Sheet;
663
+ var SheetContainer = React2.forwardRef(
664
+ ({ children, style = {}, className = "", ...rest }, ref) => {
665
+ const {
666
+ y,
667
+ isOpen,
668
+ callbacks,
669
+ snapPoints,
670
+ initialSnap = 0,
671
+ sheetRef,
672
+ windowHeight,
673
+ detent,
674
+ animationOptions,
675
+ reduceMotion
676
+ } = useSheetContext();
677
+ const { handleAnimationComplete } = useEventCallbacks(isOpen, callbacks);
678
+ const initialY = snapPoints ? snapPoints[0] - snapPoints[initialSnap] : 0;
679
+ const maxSnapHeight = snapPoints ? snapPoints[0] : null;
680
+ const height = maxSnapHeight !== null ? `min(${maxSnapHeight}px, ${MAX_HEIGHT})` : MAX_HEIGHT;
681
+ return /* @__PURE__ */ React2__default.default.createElement(
682
+ framerMotion.motion.div,
683
+ {
684
+ ...rest,
685
+ ref: mergeRefs([sheetRef, ref]),
686
+ className: `react-modal-sheet-container ${className}`,
687
+ style: {
688
+ ...styles_default.container,
689
+ ...style,
690
+ ...detent === "full-height" && { height },
691
+ ...detent === "content-height" && { maxHeight: height },
692
+ y
693
+ },
694
+ initial: reduceMotion ? false : { y: windowHeight },
695
+ animate: { y: initialY, transition: animationOptions },
696
+ exit: { y: windowHeight, transition: animationOptions },
697
+ onAnimationComplete: handleAnimationComplete
698
+ },
699
+ children
700
+ );
701
+ }
702
+ );
703
+ SheetContainer.displayName = "SheetContainer";
704
+ var SheetContainer_default = SheetContainer;
705
+ var SheetContent = React2.forwardRef(
706
+ ({ children, style, disableDrag, className = "", ...rest }, ref) => {
707
+ const sheetContext = useSheetContext();
708
+ const sheetScrollerContext = useSheetScrollerContext();
709
+ const { constraintsRef, onMeasureDragConstraints } = useDragConstraints();
710
+ const dragProps = disableDrag || sheetScrollerContext.disableDrag ? void 0 : sheetContext.dragProps;
711
+ return /* @__PURE__ */ React2__default.default.createElement(
712
+ framerMotion.motion.div,
713
+ {
714
+ ...rest,
715
+ ref: mergeRefs([ref, constraintsRef]),
716
+ className: `react-modal-sheet-content ${className}`,
717
+ style: { ...styles_default.content, ...style },
718
+ ...dragProps,
719
+ dragConstraints: constraintsRef,
720
+ onMeasureDragConstraints
721
+ },
722
+ children
723
+ );
724
+ }
725
+ );
726
+ SheetContent.displayName = "SheetContent";
727
+ var SheetContent_default = SheetContent;
728
+ var SheetHeader = React2.forwardRef(
729
+ ({ children, style, disableDrag, ...rest }, ref) => {
730
+ const { indicatorRotation, dragProps } = useSheetContext();
731
+ const { constraintsRef, onMeasureDragConstraints } = useDragConstraints();
732
+ const _dragProps = disableDrag ? void 0 : dragProps;
733
+ const indicator1Transform = framerMotion.useTransform(
734
+ indicatorRotation,
735
+ (r) => `translateX(2px) rotate(${r}deg)`
736
+ );
737
+ const indicator2Transform = framerMotion.useTransform(
738
+ indicatorRotation,
739
+ (r) => `translateX(-2px) rotate(${-1 * r}deg)`
740
+ );
741
+ return /* @__PURE__ */ React2__default.default.createElement(
742
+ framerMotion.motion.div,
743
+ {
744
+ ...rest,
745
+ ref: mergeRefs([ref, constraintsRef]),
746
+ style: { ...styles_default.headerWrapper, ...style },
747
+ ..._dragProps,
748
+ dragConstraints: constraintsRef,
749
+ onMeasureDragConstraints
750
+ },
751
+ children || /* @__PURE__ */ React2__default.default.createElement("div", { className: "react-modal-sheet-header", style: styles_default.header }, /* @__PURE__ */ React2__default.default.createElement(
752
+ framerMotion.motion.span,
753
+ {
754
+ className: "react-modal-sheet-drag-indicator",
755
+ style: { ...styles_default.indicator, transform: indicator1Transform }
756
+ }
757
+ ), /* @__PURE__ */ React2__default.default.createElement(
758
+ framerMotion.motion.span,
759
+ {
760
+ className: "react-modal-sheet-drag-indicator",
761
+ style: { ...styles_default.indicator, transform: indicator2Transform }
762
+ }
763
+ ))
764
+ );
765
+ }
766
+ );
767
+ SheetHeader.displayName = "SheetHeader";
768
+ var SheetHeader_default = SheetHeader;
769
+ var isClickable = (props) => !!props.onClick || !!props.onTap;
770
+ var SheetBackdrop = React2.forwardRef(
771
+ ({ style = {}, className = "", ...rest }, ref) => {
772
+ const Comp = isClickable(rest) ? framerMotion.motion.button : framerMotion.motion.div;
773
+ const pointerEvents = isClickable(rest) ? "auto" : "none";
774
+ return /* @__PURE__ */ React2__default.default.createElement(
775
+ Comp,
776
+ {
777
+ ...rest,
778
+ ref,
779
+ className: `react-modal-sheet-backdrop ${className}`,
780
+ style: { ...styles_default.backdrop, ...style, pointerEvents },
781
+ initial: { opacity: 0 },
782
+ animate: { opacity: 1 },
783
+ exit: { opacity: 0 }
784
+ }
785
+ );
786
+ }
787
+ );
788
+ SheetBackdrop.displayName = "SheetBackdrop";
789
+ var SheetBackdrop_default = SheetBackdrop;
790
+ var SheetScroller = React2.forwardRef(
791
+ ({ draggableAt = "top", children, style, className = "", ...rest }, ref) => {
792
+ const sheetScrollerContext = useSheetScrollerContext();
793
+ function determineDragState(element) {
794
+ const { scrollTop, scrollHeight, clientHeight } = element;
795
+ const isScrollable = scrollHeight > clientHeight;
796
+ if (!isScrollable)
797
+ return;
798
+ const isAtTop = scrollTop <= 0;
799
+ const isAtBottom = scrollHeight - scrollTop === clientHeight;
800
+ const shouldEnable = draggableAt === "top" && isAtTop || draggableAt === "bottom" && isAtBottom || draggableAt === "both" && (isAtTop || isAtBottom);
801
+ if (shouldEnable) {
802
+ sheetScrollerContext.setDragEnabled();
803
+ } else {
804
+ sheetScrollerContext.setDragDisabled();
805
+ }
806
+ }
807
+ function onScroll(e) {
808
+ determineDragState(e.currentTarget);
809
+ }
810
+ function onTouchStart(e) {
811
+ determineDragState(e.currentTarget);
812
+ }
813
+ const scrollProps = isTouchDevice() ? { onScroll, onTouchStart } : void 0;
814
+ return /* @__PURE__ */ React2__default.default.createElement(
815
+ "div",
816
+ {
817
+ ...rest,
818
+ ref,
819
+ className: `react-modal-sheet-scroller ${className}`,
820
+ style: { ...styles_default.scroller, ...style },
821
+ ...scrollProps
822
+ },
823
+ children
824
+ );
825
+ }
826
+ );
827
+ SheetScroller.displayName = "SheetScroller";
828
+ var SheetScroller_default = SheetScroller;
829
+
830
+ // src/index.tsx
831
+ var _SheetCompound = sheet_default;
832
+ _SheetCompound.Container = SheetContainer_default;
833
+ _SheetCompound.Header = SheetHeader_default;
834
+ _SheetCompound.Content = SheetContent_default;
835
+ _SheetCompound.Backdrop = SheetBackdrop_default;
836
+ _SheetCompound.Scroller = SheetScroller_default;
837
+ var Sheet2 = _SheetCompound;
838
+
839
+ exports.Sheet = Sheet2;
840
+ //# sourceMappingURL=out.js.map
841
+ //# sourceMappingURL=index.js.map