diff --git a/example/components/App.tsx b/example/components/App.tsx index 316d8df..bdcea1c 100644 --- a/example/components/App.tsx +++ b/example/components/App.tsx @@ -25,6 +25,7 @@ import { DisableDrag } from './DisableDrag'; import { ScrollableSnapPoints } from './ScrollableSnapPoints'; import { ContentHeight } from './ContentHeight'; import { AvoidKeyboard } from './AvoidKeyboard'; +import { ScrollableShadowDOM } from './ScrollableShadowDOM'; export function App() { return ( @@ -53,6 +54,16 @@ export function App() { } /> + + + + + } + /> + } /> + { +
  • + + + Scrollable (in a Shadow DOM) + +
  • +
  • diff --git a/example/components/ScrollableShadowDOM.tsx b/example/components/ScrollableShadowDOM.tsx new file mode 100644 index 0000000..17b59d0 --- /dev/null +++ b/example/components/ScrollableShadowDOM.tsx @@ -0,0 +1,90 @@ +import { useState, useEffect } from 'react'; +import { Sheet } from 'react-modal-sheet'; + +import { Button } from './common'; + +const SHADOW_ROOT_ID = 'react-modal-sheet-shadow-root'; + +export function ScrollableShadowDOM() { + const [isOpen, setOpen] = useState(false); + const [shadowRoot, setShadowRoot] = useState(null); + + useEffect(() => { + // Create a shadow DOM root dynamically if it doesn't already exist + let shadowRootContainer = document.getElementById(SHADOW_ROOT_ID); + if (!shadowRootContainer) { + shadowRootContainer = document.createElement('div'); + shadowRootContainer.id = SHADOW_ROOT_ID; + document.body.appendChild(shadowRootContainer); + } + + // Attach shadow root and update state + if (!shadowRoot) { + const root = shadowRootContainer.attachShadow({ mode: 'open' }); + setShadowRoot(root); + } + + return () => { + // Clean up the shadow root when the component is unmounted + if (shadowRoot) { + shadowRoot.host.remove(); + setShadowRoot(null); + } + }; + }, [shadowRoot]); + + const open = () => setOpen(true); + const close = () => setOpen(false); + + return ( + <> + + + {/* Render the Sheet only when the shadowRoot is ready */} + {shadowRoot && ( + + + + + + {/* We used inline styles because the CSS in document.head is outside the shadow DOM */} +
    + {Array.from({ length: 50 }).map((_, i) => ( +
    + {i} +
    + ))} +
    +
    +
    +
    + +
    + )} + + ); +} diff --git a/example/package-lock.json b/example/package-lock.json index 1d6a749..fc1bb75 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -35,9 +35,6 @@ ".yalc/react-modal-sheet": { "version": "3.3.0", "license": "MIT", - "dependencies": { - "@react-aria/utils": "3.25.3" - }, "engines": { "node": ">=18" }, diff --git a/src/use-prevent-scroll.ts b/src/use-prevent-scroll.ts index 0b60106..ee61474 100644 --- a/src/use-prevent-scroll.ts +++ b/src/use-prevent-scroll.ts @@ -157,8 +157,9 @@ function preventScrollMobileSafari() { let lastY = 0; const onTouchStart = (e: TouchEvent) => { + const target = e.composedPath()?.[0] as HTMLElement; // Store the nearest scrollable parent element from the element that the user touched. - scrollable = getScrollParent(e.target as Element, true); + scrollable = getScrollParent(target, true); if ( scrollable === document.documentElement && scrollable === document.body @@ -207,7 +208,7 @@ function preventScrollMobileSafari() { }; const onTouchEnd = (e: TouchEvent) => { - const target = e.target as HTMLElement; + const target = e.composedPath()?.[0] as HTMLElement; // Apply this change if we're not already focused on the target element if (willOpenKeyboard(target) && target !== document.activeElement) { @@ -225,7 +226,7 @@ function preventScrollMobileSafari() { }; const onFocus = (e: FocusEvent) => { - const target = e.target as HTMLElement; + const target = e.composedPath()?.[0] as HTMLElement; if (willOpenKeyboard(target)) { // Transform also needs to be applied in the focus event in cases where focus moves // other than tapping on an input directly, e.g. the next/previous buttons in the