mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-15 14:00:35 +00:00
drag&drop logic 80%
This commit is contained in:
parent
f7c69af6c4
commit
59818ae3b6
@ -1,5 +1,5 @@
|
|||||||
import { obx, autorun, computed } from '@recore/obx';
|
import { obx, autorun, computed } from '@recore/obx';
|
||||||
import { ISimulator, ComponentInstance, Component } from '../../../designer/simulator';
|
import { ISimulator, ComponentInstance, Component, NodeInstance } from '../../../designer/simulator';
|
||||||
import Viewport from './viewport';
|
import Viewport from './viewport';
|
||||||
import { createSimulator } from './create-simulator';
|
import { createSimulator } from './create-simulator';
|
||||||
import { SimulatorRenderer } from '../renderer/renderer';
|
import { SimulatorRenderer } from '../renderer/renderer';
|
||||||
@ -12,6 +12,8 @@ import { LocationData } from '../../../designer/helper/location';
|
|||||||
import { NodeData } from '../../../designer/schema';
|
import { NodeData } from '../../../designer/schema';
|
||||||
import { ComponentDescriptionSpec } from '../../../designer/component-config';
|
import { ComponentDescriptionSpec } from '../../../designer/component-config';
|
||||||
import { ReactInstance } from 'react';
|
import { ReactInstance } from 'react';
|
||||||
|
import { setNativeSelection } from '../../../utils/navtive-selection';
|
||||||
|
import cursor from '../../../designer/helper/cursor';
|
||||||
|
|
||||||
export interface SimulatorProps {
|
export interface SimulatorProps {
|
||||||
// 从 documentModel 上获取
|
// 从 documentModel 上获取
|
||||||
@ -50,6 +52,7 @@ const defaultDepends = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export class SimulatorHost implements ISimulator<SimulatorProps> {
|
export class SimulatorHost implements ISimulator<SimulatorProps> {
|
||||||
|
readonly isSimulator = true;
|
||||||
constructor(readonly document: DocumentModel) {}
|
constructor(readonly document: DocumentModel) {}
|
||||||
|
|
||||||
readonly designer = this.document.designer;
|
readonly designer = this.document.designer;
|
||||||
@ -126,6 +129,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
get contentWindow() {
|
get contentWindow() {
|
||||||
return this._contentWindow;
|
return this._contentWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.ref private _contentDocument?: Document;
|
@obx.ref private _contentDocument?: Document;
|
||||||
get contentDocument() {
|
get contentDocument() {
|
||||||
return this._contentDocument;
|
return this._contentDocument;
|
||||||
@ -192,8 +196,8 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
// TODO: think of lock when edit a node
|
// TODO: think of lock when edit a node
|
||||||
// 事件路由
|
// 事件路由
|
||||||
doc.addEventListener('mousedown', (downEvent: MouseEvent) => {
|
doc.addEventListener('mousedown', (downEvent: MouseEvent) => {
|
||||||
const target = documentModel.getNodeFromElement(downEvent.target as Element);
|
const nodeInst = documentModel.getNodeInstanceFromElement(downEvent.target as Element);
|
||||||
if (!target) {
|
if (!nodeInst?.node) {
|
||||||
selection.clear();
|
selection.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -202,7 +206,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
const isLeftButton = downEvent.which === 1 || downEvent.button === 0;
|
const isLeftButton = downEvent.which === 1 || downEvent.button === 0;
|
||||||
|
|
||||||
if (isLeftButton) {
|
if (isLeftButton) {
|
||||||
let node: Node = target;
|
let node: Node = nodeInst.node;
|
||||||
let nodes: Node[] = [node];
|
let nodes: Node[] = [node];
|
||||||
let ignoreUpSelected = false;
|
let ignoreUpSelected = false;
|
||||||
if (isMulti) {
|
if (isMulti) {
|
||||||
@ -214,7 +218,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
}
|
}
|
||||||
// 获得顶层 nodes
|
// 获得顶层 nodes
|
||||||
nodes = selection.getTopNodes();
|
nodes = selection.getTopNodes();
|
||||||
} else if (selection.containsNode(target)) {
|
} else if (selection.containsNode(node)) {
|
||||||
nodes = selection.getTopNodes();
|
nodes = selection.getTopNodes();
|
||||||
} else {
|
} else {
|
||||||
// will clear current selection & select dragment in dragstart
|
// will clear current selection & select dragment in dragstart
|
||||||
@ -236,7 +240,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
doc.removeEventListener('mouseup', checkSelect, true);
|
doc.removeEventListener('mouseup', checkSelect, true);
|
||||||
if (!isShaken(downEvent, e)) {
|
if (!isShaken(downEvent, e)) {
|
||||||
// const node = hasConditionFlow(target) ? target.conditionFlow : target;
|
// const node = hasConditionFlow(target) ? target.conditionFlow : target;
|
||||||
const node = target;
|
const node = nodeInst.node!;
|
||||||
const id = node.id;
|
const id = node.id;
|
||||||
designer.activeTracker.track(node);
|
designer.activeTracker.track(node);
|
||||||
if (isMulti && selection.has(id)) {
|
if (isMulti && selection.has(id)) {
|
||||||
@ -252,6 +256,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
// cause edit
|
// cause edit
|
||||||
doc.addEventListener('dblclick', (e: MouseEvent) => {
|
doc.addEventListener('dblclick', (e: MouseEvent) => {
|
||||||
// TODO:
|
// TODO:
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,9 +271,9 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
if (!hovering.enable) {
|
if (!hovering.enable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const node = this.document.getNodeFromElement(e.target as Element);
|
const nodeInst = this.document.getNodeInstanceFromElement(e.target as Element);
|
||||||
// TODO: enhance only hover one instance
|
// TODO: enhance only hover one instance
|
||||||
hovering.hover(node);
|
hovering.hover(nodeInst?.node || null);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
const leave = () => hovering.leave(this.document);
|
const leave = () => hovering.leave(this.document);
|
||||||
@ -293,15 +298,6 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setDraggingState(state: boolean): void {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
isDraggingState(): boolean {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
setCopyState(state: boolean): void {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
setSuspense(suspended: boolean) {
|
setSuspense(suspended: boolean) {
|
||||||
if (suspended) {
|
if (suspended) {
|
||||||
if (this.disableHovering) {
|
if (this.disableHovering) {
|
||||||
@ -315,15 +311,10 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setDesignMode(mode: string): void {
|
setDesignMode(mode: string): void {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
isCopyState(): boolean {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
clearState(): void {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
describeComponent(component: Component): ComponentDescriptionSpec {
|
describeComponent(component: Component): ComponentDescriptionSpec {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
@ -345,8 +336,8 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
getClosestNodeId(elem: Element): string | null {
|
getClosestNodeInstance(elem: Element): NodeInstance | null {
|
||||||
return this.renderer?.getClosestNodeId(elem) || null;
|
return this.renderer?.getClosestNodeInstance(elem) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
computeComponentInstanceRect(instance: ReactInstance): DOMRect | null {
|
computeComponentInstanceRect(instance: ReactInstance): DOMRect | null {
|
||||||
@ -459,6 +450,20 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #region ========= drag and drop helpers =============
|
||||||
|
setNativeSelection(enableFlag: boolean) {
|
||||||
|
setNativeSelection(enableFlag);
|
||||||
|
}
|
||||||
|
setDraggingState(state: boolean) {
|
||||||
|
cursor.setDragging(state);
|
||||||
|
}
|
||||||
|
setCopyState(state: boolean) {
|
||||||
|
cursor.setCopy(state);
|
||||||
|
}
|
||||||
|
clearState() {
|
||||||
|
cursor.release();
|
||||||
|
}
|
||||||
|
|
||||||
fixEvent(e: LocateEvent): LocateEvent {
|
fixEvent(e: LocateEvent): LocateEvent {
|
||||||
/*
|
/*
|
||||||
if (e.fixed) {
|
if (e.fixed) {
|
||||||
@ -483,7 +488,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
this.scroller.cancel();
|
this.scroller.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region drag locate logic
|
// ========= drag location logic start ==========
|
||||||
getDropTarget(e: LocateEvent): NodeParent | LocationData | null {
|
getDropTarget(e: LocateEvent): NodeParent | LocationData | null {
|
||||||
/*
|
/*
|
||||||
const { target, dragTarget } = e;
|
const { target, dragTarget } = e;
|
||||||
@ -841,5 +846,5 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
}*/
|
}*/
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//#endregion
|
// #endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import { Asset } from '../utils/asset';
|
|||||||
import loader from '../utils/loader';
|
import loader from '../utils/loader';
|
||||||
import { ComponentDescriptionSpec } from '../../../designer/component-config';
|
import { ComponentDescriptionSpec } from '../../../designer/component-config';
|
||||||
import { findDOMNodes } from '../utils/react';
|
import { findDOMNodes } from '../utils/react';
|
||||||
|
import { isESModule } from '../../../utils/is-es-module';
|
||||||
|
import { NodeInstance } from '../../../designer/simulator';
|
||||||
|
|
||||||
let REACT_KEY = '';
|
let REACT_KEY = '';
|
||||||
function cacheReactKey(el: Element): Element {
|
function cacheReactKey(el: Element): Element {
|
||||||
@ -24,28 +26,36 @@ function cacheReactKey(el: Element): Element {
|
|||||||
|
|
||||||
const SYMBOL_VNID = Symbol('_LCNodeId');
|
const SYMBOL_VNID = Symbol('_LCNodeId');
|
||||||
|
|
||||||
function getClosestNodeId(element: Element): string | null {
|
function getClosestNodeInstance(element: Element): NodeInstance | null {
|
||||||
let el: any = element;
|
let el: any = element;
|
||||||
if (el) {
|
if (el) {
|
||||||
el = cacheReactKey(el);
|
el = cacheReactKey(el);
|
||||||
}
|
}
|
||||||
while (el) {
|
while (el) {
|
||||||
if (SYMBOL_VNID in el) {
|
if (SYMBOL_VNID in el) {
|
||||||
return el[SYMBOL_VNID];
|
return {
|
||||||
|
nodeId: el[SYMBOL_VNID],
|
||||||
|
instance: el,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
// get fiberNode from element
|
||||||
if (el[REACT_KEY]) {
|
if (el[REACT_KEY]) {
|
||||||
return getNodeId(el[REACT_KEY]);
|
return getNodeInstance(el[REACT_KEY]);
|
||||||
}
|
}
|
||||||
el = el.parentElement;
|
el = el.parentElement;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeId(instance: any): string {
|
function getNodeInstance(fiberNode: any): NodeInstance | null {
|
||||||
if (instance.stateNode && SYMBOL_VNID in instance.stateNode) {
|
const instance = fiberNode.stateNode;
|
||||||
return instance.stateNode[SYMBOL_VNID];
|
if (instance && SYMBOL_VNID in instance) {
|
||||||
|
return {
|
||||||
|
nodeId: instance[SYMBOL_VNID],
|
||||||
|
instance,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return getNodeId(instance.return);
|
return getNodeInstance(fiberNode.return);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInstanceMounted(instance: any): boolean {
|
function checkInstanceMounted(instance: any): boolean {
|
||||||
@ -190,8 +200,8 @@ export class SimulatorRenderer {
|
|||||||
return this.instancesMap.get(id) || null;
|
return this.instancesMap.get(id) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getClosestNodeId(element: Element): string | null {
|
getClosestNodeInstance(element: Element): NodeInstance | null {
|
||||||
return getClosestNodeId(element);
|
return getClosestNodeInstance(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
findDOMNodes(instance: ReactInstance): Array<Element | Text> | null {
|
findDOMNodes(instance: ReactInstance): Array<Element | Text> | null {
|
||||||
@ -228,22 +238,31 @@ function accessLibrary(library: string | object) {
|
|||||||
return (window as any)[library];
|
return (window as any)[library];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubComponent(component: any, paths: string[]) {
|
function getSubComponent(library: any, paths: string[]) {
|
||||||
const l = paths.length;
|
const l = paths.length;
|
||||||
if (l < 1) {
|
if (l < 1 || !library) {
|
||||||
return component;
|
return library;
|
||||||
}
|
}
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
let component: any;
|
||||||
while (i < l) {
|
while (i < l) {
|
||||||
const key = paths[i]!;
|
const key = paths[i]!;
|
||||||
|
let ex: any;
|
||||||
try {
|
try {
|
||||||
component = (component as any)[key];
|
component = library[key];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
ex = e;
|
||||||
|
component = null;
|
||||||
|
}
|
||||||
|
if (i === 0 && component == null && key === 'default') {
|
||||||
|
if (ex) {
|
||||||
|
return l === 1 ? library : null;
|
||||||
|
}
|
||||||
|
component = library;
|
||||||
|
} else if (component == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!component) {
|
library = component;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return component;
|
return component;
|
||||||
@ -253,13 +272,21 @@ function findComponent(componentName: string, npm?: NpmInfo) {
|
|||||||
if (!npm) {
|
if (!npm) {
|
||||||
return accessLibrary(componentName);
|
return accessLibrary(componentName);
|
||||||
}
|
}
|
||||||
|
// libraryName the key access to global
|
||||||
|
// export { exportName } from xxx exportName === global.libraryName.exportName
|
||||||
|
// export exportName from xxx exportName === global.libraryName.default || global.libraryName
|
||||||
|
// export { exportName as componentName } from package
|
||||||
|
// if exportName == null exportName === componentName;
|
||||||
|
// const componentName = exportName.subName, if exportName empty subName donot use
|
||||||
const libraryName = npm.exportName || npm.componentName || componentName;
|
const libraryName = npm.exportName || npm.componentName || componentName;
|
||||||
const component = accessLibrary(libraryName);
|
const library = accessLibrary(libraryName);
|
||||||
const paths = npm.subName ? npm.subName.split('.') : [];
|
const paths = npm.exportName && npm.subName ? npm.subName.split('.') : [];
|
||||||
if (npm.destructuring) {
|
if (npm.destructuring) {
|
||||||
paths.unshift(libraryName);
|
paths.unshift(libraryName);
|
||||||
|
} else if (isESModule(library)) {
|
||||||
|
paths.unshift('default');
|
||||||
}
|
}
|
||||||
return getSubComponent(component, paths);
|
return getSubComponent(library, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildComponents(componentsMap: { [componentName: string]: ComponentDescriptionSpec }) {
|
function buildComponents(componentsMap: { [componentName: string]: ComponentDescriptionSpec }) {
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
html.my-cursor-dragging, html.my-cursor-dragging * {
|
|
||||||
cursor: move !important
|
|
||||||
}
|
|
||||||
|
|
||||||
html.my-cursor-x-resizing, html.my-cursor-x-resizing * {
|
|
||||||
cursor: col-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.my-cursor-y-resizing, html.my-cursor-y-resizing * {
|
|
||||||
cursor: row-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.my-cursor-copy, html.my-cursor-copy * {
|
|
||||||
cursor: copy !important
|
|
||||||
}
|
|
||||||
@ -12,7 +12,7 @@ import Node, { insertChildren } from './document/node/node';
|
|||||||
import { isRootNode } from './document/node/root-node';
|
import { isRootNode } from './document/node/root-node';
|
||||||
import { ComponentDescriptionSpec, ComponentConfig } from './component-config';
|
import { ComponentDescriptionSpec, ComponentConfig } from './component-config';
|
||||||
import Scroller, { IScrollable } from './helper/scroller';
|
import Scroller, { IScrollable } from './helper/scroller';
|
||||||
import { INodeInstance } from './simulator';
|
import { INodeSelector } from './simulator';
|
||||||
import OffsetObserver, { createOffsetObserver } from './helper/offset-observer';
|
import OffsetObserver, { createOffsetObserver } from './helper/offset-observer';
|
||||||
|
|
||||||
export interface DesignerProps {
|
export interface DesignerProps {
|
||||||
@ -96,7 +96,7 @@ export default class Designer {
|
|||||||
|
|
||||||
private _dropLocation?: Location;
|
private _dropLocation?: Location;
|
||||||
/**
|
/**
|
||||||
* 创建插入位置
|
* 创建插入位置,考虑放到 dragon 中
|
||||||
*/
|
*/
|
||||||
createLocation(locationData: LocationData): Location {
|
createLocation(locationData: LocationData): Location {
|
||||||
const loc = new Location(locationData);
|
const loc = new Location(locationData);
|
||||||
@ -109,7 +109,7 @@ export default class Designer {
|
|||||||
/**
|
/**
|
||||||
* 清除插入位置
|
* 清除插入位置
|
||||||
*/
|
*/
|
||||||
private clearLocation() {
|
clearLocation() {
|
||||||
if (this._dropLocation) {
|
if (this._dropLocation) {
|
||||||
this._dropLocation.document.internalSetDropLocation(null);
|
this._dropLocation.document.internalSetDropLocation(null);
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ export default class Designer {
|
|||||||
return new Scroller(scrollable);
|
return new Scroller(scrollable);
|
||||||
}
|
}
|
||||||
|
|
||||||
createOffsetObserver(nodeInstance: INodeInstance): OffsetObserver | null {
|
createOffsetObserver(nodeInstance: INodeSelector): OffsetObserver | null {
|
||||||
return createOffsetObserver(nodeInstance);
|
return createOffsetObserver(nodeInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { RootSchema, NodeData, isDOMText, isJSExpression, NodeSchema } from '../
|
|||||||
import Node, { isNodeParent, insertChildren, insertChild, NodeParent } from './node/node';
|
import Node, { isNodeParent, insertChildren, insertChild, NodeParent } from './node/node';
|
||||||
import { Selection } from './selection';
|
import { Selection } from './selection';
|
||||||
import RootNode from './node/root-node';
|
import RootNode from './node/root-node';
|
||||||
import { ISimulator, ComponentInstance, Component } from '../simulator';
|
import { ISimulator, ComponentInstance, Component, NodeInstance } from '../simulator';
|
||||||
import { computed, obx } from '@recore/obx';
|
import { computed, obx } from '@recore/obx';
|
||||||
import Location from '../helper/location';
|
import Location from '../helper/location';
|
||||||
import { ComponentConfig } from '../component-config';
|
import { ComponentConfig } from '../component-config';
|
||||||
@ -245,16 +245,20 @@ export default class DocumentModel {
|
|||||||
/**
|
/**
|
||||||
* 通过 DOM 节点获取节点,依赖 simulator 的接口
|
* 通过 DOM 节点获取节点,依赖 simulator 的接口
|
||||||
*/
|
*/
|
||||||
getNodeFromElement(target: Element | null): Node | null {
|
getNodeInstanceFromElement(target: Element | null): NodeInstance | null {
|
||||||
if (!this.simulator || !target) {
|
if (!this.simulator || !target) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = this.simulator.getClosestNodeId(target);
|
const nodeIntance = this.simulator.getClosestNodeInstance(target);
|
||||||
if (!id) {
|
if (!nodeIntance) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.getNode(id) as Node;
|
const node = this.getNode(nodeIntance.nodeId);
|
||||||
|
return {
|
||||||
|
...nodeIntance,
|
||||||
|
node,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
15
packages/designer/src/designer/helper/cursor.less
Normal file
15
packages/designer/src/designer/helper/cursor.less
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
html.lc-cursor-dragging, html.lc-cursor-dragging * {
|
||||||
|
cursor: move !important
|
||||||
|
}
|
||||||
|
|
||||||
|
html.lc-cursor-x-resizing, html.lc-cursor-x-resizing * {
|
||||||
|
cursor: col-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.lc-cursor-y-resizing, html.lc-cursor-y-resizing * {
|
||||||
|
cursor: row-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.lc-cursor-copy, html.lc-cursor-copy * {
|
||||||
|
cursor: copy !important
|
||||||
|
}
|
||||||
@ -45,14 +45,14 @@ export class Cursor {
|
|||||||
private addState(state: string) {
|
private addState(state: string) {
|
||||||
if (!this.states.has(state)) {
|
if (!this.states.has(state)) {
|
||||||
this.states.add(state);
|
this.states.add(state);
|
||||||
document.documentElement.classList.add(`my-cursor-${state}`);
|
document.documentElement.classList.add(`lc-cursor-${state}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeState(state: string) {
|
private removeState(state: string) {
|
||||||
if (this.states.has(state)) {
|
if (this.states.has(state)) {
|
||||||
this.states.delete(state);
|
this.states.delete(state);
|
||||||
document.documentElement.classList.remove(`my-cursor-${state}`);
|
document.documentElement.classList.remove(`lc-cursor-${state}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,9 +3,11 @@ import { obx } from '@recore/obx';
|
|||||||
import Location from './location';
|
import Location from './location';
|
||||||
import DocumentModel from '../document/document-model';
|
import DocumentModel from '../document/document-model';
|
||||||
import { NodeData } from '../schema';
|
import { NodeData } from '../schema';
|
||||||
import { ISimulator } from '../simulator';
|
import { ISimulator, isSimulator } from '../simulator';
|
||||||
import Node from '../document/node/node';
|
import Node from '../document/node/node';
|
||||||
import Designer from '../designer';
|
import Designer from '../designer';
|
||||||
|
import { setNativeSelection } from '../../utils/navtive-selection';
|
||||||
|
import cursor from './cursor';
|
||||||
|
|
||||||
export interface LocateEvent {
|
export interface LocateEvent {
|
||||||
readonly type: 'LocateEvent';
|
readonly type: 'LocateEvent';
|
||||||
@ -22,10 +24,17 @@ export interface LocateEvent {
|
|||||||
* 拖拽对象
|
* 拖拽对象
|
||||||
*/
|
*/
|
||||||
readonly dragObject: DragObject;
|
readonly dragObject: DragObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 激活的感应器
|
||||||
|
*/
|
||||||
|
sensor?: ISensor;
|
||||||
|
|
||||||
|
// ======= 以下是 激活的 sensor 将填充的值 ========
|
||||||
/**
|
/**
|
||||||
* 浏览器事件响应目标
|
* 浏览器事件响应目标
|
||||||
*/
|
*/
|
||||||
target: Element | null;
|
target?: Element | null;
|
||||||
/**
|
/**
|
||||||
* 当前激活文档画布坐标系
|
* 当前激活文档画布坐标系
|
||||||
*/
|
*/
|
||||||
@ -134,14 +143,18 @@ export default class Dragon {
|
|||||||
private sensors: ISensor[] = [];
|
private sensors: ISensor[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* current actived sensor
|
* current actived sensor, 可用于感应区高亮
|
||||||
*/
|
*/
|
||||||
private _activeSensor: ISensor | undefined;
|
@obx.ref private _activeSensor: ISensor | undefined;
|
||||||
get activeSensor(): ISensor | undefined {
|
get activeSensor(): ISensor | undefined {
|
||||||
return this._activeSensor;
|
return this._activeSensor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.ref dragging = false;
|
@obx.ref private _dragging: boolean = false;
|
||||||
|
get dragging(): boolean {
|
||||||
|
return this._dragging;
|
||||||
|
}
|
||||||
|
|
||||||
private emitter = new EventEmitter();
|
private emitter = new EventEmitter();
|
||||||
|
|
||||||
constructor(readonly designer: Designer) {}
|
constructor(readonly designer: Designer) {}
|
||||||
@ -168,66 +181,69 @@ export default class Dragon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getMasterSensors(): ISimulator[] {
|
getMasterSensors(): ISimulator[] {
|
||||||
return this.designer.project.documents.map(doc => (doc.actived && doc.simulator) || null).filter(Boolean) as any;
|
return this.designer.project.documents.map(doc => {
|
||||||
|
if (doc.actived && doc.simulator?.sensorAvailable) {
|
||||||
|
return doc.simulator;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}).filter(Boolean) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* dragTarget should be a INode | INode[] | NodeData | NodeData[]
|
|
||||||
*/
|
|
||||||
boost(dragObject: DragObject, boostEvent: MouseEvent) {
|
boost(dragObject: DragObject, boostEvent: MouseEvent) {
|
||||||
/*
|
|
||||||
const doc = document;
|
const doc = document;
|
||||||
const fromTop = isFromTopDocument(boostEvent);
|
const isFromTop = isFromTopDocument(boostEvent);
|
||||||
let lastLocation: any = null;
|
|
||||||
let lastSensor: ISensor | undefined;
|
|
||||||
this.dragging = false;
|
|
||||||
const masterSensors = this.getMasterSensors();
|
const masterSensors = this.getMasterSensors();
|
||||||
masterSensors.forEach((sensor) => {
|
const designer = this.designer;
|
||||||
sensor.setNativeSelection(false);
|
const newBie = dragObject.type !== DragObjectType.Node;
|
||||||
});
|
let lastSensor: ISensor | undefined;
|
||||||
//
|
|
||||||
|
this._dragging = false;
|
||||||
|
// 禁用默认的文稿拖选
|
||||||
|
this.setNativeSelection(false);
|
||||||
|
|
||||||
const checkesc = (e: KeyboardEvent) => {
|
const checkesc = (e: KeyboardEvent) => {
|
||||||
if (e.keyCode === 27) {
|
if (e.keyCode === 27) {
|
||||||
lastLocation = null;
|
designer.clearLocation();
|
||||||
master.document.clearLocation();
|
|
||||||
over();
|
over();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkcopy = (e: MouseEvent) => {
|
const checkcopy = (e: MouseEvent) => {
|
||||||
if (newBie || e.altKey || e.ctrlKey) {
|
if (newBie || e.altKey || e.ctrlKey) {
|
||||||
master.setCopy(true);
|
this.setCopyState(true);
|
||||||
} else {
|
} else {
|
||||||
master.setCopy(false);
|
this.setCopyState(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// period one fix:
|
||||||
|
// get evt source-sensor
|
||||||
|
// get globalX and globalY source-sensor
|
||||||
|
|
||||||
const drag = (e: MouseEvent) => {
|
const drag = (e: MouseEvent) => {
|
||||||
checkcopy(e);
|
checkcopy(e);
|
||||||
|
|
||||||
const locateEvent = fixEvent(e);
|
const locateEvent = createLocateEvent(e);
|
||||||
const sensor = chooseSensor(locateEvent);
|
const sensor = chooseSensor(locateEvent);
|
||||||
if (sensor) {
|
if (sensor) {
|
||||||
sensor.fixEvent(locateEvent);
|
sensor.fixEvent(locateEvent);
|
||||||
lastLocation = sensor.locate(locateEvent);
|
sensor.locate(locateEvent);
|
||||||
} else {
|
} else {
|
||||||
master.document.clearLocation();
|
designer.clearLocation();
|
||||||
lastLocation = null;
|
|
||||||
}
|
}
|
||||||
this.emitter.emit('drag', locateEvent, lastLocation);
|
this.emitter.emit('drag', locateEvent);
|
||||||
};
|
};
|
||||||
|
|
||||||
const dragstart = () => {
|
const dragstart = () => {
|
||||||
const locateEvent = fixEvent(boostEvent);
|
const locateEvent = createLocateEvent(boostEvent);
|
||||||
if (!newBie) {
|
if (!newBie) {
|
||||||
chooseSensor(locateEvent);
|
chooseSensor(locateEvent);
|
||||||
}
|
}
|
||||||
master.setDragging(true);
|
this.setDraggingState(true);
|
||||||
// ESC cancel drag
|
// ESC cancel drag
|
||||||
doc.addEventListener('keydown', checkesc, false);
|
doc.addEventListener('keydown', checkesc, false);
|
||||||
if (topDoc) {
|
if (isFromTop) {
|
||||||
topDoc.addEventListener('keydown', checkesc, false);
|
// topDoc.addEventListener('keydown', checkesc, false);
|
||||||
}
|
}
|
||||||
this.emitter.emit('dragstart', locateEvent);
|
this.emitter.emit('dragstart', locateEvent);
|
||||||
};
|
};
|
||||||
@ -239,7 +255,7 @@ export default class Dragon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isShaken(boostEvent, e)) {
|
if (isShaken(boostEvent, e)) {
|
||||||
this.dragging = true;
|
this._dragging = true;
|
||||||
|
|
||||||
setShaken(boostEvent);
|
setShaken(boostEvent);
|
||||||
dragstart();
|
dragstart();
|
||||||
@ -249,23 +265,23 @@ export default class Dragon {
|
|||||||
|
|
||||||
const over = (e?: any) => {
|
const over = (e?: any) => {
|
||||||
if (lastSensor) {
|
if (lastSensor) {
|
||||||
lastSensor.deactive();
|
lastSensor.deactiveSensor();
|
||||||
}
|
}
|
||||||
master.setNativeSelection(true);
|
this.setNativeSelection(true);
|
||||||
|
|
||||||
let exception;
|
let exception;
|
||||||
if (this.dragging) {
|
if (this._dragging) {
|
||||||
this.dragging = false;
|
this._dragging = false;
|
||||||
try {
|
try {
|
||||||
this.emitter.emit('dragend', { dragTarget: dragObject, copy: master.isCopy() }, lastLocation);
|
this.emitter.emit('dragend', { dragTarget: dragObject, copy: this.isCopyState() });
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
exception = ex;
|
exception = ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
master.releaseCursor();
|
this.clearState();
|
||||||
|
|
||||||
if (fromTop) {
|
if (isFromTop) {
|
||||||
doc.removeEventListener('mousemove', move, true);
|
doc.removeEventListener('mousemove', move, true);
|
||||||
doc.removeEventListener('mouseup', over, true);
|
doc.removeEventListener('mouseup', over, true);
|
||||||
doc.removeEventListener('mousedown', over, true);
|
doc.removeEventListener('mousedown', over, true);
|
||||||
@ -290,28 +306,44 @@ export default class Dragon {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fixEvent = (e: MouseEvent): LocateEvent => {
|
const createLocateEvent = (e: MouseEvent): LocateEvent => {
|
||||||
if (isLocateEvent(e)) {
|
if (isLocateEvent(e)) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
const evt: any = {
|
const evt: any = {
|
||||||
type: 'LocateEvent',
|
type: 'LocateEvent',
|
||||||
|
dragObject,
|
||||||
target: e.target,
|
target: e.target,
|
||||||
dragTarget: dragObject,
|
|
||||||
originalEvent: e,
|
originalEvent: e,
|
||||||
};
|
};
|
||||||
if (e.view!.document === document) {
|
|
||||||
const l = viewport.toLocalPoint(e);
|
const sourceDocument = e.view?.document;
|
||||||
evt.clientX = l.clientX;
|
|
||||||
evt.clientY = l.clientY;
|
if (!sourceDocument || sourceDocument === document) {
|
||||||
evt.globalX = e.clientX;
|
evt.globalX = e.clientX;
|
||||||
evt.globalY = e.clientY;
|
evt.globalY = e.clientY;
|
||||||
} else {
|
} else {
|
||||||
const g = viewport.toGlobalPoint(e);
|
let srcSim: ISimulator | undefined;
|
||||||
evt.clientX = e.clientX;
|
let lastSim = lastSensor && isSimulator(lastSensor) ? lastSensor : null;
|
||||||
evt.clientY = e.clientY;
|
if (lastSim && lastSim.contentDocument === sourceDocument) {
|
||||||
evt.globalX = g.clientX;
|
srcSim = lastSim;
|
||||||
evt.globalY = g.clientY;
|
} else {
|
||||||
|
srcSim = masterSensors.find(sim => sim.contentDocument === sourceDocument);
|
||||||
|
if (!srcSim && lastSim) {
|
||||||
|
srcSim = lastSim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (srcSim) {
|
||||||
|
const g = srcSim.viewport.toGlobalPoint(e);
|
||||||
|
evt.globalX = g.clientX;
|
||||||
|
evt.globalY = g.clientY;
|
||||||
|
evt.sensor = srcSim;
|
||||||
|
} else {
|
||||||
|
// this condition will not happen, just make sure ts ok
|
||||||
|
evt.globalX = e.clientX;
|
||||||
|
evt.globalY = e.clientY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return evt;
|
return evt;
|
||||||
};
|
};
|
||||||
@ -320,15 +352,13 @@ export default class Dragon {
|
|||||||
if (!isDragNodeObject(dragObject)) {
|
if (!isDragNodeObject(dragObject)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (Array.isArray(dragObject.nodes) ? dragObject.nodes[0] : dragObject.nodes)?.document.simulator || null;
|
return dragObject.nodes[0]?.document.simulator || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const simSensors = this.project.documents.map(doc => (doc.actived && doc.simulator) || null).filter(Boolean);
|
|
||||||
const sourceSensor = getSourceSensor(dragObject);
|
const sourceSensor = getSourceSensor(dragObject);
|
||||||
// check simulator is empty
|
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
|
||||||
const sensors: ISensor[] = simSensors.concat(this.sensors);
|
|
||||||
const chooseSensor = (e: LocateEvent) => {
|
const chooseSensor = (e: LocateEvent) => {
|
||||||
let sensor = sensors.find(s => s.sensorAvailable && s.isEnter(e));
|
let sensor = e.sensor || sensors.find(s => s.sensorAvailable && s.isEnter(e));
|
||||||
if (!sensor) {
|
if (!sensor) {
|
||||||
if (lastSensor) {
|
if (lastSensor) {
|
||||||
sensor = lastSensor;
|
sensor = lastSensor;
|
||||||
@ -343,6 +373,7 @@ export default class Dragon {
|
|||||||
lastSensor = sensor;
|
lastSensor = sensor;
|
||||||
}
|
}
|
||||||
if (sensor) {
|
if (sensor) {
|
||||||
|
e.sensor = sensor;
|
||||||
sensor.fixEvent(e);
|
sensor.fixEvent(e);
|
||||||
}
|
}
|
||||||
this._activeSensor = sensor;
|
this._activeSensor = sensor;
|
||||||
@ -352,26 +383,81 @@ export default class Dragon {
|
|||||||
doc.addEventListener('mousemove', move, true);
|
doc.addEventListener('mousemove', move, true);
|
||||||
doc.addEventListener('mouseup', over, true);
|
doc.addEventListener('mouseup', over, true);
|
||||||
doc.addEventListener('mousedown', over, true);
|
doc.addEventListener('mousedown', over, true);
|
||||||
if (topDoc) {
|
if (isFromTop) {/*
|
||||||
topDoc.addEventListener('mousemove', move, true);
|
topDoc.addEventListener('mousemove', move, true);
|
||||||
topDoc.addEventListener('mouseup', over, true);
|
topDoc.addEventListener('mouseup', over, true);
|
||||||
topDoc.addEventListener('mousedown', over, true);
|
topDoc.addEventListener('mousedown', over, true);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newBie) {
|
if (!newBie) {
|
||||||
doc.addEventListener('keydown', checkcopy as any, false);
|
doc.addEventListener('keydown', checkcopy as any, false);
|
||||||
doc.addEventListener('keyup', checkcopy as any, false);
|
doc.addEventListener('keyup', checkcopy as any, false);
|
||||||
if (topDoc) {
|
if (isFromTop) {/*
|
||||||
topDoc.addEventListener('keydown', checkcopy as any, false);
|
topDoc.addEventListener('keydown', checkcopy as any, false);
|
||||||
topDoc.addEventListener('keyup', checkcopy as any, false);
|
topDoc.addEventListener('keyup', checkcopy as any, false);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #region ======== drag and drop helpers ============
|
||||||
|
private setNativeSelection(enableFlag: boolean) {
|
||||||
|
setNativeSelection(enableFlag);
|
||||||
|
this.designer.project.documents.forEach(doc => {
|
||||||
|
doc.simulator?.setNativeSelection(enableFlag);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置拖拽态
|
||||||
|
*/
|
||||||
|
private setDraggingState(state: boolean) {
|
||||||
|
cursor.setDragging(state);
|
||||||
|
this.designer.project.documents.forEach(doc => {
|
||||||
|
doc.simulator?.setDraggingState(state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置拷贝态
|
||||||
|
*/
|
||||||
|
private setCopyState(state: boolean) {
|
||||||
|
cursor.setCopy(state);
|
||||||
|
this.designer.project.documents.forEach(doc => {
|
||||||
|
doc.simulator?.setCopyState(state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否拷贝态
|
||||||
|
*/
|
||||||
|
private isCopyState(): boolean {
|
||||||
|
return cursor.isCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有态:拖拽态、拷贝态
|
||||||
|
*/
|
||||||
|
private clearState() {
|
||||||
|
cursor.release();
|
||||||
|
this.designer.project.documents.forEach(doc => {
|
||||||
|
doc.simulator?.clearState();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加投放感应区
|
||||||
|
*/
|
||||||
addSensor(sensor: any) {
|
addSensor(sensor: any) {
|
||||||
this.sensors.push(sensor);
|
this.sensors.push(sensor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除投放感应
|
||||||
|
*/
|
||||||
removeSensor(sensor: any) {
|
removeSensor(sensor: any) {
|
||||||
const i = this.sensors.indexOf(sensor);
|
const i = this.sensors.indexOf(sensor);
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
@ -386,14 +472,14 @@ export default class Dragon {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onDrag(func: (e: LocateEvent, location: Location) => any) {
|
onDrag(func: (e: LocateEvent) => any) {
|
||||||
this.emitter.on('drag', func);
|
this.emitter.on('drag', func);
|
||||||
return () => {
|
return () => {
|
||||||
this.emitter.removeListener('drag', func);
|
this.emitter.removeListener('drag', func);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onDragend(func: (x: { dragObject: DragObject; copy: boolean }, location: Location) => any) {
|
onDragend(func: (x: { dragObject: DragObject; copy: boolean }) => any) {
|
||||||
this.emitter.on('dragend', func);
|
this.emitter.on('dragend', func);
|
||||||
return () => {
|
return () => {
|
||||||
this.emitter.removeListener('dragend', func);
|
this.emitter.removeListener('dragend', func);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { obx, computed } from '@recore/obx';
|
import { obx, computed } from '@recore/obx';
|
||||||
import { INodeInstance, IViewport } from '../simulator';
|
import { INodeSelector, IViewport } from '../simulator';
|
||||||
import Viewport from '../../builtins/simulator/host/viewport';
|
import Viewport from '../../builtins/simulator/host/viewport';
|
||||||
|
|
||||||
export default class OffsetObserver {
|
export default class OffsetObserver {
|
||||||
@ -24,7 +24,7 @@ export default class OffsetObserver {
|
|||||||
private pid: number | undefined;
|
private pid: number | undefined;
|
||||||
private viewport: IViewport;
|
private viewport: IViewport;
|
||||||
|
|
||||||
constructor(readonly nodeInstance: INodeInstance) {
|
constructor(readonly nodeInstance: INodeSelector) {
|
||||||
const { node, instance } = nodeInstance;
|
const { node, instance } = nodeInstance;
|
||||||
const doc = node.document;
|
const doc = node.document;
|
||||||
const host = doc.simulator!;
|
const host = doc.simulator!;
|
||||||
@ -67,7 +67,7 @@ export default class OffsetObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createOffsetObserver(nodeInstance: INodeInstance): OffsetObserver | null {
|
export function createOffsetObserver(nodeInstance: INodeSelector): OffsetObserver | null {
|
||||||
if (!nodeInstance.instance) {
|
if (!nodeInstance.instance) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,7 @@ export interface IViewport extends IScrollable {
|
|||||||
* 模拟器控制进程协议
|
* 模拟器控制进程协议
|
||||||
*/
|
*/
|
||||||
export interface ISimulator<P = object> extends ISensor {
|
export interface ISimulator<P = object> extends ISensor {
|
||||||
|
readonly isSimulator: true;
|
||||||
/**
|
/**
|
||||||
* 获得边界维度等信息
|
* 获得边界维度等信息
|
||||||
*/
|
*/
|
||||||
@ -77,26 +78,23 @@ export interface ISimulator<P = object> extends ISensor {
|
|||||||
// 获取区块代码, 通过 components 传递,可异步获取
|
// 获取区块代码, 通过 components 传递,可异步获取
|
||||||
setProps(props: P): void;
|
setProps(props: P): void;
|
||||||
|
|
||||||
|
|
||||||
|
setSuspense(suspensed: boolean): void;
|
||||||
|
|
||||||
|
// #region ========= drag and drop helpers =============
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文字拖选
|
||||||
|
*/
|
||||||
|
setNativeSelection(enableFlag: boolean): void;
|
||||||
/**
|
/**
|
||||||
* 设置拖拽态
|
* 设置拖拽态
|
||||||
*/
|
*/
|
||||||
setDraggingState(state: boolean): void;
|
setDraggingState(state: boolean): void;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否拖拽态
|
|
||||||
*/
|
|
||||||
isDraggingState(): boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置拷贝态
|
* 设置拷贝态
|
||||||
*/
|
*/
|
||||||
setCopyState(state: boolean): void;
|
setCopyState(state: boolean): void;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否拷贝态
|
|
||||||
*/
|
|
||||||
isCopyState(): boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除所有态:拖拽态、拷贝态
|
* 清除所有态:拖拽态、拷贝态
|
||||||
*/
|
*/
|
||||||
@ -107,16 +105,18 @@ export interface ISimulator<P = object> extends ISensor {
|
|||||||
*/
|
*/
|
||||||
locate(e: LocateEvent): any;
|
locate(e: LocateEvent): any;
|
||||||
|
|
||||||
/**
|
|
||||||
* 滚动视口到节点
|
|
||||||
*/
|
|
||||||
scrollToNode(node: Node, detail?: any): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给 event 打补丁,添加 canvasX, globalX 等信息,用于拖拽
|
* 给 event 打补丁,添加 canvasX, globalX 等信息,用于拖拽
|
||||||
*/
|
*/
|
||||||
fixEvent(e: LocateEvent): LocateEvent;
|
fixEvent(e: LocateEvent): LocateEvent;
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滚动视口到节点
|
||||||
|
*/
|
||||||
|
scrollToNode(node: Node, detail?: any): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 描述组件
|
* 描述组件
|
||||||
*/
|
*/
|
||||||
@ -134,19 +134,28 @@ export interface ISimulator<P = object> extends ISensor {
|
|||||||
*/
|
*/
|
||||||
getComponentContext(node: Node): object | null;
|
getComponentContext(node: Node): object | null;
|
||||||
|
|
||||||
getClosestNodeId(elem: Element): string | null;
|
getClosestNodeInstance(elem: Element): NodeInstance | null;
|
||||||
|
|
||||||
computeComponentInstanceRect(instance: ComponentInstance): DOMRect | null;
|
computeComponentInstanceRect(instance: ComponentInstance): DOMRect | null;
|
||||||
|
|
||||||
findDOMNodes(instance: ComponentInstance): Array<Element | Text> | null;
|
findDOMNodes(instance: ComponentInstance): Array<Element | Text> | null;
|
||||||
|
|
||||||
setSuspense(suspensed: boolean): void;
|
|
||||||
/**
|
/**
|
||||||
* 销毁
|
* 销毁
|
||||||
*/
|
*/
|
||||||
purge(): void;
|
purge(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSimulator(obj: any): obj is ISimulator {
|
||||||
|
return obj && obj.isSimulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeInstance {
|
||||||
|
nodeId: string;
|
||||||
|
instance: ComponentInstance;
|
||||||
|
node?: Node | null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组件类定义
|
* 组件类定义
|
||||||
*/
|
*/
|
||||||
@ -157,7 +166,7 @@ export type Component = ComponentType<any> | object;
|
|||||||
*/
|
*/
|
||||||
export type ComponentInstance = Element | ReactComponent<any> | object;
|
export type ComponentInstance = Element | ReactComponent<any> | object;
|
||||||
|
|
||||||
export interface INodeInstance {
|
export interface INodeSelector {
|
||||||
node: Node;
|
node: Node;
|
||||||
instance?: ComponentInstance;
|
instance?: ComponentInstance;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user