@wordpress/components
Version:
UI components for WordPress.
130 lines (128 loc) • 4.39 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// packages/components/src/navigable-container/container.tsx
var container_exports = {};
__export(container_exports, {
default: () => container_default
});
module.exports = __toCommonJS(container_exports);
var import_element = require("@wordpress/element");
var import_compose = require("@wordpress/compose");
var import_dom = require("@wordpress/dom");
var import_jsx_runtime = require("react/jsx-runtime");
var noop = () => {
};
var MENU_ITEM_ROLES = ["menuitem", "menuitemradio", "menuitemcheckbox"];
function cycleValue(value, total, offset) {
const nextValue = value + offset;
if (nextValue < 0) {
return total + nextValue;
} else if (nextValue >= total) {
return nextValue - total;
}
return nextValue;
}
function UnforwardedNavigableContainer({
children,
stopNavigationEvents,
eventToOffset,
onNavigate = noop,
onKeyDown,
cycle = true,
onlyBrowserTabstops,
...restProps
}, ref) {
const containerRef = (0, import_element.useRef)(null);
const getFocusableIndex = (0, import_element.useCallback)((focusables, target) => {
return focusables.indexOf(target);
}, []);
const getFocusableContext = (0, import_element.useCallback)((target) => {
if (!containerRef.current) {
return null;
}
const finder = onlyBrowserTabstops ? import_dom.focus.tabbable : import_dom.focus.focusable;
const focusables = finder.find(containerRef.current);
const index = getFocusableIndex(focusables, target);
if (index > -1 && target) {
return {
index,
target,
focusables
};
}
return null;
}, [onlyBrowserTabstops, getFocusableIndex]);
(0, import_element.useEffect)(() => {
const container = containerRef.current;
if (!container) {
return;
}
function handleKeyDown(event) {
if (onKeyDown) {
onKeyDown(event);
}
const offset = eventToOffset(event);
if (offset !== void 0 && stopNavigationEvents) {
event.stopImmediatePropagation();
const targetRole = event.target?.getAttribute("role");
const targetHasMenuItemRole = !!targetRole && MENU_ITEM_ROLES.includes(targetRole);
if (targetHasMenuItemRole) {
event.preventDefault();
}
}
if (!offset) {
return;
}
const activeElement = event.target?.ownerDocument?.activeElement;
if (!activeElement) {
return;
}
const context = getFocusableContext(activeElement);
if (!context) {
return;
}
const {
index,
focusables
} = context;
const nextIndex = cycle ? cycleValue(index, focusables.length, offset) : index + offset;
if (nextIndex >= 0 && nextIndex < focusables.length) {
focusables[nextIndex].focus();
onNavigate(nextIndex, focusables[nextIndex]);
if (event.code === "Tab") {
event.preventDefault();
}
}
}
container.addEventListener("keydown", handleKeyDown);
return () => {
container.removeEventListener("keydown", handleKeyDown);
};
}, [onKeyDown, eventToOffset, stopNavigationEvents, cycle, onNavigate, getFocusableContext]);
const mergedRef = (0, import_compose.useMergeRefs)([containerRef, ref]);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
ref: mergedRef,
...restProps,
children
});
}
var NavigableContainer = (0, import_element.forwardRef)(UnforwardedNavigableContainer);
NavigableContainer.displayName = "NavigableContainer";
var container_default = NavigableContainer;
//# sourceMappingURL=container.cjs.map