react-modal-sheet 5.3.0 → 5.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 +9 -6
- package/dist/index.js +73 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/SheetBackdrop.tsx +10 -4
- package/src/debug.ts +3 -2
- package/src/hooks/use-focused-input.ts +46 -0
- package/src/sheet.tsx +63 -33
- package/src/types.tsx +1 -0
package/dist/index.mjs
CHANGED
|
@@ -211,13 +211,16 @@ var SheetBackdrop = forwardRef(
|
|
|
211
211
|
...style,
|
|
212
212
|
pointerEvents
|
|
213
213
|
};
|
|
214
|
+
const animationProps = sheetContext.prefersReducedMotion ? {} : {
|
|
215
|
+
initial: { opacity: 0 },
|
|
216
|
+
animate: { opacity: 1 },
|
|
217
|
+
exit: { opacity: 0 },
|
|
218
|
+
transition: { duration: 1 }
|
|
219
|
+
};
|
|
214
220
|
return /* @__PURE__ */ React4.createElement(
|
|
215
221
|
Comp,
|
|
216
222
|
{
|
|
217
|
-
|
|
218
|
-
animate: { opacity: 1 },
|
|
219
|
-
exit: { opacity: 0 },
|
|
220
|
-
transition: { duration: 1 },
|
|
223
|
+
...animationProps,
|
|
221
224
|
...rest,
|
|
222
225
|
ref,
|
|
223
226
|
className: `react-modal-sheet-backdrop ${className}`,
|
|
@@ -516,6 +519,36 @@ function useDimensions() {
|
|
|
516
519
|
}, []);
|
|
517
520
|
return dimensions;
|
|
518
521
|
}
|
|
522
|
+
function useFocusedInput({
|
|
523
|
+
isEnabled,
|
|
524
|
+
sheetRef
|
|
525
|
+
}) {
|
|
526
|
+
const [focusedInput, setFocusedInput] = useState(null);
|
|
527
|
+
useEffect(() => {
|
|
528
|
+
if (!isEnabled) return;
|
|
529
|
+
const handleFocusIn = (event) => {
|
|
530
|
+
var _a;
|
|
531
|
+
const focusedElement = event.target;
|
|
532
|
+
const isInput = (focusedElement == null ? void 0 : focusedElement.tagName) === "INPUT" || (focusedElement == null ? void 0 : focusedElement.tagName) === "TEXTAREA";
|
|
533
|
+
if (isInput && ((_a = sheetRef.current) == null ? void 0 : _a.contains(focusedElement))) {
|
|
534
|
+
setFocusedInput(focusedElement);
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
const handleFocusOut = (event) => {
|
|
538
|
+
const focusedElement = event.target;
|
|
539
|
+
if (focusedElement === focusedInput) {
|
|
540
|
+
setFocusedInput(null);
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
document.addEventListener("focusin", handleFocusIn);
|
|
544
|
+
document.addEventListener("focusout", handleFocusOut);
|
|
545
|
+
return () => {
|
|
546
|
+
document.removeEventListener("focusin", handleFocusIn);
|
|
547
|
+
document.removeEventListener("focusout", handleFocusOut);
|
|
548
|
+
};
|
|
549
|
+
}, [isEnabled, focusedInput]);
|
|
550
|
+
return focusedInput;
|
|
551
|
+
}
|
|
519
552
|
function useSafeAreaInsets() {
|
|
520
553
|
const [insets] = useState(() => {
|
|
521
554
|
const fallback = { top: 0, left: 0, right: 0, bottom: 0 };
|
|
@@ -1300,23 +1333,6 @@ var Sheet = forwardRef(
|
|
|
1300
1333
|
height: sheetHeight,
|
|
1301
1334
|
snapTo
|
|
1302
1335
|
}));
|
|
1303
|
-
useEffect(() => {
|
|
1304
|
-
if (isOpen && snapPoints.length > 0 && avoidKeyboard && keyboard.isKeyboardOpen) {
|
|
1305
|
-
const visibleSheetHeight = yInverted.get() - keyboard.keyboardHeight;
|
|
1306
|
-
if (visibleSheetHeight <= 0) {
|
|
1307
|
-
const currentY = y.get();
|
|
1308
|
-
const adjustedY = Math.max(
|
|
1309
|
-
// 50 for some extra spacing between keyboard and sheet content
|
|
1310
|
-
currentY - Math.abs(visibleSheetHeight) - 50,
|
|
1311
|
-
0
|
|
1312
|
-
);
|
|
1313
|
-
animate(y, adjustedY, animationOptions);
|
|
1314
|
-
return () => {
|
|
1315
|
-
animate(y, currentY, animationOptions);
|
|
1316
|
-
};
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
}, [isOpen, keyboard.isKeyboardOpen]);
|
|
1320
1336
|
useModalEffect({
|
|
1321
1337
|
y,
|
|
1322
1338
|
detent,
|
|
@@ -1328,6 +1344,41 @@ var Sheet = forwardRef(
|
|
|
1328
1344
|
usePreventScroll({
|
|
1329
1345
|
isDisabled: disableScrollLocking || !isOpen
|
|
1330
1346
|
});
|
|
1347
|
+
const focusedInput = useFocusedInput({
|
|
1348
|
+
isEnabled: isOpen && avoidKeyboard,
|
|
1349
|
+
sheetRef
|
|
1350
|
+
});
|
|
1351
|
+
useEffect(() => {
|
|
1352
|
+
if (!isOpen || !avoidKeyboard) {
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
async function adjustSheetForKeyboard() {
|
|
1356
|
+
const sheetElement = sheetRef.current;
|
|
1357
|
+
if (!sheetElement || !focusedInput || !keyboard.isKeyboardOpen) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
const lastSnapPoint = snapPoints[snapPoints.length - 1];
|
|
1361
|
+
if (lastSnapPoint) {
|
|
1362
|
+
await animate(y, lastSnapPoint.snapValueY, animationOptions);
|
|
1363
|
+
updateSnap(lastSnapPoint.snapIndex);
|
|
1364
|
+
}
|
|
1365
|
+
requestAnimationFrame(() => {
|
|
1366
|
+
const inputRect = focusedInput.getBoundingClientRect();
|
|
1367
|
+
const sheetRect = sheetElement.getBoundingClientRect();
|
|
1368
|
+
const scroller = sheetElement.querySelector(
|
|
1369
|
+
".react-modal-sheet-content-scroller"
|
|
1370
|
+
);
|
|
1371
|
+
const scrollTarget = Math.max(
|
|
1372
|
+
inputRect.top - sheetRect.top + scroller.scrollTop - inputRect.height,
|
|
1373
|
+
0
|
|
1374
|
+
);
|
|
1375
|
+
requestAnimationFrame(() => {
|
|
1376
|
+
scroller.scrollTo({ top: scrollTarget, behavior: "smooth" });
|
|
1377
|
+
});
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
adjustSheetForKeyboard();
|
|
1381
|
+
}, [isOpen, avoidKeyboard, keyboard.isKeyboardOpen, focusedInput]);
|
|
1331
1382
|
const state = useSheetState({
|
|
1332
1383
|
isOpen,
|
|
1333
1384
|
onOpen: async () => {
|
|
@@ -1363,6 +1414,7 @@ var Sheet = forwardRef(
|
|
|
1363
1414
|
dragProps,
|
|
1364
1415
|
indicatorRotation,
|
|
1365
1416
|
avoidKeyboard,
|
|
1417
|
+
prefersReducedMotion,
|
|
1366
1418
|
sheetBoundsRef,
|
|
1367
1419
|
sheetRef,
|
|
1368
1420
|
unstyled,
|