@rc-component/util
Advanced tools
@@ -12,4 +12,5 @@ export declare function getFocusNodeList(node: HTMLElement, includePositive?: boolean): HTMLElement[]; | ||
| * It will force back to the first focusable element when focus leaves the element. | ||
| * @param id - A stable ID for this lock instance | ||
| */ | ||
| export declare function lockFocus(element: HTMLElement): VoidFunction; | ||
| export declare function lockFocus(element: HTMLElement, id: string): VoidFunction; | ||
| /** | ||
@@ -19,3 +20,4 @@ * Lock focus within an element. | ||
| * If multiple elements are locked, only the last locked element will be effective. | ||
| * @returns A function to mark an element as ignored, which will temporarily allow focus on that element even if it's outside the locked area. | ||
| */ | ||
| export declare function useLockFocus(lock: boolean, getElement: () => HTMLElement | null): void; | ||
| export declare function useLockFocus(lock: boolean, getElement: () => HTMLElement | null): [ignoreElement: (ele: HTMLElement) => void]; |
+44
-3
| import { useEffect } from 'react'; | ||
| import isVisible from "./isVisible"; | ||
| import useId from "../hooks/useId"; | ||
| function focusable(node, includePositive = false) { | ||
@@ -75,5 +76,25 @@ if (isVisible(node)) { | ||
| let focusElements = []; | ||
| // Map stable ID to lock element | ||
| const idToElementMap = new Map(); | ||
| // Map stable ID to ignored element | ||
| const ignoredElementMap = new Map(); | ||
| function getLastElement() { | ||
| return focusElements[focusElements.length - 1]; | ||
| } | ||
| function isIgnoredElement(element) { | ||
| const lastElement = getLastElement(); | ||
| if (element && lastElement) { | ||
| // Find the ID that maps to the last element | ||
| let lockId; | ||
| for (const [id, ele] of idToElementMap.entries()) { | ||
| if (ele === lastElement) { | ||
| lockId = id; | ||
| break; | ||
| } | ||
| } | ||
| const ignoredEle = ignoredElementMap.get(lockId); | ||
| return !!ignoredEle && (ignoredEle === element || ignoredEle.contains(element)); | ||
| } | ||
| return false; | ||
| } | ||
| function hasFocus(element) { | ||
@@ -90,2 +111,7 @@ const { | ||
| } = document; | ||
| // If current focus is on an ignored element, don't force it back | ||
| if (isIgnoredElement(activeElement)) { | ||
| return; | ||
| } | ||
| if (lastElement && !hasFocus(lastElement)) { | ||
@@ -122,5 +148,9 @@ const focusableList = getFocusNodeList(lastElement); | ||
| * It will force back to the first focusable element when focus leaves the element. | ||
| * @param id - A stable ID for this lock instance | ||
| */ | ||
| export function lockFocus(element) { | ||
| export function lockFocus(element, id) { | ||
| if (element) { | ||
| // Store the mapping between ID and element | ||
| idToElementMap.set(id, element); | ||
| // Refresh focus elements | ||
@@ -140,2 +170,4 @@ focusElements = focusElements.filter(ele => ele !== element); | ||
| focusElements = focusElements.filter(ele => ele !== element); | ||
| idToElementMap.delete(id); | ||
| ignoredElementMap.delete(id); | ||
| if (focusElements.length === 0) { | ||
@@ -152,4 +184,6 @@ window.removeEventListener('focusin', syncFocus); | ||
| * If multiple elements are locked, only the last locked element will be effective. | ||
| * @returns A function to mark an element as ignored, which will temporarily allow focus on that element even if it's outside the locked area. | ||
| */ | ||
| export function useLockFocus(lock, getElement) { | ||
| const id = useId(); | ||
| useEffect(() => { | ||
@@ -159,6 +193,13 @@ if (lock) { | ||
| if (element) { | ||
| return lockFocus(element); | ||
| return lockFocus(element, id); | ||
| } | ||
| } | ||
| }, [lock]); | ||
| }, [lock, id]); | ||
| const ignoreElement = ele => { | ||
| if (ele) { | ||
| // Set the ignored element using stable ID | ||
| ignoredElementMap.set(id, ele); | ||
| } | ||
| }; | ||
| return [ignoreElement]; | ||
| } |
@@ -12,4 +12,5 @@ export declare function getFocusNodeList(node: HTMLElement, includePositive?: boolean): HTMLElement[]; | ||
| * It will force back to the first focusable element when focus leaves the element. | ||
| * @param id - A stable ID for this lock instance | ||
| */ | ||
| export declare function lockFocus(element: HTMLElement): VoidFunction; | ||
| export declare function lockFocus(element: HTMLElement, id: string): VoidFunction; | ||
| /** | ||
@@ -19,3 +20,4 @@ * Lock focus within an element. | ||
| * If multiple elements are locked, only the last locked element will be effective. | ||
| * @returns A function to mark an element as ignored, which will temporarily allow focus on that element even if it's outside the locked area. | ||
| */ | ||
| export declare function useLockFocus(lock: boolean, getElement: () => HTMLElement | null): void; | ||
| export declare function useLockFocus(lock: boolean, getElement: () => HTMLElement | null): [ignoreElement: (ele: HTMLElement) => void]; |
+44
-3
@@ -12,2 +12,3 @@ "use strict"; | ||
| var _isVisible = _interopRequireDefault(require("./isVisible")); | ||
| var _useId = _interopRequireDefault(require("../hooks/useId")); | ||
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -86,5 +87,25 @@ function focusable(node, includePositive = false) { | ||
| let focusElements = []; | ||
| // Map stable ID to lock element | ||
| const idToElementMap = new Map(); | ||
| // Map stable ID to ignored element | ||
| const ignoredElementMap = new Map(); | ||
| function getLastElement() { | ||
| return focusElements[focusElements.length - 1]; | ||
| } | ||
| function isIgnoredElement(element) { | ||
| const lastElement = getLastElement(); | ||
| if (element && lastElement) { | ||
| // Find the ID that maps to the last element | ||
| let lockId; | ||
| for (const [id, ele] of idToElementMap.entries()) { | ||
| if (ele === lastElement) { | ||
| lockId = id; | ||
| break; | ||
| } | ||
| } | ||
| const ignoredEle = ignoredElementMap.get(lockId); | ||
| return !!ignoredEle && (ignoredEle === element || ignoredEle.contains(element)); | ||
| } | ||
| return false; | ||
| } | ||
| function hasFocus(element) { | ||
@@ -101,2 +122,7 @@ const { | ||
| } = document; | ||
| // If current focus is on an ignored element, don't force it back | ||
| if (isIgnoredElement(activeElement)) { | ||
| return; | ||
| } | ||
| if (lastElement && !hasFocus(lastElement)) { | ||
@@ -133,5 +159,9 @@ const focusableList = getFocusNodeList(lastElement); | ||
| * It will force back to the first focusable element when focus leaves the element. | ||
| * @param id - A stable ID for this lock instance | ||
| */ | ||
| function lockFocus(element) { | ||
| function lockFocus(element, id) { | ||
| if (element) { | ||
| // Store the mapping between ID and element | ||
| idToElementMap.set(id, element); | ||
| // Refresh focus elements | ||
@@ -151,2 +181,4 @@ focusElements = focusElements.filter(ele => ele !== element); | ||
| focusElements = focusElements.filter(ele => ele !== element); | ||
| idToElementMap.delete(id); | ||
| ignoredElementMap.delete(id); | ||
| if (focusElements.length === 0) { | ||
@@ -163,4 +195,6 @@ window.removeEventListener('focusin', syncFocus); | ||
| * If multiple elements are locked, only the last locked element will be effective. | ||
| * @returns A function to mark an element as ignored, which will temporarily allow focus on that element even if it's outside the locked area. | ||
| */ | ||
| function useLockFocus(lock, getElement) { | ||
| const id = (0, _useId.default)(); | ||
| (0, _react.useEffect)(() => { | ||
@@ -170,6 +204,13 @@ if (lock) { | ||
| if (element) { | ||
| return lockFocus(element); | ||
| return lockFocus(element, id); | ||
| } | ||
| } | ||
| }, [lock]); | ||
| }, [lock, id]); | ||
| const ignoreElement = ele => { | ||
| if (ele) { | ||
| // Set the ignored element using stable ID | ||
| ignoredElementMap.set(id, ele); | ||
| } | ||
| }; | ||
| return [ignoreElement]; | ||
| } |
+1
-1
| { | ||
| "name": "@rc-component/util", | ||
| "version": "1.8.2", | ||
| "version": "1.9.0", | ||
| "description": "Common Utils For React Component", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
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
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
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
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
193888
1.67%6382
1.3%20
11.11%