diff --git a/.changeset/olive-bears-relate.md b/.changeset/olive-bears-relate.md
new file mode 100644
index 00000000..cacd7123
--- /dev/null
+++ b/.changeset/olive-bears-relate.md
@@ -0,0 +1,9 @@
+---
+'focus-trap-react': minor
+---
+
+<<<<<<< HEAD
+Bumps focus-trap to v6.8.0. The big new feature is opt-in Shadow DOM support in focus-trap (in tabbable), and a new `getShadowRoot` tabbable option exposed in a new `focusTrapOptions.tabbableOptions` configuration option.
+=======
+Bumps focus-trap to v6.8.1. The big new feature is opt-in Shadow DOM support in focus-trap (in tabbable), and new tabbable options exposed in a new `focusTrapOptions.tabbableOptions` configuration option.
+>>>>>>> 57d9caa (Add shadow DOM support with ft v6.8.1)
diff --git a/README.md b/README.md
index a7aece4a..4b68cfd4 100644
--- a/README.md
+++ b/README.md
@@ -141,7 +141,9 @@ ReactDOM.render(demo setReturnFocus option applied
View demo source
When integrated in an iframe, you may specify the document (of the said @@ -149,7 +150,20 @@
+ This focus trap contains tabbable elements that are inside
+ open and closed Shadow DOMs. It configures tabbable
to look for Shadow DOM
+ elements and provides a reference to the closed Shadow when requested.
+
+ + View demo source + +
diff --git a/demo/js/demo-with-shadow-dom.js b/demo/js/demo-with-shadow-dom.js new file mode 100644 index 00000000..106f8b66 --- /dev/null +++ b/demo/js/demo-with-shadow-dom.js @@ -0,0 +1,107 @@ +const React = require('react'); +const ReactDOM = require('react-dom'); +const FocusTrap = require('../../dist/focus-trap-react'); + +const createShadow = function (hostEl, isOpen) { + const containerEl = document.createElement('div'); + containerEl.id = 'with-shadow-dom-closed-container'; + containerEl.style = `border: 1px dotted black; margin-top: 10px; padding: 10px; background-color: ${ + isOpen ? 'transparent' : 'rgba(0, 0, 0, 0.05)' + };`; + containerEl.innerHTML = ` +
+ This field is inside a ${ + isOpen ? 'opened' : 'closed' + } Shadow DOM: +
+ + `; + + // use same styles as host + const styleLinkEl = document.createElement('link'); + styleLinkEl.setAttribute('rel', 'stylesheet'); + styleLinkEl.setAttribute('href', 'style.css'); + + const shadowEl = hostEl.attachShadow({ mode: isOpen ? 'open' : 'closed' }); + shadowEl.appendChild(styleLinkEl); + shadowEl.appendChild(containerEl); + + return shadowEl; +}; + +const DemoWithShadowDom = function () { + const [active, setActive] = React.useState(false); + const openedShadowHostRef = React.useRef(null); + const openedShadowRef = React.useRef(null); + const closedShadowHostRef = React.useRef(null); + const closedShadowRef = React.useRef(null); + + const handleTrapActivate = React.useCallback(function () { + setActive(true); + }, []); + + const handleTrapDeactivate = React.useCallback(function () { + setActive(false); + }, []); + + React.useEffect(function () { + if (openedShadowHostRef.current && !openedShadowRef.current) { + openedShadowRef.current = createShadow(openedShadowHostRef.current, true); + } + + if (closedShadowHostRef.current && !closedShadowRef.current) { + closedShadowRef.current = createShadow( + closedShadowHostRef.current, + false + ); + } + }, []); + + return ( + + ); +}; + +ReactDOM.render( +Some text
Link 1 @@ -51,12 +72,15 @@ FocusTrapExample.propTypes = { }; describe('FocusTrap', () => { + let TestFocusTrap; + beforeEach(() => { // This surpresses React error boundary logs for testing intentionally // thrown errors, like in some test cases in this suite. See discussion of // this here: https://github.com/facebook/react/issues/11098 jest.spyOn(console, 'error'); global.console.error.mockImplementation(() => {}); + TestFocusTrap = mkTestFocusTrap(); }); afterEach(() => { @@ -65,18 +89,18 @@ describe('FocusTrap', () => { describe('incorrect children prop usage', () => { it('throws an error if a non-element child is passed', () => { - expect(() => render(Child 1
Child 2
-Child 1
-