@wordpress/block-library
Version:
Block library for the WordPress editor.
159 lines (142 loc) • 4.53 kB
JavaScript
/**
* WordPress dependencies
*/
import { useRegistry, useDispatch, useSelect } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { getDefaultBlockName, switchToBlockType } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import useOutdentListItem from './use-outdent-list-item';
const {
name: listItemName
} = {
$schema: "https://schemas.wp.org/trunk/block.json",
apiVersion: 2,
name: "core/list-item",
title: "List item",
category: "text",
parent: ["core/list"],
description: "Create a list item.",
textdomain: "default",
attributes: {
placeholder: {
type: "string"
},
content: {
type: "string",
source: "html",
selector: "li",
"default": "",
__experimentalRole: "content"
}
},
supports: {
className: false,
__experimentalSelector: "li"
}
};
export default function useMerge(clientId) {
const registry = useRegistry();
const {
getPreviousBlockClientId,
getNextBlockClientId,
getBlockOrder,
getBlockRootClientId,
getBlockName,
getBlock
} = useSelect(blockEditorStore);
const {
mergeBlocks,
moveBlocksToPosition,
replaceBlock,
selectBlock
} = useDispatch(blockEditorStore);
const [, outdentListItem] = useOutdentListItem(clientId);
function getTrailingId(id) {
const order = getBlockOrder(id);
if (!order.length) {
return id;
}
return getTrailingId(order[order.length - 1]);
}
function getParentListItemId(id) {
const listId = getBlockRootClientId(id);
const parentListItemId = getBlockRootClientId(listId);
if (!parentListItemId) return;
if (getBlockName(parentListItemId) !== listItemName) return;
return parentListItemId;
}
/**
* Return the next list item with respect to the given list item. If none,
* return the next list item of the parent list item if it exists.
*
* @param {string} id A list item client ID.
* @return {string?} The client ID of the next list item.
*/
function _getNextId(id) {
const next = getNextBlockClientId(id);
if (next) return next;
const parentListItemId = getParentListItemId(id);
if (!parentListItemId) return;
return _getNextId(parentListItemId);
}
/**
* Given a client ID, return the client ID of the list item on the next
* line, regardless of indentation level.
*
* @param {string} id The client ID of the current list item.
* @return {string?} The client ID of the next list item.
*/
function getNextId(id) {
const order = getBlockOrder(id); // If the list item does not have a nested list, return the next list
// item.
if (!order.length) {
return _getNextId(id);
} // Get the first list item in the nested list.
return getBlockOrder(order[0])[0];
}
function switchToDefaultBlockType(forward) {
const rootClientId = getBlockRootClientId(clientId);
const replacement = switchToBlockType(getBlock(rootClientId), getDefaultBlockName());
const indexToSelect = forward ? replacement.length - 1 : 0;
const initialPosition = forward ? -1 : 0;
registry.batch(() => {
replaceBlock(rootClientId, replacement);
selectBlock(replacement[indexToSelect].clientId, initialPosition);
});
}
return forward => {
if (forward) {
const nextBlockClientId = getNextId(clientId);
if (!nextBlockClientId) {
switchToDefaultBlockType(forward);
return;
}
if (getParentListItemId(nextBlockClientId)) {
outdentListItem(nextBlockClientId);
} else {
registry.batch(() => {
moveBlocksToPosition(getBlockOrder(nextBlockClientId), nextBlockClientId, getPreviousBlockClientId(nextBlockClientId));
mergeBlocks(clientId, nextBlockClientId);
});
}
} else {
// Merging is only done from the top level. For lowel levels, the
// list item is outdented instead.
const previousBlockClientId = getPreviousBlockClientId(clientId);
if (getParentListItemId(clientId)) {
outdentListItem(clientId);
} else if (previousBlockClientId) {
const trailingId = getTrailingId(previousBlockClientId);
registry.batch(() => {
moveBlocksToPosition(getBlockOrder(clientId), clientId, previousBlockClientId);
mergeBlocks(trailingId, clientId);
});
} else {
switchToDefaultBlockType(forward);
}
}
};
}
//# sourceMappingURL=use-merge.js.map