mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-15 18:58:11 +00:00
feat: 支持节点拖拽时被放入容器的视觉反馈, 通过 enableReactiveContainer 配置项
This commit is contained in:
parent
2c05bd3a78
commit
6a308ba81d
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
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 { BorderDetecting } from './border-detecting';
|
||||||
|
import { BorderContainer } from './border-container';
|
||||||
import { BuiltinSimulatorHost } from '../host';
|
import { BuiltinSimulatorHost } from '../host';
|
||||||
import { BorderSelecting } from './border-selecting';
|
import { BorderSelecting } from './border-selecting';
|
||||||
import BorderResizing from './border-resizing';
|
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)` }}>
|
<div className="lc-bem-tools" style={{ transform: `translate(${-scrollX * scale}px,${-scrollY * scale}px)` }}>
|
||||||
<BorderDetecting key="hovering" host={host} />
|
<BorderDetecting key="hovering" host={host} />
|
||||||
<BorderSelecting key="selecting" host={host} />
|
<BorderSelecting key="selecting" host={host} />
|
||||||
|
{ engineConfig.get('enableReactiveContainer') && <BorderContainer key="reactive-container-border" host={host} /> }
|
||||||
<InsertionView key="insertion" host={host} />
|
<InsertionView key="insertion" host={host} />
|
||||||
<BorderResizing key="resizing" host={host} />
|
<BorderResizing key="resizing" host={host} />
|
||||||
{
|
{
|
||||||
|
|||||||
@ -246,6 +246,7 @@ export class Designer {
|
|||||||
this._dropLocation.document.internalSetDropLocation(null);
|
this._dropLocation.document.internalSetDropLocation(null);
|
||||||
}
|
}
|
||||||
this._dropLocation = loc;
|
this._dropLocation = loc;
|
||||||
|
this.postEvent('dropLocation.change', loc);
|
||||||
loc.document.internalSetDropLocation(loc);
|
loc.document.internalSetDropLocation(loc);
|
||||||
this.activeTracker.track({ node: loc.target, detail: loc.detail });
|
this.activeTracker.track({ node: loc.target, detail: loc.detail });
|
||||||
return loc;
|
return loc;
|
||||||
@ -258,6 +259,7 @@ export class Designer {
|
|||||||
if (this._dropLocation) {
|
if (this._dropLocation) {
|
||||||
this._dropLocation.document.internalSetDropLocation(null);
|
this._dropLocation.document.internalSetDropLocation(null);
|
||||||
}
|
}
|
||||||
|
this.postEvent('dropLocation.change', undefined);
|
||||||
this._dropLocation = undefined;
|
this._dropLocation = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -187,6 +187,10 @@ interface EngineOptions {
|
|||||||
deviceMapper?: {
|
deviceMapper?: {
|
||||||
transform: (originalDevice: string) => string;
|
transform: (originalDevice: string) => string;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* 开启拖拽组件时,即将被放入的容器是否有视觉反馈
|
||||||
|
*/
|
||||||
|
enableReactiveContainer?: boolean;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user