craft.js icon indicating copy to clipboard operation
craft.js copied to clipboard

Support for Frame inside iframe / react-frame-component / react-styled-frame

Open hdaggett opened this issue 4 years ago • 8 comments

I'd like to use Craft for a drag-and-drop React editor, where the preview is resizable to show responsive behavior.

I tried using react-styled-frame like this:

<Editor resolver={allComponents}>
    <StyledFrame>
        <Frame>
            <Canvas>
                <TextComponent text="Hello world" />
            </Canvas>
        </Frame>
    </StyledFrame>
</Editor>

...but the drag-and-drop indicators show up in the wrong space, probably using the global window coordinates instead of the coordinates within the iframe.

hdaggett avatar Jan 15 '20 22:01 hdaggett

@hdaggett It's an iframe-canvas interplay transition bug. More details can be found here: https://stackoverflow.com/questions/10514081/how-to-put-iframe-in-to-canvas

i.e. you will face performance issues; https://stackoverflow.com/questions/4020910/html5-multiple-canvas-on-a-single-page

prateekrastogi avatar Jan 16 '20 05:01 prateekrastogi

@prateekrastogi The links you've shared are discussing the html <canvas> . Care to elaborate how that relates to this ?

I've not yet investigated this bug in details, but it's most likely caused by the drop indicator not being placed in the <Frame />.

prevwong avatar Jan 16 '20 05:01 prevwong

<iframe/> creates an isolated context. The iframe doesn't share scripts or stylesheets with the main document. This might actually be trickier than you might think.

If you just want to create a resizable preview, can't you just change the width of the container where craft.js renders your content? (You could even use some smart mouse-resizable container that 100% exists as a npm package already.)

And if you wanted to stick to iframes exactly for their isolation to better simulate the rendering in production. Wouldn't it be better to pass in just the serialized JSON and let an isolated rendering script handle it? I am talking about a new React instance within the iframe that would grab the JSON and construct a static page. I believe that's the usecase anyway, to have a page designed using craft.js, store the JSON in database and then use that JSON in different, totally unrelated place just to render the content.

PS: Anyway thanks for the brain exercise. I was actually looking for a solution to render a Real preview without the additional markup and html attributes craft.js might introduce for those various Canvas, Frame and other control/overhead components. And the actual solution (for my usecase) might just be the craft.js -> JSON -> render.

ackvf avatar Jan 16 '20 19:01 ackvf

@ackvf resizing the container doesn't show responsive behavior (i.e. any css @media query selectors won't be applied because it uses the window size, not the container size)

I got around the "share scripts or stylesheets" problem with this hack inside the StyledFrame: <div dangerouslySetInnerHTML={{__html: document.head.innerHTML}}></div>

It actually appears that Craft is working inside StyledFrame, but the indicators just aren't appearing in the right place. I can still drag and drop and move things around, but the indicator coordinates are off. I had this working with SlateJS so I feel it should be possible to also work with Craft.

hdaggett avatar Jan 16 '20 19:01 hdaggett

@ackvf Craft.js does not introduce additional markup/attributes (only the draggable attribute is added to the elements with the drag connector). You can still pass the json prop to preview the result and also set the enabled prop to false in the <Editor /> and that will disable all editing features, and remove the draggable attribute as well.

prevwong avatar Jan 17 '20 03:01 prevwong

Hi, not sure if this could help, but I'm working to make it support iframes

https://github.com/prevwong/craft.js/pull/125

nicoladefranceschi avatar Sep 24 '20 07:09 nicoladefranceschi

hi @nicoladefranceschi could you post an example on how to use craft.js with an iframe? Thank you!

shakdoesgithub avatar May 22 '21 17:05 shakdoesgithub

For those who want to render craft.js contents into an iframe, here are my thoughts and learnings:

When you use native html

Ideally you should be using react-frame-component as advised by the Author, because what this library does is, it waits until your iframe is loaded and then renders your children inside a React portal . This React portal allows the contents rendered inside your iframe content to be part of your parent's React-tree.

Even if the iframe contents are part of React context, your external resources cannot be. So if your parent has an external .css file it would not work inside the react-frame-component's iframe but you may have to inject it seperately on the head of the iframe.

Here is an extended example of the Author's old example where you can see the contents rendered inside an iframe using react-frame-component but not styles isolated.

https://codesandbox.io/p/devbox/9tsc5r

rajeshdavidbabu avatar Jan 14 '24 19:01 rajeshdavidbabu