diff --git a/packages/core/src/canvas/config/config.ts b/packages/core/src/canvas/config/config.ts index 8bd45e009..de374e03a 100644 --- a/packages/core/src/canvas/config/config.ts +++ b/packages/core/src/canvas/config/config.ts @@ -1,5 +1,9 @@ import Component from '../../dom_components/model/Component'; +import ComponentView from '../../dom_components/view/ComponentView'; +import Editor from '../../editor'; import { CanvasSpotBuiltInTypes } from '../model/CanvasSpot'; +import Frame from '../model/Frame'; +import FrameView from '../view/FrameView'; export interface CanvasConfig { stylePrefix?: string; @@ -102,6 +106,19 @@ export interface CanvasConfig { * @default false */ scrollableCanvas?: boolean; + + /** + * Custom renderer function for canvas content. + * This allows replacing the default HTML rendering with custom frameworks like React. + * @example + * customRenderer: ({ editor, frame, window, frameView }) => { + * // Mount React on the frame body + * const root = frame.getComponent(); + * const reactRoot = createRoot(window.document.body); + * reactRoot.render(); + * } + */ + customRenderer?: (options: { editor: Editor; frame: Frame; window: Window; frameView: FrameView }) => ComponentView; } const config: () => CanvasConfig = () => ({ diff --git a/packages/core/src/canvas/view/FrameView.ts b/packages/core/src/canvas/view/FrameView.ts index c987aeb7b..7eb88d3c3 100644 --- a/packages/core/src/canvas/view/FrameView.ts +++ b/packages/core/src/canvas/view/FrameView.ts @@ -429,14 +429,23 @@ export default class FrameView extends ModuleView { const { view } = em?.Components?.getType('wrapper') || {}; if (!view) return; - this.wrapper = new view({ - model: root, - config: { - ...root.config, - em, + if (typeof config.customRenderer === 'function') { + this.wrapper = config.customRenderer({ + editor: em.Editor, + frame: model, + window: win, frameView: this, - }, - }).render(); + }); + } else { + this.wrapper = new view({ + model: root, + config: { + ...root.config, + em, + frameView: this, + }, + }).render(); + } append(body, this.wrapper?.el!); append( body,