fix(content-manager): dont support list selector when multiple blocks are selected

This commit is contained in:
Fernando Chavez 2024-06-25 16:22:55 +02:00
parent c58fb0f790
commit 3b379e30a6
5 changed files with 61 additions and 33 deletions

View File

@ -34,7 +34,7 @@ const LinkContent = React.forwardRef<HTMLAnchorElement, LinkContentProps>(
const [linkText, setLinkText] = React.useState(elementText);
const [linkUrl, setLinkUrl] = React.useState(link.url);
const linkInputRef = React.useRef<HTMLInputElement>(null);
const showRemoveButton = editor.lastInsertedLinkPath
const isLastInsertedLink = editor.lastInsertedLinkPath
? !Path.equals(path, editor.lastInsertedLinkPath)
: true;
const [isSaveDisabled, setIsSaveDisabled] = React.useState(false);
@ -147,7 +147,7 @@ const LinkContent = React.forwardRef<HTMLAnchorElement, LinkContentProps>(
<RemoveButton
variant="danger-light"
onClick={() => removeLink(editor)}
$visible={showRemoveButton}
$visible={isLastInsertedLink}
>
{formatMessage({
id: 'components.Blocks.popover.remove',

View File

@ -272,9 +272,11 @@ const handleEnterKeyOnList = (editor: Editor) => {
* Common handler for converting a node to a list
*/
const handleConvertToList = (editor: Editor, format: Block<'list'>['format']) => {
baseHandleConvert<Block<'list-item'>>(editor, { type: 'list-item' });
const convertedPath = baseHandleConvert<Block<'list-item'>>(editor, { type: 'list-item' });
Transforms.wrapNodes(editor, { type: 'list', format, children: [] });
if (!convertedPath) return;
Transforms.wrapNodes(editor, { type: 'list', format, children: [] }, { at: convertedPath });
};
/**

View File

@ -1419,38 +1419,29 @@ describe('List', () => {
it('converts a heading with a link to a list', () => {
const baseEditor = createEditor();
baseEditor.children = [
{
type: 'heading',
level: 1,
children: [
{
text: '',
type: 'text',
},
{
type: 'link',
url: 'https://strapi.io',
children: [
{
text: 'Heading link',
type: 'text',
text: 'Heading link',
},
],
},
{
text: '',
type: 'text',
},
],
level: 1,
},
];
// Set the cursor on the heading
Transforms.select(baseEditor, {
anchor: { path: [0, 1, 0], offset: 0 },
focus: { path: [0, 1, 0], offset: 0 },
anchor: { path: [0, 0, 0], offset: 0 },
focus: { path: [0, 0, 0], offset: 0 },
});
listBlocks['list-ordered'].handleConvert!(baseEditor);

View File

@ -362,6 +362,39 @@ const ListButton = ({ block, format }: ListButtonProps) => {
return false;
};
/**
* @TODO: Currently, applying list while multiple blocks are selected is not supported.
* We should implement this feature in the future.
*/
const isListDisabled = () => {
// Always disabled when the whole editor is disabled
if (disabled) {
return true;
}
// Always enabled when there's no selection
if (!editor.selection) {
return false;
}
// Get the block node closest to the anchor and focus
const anchorNodeEntry = Editor.above(editor, {
at: editor.selection.anchor,
match: (node) => !Editor.isEditor(node) && node.type !== 'text',
});
const focusNodeEntry = Editor.above(editor, {
at: editor.selection.focus,
match: (node) => !Editor.isEditor(node) && node.type !== 'text',
});
if (!anchorNodeEntry || !focusNodeEntry) {
return false;
}
// Disabled if the anchor and focus are not in the same block
return anchorNodeEntry[0] !== focusNodeEntry[0];
};
const toggleList = (format: Block<'list'>['format']) => {
let currentListEntry;
if (editor.selection) {
@ -403,7 +436,7 @@ const ListButton = ({ block, format }: ListButtonProps) => {
name={format}
label={block.label}
isActive={isListActive()}
disabled={disabled}
disabled={isListDisabled()}
handleClick={() => toggleList(format)}
/>
);

View File

@ -1,4 +1,4 @@
import { type Element, Editor, Transforms } from 'slate';
import { type Element, type Path, Editor, Transforms } from 'slate';
/**
* Extracts some logic that is common to most blocks' handleConvert functions.
@ -7,7 +7,7 @@ import { type Element, Editor, Transforms } from 'slate';
const baseHandleConvert = <T extends Element>(
editor: Editor,
attributesToSet: Partial<T> & { type: T['type'] }
): void => {
): void | Path => {
// If there is no selection, convert last inserted node
const [_, lastNodePath] = Editor.last(editor, []);
@ -18,27 +18,29 @@ const baseHandleConvert = <T extends Element>(
at: editor.selection ?? lastNodePath,
});
// Make sure we get block nodes (elements), not an inline node
// Make sure we get a block node, not an inline node
const [, updatedLastNodePath] = Editor.last(editor, []);
const nodes = Editor.nodes(editor, {
const entry = Editor.above(editor, {
match: (node) => !Editor.isEditor(node) && node.type !== 'text' && node.type !== 'link',
at: editor.selection ?? updatedLastNodePath,
});
if (!nodes) {
if (!entry || Editor.isEditor(entry[0])) {
return;
}
for (const [element, elementPath] of nodes) {
Transforms.setNodes(
editor,
{
...getAttributesToClear(element as Element), // because of the match we can safely assume it's a Node of type Element
...attributesToSet,
} as Partial<Element>,
{ at: elementPath }
);
}
const [element, elementPath] = entry;
Transforms.setNodes(
editor,
{
...getAttributesToClear(element),
...attributesToSet,
} as Partial<Element>,
{ at: elementPath }
);
return elementPath;
};
/**