Merge branch 'release/0.16.0' into 'release/1.0.56'

feat: 兼容磁贴布局功能 to #34464969

支持RGL功能

See merge request !1284323
This commit is contained in:
力皓 2021-06-10 21:08:13 +08:00
commit f813bd026a
5 changed files with 301 additions and 77 deletions

View File

@ -24,7 +24,7 @@ export class BemTools extends Component<{ host: BuiltinSimulatorHost }> {
}
return (
<div className="lc-bem-tools" style={{ transform: `translate(${-scrollX * scale}px,${-scrollY * scale}px)` }}>
<BorderDetecting key="hovering" host={host} />
{ !engineConfig.get('disableDetecting') && <BorderDetecting key="hovering" host={host} /> }
<BorderSelecting key="selecting" host={host} />
{ engineConfig.get('enableReactiveContainer') && <BorderContainer key="reactive-container-border" host={host} /> }
<InsertionView key="insertion" host={host} />
@ -38,4 +38,4 @@ export class BemTools extends Component<{ host: BuiltinSimulatorHost }> {
</div>
);
}
}
}

View File

@ -1,9 +1,23 @@
import { obx, autorun, computed, getPublicPath, hotkey, focusTracker, engineConfig } from '@ali/lowcode-editor-core';
import {
obx,
autorun,
computed,
getPublicPath,
hotkey,
focusTracker,
engineConfig,
} from '@ali/lowcode-editor-core';
import { EventEmitter } from 'events';
import { ISimulatorHost, Component, NodeInstance, ComponentInstance, DropContainer } from '../simulator';
import {
ISimulatorHost,
Component,
NodeInstance,
ComponentInstance,
DropContainer,
} from '../simulator';
import Viewport from './viewport';
import { createSimulator } from './create-simulator';
import { Node, ParentalNode, isNode, contains, isRootNode } from '../document';
import { Node, ParentalNode, contains, isRootNode } from '../document';
import ResourceConsumer from './resource-consumer';
import {
AssetLevel,
@ -23,7 +37,6 @@ import {
LocateEvent,
isDragAnyObject,
isDragNodeObject,
LocationData,
isLocationData,
LocationChildrenDetail,
LocationDetailType,
@ -36,7 +49,12 @@ import {
} from '../designer';
import { parseMetadata } from './utils/parse-metadata';
import { getClosestClickableNode } from './utils/clickable';
import { ComponentMetadata, ComponentSchema, TransformStage, ActivityData } from '@ali/lowcode-types';
import {
ComponentMetadata,
ComponentSchema,
TransformStage,
ActivityData,
} from '@ali/lowcode-types';
import { BuiltinSimulatorRenderer } from './renderer';
import clipboard from '../designer/clipboard';
import { LiveEditing } from './live-editing/live-editing';
@ -80,7 +98,10 @@ const defaultSimulatorUrl = (() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, prefix = '', dev] = /^(.+?)(\/js)?\/?$/.exec(publicPath) || [];
if (dev) {
urls = [`${prefix}/css/react-simulator-renderer.css`, `${prefix}/js/react-simulator-renderer.js`];
urls = [
`${prefix}/css/react-simulator-renderer.css`,
`${prefix}/js/react-simulator-renderer.js`,
];
} else if (process.env.NODE_ENV === 'production') {
urls = [`${prefix}/react-simulator-renderer.css`, `${prefix}/react-simulator-renderer.js`];
} else {
@ -106,12 +127,16 @@ const defaultRaxSimulatorUrl = (() => {
const defaultEnvironment = [
// https://g.alicdn.com/mylib/??react/16.11.0/umd/react.production.min.js,react-dom/16.8.6/umd/react-dom.production.min.js,prop-types/15.7.2/prop-types.min.js
assetItem(AssetType.JSText, 'window.React=parent.React;window.ReactDOM=parent.ReactDOM;window.__is_simulator_env__=true;', undefined, 'react'),
assetItem(
AssetType.JSText,
'window.React=parent.React;window.ReactDOM=parent.ReactDOM;window.__is_simulator_env__=true;',
undefined,
'react',
),
assetItem(
AssetType.JSText,
'window.PropTypes=parent.PropTypes;React.PropTypes=parent.PropTypes; window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;',
),
];
const defaultRaxEnvironment = [
@ -217,7 +242,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
get(key: string): any {
if (key === 'device') {
return this.designer?.editor?.get('deviceMapper')?.transform?.(this._props.device) || this._props.device;
return (
this.designer?.editor?.get('deviceMapper')?.transform?.(this._props.device) ||
this._props.device
);
}
return this._props[key];
}
@ -225,7 +253,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/**
* Renderer
*/
connect(renderer: BuiltinSimulatorRenderer, fn: (context: { dispose: () => void; firstRun: boolean }) => void) {
connect(
renderer: BuiltinSimulatorRenderer,
fn: (context: { dispose: () => void; firstRun: boolean }) => void,
) {
this._renderer = renderer;
return autorun(fn as any, true);
}
@ -294,7 +325,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
* libraryString umd包直接导出的name
*/
buildLibrary(library) {
library = library || this.get('library') as LibraryItem[];
library = library || (this.get('library') as LibraryItem[]);
const libraryAsset: AssetList = [];
const libraryExportList = [];
@ -305,7 +336,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
this.asyncLibraryMap[item.package] = item;
}
if (item.exportName && item.library) {
libraryExportList.push(`Object.defineProperty(window,'${item.exportName}',{get:()=>window.${item.library}});`);
libraryExportList.push(
`Object.defineProperty(window,'${item.exportName}',{get:()=>window.${item.library}});`,
);
}
if (item.urls) {
libraryAsset.push(item.urls);
@ -337,7 +370,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const vendors = [
// required & use once
assetBundle(
this.get('environment') || (this.renderEnv === 'rax' ? defaultRaxEnvironment : defaultEnvironment),
this.get('environment') ||
(this.renderEnv === 'rax' ? defaultRaxEnvironment : defaultEnvironment),
AssetLevel.Environment,
),
// required & use once
@ -349,7 +383,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
assetBundle(this.theme, AssetLevel.Theme),
// required & use once
assetBundle(
this.get('simulatorUrl') || (this.renderEnv === 'rax' ? defaultRaxSimulatorUrl : defaultSimulatorUrl),
this.get('simulatorUrl') ||
(this.renderEnv === 'rax' ? defaultRaxSimulatorUrl : defaultSimulatorUrl),
AssetLevel.Runtime,
),
];
@ -357,7 +392,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// wait 准备 iframe 内容、依赖库注入
const renderer = await createSimulator(this, iframe, vendors);
// TODO: !!! thinkof reload onloa
// wait 业务组件被第一次消费,否则会渲染出错
@ -366,7 +400,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// wait 运行时上下文
await this.injectionConsumer.waitFirstConsume();
if (Object.keys(this.asyncLibraryMap).length > 0) {
// 加载异步Library
await renderer.loadAsyncLibrary(this.asyncLibraryMap);
@ -384,7 +417,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
focusTracker.mount(this._contentWindow);
clipboard.injectCopyPaster(this._contentDocument);
// TODO: dispose the bindings
}
@ -437,15 +469,19 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
if (!node.isInited) return;
// 静音状态不触发事件,通常是非局部更新操作
if (this.mutedActivityEvent) return;
this.postEvent('activity', {
type: 'modified',
payload: {
schema: node.export(TransformStage.Render, { bypassChildren: true }),
oldValue,
newValue,
prop,
this.postEvent(
'activity',
{
type: 'modified',
payload: {
schema: node.export(TransformStage.Render, { bypassChildren: true }),
oldValue,
newValue,
prop,
},
},
}, { doc: this.currentDocument });
{ doc: this.currentDocument },
);
});
// editor.on('node.add', ({ node }) => {
// console.log('add node', node);
@ -501,20 +537,82 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
} else if (!downEvent.metaKey) {
return;
}
// stop response document focus event
downEvent.stopPropagation();
downEvent.preventDefault();
// FIXME: dirty fix remove label-for fro liveEditing
(downEvent.target as HTMLElement).removeAttribute('for');
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element);
const node = getClosestClickableNode(nodeInst?.node || documentModel?.rootNode, downEvent);
// 如果找不到可点击的节点, 直接返回
if (!node) {
return;
}
const isRGLNode = node?.getParent()?.isRGLContainer;
const rglNode = node?.getParent();
if (isRGLNode) {
// 如果拖拽的是磁铁块的右下角handle则直接跳过
if (downEvent.target.classList.contains('react-resizable-handle')) return;
isMulti = false;
designer.dragon.emitter.emit('rgl.switch', {
action: 'start',
rglNode,
});
const judgeEnterOtherRGL = (e: MouseEvent) => {
const _nodeInst = this.getNodeInstanceFromElement(e.target as Element);
const { isRGL: _isRGL, rglNode: _rglNode } = this.getRGLObject(
_nodeInst as NodeInstance,
);
const status = !!(
_isRGL &&
_rglNode?.id !== rglNode?.id &&
_rglNode?.getParent() !== node &&
nodeInst?.node !== _nodeInst?.node
);
return { status, rglNode: _rglNode };
};
const move = (e: MouseEvent) => {
if (!isShaken(downEvent, e)) {
if (nodeInst.instance && nodeInst.instance.style) {
nodeInst.instance.style.pointerEvents = 'none';
}
}
const { status, rglNode: _rglNode } = judgeEnterOtherRGL(e);
if (status) {
designer.dragon.emitter.emit('rgl.add.placeholder', {
rglNode: _rglNode,
node,
event: e,
fromRglNode: rglNode,
});
} else {
designer.dragon.emitter.emit('rgl.remove.placeholder');
}
};
const over = (e: MouseEvent) => {
const { status, rglNode: _rglNode } = judgeEnterOtherRGL(e);
if (status) {
designer.dragon.emitter.emit('rgl.drop', {
rglNode: _rglNode,
node,
fromRglNode: rglNode,
});
}
designer.dragon.emitter.emit('rgl.remove.placeholder');
if (nodeInst.instance && nodeInst.instance.style) {
nodeInst.instance.style.pointerEvents = '';
}
designer.dragon.emitter.emit('rgl.switch', {
action: 'end',
rglNode,
});
doc.removeEventListener('mouseup', over, true);
doc.removeEventListener('mousemove', move, true);
};
doc.addEventListener('mouseup', over, true);
doc.addEventListener('mousemove', move, true);
} else {
// stop response document focus event
downEvent.stopPropagation();
downEvent.preventDefault();
}
// if (!node?.isValidComponent()) {
// // 对于未注册组件直接返回
// return;
@ -522,8 +620,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const isLeftButton = downEvent.which === 1 || downEvent.button === 0;
const checkSelect = (e: MouseEvent) => {
doc.removeEventListener('mouseup', checkSelect, true);
// 鼠标是否移动
if (!isShaken(downEvent, e)) {
// 鼠标是否移动 ? - 鼠标抖动应该也需要支持选中事件偶尔点击不能选中磁帖块移除shaken检测
if (!isShaken(downEvent, e) || isRGLNode) {
let { id } = node;
designer.activeTracker.track({ node, instance: nodeInst?.instance });
if (isMulti && !isRootNode(node) && selection.has(id)) {
@ -531,10 +629,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
} else {
// TODO: 避免选中 Page 组件,默认选中第一个子节点;新增规则 或 判断 Live 模式
if (node.isPage() && node.getChildren()?.notEmpty() && this.designMode === 'live') {
const firstChildId = node
.getChildren()
?.get(0)
?.getId();
const firstChildId = node.getChildren()?.get(0)?.getId();
if (firstChildId) id = firstChildId;
}
selection.select(id);
@ -552,7 +647,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}
}
};
if (isLeftButton && !isRootNode(node)) {
let nodes: Node[] = [node];
let ignoreUpSelected = false;
@ -571,13 +665,16 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
} else {
// will clear current selection & select dragment in dragstart
}
designer.dragon.boost(
{
type: DragObjectType.Node,
nodes,
},
downEvent,
);
if (!isRGLNode) {
designer.dragon.boost(
{
type: DragObjectType.Node,
nodes,
},
downEvent,
true,
);
}
if (ignoreUpSelected) {
// multi select mode has add selected, should return
return;
@ -636,6 +733,20 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
private disableHovering?: () => void;
private disableDetecting?: () => void;
/**
* node实例的磁贴相关信息
*/
getRGLObject(nodeInst: NodeInstance) {
const isContainerNode = nodeInst?.node.isContainer();
const isEmptyNode = nodeInst?.node?.isEmpty();
const isRGLContainerNode = nodeInst?.node?.isRGLContainer;
const isRGLNode = nodeInst?.node?.getParent()?.isRGLContainer;
const isRGL = isRGLContainerNode || (isRGLNode && (!isContainerNode || !isEmptyNode));
let rglNode = isRGLContainerNode ? nodeInst?.node : isRGL ? nodeInst?.node?.getParent() : {};
return { isContainerNode, isEmptyNode, isRGLContainerNode, isRGLNode, isRGL, rglNode };
}
/**
*
*/
@ -698,7 +809,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return;
}
const rootElement = this.findDOMNodes(nodeInst.instance, node.componentMeta.rootSelector)?.find(
const rootElement = this.findDOMNodes(
nodeInst.instance,
node.componentMeta.rootSelector,
)?.find(
(item) =>
// 可能是 [null];
item && item.contains(targetElement),
@ -851,7 +965,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/**
* @see ISimulator
*/
getClosestNodeInstance(from: ComponentInstance, specId?: string): NodeInstance<ComponentInstance> | null {
getClosestNodeInstance(
from: ComponentInstance,
specId?: string,
): NodeInstance<ComponentInstance> | null {
return this.renderer?.getClosestNodeInstance(from, specId) || null;
}
@ -978,7 +1095,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
* @see ISimulator
*/
/* istanbul ignore next */
scrollToNode(node: Node, detail?: any/* , tryTimes = 0 */) {
scrollToNode(node: Node, detail?: any /* , tryTimes = 0 */) {
this.tryScrollAgain = null;
if (this.sensing) {
// actived sensor
@ -1100,7 +1217,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
*/
isEnter(e: LocateEvent): boolean {
const rect = this.viewport.bounds;
return e.globalY >= rect.top && e.globalY <= rect.bottom && e.globalX >= rect.left && e.globalX <= rect.right;
return (
e.globalY >= rect.top &&
e.globalY <= rect.bottom &&
e.globalX >= rect.left &&
e.globalX <= rect.right
);
}
private sensing = false;
@ -1157,7 +1279,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const { container, instance: containerInstance } = dropContainer;
const edge = this.computeComponentInstanceRect(containerInstance, container.componentMeta.rootSelector);
const edge = this.computeComponentInstanceRect(
containerInstance,
container.componentMeta.rootSelector,
);
if (!edge) {
return null;
@ -1209,10 +1334,15 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const instances = this.getComponentInstances(node);
const inst = instances
? instances.length > 1
? instances.find((_inst) => this.getClosestNodeInstance(_inst, container.id)?.instance === containerInstance)
? instances.find(
(_inst) =>
this.getClosestNodeInstance(_inst, container.id)?.instance === containerInstance,
)
: instances[0]
: null;
const rect = inst ? this.computeComponentInstanceRect(inst, node.componentMeta.rootSelector) : null;
const rect = inst
? this.computeComponentInstanceRect(inst, node.componentMeta.rootSelector)
: null;
if (!rect) {
continue;
@ -1344,7 +1474,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
if (nodeInstance.node === container) {
instance = nodeInstance.instance;
} else {
instance = this.getClosestNodeInstance(nodeInstance.instance as any, container.id)?.instance;
instance = this.getClosestNodeInstance(
nodeInstance.instance as any,
container.id,
)?.instance;
}
} else {
instance = this.getComponentInstances(container)?.[0];
@ -1381,7 +1514,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
} else {
return null;
}
}/* else if (res === DRILL_DOWN) {
} /* else if (res === DRILL_DOWN) {
if (!upward) {
container = container.parent;
instance = this.getClosestNodeInstance(dropContainer.instance, container.id)?.instance;
@ -1466,7 +1599,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/**
*
*/
getNearByContainer({ container, instance }: DropContainer, drillDownExcludes: Set<Node>, e: LocateEvent) {
getNearByContainer(
{ container, instance }: DropContainer,
drillDownExcludes: Set<Node>,
e: LocateEvent,
) {
const { children } = container;
const document = this.project.currentDocument!;
if (!children || children.isEmpty()) {

View File

@ -13,7 +13,14 @@ import {
} from '@ali/lowcode-types';
import { megreAssets, AssetsJson } from '@ali/lowcode-utils';
import { Project } from '../project';
import { Node, DocumentModel, insertChildren, isRootNode, ParentalNode, TransformStage } from '../document';
import {
Node,
DocumentModel,
insertChildren,
isRootNode,
ParentalNode,
TransformStage,
} from '../document';
import { ComponentMeta } from '../component-meta';
import { INodeSelector, Component } from '../simulator';
import { Scroller, IScrollable } from './scroller';
@ -125,7 +132,7 @@ export class Designer {
} else if (isDragNodeDataObject(dragObject)) {
// process nodeData
const nodeData = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
const isNotNodeSchema = nodeData.find(item => !isNodeSchema(item));
const isNotNodeSchema = nodeData.find((item) => !isNodeSchema(item));
if (isNotNodeSchema) {
return;
}
@ -213,7 +220,11 @@ export class Designer {
}
const { currentSelection } = this;
// TODO: 避免选中 Page 组件,默认选中第一个子节点;新增规则 或 判断 Live 模式
if (currentSelection && currentSelection.selected.length === 0 && this.simulatorProps?.designMode === 'live') {
if (
currentSelection &&
currentSelection.selected.length === 0 &&
this.simulatorProps?.designMode === 'live'
) {
const rootNodeChildrens = this.currentDocument.getRoot().getChildren().children;
if (rootNodeChildrens.length > 0) {
currentSelection.select(rootNodeChildrens[0].id);
@ -301,12 +312,18 @@ export class Designer {
/**
*
*/
getSuitableInsertion(insertNode?: Node | NodeSchema | NodeSchema[]): { target: ParentalNode; index?: number } | null {
getSuitableInsertion(
insertNode?: Node | NodeSchema | NodeSchema[],
): { target: ParentalNode; index?: number } | null {
const activedDoc = this.project.currentDocument;
if (!activedDoc) {
return null;
}
if (Array.isArray(insertNode) && isNodeSchema(insertNode[0]) && this.getComponentMeta(insertNode[0].componentName).isModal) {
if (
Array.isArray(insertNode) &&
isNodeSchema(insertNode[0]) &&
this.getComponentMeta(insertNode[0].componentName).isModal
) {
return {
target: activedDoc.rootNode as ParentalNode,
};
@ -355,7 +372,10 @@ export class Designer {
if (props.suspensed !== this.props.suspensed && props.suspensed != null) {
this.suspensed = props.suspensed;
}
if (props.componentMetadatas !== this.props.componentMetadatas && props.componentMetadatas != null) {
if (
props.componentMetadatas !== this.props.componentMetadatas &&
props.componentMetadatas != null
) {
this.buildComponentMetasMap(props.componentMetadatas);
}
} else {
@ -477,7 +497,10 @@ export class Designer {
return this.props?.globalComponentActions || null;
}
getComponentMeta(componentName: string, generateMetadata?: () => ComponentMetadata | null): ComponentMeta {
getComponentMeta(
componentName: string,
generateMetadata?: () => ComponentMetadata | null,
): ComponentMeta {
if (this._componentMetasMap.has(componentName)) {
return this._componentMetasMap.get(componentName)!;
}
@ -558,4 +581,8 @@ export class Designer {
}
export type PropsReducerContext = { stage: TransformStage };
export type PropsReducer = (props: CompositeObject, node: Node, ctx?: PropsReducerContext) => CompositeObject;
export type PropsReducer = (
props: CompositeObject,
node: Node,
ctx?: PropsReducerContext,
) => CompositeObject;

View File

@ -4,7 +4,7 @@ import { NodeSchema } from '@ali/lowcode-types';
import { setNativeSelection, cursor } from '@ali/lowcode-utils';
import { DropLocation } from './location';
import { Node, DocumentModel } from '../document';
import { ISimulatorHost, isSimulatorHost } from '../simulator';
import { ISimulatorHost, isSimulatorHost, NodeInstance, ComponentInstance } from '../simulator';
import { Designer } from './designer';
export interface LocateEvent {
@ -72,6 +72,14 @@ export interface ISensor {
*
*/
deactiveSensor(): void;
/**
*
*/
getNodeInstanceFromElement(e: Element | null): NodeInstance<ComponentInstance> | null;
/**
* RGL相关信息
*/
getRGLObject(nodeInst: NodeInstance): any;
}
export type DragObject = DragNodeObject | DragNodeDataObject | DragAnyObject;
@ -126,7 +134,9 @@ export function isShaken(e1: MouseEvent | DragEvent, e2: MouseEvent | DragEvent)
if (e1.target !== e2.target) {
return true;
}
return Math.pow(e1.clientY - e2.clientY, 2) + Math.pow(e1.clientX - e2.clientX, 2) > SHAKE_DISTANCE;
return (
Math.pow(e1.clientY - e2.clientY, 2) + Math.pow(e1.clientX - e2.clientX, 2) > SHAKE_DISTANCE
);
}
function isInvalidPoint(e: any, last: any): boolean {
@ -199,6 +209,8 @@ export class Dragon {
@obx.ref private _dragging = false;
@obx.ref private _canDrop = false;
get dragging(): boolean {
return this._dragging;
}
@ -239,17 +251,26 @@ export class Dragon {
* @param dragObject
* @param boostEvent
*/
boost(dragObject: DragObject, boostEvent: MouseEvent | DragEvent) {
boost(dragObject: DragObject, boostEvent: MouseEvent | DragEvent, isFromRGLNode?: boolean) {
const { designer } = this;
const masterSensors = this.getMasterSensors();
const handleEvents = makeEventsHandler(boostEvent, masterSensors);
const newBie = !isDragNodeObject(dragObject);
const forceCopyState = isDragNodeObject(dragObject) && dragObject.nodes.some((node) => node.isSlot());
const forceCopyState =
isDragNodeObject(dragObject) && dragObject.nodes.some((node) => node.isSlot());
const isBoostFromDragAPI = isDragEvent(boostEvent);
let lastSensor: ISensor | undefined;
this._dragging = false;
const getRGLObject = (e: MouseEvent | DragEvent) => {
const locateEvent = createLocateEvent(e);
const sensor = chooseSensor(locateEvent);
if (!sensor || !sensor.getNodeInstanceFromElement) return {};
const nodeInst = sensor.getNodeInstanceFromElement(e.target as Element);
return sensor.getRGLObject(nodeInst as NodeInstance);
};
const checkesc = (e: KeyboardEvent) => {
if (e.keyCode === 27) {
designer.clearLocation();
@ -304,13 +325,31 @@ export class Dragon {
const locateEvent = createLocateEvent(e);
const sensor = chooseSensor(locateEvent);
if (sensor) {
sensor.fixEvent(locateEvent);
sensor.locate(locateEvent);
} else {
this._canDrop = !!sensor?.locate(locateEvent);
const { isRGL, rglNode } = getRGLObject(e);
if (isRGL) {
// 禁止原生响应
if (!isFromRGLNode && this._canDrop) {
this.emitter.emit('rgl.add.placeholder', {
rglNode,
node: locateEvent.dragObject.nodes[0],
event: e,
});
}
designer.clearLocation();
this.clearState();
this.emitter.emit('drag', locateEvent);
} else {
if (!isFromRGLNode && this._canDrop) {
this.emitter.emit('rgl.remove.placeholder');
}
if (sensor) {
sensor.fixEvent(locateEvent);
} else {
designer.clearLocation();
}
this.emitter.emit('drag', locateEvent);
}
this.emitter.emit('drag', locateEvent);
};
const dragstart = () => {
@ -363,6 +402,20 @@ export class Dragon {
// end-tail drag process
const over = (e?: any) => {
// 发送drop事件
if (e) {
const { isRGL, rglNode } = getRGLObject(e);
if (isRGL && !isFromRGLNode && this._canDrop) {
const tarNode = dragObject.nodes[0];
this.emitter.emit('rgl.drop', {
rglNode,
node: tarNode,
});
const { selection } = designer.project.currentDocument;
selection.select(tarNode.id);
}
}
/* istanbul ignore next */
if (e && isDragEvent(e)) {
e.preventDefault();
@ -461,7 +514,10 @@ export class Dragon {
const chooseSensor = (e: LocateEvent) => {
// this.sensors will change on dragstart
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
let sensor = e.sensor && e.sensor.isEnter(e) ? e.sensor : sensors.find((s) => s.sensorAvailable && s.isEnter(e));
let sensor =
e.sensor && e.sensor.isEnter(e)
? e.sensor
: sensors.find((s) => s.sensorAvailable && s.isEnter(e));
if (!sensor) {
// TODO: enter some area like componentspanel cancel
if (lastSensor) {
@ -547,7 +603,7 @@ export class Dragon {
}
private getSimulators() {
return new Set(this.designer.project.documents.map(doc => doc.simulator));
return new Set(this.designer.project.documents.map((doc) => doc.simulator));
}
// #region ======== drag and drop helpers ============

View File

@ -195,6 +195,10 @@ interface EngineOptions {
* false
*/
disableAutoRender?: boolean;
/**
* 线false
*/
disableDetecting?: boolean;
/**
* Vision-polyfill settings
*/
@ -203,7 +207,7 @@ interface EngineOptions {
disableCompatibleReducer?: boolean;
// 是否开启在 render 阶段开启 filter reducer默认值false
enableFilterReducerInRenderStage?: boolean;
}
};
[key: string]: any;
}
export async function init(container?: Element, options?: EngineOptions) {