Comprehensive drag and drop functionality for the low-code editor, providing type-safe interfaces for dragging components, nodes, and custom objects.
Core types for objects that can be dragged in the editor.
/**
* Union type for all draggable objects
*/
type IPublicTypeDragObject =
| IPublicTypeDragNodeObject
| IPublicTypeDragNodeDataObject
| IPublicTypeDragAnyObject;
/**
* Drag object containing actual node instances
*/
interface IPublicTypeDragNodeObject {
/** Type indicator for node objects */
type: IPublicEnumDragObjectType.Node;
/** Array of node instances being dragged */
nodes: IPublicModelNode[];
}
/**
* Drag object containing node schema data
*/
interface IPublicTypeDragNodeDataObject {
/** Type indicator for node data objects */
type: IPublicEnumDragObjectType.NodeData;
/** Node schema data being dragged */
data: IPublicTypeNodeSchema | IPublicTypeNodeSchema[];
/** Optional thumbnail image */
thumbnail?: string;
/** Optional description text */
description?: string;
/** Additional custom properties */
[extra: string]: any;
}
/**
* Generic drag object for custom drag types
*/
interface IPublicTypeDragAnyObject {
/** Custom type identifier */
type: string;
/** Additional custom properties */
[key: string]: any;
}Usage Examples:
import {
IPublicTypeDragObject,
IPublicTypeDragNodeDataObject,
IPublicEnumDragObjectType
} from "@alilc/lowcode-types";
// Create drag object for component from material
const componentDragObject: IPublicTypeDragNodeDataObject = {
type: IPublicEnumDragObjectType.NodeData,
data: {
componentName: "Button",
props: {
type: "primary",
children: "Click me"
}
},
thumbnail: "/assets/button-thumbnail.png",
description: "Primary button component"
};
// Create drag object for existing nodes
const nodeDragObject: IPublicTypeDragNodeObject = {
type: IPublicEnumDragObjectType.Node,
nodes: [selectedNode1, selectedNode2]
};
// Create custom drag object
const customDragObject: IPublicTypeDragAnyObject = {
type: "custom-widget",
widgetId: "widget-123",
config: { color: "blue" }
};The Dragon model provides the core drag and drop engine functionality.
/**
* Dragon model interface for drag and drop operations
*/
interface IPublicModelDragon {
/** Whether currently dragging */
readonly dragging: boolean;
/** Listen for drag start events */
onDragstart(func: (e: IPublicModelLocateEvent) => any): IPublicTypeDisposable;
/** Listen for drag events */
onDrag(func: (e: IPublicModelLocateEvent) => any): IPublicTypeDisposable;
/** Listen for drag end events */
onDragend(func: (o: { dragObject: IPublicModelDragObject; copy?: boolean }) => any): IPublicTypeDisposable;
/** Set drag monitoring shell and boost function */
from(shell: Element, boost: (e: MouseEvent) => IPublicTypeDragNodeDataObject | null): any;
/** Boost drag object for dragging */
boost(dragObject: IPublicTypeDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: IPublicModelNode): void;
/** Add sensor area */
addSensor(sensor: IPublicModelSensor): void;
/** Remove sensor area */
removeSensor(sensor: IPublicModelSensor): void;
}Usage Examples:
import { IPublicModelDragon } from "@alilc/lowcode-types";
// Setup drag and drop system
function setupDragDrop(dragon: IPublicModelDragon) {
// Listen for drag start
dragon.onDragstart((e) => {
console.log("Drag started at:", e.clientX, e.clientY);
// Prepare drag state
showDragPreview();
});
// Listen for drag events
dragon.onDrag((e) => {
// Update drag preview position
updateDragPreview(e.clientX, e.clientY);
});
// Listen for drag end
dragon.onDragend(({ dragObject, copy }) => {
console.log("Drag ended:", dragObject.type);
if (copy) {
console.log("Copy operation performed");
}
hideDragPreview();
});
// Setup drag source
const materialPanel = document.getElementById('material-panel');
if (materialPanel) {
dragon.from(materialPanel, (e: MouseEvent) => {
const target = e.target as Element;
const componentName = target.getAttribute('data-component');
if (componentName) {
return {
type: IPublicEnumDragObjectType.NodeData,
data: {
componentName,
props: getDefaultProps(componentName)
}
};
}
return null;
});
}
}Sensors detect and handle drop operations in specific areas.
/**
* Sensor interface for handling drop operations
*/
interface IPublicModelSensor {
/** Sensor active state */
active: boolean;
/** Enter sensor area */
enter(dragObject: IPublicModelDragObject): boolean;
/** Leave sensor area */
leave(dragObject: IPublicModelDragObject): void;
/** Check if can drop */
canDrop(dragObject: IPublicModelDragObject): boolean;
/** Handle drop operation */
drop(dragObject: IPublicModelDragObject, dropLocation: IPublicModelDropLocation): void;
}
/**
* Drop location interface
*/
interface IPublicModelDropLocation {
/** Target node for drop */
target: IPublicModelNode;
/** Drop index within target */
index: number;
/** Drop edge position */
edge: 'before' | 'after' | 'inside';
}Usage Examples:
import { IPublicModelSensor, IPublicModelDragObject } from "@alilc/lowcode-types";
// Create custom sensor for canvas area
class CanvasSensor implements IPublicModelSensor {
active = true;
enter(dragObject: IPublicModelDragObject): boolean {
// Check if drag object can be dropped on canvas
if (dragObject.type === IPublicEnumDragObjectType.NodeData) {
return true;
}
return false;
}
leave(dragObject: IPublicModelDragObject): void {
// Clean up drop indicators
this.clearDropIndicators();
}
canDrop(dragObject: IPublicModelDragObject): boolean {
// Validate drop operation
return this.validateDrop(dragObject);
}
drop(dragObject: IPublicModelDragObject, dropLocation: IPublicModelDropLocation): void {
// Handle the drop operation
if (dragObject.type === IPublicEnumDragObjectType.NodeData) {
const nodeData = (dragObject as IPublicTypeDragNodeDataObject).data;
this.insertNode(nodeData, dropLocation);
}
}
private clearDropIndicators(): void {
// Implementation
}
private validateDrop(dragObject: IPublicModelDragObject): boolean {
// Implementation
return true;
}
private insertNode(nodeData: any, location: IPublicModelDropLocation): void {
// Implementation
}
}
// Register sensor with dragon
function registerCanvasSensor(dragon: IPublicModelDragon) {
const sensor = new CanvasSensor();
dragon.addSensor(sensor);
return () => {
dragon.removeSensor(sensor);
};
}Location events provide detailed information about drag operations.
/**
* Locate event interface for drag operations
*/
interface IPublicModelLocateEvent {
/** Event type */
type: string;
/** Target element */
target: Element;
/** Client coordinates */
clientX: number;
clientY: number;
/** Global coordinates */
globalX: number;
globalY: number;
/** Original DOM event */
originalEvent: Event;
/** Prevent default behavior */
preventDefault(): void;
/** Stop event propagation */
stopPropagation(): void;
}import {
IPublicTypeDragObject,
IPublicTypeDragNodeObject,
IPublicTypeDragNodeDataObject,
IPublicTypeDragAnyObject,
IPublicModelDragon,
IPublicModelSensor,
IPublicModelDropLocation,
IPublicModelLocateEvent,
IPublicEnumDragObjectType
} from "@alilc/lowcode-types";import {
IPublicModelDragon,
IPublicEnumDragObjectType,
IPublicTypeDragNodeDataObject
} from "@alilc/lowcode-types";
// Complete drag and drop setup
class DragDropManager {
private dragon: IPublicModelDragon;
constructor(dragon: IPublicModelDragon) {
this.dragon = dragon;
this.setupDragSources();
this.setupDropTargets();
}
private setupDragSources(): void {
// Setup material panel as drag source
const materialPanel = document.getElementById('materials');
if (materialPanel) {
this.dragon.from(materialPanel, (e: MouseEvent) => {
const component = this.getComponentFromEvent(e);
if (component) {
return {
type: IPublicEnumDragObjectType.NodeData,
data: {
componentName: component.name,
props: component.defaultProps
},
thumbnail: component.thumbnail,
description: component.description
} as IPublicTypeDragNodeDataObject;
}
return null;
});
}
}
private setupDropTargets(): void {
// Add canvas sensor
const canvasSensor = new CanvasSensor();
this.dragon.addSensor(canvasSensor);
// Setup event listeners
this.dragon.onDragstart(() => {
document.body.classList.add('dragging');
});
this.dragon.onDragend(() => {
document.body.classList.remove('dragging');
});
}
private getComponentFromEvent(e: MouseEvent): any {
// Implementation to extract component info from mouse event
return null;
}
}This drag and drop system provides comprehensive support for all dragging scenarios in the low-code editor.