react-modal-sheet 4.2.0 → 4.4.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 +79 -4
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +83 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +83 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/SheetScroller.tsx +49 -18
- package/src/sheet.tsx +33 -27
- package/src/styles.ts +2 -0
- package/src/types.tsx +6 -4
- package/src/utils.ts +34 -0
package/src/sheet.tsx
CHANGED
|
@@ -30,11 +30,10 @@ import {
|
|
|
30
30
|
} from './constants';
|
|
31
31
|
|
|
32
32
|
import {
|
|
33
|
-
getClosest,
|
|
34
33
|
getSheetHeight,
|
|
35
34
|
getSnapY,
|
|
36
35
|
getSnapPoints,
|
|
37
|
-
|
|
36
|
+
getClosestSnapPoint,
|
|
38
37
|
} from './utils';
|
|
39
38
|
|
|
40
39
|
import { type SheetContextType, type SheetProps } from './types';
|
|
@@ -116,7 +115,24 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
116
115
|
};
|
|
117
116
|
});
|
|
118
117
|
|
|
119
|
-
const onDrag = useStableCallback((_,
|
|
118
|
+
const onDrag = useStableCallback((_: PointerEvent, info: PanInfo) => {
|
|
119
|
+
const currentY = y.get();
|
|
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
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
120
136
|
// Update drag indicator rotation based on drag velocity
|
|
121
137
|
const velocity = y.getVelocity();
|
|
122
138
|
|
|
@@ -124,7 +140,7 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
124
140
|
if (velocity < 0) indicatorRotation.set(-10);
|
|
125
141
|
|
|
126
142
|
// Make sure user cannot drag beyond the top of the sheet
|
|
127
|
-
y.set(Math.max(
|
|
143
|
+
y.set(Math.max(currentY + info.delta.y, 0));
|
|
128
144
|
});
|
|
129
145
|
|
|
130
146
|
const onDragStart = useStableCallback(() => {
|
|
@@ -158,25 +174,15 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
158
174
|
: undefined;
|
|
159
175
|
|
|
160
176
|
if (snapPoints) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
// Allow snapping to the top of the sheet if detent is set to `content-height`
|
|
167
|
-
if (detent === 'content-height' && !snapInverse.includes(0)) {
|
|
168
|
-
snapInverse.unshift(0);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Get the closest snap point
|
|
172
|
-
const snapTo = getClosest(snapInverse, currentY);
|
|
173
|
-
const snapIndex = snapInverse.indexOf(snapTo);
|
|
174
|
-
|
|
175
|
-
yTo = validateSnapTo({
|
|
176
|
-
snapTo: getClosest(snapInverse, currentY),
|
|
177
|
+
const { snapY, snapIndex } = getClosestSnapPoint({
|
|
178
|
+
snapPoints,
|
|
179
|
+
currentY,
|
|
177
180
|
sheetHeight,
|
|
181
|
+
detent,
|
|
178
182
|
});
|
|
179
183
|
|
|
184
|
+
yTo = snapY;
|
|
185
|
+
|
|
180
186
|
// This happens before calling `animate` but it doesn't really matter
|
|
181
187
|
onSnap?.(snapIndex);
|
|
182
188
|
} else if (currentY / sheetHeight > dragCloseThreshold) {
|
|
@@ -214,10 +220,10 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
214
220
|
const snapIndex = initialSnap;
|
|
215
221
|
const sheetHeight = getSheetHeight(sheetRef);
|
|
216
222
|
const snapPoints = getSnapPoints({ snapPointsProp, sheetHeight });
|
|
217
|
-
const
|
|
223
|
+
const snapY = getSnapY({ sheetHeight, snapPoints, snapIndex });
|
|
218
224
|
|
|
219
|
-
if (
|
|
220
|
-
yTo =
|
|
225
|
+
if (snapY !== null) {
|
|
226
|
+
yTo = snapY;
|
|
221
227
|
}
|
|
222
228
|
}
|
|
223
229
|
|
|
@@ -234,14 +240,14 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
234
240
|
|
|
235
241
|
const sheetHeight = getSheetHeight(sheetRef);
|
|
236
242
|
const snapPoints = getSnapPoints({ snapPointsProp, sheetHeight });
|
|
237
|
-
const
|
|
243
|
+
const snapY = getSnapY({ sheetHeight, snapPoints, snapIndex });
|
|
238
244
|
|
|
239
|
-
if (
|
|
240
|
-
animate(y,
|
|
245
|
+
if (snapY !== null) {
|
|
246
|
+
animate(y, snapY, animationOptions);
|
|
241
247
|
onSnap?.(snapIndex);
|
|
242
248
|
|
|
243
249
|
// +1px for imprecision tolerance
|
|
244
|
-
if (
|
|
250
|
+
if (snapY + 1 >= sheetHeight) {
|
|
245
251
|
onClose();
|
|
246
252
|
}
|
|
247
253
|
}
|
package/src/styles.ts
CHANGED
|
@@ -20,6 +20,7 @@ export const styles: Record<string, Properties> = {
|
|
|
20
20
|
backgroundColor: 'rgba(0, 0, 0, 0.2)',
|
|
21
21
|
touchAction: 'none',
|
|
22
22
|
border: 'none',
|
|
23
|
+
userSelect: 'none',
|
|
23
24
|
WebkitTapHighlightColor: 'transparent',
|
|
24
25
|
},
|
|
25
26
|
container: {
|
|
@@ -63,5 +64,6 @@ export const styles: Record<string, Properties> = {
|
|
|
63
64
|
scroller: {
|
|
64
65
|
height: '100%',
|
|
65
66
|
overflowY: 'auto',
|
|
67
|
+
overscrollBehaviorY: 'none',
|
|
66
68
|
},
|
|
67
69
|
};
|
package/src/types.tsx
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ComponentPropsWithoutRef,
|
|
3
3
|
type ForwardRefExoticComponent,
|
|
4
|
-
type HTMLAttributes,
|
|
5
|
-
type MutableRefObject,
|
|
6
4
|
type ReactNode,
|
|
7
5
|
type RefAttributes,
|
|
8
6
|
type RefObject,
|
|
@@ -31,6 +29,8 @@ type CommonProps = MotionProps & {
|
|
|
31
29
|
className?: string;
|
|
32
30
|
};
|
|
33
31
|
|
|
32
|
+
type MotionDivProps = ComponentPropsWithoutRef<typeof motion.div>;
|
|
33
|
+
|
|
34
34
|
export interface SheetTweenConfig {
|
|
35
35
|
ease: EasingDefinition;
|
|
36
36
|
duration: number;
|
|
@@ -55,7 +55,7 @@ export type SheetProps = {
|
|
|
55
55
|
dragCloseThreshold?: number;
|
|
56
56
|
modalEffectThreshold?: number;
|
|
57
57
|
} & SheetEvents &
|
|
58
|
-
|
|
58
|
+
MotionDivProps;
|
|
59
59
|
|
|
60
60
|
export type SheetContainerProps = Omit<
|
|
61
61
|
CommonProps,
|
|
@@ -83,8 +83,10 @@ export type SheetBackdropProps = Omit<
|
|
|
83
83
|
'initial' | 'animate' | 'exit'
|
|
84
84
|
>;
|
|
85
85
|
|
|
86
|
-
export type SheetScrollerProps =
|
|
86
|
+
export type SheetScrollerProps = MotionDivProps & {
|
|
87
87
|
draggableAt?: 'top' | 'bottom' | 'both';
|
|
88
|
+
disableScroll?: boolean;
|
|
89
|
+
autoPadding?: boolean;
|
|
88
90
|
};
|
|
89
91
|
|
|
90
92
|
export interface SheetDragProps {
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ForwardedRef, type RefCallback, type RefObject } from 'react';
|
|
2
2
|
import { IS_SSR } from './constants';
|
|
3
|
+
import type { SheetDetent } from './types';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Get the rounded height of the sheet element and log a warning if the
|
|
@@ -45,6 +46,39 @@ export function getSnapPoints({
|
|
|
45
46
|
return snapPointValues;
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
export function getClosestSnapPoint({
|
|
50
|
+
snapPoints,
|
|
51
|
+
currentY,
|
|
52
|
+
sheetHeight,
|
|
53
|
+
detent,
|
|
54
|
+
}: {
|
|
55
|
+
snapPoints: number[];
|
|
56
|
+
currentY: number;
|
|
57
|
+
sheetHeight: number;
|
|
58
|
+
detent?: SheetDetent;
|
|
59
|
+
}) {
|
|
60
|
+
// Inverse values are the values that can be passed to `animate`
|
|
61
|
+
const snapInverse = snapPoints.map(
|
|
62
|
+
(p) => sheetHeight - Math.min(p, sheetHeight)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Allow snapping to the top of the sheet if detent is set to `content-height`
|
|
66
|
+
if (detent === 'content-height' && !snapInverse.includes(0)) {
|
|
67
|
+
snapInverse.unshift(0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Get the closest snap point
|
|
71
|
+
const snapTo = getClosest(snapInverse, currentY);
|
|
72
|
+
const snapIndex = snapInverse.indexOf(snapTo);
|
|
73
|
+
|
|
74
|
+
const snapY = validateSnapTo({
|
|
75
|
+
snapTo: getClosest(snapInverse, currentY),
|
|
76
|
+
sheetHeight,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return { snapY, snapIndex };
|
|
80
|
+
}
|
|
81
|
+
|
|
48
82
|
/**
|
|
49
83
|
* Get the closest number to the goal from the array of numbers.
|
|
50
84
|
*/
|