@chakra-ui/focus-lock
Version:
React focus lock for all Chakra components
1 lines • 3.89 kB
Source Map (JSON)
{"version":3,"sources":["../src/focus-lock.tsx"],"sourcesContent":["import ReactFocusLock from \"react-focus-lock\"\nimport { getAllFocusable } from \"@chakra-ui/dom-utils\"\nimport { useCallback } from \"react\"\n\nconst FocusTrap: typeof ReactFocusLock =\n (ReactFocusLock as any).default ?? ReactFocusLock\n\ninterface FocusableElement {\n focus(options?: FocusOptions): void\n}\nexport interface FocusLockProps {\n /**\n * `ref` of the element to receive focus initially\n */\n initialFocusRef?: React.RefObject<FocusableElement>\n /**\n * `ref` of the element to return focus to when `FocusLock`\n * unmounts\n */\n finalFocusRef?: React.RefObject<FocusableElement>\n /**\n * The `ref` of the wrapper for which the focus-lock wraps\n */\n contentRef?: React.RefObject<HTMLElement>\n /**\n * If `true`, focus will be restored to the element that\n * triggered the `FocusLock` once it unmounts\n *\n * @default false\n */\n restoreFocus?: boolean\n /**\n * The component to render\n */\n children: React.ReactNode\n /**\n * If `true`, focus trapping will be disabled\n *\n * @default false\n */\n isDisabled?: boolean\n /**\n * If `true`, the first focusable element within the `children`\n * will auto-focused once `FocusLock` mounts\n *\n * @default false\n */\n autoFocus?: boolean\n /**\n * If `true`, disables text selections inside, and outside focus lock\n *\n * @default false\n */\n persistentFocus?: boolean\n /**\n * Enables aggressive focus capturing within iframes.\n * - If `true`: keep focus in the lock, no matter where lock is active\n * - If `false`: allows focus to move outside of iframe\n *\n * @default false\n */\n lockFocusAcrossFrames?: boolean\n}\n\nexport const FocusLock: React.FC<FocusLockProps> = (props) => {\n const {\n initialFocusRef,\n finalFocusRef,\n contentRef,\n restoreFocus,\n children,\n isDisabled,\n autoFocus,\n persistentFocus,\n lockFocusAcrossFrames,\n } = props\n\n const onActivation = useCallback(() => {\n if (initialFocusRef?.current) {\n initialFocusRef.current.focus()\n } else if (contentRef?.current) {\n const focusables = getAllFocusable(contentRef.current)\n if (focusables.length === 0) {\n requestAnimationFrame(() => {\n contentRef.current?.focus()\n })\n }\n }\n }, [initialFocusRef, contentRef])\n\n const onDeactivation = useCallback(() => {\n finalFocusRef?.current?.focus()\n }, [finalFocusRef])\n\n const returnFocus = restoreFocus && !finalFocusRef\n\n return (\n <FocusTrap\n crossFrame={lockFocusAcrossFrames}\n persistentFocus={persistentFocus}\n autoFocus={autoFocus}\n disabled={isDisabled}\n onActivation={onActivation}\n onDeactivation={onDeactivation}\n returnFocus={returnFocus}\n >\n {children}\n </FocusTrap>\n )\n}\n\nFocusLock.displayName = \"FocusLock\"\n\nexport default FocusLock\n"],"mappings":";;;AAAA,OAAO,oBAAoB;AAC3B,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AA+FxB;AAjGJ;AAIA,IAAM,aACH,oBAAuB,YAAvB,YAAkC;AA2D9B,IAAM,YAAsC,CAAC,UAAU;AAC5D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,mDAAiB,SAAS;AAC5B,sBAAgB,QAAQ,MAAM;AAAA,IAChC,WAAW,yCAAY,SAAS;AAC9B,YAAM,aAAa,gBAAgB,WAAW,OAAO;AACrD,UAAI,WAAW,WAAW,GAAG;AAC3B,8BAAsB,MAAM;AAnFpC,cAAAA;AAoFU,WAAAA,MAAA,WAAW,YAAX,gBAAAA,IAAoB;AAAA,QACtB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,GAAG,CAAC,iBAAiB,UAAU,CAAC;AAEhC,QAAM,iBAAiB,YAAY,MAAM;AA1F3C,QAAAA;AA2FI,KAAAA,MAAA,+CAAe,YAAf,gBAAAA,IAAwB;AAAA,EAC1B,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,cAAc,gBAAgB,CAAC;AAErC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEA,UAAU,cAAc;AAExB,IAAO,qBAAQ;","names":["_a"]}