react-modal-sheet 4.4.0 → 5.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/README.md +332 -188
- package/dist/index.d.mts +51 -39
- package/dist/index.d.ts +51 -39
- package/dist/index.js +854 -585
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +847 -579
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -3
- package/src/SheetBackdrop.tsx +19 -6
- package/src/SheetContainer.tsx +34 -25
- package/src/SheetContent.tsx +77 -14
- package/src/SheetDragIndicator.tsx +52 -0
- package/src/SheetHeader.tsx +30 -30
- package/src/constants.ts +5 -3
- package/src/context.tsx +2 -42
- package/src/hooks/use-dimensions.ts +4 -4
- package/src/hooks/use-drag-constraints.ts +3 -3
- package/src/hooks/use-modal-effect.ts +19 -23
- package/src/hooks/use-resize-observer.ts +31 -0
- package/src/hooks/use-scroll-position.ts +72 -0
- package/src/hooks/use-sheet-state.ts +63 -0
- package/src/hooks/use-virtual-keyboard.ts +153 -0
- package/src/index.tsx +14 -10
- package/src/sheet.tsx +247 -209
- package/src/snap.ts +226 -0
- package/src/styles.ts +94 -53
- package/src/types.tsx +83 -79
- package/src/utils.ts +8 -149
- package/src/SheetScroller.tsx +0 -96
- package/src/hooks/use-event-callbacks.ts +0 -44
package/src/sheet.tsx
CHANGED
|
@@ -1,82 +1,94 @@
|
|
|
1
|
-
import { createPortal } from 'react-dom';
|
|
2
|
-
|
|
3
|
-
import React, {
|
|
4
|
-
Children,
|
|
5
|
-
cloneElement,
|
|
6
|
-
forwardRef,
|
|
7
|
-
useEffect,
|
|
8
|
-
useImperativeHandle,
|
|
9
|
-
useMemo,
|
|
10
|
-
useRef,
|
|
11
|
-
} from 'react';
|
|
12
|
-
|
|
13
1
|
import {
|
|
2
|
+
type DragHandler,
|
|
3
|
+
type Transition,
|
|
14
4
|
animate,
|
|
15
|
-
AnimatePresence,
|
|
16
5
|
motion,
|
|
17
|
-
type PanInfo,
|
|
18
|
-
type Transition,
|
|
19
6
|
useMotionValue,
|
|
20
7
|
useReducedMotion,
|
|
21
8
|
useTransform,
|
|
22
9
|
} from 'motion/react';
|
|
10
|
+
import React, {
|
|
11
|
+
forwardRef,
|
|
12
|
+
useImperativeHandle,
|
|
13
|
+
useRef,
|
|
14
|
+
useState,
|
|
15
|
+
} from 'react';
|
|
16
|
+
import { createPortal } from 'react-dom';
|
|
17
|
+
import useMeasure from 'react-use-measure';
|
|
23
18
|
|
|
24
19
|
import {
|
|
25
|
-
REDUCED_MOTION_TWEEN_CONFIG,
|
|
26
|
-
DEFAULT_TWEEN_CONFIG,
|
|
27
20
|
DEFAULT_DRAG_CLOSE_THRESHOLD,
|
|
28
21
|
DEFAULT_DRAG_VELOCITY_THRESHOLD,
|
|
22
|
+
DEFAULT_TWEEN_CONFIG,
|
|
29
23
|
IS_SSR,
|
|
24
|
+
REDUCED_MOTION_TWEEN_CONFIG,
|
|
30
25
|
} from './constants';
|
|
31
|
-
|
|
32
|
-
import {
|
|
33
|
-
getSheetHeight,
|
|
34
|
-
getSnapY,
|
|
35
|
-
getSnapPoints,
|
|
36
|
-
getClosestSnapPoint,
|
|
37
|
-
} from './utils';
|
|
38
|
-
|
|
39
|
-
import { type SheetContextType, type SheetProps } from './types';
|
|
40
|
-
import { SheetScrollerContextProvider, SheetContext } from './context';
|
|
41
|
-
import { styles } from './styles';
|
|
42
|
-
import { useModalEffect } from './hooks/use-modal-effect';
|
|
26
|
+
import { SheetContext } from './context';
|
|
43
27
|
import { useDimensions } from './hooks/use-dimensions';
|
|
44
|
-
import {
|
|
45
|
-
import { useStableCallback } from './hooks/use-stable-callback';
|
|
28
|
+
import { useModalEffect } from './hooks/use-modal-effect';
|
|
46
29
|
import { usePreventScroll } from './hooks/use-prevent-scroll';
|
|
30
|
+
import { useSheetState } from './hooks/use-sheet-state';
|
|
31
|
+
import { useStableCallback } from './hooks/use-stable-callback';
|
|
32
|
+
import { useVirtualKeyboard } from './hooks/use-virtual-keyboard';
|
|
33
|
+
import {
|
|
34
|
+
computeSnapPoints,
|
|
35
|
+
handleHighVelocityDrag,
|
|
36
|
+
handleLowVelocityDrag,
|
|
37
|
+
} from './snap';
|
|
38
|
+
import { styles } from './styles';
|
|
39
|
+
import { type SheetContextType, type SheetProps } from './types';
|
|
40
|
+
import { applyStyles } from './utils';
|
|
47
41
|
|
|
48
42
|
export const Sheet = forwardRef<any, SheetProps>(
|
|
49
43
|
(
|
|
50
44
|
{
|
|
51
|
-
|
|
52
|
-
onOpenEnd,
|
|
53
|
-
onClose,
|
|
54
|
-
onCloseStart,
|
|
55
|
-
onCloseEnd,
|
|
56
|
-
onSnap,
|
|
45
|
+
avoidKeyboard = true,
|
|
57
46
|
children,
|
|
47
|
+
className = '',
|
|
48
|
+
detent = 'default',
|
|
49
|
+
disableDismiss = false,
|
|
50
|
+
disableDrag: disableDragProp = false,
|
|
58
51
|
disableScrollLocking = false,
|
|
52
|
+
dragCloseThreshold = DEFAULT_DRAG_CLOSE_THRESHOLD,
|
|
53
|
+
dragVelocityThreshold = DEFAULT_DRAG_VELOCITY_THRESHOLD,
|
|
54
|
+
initialSnap,
|
|
59
55
|
isOpen,
|
|
60
|
-
snapPoints: snapPointsProp,
|
|
61
|
-
rootId,
|
|
62
56
|
modalEffectRootId,
|
|
57
|
+
modalEffectThreshold,
|
|
63
58
|
mountPoint,
|
|
64
|
-
style,
|
|
65
|
-
detent = 'full-height',
|
|
66
|
-
initialSnap = 0,
|
|
67
|
-
disableDrag = false,
|
|
68
59
|
prefersReducedMotion = false,
|
|
60
|
+
snapPoints: snapPointsProp,
|
|
61
|
+
style,
|
|
69
62
|
tweenConfig = DEFAULT_TWEEN_CONFIG,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
unstyled = false,
|
|
64
|
+
onOpenStart,
|
|
65
|
+
onOpenEnd,
|
|
66
|
+
onClose,
|
|
67
|
+
onCloseStart,
|
|
68
|
+
onCloseEnd,
|
|
69
|
+
onSnap,
|
|
70
|
+
onDrag: onDragProp,
|
|
71
|
+
onDragStart: onDragStartProp,
|
|
72
|
+
onDragEnd: onDragEndProp,
|
|
73
73
|
...rest
|
|
74
74
|
},
|
|
75
75
|
ref
|
|
76
76
|
) => {
|
|
77
|
+
const [sheetBoundsRef, sheetBounds] = useMeasure();
|
|
77
78
|
const sheetRef = useRef<HTMLDivElement>(null);
|
|
79
|
+
const sheetHeight = Math.round(sheetBounds.height);
|
|
80
|
+
const [currentSnap, setCurrentSnap] = useState(initialSnap);
|
|
81
|
+
const snapPoints =
|
|
82
|
+
snapPointsProp && sheetHeight > 0
|
|
83
|
+
? computeSnapPoints({ sheetHeight, snapPointsProp })
|
|
84
|
+
: [];
|
|
85
|
+
|
|
86
|
+
const { windowHeight } = useDimensions();
|
|
87
|
+
const closedY = sheetHeight > 0 ? sheetHeight : windowHeight;
|
|
88
|
+
const y = useMotionValue(closedY);
|
|
89
|
+
const yInverted = useTransform(y, (val) => Math.max(sheetHeight - val, 0));
|
|
78
90
|
const indicatorRotation = useMotionValue(0);
|
|
79
|
-
|
|
91
|
+
|
|
80
92
|
const shouldReduceMotion = useReducedMotion();
|
|
81
93
|
const reduceMotion = Boolean(prefersReducedMotion || shouldReduceMotion);
|
|
82
94
|
const animationOptions: Transition = {
|
|
@@ -84,66 +96,67 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
84
96
|
...(reduceMotion ? REDUCED_MOTION_TWEEN_CONFIG : tweenConfig),
|
|
85
97
|
};
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
const keyboard = useVirtualKeyboard({
|
|
100
|
+
isEnabled: isOpen && avoidKeyboard,
|
|
101
|
+
containerRef: sheetRef,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Disable drag if the keyboard is open to avoid weird behavior
|
|
105
|
+
const disableDrag = keyboard.isKeyboardOpen || disableDragProp;
|
|
91
106
|
|
|
92
107
|
// +2 for tolerance in case the animated value is slightly off
|
|
93
|
-
const zIndex = useTransform(y, (
|
|
94
|
-
|
|
108
|
+
const zIndex = useTransform(y, (val) =>
|
|
109
|
+
val + 2 >= closedY ? -1 : (style?.zIndex ?? 9999)
|
|
95
110
|
);
|
|
96
|
-
const visibility = useTransform(y, (
|
|
97
|
-
|
|
111
|
+
const visibility = useTransform(y, (val) =>
|
|
112
|
+
val + 2 >= closedY ? 'hidden' : 'visible'
|
|
98
113
|
);
|
|
99
114
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
onOpenStart,
|
|
104
|
-
onOpenEnd,
|
|
105
|
-
onCloseStart,
|
|
106
|
-
onCloseEnd,
|
|
115
|
+
const updateSnap = useStableCallback((snapIndex: number) => {
|
|
116
|
+
setCurrentSnap(snapIndex);
|
|
117
|
+
onSnap?.(snapIndex);
|
|
107
118
|
});
|
|
108
119
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
const getSnapPoint = useStableCallback((snapIndex: number) => {
|
|
121
|
+
if (snapPointsProp && snapPoints) {
|
|
122
|
+
if (snapIndex < 0 || snapIndex >= snapPoints.length) {
|
|
123
|
+
console.warn(
|
|
124
|
+
`Invalid snap index ${snapIndex}. Snap points are: [${snapPointsProp.join(', ')}] and their computed values are: [${snapPoints
|
|
125
|
+
.map((point) => point.snapValue)
|
|
126
|
+
.join(', ')}]`
|
|
127
|
+
);
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return snapPoints[snapIndex];
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
116
133
|
});
|
|
117
134
|
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
* Make sure the user cannot drag the sheet beyond the upmost snap point
|
|
123
|
-
* if the `snapPoints` prop is provided.
|
|
124
|
-
*/
|
|
125
|
-
if (snapPointsProp) {
|
|
126
|
-
const sheetHeight = getSheetHeight(sheetRef);
|
|
127
|
-
const snapPoints = getSnapPoints({ snapPointsProp, sheetHeight });
|
|
128
|
-
const topSnapPoint = sheetHeight - snapPoints[0];
|
|
129
|
-
|
|
130
|
-
if (info.delta.y < 0 && currentY <= topSnapPoint) {
|
|
131
|
-
y.set(topSnapPoint);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
135
|
+
const snapTo = useStableCallback(async (snapIndex: number) => {
|
|
136
|
+
if (!snapPointsProp) {
|
|
137
|
+
console.warn('Snapping is not possible without `snapPoints` prop.');
|
|
138
|
+
return;
|
|
134
139
|
}
|
|
135
140
|
|
|
136
|
-
|
|
137
|
-
const velocity = y.getVelocity();
|
|
141
|
+
const snapPoint = getSnapPoint(snapIndex);
|
|
138
142
|
|
|
139
|
-
if (
|
|
140
|
-
|
|
143
|
+
if (snapPoint === null) {
|
|
144
|
+
console.warn(`Invalid snap index ${snapIndex}.`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
141
147
|
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
if (snapIndex === 0) {
|
|
149
|
+
onClose();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
await animate(y, snapPoint.snapValueY, {
|
|
154
|
+
...animationOptions,
|
|
155
|
+
onComplete: () => updateSnap(snapIndex),
|
|
156
|
+
});
|
|
144
157
|
});
|
|
145
158
|
|
|
146
|
-
const
|
|
159
|
+
const blurActiveInput = useStableCallback(() => {
|
|
147
160
|
// Find focused input inside the sheet and blur it when dragging starts
|
|
148
161
|
// to prevent a weird ghost caret "bug" on mobile
|
|
149
162
|
const focusedElement = document.activeElement as HTMLElement | null;
|
|
@@ -159,148 +172,175 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
159
172
|
}
|
|
160
173
|
});
|
|
161
174
|
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
// User flicked the sheet down
|
|
165
|
-
onClose();
|
|
166
|
-
} else {
|
|
167
|
-
const sheetHeight = getSheetHeight(sheetRef);
|
|
168
|
-
const currentY = y.get();
|
|
175
|
+
const onDrag = useStableCallback<DragHandler>((event, info) => {
|
|
176
|
+
onDragProp?.(event, info);
|
|
169
177
|
|
|
170
|
-
|
|
178
|
+
const currentY = y.get();
|
|
171
179
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
180
|
+
// Update drag indicator rotation based on drag velocity
|
|
181
|
+
const velocity = y.getVelocity();
|
|
182
|
+
if (velocity > 0) indicatorRotation.set(10);
|
|
183
|
+
if (velocity < 0) indicatorRotation.set(-10);
|
|
175
184
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
currentY,
|
|
180
|
-
sheetHeight,
|
|
181
|
-
detent,
|
|
182
|
-
});
|
|
185
|
+
// Make sure user cannot drag beyond the top of the sheet
|
|
186
|
+
y.set(Math.max(currentY + info.delta.y, 0));
|
|
187
|
+
});
|
|
183
188
|
|
|
184
|
-
|
|
189
|
+
const onDragStart = useStableCallback<DragHandler>((event, info) => {
|
|
190
|
+
blurActiveInput();
|
|
191
|
+
onDragStartProp?.(event, info);
|
|
192
|
+
});
|
|
185
193
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
// Close if dragged over enough far
|
|
190
|
-
yTo = sheetHeight;
|
|
191
|
-
}
|
|
194
|
+
const onDragEnd = useStableCallback<DragHandler>((event, info) => {
|
|
195
|
+
blurActiveInput();
|
|
196
|
+
onDragEndProp?.(event, info);
|
|
192
197
|
|
|
193
|
-
|
|
194
|
-
animate(y, yTo, animationOptions);
|
|
198
|
+
const currentY = y.get();
|
|
195
199
|
|
|
196
|
-
|
|
197
|
-
if (yTo + 1 >= sheetHeight) {
|
|
198
|
-
onClose();
|
|
199
|
-
}
|
|
200
|
-
}
|
|
200
|
+
let yTo = 0;
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
});
|
|
202
|
+
const currentSnapPoint =
|
|
203
|
+
currentSnap !== undefined ? getSnapPoint(currentSnap) : null;
|
|
205
204
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}, [isOpen]);
|
|
205
|
+
if (currentSnapPoint) {
|
|
206
|
+
const dragOffsetDirection = info.offset.y > 0 ? 'down' : 'up';
|
|
207
|
+
const dragVelocityDirection = info.velocity.y > 0 ? 'down' : 'up';
|
|
208
|
+
const isHighVelocity =
|
|
209
|
+
Math.abs(info.velocity.y) > dragVelocityThreshold;
|
|
212
210
|
|
|
213
|
-
|
|
214
|
-
useEffect(() => {
|
|
215
|
-
if (!isOpen) return; // let `AnimatePresence` handle the exit animation
|
|
211
|
+
let result: { yTo: number; snapIndex: number | undefined };
|
|
216
212
|
|
|
217
|
-
|
|
213
|
+
if (isHighVelocity) {
|
|
214
|
+
result = handleHighVelocityDrag({
|
|
215
|
+
snapPoints,
|
|
216
|
+
dragDirection: dragVelocityDirection,
|
|
217
|
+
});
|
|
218
|
+
} else {
|
|
219
|
+
result = handleLowVelocityDrag({
|
|
220
|
+
currentSnapPoint,
|
|
221
|
+
currentY,
|
|
222
|
+
dragDirection: dragOffsetDirection,
|
|
223
|
+
snapPoints,
|
|
224
|
+
velocity: info.velocity.y,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
218
227
|
|
|
219
|
-
|
|
220
|
-
const snapIndex = initialSnap;
|
|
221
|
-
const sheetHeight = getSheetHeight(sheetRef);
|
|
222
|
-
const snapPoints = getSnapPoints({ snapPointsProp, sheetHeight });
|
|
223
|
-
const snapY = getSnapY({ sheetHeight, snapPoints, snapIndex });
|
|
228
|
+
yTo = result.yTo;
|
|
224
229
|
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
// If disableDismiss is true, prevent closing via gesture
|
|
231
|
+
if (disableDismiss && yTo + 1 >= sheetHeight) {
|
|
232
|
+
// Use the bottom-most open snap point
|
|
233
|
+
const bottomSnapPoint = snapPoints.find((s) => s.snapValue > 0);
|
|
234
|
+
|
|
235
|
+
if (bottomSnapPoint) {
|
|
236
|
+
yTo = bottomSnapPoint.snapValueY;
|
|
237
|
+
updateSnap(bottomSnapPoint.snapIndex);
|
|
238
|
+
} else {
|
|
239
|
+
// If no open snap points available, stay at current position
|
|
240
|
+
yTo = currentY;
|
|
241
|
+
}
|
|
242
|
+
} else if (result.snapIndex !== undefined) {
|
|
243
|
+
updateSnap(result.snapIndex);
|
|
244
|
+
}
|
|
245
|
+
} else if (
|
|
246
|
+
info.velocity.y > dragVelocityThreshold ||
|
|
247
|
+
currentY > sheetHeight * dragCloseThreshold
|
|
248
|
+
) {
|
|
249
|
+
// Close the sheet if dragged past the threshold or if the velocity is high enough
|
|
250
|
+
// But only if disableDismiss is false
|
|
251
|
+
if (disableDismiss) {
|
|
252
|
+
// If disableDismiss, snap back to the open position
|
|
253
|
+
yTo = 0;
|
|
254
|
+
} else {
|
|
255
|
+
yTo = closedY;
|
|
227
256
|
}
|
|
228
257
|
}
|
|
229
258
|
|
|
259
|
+
// Update the spring value so that the sheet is animated to the snap point
|
|
230
260
|
animate(y, yTo, animationOptions);
|
|
231
|
-
}, [isOpen]);
|
|
232
|
-
|
|
233
|
-
useImperativeHandle(ref, () => ({
|
|
234
|
-
y,
|
|
235
|
-
snapTo: (snapIndex: number) => {
|
|
236
|
-
if (!snapPointsProp) {
|
|
237
|
-
console.warn('Snapping is not possible without `snapPoints` prop.');
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
261
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
262
|
+
// +1px for imprecision tolerance
|
|
263
|
+
// Only call onClose if disableDismiss is false or if we're actually closing
|
|
264
|
+
if (yTo + 1 >= sheetHeight && !disableDismiss) {
|
|
265
|
+
onClose();
|
|
266
|
+
}
|
|
244
267
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
268
|
+
// Reset indicator rotation after dragging
|
|
269
|
+
indicatorRotation.set(0);
|
|
270
|
+
});
|
|
248
271
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
},
|
|
272
|
+
useImperativeHandle(ref, () => ({
|
|
273
|
+
y,
|
|
274
|
+
yInverted,
|
|
275
|
+
height: sheetHeight,
|
|
276
|
+
snapTo,
|
|
255
277
|
}));
|
|
256
278
|
|
|
257
|
-
if (rootId) {
|
|
258
|
-
console.warn(
|
|
259
|
-
'The `rootId` prop is deprecated and will be removed in the next major version. Use `modalEffectRootId` instead.'
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
279
|
useModalEffect({
|
|
264
280
|
y,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
281
|
+
detent,
|
|
282
|
+
sheetHeight,
|
|
283
|
+
snapPoints,
|
|
284
|
+
rootId: modalEffectRootId,
|
|
268
285
|
startThreshold: modalEffectThreshold,
|
|
269
286
|
});
|
|
270
287
|
|
|
271
|
-
|
|
272
|
-
|
|
288
|
+
/**
|
|
289
|
+
* Motion should handle body scroll locking but it's not working properly on iOS.
|
|
290
|
+
* Scroll locking from React Aria seems to work much better 🤷♂️
|
|
291
|
+
*/
|
|
273
292
|
usePreventScroll({
|
|
274
293
|
isDisabled: disableScrollLocking || !isOpen,
|
|
275
294
|
});
|
|
276
295
|
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
dragMomentum: false,
|
|
282
|
-
dragPropagation: false,
|
|
283
|
-
onDrag,
|
|
284
|
-
onDragStart,
|
|
285
|
-
onDragEnd,
|
|
286
|
-
};
|
|
296
|
+
const state = useSheetState({
|
|
297
|
+
isOpen,
|
|
298
|
+
onOpen: async () => {
|
|
299
|
+
onOpenStart?.();
|
|
287
300
|
|
|
288
|
-
|
|
289
|
-
|
|
301
|
+
const initialSnapPoint =
|
|
302
|
+
initialSnap !== undefined ? getSnapPoint(initialSnap) : null;
|
|
303
|
+
|
|
304
|
+
const yTo = initialSnapPoint?.snapValueY ?? 0;
|
|
305
|
+
|
|
306
|
+
await animate(y, yTo, animationOptions);
|
|
307
|
+
|
|
308
|
+
if (initialSnap !== undefined) {
|
|
309
|
+
updateSnap(initialSnap);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
onOpenEnd?.();
|
|
313
|
+
},
|
|
314
|
+
onClosing: async () => {
|
|
315
|
+
onCloseStart?.();
|
|
316
|
+
|
|
317
|
+
await animate(y, closedY, animationOptions);
|
|
318
|
+
|
|
319
|
+
onCloseEnd?.();
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
const dragProps: SheetContextType['dragProps'] = {
|
|
324
|
+
drag: 'y',
|
|
325
|
+
dragElastic: 0,
|
|
326
|
+
dragMomentum: false,
|
|
327
|
+
dragPropagation: false,
|
|
328
|
+
onDrag,
|
|
329
|
+
onDragStart,
|
|
330
|
+
onDragEnd,
|
|
331
|
+
};
|
|
290
332
|
|
|
291
333
|
const context: SheetContextType = {
|
|
292
|
-
|
|
293
|
-
sheetRef,
|
|
294
|
-
isOpen,
|
|
295
|
-
initialSnap,
|
|
334
|
+
currentSnap,
|
|
296
335
|
detent,
|
|
297
|
-
indicatorRotation,
|
|
298
|
-
callbacks,
|
|
299
|
-
dragProps,
|
|
300
|
-
windowHeight,
|
|
301
|
-
animationOptions,
|
|
302
|
-
reduceMotion,
|
|
303
336
|
disableDrag,
|
|
337
|
+
dragProps,
|
|
338
|
+
indicatorRotation,
|
|
339
|
+
avoidKeyboard,
|
|
340
|
+
sheetBoundsRef,
|
|
341
|
+
sheetRef,
|
|
342
|
+
unstyled,
|
|
343
|
+
y,
|
|
304
344
|
};
|
|
305
345
|
|
|
306
346
|
const sheet = (
|
|
@@ -308,18 +348,16 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
308
348
|
<motion.div
|
|
309
349
|
{...rest}
|
|
310
350
|
ref={ref}
|
|
311
|
-
|
|
351
|
+
data-sheet-state={state}
|
|
352
|
+
className={`react-modal-sheet-root ${className}`}
|
|
353
|
+
style={{
|
|
354
|
+
...applyStyles(styles.root, unstyled),
|
|
355
|
+
zIndex,
|
|
356
|
+
visibility,
|
|
357
|
+
...style,
|
|
358
|
+
}}
|
|
312
359
|
>
|
|
313
|
-
|
|
314
|
-
{/* NOTE: AnimatePresence requires us to set keys to children */}
|
|
315
|
-
{isOpen ? (
|
|
316
|
-
<SheetScrollerContextProvider>
|
|
317
|
-
{Children.map(children, (child: any, i) =>
|
|
318
|
-
cloneElement(child, { key: `sheet-child-${i}` })
|
|
319
|
-
)}
|
|
320
|
-
</SheetScrollerContextProvider>
|
|
321
|
-
) : null}
|
|
322
|
-
</AnimatePresence>
|
|
360
|
+
{state !== 'closed' ? children : null}
|
|
323
361
|
</motion.div>
|
|
324
362
|
</SheetContext.Provider>
|
|
325
363
|
);
|