@gechiui/block-editor
Version:
266 lines (222 loc) • 8.82 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@gechiui/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classnames = _interopRequireDefault(require("classnames"));
var _icons = require("@gechiui/icons");
var _components = require("@gechiui/components");
var _data = require("@gechiui/data");
var _keycodes = require("@gechiui/keycodes");
var _blocks = require("@gechiui/blocks");
var _a11y = require("@gechiui/a11y");
var _dom = require("@gechiui/dom");
var _i18n = require("@gechiui/i18n");
var _blockTitle = _interopRequireDefault(require("../block-title"));
var _blockIcon = _interopRequireDefault(require("../block-icon"));
var _store = require("../../store");
var _blockDraggable = _interopRequireDefault(require("../block-draggable"));
var _useBlockDisplayInformation = _interopRequireDefault(require("../use-block-display-information"));
/**
* External dependencies
*/
/**
* GeChiUI dependencies
*/
/**
* Internal dependencies
*/
/**
* Block selection button component, displaying the label of the block. If the block
* descends from a root block, a button is displayed enabling the user to select
* the root block.
*
* @param {string} props Component props.
* @param {string} props.clientId Client ID of block.
*
* @return {GCComponent} The component to be rendered.
*/
function BlockSelectionButton(_ref) {
let {
clientId,
rootClientId,
blockElement
} = _ref;
const blockInformation = (0, _useBlockDisplayInformation.default)(clientId);
const selected = (0, _data.useSelect)(select => {
var _getBlockListSettings;
const {
getBlock,
getBlockIndex,
hasBlockMovingClientId,
getBlockListSettings
} = select(_store.store);
const index = getBlockIndex(clientId);
const {
name,
attributes
} = getBlock(clientId);
const blockMovingMode = hasBlockMovingClientId();
return {
index,
name,
attributes,
blockMovingMode,
orientation: (_getBlockListSettings = getBlockListSettings(rootClientId)) === null || _getBlockListSettings === void 0 ? void 0 : _getBlockListSettings.orientation
};
}, [clientId, rootClientId]);
const {
index,
name,
attributes,
blockMovingMode,
orientation
} = selected;
const {
setNavigationMode,
removeBlock
} = (0, _data.useDispatch)(_store.store);
const ref = (0, _element.useRef)();
const blockType = (0, _blocks.getBlockType)(name);
const label = (0, _blocks.__experimentalGetAccessibleBlockLabel)(blockType, attributes, index + 1, orientation); // Focus the breadcrumb in navigation mode.
(0, _element.useEffect)(() => {
ref.current.focus();
(0, _a11y.speak)(label);
}, [label]);
const {
hasBlockMovingClientId,
getBlockIndex,
getBlockRootClientId,
getClientIdsOfDescendants,
getSelectedBlockClientId,
getMultiSelectedBlocksEndClientId,
getPreviousBlockClientId,
getNextBlockClientId,
isNavigationMode
} = (0, _data.useSelect)(_store.store);
const {
selectBlock,
clearSelectedBlock,
setBlockMovingClientId,
moveBlockToPosition
} = (0, _data.useDispatch)(_store.store);
function onKeyDown(event) {
const {
keyCode
} = event;
const isUp = keyCode === _keycodes.UP;
const isDown = keyCode === _keycodes.DOWN;
const isLeft = keyCode === _keycodes.LEFT;
const isRight = keyCode === _keycodes.RIGHT;
const isTab = keyCode === _keycodes.TAB;
const isEscape = keyCode === _keycodes.ESCAPE;
const isEnter = keyCode === _keycodes.ENTER;
const isSpace = keyCode === _keycodes.SPACE;
const isShift = event.shiftKey;
if (keyCode === _keycodes.BACKSPACE || keyCode === _keycodes.DELETE) {
removeBlock(clientId);
event.preventDefault();
return;
}
const selectedBlockClientId = getSelectedBlockClientId();
const selectionEndClientId = getMultiSelectedBlocksEndClientId();
const selectionBeforeEndClientId = getPreviousBlockClientId(selectionEndClientId || selectedBlockClientId);
const selectionAfterEndClientId = getNextBlockClientId(selectionEndClientId || selectedBlockClientId);
const navigateUp = isTab && isShift || isUp;
const navigateDown = isTab && !isShift || isDown; // Move out of current nesting level (no effect if at root level).
const navigateOut = isLeft; // Move into next nesting level (no effect if the current block has no innerBlocks).
const navigateIn = isRight;
let focusedBlockUid;
if (navigateUp) {
focusedBlockUid = selectionBeforeEndClientId;
} else if (navigateDown) {
focusedBlockUid = selectionAfterEndClientId;
} else if (navigateOut) {
var _getBlockRootClientId;
focusedBlockUid = (_getBlockRootClientId = getBlockRootClientId(selectedBlockClientId)) !== null && _getBlockRootClientId !== void 0 ? _getBlockRootClientId : selectedBlockClientId;
} else if (navigateIn) {
var _getClientIdsOfDescen;
focusedBlockUid = (_getClientIdsOfDescen = getClientIdsOfDescendants([selectedBlockClientId])[0]) !== null && _getClientIdsOfDescen !== void 0 ? _getClientIdsOfDescen : selectedBlockClientId;
}
const startingBlockClientId = hasBlockMovingClientId();
if (isEscape && isNavigationMode()) {
clearSelectedBlock();
event.preventDefault();
}
if (isEscape && startingBlockClientId && !event.defaultPrevented) {
setBlockMovingClientId(null);
event.preventDefault();
}
if ((isEnter || isSpace) && startingBlockClientId) {
const sourceRoot = getBlockRootClientId(startingBlockClientId);
const destRoot = getBlockRootClientId(selectedBlockClientId);
const sourceBlockIndex = getBlockIndex(startingBlockClientId);
let destinationBlockIndex = getBlockIndex(selectedBlockClientId);
if (sourceBlockIndex < destinationBlockIndex && sourceRoot === destRoot) {
destinationBlockIndex -= 1;
}
moveBlockToPosition(startingBlockClientId, sourceRoot, destRoot, destinationBlockIndex);
selectBlock(startingBlockClientId);
setBlockMovingClientId(null);
}
if (navigateDown || navigateUp || navigateOut || navigateIn) {
if (focusedBlockUid) {
event.preventDefault();
selectBlock(focusedBlockUid);
} else if (isTab && selectedBlockClientId) {
let nextTabbable;
if (navigateDown) {
nextTabbable = _dom.focus.tabbable.findNext(blockElement);
if (!nextTabbable) {
nextTabbable = blockElement.ownerDocument.defaultView.frameElement;
nextTabbable = _dom.focus.tabbable.findNext(nextTabbable);
}
} else {
nextTabbable = _dom.focus.tabbable.findPrevious(blockElement);
}
if (nextTabbable) {
event.preventDefault();
nextTabbable.focus();
clearSelectedBlock();
}
}
}
}
const classNames = (0, _classnames.default)('block-editor-block-list__block-selection-button', {
'is-block-moving-mode': !!blockMovingMode
});
const dragHandleLabel = (0, _i18n.__)('拖动');
return (0, _element.createElement)("div", {
className: classNames
}, (0, _element.createElement)(_components.Flex, {
justify: "center",
className: "block-editor-block-list__block-selection-button__content"
}, (0, _element.createElement)(_components.FlexItem, null, (0, _element.createElement)(_blockIcon.default, {
icon: blockInformation === null || blockInformation === void 0 ? void 0 : blockInformation.icon,
showColors: true
})), (0, _element.createElement)(_components.FlexItem, null, (0, _element.createElement)(_blockDraggable.default, {
clientIds: [clientId]
}, draggableProps => (0, _element.createElement)(_components.Button, (0, _extends2.default)({
icon: _icons.dragHandle,
className: "block-selection-button_drag-handle",
"aria-hidden": "true",
label: dragHandleLabel // Should not be able to tab to drag handle as this
// button can only be used with a pointer device.
,
tabIndex: "-1"
}, draggableProps)))), (0, _element.createElement)(_components.FlexItem, null, (0, _element.createElement)(_components.Button, {
ref: ref,
onClick: () => setNavigationMode(false),
onKeyDown: onKeyDown,
label: label,
className: "block-selection-button_select-button"
}, (0, _element.createElement)(_blockTitle.default, {
clientId: clientId
})))));
}
var _default = BlockSelectionButton;
exports.default = _default;
//# sourceMappingURL=block-selection-button.js.map