Skip to content

InlineContent behaviour inside custom block #382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hncheung9 opened this issue Oct 16, 2023 · 1 comment · Fixed by #392
Closed

InlineContent behaviour inside custom block #382

hncheung9 opened this issue Oct 16, 2023 · 1 comment · Fixed by #392
Labels
bug Something isn't working prio:mid Medium priority

Comments

@hncheung9
Copy link

Describe the bug
InlineContent in custom block has strange overflow control.
Screenshot 2023-10-16 at 1 02 15 PM

To Reproduce

  1. create custom block(which has InlineContent)
  2. Type in InlineContent without spacing(i.e. long single string)
  3. Block overflow expands out of editor

Misc

  • Node version: v20.6.0
  • Package manager: pnpm
  • Browser: Chrome Version 117.0.5938.149 (Official Build) (arm64)

Side issue:
I am building a block with 2 editable rich-text fields. However, I cant have 2 InlineContent working in one block. So one of them is built-in InlineContent, another is ContentEditable from 'react-contenteditable'. When onClick of the custom block, it always focus on InlineContent but not ContentEditable. Is it possible to focus on other parts of the block(i.e.ContentEditable)? Also, is it possible that other parts of the block trigger onEditorContentChange so that its content can be saved in topLevelBlocks?

Sorry if there are too many issues in one report. Really appreciate the work of BlockNote nevertheless! It will certainly be a huge improvement if I can built my ideal BlockNote.


Source code if needed:
`
//imports same as custom block in https://www.blocknotejs.org/docs/block-types
//...
const [blocks, setBlocks] = useState<Block[] | null>(null);
const titleRef = useRef(null);
const contentRef = useRef(null);
const blocknotePinBlock = createReactBlockSpec({
type: 'pin',
propSchema: {
...defaultProps,
title: {
default: 'Pin-',
},
context: {
default: '',
},
colorTag: {
default: '#ff0000',
},
collapsed: {
default: false,
},
},
containsInlineContent: true,

render: ({ block }) => (
  <div className="relative flex w-full max-w-full pb-2">
    <div
      style={{ backgroundColor: block.props.colorTag }}
      className="mr-1 w-1 shrink-0"
    ></div>
    <div className="flex w-full flex-col">
      <div>
        <ContentEditable
          id={block.id + 'title'}
          style={{ zIndex: 2 }}
          innerRef={titleRef}
          className="p-1 text-3xl"
          html={block.props.title ? block.props.title : ''}
          onClick={() => {
            if (titleRef.current) titleRef.current.focus();
          }}
          onChange={(e) => {

          }}
        />
        {block.props.title === '' && (
          <div
            className="absolute top-0 w-full cursor-text select-none p-1 text-3xl text-gray-400"
            style={{ zIndex: 0 }}
            onClick={() => {
              if (titleRef.current) titleRef.current.focus();
            }}
          >
            Pin Block Title
          </div>
        )}
      </div>
        < InlineContent />
    </div>
  </div>
),

});

const customSchema = {
// Adds all default blocks.
...defaultBlockSchema,
// Adds the custom pin block.
pin: blocknotePinBlock,
} satisfies BlockSchema;

const addPinBlock: ReactSlashMenuItem = {
name: 'Insert Pin Block',
execute: (editor) => {
const title: string | null = 'Pin-' + pinNumber.current;
const context: string | null = '';

  editor.insertBlocks(
    [
      {
        type: 'pin',
        props: {
          title: title || 'Pin-',
          context: context || '',
          collapsed: false,
          colorTag: '#ff0000',
        },
      },
    ],
    editor.getTextCursorPosition().block,
    'before',
  );
},
aliases: ['pin', 'p'],
group: 'Pin',
icon: <IconPin className="w-5" />,
hint: 'Insert a pin block',

};
// Creates a new editor instance.
const editor: BlockNoteEditor = useBlockNote({
// Listens for when the editor's contents change.
blockSchema: customSchema,
slashMenuItems: [
...getDefaultReactSlashMenuItems(customSchema),
addPinBlock,
],
onEditorContentChange: (editor) =>
// Converts the editor's contents to an array of Block objects.
setBlocks(editor.topLevelBlocks),
});

return (
console.log(JSON.stringify(blocks, null, 2)),
(


<BlockNoteView editor={editor} theme={'light'} />

)
);
}`

@hncheung9 hncheung9 added the bug Something isn't working label Oct 16, 2023
@matthewlipski
Copy link
Collaborator

matthewlipski commented Oct 17, 2023

Thanks for documenting this issue! Regarding having 2 editable fields in one block - that's currently a limitation of the custom blocks API, they're really designed to only have 1 InlineContent element. You can get around the focus issue in a somewhat hacky way with a focus event handler on your InlineContent component, and trigger onEditorContentChange by storing the text of the second input field as one of the block's props (this will also ensure that the second input field's content doesn't get reset). Keep in mind that while this should work, the functionality isn't officially supported so you may run into a few issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working prio:mid Medium priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants