@wordpress/block-editor
Version:
216 lines (214 loc) • 7.96 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// packages/block-editor/src/components/navigable-toolbar/index.js
var navigable_toolbar_exports = {};
__export(navigable_toolbar_exports, {
default: () => NavigableToolbar
});
module.exports = __toCommonJS(navigable_toolbar_exports);
var import_components = require("@wordpress/components");
var import_element = require("@wordpress/element");
var import_data = require("@wordpress/data");
var import_deprecated = __toESM(require("@wordpress/deprecated"));
var import_dom = require("@wordpress/dom");
var import_keyboard_shortcuts = require("@wordpress/keyboard-shortcuts");
var import_keycodes = require("@wordpress/keycodes");
var import_store = require("../../store");
var import_lock_unlock = require("../../lock-unlock");
var import_jsx_runtime = require("react/jsx-runtime");
function hasOnlyToolbarItem(elements) {
const dataProp = "toolbarItem";
return !elements.some((element) => !(dataProp in element.dataset));
}
function getAllFocusableToolbarItemsIn(container) {
return Array.from(
container.querySelectorAll("[data-toolbar-item]:not([disabled])")
);
}
function hasFocusWithin(container) {
return container.contains(container.ownerDocument.activeElement);
}
function focusFirstTabbableIn(container) {
const [firstTabbable] = import_dom.focus.tabbable.find(container);
if (firstTabbable) {
firstTabbable.focus({
// When focusing newly mounted toolbars,
// the position of the popover is often not right on the first render
// This prevents the layout shifts when focusing the dialogs.
preventScroll: true
});
}
}
function useIsAccessibleToolbar(toolbarRef) {
const initialAccessibleToolbarState = true;
const [isAccessibleToolbar, setIsAccessibleToolbar] = (0, import_element.useState)(
initialAccessibleToolbarState
);
const determineIsAccessibleToolbar = (0, import_element.useCallback)(() => {
const tabbables = import_dom.focus.tabbable.find(toolbarRef.current);
const onlyToolbarItem = hasOnlyToolbarItem(tabbables);
if (!onlyToolbarItem) {
(0, import_deprecated.default)("Using custom components as toolbar controls", {
since: "5.6",
alternative: "ToolbarItem, ToolbarButton or ToolbarDropdownMenu components",
link: "https://developer.wordpress.org/block-editor/components/toolbar-button/#inside-blockcontrols"
});
}
setIsAccessibleToolbar(onlyToolbarItem);
}, [toolbarRef]);
(0, import_element.useLayoutEffect)(() => {
const observer = new window.MutationObserver(
determineIsAccessibleToolbar
);
observer.observe(toolbarRef.current, {
childList: true,
subtree: true
});
return () => observer.disconnect();
}, [determineIsAccessibleToolbar, isAccessibleToolbar, toolbarRef]);
return isAccessibleToolbar;
}
function useToolbarFocus({
toolbarRef,
focusOnMount,
isAccessibleToolbar,
defaultIndex,
onIndexChange,
shouldUseKeyboardFocusShortcut,
focusEditorOnEscape
}) {
const [initialFocusOnMount] = (0, import_element.useState)(focusOnMount);
const [initialIndex] = (0, import_element.useState)(defaultIndex);
const focusToolbar = (0, import_element.useCallback)(() => {
focusFirstTabbableIn(toolbarRef.current);
}, [toolbarRef]);
const focusToolbarViaShortcut = () => {
if (shouldUseKeyboardFocusShortcut) {
focusToolbar();
}
};
(0, import_keyboard_shortcuts.useShortcut)("core/block-editor/focus-toolbar", focusToolbarViaShortcut);
(0, import_element.useEffect)(() => {
if (initialFocusOnMount) {
focusToolbar();
}
}, [isAccessibleToolbar, initialFocusOnMount, focusToolbar]);
(0, import_element.useEffect)(() => {
const navigableToolbarRef = toolbarRef.current;
let raf = 0;
if (!initialFocusOnMount && !hasFocusWithin(navigableToolbarRef)) {
raf = window.requestAnimationFrame(() => {
const items = getAllFocusableToolbarItemsIn(navigableToolbarRef);
const index = initialIndex || 0;
if (items[index] && hasFocusWithin(navigableToolbarRef)) {
items[index].focus({
// When focusing newly mounted toolbars,
// the position of the popover is often not right on the first render
// This prevents the layout shifts when focusing the dialogs.
preventScroll: true
});
}
});
}
return () => {
window.cancelAnimationFrame(raf);
if (!onIndexChange || !navigableToolbarRef) {
return;
}
const items = getAllFocusableToolbarItemsIn(navigableToolbarRef);
const index = items.findIndex((item) => item.tabIndex === 0);
onIndexChange(index);
};
}, [initialIndex, initialFocusOnMount, onIndexChange, toolbarRef]);
const { getLastFocus } = (0, import_lock_unlock.unlock)((0, import_data.useSelect)(import_store.store));
(0, import_element.useEffect)(() => {
const navigableToolbarRef = toolbarRef.current;
if (focusEditorOnEscape) {
const handleKeyDown = (event) => {
const lastFocus = getLastFocus();
if (event.keyCode === import_keycodes.ESCAPE && lastFocus?.current) {
event.preventDefault();
lastFocus.current.focus();
}
};
navigableToolbarRef.addEventListener("keydown", handleKeyDown);
return () => {
navigableToolbarRef.removeEventListener(
"keydown",
handleKeyDown
);
};
}
}, [focusEditorOnEscape, getLastFocus, toolbarRef]);
}
function NavigableToolbar({
children,
focusOnMount,
focusEditorOnEscape = false,
shouldUseKeyboardFocusShortcut = true,
__experimentalInitialIndex: initialIndex,
__experimentalOnIndexChange: onIndexChange,
orientation = "horizontal",
...props
}) {
const toolbarRef = (0, import_element.useRef)();
const isAccessibleToolbar = useIsAccessibleToolbar(toolbarRef);
useToolbarFocus({
toolbarRef,
focusOnMount,
defaultIndex: initialIndex,
onIndexChange,
isAccessibleToolbar,
shouldUseKeyboardFocusShortcut,
focusEditorOnEscape
});
if (isAccessibleToolbar) {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.Toolbar,
{
label: props["aria-label"],
ref: toolbarRef,
orientation,
...props,
children
}
);
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.NavigableMenu,
{
orientation,
role: "toolbar",
ref: toolbarRef,
...props,
children
}
);
}
//# sourceMappingURL=index.js.map