diff --git a/packages/core/src/canvas/config/config.ts b/packages/core/src/canvas/config/config.ts
index de374e03a..01266fc68 100644
--- a/packages/core/src/canvas/config/config.ts
+++ b/packages/core/src/canvas/config/config.ts
@@ -5,6 +5,14 @@ import { CanvasSpotBuiltInTypes } from '../model/CanvasSpot';
import Frame from '../model/Frame';
import FrameView from '../view/FrameView';
+export interface CustomRendererProps {
+ editor: Editor;
+ frame: Frame;
+ window: Window;
+ frameView: FrameView;
+ onMount: (view: ComponentView) => void;
+}
+
export interface CanvasConfig {
stylePrefix?: string;
@@ -118,7 +126,7 @@ export interface CanvasConfig {
* reactRoot.render();
* }
*/
- customRenderer?: (options: { editor: Editor; frame: Frame; window: Window; frameView: FrameView }) => ComponentView;
+ customRenderer?: (props: CustomRendererProps) => void;
}
const config: () => CanvasConfig = () => ({
diff --git a/packages/core/src/canvas/view/FrameView.ts b/packages/core/src/canvas/view/FrameView.ts
index 7eb88d3c3..123127dcf 100644
--- a/packages/core/src/canvas/view/FrameView.ts
+++ b/packages/core/src/canvas/view/FrameView.ts
@@ -1,18 +1,18 @@
-import { bindAll, debounce, isString, isUndefined } from 'underscore';
+import { bindAll, debounce, isFunction, isString } from 'underscore';
import { ModuleView } from '../../abstract';
import { BoxRect, ObjectAny } from '../../common';
import CssRulesView from '../../css_composer/view/CssRulesView';
-import ComponentWrapperView from '../../dom_components/view/ComponentWrapperView';
-import ComponentView from '../../dom_components/view/ComponentView';
import { type as typeHead } from '../../dom_components/model/ComponentHead';
+import ComponentView from '../../dom_components/view/ComponentView';
+import ComponentWrapperView from '../../dom_components/view/ComponentWrapperView';
+import AutoScroller from '../../utils/AutoScroller';
import Droppable from '../../utils/Droppable';
import { append, appendVNodes, createCustomEvent, createEl, motionsEv, off, on } from '../../utils/dom';
import { hasDnd, setViewEl } from '../../utils/mixins';
import Canvas from '../model/Canvas';
import Frame from '../model/Frame';
-import FrameWrapView from './FrameWrapView';
import CanvasEvents from '../types';
-import AutoScroller from '../../utils/AutoScroller';
+import FrameWrapView from './FrameWrapView';
export default class FrameView extends ModuleView {
/** @ts-ignore */
@@ -339,7 +339,6 @@ export default class FrameView extends ModuleView {
renderBody() {
const { config, em, model, ppfx } = this;
- const doc = this.getDoc();
const body = this.getBody();
const win = this.getWindow();
const hasAutoHeight = model.hasAutoHeight();
@@ -429,12 +428,16 @@ export default class FrameView extends ModuleView {
const { view } = em?.Components?.getType('wrapper') || {};
if (!view) return;
- if (typeof config.customRenderer === 'function') {
- this.wrapper = config.customRenderer({
+ if (isFunction(config.customRenderer)) {
+ config.customRenderer({
editor: em.Editor,
frame: model,
window: win,
frameView: this,
+ onMount: (rootView) => {
+ this.wrapper = rootView;
+ this._onRootMount(rootView);
+ },
});
} else {
this.wrapper = new view({
@@ -445,8 +448,15 @@ export default class FrameView extends ModuleView {
frameView: this,
},
}).render();
+ this._onRootMount(this.wrapper!);
}
- append(body, this.wrapper?.el!);
+ }
+
+ _onRootMount(rootView: ComponentView) {
+ const { config, em, model } = this;
+ const doc = this.getDoc();
+ const body = doc.body;
+ append(body, rootView.el);
append(
body,
new CssRulesView({
diff --git a/packages/core/src/utils/Droppable.ts b/packages/core/src/utils/Droppable.ts
index c38396064..368503165 100644
--- a/packages/core/src/utils/Droppable.ts
+++ b/packages/core/src/utils/Droppable.ts
@@ -187,9 +187,10 @@ export default class Droppable {
sorter.eventHandlers.legacyOnEnd = sorterOptions.legacyOnEnd;
sorter.containerContext.customTarget = sorterOptions.customTarget;
}
- let dropModel = this.getTempDropModel(content);
- const el = dropModel.view?.el;
- const sources = el ? [{ element: el, dragSource: dragSourceOrigin }] : [];
+ const shallowCmp = em.Components.getShallowWrapper();
+ const model = shallowCmp?.append(content, { temporary: true })[0];
+ const element = model?.getEl();
+ const sources = [{ element, dragSource: { model, ...dragSourceOrigin } }];
sorter.startSort(sources);
this.sorter = sorter;
this.draggedNode = sorter.sourceNodes?.[0];
@@ -206,25 +207,6 @@ export default class Droppable {
em.trigger('canvas:dragenter', dt, content);
}
- /**
- * Generates a temporary model of the content being dragged for use with the sorter.
- * @returns The temporary model representing the dragged content.
- */
- private getTempDropModel(content?: any) {
- const comps = this.em.Components.getComponents();
- const opts = {
- avoidChildren: 1,
- avoidStore: 1,
- avoidUpdateStyle: 1,
- };
- const tempModel = comps.add(content, { ...opts, temporary: true });
- let dropModel = comps.remove(tempModel, { ...opts, temporary: true } as any);
- // @ts-ignore
- dropModel = dropModel instanceof Array ? dropModel[0] : dropModel;
- dropModel.view?.$el.data('model', dropModel);
- return dropModel;
- }
-
handleDragEnd(model: any, dt: any) {
const { em } = this;
this.over = false;
diff --git a/packages/core/src/utils/sorter/Sorter.ts b/packages/core/src/utils/sorter/Sorter.ts
index c1505db17..78897968f 100644
--- a/packages/core/src/utils/sorter/Sorter.ts
+++ b/packages/core/src/utils/sorter/Sorter.ts
@@ -17,6 +17,11 @@ import {
import Dimension from './Dimension';
import { SorterOptions } from './types';
+interface SorterSource {
+ element?: HTMLElement;
+ dragSource?: DragSource;
+}
+
export default class Sorter> {
em: EditorModel;
treeClass: new (model: T, dragSource?: DragSource) => NodeType;
@@ -70,7 +75,7 @@ export default class Sorter> {
* Picking components to move
* @param {HTMLElement[]} sources[]
* */
- startSort(sources: { element?: HTMLElement; dragSource?: DragSource }[]) {
+ startSort(sources: SorterSource[]) {
const { sourceNodes, sourcesWithModel } = this.getSourceNodes(sources);
this.sourceNodes = sourceNodes;
this.dropLocationDeterminer.startSort(sourceNodes);
@@ -93,11 +98,7 @@ export default class Sorter> {
this.em.trigger('sorter:drag:start', sources[0], sourcesWithModel[0]);
}
- validTarget(
- targetEl: HTMLElement | undefined,
- sources: { element?: HTMLElement; dragSource?: DragSource }[],
- index: number,
- ): boolean {
+ validTarget(targetEl: HTMLElement | undefined, sources: SorterSource[], index: number): boolean {
if (!targetEl) return false;
const targetModel = $(targetEl).data('model');
if (!targetModel) return false;
@@ -108,12 +109,12 @@ export default class Sorter> {
return canMove;
}
- private getSourceNodes(sources: { element?: HTMLElement; dragSource?: DragSource }[]) {
+ private getSourceNodes(sources: SorterSource[]) {
const validSources = sources.filter((source) => !!source.dragSource || this.findValidSourceElement(source.element));
const sourcesWithModel: { model: T; content?: any }[] = validSources.map((source) => {
return {
- model: $(source.element)?.data('model'),
+ model: source.dragSource?.model || $(source.element)?.data('model'),
content: source.dragSource,
};
});
@@ -188,7 +189,7 @@ export default class Sorter> {
/**
* Finds the closest valid source element within the container context.
-
+
* @param sourceElement - The initial source element to check.
* @returns The closest valid source element, or null if none is found.
*/