BlockNote
BlockNote copied to clipboard
Custom code block
Hi,
I would like to create a code block for my website that uses Blocknote, but when I click enter it jumps to the next line without the code block, but I would like the block to expand.
This is the code:
// code.tsx
import { defaultBlockSchema, defaultProps } from "@blocknote/core";
import { ReactSlashMenuItem, createReactBlockSpec } from "@blocknote/react";
import { CodeIcon } from "lucide-react";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
export const codeBlock = createReactBlockSpec(
{
type: "codeBlock",
propSchema: {
...defaultProps,
},
content: "inline",
},
{
render: (props) => (
<div className="bg-foreground/5 p-2 rounded-md relative">
<Select>
<SelectTrigger className="w-[180px] absolute right-1 top-1 p-1 h-max">
<SelectValue placeholder="Language" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Languages</SelectLabel>
<SelectItem value="js">JavaScript</SelectItem>
<SelectItem value="jsx">React</SelectItem>
<SelectItem value="cs">C#</SelectItem>
<SelectItem value="cpp">C++</SelectItem>
<SelectItem value="rust">Rust</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<pre ref={props.contentRef}></pre>
</div>
),
}
);
export const insertCodeBlock: ReactSlashMenuItem<typeof defaultBlockSchema> = {
name: "Code Block",
execute: (editor) => {
editor.insertBlocks(
[
{
// @ts-ignore
type: "codeBlock",
},
],
editor.getTextCursorPosition().nextBlock
);
},
aliases: ["code"],
group: "other",
icon: <CodeIcon />,
};
How do I make it not create a new paragraph when I click enter, but expand the code block?
This might not be possible atm - you can try adding an onKeyDown event listener to editor.domElement with capture=true
and call event.preventDefault(); event.stopPropagation();. The idea it that it will handle the event before BlockNote's handler, but you would have to add the line break yourself since the default behaviour is also blocked.
I had same issue. Based on the comments of matthewlipski, I was able to reflect a newline when pressing Enter with the following code.
const editor = useBlockNote({...});
const handleKeyDown = (event) => {
if (event.key === 'Enter' && !event.shiftKey){
const pos = editor.getTextCursorPosition();
if (pos?.block?.type === 'codeBlock') {
event.preventDefault();
event.stopPropagation();
const keyEvent = new KeyboardEvent('keydown', {
code: 'Enter',
key: 'Enter',
shiftKey: true,
view: window,
bubbles: false
});
editor.domElement.dispatchEvent(keyEvent);
}
}
};
useEffect(() => {
editor.domElement.addEventListener('keydown', handleKeyDown, true);
}, []);