BlockNote icon indicating copy to clipboard operation
BlockNote copied to clipboard

Image dissappearing (width=0) from image block if BlockNote is not visible (not in viewport)

Open kblt opened this issue 1 year ago • 3 comments

Describe the bug <what's going wrong!?> I have embedded BlockNotes in the cards on the big whiteboard. Sometimes cards can be outside the viewport. While refreshing images are not showing up. Some investigations showed it's because all images which are outside the viewport have width=0.

If go to docs: @blocknote/reacr/src/blocks/ImageBlockContent.tsx

const [width, setWidth] = useState<number>(
    Math.min(
      props.block.props.previewWidth!,
      props.editor.domElement.firstElementChild!.clientWidth
    )
  );

So if we check props.editor.domElement.firstElementChild - it will be div with className = "bn-block-group" and while refreshing the whole and card is outside viewport - this element will be returning clientWidth = 0. If card (embedded blocknote) is visible the clientWidth will be > 0. If check size of BlockNote component it's fine - width > 0.

It was possible to fix by manual change size of the image block to set attribute width of image. p.s. please don't be mad on my code - i hope it's ok

editor.document.forEach((block, _) => {
      if (block.type === "image" && block.props.showPreview == true) {
        const outerBlocks = editor?.domElement?.getElementsByClassName("bn-block-outer")
        if (outerBlocks != null) {
            const innerBlock = Array.from(outerBlocks).find((item) => item.getAttribute("data-id") === block.id);
            if (innerBlock != null) {
                const imageBlocks = innerBlock.getElementsByClassName("bn-visual-media");
                Array.from(imageBlocks).forEach((imageBlock) => {
                    if (imageBlock.getAttribute("width") === "0") {
                        imageBlock.setAttribute("width", block.props.previewWidth.toString());
                    }
                });                            
            }
        }
      }
  })

Please let me know if there are any ways to avoid manual change parameters in DOM - maybe override ImageBlockContent or pass some other parameter to blocknote to remove clientWidth checking. Or maybe other ways to fix it. Thanks

here is some example how it works:

https://github.com/user-attachments/assets/6b52aed9-eca3-4d6d-9afd-8ec9547716fb

To Reproduce <clear steps to reproduce are super helpful! Best is to provide an online sandbox, click to create one>

We are using TLDraw with cards with BlockNote component inside card.

Tried to make 2 blocknotes with one outside the screen, but seems working ok in this case.

Misc

  • Node version: node: '22.5.1',

  • Package manager: npm: '10.7.0',

  • Browser: Chrome Version 128.0.6613.85 (Official Build) (64-bit)

  • [ ] I'm a sponsor and would appreciate if you could look into this sooner than later 💖

kblt avatar Aug 28 '24 07:08 kblt

Thanks for reporting this! We didn't consider the edge case before, but I think we might be able to fix this by using getBoundingClientRect().width instead of clientWidth. For now, keep using the workaround if it's working for you, and in the meantime I'll look into fixing this👍

matthewlipski avatar Aug 28 '24 17:08 matthewlipski

Thanks for reporting this! We didn't consider the edge case before, but I think we might be able to fix this by using getBoundingClientRect().width instead of clientWidth. For now, keep using the workaround if it's working for you, and in the meantime I'll look into fixing this👍

Thanks a lot for your fast answer and for your work! Looking forward for future updates. 💪

Thanks for your suggestion. I also checked getBoundingClientRect().width and it's also returning zeros while blocknote is outside the viewport. console.log(editor?.domElement?.firstElementChild?.getBoundingClientRect()); is returning DOMRect {x: 0, y: 0, width: 0, height: 0, top: 0,width: 0,x: 0, y: 0} in our case. If blocknote is visible - all values are fine.

Maybe it's possible to work around value "0", but i'm not sure about other edge cases.

kblt avatar Aug 29 '24 01:08 kblt

Ah damn, that's a shame - it might be annoying to come up with a robust fix for this in that case

matthewlipski avatar Aug 30 '24 16:08 matthewlipski

I have the same issue. But my image block is in the editor. I upload, everything is good. But when i refresh the page the width is 0. I've investigated and the same issue

const [width, setWidth] = useState<number>(
    Math.min(
      props.block.props.previewWidth!,
      props.editor.domElement.firstElementChild!.clientWidth
    )
  );

the clientWidth is 0 and the getBoundingClientRect().width is also 0. I don't see this as an edge case.

https://github.com/TypeCellOS/BlockNote/blob/71792c2fbdc99785cd8ce5b540d1a468e6c66131/packages/core/src/blocks/ImageBlockContent/ImageBlockContent.ts#L71

Do you plan to help us here?

PandasProperty avatar Dec 05 '24 13:12 PandasProperty

getting this error while using blockToFullHTML

export async function blockToHTML(buffer) { const editor = ServerBlockNoteEditor.create(); const doc = new Y.Doc(); Y.applyUpdate(doc, buffer); console.log(doc.getXmlFragment('default').toJSON()); const blocks = editor.yXmlFragmentToBlocks(doc.getXmlFragment("default")); console.log(blocks); console.log(await editor.blocksToFullHTML(blocks)) }

Blocks: { id: 'b1d52444-6815-423b-8431-9c6d5aaadd21', type: 'image', props: { backgroundColor: 'default', textAlignment: 'left', name: 'techdoc.jpg', url: 'https://storage.googleapis.com/dev-techdoc.walkover.in/h1Qef_JkjKnV/PgBUvXEIWGyM/c7ebd570-24ae-4543-b0fc-1c604374679a_techdoc.jpg', caption: '', showPreview: true, previewWidth: 196 }, content: undefined, children: [] },

didn't converted in HTML, got this error: t.domElement.firstElementChild.clientWidth ^ TypeError: Cannot read properties of undefined (reading 'firstElementChild')

@matthewlipski please help on this!!

goutam01mehta avatar Dec 07 '24 11:12 goutam01mehta

This should be fixed coming week! see #1305

YousefED avatar Dec 07 '24 20:12 YousefED