react-modal-sheet 5.3.1 → 5.4.1

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 CHANGED
@@ -423,18 +423,21 @@ function KeyboardExample() {
423
423
  }
424
424
  ```
425
425
 
426
- The keyboard avoidance feature:
426
+ Virtual keyboard avoidance consists of several key features:
427
427
 
428
428
  - Uses the `env(keyboard-inset-height)` from [Virtual Keyboard API](https://developer.mozilla.org/en-US/docs/Web/API/VirtualKeyboard_API) and fallbacks to [Visual Viewport API](https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API) and custom `keyboard-inset-height` CSS environment variable.
429
429
  - Works automatically on mobile devices with virtual keyboard support.
430
430
  - Applies dynamic padding to keep content visible when the keyboard opens.
431
+ - Scrolls the focused input into view if it's covered by the keyboard.
431
432
  - Disables drag gestures while the keyboard is open to prevent glitches.
432
- - When using snap points if the sheet is at a snap point that would be covered by the keyboard, **the sheet will be automatically moved up to ensure the content is visible and then moved back down when the keyboard closes.**
433
+ - When using snap points, the sheet will be automatically moved up to the last snap point to ensure that all content is reachable (even when the content is scrollable) within the sheet when the keyboard is open.
433
434
 
434
- If you need to disable keyboard avoidance, set `avoidKeyboard={false}`.
435
-
436
- > [!IMPORTANT]
437
- > If your sheet content is very long and some inputs are below the keyboard even after adding the padding, you might need to scroll the content into view manually when an input is focused.
435
+ > [!NOTE]
436
+ > Avoiding the virtual keyboard is a complex problem and the built-in avoidance may not work perfectly in all cases or on all devices. The library does its best to handle the most common scenarios but there may be edge cases where it doesn't work as expected.
437
+ >
438
+ > Mobile browsers, eg. Android Chrome, may try to automatically move the focused input into view when the keyboard opens which might interfere with the built-in keyboard avoidance behavior causing the sheet content to jump around.
439
+ >
440
+ > If you need to disable the built-in keyboard avoidance, set `avoidKeyboard={false}`.
438
441
 
439
442
  #### Managing virtual keyboard manually
440
443
 
package/dist/index.d.mts CHANGED
@@ -139,11 +139,6 @@ type UseVirtualKeyboardOptions = {
139
139
  * @default 100
140
140
  */
141
141
  visualViewportThreshold?: number;
142
- /**
143
- * Whether to treat contenteditable elements as text inputs.
144
- * @default true
145
- */
146
- includeContentEditable?: boolean;
147
142
  /**
148
143
  * Delay in ms for debouncing viewport changes.
149
144
  * @default 100
package/dist/index.d.ts CHANGED
@@ -139,11 +139,6 @@ type UseVirtualKeyboardOptions = {
139
139
  * @default 100
140
140
  */
141
141
  visualViewportThreshold?: number;
142
- /**
143
- * Whether to treat contenteditable elements as text inputs.
144
- * @default true
145
- */
146
- includeContentEditable?: boolean;
147
142
  /**
148
143
  * Delay in ms for debouncing viewport changes.
149
144
  * @default 100
package/dist/index.js CHANGED
@@ -203,6 +203,23 @@ function waitForElement(className, interval = 50, maxAttempts = 20) {
203
203
  }, interval);
204
204
  });
205
205
  }
206
+ var nonTextInputTypes = /* @__PURE__ */ new Set([
207
+ "checkbox",
208
+ "radio",
209
+ "range",
210
+ "color",
211
+ "file",
212
+ "image",
213
+ "button",
214
+ "submit",
215
+ "reset"
216
+ ]);
217
+ function willOpenKeyboard(target) {
218
+ return target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type) || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable;
219
+ }
220
+ function isHTTPS() {
221
+ return typeof window !== "undefined" && window.isSecureContext;
222
+ }
206
223
 
207
224
  // src/SheetBackdrop.tsx
208
225
  var isClickable = (props) => !!props.onClick || !!props.onTap;
@@ -218,13 +235,16 @@ var SheetBackdrop = React4.forwardRef(
218
235
  ...style,
219
236
  pointerEvents
220
237
  };
238
+ const animationProps = sheetContext.prefersReducedMotion ? {} : {
239
+ initial: { opacity: 0 },
240
+ animate: { opacity: 1 },
241
+ exit: { opacity: 0 },
242
+ transition: { duration: 1 }
243
+ };
221
244
  return /* @__PURE__ */ React4__default.default.createElement(
222
245
  Comp,
223
246
  {
224
- initial: { opacity: 0 },
225
- animate: { opacity: 1 },
226
- exit: { opacity: 0 },
227
- transition: { duration: 1 },
247
+ ...animationProps,
228
248
  ...rest,
229
249
  ref,
230
250
  className: `react-modal-sheet-backdrop ${className}`,
@@ -400,7 +420,7 @@ var SheetContent = React4.forwardRef(
400
420
  };
401
421
  const scrollStyle = applyStyles(styles.scroller, isUnstyled);
402
422
  if (sheetContext.avoidKeyboard) {
403
- scrollStyle.paddingBottom = "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))";
423
+ scrollStyle.paddingBottom = isHTTPS() ? "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))" : "var(--keyboard-inset-height, 0px)";
404
424
  }
405
425
  if (disableScroll) {
406
426
  scrollStyle.overflowY = "hidden";
@@ -523,6 +543,195 @@ function useDimensions() {
523
543
  }, []);
524
544
  return dimensions;
525
545
  }
546
+ var virtualKeyboardOverlayUsers = 0;
547
+ var initialVirtualKeyboardOverlaysContent = null;
548
+ function useVirtualKeyboard(options = {}) {
549
+ const {
550
+ containerRef,
551
+ isEnabled = true,
552
+ debounceDelay = 100,
553
+ visualViewportThreshold = 100
554
+ } = options;
555
+ const [state, setState] = React4.useState({
556
+ isVisible: false,
557
+ height: 0
558
+ });
559
+ const focusedElementRef = React4.useRef(null);
560
+ const debounceTimer = React4.useRef(null);
561
+ React4.useEffect(() => {
562
+ const vv = window.visualViewport;
563
+ const vk = getVirtualKeyboardApi();
564
+ function setKeyboardInsetHeightEnv(height) {
565
+ const element = (containerRef == null ? void 0 : containerRef.current) || document.documentElement;
566
+ if (vk) {
567
+ element.style.setProperty(
568
+ "--keyboard-inset-height",
569
+ `env(keyboard-inset-height, ${height}px)`
570
+ );
571
+ } else {
572
+ element.style.setProperty("--keyboard-inset-height", `${height}px`);
573
+ }
574
+ }
575
+ function setKeyboardState(nextState) {
576
+ setState(
577
+ (prevState) => prevState.isVisible === nextState.isVisible && prevState.height === nextState.height ? prevState : nextState
578
+ );
579
+ }
580
+ function resetKeyboardState() {
581
+ focusedElementRef.current = null;
582
+ setKeyboardInsetHeightEnv(0);
583
+ setKeyboardState({ isVisible: false, height: 0 });
584
+ }
585
+ if (!isEnabled) {
586
+ resetKeyboardState();
587
+ return;
588
+ }
589
+ function updateKeyboardState() {
590
+ if (debounceTimer.current) {
591
+ clearTimeout(debounceTimer.current);
592
+ }
593
+ debounceTimer.current = setTimeout(() => {
594
+ const active = getActiveElement() ?? focusedElementRef.current;
595
+ const inputIsFocused = active ? willOpenKeyboard(active) : false;
596
+ if (!inputIsFocused) {
597
+ resetKeyboardState();
598
+ return;
599
+ }
600
+ focusedElementRef.current = active;
601
+ if (vk == null ? void 0 : vk.overlaysContent) {
602
+ const keyboardHeight = vk.boundingRect.height;
603
+ setKeyboardInsetHeightEnv(keyboardHeight);
604
+ setKeyboardState({ isVisible: true, height: keyboardHeight });
605
+ return;
606
+ }
607
+ if (vv) {
608
+ const heightDiff = window.innerHeight - vv.height;
609
+ if (heightDiff > visualViewportThreshold) {
610
+ setKeyboardInsetHeightEnv(heightDiff);
611
+ setKeyboardState({ isVisible: true, height: heightDiff });
612
+ return;
613
+ }
614
+ }
615
+ resetKeyboardState();
616
+ }, debounceDelay);
617
+ }
618
+ function handleFocusIn(e) {
619
+ if (e.target instanceof HTMLElement && willOpenKeyboard(e.target)) {
620
+ focusedElementRef.current = e.target;
621
+ updateKeyboardState();
622
+ }
623
+ }
624
+ function handleFocusOut() {
625
+ requestAnimationFrame(() => {
626
+ focusedElementRef.current = getActiveElement();
627
+ updateKeyboardState();
628
+ });
629
+ }
630
+ document.addEventListener("focusin", handleFocusIn);
631
+ document.addEventListener("focusout", handleFocusOut);
632
+ if (vv) {
633
+ vv.addEventListener("resize", updateKeyboardState);
634
+ vv.addEventListener("scroll", updateKeyboardState);
635
+ }
636
+ if (vk) {
637
+ if (virtualKeyboardOverlayUsers === 0) {
638
+ initialVirtualKeyboardOverlaysContent = vk.overlaysContent;
639
+ vk.overlaysContent = true;
640
+ }
641
+ virtualKeyboardOverlayUsers++;
642
+ vk.addEventListener("geometrychange", updateKeyboardState);
643
+ }
644
+ focusedElementRef.current = getActiveElement();
645
+ updateKeyboardState();
646
+ return () => {
647
+ document.removeEventListener("focusin", handleFocusIn);
648
+ document.removeEventListener("focusout", handleFocusOut);
649
+ if (vv) {
650
+ vv.removeEventListener("resize", updateKeyboardState);
651
+ vv.removeEventListener("scroll", updateKeyboardState);
652
+ }
653
+ if (vk) {
654
+ vk.removeEventListener("geometrychange", updateKeyboardState);
655
+ virtualKeyboardOverlayUsers = Math.max(
656
+ 0,
657
+ virtualKeyboardOverlayUsers - 1
658
+ );
659
+ if (virtualKeyboardOverlayUsers === 0) {
660
+ vk.overlaysContent = initialVirtualKeyboardOverlaysContent ?? false;
661
+ initialVirtualKeyboardOverlaysContent = null;
662
+ }
663
+ }
664
+ if (debounceTimer.current) {
665
+ clearTimeout(debounceTimer.current);
666
+ }
667
+ resetKeyboardState();
668
+ };
669
+ }, [debounceDelay, isEnabled, visualViewportThreshold]);
670
+ return {
671
+ keyboardHeight: state.height,
672
+ isKeyboardOpen: state.isVisible
673
+ };
674
+ }
675
+ function getVirtualKeyboardApi() {
676
+ return isHTTPS() && "virtualKeyboard" in navigator ? navigator.virtualKeyboard : null;
677
+ }
678
+ function getActiveElement() {
679
+ var _a;
680
+ let activeElement = document.activeElement;
681
+ while (activeElement instanceof HTMLElement && ((_a = activeElement.shadowRoot) == null ? void 0 : _a.activeElement)) {
682
+ activeElement = activeElement.shadowRoot.activeElement;
683
+ }
684
+ return activeElement && willOpenKeyboard(activeElement) ? activeElement : null;
685
+ }
686
+
687
+ // src/hooks/use-keyboard-avoidance.ts
688
+ function useKeyboardAvoidance({
689
+ isEnabled,
690
+ containerRef,
691
+ onWillOpenKeyboard,
692
+ onDidOpenKeyboard
693
+ }) {
694
+ const [focusedElement, setFocusedElement] = React4.useState(
695
+ null
696
+ );
697
+ const keyboard = useVirtualKeyboard({
698
+ isEnabled,
699
+ containerRef
700
+ });
701
+ const handleFocusIn = useStableCallback(async (event) => {
702
+ var _a;
703
+ const element = event.target;
704
+ if (willOpenKeyboard(element) && ((_a = containerRef.current) == null ? void 0 : _a.contains(element))) {
705
+ await (onWillOpenKeyboard == null ? void 0 : onWillOpenKeyboard(event));
706
+ setFocusedElement(element);
707
+ }
708
+ });
709
+ const handleFocusOut = useStableCallback((event) => {
710
+ const element = event.target;
711
+ if (focusedElement === element) {
712
+ setFocusedElement(null);
713
+ }
714
+ });
715
+ React4.useEffect(() => {
716
+ if (!isEnabled) return;
717
+ document.addEventListener("focusin", handleFocusIn);
718
+ document.addEventListener("focusout", handleFocusOut);
719
+ return () => {
720
+ document.removeEventListener("focusin", handleFocusIn);
721
+ document.removeEventListener("focusout", handleFocusOut);
722
+ };
723
+ }, [isEnabled]);
724
+ React4.useEffect(() => {
725
+ const containerElement = containerRef.current;
726
+ if (!isEnabled || !focusedElement || !containerElement || !keyboard.isKeyboardOpen) {
727
+ return;
728
+ }
729
+ requestAnimationFrame(() => {
730
+ onDidOpenKeyboard == null ? void 0 : onDidOpenKeyboard(focusedElement);
731
+ });
732
+ }, [isEnabled, keyboard.isKeyboardOpen, focusedElement]);
733
+ return keyboard;
734
+ }
526
735
  function useSafeAreaInsets() {
527
736
  const [insets] = React4.useState(() => {
528
737
  const fallback = { top: 0, left: 0, right: 0, bottom: 0 };
@@ -665,13 +874,13 @@ function isScrollable(node, checkForOverflow) {
665
874
  return false;
666
875
  }
667
876
  const style = window.getComputedStyle(node);
668
- let isScrollable2 = /(auto|scroll)/.test(
877
+ let scrollable = /(auto|scroll)/.test(
669
878
  style.overflow + style.overflowX + style.overflowY
670
879
  );
671
- if (isScrollable2 && checkForOverflow) {
672
- isScrollable2 = node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth;
880
+ if (scrollable && checkForOverflow) {
881
+ scrollable = node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth;
673
882
  }
674
- return isScrollable2;
883
+ return scrollable;
675
884
  }
676
885
  function getScrollParent(node, checkForOverflow) {
677
886
  let scrollableNode = node;
@@ -683,17 +892,6 @@ function getScrollParent(node, checkForOverflow) {
683
892
  }
684
893
  return scrollableNode || document.scrollingElement || document.documentElement;
685
894
  }
686
- var nonTextInputTypes = /* @__PURE__ */ new Set([
687
- "checkbox",
688
- "radio",
689
- "range",
690
- "color",
691
- "file",
692
- "image",
693
- "button",
694
- "submit",
695
- "reset"
696
- ]);
697
895
  var preventScrollCount = 0;
698
896
  var restore;
699
897
  function usePreventScroll(options = {}) {
@@ -860,9 +1058,6 @@ function scrollIntoView(target) {
860
1058
  target = scrollable.parentElement;
861
1059
  }
862
1060
  }
863
- function willOpenKeyboard(target) {
864
- return target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type) || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable;
865
- }
866
1061
  function useSheetState({
867
1062
  isOpen,
868
1063
  onClosed: _onClosed,
@@ -907,108 +1102,6 @@ function useSheetState({
907
1102
  }, [state]);
908
1103
  return state;
909
1104
  }
910
- function useVirtualKeyboard(options = {}) {
911
- const {
912
- containerRef,
913
- isEnabled = true,
914
- debounceDelay = 100,
915
- includeContentEditable = true,
916
- visualViewportThreshold = 100
917
- } = options;
918
- const [state, setState] = React4.useState({
919
- isVisible: false,
920
- height: 0
921
- });
922
- const focusedElementRef = React4.useRef(null);
923
- const debounceTimer = React4.useRef(null);
924
- const isTextInput = useStableCallback((el) => {
925
- return (el == null ? void 0 : el.tagName) === "INPUT" || (el == null ? void 0 : el.tagName) === "TEXTAREA" || includeContentEditable && el instanceof HTMLElement && el.isContentEditable;
926
- });
927
- React4.useEffect(() => {
928
- if (!isEnabled) return;
929
- const vv = window.visualViewport;
930
- const vk = navigator.virtualKeyboard;
931
- function setKeyboardInsetHeightEnv(height) {
932
- const element = (containerRef == null ? void 0 : containerRef.current) || document.documentElement;
933
- if (window.isSecureContext) {
934
- element.style.setProperty(
935
- "--keyboard-inset-height",
936
- `env(keyboard-inset-height, ${height}px)`
937
- );
938
- } else {
939
- element.style.setProperty("--keyboard-inset-height", `${height}px`);
940
- }
941
- }
942
- function handleFocusIn(e) {
943
- if (e.target instanceof HTMLElement && isTextInput(e.target)) {
944
- focusedElementRef.current = e.target;
945
- updateKeyboardState();
946
- }
947
- }
948
- function handleFocusOut() {
949
- focusedElementRef.current = null;
950
- updateKeyboardState();
951
- }
952
- function updateKeyboardState() {
953
- if (debounceTimer.current) {
954
- clearTimeout(debounceTimer.current);
955
- }
956
- debounceTimer.current = setTimeout(() => {
957
- const active = focusedElementRef.current;
958
- const inputIsFocused = isTextInput(active);
959
- if (!inputIsFocused) {
960
- setKeyboardInsetHeightEnv(0);
961
- setState({ isVisible: false, height: 0 });
962
- return;
963
- }
964
- if (vv) {
965
- const heightDiff = window.innerHeight - vv.height;
966
- if (heightDiff > visualViewportThreshold) {
967
- setKeyboardInsetHeightEnv(heightDiff);
968
- setState({ isVisible: true, height: heightDiff });
969
- } else {
970
- setKeyboardInsetHeightEnv(0);
971
- setState({ isVisible: false, height: 0 });
972
- }
973
- }
974
- }, debounceDelay);
975
- }
976
- window.addEventListener("focusin", handleFocusIn);
977
- window.addEventListener("focusout", handleFocusOut);
978
- if (vv) {
979
- vv.addEventListener("resize", updateKeyboardState);
980
- vv.addEventListener("scroll", updateKeyboardState);
981
- }
982
- let currentOverlaysContent = false;
983
- if (vk) {
984
- currentOverlaysContent = vk.overlaysContent;
985
- vk.overlaysContent = true;
986
- }
987
- return () => {
988
- window.removeEventListener("focusin", handleFocusIn);
989
- window.removeEventListener("focusout", handleFocusOut);
990
- if (vv) {
991
- vv.removeEventListener("resize", updateKeyboardState);
992
- vv.removeEventListener("scroll", updateKeyboardState);
993
- }
994
- if (vk) {
995
- vk.overlaysContent = currentOverlaysContent;
996
- }
997
- if (debounceTimer.current) {
998
- clearTimeout(debounceTimer.current);
999
- }
1000
- };
1001
- }, [
1002
- debounceDelay,
1003
- includeContentEditable,
1004
- isEnabled,
1005
- visualViewportThreshold
1006
- ]);
1007
- return {
1008
- keyboardHeight: state.height,
1009
- isKeyboardOpen: state.isVisible
1010
- };
1011
- }
1012
1105
 
1013
1106
  // src/snap.ts
1014
1107
  function computeSnapPoints({
@@ -1183,11 +1276,6 @@ var Sheet = React4.forwardRef(
1183
1276
  type: "tween",
1184
1277
  ...reduceMotion ? REDUCED_MOTION_TWEEN_CONFIG : tweenConfig
1185
1278
  };
1186
- const keyboard = useVirtualKeyboard({
1187
- isEnabled: isOpen && avoidKeyboard,
1188
- containerRef: sheetRef
1189
- });
1190
- const disableDrag = keyboard.isKeyboardOpen || disableDragProp;
1191
1279
  const zIndex = react.useTransform(
1192
1280
  y,
1193
1281
  (val) => val + 2 >= closedY ? -1 : (style == null ? void 0 : style.zIndex) ?? 9999
@@ -1231,14 +1319,45 @@ var Sheet = React4.forwardRef(
1231
1319
  onComplete: () => updateSnap(snapIndex)
1232
1320
  });
1233
1321
  });
1322
+ const keyboard = useKeyboardAvoidance({
1323
+ isEnabled: isOpen && avoidKeyboard,
1324
+ containerRef: sheetRef,
1325
+ onWillOpenKeyboard: async () => {
1326
+ const lastSnapPoint = snapPoints[snapPoints.length - 1];
1327
+ if (lastSnapPoint && lastSnapPoint.snapIndex !== currentSnap) {
1328
+ await react.animate(y, lastSnapPoint.snapValueY, animationOptions);
1329
+ updateSnap(lastSnapPoint.snapIndex);
1330
+ }
1331
+ },
1332
+ onDidOpenKeyboard: (focusedElement) => {
1333
+ const sheetElement = sheetRef.current;
1334
+ if (!sheetElement) return;
1335
+ const inputRect = focusedElement.getBoundingClientRect();
1336
+ const containerRect = sheetElement.getBoundingClientRect();
1337
+ const scroller = sheetElement.querySelector(
1338
+ ".react-modal-sheet-content-scroller"
1339
+ );
1340
+ const scrollTarget = Math.max(
1341
+ inputRect.top - containerRect.top + scroller.scrollTop - inputRect.height,
1342
+ 0
1343
+ );
1344
+ requestAnimationFrame(() => {
1345
+ scroller.scrollTo({ top: scrollTarget, behavior: "smooth" });
1346
+ });
1347
+ }
1348
+ });
1349
+ const disableDrag = keyboard.isKeyboardOpen || disableDragProp;
1234
1350
  const blurActiveInput = useStableCallback(() => {
1351
+ var _a;
1235
1352
  const focusedElement = document.activeElement;
1236
- if (!focusedElement || !sheetRef.current) return;
1237
- const isInput = focusedElement.tagName === "INPUT" || focusedElement.tagName === "TEXTAREA";
1238
- if (isInput && sheetRef.current.contains(focusedElement)) {
1353
+ if (focusedElement && willOpenKeyboard(focusedElement) && ((_a = sheetRef.current) == null ? void 0 : _a.contains(focusedElement))) {
1239
1354
  focusedElement.blur();
1240
1355
  }
1241
1356
  });
1357
+ const onDragStart = useStableCallback((event, info) => {
1358
+ blurActiveInput();
1359
+ onDragStartProp == null ? void 0 : onDragStartProp(event, info);
1360
+ });
1242
1361
  const onDrag = useStableCallback((event, info) => {
1243
1362
  onDragProp == null ? void 0 : onDragProp(event, info);
1244
1363
  const currentY = y.get();
@@ -1247,10 +1366,6 @@ var Sheet = React4.forwardRef(
1247
1366
  if (velocity < 0) indicatorRotation.set(-10);
1248
1367
  y.set(Math.max(currentY + info.delta.y, 0));
1249
1368
  });
1250
- const onDragStart = useStableCallback((event, info) => {
1251
- blurActiveInput();
1252
- onDragStartProp == null ? void 0 : onDragStartProp(event, info);
1253
- });
1254
1369
  const onDragEnd = useStableCallback((event, info) => {
1255
1370
  blurActiveInput();
1256
1371
  onDragEndProp == null ? void 0 : onDragEndProp(event, info);
@@ -1307,29 +1422,6 @@ var Sheet = React4.forwardRef(
1307
1422
  height: sheetHeight,
1308
1423
  snapTo
1309
1424
  }));
1310
- React4.useEffect(() => {
1311
- if (isOpen && snapPoints.length > 0 && avoidKeyboard && keyboard.isKeyboardOpen) {
1312
- const focusedElement = document.activeElement;
1313
- const visibleSheetHeight = yInverted.get() - keyboard.keyboardHeight;
1314
- if (visibleSheetHeight <= 0 && focusedElement) {
1315
- const currentY = y.get();
1316
- const diffY = Math.max(currentY - Math.abs(visibleSheetHeight), 0);
1317
- requestAnimationFrame(() => {
1318
- var _a;
1319
- const inputRect = focusedElement.getBoundingClientRect();
1320
- const sheetRect = (_a = sheetRef.current) == null ? void 0 : _a.getBoundingClientRect();
1321
- let inputOffset = 0;
1322
- if (sheetRect) {
1323
- inputOffset = inputRect.top - sheetRect.top + inputRect.height;
1324
- }
1325
- react.animate(y, diffY - inputOffset, animationOptions);
1326
- });
1327
- return () => {
1328
- react.animate(y, currentY, animationOptions);
1329
- };
1330
- }
1331
- }
1332
- }, [isOpen, keyboard.isKeyboardOpen]);
1333
1425
  useModalEffect({
1334
1426
  y,
1335
1427
  detent,
@@ -1376,6 +1468,7 @@ var Sheet = React4.forwardRef(
1376
1468
  dragProps,
1377
1469
  indicatorRotation,
1378
1470
  avoidKeyboard,
1471
+ prefersReducedMotion,
1379
1472
  sheetBoundsRef,
1380
1473
  sheetRef,
1381
1474
  unstyled,