Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: dnm testing size and verdaccio shadowdom for size testing #7548

Closed
wants to merge 151 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
151 commits
Select commit Hold shift + click to select a range
c026270
Add `getRootNode` utility.
MahmoudElsayad Mar 11, 2024
9299cee
Update `getRootNode` util.
MahmoudElsayad Mar 11, 2024
71836e3
Update `getOwnerWindow` util.
MahmoudElsayad Mar 11, 2024
10893b9
Add tests for Shadow DOM handling using `getRootNode`.
MahmoudElsayad Mar 11, 2024
5f81d34
Update comment.
MahmoudElsayad Mar 11, 2024
bfb9429
Fix FocusScope.tsx in Shadow DOM.
MahmoudElsayad Mar 12, 2024
3448ed7
Add more test for FocusScope.test.js.
MahmoudElsayad Mar 12, 2024
0c07404
Fix another `useRestoreFocus` issue with restoring focus in `Keyboard…
MahmoudElsayad Mar 13, 2024
90906bf
Add tests for `getDeepActiveElement`
MahmoudElsayad Mar 13, 2024
314fc44
Add `useFocus` shadow DOM tests.
MahmoudElsayad Mar 13, 2024
9cb6c5a
Update `focusSafely`.
MahmoudElsayad Mar 13, 2024
67399bb
Update `useInteractionOutside` for Shadow DOM support.
MahmoudElsayad Mar 13, 2024
59c3705
Update `useFocusVisible` for Shadow DOM support.
MahmoudElsayad Mar 14, 2024
3c85408
Add `useInteractOutside` tests.
MahmoudElsayad Mar 14, 2024
61ba1b0
Add test for use case mentioned in issue #1472.
MahmoudElsayad Mar 14, 2024
75d7fa5
Add tests for `usePress` hook.
MahmoudElsayad Mar 15, 2024
db45ef4
Update the fix for `useInteractOutside` to use simpler one.
MahmoudElsayad Mar 15, 2024
f9b94a3
Update `useOverlay` to use composedPath.
MahmoudElsayad Mar 15, 2024
758575c
Tests refactor.
MahmoudElsayad Mar 15, 2024
25ef5c5
Revert `useOverlay` changes as it works correctly without these changes.
MahmoudElsayad Mar 17, 2024
0d4f70e
Fix types.
MahmoudElsayad Mar 18, 2024
3cf2091
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Mar 18, 2024
1d8c439
Fix types.
MahmoudElsayad Mar 18, 2024
e5dbda1
lint.
MahmoudElsayad Mar 18, 2024
ae7b76e
lint.
MahmoudElsayad Mar 18, 2024
aea5d8d
Fix failing tests.
MahmoudElsayad Mar 19, 2024
f2ca9b7
Fix failing tests.
MahmoudElsayad Mar 19, 2024
4d6ff95
Fix failing tests.
MahmoudElsayad Mar 19, 2024
4c53797
Test CI
MahmoudElsayad Mar 19, 2024
85b7146
Test CI
MahmoudElsayad Mar 19, 2024
a001f2a
Fix shadow DOM tests
MahmoudElsayad Mar 19, 2024
d00f0b2
Fix shadow DOM tests.
MahmoudElsayad Mar 20, 2024
e875828
Fix CI?
MahmoudElsayad Mar 20, 2024
b483e61
Fix CI?
MahmoudElsayad Mar 20, 2024
b8ef055
Fix CI?
MahmoudElsayad Mar 20, 2024
cc2a7c4
Re-add commented test.
MahmoudElsayad Mar 20, 2024
7447a79
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
ritz078 Mar 28, 2024
492d83f
Update `getRootNode` to handle iframes as well, and everything that …
MahmoudElsayad Mar 28, 2024
139a209
Merge remote-tracking branch 'upstream/main' into shadow-dom-enhancem…
MahmoudElsayad Apr 26, 2024
805561b
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Apr 27, 2024
a319991
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad May 7, 2024
dc2231d
Fix tests.
MahmoudElsayad May 7, 2024
bd536b6
Fix tests?
MahmoudElsayad May 7, 2024
f1aa64a
Fix tests?
MahmoudElsayad May 7, 2024
6426c08
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad May 9, 2024
7cafb6a
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad May 20, 2024
1a3e068
Fix tests.
MahmoudElsayad May 21, 2024
f1fe364
Fix tests.?
MahmoudElsayad May 21, 2024
24550d6
Fix tests.?
MahmoudElsayad May 21, 2024
b9a11ee
Fix tests.?
MahmoudElsayad May 22, 2024
97d73f2
Fix tests.?
MahmoudElsayad May 22, 2024
720ee18
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad May 22, 2024
6f80dbc
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger May 23, 2024
6ca6996
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger May 28, 2024
1f6ecf3
Apply suggestions from code review
MahmoudElsayad May 28, 2024
13278d9
Update packages/@react-aria/interactions/test/usePress.test.js
MahmoudElsayad May 28, 2024
93a5071
- Update tests to use `createShadowRoot` util.
MahmoudElsayad Jun 3, 2024
4ca6f75
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Jun 3, 2024
9fa339d
- Update tests and remove reactCompat.
MahmoudElsayad Jun 6, 2024
0586b9e
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Jun 6, 2024
90e52b9
- Leftover.
MahmoudElsayad Jun 6, 2024
f2b2d18
Merge remote-tracking branch 'origin/shadow-dom-enhancement-1-getRoot…
MahmoudElsayad Jun 6, 2024
717a8ab
- Revert changes to getFocusableTreeWalker.
MahmoudElsayad Jun 6, 2024
979a542
- Remove casting.
MahmoudElsayad Jun 6, 2024
fbe8f89
- return null in case element is disconnected in `getRootNode`.
MahmoudElsayad Jun 6, 2024
bd22291
- Casting.
MahmoudElsayad Jun 6, 2024
6548170
- Update unit test.
MahmoudElsayad Jun 6, 2024
db93e53
- Handle focus movements between shadow DOMs.
MahmoudElsayad Jun 25, 2024
98e255e
- TS fixes.
MahmoudElsayad Jun 25, 2024
820cd72
Merge remote-tracking branch 'upstream/main' into shadow-dom-enhancem…
MahmoudElsayad Jun 27, 2024
580e1f0
Merge remote-tracking branch 'refs/remotes/upstream/main' into shadow…
MahmoudElsayad Jun 27, 2024
e15086e
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Jun 27, 2024
9453cac
Update usePress.test.js
MahmoudElsayad Jun 27, 2024
debb4ba
Refactors and TS errors.
MahmoudElsayad Jun 28, 2024
cd6a2d7
Update fix.
MahmoudElsayad Jun 28, 2024
7673da1
Remove broken sandbox link.
MahmoudElsayad Jun 28, 2024
a8773c1
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Jun 28, 2024
60cb5da
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Jul 16, 2024
8d2a6dd
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Jul 19, 2024
52baba2
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Aug 5, 2024
afd28e9
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Aug 13, 2024
173cb03
Refactor `getRootNode` to improve root node handling.
MahmoudElsayad Aug 14, 2024
9d40d58
Use `getDeepActiveElement` inside focusSafely.ts to get the active el…
MahmoudElsayad Aug 14, 2024
40cd5dd
Refactor event listener registration
MahmoudElsayad Aug 14, 2024
72596b9
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Aug 14, 2024
ae30def
Remove `ownerDocument` fallback in usePress.ts
MahmoudElsayad Aug 14, 2024
c5ddb24
Refactor `createEventListener` for type-safe caching.
MahmoudElsayad Aug 14, 2024
4ce0c1c
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Sep 22, 2024
d75d68f
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Sep 24, 2024
2d84757
- Test out the updated getOwnerWindow to fix iframe focus issues.
MahmoudElsayad Sep 24, 2024
a690850
- Test out the updated getOwnerWindow to fix iframe focus issues.
MahmoudElsayad Sep 24, 2024
638d7eb
- Test?
MahmoudElsayad Sep 25, 2024
2c4a9bc
- Revert Focus scope changes, for testing.
MahmoudElsayad Sep 25, 2024
9210f8e
- Fix tests?
MahmoudElsayad Sep 25, 2024
3cb0874
- Fix tests?
MahmoudElsayad Sep 25, 2024
0181bc3
- Fix tests?
MahmoudElsayad Sep 26, 2024
930a2c3
- Revert the changes to getRootNode.
MahmoudElsayad Sep 26, 2024
1cecef0
- Revert `isElementInScope` as well.
MahmoudElsayad Sep 26, 2024
2bd25dd
- Test out if instance check failure across context for iframes is wh…
MahmoudElsayad Sep 26, 2024
bc7d188
- Replace the use of `instanceof` with `nodeType` to correctly identi…
MahmoudElsayad Sep 26, 2024
3b6a4cd
- Fix ESlint errors.
MahmoudElsayad Sep 26, 2024
6661416
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Sep 26, 2024
18f0519
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Sep 26, 2024
27d8d85
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Oct 16, 2024
22e75e6
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Oct 23, 2024
51932a5
- Update the usages of `instanceof` to use `nodeType` instead.
MahmoudElsayad Oct 24, 2024
541dd5f
Update packages/@react-aria/interactions/src/useFocusVisible.ts
MahmoudElsayad Oct 25, 2024
4b35260
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Oct 25, 2024
3fa8c44
- Update the usages of `instanceof` to use `nodeType` instead.
MahmoudElsayad Oct 25, 2024
ab9f8db
- Lint.
MahmoudElsayad Oct 25, 2024
47be393
- Lint.
MahmoudElsayad Oct 25, 2024
54cfe24
- Update `getDeepActiveElement` to accept an optional document or sha…
MahmoudElsayad Oct 31, 2024
e918e38
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Oct 31, 2024
95a6b64
- Add extra unit test for `getDeepActiveElement`.
MahmoudElsayad Nov 1, 2024
c830aab
- Update `getDeepActiveElement` to always rely on `getRootNode`.
MahmoudElsayad Nov 1, 2024
319617f
- Update `getDeepActiveElement` to always rely on `getRootNode`.
MahmoudElsayad Nov 1, 2024
3e1730e
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
MahmoudElsayad Nov 1, 2024
0d0af54
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Nov 1, 2024
563501a
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Nov 13, 2024
5aeb024
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Dec 3, 2024
03c23c4
refactor usePress to still have global listeners for cleanup across b…
snowystinger Dec 3, 2024
cf3f567
fix lint and test
snowystinger Dec 4, 2024
64348e4
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Dec 11, 2024
fc82be0
restore remaining document level listeners
snowystinger Dec 12, 2024
b62d83f
fix tests
snowystinger Dec 13, 2024
366565c
fix lint
snowystinger Dec 13, 2024
edc9892
simplify
snowystinger Dec 16, 2024
9b08f75
Update packages/@react-aria/focus/src/FocusScope.tsx
snowystinger Dec 16, 2024
39543de
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Dec 16, 2024
4c4e006
fix autofocus
snowystinger Dec 16, 2024
bbdb342
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Dec 18, 2024
96b9166
minor test updates to preserve test intent
LFDanLu Dec 18, 2024
87b3542
review comments
snowystinger Dec 19, 2024
650bf4a
fix esm test
snowystinger Dec 23, 2024
6e2068b
wip: dnm testing size and verdaccio shadowdom
snowystinger Dec 23, 2024
7d187c4
fix lint
snowystinger Dec 23, 2024
1660aad
fix lint
snowystinger Dec 23, 2024
edd5019
Merge branch 'main' into for-size-testing
snowystinger Dec 23, 2024
d90cc98
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Jan 13, 2025
c43a15e
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Jan 16, 2025
0d962db
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Jan 16, 2025
9bf04b1
check in speed tests
snowystinger Jan 16, 2025
4c22e04
Merge branch 'shadow-dom-enhancement-1-getRootNode' into for-size-tes…
snowystinger Jan 16, 2025
613e129
fix lint
snowystinger Jan 16, 2025
21b80bd
fix lint
snowystinger Jan 16, 2025
a549500
get comment in the circle job hopefully
snowystinger Jan 16, 2025
ba6fbd7
use shadow tree walker to see impact on aria hide outside
snowystinger Jan 16, 2025
95e6162
track time
snowystinger Jan 17, 2025
5bf5bb7
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Jan 20, 2025
a4f35b1
Merge branch 'main' into shadow-dom-enhancement-1-getRootNode
snowystinger Jan 22, 2025
9e6e238
Merge branch 'shadow-dom-enhancement-1-getRootNode' into for-size-tes…
snowystinger Jan 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion .circleci/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,21 @@ async function run() {
break;
}
}
} else if (process.env.CIRCLE_BRANCH === 'main') {
} else if (true) {
console.log(`Verdaccio builds:
[CRA Test App](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/build/index.html)
[NextJS Test App](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/next/index.html)
[RAC Tailwind Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/rac-tailwind/index.html)
[RAC Spectrum + Tailwind Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/rac-spectrum-tailwind/index.html)
[S2 Parcel Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/s2-parcel-example/index.html)
[S2 Webpack Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/s2-webpack-5-example/index.html)
[CRA Test App Size](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/build-stats.txt)
[NextJS App Size](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/next-build-stats.txt)
[Publish stats](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/publish.json)
[Size diff since last release](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/size-diff.txt)
[Docs](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/docs/index.html)
[Storybook](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/storybook/index.html)
[S2 Storybook](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/storybook-s2/index.html)`);
//If it isn't a PR commit, then we are on main. Create a comment for the test app and docs build
await octokit.repos.createCommitComment({
owner: 'adobe',
Expand Down Expand Up @@ -71,6 +85,20 @@ async function run() {
}
console.log('PR number to comment on', pr);
if (pr != null) {
console.log(`Verdaccio builds:
[CRA Test App](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/build/index.html)
[NextJS Test App](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/next/index.html)
[RAC Tailwind Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/rac-tailwind/index.html)
[RAC Spectrum + Tailwind Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/rac-spectrum-tailwind/index.html)
[S2 Parcel Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/s2-parcel-example/index.html)
[S2 Webpack Example](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/s2-webpack-5-example/index.html)
[CRA Test App Size](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/build-stats.txt)
[NextJS App Size](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/next-build-stats.txt)
[Publish stats](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/publish.json)
[Size diff since last release](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/publish-stats/size-diff.txt)
[Docs](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/verdaccio/docs/index.html)
[Storybook](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/storybook/index.html)
[S2 Storybook](https://reactspectrum.blob.core.windows.net/reactspectrum/${process.env.CIRCLE_SHA1}/storybook-s2/index.html)`);
try {
await octokit.issues.createComment({
owner: 'adobe',
Expand Down
3 changes: 0 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -647,9 +647,6 @@ workflows:
requires:
- install
- docs-verdaccio:
filters:
branches:
only: main
requires:
- install
- deploy:
Expand Down
29 changes: 29 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,32 @@ This codebase contains a modified portion of code from Yarn berry which can be o
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


-------------------------------------------------------------------------------
This codebase contains a modified portion of code from Yarn berry which can be obtained at:
* SOURCE:
* https://github.com/microsoft/tabster

* LICENSE:
MIT License

Copyright (c) Microsoft Corporation.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
73 changes: 47 additions & 26 deletions packages/@react-aria/focus/src/FocusScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@
* governing permissions and limitations under the License.
*/

import {
createShadowTreeWalker,
getActiveElement,
getOwnerDocument,
isAndroid,
isChrome,
isFocusable,
isTabbable,
ShadowTreeWalker,
useLayoutEffect
} from '@react-aria/utils';
import {FocusableElement, RefObject} from '@react-types/shared';
import {focusSafely} from './focusSafely';
import {getInteractionModality} from '@react-aria/interactions';
import {getOwnerDocument, isAndroid, isChrome, isFocusable, isTabbable, useLayoutEffect} from '@react-aria/utils';
import {isElementVisible} from './isElementVisible';
import React, {ReactNode, useContext, useEffect, useMemo, useRef} from 'react';

Expand Down Expand Up @@ -55,7 +65,7 @@ export interface FocusManager {
focusPrevious(opts?: FocusManagerOptions): FocusableElement | null,
/** Moves focus to the first focusable or tabbable element in the focus scope. */
focusFirst(opts?: FocusManagerOptions): FocusableElement | null,
/** Moves focus to the last focusable or tabbable element in the focus scope. */
/** Moves focus to the last focusable or tabbable element in the focus scope. */
focusLast(opts?: FocusManagerOptions): FocusableElement | null
}

Expand Down Expand Up @@ -144,7 +154,7 @@ export function FocusScope(props: FocusScopeProps) {
// This needs to be an effect so that activeScope is updated after the FocusScope tree is complete.
// It cannot be a useLayoutEffect because the parent of this node hasn't been attached in the tree yet.
useEffect(() => {
const activeElement = getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined).activeElement;
const activeElement = getActiveElement(getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined));
let scope: TreeNode | null = null;

if (isElementInScope(activeElement, scopeRef.current)) {
Expand Down Expand Up @@ -208,7 +218,7 @@ function createFocusManagerForScope(scopeRef: React.RefObject<Element[] | null>)
focusNext(opts: FocusManagerOptions = {}) {
let scope = scopeRef.current!;
let {from, tabbable, wrap, accept} = opts;
let node = from || getOwnerDocument(scope[0]).activeElement!;
let node = from || getActiveElement(getOwnerDocument(scope[0] ?? undefined))!;
let sentinel = scope[0].previousElementSibling!;
let scopeRoot = getScopeRoot(scope);
let walker = getFocusableTreeWalker(scopeRoot, {tabbable, accept}, scope);
Expand All @@ -226,11 +236,11 @@ function createFocusManagerForScope(scopeRef: React.RefObject<Element[] | null>)
focusPrevious(opts: FocusManagerOptions = {}) {
let scope = scopeRef.current!;
let {from, tabbable, wrap, accept} = opts;
let node = from || getOwnerDocument(scope[0]).activeElement!;
let node = from || getActiveElement(getOwnerDocument(scope[0] ?? undefined))!;
let sentinel = scope[scope.length - 1].nextElementSibling!;
let scopeRoot = getScopeRoot(scope);
let walker = getFocusableTreeWalker(scopeRoot, {tabbable, accept}, scope);
walker.currentNode = isElementInScope(node, scope) ? node : sentinel;
walker.currentNode = isElementInScope(node, scope) ? node : sentinel;
let previousNode = walker.previousNode() as FocusableElement;
if (!previousNode && wrap) {
walker.currentNode = sentinel;
Expand Down Expand Up @@ -308,7 +318,7 @@ function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: bo
return;
}

let focusedElement = ownerDocument.activeElement;
let focusedElement = getActiveElement(ownerDocument);
let scope = scopeRef.current;
if (!scope || !isElementInScope(focusedElement, scope)) {
return;
Expand Down Expand Up @@ -364,9 +374,10 @@ function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: bo
let shouldSkipFocusRestore = (modality === 'virtual' || modality === null) && isAndroid() && isChrome();

// Use document.activeElement instead of e.relatedTarget so we can tell if user clicked into iframe
if (!shouldSkipFocusRestore && ownerDocument.activeElement && shouldContainFocus(scopeRef) && !isElementInChildScope(ownerDocument.activeElement, scopeRef)) {
let activeElement = getActiveElement(ownerDocument);
if (!shouldSkipFocusRestore && activeElement && shouldContainFocus(scopeRef) && !isElementInChildScope(activeElement, scopeRef)) {
activeScope = scopeRef;
if (ownerDocument.body.contains(e.target)) {
if (e.target.isConnected) {
focusedNode.current = e.target;
focusedNode.current?.focus();
} else if (activeScope.current) {
Expand Down Expand Up @@ -490,7 +501,7 @@ function useAutoFocus(scopeRef: RefObject<Element[] | null>, autoFocus?: boolean
if (autoFocusRef.current) {
activeScope = scopeRef;
const ownerDocument = getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined);
if (!isElementInScope(ownerDocument.activeElement, activeScope.current) && scopeRef.current) {
if (!isElementInScope(getActiveElement(ownerDocument), activeScope.current) && scopeRef.current) {
focusFirstInScope(scopeRef.current);
}
}
Expand Down Expand Up @@ -543,7 +554,7 @@ function shouldRestoreFocus(scopeRef: ScopeRef) {
function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: boolean, contain?: boolean) {
// create a ref during render instead of useLayoutEffect so the active element is saved before a child with autoFocus=true mounts.
// eslint-disable-next-line no-restricted-globals
const nodeToRestoreRef = useRef(typeof document !== 'undefined' ? getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined).activeElement as FocusableElement : null);
const nodeToRestoreRef = useRef(typeof document !== 'undefined' ? getActiveElement(getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined)) as FocusableElement : null);

// restoring scopes should all track if they are active regardless of contain, but contain already tracks it plus logic to contain the focus
// restoring-non-containing scopes should only care if they become active so they can perform the restore
Expand All @@ -558,7 +569,7 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
// If focusing an element in a child scope of the currently active scope, the child becomes active.
// Moving out of the active scope to an ancestor is not allowed.
if ((!activeScope || isAncestorScope(activeScope, scopeRef)) &&
isElementInScope(ownerDocument.activeElement, scopeRef.current)
isElementInScope(getActiveElement(ownerDocument), scopeRef.current)
) {
activeScope = scopeRef;
}
Expand All @@ -570,7 +581,7 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
ownerDocument.removeEventListener('focusin', onFocus, false);
scope?.forEach(element => element.removeEventListener('focusin', onFocus, false));
};
// eslint-disable-next-line react-hooks/exhaustive-deps
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scopeRef, contain]);

useLayoutEffect(() => {
Expand Down Expand Up @@ -606,7 +617,7 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
walker.currentNode = focusedElement;
let nextElement = (e.shiftKey ? walker.previousNode() : walker.nextNode()) as FocusableElement;

if (!nodeToRestore || !ownerDocument.body.contains(nodeToRestore) || nodeToRestore === ownerDocument.body) {
if (!nodeToRestore || !nodeToRestore.isConnected || nodeToRestore === ownerDocument.body) {
nodeToRestore = undefined;
treeNode.nodeToRestore = undefined;
}
Expand All @@ -626,9 +637,9 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
if (nextElement) {
focusElement(nextElement, true);
} else {
// If there is no next element and the nodeToRestore isn't within a FocusScope (i.e. we are leaving the top level focus scope)
// then move focus to the body.
// Otherwise restore focus to the nodeToRestore (e.g menu within a popover -> tabbing to close the menu should move focus to menu trigger)
// If there is no next element and the nodeToRestore isn't within a FocusScope (i.e. we are leaving the top level focus scope)
// then move focus to the body.
// Otherwise restore focus to the nodeToRestore (e.g menu within a popover -> tabbing to close the menu should move focus to menu trigger)
if (!isElementInAnyScope(nodeToRestore)) {
focusedElement.blur();
} else {
Expand All @@ -639,12 +650,12 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
};

if (!contain) {
ownerDocument.addEventListener('keydown', onKeyDown, true);
ownerDocument.addEventListener('keydown', onKeyDown as EventListener, true);
}

return () => {
if (!contain) {
ownerDocument.removeEventListener('keydown', onKeyDown, true);
ownerDocument.removeEventListener('keydown', onKeyDown as EventListener, true);
}
};
}, [scopeRef, restoreFocus, contain]);
Expand All @@ -670,11 +681,12 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
let nodeToRestore = treeNode.nodeToRestore;

// if we already lost focus to the body and this was the active scope, then we should attempt to restore
let activeElement = getActiveElement(ownerDocument);
if (
restoreFocus
&& nodeToRestore
&& (
((ownerDocument.activeElement && isElementInChildScope(ownerDocument.activeElement, scopeRef)) || (ownerDocument.activeElement === ownerDocument.body && shouldRestoreFocus(scopeRef)))
((activeElement && isElementInChildScope(activeElement, scopeRef)) || (activeElement === ownerDocument.body && shouldRestoreFocus(scopeRef)))
)
) {
// freeze the focusScopeTree so it persists after the raf, otherwise during unmount nodes are removed from it
Expand Down Expand Up @@ -723,10 +735,19 @@ function restoreFocusToElement(node: FocusableElement) {
* Create a [TreeWalker]{@link https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker}
* that matches all focusable/tabbable elements.
*/
export function getFocusableTreeWalker(root: Element, opts?: FocusManagerOptions, scope?: Element[]) {
export function getFocusableTreeWalker(root: Element, opts?: FocusManagerOptions, scope?: Element[]): ShadowTreeWalker {
let filter = opts?.tabbable ? isTabbable : isFocusable;
let walker = getOwnerDocument(root).createTreeWalker(
root,

// Ensure that root is an Element or fall back appropriately
let rootElement = root?.nodeType === Node.ELEMENT_NODE ? (root as Element) : null;

// Determine the document to use
let doc = getOwnerDocument(rootElement);

// Create a TreeWalker, ensuring the root is an Element or Document
let walker = createShadowTreeWalker(
doc,
root || doc,
NodeFilter.SHOW_ELEMENT,
{
acceptNode(node) {
Expand Down Expand Up @@ -766,7 +787,7 @@ export function createFocusManager(ref: RefObject<Element | null>, defaultOption
return null;
}
let {from, tabbable = defaultOptions.tabbable, wrap = defaultOptions.wrap, accept = defaultOptions.accept} = opts;
let node = from || getOwnerDocument(root).activeElement;
let node = from || getActiveElement(getOwnerDocument(root));
let walker = getFocusableTreeWalker(root, {tabbable, accept});
if (root.contains(node)) {
walker.currentNode = node!;
Expand All @@ -787,7 +808,7 @@ export function createFocusManager(ref: RefObject<Element | null>, defaultOption
return null;
}
let {from, tabbable = defaultOptions.tabbable, wrap = defaultOptions.wrap, accept = defaultOptions.accept} = opts;
let node = from || getOwnerDocument(root).activeElement;
let node = from || getActiveElement(getOwnerDocument(root));
let walker = getFocusableTreeWalker(root, {tabbable, accept});
if (root.contains(node)) {
walker.currentNode = node!;
Expand Down Expand Up @@ -842,7 +863,7 @@ export function createFocusManager(ref: RefObject<Element | null>, defaultOption
};
}

function last(walker: TreeWalker) {
function last(walker: ShadowTreeWalker) {
let next: FocusableElement | undefined = undefined;
let last: FocusableElement;
do {
Expand Down
Loading
Loading