UNPKG

@ariakit/react

Version:

Toolkit for building accessible web apps with React

297 lines (270 loc) 11 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); var _LZ6L3ECGcjs = require('./LZ6L3ECG.cjs'); // ../ariakit-react-components/dist/focusable/focusable-context.js var _react = require('react'); var FocusableContext = _react.createContext.call(void 0, true); // ../ariakit-react-components/dist/focusable/focusable.js var TagName = "div"; var accessibleWhenDisabledSymbol = /* @__PURE__ */ Symbol("accessibleWhenDisabled"); var isSafariBrowser = _LZ6L3ECGcjs.isSafari.call(void 0, ); var alwaysFocusVisibleInputTypes = [ "text", "search", "url", "tel", "email", "password", "number", "date", "month", "week", "time", "datetime", "datetime-local" ]; function isAlwaysFocusVisible(element) { const { tagName, readOnly, type } = element; if (tagName === "TEXTAREA" && !readOnly) return true; if (tagName === "SELECT" && !readOnly) return true; if (tagName === "INPUT" && !readOnly) return alwaysFocusVisibleInputTypes.includes(type); if (element.isContentEditable) return true; if (element.getAttribute("role") === "combobox" && element.dataset.name) return true; return false; } function isNativeTabbable(tagName) { if (!tagName) return true; return tagName === "button" || tagName === "summary" || tagName === "input" || tagName === "select" || tagName === "textarea" || tagName === "a"; } function supportsDisabledAttribute(tagName) { if (!tagName) return true; return tagName === "button" || tagName === "input" || tagName === "select" || tagName === "textarea"; } function isNativeSubmitControl(element) { if (element.tagName === "BUTTON") { const { type } = element; return type === "submit"; } if (element.tagName === "INPUT") { const { type } = element; return type === "submit" || type === "image"; } return false; } function getTabIndex({ focusable, trulyDisabled, nativeTabbable, supportsDisabled, safariTabIndex, tabIndexProp }) { if (!focusable) return tabIndexProp; if (trulyDisabled) { if (nativeTabbable && !supportsDisabled) return -1; return; } if (nativeTabbable) { if (safariTabIndex && tabIndexProp == null) return 0; return tabIndexProp; } return tabIndexProp != null ? tabIndexProp : 0; } function useDisableEvent(onEvent, disabled) { return _LZ6L3ECGcjs.useEvent.call(void 0, (event) => { onEvent == null ? void 0 : onEvent(event); if (event.defaultPrevented) return; if (disabled) { event.stopPropagation(); event.preventDefault(); } }); } var hasInstalledGlobalEventListeners = false; var isKeyboardModality = true; function onGlobalMouseDown(event) { const target = event.target; if (_LZ6L3ECGcjs.isElement.call(void 0, target) && !target.hasAttribute("data-focus-visible")) isKeyboardModality = false; } function onGlobalKeyDown(event) { if (event.metaKey) return; if (event.ctrlKey) return; if (event.altKey) return; isKeyboardModality = true; } var useFocusable = _LZ6L3ECGcjs.createHook.call(void 0, function useFocusable2({ focusable = true, accessibleWhenDisabled, autoFocus, onFocusVisible, ...props }) { const ref = _react.useRef.call(void 0, null); const [parentAccessibleWhenDisabled, metadataProps] = _LZ6L3ECGcjs.useMetadataProps.call(void 0, props, accessibleWhenDisabledSymbol, accessibleWhenDisabled); accessibleWhenDisabled != null ? accessibleWhenDisabled : accessibleWhenDisabled = parentAccessibleWhenDisabled; _react.useEffect.call(void 0, () => { if (!focusable) return; if (hasInstalledGlobalEventListeners) return; _LZ6L3ECGcjs.addGlobalEventListener.call(void 0, "mousedown", onGlobalMouseDown, true); _LZ6L3ECGcjs.addGlobalEventListener.call(void 0, "keydown", onGlobalKeyDown, true); hasInstalledGlobalEventListeners = true; }, [focusable]); const disabled = focusable && _LZ6L3ECGcjs.disabledFromProps.call(void 0, props); const trulyDisabled = disabled && !accessibleWhenDisabled; const [focusVisible, setFocusVisible] = _react.useState.call(void 0, false); const focusVisibleRef = _react.useRef.call(void 0, false); const nativeSubmitObserverCleanupRef = _react.useRef.call(void 0, null); const cleanupFocusVisible = _LZ6L3ECGcjs.useEvent.call(void 0, (element) => { var _a; (_a = nativeSubmitObserverCleanupRef.current) == null ? void 0 : _a.call(nativeSubmitObserverCleanupRef); nativeSubmitObserverCleanupRef.current = null; focusVisibleRef.current = false; element == null ? void 0 : element.removeAttribute("data-focus-visible"); }); _react.useEffect.call(void 0, () => { if (!focusable) return; if (!trulyDisabled) return; cleanupFocusVisible(ref.current); if (focusVisible) setFocusVisible(false); }, [ focusable, trulyDisabled, focusVisible, cleanupFocusVisible ]); _react.useEffect.call(void 0, () => { if (!focusable) return; if (!focusVisible) return; const element = ref.current; if (!element) return; if (typeof IntersectionObserver === "undefined") return; const observer = new IntersectionObserver(() => { if (!_LZ6L3ECGcjs.isFocusable.call(void 0, element)) { focusVisibleRef.current = false; setFocusVisible(false); } }); observer.observe(element); return () => observer.disconnect(); }, [focusable, focusVisible]); _react.useEffect.call(void 0, () => { return () => { var _a; return (_a = nativeSubmitObserverCleanupRef.current) == null ? void 0 : _a.call(nativeSubmitObserverCleanupRef); }; }, []); const onKeyPressCapture = useDisableEvent(props.onKeyPressCapture, disabled); const onMouseDownCapture = useDisableEvent(props.onMouseDownCapture, disabled); const onClickCapture = useDisableEvent(props.onClickCapture, disabled); const handleFocusVisible = (event, currentTarget) => { var _a; if (currentTarget) event.currentTarget = currentTarget; if (!focusable) return; const element = event.currentTarget; if (!element) return; if (!_LZ6L3ECGcjs.hasFocus.call(void 0, element)) return; onFocusVisible == null ? void 0 : onFocusVisible(event); if (event.defaultPrevented) return; element.dataset.focusVisible = "true"; focusVisibleRef.current = true; if (isNativeSubmitControl(element)) { (_a = nativeSubmitObserverCleanupRef.current) == null ? void 0 : _a.call(nativeSubmitObserverCleanupRef); nativeSubmitObserverCleanupRef.current = null; if (typeof IntersectionObserver !== "undefined") { const observer = new IntersectionObserver(() => { if (_LZ6L3ECGcjs.isFocusable.call(void 0, element)) return; cleanupFocusVisible(element); }); observer.observe(element); nativeSubmitObserverCleanupRef.current = () => observer.disconnect(); } return; } setFocusVisible(true); }; const onKeyDownCaptureProp = props.onKeyDownCapture; const onKeyDownCapture = _LZ6L3ECGcjs.useEvent.call(void 0, (event) => { onKeyDownCaptureProp == null ? void 0 : onKeyDownCaptureProp(event); if (event.defaultPrevented) return; if (!focusable) return; if (focusVisible) return; if (focusVisibleRef.current) return; if (event.metaKey) return; if (event.altKey) return; if (event.ctrlKey) return; if (!_LZ6L3ECGcjs.isSelfTarget.call(void 0, event)) return; const element = event.currentTarget; const applyFocusVisible = () => handleFocusVisible(event, element); _LZ6L3ECGcjs.queueBeforeEvent.call(void 0, element, "focusout", applyFocusVisible); }); const onFocusCaptureProp = props.onFocusCapture; const onFocusCapture = _LZ6L3ECGcjs.useEvent.call(void 0, (event) => { onFocusCaptureProp == null ? void 0 : onFocusCaptureProp(event); if (event.defaultPrevented) return; if (!focusable) return; if (!_LZ6L3ECGcjs.isSelfTarget.call(void 0, event)) { setFocusVisible(false); return; } const element = event.currentTarget; const applyFocusVisible = () => handleFocusVisible(event, element); if (isKeyboardModality || isAlwaysFocusVisible(event.target)) _LZ6L3ECGcjs.queueBeforeEvent.call(void 0, event.target, "focusout", applyFocusVisible); else setFocusVisible(false); }); const onBlurProp = props.onBlur; const onBlur = _LZ6L3ECGcjs.useEvent.call(void 0, (event) => { onBlurProp == null ? void 0 : onBlurProp(event); if (!focusable) return; if (!_LZ6L3ECGcjs.isFocusEventOutside.call(void 0, event)) return; cleanupFocusVisible(event.currentTarget); setFocusVisible(false); }); const autoFocusOnShow = _react.useContext.call(void 0, FocusableContext); const autoFocusRef = _LZ6L3ECGcjs.useEvent.call(void 0, (element) => { if (!focusable) return; if (!autoFocus) return; if (!element) return; if (!autoFocusOnShow) return; queueMicrotask(() => { if (_LZ6L3ECGcjs.hasFocus.call(void 0, element)) return; if (!_LZ6L3ECGcjs.isFocusable.call(void 0, element)) return; element.focus(); }); }); const tagName = _LZ6L3ECGcjs.useTagName.call(void 0, ref); const nativeTabbable = focusable && isNativeTabbable(tagName); const supportsDisabled = focusable && supportsDisabledAttribute(tagName); const [safariTabIndex, setSafariTabIndex] = _react.useState.call(void 0, false); if (isSafariBrowser) _react.useEffect.call(void 0, () => { if (!focusable) return; const element = ref.current; if (!element) return; const { type } = element; const isNativeCheckboxOrRadio = element.tagName === "INPUT" && (type === "checkbox" || type === "radio"); setSafariTabIndex(_LZ6L3ECGcjs.isButton.call(void 0, element) || isNativeCheckboxOrRadio); }, [focusable]); const styleProp = props.style; const style = _react.useMemo.call(void 0, () => { if (trulyDisabled) return { pointerEvents: "none", ...styleProp }; return styleProp; }, [trulyDisabled, styleProp]); props = { "data-focus-visible": focusable && focusVisible || void 0, "data-autofocus": autoFocus || void 0, "aria-disabled": disabled || void 0, ...props, ...metadataProps, ref: _LZ6L3ECGcjs.useMergeRefs.call(void 0, ref, autoFocusRef, props.ref), style, tabIndex: getTabIndex({ focusable, trulyDisabled, nativeTabbable, supportsDisabled, safariTabIndex, tabIndexProp: props.tabIndex }), disabled: supportsDisabled && trulyDisabled ? true : void 0, contentEditable: disabled ? void 0 : props.contentEditable, onKeyPressCapture, onClickCapture, onMouseDownCapture, onKeyDownCapture, onFocusCapture, onBlur }; return _LZ6L3ECGcjs.removeUndefinedValues.call(void 0, props); }); var Focusable = _LZ6L3ECGcjs.forwardRef.call(void 0, function Focusable2(props) { return _LZ6L3ECGcjs.createElement.call(void 0, TagName, useFocusable(props)); }); exports.FocusableContext = FocusableContext; exports.useFocusable = useFocusable; exports.Focusable = Focusable;