mirror of
https://github.com/strapi/strapi.git
synced 2025-12-13 07:55:33 +00:00
fix(content-manager): dont support list selector when multiple blocks are selected
This commit is contained in:
parent
c58fb0f790
commit
3b379e30a6
@ -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',
|
||||
|
||||
@ -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 });
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user