diff --git a/src/canvas/config/config.ts b/src/canvas/config/config.ts
index baf78e90f..770d166aa 100644
--- a/src/canvas/config/config.ts
+++ b/src/canvas/config/config.ts
@@ -61,6 +61,15 @@ export interface CanvasConfig {
* This option allows to customize, by a selector, which element should not be considered textable.
*/
notTextable?: string[];
+
+ /**
+ * By default, the editor allows to drop external elements by relying on the native HTML5
+ * drag & drop API (eg. like a D&D of an image file from your desktop).
+ * If you want to customize how external elements are interpreted by the editor, you can rely
+ * on `canvas:dragdata` event, eg. https://github.com/GrapesJS/grapesjs/discussions/3849
+ * @default true
+ */
+ allowExternalDrop?: boolean;
}
const config: CanvasConfig = {
@@ -78,6 +87,7 @@ const config: CanvasConfig = {
* ::-webkit-scrollbar { width: 10px }
`,
notTextable: ['button', 'a', 'input[type=checkbox]', 'input[type=radio]'],
+ allowExternalDrop: true,
};
export default config;
diff --git a/src/utils/Droppable.ts b/src/utils/Droppable.ts
index d3654a13e..07824d28b 100644
--- a/src/utils/Droppable.ts
+++ b/src/utils/Droppable.ts
@@ -83,10 +83,13 @@ export default class Droppable {
this.over ? this.endDrop(cancel) : this.__customTglEff(false);
}
+ /**
+ * This function is expected to be always executed at the end of d&d.
+ */
endDrop(cancel?: boolean, ev?: Event) {
const { em, dragStop } = this;
this.counter = 0;
- dragStop && dragStop(cancel);
+ dragStop && dragStop(cancel || !this.over);
this.__customTglEff(false);
em.trigger('canvas:dragend', ev);
}
@@ -103,6 +106,12 @@ export default class Droppable {
handleDragEnter(ev: DragEvent | Event) {
const { em, canvas } = this;
const dt = (ev as DragEvent).dataTransfer;
+ const dragContentOrigin = em.get('dragContent');
+
+ if (!dragContentOrigin && !canvas.getConfig().allowExternalDrop) {
+ return;
+ }
+
this.updateCounter(1, ev);
if (this.over) return;
this.over = true;
@@ -110,7 +119,7 @@ export default class Droppable {
// For security reason I can't read the drag data on dragenter, but
// as I need it for the Sorter context I will use `dragContent` or just
// any not empty element
- let content = em.get('dragContent') || '
';
+ let content = dragContentOrigin || '
';
let dragStop: DragStop;
let dragContent;
em.stopDefault();