I have created an editor from composing a couple of slates examples together, namely https://www.slatejs.org/examples/richtext and https://www.slatejs.org/examples/links
However when I added these the active state for all block level nodes it doesn't work at all, meaning I can't toggle list items on and off, anchor links end up getting nested etc.
The broken code seems to be these lines, coming from isBlockActive function in all the examples:
const isBlockActive = (editor, format) => {
const [match] = Editor.nodes(editor, {
match: n => {
console.log('n.type', n.type);
return n.type === format;
},
});
return !!match;
};
match
is always undefined no matter where my cursor is located.
I am running latest on all the packages currently 0.58.1
.
Below is my toggleBlock
function I also took from the examples that uses the isBlockActive function to work out the toggling logic.
const toggleBlock = (editor, format) => {
const isActive = isBlockActive(editor, format);
const isList = LIST_TYPES.includes(format);
Transforms.unwrapNodes(editor, {
match: n => LIST_TYPES.includes(n.type),
split: true,
});
Transforms.setNodes(editor, {
type: isActive ? 'paragraph' : isList ? 'list-item' : format,
});
if (!isActive && isList) {
const block = { type: format, children: [] };
Transforms.wrapNodes(editor, block);
}
};
Has anyone run into this problem before, perhaps the codebase is not in sync with the examples and Editor.nodes
isn't recommended anymore?
All inline formatting options work as the example uses a different approach:
const isMarkActive = (editor, format) => {
const marks = Editor.marks(editor);
return marks ? marks[format] === true : false;
};
Also here is my toolbar and renderElement functions if it helps:
<Slate editor={editor} value={value} onChange={handleChange}>
<div className={styles.toolbar}>
<MarkButton format="bold" icon="bold" />
<MarkButton format="italic" icon="italic" />
<MarkButton format="underline" icon="underline" />
<MarkButton format="code" icon="code" />
<BlockButton format="heading-one" icon="h1" />
<BlockButton format="heading-two" icon="h2" />
<BlockButton format="heading-three" icon="h3" />
<BlockButton format="quote" icon="quote-left" />
<BlockButton format="numbered-list" icon="list-ol" />
<BlockButton format="bulleted-list" icon="list-ul" />
<BlockButton format="break" icon="horizontal-rule" />
<LinkButton />
</div>
...
const Element = ({ attributes, children, element }) => {
switch (element.type) {
case 'quote':
return <blockquote {...attributes}>{children}</blockquote>;
case 'code':
return (
<pre>
<code {...attributes}>{children}</code>
</pre>
);
case 'heading-one':
return <h1 {...attributes}>{children}</h1>;
case 'heading-two':
return <h2 {...attributes}>{children}</h2>;
case 'heading-three':
return <h3 {...attributes}>{children}</h3>;
case 'heading-four':
return <h4 {...attributes}>{children}</h4>;
case 'heading-five':
return <h5 {...attributes}>{children}</h5>;
case 'heading-six':
return <h6 {...attributes}>{children}</h6>;
case 'list-item':
return <li {...attributes}>{children}</li>;
case 'numbered-list':
return <ol {...attributes}>{children}</ol>;
case 'bulleted-list':
return <ul {...attributes}>{children}</ul>;
case 'link':
return (
<a {...attributes} href={element.url}>
{children}
</a>
);
default:
return <p {...attributes}>{children}</p>;
}
};
Editor.nodes()
returns an iterator.You'll need to change the
isBlockActive
function to: