react-focus-lock
Advanced tools
| "use strict"; | ||
| var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| exports.default = exports.hiddenGuard = void 0; | ||
| var _react = _interopRequireDefault(require("react")); | ||
| var _propTypes = _interopRequireDefault(require("prop-types")); | ||
| var hiddenGuard = { | ||
| width: '1px', | ||
| height: '0px', | ||
| padding: 0, | ||
| overflow: 'hidden', | ||
| position: 'fixed', | ||
| top: '1px', | ||
| left: '1px' | ||
| }; | ||
| exports.hiddenGuard = hiddenGuard; | ||
| var InFocusGuard = function InFocusGuard(_ref) { | ||
| var children = _ref.children; | ||
| return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement("div", { | ||
| key: "guard-first", | ||
| "data-focus-guard": true, | ||
| "data-focus-auto-guard": true, | ||
| style: hiddenGuard | ||
| }), children, children && _react.default.createElement("div", { | ||
| key: "guard-last", | ||
| "data-focus-guard": true, | ||
| "data-focus-auto-guard": true, | ||
| style: hiddenGuard | ||
| })); | ||
| }; | ||
| InFocusGuard.propTypes = process.env.NODE_ENV !== "production" ? { | ||
| children: _propTypes.default.node | ||
| } : {}; | ||
| var _default = InFocusGuard; | ||
| exports.default = _default; |
| import React from 'react'; | ||
| import PropTypes from 'prop-types'; | ||
| export var hiddenGuard = { | ||
| width: '1px', | ||
| height: '0px', | ||
| padding: 0, | ||
| overflow: 'hidden', | ||
| position: 'fixed', | ||
| top: '1px', | ||
| left: '1px' | ||
| }; | ||
| var InFocusGuard = function InFocusGuard(_ref) { | ||
| var children = _ref.children; | ||
| return React.createElement(React.Fragment, null, React.createElement("div", { | ||
| key: "guard-first", | ||
| "data-focus-guard": true, | ||
| "data-focus-auto-guard": true, | ||
| style: hiddenGuard | ||
| }), children, children && React.createElement("div", { | ||
| key: "guard-last", | ||
| "data-focus-guard": true, | ||
| "data-focus-auto-guard": true, | ||
| style: hiddenGuard | ||
| })); | ||
| }; | ||
| InFocusGuard.propTypes = process.env.NODE_ENV !== "production" ? { | ||
| children: PropTypes.node | ||
| } : {}; | ||
| export default InFocusGuard; |
Sorry, the diff of this file is too big to display
@@ -26,2 +26,8 @@ "use strict"; | ||
| }); | ||
| Object.defineProperty(exports, "InFocusGuard", { | ||
| enumerable: true, | ||
| get: function get() { | ||
| return _FocusGuard.default; | ||
| } | ||
| }); | ||
| exports.default = void 0; | ||
@@ -37,3 +43,5 @@ | ||
| var _FocusGuard = _interopRequireDefault(require("./FocusGuard")); | ||
| var _default = _Lock.default; | ||
| exports.default = _default; |
+13
-12
@@ -38,2 +38,4 @@ "use strict"; | ||
| var _FocusGuard = require("./FocusGuard"); | ||
| var RenderChildren = function RenderChildren(_ref) { | ||
@@ -48,11 +50,3 @@ var children = _ref.children; | ||
| var Fragment = _react.default.Fragment ? _react.default.Fragment : RenderChildren; | ||
| var hidden = { | ||
| width: '1px', | ||
| height: '0px', | ||
| padding: 0, | ||
| overflow: 'hidden', | ||
| position: 'fixed', | ||
| top: '1px', | ||
| left: '1px' | ||
| }; | ||
| var emptyArray = []; | ||
@@ -139,2 +133,4 @@ var FocusLock = | ||
| whiteList = _this$props.whiteList, | ||
| _this$props$shards = _this$props.shards, | ||
| shards = _this$props$shards === void 0 ? emptyArray : _this$props$shards, | ||
| _this$props$as = _this$props.as, | ||
@@ -158,3 +154,3 @@ Container = _this$props$as === void 0 ? 'div' : _this$props$as, | ||
| tabIndex: disabled ? -1 : 0, | ||
| style: hidden | ||
| style: _FocusGuard.hiddenGuard | ||
| }), // nearest focus guard | ||
@@ -165,3 +161,3 @@ _react.default.createElement("div", { | ||
| tabIndex: disabled ? -1 : 1, | ||
| style: hidden | ||
| style: _FocusGuard.hiddenGuard | ||
| })], _react.default.createElement(Container, (0, _extends2.default)({ | ||
@@ -179,2 +175,3 @@ ref: this.setObserveNode | ||
| whiteList: whiteList, | ||
| shards: shards, | ||
| onActivation: this.onActivation, | ||
@@ -185,3 +182,3 @@ onDeactivation: this.onDeactivation | ||
| tabIndex: disabled ? -1 : 0, | ||
| style: hidden | ||
| style: _FocusGuard.hiddenGuard | ||
| })); | ||
@@ -204,2 +201,5 @@ } | ||
| whiteList: _propTypes.default.func, | ||
| shards: _propTypes.default.arrayOf(_propTypes.default.shape({ | ||
| current: _propTypes.default.instanceOf(Element) | ||
| })), | ||
| as: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.func, _propTypes.default.object]), | ||
@@ -220,2 +220,3 @@ lockProps: _propTypes.default.object, | ||
| whiteList: undefined, | ||
| shards: undefined, | ||
| as: 'div', | ||
@@ -222,0 +223,0 @@ lockProps: {}, |
+70
-15
@@ -12,2 +12,4 @@ "use strict"; | ||
| var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); | ||
| var _react = _interopRequireDefault(require("react")); | ||
@@ -54,2 +56,23 @@ | ||
| function autoGuard(startIndex, end, step, allNodes) { | ||
| var lastGuard = null; | ||
| var i = startIndex; | ||
| do { | ||
| var node = allNodes[i]; | ||
| if (node.guard) { | ||
| lastGuard = node; | ||
| } else if (node.lockItem) { | ||
| lastGuard = null; | ||
| } else { | ||
| break; | ||
| } | ||
| } while ((i += step) !== end); | ||
| if (lastGuard) { | ||
| lastGuard.node.tabIndex = 0; | ||
| } | ||
| } | ||
| var activateTrap = function activateTrap() { | ||
@@ -62,19 +85,51 @@ var result = false; | ||
| persistentFocus = _lastActiveTrap.persistentFocus, | ||
| autoFocus = _lastActiveTrap.autoFocus; | ||
| autoFocus = _lastActiveTrap.autoFocus, | ||
| shards = _lastActiveTrap.shards; | ||
| var workingNode = observed || lastPortaledElement && lastPortaledElement.portaledElement; | ||
| var activeElement = document && document.activeElement; | ||
| if (!activeElement || focusWhitelisted(activeElement)) { | ||
| if (persistentFocus || !isFreeFocus() || !lastActiveFocus && autoFocus) { | ||
| if (workingNode && !((0, _focusLock.focusInside)(workingNode) || focusIsPortaledPair(activeElement, workingNode))) { | ||
| if (document && !lastActiveFocus && activeElement && !autoFocus) { | ||
| activeElement.blur(); | ||
| document.body.focus(); | ||
| } else { | ||
| result = (0, _focusLock.default)(workingNode, lastActiveFocus); | ||
| lastPortaledElement = {}; | ||
| if (workingNode) { | ||
| var workingArea = [workingNode].concat((0, _toConsumableArray2.default)(shards.map(function (_ref) { | ||
| var current = _ref.current; | ||
| return current; | ||
| }))); | ||
| if (!activeElement || focusWhitelisted(activeElement)) { | ||
| if (persistentFocus || !isFreeFocus() || !lastActiveFocus && autoFocus) { | ||
| if (workingNode && !((0, _focusLock.focusInside)(workingArea) || focusIsPortaledPair(activeElement, workingNode))) { | ||
| if (document && !lastActiveFocus && activeElement && !autoFocus) { | ||
| activeElement.blur(); | ||
| document.body.focus(); | ||
| } else { | ||
| result = (0, _focusLock.default)(workingArea, lastActiveFocus); | ||
| lastPortaledElement = {}; | ||
| } | ||
| } | ||
| lastActiveFocus = document && document.activeElement; | ||
| } | ||
| } | ||
| lastActiveFocus = document && document.activeElement; | ||
| if (document) { | ||
| var newActiveElement = document && document.activeElement; | ||
| var allNodes = (0, _focusLock.getFocusabledIn)(workingArea); | ||
| var focusedItem = allNodes.find(function (_ref2) { | ||
| var node = _ref2.node; | ||
| return node === newActiveElement; | ||
| }); | ||
| if (focusedItem) { | ||
| // remove old focus | ||
| allNodes.filter(function (_ref3) { | ||
| var guard = _ref3.guard, | ||
| node = _ref3.node; | ||
| return guard && node.dataset.focusAutoGuard; | ||
| }).forEach(function (_ref4) { | ||
| var node = _ref4.node; | ||
| return node.removeAttribute('tabIndex'); | ||
| }); | ||
| var focusedIndex = allNodes.indexOf(focusedItem); | ||
| autoGuard(focusedIndex, allNodes.length, +1, allNodes); | ||
| autoGuard(focusedIndex, -1, -1, allNodes); | ||
| } | ||
| } | ||
@@ -117,4 +172,4 @@ } | ||
| var FocusTrap = function FocusTrap(_ref) { | ||
| var children = _ref.children; | ||
| var FocusTrap = function FocusTrap(_ref5) { | ||
| var children = _ref5.children; | ||
| return _react.default.createElement("div", { | ||
@@ -141,4 +196,4 @@ onBlur: onBlur, | ||
| function reducePropsToState(propsList) { | ||
| return propsList.filter(function (_ref2) { | ||
| var disabled = _ref2.disabled; | ||
| return propsList.filter(function (_ref6) { | ||
| var disabled = _ref6.disabled; | ||
| return !disabled; | ||
@@ -145,0 +200,0 @@ }).slice(-1)[0]; |
@@ -5,3 +5,4 @@ import FocusLock from './Lock'; | ||
| import FreeFocusInside from './FreeFocusInside'; | ||
| export { AutoFocusInside, MoveFocusInside, FreeFocusInside }; | ||
| import InFocusGuard from './FocusGuard'; | ||
| export { AutoFocusInside, MoveFocusInside, FreeFocusInside, InFocusGuard }; | ||
| export default FocusLock; |
+12
-12
@@ -9,2 +9,3 @@ import _extends from "@babel/runtime/helpers/extends"; | ||
| import FocusTrap, { onBlur, onFocus } from './Trap'; | ||
| import { hiddenGuard } from './FocusGuard'; | ||
@@ -20,11 +21,3 @@ var RenderChildren = function RenderChildren(_ref) { | ||
| var Fragment = React.Fragment ? React.Fragment : RenderChildren; | ||
| var hidden = { | ||
| width: '1px', | ||
| height: '0px', | ||
| padding: 0, | ||
| overflow: 'hidden', | ||
| position: 'fixed', | ||
| top: '1px', | ||
| left: '1px' | ||
| }; | ||
| var emptyArray = []; | ||
@@ -117,2 +110,4 @@ var FocusLock = | ||
| whiteList = _this$props.whiteList, | ||
| _this$props$shards = _this$props.shards, | ||
| shards = _this$props$shards === void 0 ? emptyArray : _this$props$shards, | ||
| _this$props$as = _this$props.as, | ||
@@ -137,3 +132,3 @@ Container = _this$props$as === void 0 ? 'div' : _this$props$as, | ||
| tabIndex: disabled ? -1 : 0, | ||
| style: hidden | ||
| style: hiddenGuard | ||
| }), // nearest focus guard | ||
@@ -144,3 +139,3 @@ React.createElement("div", { | ||
| tabIndex: disabled ? -1 : 1, | ||
| style: hidden | ||
| style: hiddenGuard | ||
| })], React.createElement(Container, _extends({ | ||
@@ -158,2 +153,3 @@ ref: this.setObserveNode | ||
| whiteList: whiteList, | ||
| shards: shards, | ||
| onActivation: this.onActivation, | ||
@@ -164,3 +160,3 @@ onDeactivation: this.onDeactivation | ||
| tabIndex: disabled ? -1 : 0, | ||
| style: hidden | ||
| style: hiddenGuard | ||
| })); | ||
@@ -183,2 +179,5 @@ }; | ||
| whiteList: PropTypes.func, | ||
| shards: PropTypes.arrayOf(PropTypes.shape({ | ||
| current: PropTypes.instanceOf(Element) | ||
| })), | ||
| as: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.object]), | ||
@@ -199,2 +198,3 @@ lockProps: PropTypes.object, | ||
| whiteList: undefined, | ||
| shards: undefined, | ||
| as: 'div', | ||
@@ -201,0 +201,0 @@ lockProps: {}, |
+69
-16
| import React from 'react'; | ||
| import PropTypes from 'prop-types'; | ||
| import withSideEffect from 'react-clientside-effect'; | ||
| import moveFocusInside, { focusInside, focusIsHidden } from 'focus-lock'; | ||
| import moveFocusInside, { focusInside, focusIsHidden, getFocusabledIn } from 'focus-lock'; | ||
| import { deferAction } from './util'; | ||
@@ -38,2 +38,23 @@ | ||
| function autoGuard(startIndex, end, step, allNodes) { | ||
| var lastGuard = null; | ||
| var i = startIndex; | ||
| do { | ||
| var node = allNodes[i]; | ||
| if (node.guard) { | ||
| lastGuard = node; | ||
| } else if (node.lockItem) { | ||
| lastGuard = null; | ||
| } else { | ||
| break; | ||
| } | ||
| } while ((i += step) !== end); | ||
| if (lastGuard) { | ||
| lastGuard.node.tabIndex = 0; | ||
| } | ||
| } | ||
| var activateTrap = function activateTrap() { | ||
@@ -46,19 +67,51 @@ var result = false; | ||
| persistentFocus = _lastActiveTrap.persistentFocus, | ||
| autoFocus = _lastActiveTrap.autoFocus; | ||
| autoFocus = _lastActiveTrap.autoFocus, | ||
| shards = _lastActiveTrap.shards; | ||
| var workingNode = observed || lastPortaledElement && lastPortaledElement.portaledElement; | ||
| var activeElement = document && document.activeElement; | ||
| if (!activeElement || focusWhitelisted(activeElement)) { | ||
| if (persistentFocus || !isFreeFocus() || !lastActiveFocus && autoFocus) { | ||
| if (workingNode && !(focusInside(workingNode) || focusIsPortaledPair(activeElement, workingNode))) { | ||
| if (document && !lastActiveFocus && activeElement && !autoFocus) { | ||
| activeElement.blur(); | ||
| document.body.focus(); | ||
| } else { | ||
| result = moveFocusInside(workingNode, lastActiveFocus); | ||
| lastPortaledElement = {}; | ||
| if (workingNode) { | ||
| var workingArea = [workingNode].concat(shards.map(function (_ref) { | ||
| var current = _ref.current; | ||
| return current; | ||
| })); | ||
| if (!activeElement || focusWhitelisted(activeElement)) { | ||
| if (persistentFocus || !isFreeFocus() || !lastActiveFocus && autoFocus) { | ||
| if (workingNode && !(focusInside(workingArea) || focusIsPortaledPair(activeElement, workingNode))) { | ||
| if (document && !lastActiveFocus && activeElement && !autoFocus) { | ||
| activeElement.blur(); | ||
| document.body.focus(); | ||
| } else { | ||
| result = moveFocusInside(workingArea, lastActiveFocus); | ||
| lastPortaledElement = {}; | ||
| } | ||
| } | ||
| lastActiveFocus = document && document.activeElement; | ||
| } | ||
| } | ||
| lastActiveFocus = document && document.activeElement; | ||
| if (document) { | ||
| var newActiveElement = document && document.activeElement; | ||
| var allNodes = getFocusabledIn(workingArea); | ||
| var focusedItem = allNodes.find(function (_ref2) { | ||
| var node = _ref2.node; | ||
| return node === newActiveElement; | ||
| }); | ||
| if (focusedItem) { | ||
| // remove old focus | ||
| allNodes.filter(function (_ref3) { | ||
| var guard = _ref3.guard, | ||
| node = _ref3.node; | ||
| return guard && node.dataset.focusAutoGuard; | ||
| }).forEach(function (_ref4) { | ||
| var node = _ref4.node; | ||
| return node.removeAttribute('tabIndex'); | ||
| }); | ||
| var focusedIndex = allNodes.indexOf(focusedItem); | ||
| autoGuard(focusedIndex, allNodes.length, +1, allNodes); | ||
| autoGuard(focusedIndex, -1, -1, allNodes); | ||
| } | ||
| } | ||
@@ -96,4 +149,4 @@ } | ||
| var FocusTrap = function FocusTrap(_ref) { | ||
| var children = _ref.children; | ||
| var FocusTrap = function FocusTrap(_ref5) { | ||
| var children = _ref5.children; | ||
| return React.createElement("div", { | ||
@@ -120,4 +173,4 @@ onBlur: onBlur, | ||
| function reducePropsToState(propsList) { | ||
| return propsList.filter(function (_ref2) { | ||
| var disabled = _ref2.disabled; | ||
| return propsList.filter(function (_ref6) { | ||
| var disabled = _ref6.disabled; | ||
| return !disabled; | ||
@@ -124,0 +177,0 @@ }).slice(-1)[0]; |
+3
-3
| { | ||
| "name": "react-focus-lock", | ||
| "version": "1.17.7", | ||
| "version": "1.18.0", | ||
| "description": "It is a trap! (for a focus)", | ||
@@ -79,3 +79,3 @@ "main": "dist/cjs/index.js", | ||
| "sinon": "3.2.1", | ||
| "size-limit": "^0.21.0" | ||
| "size-limit": "^0.21.1" | ||
| }, | ||
@@ -85,3 +85,3 @@ "homepage": "https://github.com/theKashey/react-focus-lock#readme", | ||
| "@babel/runtime": "^7.0.0", | ||
| "focus-lock": "^0.5.2", | ||
| "focus-lock": "^0.6.0", | ||
| "prop-types": "^15.6.2", | ||
@@ -88,0 +88,0 @@ "react-clientside-effect": "^1.2.0" |
@@ -70,2 +70,7 @@ declare module 'react-focus-lock' { | ||
| /** | ||
| * Shards forms a scattered lock, same as `group` does, but in more "low" and controlled way | ||
| */ | ||
| shards?: Array<React.RefObject<any>>; | ||
| children: React.ReactNode; | ||
@@ -83,2 +88,6 @@ } | ||
| interface InFocusGuardProps { | ||
| children: React.ReactNode; | ||
| } | ||
| /** | ||
@@ -107,2 +116,8 @@ * Traps Focus inside a Lock | ||
| } | ||
| /** | ||
| * Secures the focus around the node | ||
| */ | ||
| export class InFocusGuard extends React.Component<InFocusGuardProps> { | ||
| } | ||
| } |
+65
-0
@@ -69,2 +69,3 @@ <div align="left"> | ||
| - `group` named focus group for focus scattering aka [combined lock targets](https://github.com/theKashey/vue-focus-lock/issues/2) | ||
| - `shards` an array of `ref` pointing to the nodes, which focus lock should consider and a part of it. This is another way focus scattering. | ||
| - `whiteList` you could _whitelist_ locations FocusLock should carry about. Everything outside it will ignore. For example - any modals. | ||
@@ -128,2 +129,66 @@ - `as` if you need to change internal `div` element, to any other. Use ref forwarding to give FocusLock the node to work with. | ||
| # Portals | ||
| Use focus scattering to handle portals | ||
| - using `groups`. Just create a few locks (only one could be active) with a same group name | ||
| ```js | ||
| const PortaledElement = () => ( | ||
| <FocusLock group="group42" disabled={true}> | ||
| // "discoverable" portaled content | ||
| </FocusLock> | ||
| ); | ||
| <FocusLock group="group42"> | ||
| // main content | ||
| </FocusLock> | ||
| ``` | ||
| - using `shards`. Just pass all the pieces to the "shards" prop. | ||
| ```js | ||
| const PortaledElement = () => ( | ||
| <div ref={ref}> | ||
| // "discoverable" portaled content | ||
| </div> | ||
| ); | ||
| <FocusLock shards={[ref]}> | ||
| // main content | ||
| </FocusLock> | ||
| ``` | ||
| - without anything. FocusLock will not prevent focusing portaled element, but will not include them in to tab order | ||
| ```js | ||
| const PortaledElement = () => ( | ||
| <div> | ||
| // NON-"discoverable" portaled content | ||
| </div> | ||
| ); | ||
| <FocusLock shards={[ref]}> | ||
| // main content | ||
| <PortaledElement /> | ||
| </FocusLock> | ||
| ``` | ||
| ### Guarding | ||
| As you may know - FocusLock is adding `Focus Guards` before and after lock to remove some side effects, like page scrolling. | ||
| But `shards` will not have such guards, and it might be not so cool to use them - for example if no `tabbable` would be | ||
| defined after shard - you will tab to the browser chrome. | ||
| You may wrap shard with `InFocusGuard` or just drop `InFocusGuard` here and there - that would solve the problem. | ||
| ```js | ||
| import {InFocusGuard} from 'react-focus-lock'; | ||
| <InFocusGuard> | ||
| <button> | ||
| </InFocusGuard> | ||
| // | ||
| <InFocusGuard /> | ||
| <button> | ||
| <InFocusGuard /> | ||
| ``` | ||
| InFocusGuards would be active(tabbable) only when tabble, it protecting, is focused. | ||
| ### Automatic potral discovery | ||
| # Unmounting and focus management | ||
@@ -130,0 +195,0 @@ - In case FocusLock has `returnFocus` enabled, and it's gonna to be unmounted - focus will be returned after zero-timeout. |
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
623515
780.83%23
15%1177
17.7%260
33.33%16
14.29%+ Added
- Removed
Updated