BlockNote icon indicating copy to clipboard operation
BlockNote copied to clipboard

Custom code block

Open DDDASHXD opened this issue 1 year ago • 2 comments

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?

DDDASHXD avatar Feb 12 '24 11:02 DDDASHXD

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.

matthewlipski avatar Feb 12 '24 13:02 matthewlipski

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);
}, []);

yamap24 avatar Feb 13 '24 06:02 yamap24