UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

116 lines (115 loc) 4.17 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0/LICENSE.txt */ import { makeGenericController } from "@arcgis/lumina/controllers"; import { createFocusTrap } from "focus-trap"; import { u as tabbableOptions, j as focusElement } from "./dom.js"; import { a as getConfig } from "./runtime.js"; function getEffectiveContainerElements(targetEl, { focusTrapOptions }, extraContainers) { if (!focusTrapOptions?.extraContainers && !extraContainers) { return targetEl; } return [targetEl, ...toContainerArray(focusTrapOptions?.extraContainers), ...toContainerArray(extraContainers)]; } function toContainerArray(containers = []) { return Array.isArray(containers) ? containers : [containers]; } const outsideClickDeactivated = /* @__PURE__ */ new WeakSet(); function defaultSetReturnFocus(hostEl, el) { const hasPreviousRelatedFocusedEl = el && el !== document.body && el !== document.documentElement; if (!outsideClickDeactivated.has(hostEl) && hasPreviousRelatedFocusedEl) { focusElement(el); } return false; } function createFocusTrapOptions(hostEl, options) { const fallbackFocus = options?.fallbackFocus || hostEl; const clickOutsideDeactivates = options?.clickOutsideDeactivates ?? true; return { fallbackFocus, ...options, // the following options are not overridable document: hostEl.ownerDocument, tabbableOptions, trapStack: getConfig().focusTrapStack, clickOutsideDeactivates: (event) => { if (!outsideClickDeactivated.has(hostEl)) { outsideClickDeactivated.add(hostEl); } return typeof clickOutsideDeactivates === "function" ? clickOutsideDeactivates(event) : clickOutsideDeactivates; }, onPostDeactivate: () => { outsideClickDeactivated.delete(hostEl); }, setReturnFocus: (el) => { const returnFocusTarget = typeof options?.setReturnFocus === "function" ? options.setReturnFocus(el) : options?.setReturnFocus; return returnFocusTarget === void 0 ? defaultSetReturnFocus(hostEl, el) : returnFocusTarget; } }; } const useFocusTrap = (options) => { return makeGenericController((component, controller) => { let focusTrap; let focusTrapEl; let effectiveContainers; const internalFocusTrapOptions = options.focusTrapOptions; controller.onConnected(() => { if (component[options.triggerProp] && focusTrap) { utils.activate(); } }); controller.onUpdate((changes) => { if (component.hasUpdated && changes.has("focusTrapDisabled")) { if (component.focusTrapDisabled) { utils.deactivate(); } else { utils.activate(); } } }); controller.onDisconnected(() => utils.deactivate()); const utils = { get _instance() { if (process.env.NODE_ENV === "test") { return focusTrap; } return void 0; }, activate: () => { const targetEl = focusTrapEl || component.el; if (!targetEl.isConnected) { return; } if (!focusTrap) { effectiveContainers ||= getEffectiveContainerElements(targetEl, component); focusTrap = createFocusTrap( effectiveContainers, createFocusTrapOptions(targetEl, { ...internalFocusTrapOptions, ...component.focusTrapOptions }) ); } if (typeof component.focusTrapDisabledOverride === "function" ? !component.focusTrapDisabledOverride() : !component.focusTrapDisabled) { focusTrap.activate(); } }, deactivate: () => focusTrap?.deactivate(), overrideFocusTrapEl: (el) => { if (focusTrap) { throw new Error("Focus trap already created"); } focusTrapEl = el; }, setExtraContainers: (extraContainers) => { const targetEl = focusTrapEl || component.el; effectiveContainers = getEffectiveContainerElements(targetEl, component, extraContainers); }, updateContainerElements: () => { return focusTrap?.updateContainerElements(effectiveContainers); } }; return utils; }); }; export { useFocusTrap as u };