complete router

This commit is contained in:
kangwei 2020-08-12 18:05:07 +08:00
parent 45ffc98277
commit dc8542a8fa
18 changed files with 336 additions and 244 deletions

View File

@ -57,7 +57,10 @@ export class BorderDetecting extends Component<{ host: BuiltinSimulatorHost }> {
@computed get current() {
const host = this.props.host;
const doc = host.document;
const doc = host.currentDocument;
if (!doc) {
return null;
}
const selection = doc.selection;
const current = host.designer.detecting.current;
if (!current || current.document !== doc || selection.has(current.id)) {

View File

@ -5,6 +5,7 @@ import classNames from 'classnames';
import { SimulatorContext } from '../context';
import { BuiltinSimulatorHost } from '../host';
import { OffsetObserver, Designer } from '../../designer';
import { Node } from '../../document';
@observer
export default class BoxResizing extends Component<{ host: BuiltinSimulatorHost }> {
@ -19,8 +20,8 @@ export default class BoxResizing extends Component<{ host: BuiltinSimulatorHost
}
@computed get selecting() {
const doc = this.host.document;
if (doc.suspensed) {
const doc = this.host.currentDocument;
if (!doc || doc.suspensed) {
return null;
}
const selection = doc.selection;
@ -146,9 +147,9 @@ export class BoxResizingInstance extends Component<{
metaData.experimental.callbacks &&
typeof metaData.experimental.callbacks.onResize === 'function'
) {
e.trigger = direction;
e.deltaX = moveX;
e.deltaY = moveY;
(e as any).trigger = direction;
(e as any).deltaX = moveX;
(e as any).deltaY = moveY;
metaData.experimental.callbacks.onResize(e, node);
}
};
@ -161,7 +162,7 @@ export class BoxResizingInstance extends Component<{
metaData.experimental.callbacks &&
typeof metaData.experimental.callbacks.onResizeStart === 'function'
) {
e.trigger = direction;
(e as any).trigger = direction;
metaData.experimental.callbacks.onResizeStart(e, node);
}
};
@ -174,7 +175,7 @@ export class BoxResizingInstance extends Component<{
metaData.experimental.callbacks &&
typeof metaData.experimental.callbacks.onResizeEnd === 'function'
) {
e.trigger = direction;
(e as any).trigger = direction;
metaData.experimental.callbacks.onResizeStart(e, node);
}

View File

@ -198,8 +198,8 @@ export class BorderSelecting extends Component<{ host: BuiltinSimulatorHost }> {
}
@computed get selecting() {
const doc = this.host.document;
if (doc.suspensed || this.host.liveEditing.editing) {
const doc = this.host.currentDocument;
if (!doc || doc.suspensed || this.host.liveEditing.editing) {
return null;
}
const selection = doc.selection;

View File

@ -119,7 +119,7 @@ export class InsertionView extends Component<{ host: BuiltinSimulatorHost }> {
render() {
const { host } = this.props;
const loc = host.document.dropLocation;
const loc = host.currentDocument?.dropLocation;
if (!loc) {
return null;
}

View File

@ -2,7 +2,7 @@ import { obx, autorun, computed, getPublicPath, hotkey, focusTracker } from '@al
import { ISimulatorHost, Component, NodeInstance, ComponentInstance } from '../simulator';
import Viewport from './viewport';
import { createSimulator } from './create-simulator';
import { Node, ParentalNode, DocumentModel, isNode, contains, isRootNode } from '../document';
import { Node, ParentalNode, isNode, contains, isRootNode } from '../document';
import ResourceConsumer from './resource-consumer';
import {
AssetLevel,
@ -89,6 +89,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
readonly designer = this.project.designer;
get currentDocument() {
return this.project.currentDocument;
}
@computed get device(): string {
return this.get('device') || 'default';
}
@ -141,6 +145,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return autorun(fn as any, true);
}
autorun(fn: (context: { dispose: () => void; firstRun: boolean }) => void) {
return autorun(fn as any, true);
}
purge(): void {
// todo
}
@ -245,9 +253,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}
setupDragAndClick() {
const documentModel = this.document;
const selection = documentModel.selection;
const designer = documentModel.designer;
const designer = this.designer;
const doc = this.contentDocument!;
// TODO: think of lock when edit a node
@ -257,9 +263,11 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
(downEvent: MouseEvent) => {
// fix for popups close logic
document.dispatchEvent(new Event('mousedown'));
if (this.liveEditing.editing) {
const documentModel = this.project.currentDocument;
if (this.liveEditing.editing || !documentModel) {
return;
}
const selection = documentModel.selection;
// stop response document focus event
downEvent.stopPropagation();
downEvent.preventDefault();
@ -267,8 +275,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// FIXME: dirty fix remove label-for fro liveEditing
(downEvent.target as HTMLElement).removeAttribute('for');
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element);
const node = nodeInst?.node || this.document.rootNode;
const node = nodeInst?.node || documentModel.rootNode;
const isMulti = downEvent.metaKey || downEvent.ctrlKey;
const isLeftButton = downEvent.which === 1 || downEvent.button === 0;
const checkSelect = (e: MouseEvent) => {
@ -280,6 +289,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
selection.remove(id);
} else {
selection.select(id);
// dirty code should refector
const editor = this.designer?.editor;
const npm = node?.componentMeta?.npm;
const selected =
@ -303,7 +314,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
selection.add(node.id);
ignoreUpSelected = true;
}
selection.remove(this.document.rootNode.id);
selection.remove(documentModel.rootNode.id);
// 获得顶层 nodes
nodes = selection.getTopNodes();
} else if (selection.containsNode(node, true)) {
@ -359,7 +370,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
*/
setupDetecting() {
const doc = this.contentDocument!;
const detecting = this.document.designer.detecting;
const detecting = this.designer.detecting;
const hover = (e: MouseEvent) => {
if (!detecting.enable) {
return;
@ -368,7 +379,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
detecting.capture(nodeInst?.node || null);
e.stopPropagation();
};
const leave = () => detecting.leave(this.document);
const leave = () => detecting.leave(this.project.currentDocument);
doc.addEventListener('mouseover', hover, true);
doc.addEventListener('mouseleave', leave, false);
@ -383,7 +394,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
);
this.disableHovering = () => {
detecting.leave(this.document);
detecting.leave(this.project.currentDocument);
doc.removeEventListener('mouseover', hover, true);
doc.removeEventListener('mouseleave', leave, false);
this.disableHovering = undefined;
@ -406,7 +417,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
if (!nodeInst) {
return;
}
const node = nodeInst.node || this.document.rootNode;
const node = nodeInst.node || this.project.currentDocument?.rootNode;
if (!node) {
return;
}
const rootElement = this.findDOMNodes(nodeInst.instance, node.componentMeta.rootSelector)?.find((item) =>
item.contains(targetElement),
@ -450,10 +464,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
if (!nodeInst) {
return;
}
const node = nodeInst.node || this.document.rootNode;
const node = nodeInst.node || this.project.currentDocument?.rootNode;
if (!node) {
return;
}
// dirty code should refector
const editor = this.designer?.editor;
const npm = node?.componentMeta?.npm;
const selected =
@ -504,14 +520,15 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}
createComponent(schema: ComponentSchema): Component | null {
return this.renderer?.createComponent(schema) || null;
return null;
// return this.renderer?.createComponent(schema) || null;
}
@obx private instancesMap: {
[docId: string]: Map<string, ComponentInstance[]>;
} = {};
setInstance(docId: string, id: string, instances: ComponentInstance[] | null) {
if (hasOwnProperty(this.instancesMap, docId)) {
if (!hasOwnProperty(this.instancesMap, docId)) {
this.instancesMap[docId] = new Map();
}
if (instances == null) {
@ -524,17 +541,18 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/**
* @see ISimulator
*/
getComponentInstances(node: Node): ComponentInstance[] | null {
getComponentInstances(node: Node, context?: NodeInstance): ComponentInstance[] | null {
const docId = node.document.id;
return this.instancesMap[docId]?.get(node.id) || null;
}
let instances = this.instancesMap[docId]?.get(node.id) || null;
if (!instances || !context) {
return instances;
}
/**
* @see ISimulator
*/
getComponentInstanceId(instance: ComponentInstance) {
throw new Error('Method not implemented.');
// filter with context
return instances.filter((instance) => {
return this.getClosestNodeInstance(instance, context.nodeId)?.instance === context.instance
});
}
/**
@ -659,7 +677,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
if (!nodeIntance) {
return null;
}
const node = this.document.getNode(nodeIntance.nodeId);
const { docId } = nodeIntance;
const doc = this.project.getDocument(docId)!;
const node = doc.getNode(nodeIntance.nodeId);
return {
...nodeIntance,
node,
@ -782,9 +802,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
e.target = this.contentDocument!.elementFromPoint(e.canvasX!, e.canvasY!);
}
// documentModel : 目标文档
e.documentModel = this.document;
// 事件已订正
e.fixed = true;
return e;
@ -815,6 +832,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
locate(e: LocateEvent): any {
this.sensing = true;
this.scroller.scrolling(e);
const document = this.project.currentDocument;
if (!document) {
return null;
}
const dropContainer = this.getDropContainer(e);
if (!dropContainer) {
return null;
@ -841,9 +862,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
};
const locationData = {
target: container,
target: container as ParentalNode,
detail,
source: 'simulator' + this.document.id,
source: 'simulator' + document.id,
event: e,
};
@ -854,9 +875,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
e.dragObject.nodes[0].getPrototype()?.isModal()
) {
return this.designer.createLocation({
target: this.document.rootNode,
target: document.rootNode,
detail,
source: 'simulator' + this.document.id,
source: 'simulator' + document.id,
event: e,
});
}
@ -960,7 +981,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
getDropContainer(e: LocateEvent): DropContainer | LocationData | null {
const { target, dragObject } = e;
const isAny = isDragAnyObject(dragObject);
const { modalNode, currentRoot } = this.document;
const document = this.project.currentDocument!;
const { currentRoot } = document;
let container: Node;
let nodeInstance: NodeInstance<ComponentInstance> | undefined;
@ -984,11 +1006,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
container = container.parent || currentRoot;
}
// check container if in modalNode layer, if not, use modalNode
if (modalNode && !modalNode.contains(container)) {
container = modalNode;
}
// TODO: use spec container to accept specialData
if (isAny) {
// will return locationData
@ -996,7 +1013,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}
// get common parent, avoid drop container contains by dragObject
// TODO: renderengine support pointerEvents: none for acceleration
const drillDownExcludes = new Set<Node>();
if (isDragNodeObject(dragObject)) {
const nodes = dragObject.nodes;
@ -1008,63 +1024,70 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}
}
if (p !== container) {
container = p || this.document.rootNode;
container = p || document.rootNode;
drillDownExcludes.add(container);
}
}
const ret: any = {
container,
};
let instance: any;
if (nodeInstance) {
if (nodeInstance.node === container) {
ret.instance = nodeInstance.instance;
instance = nodeInstance.instance;
} else {
ret.instance = this.getClosestNodeInstance(nodeInstance.instance as any, container.id)?.instance;
instance = this.getClosestNodeInstance(nodeInstance.instance as any, container.id)?.instance;
}
} else {
ret.instance = this.getComponentInstances(container)?.[0];
instance = this.getComponentInstances(container)?.[0];
}
let dropContainer: DropContainer = {
container: container as any,
instance
};
let res: any;
let upward: any;
// TODO: complete drill down logic
let upward: DropContainer | null = null;
while (container) {
if (ret.container !== container) {
ret.container = container;
ret.instance = this.getClosestNodeInstance(ret.instance, container.id)?.instance;
}
res = this.handleAccept(ret, e);
res = this.handleAccept(dropContainer, e);
if (isLocationData(res)) {
return res;
}
if (res === true) {
return ret;
return dropContainer;
}
if (!res) {
drillDownExcludes.add(container);
if (upward) {
container = upward;
dropContainer = upward;
container = dropContainer.container;
upward = null;
} else if (container.parent) {
container = container.parent;
instance = this.getClosestNodeInstance(dropContainer.instance, container.id)?.instance;
dropContainer = {
container: container as ParentalNode,
instance
};
} else {
return null;
}
} else if (isNode(res)) {
/* else if (res === DRILL_DOWN) {
}/* else if (res === DRILL_DOWN) {
if (!upward) {
upward = container.parent;
container = container.parent;
instance = this.getClosestNodeInstance(dropContainer.instance, container.id)?.instance;
upward = {
container,
instance
};
}
container = this.getNearByContainer(container, drillExcludes, e);
if (!container) {
container = upward;
dropContainer = this.getNearByContainer(dropContainer, drillDownExcludes, e);
if (!dropContainer) {
dropContainer = upward;
upward = null;
}
} else if (isNode(res)) {
// TODO:
}*/
container = res;
upward = null;
}
}
return null;
}
@ -1086,8 +1109,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
*/
handleAccept({ container, instance }: DropContainer, e: LocateEvent) {
const { dragObject } = e;
const document = this.currentDocument!;
if (isRootNode(container)) {
return this.document.checkDropTarget(container, dragObject as any);
return document.checkDropTarget(container, dragObject as any);
}
const meta = (container as Node).componentMeta;
@ -1126,36 +1150,44 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}
// check nesting
return this.document.checkNesting(container, dragObject as any);
return document.checkNesting(container, dragObject as any);
}
/**
*
*/
getNearByContainer(container: ParentalNode, e: LocateEvent) {
/*
getNearByContainer({ container, instance }: DropContainer, drillDownExcludes: Set<Node>, e: LocateEvent) {
const children = container.children;
if (!children || children.length < 1) {
const document = this.project.currentDocument!;
if (!children || children.isEmpty()) {
return null;
}
let nearDistance: any = null;
let nearBy: any = null;
for (let i = 0, l = children.length; i < l; i++) {
let child: any = children[i];
if (!isElementNode(child)) {
for (let i = 0, l = children.size; i < l; i++) {
let child = children.get(i);
if (!child) {
continue;
}
if (hasConditionFlow(child)) {
const bn = child.conditionFlow;
if (child.conditionGroup) {
const bn = child.conditionGroup;
i = bn.index + bn.length - 1;
child = bn.visibleNode;
}
const rect = this.document.computeRect(child);
if (!child.isParental() || drillDownExcludes.has(child)) {
continue;
}
// TODO:
this.findDOMNodes(instance);
this.getComponentInstances(child)
const rect = this.computeRect(child);
if (!rect) {
continue;
}
/*
if (isPointInRect(e, rect)) {
return child;
}
@ -1164,11 +1196,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
if (nearDistance === null || distance < nearDistance) {
nearDistance = distance;
nearBy = child;
}
}*/
}
return nearBy;
*/
}
// #endregion
}

View File

@ -29,7 +29,7 @@ export class Detecting {
}
}
leave(document: DocumentModel) {
leave(document: DocumentModel | undefined) {
if (this.current && this.current.document === document) {
this._current = null;
}

View File

@ -202,8 +202,7 @@ export class Dragon {
private emitter = new EventEmitter();
constructor(readonly designer: Designer) {
}
constructor(readonly designer: Designer) {}
/**
* Quick listen a shell(container element) drag behavior
@ -416,7 +415,8 @@ export class Dragon {
if (!sourceDocument || sourceDocument === document) {
evt.globalX = e.clientX;
evt.globalY = e.clientY;
} else { // event from simulator sandbox
} else {
// event from simulator sandbox
let srcSim: ISimulatorHost | undefined;
const lastSim = lastSensor && isSimulatorHost(lastSensor) ? lastSensor : null;
// check source simulator
@ -517,22 +517,30 @@ export class Dragon {
}
private getMasterSensors(): ISimulatorHost[] {
return this.designer.project.documents
.map((doc) => {
// TODO: not use actived,
if (doc.actived && doc.simulator?.sensorAvailable) {
return doc.simulator;
}
return null;
})
.filter(Boolean) as any;
return Array.from(
new Set(
this.designer.project.documents
.map((doc) => {
// TODO: not use actived,
if (doc.actived && doc.simulator?.sensorAvailable) {
return doc.simulator;
}
return null;
})
.filter(Boolean) as any,
),
);
}
private getSimulators() {
return new Set(this.designer.project.documents.map(doc => doc.simulator));
}
// #region ======== drag and drop helpers ============
private setNativeSelection(enableFlag: boolean) {
setNativeSelection(enableFlag);
this.designer.project.documents.forEach((doc) => {
doc.simulator?.setNativeSelection(enableFlag);
this.getSimulators().forEach((sim) => {
sim?.setNativeSelection(enableFlag);
});
}
@ -541,8 +549,8 @@ export class Dragon {
*/
private setDraggingState(state: boolean) {
cursor.setDragging(state);
this.designer.project.documents.forEach((doc) => {
doc.simulator?.setDraggingState(state);
this.getSimulators().forEach((sim) => {
sim?.setDraggingState(state);
});
}
@ -551,8 +559,8 @@ export class Dragon {
*/
private setCopyState(state: boolean) {
cursor.setCopy(state);
this.designer.project.documents.forEach((doc) => {
doc.simulator?.setCopyState(state);
this.getSimulators().forEach((sim) => {
sim?.setCopyState(state);
});
}
@ -561,8 +569,8 @@ export class Dragon {
*/
private clearState() {
cursor.release();
this.designer.project.documents.forEach((doc) => {
doc.simulator?.clearState();
this.getSimulators().forEach((sim) => {
sim?.clearState();
});
}
// #endregion

View File

@ -1,4 +1,3 @@
export * from './document-view';
export * from './document-model';
export * from './node';
export * from './selection';

View File

@ -28,6 +28,10 @@ export class ExclusiveGroup {
return this.children[0]!;
}
get index() {
return this.firstNode.index;
}
add(node: Node) {
if (node.nextSibling && node.nextSibling.conditionGroup === this) {
const i = this.children.indexOf(node.nextSibling);

View File

@ -12,17 +12,9 @@
background: transparent url(//img.alicdn.com/tfs/TB1xLKQAbj1gK0jSZFuXXcrHpXa-90-90.png) center 30% no-repeat;
padding-top: 50%;
}
.lc-document {
.lc-simulator-shell {
width: 100%;
height: 100%;
&-hidden {
// todo:
display: none;
}
.lc-simulator-shell {
width: 100%;
height: 100%;
}
}
}

View File

@ -11,8 +11,6 @@ export class Project {
private data: ProjectSchema = { version: '1.0.0', componentsMap: [], componentsTree: [] };
@obx.ref canvasDisplayMode: 'exclusive' | 'overview' = 'exclusive';
private _simulator?: ISimulatorHost;
/**
@ -112,14 +110,26 @@ export class Project {
| string,
): any {}
private documentsMap = new Map<string, DocumentModel>();
getDocument(id: string): DocumentModel | null {
return this.documentsMap.get(id) || null;
}
createDocument(data?: RootSchema): DocumentModel {
const doc = new DocumentModel(this, data);
this.documents.push(doc);
this.documentsMap.set(doc.id, doc);
return doc;
}
open(doc?: string | DocumentModel | RootSchema): DocumentModel | null {
if (!doc) {
const got = this.documents.find((item) => item.isBlank());
if (got) {
return got.open();
}
doc = new DocumentModel(this);
this.documents.push(doc);
doc = this.createDocument();
return doc.open();
}
if (typeof doc === 'string') {
@ -130,8 +140,7 @@ export class Project {
const data = this.data.componentsTree.find((data) => data.fileName === doc);
if (data) {
doc = new DocumentModel(this, data);
this.documents.push(doc);
doc = this.createDocument(data);
return doc.open();
}
@ -142,8 +151,7 @@ export class Project {
return doc.open();
}
doc = new DocumentModel(this, doc);
this.documents.push(doc);
doc = this.createDocument(doc);
return doc.open();
}

View File

@ -86,7 +86,6 @@ export class Trunk {
}
registerSetter(type: string, setter: CustomView | RegisteredSetter) {
// console.warn('Trunk.registerSetter is deprecated');
registerSetter(type, setter);
}

View File

@ -25,7 +25,7 @@ class Contents extends Component<{ area: Area }> {
const top: any[] = [];
const bottom: any[] = [];
area.container.items.forEach((item) => {
const content = <div id={`left-area-${item.name}`}>{item.content}</div>;
const content = <div key={`left-area-${item.name}`}>{item.content}</div>;
if (item.align === 'bottom') {
bottom.push(content);
} else {

View File

@ -30,7 +30,7 @@ class Contents extends Component<{ area: Area, itemClassName?: string }> {
return index1 === index2 ? 0 : (index1 > index2 ? 1 : -1);
}).forEach(item => {
const content = (
<div className={itemClassName || ''} id={`top-area-${item.name}`}>
<div className={itemClassName || ''} key={`top-area-${item.name}`}>
{item.content}
</div>
);

View File

@ -82,9 +82,6 @@ export class OutlineMain implements ISensor, ITreeBoard, IScrollable {
e.target = document.elementFromPoint(e.canvasX!, e.canvasY!);
}
// documentModel : 目标文档
e.documentModel = this._designer?.currentDocument;
// 事件已订正
e.fixed = true;
return e;

View File

@ -2,6 +2,7 @@ import LowCodeRenderer from '@ali/lowcode-react-renderer';
import { ReactInstance, Fragment, Component, createElement } from 'react';
import { observer } from '@recore/obx-react';
import { SimulatorRendererContainer, DocumentInstance } from './renderer';
import { Router, Route, Switch } from 'react-router';
import './renderer.less';
// patch cloneElement avoid lost keyProps
@ -38,17 +39,19 @@ export default class SimulatorRendererView extends Component<{ rendererContainer
render() {
const { rendererContainer } = this.props;
return (
<Layout rendererContainer={rendererContainer}>
<Router onChange={(currentPath: string) => {
rendererContainer.redirect(currentPath);
}}>
{rendererContainer.getDocumentInstances().map((instance) => {
return <Route path={instance.document.get('fileName')}>
<Renderer documentInstance={instance} />
</Route>
})}
</Router>
</Layout>
<Router history={rendererContainer.history}>
<Layout rendererContainer={rendererContainer}>
<Switch>
{rendererContainer.documentInstances.map((instance) => (
<Route
path={instance.path}
key={instance.id}
render={(routeProps) => <Renderer documentInstance={instance} {...routeProps} />}
/>
))}
</Switch>
</Layout>
</Router>
);
}
}
@ -106,7 +109,6 @@ class Renderer extends Component<{ documentInstance: DocumentInstance }> {
schema={documentInstance.schema}
components={container.components}
appHelper={container.context}
// context={renderer.context}
designMode={designMode}
suspended={documentInstance.suspended}
self={documentInstance.scope}
@ -116,27 +118,44 @@ class Renderer extends Component<{ documentInstance: DocumentInstance }> {
const leaf = documentInstance.getNode(__id);
viewProps._leaf = leaf;
viewProps._componentName = leaf?.componentName;
let _children = leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children;
let _children = leaf?.isContainer()
? children == null
? []
: Array.isArray(children)
? children
: [children]
: children;
if (props.children && props.children.length) {
if (Array.isArray(props.children)) {
_children = Array.isArray(_children) ? _children.concat(props.children) : props.children.unshift(_children);
_children = Array.isArray(_children)
? _children.concat(props.children)
: props.children.unshift(_children);
} else {
Array.isArray(_children) && _children.push(props.children) || (_children = [_children].push(props.children));
(Array.isArray(_children) && _children.push(props.children)) ||
(_children = [_children].push(props.children));
}
}
// 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动
if (leaf?.isContainer() && (_children == null || !_children.length) && (!viewProps.style || Object.keys(viewProps.style).length == 0)){
_children = <div style={{
height:'66px',
backgroundColor:'#f0f0f0',
borderColor:'#a7b1bd',
border: '1px dotted',
color:'#a7b1bd',
textAlign:'center',
lineHeight:'66px'
}}>
</div>
if (
leaf?.isContainer() &&
(_children == null || !_children.length) &&
(!viewProps.style || Object.keys(viewProps.style).length == 0)
) {
_children = (
<div
style={{
height: '66px',
backgroundColor: '#f0f0f0',
borderColor: '#a7b1bd',
border: '1px dotted',
color: '#a7b1bd',
textAlign: 'center',
lineHeight: '66px',
}}
>
</div>
);
}
if (viewProps._componentName === 'Menu') {
@ -159,17 +178,13 @@ class Renderer extends Component<{ documentInstance: DocumentInstance }> {
console.info('menuprops', viewProps);
}
return createElement(
getDeviceView(Component, device, designMode),
viewProps,
_children,
);
return createElement(getDeviceView(Component, device, designMode), viewProps, _children);
}}
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
documentInstance.mountInstance(schema.id, ref);
}}
//onCompGetCtx={(schema: any, ctx: object) => {
// renderer.mountContext(schema.id, ctx);
// documentInstance.mountContext(schema.id, ctx);
//}}
/>
);

View File

@ -9,8 +9,8 @@ import loader from './utils/loader';
import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes';
import { isESModule, isElement, cursor, setNativeSelection } from '@ali/lowcode-utils';
import { RootSchema, NpmInfo, ComponentSchema, TransformStage } from '@ali/lowcode-types';
// just use types
import { BuiltinSimulatorRenderer, NodeInstance, Component, DocumentModel, Node } from '@ali/lowcode-designer';
import { createMemoryHistory, MemoryHistory } from 'history';
import Slot from './builtin-components/slot';
import Leaf from './builtin-components/leaf';
@ -22,13 +22,13 @@ export class DocumentInstance {
return this._schema;
}
constructor(readonly container: SimulatorRendererContainer, readonly document: DocumentModel) {
this.dispose = host.connect(this, () => {
// sync layout config
private dispose?: () => void;
constructor(readonly container: SimulatorRendererContainer, readonly document: DocumentModel) {
this.dispose = host.autorun(() => {
// sync schema
this._schema = host.document.export(1);
})
this._schema = document.export(1);
});
}
@computed get suspended(): any {
@ -38,6 +38,14 @@ export class DocumentInstance {
return null;
}
get path(): string {
return '/' + this.document.fileName;
}
get id() {
return this.document.id;
}
private unmountIntance(id: string, instance: ReactInstance) {
const instances = this.instancesMap.get(id);
if (instances) {
@ -114,62 +122,6 @@ export class DocumentInstance {
// this.ctxMap.set(id, ctx);
}
createComponent(schema: ComponentSchema): Component | null {
const _schema = {
...schema,
};
_schema.methods = {};
_schema.lifeCycles = {};
const processPropsSchema = (propsSchema: any, propsMap: any): any => {
if (!propsSchema) {
return {};
}
const result = {...propsSchema};
const reg = /^(?:this\.props|props)\.(\S+)$/;
Object.keys(propsSchema).map((key: string) => {
if (propsSchema[key].type === 'JSExpression') {
const { value } = propsSchema[key];
const matched = reg.exec(value);
if (matched) {
const propName = matched[1];
result[key] = propsMap[propName];
}
}
});
return result;
};
const getElement = (componentsMap: any, schema: any, propsMap: any): ReactElement => {
const Com = componentsMap[schema.componentName];
let children = null;
if (schema.children && schema.children.length > 0) {
children = schema.children.map((item: any) => getElement(componentsMap, item, propsMap));
}
const _leaf = this.document.designer.currentDocument?.createNode(schema);
const node = this.document.createNode(schema);
let props = processPropsSchema(schema.props, propsMap);
props = this.document.designer.transformProps(props, node, TransformStage.Init);
props = this.document.designer.transformProps(props, node, TransformStage.Render);
return createElement(Com, {...props, _leaf}, children);
}
const container = this.container;
class Com extends React.Component {
render() {
const componentsMap = container.componentsMap;
let children = null;
if (_schema.children && Array.isArray(_schema.children)) {
children = _schema.children?.map((item:any) => getElement(componentsMap, item, this.props));
}
return createElement(React.Fragment, {}, children);
}
}
return Com;
}
getNode(id: string): Node | null {
return this.document.getNode(id);
}
@ -178,12 +130,14 @@ export class DocumentInstance {
export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
readonly isSimulatorRenderer = true;
private dispose?: () => void;
readonly history: MemoryHistory;
@obx.ref private _documentInstances: DocumentInstance[] = [];
get documentInstances() {
return this._documentInstances;
}
constructor() {
if (!host) {
return;
}
this.dispose = host.connect(this, () => {
// sync layout config
// todo: split with others, not all should recompute
@ -199,6 +153,27 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
// sync device
this._device = host.device;
});
const documentInstanceMap = new Map<string, DocumentInstance>();
host.autorun(() => {
this._documentInstances = host.project.documents.map((doc) => {
let inst = documentInstanceMap.get(doc.id);
if (!inst) {
inst = new DocumentInstance(this, doc);
documentInstanceMap.set(doc.id, inst);
}
return inst;
});
console.info('instances', this._documentInstances);
});
const initialEntry = host.project.currentDocument
? documentInstanceMap.get(host.project.currentDocument.id)!.path
: '/';
this.history = createMemoryHistory({
initialEntries: [initialEntry],
});
this.history.listen((location, action) => {
console.info(location);
});
host.componentsConsumer.consume(async (componentsAsset) => {
if (componentsAsset) {
await this.load(componentsAsset);
@ -208,10 +183,13 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
host.injectionConsumer.consume((data) => {
// sync utils, i18n, contants,... config
this._appContext = {
utils: {},
constants: {
name: 'demo',
utils: {
router: {
push() {},
replace() {},
},
},
constants: {},
};
});
}
@ -255,13 +233,6 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
return loader.load(asset);
}
private documentInstanceMap = new Map<string, DocumentInstance>();
redirect(path: string) {
}
getComponent(componentName: string) {
const paths = componentName.split('.');
const subs: string[] = [];
@ -308,6 +279,66 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
cursor.release();
}
createComponent(schema: ComponentSchema): Component | null {
return null;
// TODO: use ComponentEngine refactor
/*
const _schema = {
...schema,
};
_schema.methods = {};
_schema.lifeCycles = {};
const processPropsSchema = (propsSchema: any, propsMap: any): any => {
if (!propsSchema) {
return {};
}
const result = { ...propsSchema };
const reg = /^(?:this\.props|props)\.(\S+)$/;
Object.keys(propsSchema).map((key: string) => {
if (propsSchema[key].type === 'JSExpression') {
const { value } = propsSchema[key];
const matched = reg.exec(value);
if (matched) {
const propName = matched[1];
result[key] = propsMap[propName];
}
}
});
return result;
};
const getElement = (componentsMap: any, schema: any, propsMap: any): ReactElement => {
const Com = componentsMap[schema.componentName];
let children = null;
if (schema.children && schema.children.length > 0) {
children = schema.children.map((item: any) => getElement(componentsMap, item, propsMap));
}
const _leaf = this.document.designer.currentDocument?.createNode(schema);
const node = this.document.createNode(schema);
let props = processPropsSchema(schema.props, propsMap);
props = this.document.designer.transformProps(props, node, TransformStage.Init);
props = this.document.designer.transformProps(props, node, TransformStage.Render);
return createElement(Com, { ...props, _leaf }, children);
};
const container = this;
class Com extends React.Component {
render() {
const componentsMap = container.componentsMap;
let children = null;
if (_schema.children && Array.isArray(_schema.children)) {
children = _schema.children?.map((item: any) => getElement(componentsMap, item, this.props));
}
return createElement(React.Fragment, {}, children);
}
}
return Com;
*/
}
private _running = false;
run() {
if (this._running) {
@ -321,6 +352,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
document.body.appendChild(container);
container.id = containerId;
}
// ==== compatiable vision
document.documentElement.classList.add('engine-page');
document.body.classList.add('engine-document'); // important! Stylesheet.invoke depends
@ -401,9 +433,12 @@ const builtinComponents = {
Leaf,
};
function buildComponents(libraryMap: LibraryMap, componentsMap: { [componentName: string]: NpmInfo | ComponentType<any> }) {
function buildComponents(
libraryMap: LibraryMap,
componentsMap: { [componentName: string]: NpmInfo | ComponentType<any> },
) {
const components: any = {
...builtinComponents
...builtinComponents,
};
Object.keys(componentsMap).forEach((componentName) => {
let component = componentsMap[componentName];

View File

@ -42,7 +42,7 @@ export class Cursor {
}
}
private addState(state: string) {
addState(state: string) {
if (!this.states.has(state)) {
this.states.add(state);
document.documentElement.classList.add(`lc-cursor-${state}`);