From 5141a18a7e95f8234e3ab50e575854754f56150b Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Sun, 1 May 2022 22:00:50 +1000 Subject: [PATCH] correct react 18 integration --- CHANGELOG.md | 9 +++++++++ interfaces.d.ts | 1 + package.json | 10 ++++++++-- src/Trap.js | 40 +++++++++++++++++++++------------------- yarn.lock | 21 ++++++++++++++++++++- 5 files changed, 59 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 807af9e..daff17a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [2.8.1](https://github.com/theKashey/react-focus-lock/compare/v2.8.0...v2.8.1) (2022-02-14) + + +### Bug Fixes + +* correct shadow-dom specification, fixes [#188](https://github.com/theKashey/react-focus-lock/issues/188) ([159bb98](https://github.com/theKashey/react-focus-lock/commit/159bb9861265793117524eb43a7475fc2c96c994)) + + + # [2.8.0](https://github.com/theKashey/react-focus-lock/compare/v2.7.1...v2.8.0) (2022-02-14) diff --git a/interfaces.d.ts b/interfaces.d.ts index 57c57ac..06d10f4 100644 --- a/interfaces.d.ts +++ b/interfaces.d.ts @@ -117,6 +117,7 @@ export interface AutoFocusProps { } export interface FreeFocusProps { + children: React.ReactNode; className?: string; } diff --git a/package.json b/package.json index ad3ddef..78e6a0e 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,13 @@ "url": "https://github.com/theKashey/react-focus-lock/issues" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } }, "devDependencies": { "@babel/cli": "^7.0.0", @@ -64,7 +70,7 @@ "@storybook/addon-actions": "^5.1.8", "@storybook/addon-links": "^5.1.8", "@storybook/react": "^5.1.8", - "@types/react": "^16.8.19", + "@types/react": "^18.0.8", "babel-eslint": "^10.0.1", "babel-loader": "^8.0.4", "babel-plugin-transform-react-remove-prop-types": "^0.4.19", diff --git a/src/Trap.js b/src/Trap.js index de1ebf8..7933084 100644 --- a/src/Trap.js +++ b/src/Trap.js @@ -1,9 +1,10 @@ +/* eslint-disable no-mixed-operators */ import * as React from 'react'; import PropTypes from 'prop-types'; import withSideEffect from 'react-clientside-effect'; -import moveFocusInside, {focusInside, focusIsHidden, getFocusabledIn} from 'focus-lock'; -import {deferAction} from './util'; -import {mediumFocus, mediumBlur, mediumEffect} from './medium'; +import moveFocusInside, { focusInside, focusIsHidden, getFocusabledIn } from 'focus-lock'; +import { deferAction } from './util'; +import { mediumFocus, mediumBlur, mediumEffect } from './medium'; const focusOnBody = () => ( document && document.activeElement === document.body @@ -25,7 +26,7 @@ const focusWhitelisted = activeElement => ( ); const recordPortal = (observerNode, portaledElement) => { - lastPortaledElement = {observerNode, portaledElement}; + lastPortaledElement = { observerNode, portaledElement }; }; const focusIsPortaledPair = element => ( @@ -68,15 +69,16 @@ const focusWasOutside = (crossFrameOption) => { }; const checkInHost = (check, el, boundary) => ( - el + el && ( // find host equal to active element and check nested active element - && (el.host === check && (!el.activeElement || boundary.contains(el.activeElement)) + (el.host === check && (!el.activeElement || boundary.contains(el.activeElement)) // dive up - || el.parentNode && checkInHost(check, el.parentNode, boundary))) + || (el.parentNode && checkInHost(check, el.parentNode, boundary)))) +); -const withinHost = (activeElement, workingArea) => { - return workingArea.some(area => checkInHost(activeElement, area, area)) -} +const withinHost = (activeElement, workingArea) => ( + workingArea.some(area => checkInHost(activeElement, area, area)) +); const activateTrap = () => { let result = false; @@ -103,8 +105,8 @@ const activateTrap = () => { && !( // active element is "inside" working area (focusInside(workingArea) || ( - // check for shadow-dom contained elements - activeElement && withinHost(activeElement, workingArea)) + // check for shadow-dom contained elements + activeElement && withinHost(activeElement, workingArea)) ) || focusIsPortaledPair(activeElement, workingNode) ) @@ -116,7 +118,7 @@ const activateTrap = () => { } document.body.focus(); } else { - result = moveFocusInside(workingArea, lastActiveFocus, {focusOptions}); + result = moveFocusInside(workingArea, lastActiveFocus, { focusOptions }); lastPortaledElement = {}; } } @@ -128,12 +130,12 @@ const activateTrap = () => { if (document) { const newActiveElement = document && document.activeElement; const allNodes = getFocusabledIn(workingArea); - const focusedIndex = allNodes.map(({node}) => node).indexOf(newActiveElement); + const focusedIndex = allNodes.map(({ node }) => node).indexOf(newActiveElement); if (focusedIndex > -1) { // remove old focus allNodes - .filter(({guard, node}) => guard && node.dataset.focusAutoGuard) - .forEach(({node}) => node.removeAttribute('tabIndex')); + .filter(({ guard, node }) => guard && node.dataset.focusAutoGuard) + .forEach(({ node }) => node.removeAttribute('tabIndex')); autoGuard(focusedIndex, allNodes.length, +1, allNodes); autoGuard(focusedIndex, -1, -1, allNodes); @@ -167,7 +169,7 @@ const onFocus = (event) => { const FocusWatcher = () => null; -const FocusTrap = ({children}) => ( +const FocusTrap = ({ children }) => (
{children}
@@ -199,7 +201,7 @@ const detachHandler = () => { function reducePropsToState(propsList) { return propsList - .filter(({disabled}) => !disabled); + .filter(({ disabled }) => !disabled); } function handleStateChangeOnClient(traps) { @@ -216,7 +218,7 @@ function handleStateChangeOnClient(traps) { if (lastTrap && !sameTrap) { lastTrap.onDeactivation(); // return focus only of last trap was removed - if (!traps.filter(({id}) => id === lastTrap.id).length) { + if (!traps.filter(({ id }) => id === lastTrap.id).length) { // allow defer is no other trap is awaiting restore lastTrap.returnFocus(!trap); } diff --git a/yarn.lock b/yarn.lock index 5289feb..d676b16 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1735,7 +1735,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.8.19": +"@types/react@*": version "16.9.36" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.36.tgz#ade589ff51e2a903e34ee4669e05dbfa0c1ce849" integrity sha512-mGgUb/Rk/vGx4NCvquRuSH0GHBQKb1OqpGS9cT9lFxlTLHZgkksgI60TuIxubmn7JuCb+sENHhQciqa0npm0AQ== @@ -1743,6 +1743,20 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/react@^18.0.8": + version "18.0.8" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.8.tgz#a051eb380a9fbcaa404550543c58e1cf5ce4ab87" + integrity sha512-+j2hk9BzCOrrOSJASi5XiOyBbERk9jG5O73Ya4M0env5Ixi6vUNli4qy994AINcEF+1IEHISYFfIT4zwr++LKw== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" @@ -4136,6 +4150,11 @@ csstype@^2.2.0, csstype@^2.5.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b" integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w== +csstype@^3.0.2: + version "3.0.11" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" + integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"