feat: 支持节点拖拽时被放入容器的视觉反馈, 通过 enableReactiveContainer 配置项

This commit is contained in:
力皓 2021-05-31 21:01:42 +08:00
parent 2c05bd3a78
commit 6a308ba81d
4 changed files with 128 additions and 1 deletions

View File

@ -0,0 +1,119 @@
import * as React from 'react';
import { Component, Fragment, ReactElement, PureComponent } from 'react';
import classNames from 'classnames';
import { computed, observer, Title, globalLocale } from '@ali/lowcode-editor-core';
import { I18nData, isI18nData, TitleContent } from '@ali/lowcode-types';
import { DropLocation } from '../../designer';
import { BuiltinSimulatorHost } from '../../builtin-simulator/host';
import { ParentalNode } from '../../document/node';
export class BorderContainerInstance extends PureComponent<{
title: TitleContent;
rect: DOMRect | null;
scale: number;
scrollX: number;
scrollY: number;
}> {
render() {
const { title, rect, scale, scrollX, scrollY } = this.props;
if (!rect) {
return null;
}
const style = {
width: rect.width * scale,
height: rect.height * scale,
transform: `translate(${(scrollX + rect.left) * scale}px, ${(scrollY + rect.top) * scale}px)`,
};
const className = classNames('lc-borders lc-borders-detecting');
return (
<div className={className} style={style}>
<Title title={title} className="lc-borders-title" />
</div>
);
}
}
function getTitle(title: string | I18nData | ReactElement) {
if (typeof title === 'string') return title;
if (isI18nData(title)) {
const locale = globalLocale.getLocale() || 'zh-CN';
return `将放入到此${title[locale]}`;
}
return '';
}
@observer
export class BorderContainer extends Component<{
host: BuiltinSimulatorHost,
}, {
target?: ParentalNode,
}> {
state = {} as any;
@computed get scale() {
return this.props.host.viewport.scale;
}
@computed get scrollX() {
return this.props.host.viewport.scrollX;
}
@computed get scrollY() {
return this.props.host.viewport.scrollY;
}
componentDidMount() {
const { host } = this.props;
host.designer.editor.on('designer.dropLocation.change', (loc: DropLocation) => {
let { target } = this.state;
if (target === loc?.target) return;
this.setState({
target: loc?.target,
});
});
}
render() {
const { host } = this.props;
const { target } = this.state;
if (target == undefined) {
return null;
}
const instances = host.getComponentInstances(target!);
if (!instances || instances.length < 1) {
return null;
}
if (instances.length === 1) {
return (
<BorderContainerInstance
key="line-h"
title={getTitle(target.componentMeta.title)}
scale={this.scale}
scrollX={this.scrollX}
scrollY={this.scrollY}
rect={host.computeComponentInstanceRect(instances[0], target.componentMeta.rootSelector)}
/>
);
}
return (
<Fragment>
{instances.map((inst, i) => (
<BorderContainerInstance
key={`line-h-${i}`}
title={getTitle(target.componentMeta.title)}
scale={this.scale}
scrollX={this.scrollX}
scrollY={this.scrollY}
rect={host.computeComponentInstanceRect(inst, target.componentMeta.rootSelector)}
/>
))}
</Fragment>
);
}
}

View File

@ -1,6 +1,7 @@
import React, { Component } from 'react';
import { observer } from '@ali/lowcode-editor-core';
import { observer, engineConfig } from '@ali/lowcode-editor-core';
import { BorderDetecting } from './border-detecting';
import { BorderContainer } from './border-container';
import { BuiltinSimulatorHost } from '../host';
import { BorderSelecting } from './border-selecting';
import BorderResizing from './border-resizing';
@ -25,6 +26,7 @@ export class BemTools extends Component<{ host: BuiltinSimulatorHost }> {
<div className="lc-bem-tools" style={{ transform: `translate(${-scrollX * scale}px,${-scrollY * scale}px)` }}>
<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} />
<BorderResizing key="resizing" host={host} />
{

View File

@ -246,6 +246,7 @@ export class Designer {
this._dropLocation.document.internalSetDropLocation(null);
}
this._dropLocation = loc;
this.postEvent('dropLocation.change', loc);
loc.document.internalSetDropLocation(loc);
this.activeTracker.track({ node: loc.target, detail: loc.detail });
return loc;
@ -258,6 +259,7 @@ export class Designer {
if (this._dropLocation) {
this._dropLocation.document.internalSetDropLocation(null);
}
this.postEvent('dropLocation.change', undefined);
this._dropLocation = undefined;
}

View File

@ -187,6 +187,10 @@ interface EngineOptions {
deviceMapper?: {
transform: (originalDevice: string) => string;
};
/**
*
*/
enableReactiveContainer?: boolean;
[key: string]: any;
}