@wordpress/block-editor
Version:
314 lines (275 loc) • 11.1 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _classnames = _interopRequireDefault(require("classnames"));
var _blocks = require("@wordpress/blocks");
var _components = require("@wordpress/components");
var _compose = require("@wordpress/compose");
var _icons = require("@wordpress/icons");
var _data = require("@wordpress/data");
var _i18n = require("@wordpress/i18n");
var _dom = require("@wordpress/dom");
var _leaf = _interopRequireDefault(require("./leaf"));
var _useListViewScrollIntoView = _interopRequireDefault(require("./use-list-view-scroll-into-view"));
var _button = require("../block-mover/button");
var _blockContents = _interopRequireDefault(require("./block-contents"));
var _context = require("./context");
var _utils = require("./utils");
var _store = require("../../store");
var _useBlockDisplayInformation = _interopRequireDefault(require("../use-block-display-information"));
var _blockLock = require("../block-lock");
var _lockUnlock = require("../../lock-unlock");
var _ariaReferencedText = _interopRequireDefault(require("./aria-referenced-text"));
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
function ListViewBlock({
block: {
clientId
},
isDragged,
isSelected,
isBranchSelected,
selectBlock,
position,
level,
rowCount,
siblingBlockCount,
showBlockMovers,
path,
isExpanded,
selectedClientIds,
isSyncedBranch
}) {
const cellRef = (0, _element.useRef)(null);
const rowRef = (0, _element.useRef)(null);
const [isHovered, setIsHovered] = (0, _element.useState)(false);
const {
isLocked,
canEdit
} = (0, _blockLock.useBlockLock)(clientId);
const isFirstSelectedBlock = isSelected && selectedClientIds[0] === clientId;
const isLastSelectedBlock = isSelected && selectedClientIds[selectedClientIds.length - 1] === clientId;
const {
toggleBlockHighlight
} = (0, _data.useDispatch)(_store.store);
const blockInformation = (0, _useBlockDisplayInformation.default)(clientId);
const blockTitle = blockInformation?.title || (0, _i18n.__)('Untitled');
const block = (0, _data.useSelect)(select => select(_store.store).getBlock(clientId), [clientId]);
const blockName = (0, _data.useSelect)(select => select(_store.store).getBlockName(clientId), [clientId]);
const blockEditingMode = (0, _data.useSelect)(select => (0, _lockUnlock.unlock)(select(_store.store)).getBlockEditingMode(clientId), [clientId]);
const showBlockActions = // When a block hides its toolbar it also hides the block settings menu,
// since that menu is part of the toolbar in the editor canvas.
// List View respects this by also hiding the block settings menu.
(0, _blocks.hasBlockSupport)(blockName, '__experimentalToolbar', true) && // Don't show the settings menu if block is disabled or content only.
blockEditingMode === 'default';
const instanceId = (0, _compose.useInstanceId)(ListViewBlock);
const descriptionId = `list-view-block-select-button__${instanceId}`;
const blockPositionDescription = (0, _utils.getBlockPositionDescription)(position, siblingBlockCount, level);
const blockAriaLabel = isLocked ? (0, _i18n.sprintf)( // translators: %s: The title of the block. This string indicates a link to select the locked block.
(0, _i18n.__)('%s (locked)'), blockTitle) : blockTitle;
const settingsAriaLabel = (0, _i18n.sprintf)( // translators: %s: The title of the block.
(0, _i18n.__)('Options for %s'), blockTitle);
const {
isTreeGridMounted,
expand,
collapse,
BlockSettingsMenu,
listViewInstanceId,
expandedState,
setInsertedBlock,
treeGridElementRef
} = (0, _context.useListViewContext)();
const hasSiblings = siblingBlockCount > 0;
const hasRenderedMovers = showBlockMovers && hasSiblings;
const moverCellClassName = (0, _classnames.default)('block-editor-list-view-block__mover-cell', {
'is-visible': isHovered || isSelected
});
const listViewBlockSettingsClassName = (0, _classnames.default)('block-editor-list-view-block__menu-cell', {
'is-visible': isHovered || isFirstSelectedBlock
}); // If ListView has experimental features related to the Persistent List View,
// only focus the selected list item on mount; otherwise the list would always
// try to steal the focus from the editor canvas.
(0, _element.useEffect)(() => {
if (!isTreeGridMounted && isSelected) {
cellRef.current.focus();
}
}, []);
const onMouseEnter = (0, _element.useCallback)(() => {
setIsHovered(true);
toggleBlockHighlight(clientId, true);
}, [clientId, setIsHovered, toggleBlockHighlight]);
const onMouseLeave = (0, _element.useCallback)(() => {
setIsHovered(false);
toggleBlockHighlight(clientId, false);
}, [clientId, setIsHovered, toggleBlockHighlight]);
const selectEditorBlock = (0, _element.useCallback)(event => {
selectBlock(event, clientId);
event.preventDefault();
}, [clientId, selectBlock]);
const updateFocusAndSelection = (0, _element.useCallback)((focusClientId, shouldSelectBlock) => {
if (shouldSelectBlock) {
selectBlock(undefined, focusClientId, null, null);
}
const getFocusElement = () => {
const row = treeGridElementRef.current?.querySelector(`[role=row][data-block="${focusClientId}"]`);
if (!row) return null; // Focus the first focusable in the row, which is the ListViewBlockSelectButton.
return _dom.focus.focusable.find(row)[0];
};
let focusElement = getFocusElement();
if (focusElement) {
focusElement.focus();
} else {
// The element hasn't been painted yet. Defer focusing on the next frame.
// This could happen when all blocks have been deleted and the default block
// hasn't been added to the editor yet.
window.requestAnimationFrame(() => {
focusElement = getFocusElement(); // Ignore if the element still doesn't exist.
if (focusElement) {
focusElement.focus();
}
});
}
}, [selectBlock, treeGridElementRef]);
const toggleExpanded = (0, _element.useCallback)(event => {
// Prevent shift+click from opening link in a new window when toggling.
event.preventDefault();
event.stopPropagation();
if (isExpanded === true) {
collapse(clientId);
} else if (isExpanded === false) {
expand(clientId);
}
}, [clientId, expand, collapse, isExpanded]);
let colSpan;
if (hasRenderedMovers) {
colSpan = 2;
} else if (!showBlockActions) {
colSpan = 3;
}
const classes = (0, _classnames.default)({
'is-selected': isSelected,
'is-first-selected': isFirstSelectedBlock,
'is-last-selected': isLastSelectedBlock,
'is-branch-selected': isBranchSelected,
'is-synced-branch': isSyncedBranch,
'is-dragging': isDragged,
'has-single-cell': !showBlockActions,
'is-synced': blockInformation?.isSynced
}); // Only include all selected blocks if the currently clicked on block
// is one of the selected blocks. This ensures that if a user attempts
// to alter a block that isn't part of the selection, they're still able
// to do so.
const dropdownClientIds = selectedClientIds.includes(clientId) ? selectedClientIds : [clientId]; // Pass in a ref to the row, so that it can be scrolled
// into view when selected. For long lists, the placeholder for the
// selected block is also observed, within ListViewLeafPlaceholder.
(0, _useListViewScrollIntoView.default)({
isSelected,
rowItemRef: rowRef,
selectedClientIds
}); // Detect if there is a block in the canvas currently being edited and multi-selection is not happening.
const currentlyEditingBlockInCanvas = isSelected && selectedClientIds.length === 1;
return (0, _element.createElement)(_leaf.default, {
className: classes,
onMouseEnter: onMouseEnter,
onMouseLeave: onMouseLeave,
onFocus: onMouseEnter,
onBlur: onMouseLeave,
level: level,
position: position,
rowCount: rowCount,
path: path,
id: `list-view-${listViewInstanceId}-block-${clientId}`,
"data-block": clientId,
"data-expanded": canEdit ? isExpanded : undefined,
ref: rowRef
}, (0, _element.createElement)(_components.__experimentalTreeGridCell, {
className: "block-editor-list-view-block__contents-cell",
colSpan: colSpan,
ref: cellRef,
"aria-selected": !!isSelected
}, ({
ref,
tabIndex,
onFocus
}) => (0, _element.createElement)("div", {
className: "block-editor-list-view-block__contents-container"
}, (0, _element.createElement)(_blockContents.default, {
block: block,
onClick: selectEditorBlock,
onToggleExpanded: toggleExpanded,
isSelected: isSelected,
position: position,
siblingBlockCount: siblingBlockCount,
level: level,
ref: ref,
tabIndex: currentlyEditingBlockInCanvas ? 0 : tabIndex,
onFocus: onFocus,
isExpanded: canEdit ? isExpanded : undefined,
selectedClientIds: selectedClientIds,
ariaLabel: blockAriaLabel,
ariaDescribedBy: descriptionId,
updateFocusAndSelection: updateFocusAndSelection
}), (0, _element.createElement)(_ariaReferencedText.default, {
id: descriptionId
}, blockPositionDescription))), hasRenderedMovers && (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_components.__experimentalTreeGridCell, {
className: moverCellClassName,
withoutGridItem: true
}, (0, _element.createElement)(_components.__experimentalTreeGridItem, null, ({
ref,
tabIndex,
onFocus
}) => (0, _element.createElement)(_button.BlockMoverUpButton, {
orientation: "vertical",
clientIds: [clientId],
ref: ref,
tabIndex: tabIndex,
onFocus: onFocus
})), (0, _element.createElement)(_components.__experimentalTreeGridItem, null, ({
ref,
tabIndex,
onFocus
}) => (0, _element.createElement)(_button.BlockMoverDownButton, {
orientation: "vertical",
clientIds: [clientId],
ref: ref,
tabIndex: tabIndex,
onFocus: onFocus
})))), showBlockActions && BlockSettingsMenu && (0, _element.createElement)(_components.__experimentalTreeGridCell, {
className: listViewBlockSettingsClassName,
"aria-selected": !!isSelected
}, ({
ref,
tabIndex,
onFocus
}) => (0, _element.createElement)(BlockSettingsMenu, {
clientIds: dropdownClientIds,
block: block,
icon: _icons.moreVertical,
label: settingsAriaLabel,
toggleProps: {
ref,
className: 'block-editor-list-view-block__menu',
tabIndex,
onFocus
},
disableOpenOnArrowDown: true,
expand: expand,
expandedState: expandedState,
setInsertedBlock: setInsertedBlock,
__experimentalSelectBlock: updateFocusAndSelection
})));
}
var _default = (0, _element.memo)(ListViewBlock);
exports.default = _default;
//# sourceMappingURL=block.js.map