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/snap.ts
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import type { SheetSnapPoint } from './types';
|
|
2
|
+
import { isAscendingOrder } from './utils';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Convert negative / percentage snap points to absolute values
|
|
6
|
+
*
|
|
7
|
+
* Example output:
|
|
8
|
+
*
|
|
9
|
+
* ```json
|
|
10
|
+
* [
|
|
11
|
+
* {
|
|
12
|
+
* "snapIndex": 0, // <-- bottom snap point
|
|
13
|
+
* "snapValue": 0,
|
|
14
|
+
* "snapValueY": 810
|
|
15
|
+
* },
|
|
16
|
+
* {
|
|
17
|
+
* "snapIndex": 1,
|
|
18
|
+
* "snapValue": 170,
|
|
19
|
+
* "snapValueY": 640
|
|
20
|
+
* },
|
|
21
|
+
* {
|
|
22
|
+
* "snapIndex": 2,
|
|
23
|
+
* "snapValue": 405,
|
|
24
|
+
* "snapValueY": 405
|
|
25
|
+
* },
|
|
26
|
+
* {
|
|
27
|
+
* "snapIndex": 3,
|
|
28
|
+
* "snapValue": 760,
|
|
29
|
+
* "snapValueY": 50
|
|
30
|
+
* },
|
|
31
|
+
* {
|
|
32
|
+
* "snapIndex": 4, // <-- top snap point
|
|
33
|
+
* "snapValue": 810,
|
|
34
|
+
* "snapValueY": 0
|
|
35
|
+
* }
|
|
36
|
+
* ]
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function computeSnapPoints({
|
|
40
|
+
snapPointsProp,
|
|
41
|
+
sheetHeight,
|
|
42
|
+
}: {
|
|
43
|
+
snapPointsProp: number[];
|
|
44
|
+
sheetHeight: number;
|
|
45
|
+
}): SheetSnapPoint[] {
|
|
46
|
+
if (sheetHeight <= 0) {
|
|
47
|
+
console.warn(
|
|
48
|
+
`Sheet height is ${sheetHeight}, cannot compute snap points. ` +
|
|
49
|
+
'Make sure the sheet is mounted and has a valid height.'
|
|
50
|
+
);
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const snapPointValues = snapPointsProp.map((point) => {
|
|
55
|
+
// Percentage values e.g. between 0.0 and 1.0
|
|
56
|
+
if (point > 0 && point <= 1) {
|
|
57
|
+
return Math.round(point * sheetHeight);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return point < 0 ? sheetHeight + point : point; // negative values
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
console.assert(
|
|
64
|
+
isAscendingOrder(snapPointValues),
|
|
65
|
+
`Snap points need to be in ascending order got: [${snapPointsProp.join(', ')}]`
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// Make sure all snap points are within the sheet height
|
|
69
|
+
snapPointValues.forEach((snap) => {
|
|
70
|
+
if (snap < 0 || snap > sheetHeight) {
|
|
71
|
+
console.warn(
|
|
72
|
+
`Snap point ${snap} is outside of the sheet height ${sheetHeight}. ` +
|
|
73
|
+
'This can cause unexpected behavior. Consider adjusting your snap points.'
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
if (!snapPointValues.includes(sheetHeight)) {
|
|
79
|
+
console.warn(
|
|
80
|
+
'Snap points do not include the sheet height.' +
|
|
81
|
+
'Please include `1` as the last snap point or it will be included automatically.' +
|
|
82
|
+
'This is to ensure the sheet can be fully opened.'
|
|
83
|
+
);
|
|
84
|
+
snapPointValues.push(sheetHeight);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return snapPointValues.map((snap, index) => ({
|
|
88
|
+
snapIndex: index,
|
|
89
|
+
snapValue: snap, // Absolute value from the bottom of the sheet
|
|
90
|
+
snapValueY: sheetHeight - snap, // Y value is inverted as `y = 0` means sheet is at the top
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function findClosestSnapPoint({
|
|
95
|
+
snapPoints,
|
|
96
|
+
currentY,
|
|
97
|
+
}: {
|
|
98
|
+
snapPoints: SheetSnapPoint[];
|
|
99
|
+
currentY: number;
|
|
100
|
+
}) {
|
|
101
|
+
return snapPoints.reduce((closest, snap) =>
|
|
102
|
+
Math.abs(snap.snapValueY - currentY) <
|
|
103
|
+
Math.abs(closest.snapValueY - currentY)
|
|
104
|
+
? snap
|
|
105
|
+
: closest
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function findNextSnapPointInDirection({
|
|
110
|
+
y,
|
|
111
|
+
snapPoints,
|
|
112
|
+
dragDirection,
|
|
113
|
+
}: {
|
|
114
|
+
y: number;
|
|
115
|
+
snapPoints: SheetSnapPoint[];
|
|
116
|
+
dragDirection: 'up' | 'down';
|
|
117
|
+
}) {
|
|
118
|
+
// NOTE: lower Y means higher in the sheet position!
|
|
119
|
+
if (dragDirection === 'down') {
|
|
120
|
+
/**
|
|
121
|
+
* Example:
|
|
122
|
+
*
|
|
123
|
+
* [
|
|
124
|
+
* { snapIndex: 0, snapValueY: 810 },
|
|
125
|
+
* { snapIndex: 1, snapValueY: 640 },
|
|
126
|
+
* { snapIndex: 2, snapValueY: 405 }, <-- next down
|
|
127
|
+
* ------------- Y = 60 ------------
|
|
128
|
+
* { snapIndex: 3, snapValueY: 50 },
|
|
129
|
+
* { snapIndex: 4, snapValueY: 0 },
|
|
130
|
+
* ]
|
|
131
|
+
*/
|
|
132
|
+
return snapPoints
|
|
133
|
+
.slice()
|
|
134
|
+
.reverse()
|
|
135
|
+
.find((s) => s.snapValueY > y);
|
|
136
|
+
} else {
|
|
137
|
+
/**
|
|
138
|
+
* Example:
|
|
139
|
+
* [
|
|
140
|
+
* { snapIndex: 0, snapValueY: 810 },
|
|
141
|
+
* { snapIndex: 1, snapValueY: 640 },
|
|
142
|
+
* { snapIndex: 2, snapValueY: 405 },
|
|
143
|
+
* ------------- Y = 60 ------------
|
|
144
|
+
* { snapIndex: 3, snapValueY: 50 }, <-- next up
|
|
145
|
+
* { snapIndex: 4, snapValueY: 0 },
|
|
146
|
+
* ]
|
|
147
|
+
*/
|
|
148
|
+
return snapPoints.find((s) => s.snapValueY < y);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
export function handleHighVelocityDrag({
|
|
152
|
+
dragDirection,
|
|
153
|
+
snapPoints,
|
|
154
|
+
}: {
|
|
155
|
+
dragDirection: 'up' | 'down';
|
|
156
|
+
snapPoints: SheetSnapPoint[];
|
|
157
|
+
}) {
|
|
158
|
+
// Go to either the last or the first snap point depending on the direction
|
|
159
|
+
const bottomSnapPoint = snapPoints[0];
|
|
160
|
+
const topSnapPoint = snapPoints[snapPoints.length - 1];
|
|
161
|
+
|
|
162
|
+
if (dragDirection === 'down') {
|
|
163
|
+
return {
|
|
164
|
+
yTo: bottomSnapPoint.snapValueY,
|
|
165
|
+
snapIndex: bottomSnapPoint.snapIndex,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
yTo: topSnapPoint.snapValueY,
|
|
170
|
+
snapIndex: topSnapPoint.snapIndex,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function handleLowVelocityDrag({
|
|
175
|
+
currentSnapPoint,
|
|
176
|
+
currentY,
|
|
177
|
+
dragDirection,
|
|
178
|
+
snapPoints,
|
|
179
|
+
velocity,
|
|
180
|
+
}: {
|
|
181
|
+
currentSnapPoint: SheetSnapPoint;
|
|
182
|
+
currentY: number;
|
|
183
|
+
dragDirection: 'up' | 'down';
|
|
184
|
+
snapPoints: SheetSnapPoint[];
|
|
185
|
+
velocity: number;
|
|
186
|
+
}) {
|
|
187
|
+
const closestSnapRelativeToCurrentY = findClosestSnapPoint({
|
|
188
|
+
snapPoints,
|
|
189
|
+
currentY,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* If velocity is very low the user has stopped the sheet to a specific
|
|
194
|
+
* position and we should snap to the closest snap point as there is no
|
|
195
|
+
* "momentum" that would push the sheet further to the given direction
|
|
196
|
+
*/
|
|
197
|
+
if (Math.abs(velocity) < 20) {
|
|
198
|
+
return {
|
|
199
|
+
yTo: closestSnapRelativeToCurrentY.snapValueY,
|
|
200
|
+
snapIndex: closestSnapRelativeToCurrentY.snapIndex,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* If the dragging has a bit more velocity, we instead want to go to
|
|
206
|
+
* the next snap point in the given direction if it exists
|
|
207
|
+
*/
|
|
208
|
+
const nextSnapInDirectionRelativeToCurrentY = findNextSnapPointInDirection({
|
|
209
|
+
y: currentY,
|
|
210
|
+
snapPoints,
|
|
211
|
+
dragDirection,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (nextSnapInDirectionRelativeToCurrentY) {
|
|
215
|
+
return {
|
|
216
|
+
yTo: nextSnapInDirectionRelativeToCurrentY.snapValueY,
|
|
217
|
+
snapIndex: nextSnapInDirectionRelativeToCurrentY.snapIndex,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// No snap point down, stay at current
|
|
222
|
+
return {
|
|
223
|
+
yTo: currentSnapPoint.snapValueY,
|
|
224
|
+
snapIndex: currentSnapPoint.snapIndex,
|
|
225
|
+
};
|
|
226
|
+
}
|
package/src/styles.ts
CHANGED
|
@@ -1,69 +1,110 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
2
|
|
|
3
|
-
export const styles
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
export const styles = {
|
|
4
|
+
root: {
|
|
5
|
+
base: {
|
|
6
|
+
position: 'fixed',
|
|
7
|
+
top: 0,
|
|
8
|
+
bottom: 0,
|
|
9
|
+
left: 0,
|
|
10
|
+
right: 0,
|
|
11
|
+
overflow: 'hidden',
|
|
12
|
+
pointerEvents: 'none',
|
|
13
|
+
},
|
|
14
|
+
decorative: {},
|
|
12
15
|
},
|
|
13
16
|
backdrop: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
base: {
|
|
18
|
+
zIndex: 1,
|
|
19
|
+
position: 'fixed',
|
|
20
|
+
top: 0,
|
|
21
|
+
left: 0,
|
|
22
|
+
width: '100%',
|
|
23
|
+
height: '100%',
|
|
24
|
+
touchAction: 'none',
|
|
25
|
+
userSelect: 'none',
|
|
26
|
+
},
|
|
27
|
+
decorative: {
|
|
28
|
+
backgroundColor: 'rgba(0, 0, 0, 0.2)',
|
|
29
|
+
border: 'none',
|
|
30
|
+
WebkitTapHighlightColor: 'transparent',
|
|
31
|
+
},
|
|
25
32
|
},
|
|
26
33
|
container: {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
base: {
|
|
35
|
+
zIndex: 2,
|
|
36
|
+
position: 'absolute',
|
|
37
|
+
left: 0,
|
|
38
|
+
bottom: 0,
|
|
39
|
+
width: '100%',
|
|
40
|
+
pointerEvents: 'auto',
|
|
41
|
+
display: 'flex',
|
|
42
|
+
flexDirection: 'column',
|
|
43
|
+
},
|
|
44
|
+
decorative: {
|
|
45
|
+
backgroundColor: '#fff',
|
|
46
|
+
borderTopRightRadius: '8px',
|
|
47
|
+
borderTopLeftRadius: '8px',
|
|
48
|
+
boxShadow: '0px -2px 16px rgba(0, 0, 0, 0.3)',
|
|
49
|
+
},
|
|
39
50
|
},
|
|
40
51
|
headerWrapper: {
|
|
41
|
-
|
|
52
|
+
base: {
|
|
53
|
+
width: '100%',
|
|
54
|
+
},
|
|
55
|
+
decorative: {},
|
|
42
56
|
},
|
|
43
57
|
header: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
base: {
|
|
59
|
+
width: '100%',
|
|
60
|
+
position: 'relative',
|
|
61
|
+
},
|
|
62
|
+
decorative: {
|
|
63
|
+
height: '40px',
|
|
64
|
+
display: 'flex',
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
justifyContent: 'center',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
indicatorWrapper: {
|
|
70
|
+
base: {
|
|
71
|
+
display: 'flex',
|
|
72
|
+
},
|
|
73
|
+
decorative: {},
|
|
50
74
|
},
|
|
51
75
|
indicator: {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
76
|
+
base: {
|
|
77
|
+
display: 'inline-block',
|
|
78
|
+
},
|
|
79
|
+
decorative: {
|
|
80
|
+
width: '18px',
|
|
81
|
+
height: '4px',
|
|
82
|
+
borderRadius: '99px',
|
|
83
|
+
backgroundColor: '#ddd',
|
|
84
|
+
},
|
|
56
85
|
},
|
|
57
86
|
content: {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
87
|
+
base: {
|
|
88
|
+
minHeight: '0px',
|
|
89
|
+
position: 'relative',
|
|
90
|
+
flexGrow: 1,
|
|
91
|
+
display: 'flex',
|
|
92
|
+
flexDirection: 'column',
|
|
93
|
+
},
|
|
94
|
+
decorative: {},
|
|
63
95
|
},
|
|
64
96
|
scroller: {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
97
|
+
base: {
|
|
98
|
+
height: '100%',
|
|
99
|
+
overflowY: 'auto',
|
|
100
|
+
overscrollBehaviorY: 'none',
|
|
101
|
+
},
|
|
102
|
+
decorative: {},
|
|
68
103
|
},
|
|
69
|
-
}
|
|
104
|
+
} satisfies Record<
|
|
105
|
+
string,
|
|
106
|
+
{
|
|
107
|
+
base: CSSProperties;
|
|
108
|
+
decorative: CSSProperties;
|
|
109
|
+
}
|
|
110
|
+
>;
|
package/src/types.tsx
CHANGED
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type CSSProperties,
|
|
2
3
|
type ComponentPropsWithoutRef,
|
|
3
4
|
type ForwardRefExoticComponent,
|
|
5
|
+
type FunctionComponent,
|
|
6
|
+
type HTMLAttributes,
|
|
4
7
|
type ReactNode,
|
|
5
8
|
type RefAttributes,
|
|
6
9
|
type RefObject,
|
|
7
10
|
} from 'react';
|
|
8
11
|
|
|
9
12
|
import {
|
|
10
|
-
type
|
|
11
|
-
type
|
|
13
|
+
type DragHandler,
|
|
14
|
+
type EasingDefinition,
|
|
12
15
|
type MotionProps,
|
|
16
|
+
type MotionValue,
|
|
13
17
|
type motion,
|
|
14
|
-
type EasingDefinition,
|
|
15
|
-
type Transition,
|
|
16
18
|
} from 'motion/react';
|
|
17
19
|
|
|
18
|
-
export
|
|
19
|
-
onOpenStart?: () => void;
|
|
20
|
-
onOpenEnd?: () => void;
|
|
21
|
-
onCloseStart?: () => void;
|
|
22
|
-
onCloseEnd?: () => void;
|
|
23
|
-
onSnap?: (index: number) => void;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type SheetDetent = 'full-height' | 'content-height';
|
|
20
|
+
export type SheetDetent = 'default' | 'full' | 'content';
|
|
27
21
|
|
|
28
|
-
type CommonProps =
|
|
22
|
+
type CommonProps = {
|
|
29
23
|
className?: string;
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
unstyled?: boolean;
|
|
30
26
|
};
|
|
31
27
|
|
|
28
|
+
type MotionCommonProps = Omit<MotionProps, 'initial' | 'animate' | 'exit'> &
|
|
29
|
+
CommonProps;
|
|
30
|
+
|
|
32
31
|
type MotionDivProps = ComponentPropsWithoutRef<typeof motion.div>;
|
|
33
32
|
|
|
34
33
|
export interface SheetTweenConfig {
|
|
@@ -37,81 +36,86 @@ export interface SheetTweenConfig {
|
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
export type SheetProps = {
|
|
40
|
-
|
|
39
|
+
unstyled?: boolean;
|
|
40
|
+
avoidKeyboard?: boolean;
|
|
41
41
|
children: ReactNode;
|
|
42
|
-
onClose: () => void;
|
|
43
|
-
/** @deprecated Use `modalEffectRootId` instead! */
|
|
44
|
-
rootId?: string;
|
|
45
|
-
modalEffectRootId?: string;
|
|
46
|
-
mountPoint?: Element;
|
|
47
|
-
snapPoints?: number[];
|
|
48
42
|
detent?: SheetDetent;
|
|
49
|
-
|
|
50
|
-
tweenConfig?: SheetTweenConfig;
|
|
43
|
+
disableDismiss?: boolean;
|
|
51
44
|
disableDrag?: boolean;
|
|
52
45
|
disableScrollLocking?: boolean;
|
|
53
|
-
prefersReducedMotion?: boolean;
|
|
54
|
-
dragVelocityThreshold?: number;
|
|
55
46
|
dragCloseThreshold?: number;
|
|
47
|
+
dragVelocityThreshold?: number;
|
|
48
|
+
initialSnap?: number; // index of snap points array
|
|
49
|
+
isOpen: boolean;
|
|
50
|
+
modalEffectRootId?: string;
|
|
56
51
|
modalEffectThreshold?: number;
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
mountPoint?: Element;
|
|
53
|
+
prefersReducedMotion?: boolean;
|
|
54
|
+
snapPoints?: number[];
|
|
55
|
+
tweenConfig?: SheetTweenConfig;
|
|
56
|
+
onClose: () => void;
|
|
57
|
+
onCloseEnd?: () => void;
|
|
58
|
+
onCloseStart?: () => void;
|
|
59
|
+
onOpenEnd?: () => void;
|
|
60
|
+
onOpenStart?: () => void;
|
|
61
|
+
onSnap?: (index: number) => void;
|
|
62
|
+
} & MotionDivProps;
|
|
59
63
|
|
|
60
|
-
export type SheetContainerProps =
|
|
61
|
-
CommonProps
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
children: ReactNode;
|
|
65
|
-
};
|
|
64
|
+
export type SheetContainerProps = MotionCommonProps &
|
|
65
|
+
CommonProps & {
|
|
66
|
+
children: ReactNode;
|
|
67
|
+
};
|
|
66
68
|
|
|
67
|
-
export type
|
|
68
|
-
CommonProps
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
| 'dragMomentum'
|
|
73
|
-
| 'onDrag'
|
|
74
|
-
| 'onDragStart'
|
|
75
|
-
| 'onDragEnd'
|
|
76
|
-
> & {
|
|
77
|
-
children?: ReactNode;
|
|
78
|
-
disableDrag?: boolean;
|
|
79
|
-
};
|
|
69
|
+
export type SheetHeaderProps = MotionDivProps &
|
|
70
|
+
CommonProps & {
|
|
71
|
+
children?: ReactNode;
|
|
72
|
+
disableDrag?: boolean;
|
|
73
|
+
};
|
|
80
74
|
|
|
81
|
-
export type
|
|
82
|
-
CommonProps
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
export type SheetContentProps = MotionDivProps &
|
|
76
|
+
CommonProps & {
|
|
77
|
+
disableDrag?: boolean | ((args: SheetStateInfo) => boolean);
|
|
78
|
+
disableScroll?: boolean | ((args: SheetStateInfo) => boolean);
|
|
79
|
+
scrollRef?: RefObject<HTMLDivElement | null>;
|
|
80
|
+
};
|
|
85
81
|
|
|
86
|
-
export type
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
82
|
+
export type SheetBackdropProps = MotionCommonProps & CommonProps;
|
|
83
|
+
|
|
84
|
+
export type SheetDragIndicatorProps = HTMLAttributes<HTMLDivElement> &
|
|
85
|
+
CommonProps;
|
|
91
86
|
|
|
92
87
|
export interface SheetDragProps {
|
|
93
88
|
drag: 'y';
|
|
94
89
|
dragElastic: number;
|
|
95
90
|
dragMomentum: boolean;
|
|
96
91
|
dragPropagation: boolean;
|
|
97
|
-
onDrag:
|
|
98
|
-
onDragStart:
|
|
99
|
-
onDragEnd:
|
|
92
|
+
onDrag: DragHandler;
|
|
93
|
+
onDragStart: DragHandler;
|
|
94
|
+
onDragEnd: DragHandler;
|
|
100
95
|
}
|
|
101
96
|
|
|
97
|
+
export type SheetStateInfo = {
|
|
98
|
+
scrollPosition?: 'top' | 'bottom' | 'middle';
|
|
99
|
+
currentSnap?: number;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export type SheetSnapPoint = {
|
|
103
|
+
snapIndex: number;
|
|
104
|
+
snapValue: number; // Absolute value from the bottom of the sheet
|
|
105
|
+
snapValueY: number; // Y value is inverted as `y = 0` means sheet is at the top
|
|
106
|
+
};
|
|
107
|
+
|
|
102
108
|
export interface SheetContextType {
|
|
103
|
-
|
|
104
|
-
sheetRef: RefObject<any>;
|
|
105
|
-
isOpen: boolean;
|
|
109
|
+
currentSnap?: number;
|
|
106
110
|
detent: SheetDetent;
|
|
107
|
-
initialSnap: SheetProps['initialSnap'];
|
|
108
|
-
indicatorRotation: MotionValue<number>;
|
|
109
|
-
callbacks: RefObject<SheetEvents>;
|
|
110
|
-
dragProps?: SheetDragProps;
|
|
111
|
-
windowHeight: number;
|
|
112
|
-
animationOptions: Transition;
|
|
113
|
-
reduceMotion: boolean;
|
|
114
111
|
disableDrag: boolean;
|
|
112
|
+
dragProps?: SheetDragProps;
|
|
113
|
+
indicatorRotation: MotionValue<number>;
|
|
114
|
+
avoidKeyboard: boolean;
|
|
115
|
+
sheetBoundsRef: (node: HTMLDivElement | null) => void;
|
|
116
|
+
sheetRef: RefObject<any>;
|
|
117
|
+
unstyled: boolean;
|
|
118
|
+
y: MotionValue<any>;
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
export interface SheetScrollerContextType {
|
|
@@ -120,32 +124,32 @@ export interface SheetScrollerContextType {
|
|
|
120
124
|
setDragEnabled: () => void;
|
|
121
125
|
}
|
|
122
126
|
|
|
127
|
+
type SheetComponent = ForwardRefExoticComponent<
|
|
128
|
+
SheetProps & RefAttributes<any>
|
|
129
|
+
>;
|
|
130
|
+
|
|
123
131
|
type ContainerComponent = ForwardRefExoticComponent<
|
|
124
132
|
SheetContainerProps & RefAttributes<any>
|
|
125
133
|
>;
|
|
126
134
|
|
|
127
|
-
type
|
|
128
|
-
|
|
135
|
+
type HeaderComponent = ForwardRefExoticComponent<
|
|
136
|
+
SheetHeaderProps & RefAttributes<any>
|
|
129
137
|
>;
|
|
130
138
|
|
|
131
139
|
type BackdropComponent = ForwardRefExoticComponent<
|
|
132
140
|
SheetBackdropProps & RefAttributes<any>
|
|
133
141
|
>;
|
|
134
142
|
|
|
135
|
-
type
|
|
136
|
-
|
|
137
|
-
>;
|
|
138
|
-
|
|
139
|
-
type ScrollerComponent = ForwardRefExoticComponent<
|
|
140
|
-
SheetScrollerProps & RefAttributes<any>
|
|
143
|
+
type ContentComponent = ForwardRefExoticComponent<
|
|
144
|
+
SheetContentProps & RefAttributes<any>
|
|
141
145
|
>;
|
|
142
146
|
|
|
143
147
|
interface SheetCompoundComponent {
|
|
144
148
|
Container: ContainerComponent;
|
|
145
|
-
Header:
|
|
146
|
-
|
|
149
|
+
Header: HeaderComponent;
|
|
150
|
+
DragIndicator: FunctionComponent<SheetDragIndicatorProps>;
|
|
151
|
+
Content: ContentComponent;
|
|
147
152
|
Backdrop: BackdropComponent;
|
|
148
|
-
Scroller: ScrollerComponent;
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
export type SheetCompound = SheetComponent & SheetCompoundComponent;
|