react-modal-sheet 5.6.0 → 5.7.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 +42 -1
- package/dist/index.js +54 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/use-modal-effect.ts +72 -15
- package/src/sheet.tsx +1 -1
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import { type MotionValue, transform } from 'motion';
|
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
|
|
4
4
|
import type { SheetDetent, SheetSnapPoint } from '../types';
|
|
5
|
+
import { clamp } from '../utils';
|
|
5
6
|
import { useSafeAreaInsets } from './use-safe-area-insets';
|
|
6
7
|
import { useStableCallback } from './use-stable-callback';
|
|
7
8
|
|
|
@@ -79,13 +80,7 @@ export function useModalEffect({
|
|
|
79
80
|
// Make sure progress is between 0 and 1
|
|
80
81
|
progress = Math.max(0, Math.min(1, progress));
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
updateModalEffect(rootId, {
|
|
85
|
-
scale: transform(progress, [0, 1], [1, (pageWidth - 16) / pageWidth]),
|
|
86
|
-
translateY: transform(progress, [0, 1], [0, 24 + insetTop]),
|
|
87
|
-
borderRadius: transform(progress, [0, 1], [0, 10]),
|
|
88
|
-
});
|
|
83
|
+
updateModalEffect(rootId, { progress, insetTop });
|
|
89
84
|
});
|
|
90
85
|
|
|
91
86
|
const handleYComplete = useStableCallback(() => {
|
|
@@ -122,9 +117,18 @@ export function useModalEffect({
|
|
|
122
117
|
}
|
|
123
118
|
|
|
124
119
|
function setupModalEffect(rootId: string) {
|
|
125
|
-
const
|
|
126
|
-
if (!
|
|
120
|
+
const target = getModalEffectTarget(rootId);
|
|
121
|
+
if (!target) return;
|
|
122
|
+
|
|
123
|
+
if (target.type === 'sheet') {
|
|
124
|
+
const sheet = target.element;
|
|
127
125
|
|
|
126
|
+
// No transition as the sheet follows the `y` of the stacked sheet
|
|
127
|
+
sheet.style.transformOrigin = 'center top';
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const root = target.element;
|
|
128
132
|
const body = document.querySelector('body') as HTMLBodyElement;
|
|
129
133
|
|
|
130
134
|
body.style.backgroundColor = '#000000';
|
|
@@ -137,21 +141,55 @@ function setupModalEffect(rootId: string) {
|
|
|
137
141
|
|
|
138
142
|
function updateModalEffect(
|
|
139
143
|
rootId: string,
|
|
140
|
-
opts: {
|
|
144
|
+
opts: { progress: number; insetTop: number }
|
|
141
145
|
) {
|
|
142
|
-
const
|
|
143
|
-
if (!
|
|
146
|
+
const target = getModalEffectTarget(rootId);
|
|
147
|
+
if (!target) return;
|
|
148
|
+
|
|
149
|
+
const { progress, insetTop } = opts;
|
|
150
|
+
|
|
151
|
+
if (target.type === 'sheet') {
|
|
152
|
+
const sheet = target.element;
|
|
153
|
+
|
|
154
|
+
const sheetWidth = sheet.offsetWidth;
|
|
155
|
+
const sheetTop = sheet.offsetTop;
|
|
156
|
+
const scaleEnd = (sheetWidth - 16) / sheetWidth;
|
|
157
|
+
const scale = transform(progress, [0, 1], [1, scaleEnd]);
|
|
158
|
+
// Match the scaled app root's top edge, but cap the final lift for short sheets.
|
|
159
|
+
const translateYEnd = clamp(scaleEnd * (24 + insetTop) - sheetTop, -10, 0);
|
|
160
|
+
const translateY = transform(progress, [0, 1], [0, translateYEnd]);
|
|
161
|
+
|
|
162
|
+
sheet.style.scale = `${scale}`;
|
|
163
|
+
sheet.style.translate = `0 ${translateY}px`;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const root = target.element;
|
|
168
|
+
const pageWidth = window.innerWidth;
|
|
169
|
+
const scaleEnd = (pageWidth - 16) / pageWidth;
|
|
170
|
+
const scale = transform(progress, [0, 1], [1, scaleEnd]);
|
|
171
|
+
const translateY = transform(progress, [0, 1], [0, 24 + insetTop]);
|
|
172
|
+
const borderRadius = transform(progress, [0, 1], [0, 10]);
|
|
144
173
|
|
|
145
|
-
const { scale, translateY, borderRadius } = opts;
|
|
146
174
|
root.style.transform = `scale(${scale}) translate3d(0, ${translateY}px, 0)`;
|
|
147
175
|
root.style.borderTopRightRadius = `${borderRadius}px`;
|
|
148
176
|
root.style.borderTopLeftRadius = `${borderRadius}px`;
|
|
149
177
|
}
|
|
150
178
|
|
|
151
179
|
function cleanupModalEffect(rootId: string) {
|
|
152
|
-
const
|
|
153
|
-
if (!
|
|
180
|
+
const target = getModalEffectTarget(rootId);
|
|
181
|
+
if (!target) return;
|
|
154
182
|
|
|
183
|
+
if (target.type === 'sheet') {
|
|
184
|
+
const sheet = target.element;
|
|
185
|
+
|
|
186
|
+
sheet.style.removeProperty('transform-origin');
|
|
187
|
+
sheet.style.removeProperty('scale');
|
|
188
|
+
sheet.style.removeProperty('translate');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const root = target.element;
|
|
155
193
|
const body = document.querySelector('body') as HTMLBodyElement;
|
|
156
194
|
|
|
157
195
|
body.style.removeProperty('background-color');
|
|
@@ -164,3 +202,22 @@ function cleanupModalEffect(rootId: string) {
|
|
|
164
202
|
root.style.removeProperty('border-top-right-radius');
|
|
165
203
|
root.style.removeProperty('border-top-left-radius');
|
|
166
204
|
}
|
|
205
|
+
|
|
206
|
+
function getModalEffectTarget(rootId: string) {
|
|
207
|
+
const root = document.getElementById(rootId) as HTMLDivElement;
|
|
208
|
+
if (!root) return null;
|
|
209
|
+
|
|
210
|
+
// When stacking sheets the effect is applied to the container of the sheet
|
|
211
|
+
const sheetRoot = root.closest('.react-modal-sheet-root');
|
|
212
|
+
|
|
213
|
+
if (sheetRoot) {
|
|
214
|
+
const container = sheetRoot.querySelector(
|
|
215
|
+
'.react-modal-sheet-container'
|
|
216
|
+
) as HTMLDivElement;
|
|
217
|
+
if (!container) return null;
|
|
218
|
+
|
|
219
|
+
return { type: 'sheet', element: container };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return { type: 'root', element: root };
|
|
223
|
+
}
|
package/src/sheet.tsx
CHANGED
|
@@ -75,7 +75,7 @@ export const Sheet = forwardRef<any, SheetProps>(
|
|
|
75
75
|
},
|
|
76
76
|
ref
|
|
77
77
|
) => {
|
|
78
|
-
const [sheetBoundsRef, sheetBounds] = useMeasure();
|
|
78
|
+
const [sheetBoundsRef, sheetBounds] = useMeasure({ offsetSize: true });
|
|
79
79
|
const sheetRef = useRef<HTMLDivElement>(null);
|
|
80
80
|
const sheetHeight = Math.round(sheetBounds.height);
|
|
81
81
|
const [currentSnap, setCurrentSnap] = useState(initialSnap);
|