mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-10 01:48:18 +00:00
384 lines
11 KiB
TypeScript
384 lines
11 KiB
TypeScript
import { Component, ReactElement } from 'react';
|
||
import { Icon } from '@alifd/next';
|
||
import classNames from 'classnames';
|
||
import { Title, observer, Tip, globalContext } from '@alilc/lowcode-editor-core';
|
||
import { DockProps } from '../../types';
|
||
import { PanelDock } from '../../widget/panel-dock';
|
||
import { composeTitle } from '../../widget/utils';
|
||
import { WidgetContainer } from '../../widget/widget-container';
|
||
import { Panel } from '../../widget/panel';
|
||
import { IWidget } from '../../widget/widget';
|
||
import { SkeletonEvents } from '../../skeleton';
|
||
import DraggableLine from '../draggable-line';
|
||
import PanelOperationRow from './panel-operation-row';
|
||
|
||
import './index.less';
|
||
|
||
export function DockView({ title, icon, description, size, className, onClick }: DockProps) {
|
||
return (
|
||
<Title
|
||
title={composeTitle(title, icon, description)}
|
||
className={classNames('lc-dock', className, {
|
||
[`lc-dock-${size}`]: size,
|
||
})}
|
||
onClick={onClick}
|
||
/>
|
||
);
|
||
}
|
||
|
||
function HelpTip({ tip }: any) {
|
||
if (tip && tip.url) {
|
||
return (
|
||
<div>
|
||
<a href={tip.url} target="_blank" rel="noopener noreferrer">
|
||
<Icon type="help" size="small" className="lc-help-tip" />
|
||
</a>
|
||
<Tip>{tip.content}</Tip>
|
||
</div>
|
||
);
|
||
}
|
||
return (
|
||
<div>
|
||
<Icon type="help" size="small" className="lc-help-tip" />
|
||
<Tip>{tip.content}</Tip>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
@observer
|
||
export class PanelDockView extends Component<DockProps & { dock: PanelDock }> {
|
||
private lastActived = false;
|
||
|
||
componentDidMount() {
|
||
this.checkActived();
|
||
}
|
||
|
||
componentDidUpdate() {
|
||
this.checkActived();
|
||
}
|
||
|
||
checkActived() {
|
||
const { dock } = this.props;
|
||
if (dock.actived !== this.lastActived) {
|
||
this.lastActived = dock.actived;
|
||
if (this.lastActived) {
|
||
dock.skeleton.postEvent(SkeletonEvents.PANEL_DOCK_ACTIVE, dock.name, dock);
|
||
} else {
|
||
dock.skeleton.postEvent(SkeletonEvents.PANEL_DOCK_UNACTIVE, dock.name, dock);
|
||
}
|
||
}
|
||
}
|
||
|
||
render() {
|
||
const { dock, className, onClick, ...props } = this.props;
|
||
return DockView({
|
||
...props,
|
||
className: classNames(className, {
|
||
actived: dock.actived,
|
||
}),
|
||
onClick: () => {
|
||
onClick && onClick();
|
||
dock.togglePanel();
|
||
},
|
||
});
|
||
}
|
||
}
|
||
|
||
export class DialogDockView extends Component {}
|
||
|
||
export class DraggableLineView extends Component<{ panel: Panel }> {
|
||
private shell: any;
|
||
private defaultWidth: number;
|
||
|
||
private getDefaultWidth() {
|
||
const configWidth = this.props.panel?.config.props?.width;
|
||
if (configWidth) {
|
||
return configWidth;
|
||
}
|
||
if (this.defaultWidth) {
|
||
return this.defaultWidth;
|
||
}
|
||
const containerRef = this.shell?.getParent();
|
||
if (containerRef) {
|
||
this.defaultWidth = containerRef.offsetWidth;
|
||
return this.defaultWidth;
|
||
}
|
||
return 300;
|
||
}
|
||
|
||
onDrag(value: number) {
|
||
const defaultWidth = this.getDefaultWidth();
|
||
const width = defaultWidth + value;
|
||
|
||
const containerRef = this.shell?.getParent();
|
||
if (containerRef) {
|
||
containerRef.style.width = `${width}px`;
|
||
}
|
||
|
||
// 抛出事件,对于有些需要 panel 插件随着 度变化进行再次渲染的,由panel插件内部监听事件实现
|
||
const workspace = globalContext.get('workspace');
|
||
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
|
||
editor?.eventBus.emit('dockpane.drag', width);
|
||
}
|
||
|
||
onDragChange(type: 'start' | 'end') {
|
||
const workspace = globalContext.get('workspace');
|
||
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
|
||
editor?.eventBus.emit('dockpane.dragchange', type);
|
||
// builtinSimulator 屏蔽掉 鼠标事件
|
||
editor?.eventBus.emit('designer.builtinSimulator.disabledEvents', type === 'start');
|
||
}
|
||
|
||
render() {
|
||
// left fixed 下不允许改变宽度
|
||
// 默认 关闭,通过配置开启
|
||
const enableDrag = this.props.panel.config.props?.enableDrag;
|
||
const isRightArea = this.props.panel.config?.area === 'rightArea';
|
||
if (isRightArea || !enableDrag || this.props.panel?.parent?.name === 'leftFixedArea') {
|
||
return null;
|
||
}
|
||
return (
|
||
<DraggableLine
|
||
ref={(ref) => {
|
||
this.shell = ref;
|
||
}}
|
||
position="right"
|
||
className="lc-engine-slate-draggable-line-right"
|
||
onDrag={(e) => this.onDrag(e)}
|
||
onDragStart={() => this.onDragChange('start')}
|
||
onDragEnd={() => this.onDragChange('end')}
|
||
maxIncrement={500}
|
||
maxDecrement={0}
|
||
// TODO: 优化
|
||
// maxIncrement={dock.getMaxWidth() - this.cachedSize.width}
|
||
// maxDecrement={this.cachedSize.width - dock.getWidth()}
|
||
/>
|
||
);
|
||
}
|
||
}
|
||
|
||
@observer
|
||
export class TitledPanelView extends Component<{ panel: Panel; area?: string }> {
|
||
private lastVisible = false;
|
||
|
||
componentDidMount() {
|
||
this.checkVisible();
|
||
}
|
||
|
||
componentDidUpdate() {
|
||
this.checkVisible();
|
||
}
|
||
|
||
checkVisible() {
|
||
const { panel } = this.props;
|
||
const currentVisible = panel.inited && panel.visible;
|
||
if (currentVisible !== this.lastVisible) {
|
||
this.lastVisible = currentVisible;
|
||
if (this.lastVisible) {
|
||
panel.skeleton.postEvent(SkeletonEvents.PANEL_SHOW, panel.name, panel);
|
||
} else {
|
||
panel.skeleton.postEvent(SkeletonEvents.PANEL_HIDE, panel.name, panel);
|
||
}
|
||
}
|
||
}
|
||
|
||
render() {
|
||
const { panel, area } = this.props;
|
||
if (!panel.inited) {
|
||
return null;
|
||
}
|
||
const workspace = globalContext.get('workspace');
|
||
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
|
||
const panelName = area ? `${area}-${panel.name}` : panel.name;
|
||
editor?.eventBus.emit('skeleton.panel.toggle', {
|
||
name: panelName || '',
|
||
status: panel.visible ? 'show' : 'hide',
|
||
});
|
||
return (
|
||
<div
|
||
className={classNames('lc-titled-panel', {
|
||
hidden: !panel.visible,
|
||
})}
|
||
id={panelName}
|
||
data-keep-visible-while-dragging={panel.config.props?.keepVisibleWhileDragging}
|
||
>
|
||
<PanelOperationRow panel={panel} />
|
||
<PanelTitle panel={panel} />
|
||
<div className="lc-panel-body">{panel.body}</div>
|
||
<DraggableLineView panel={panel} />
|
||
</div>
|
||
);
|
||
}
|
||
}
|
||
|
||
@observer
|
||
export class PanelView extends Component<{
|
||
panel: Panel;
|
||
area?: string;
|
||
hideOperationRow?: boolean;
|
||
hideDragLine?: boolean;
|
||
}> {
|
||
private lastVisible = false;
|
||
|
||
componentDidMount() {
|
||
this.checkVisible();
|
||
}
|
||
|
||
componentDidUpdate() {
|
||
this.checkVisible();
|
||
}
|
||
|
||
checkVisible() {
|
||
const { panel } = this.props;
|
||
const currentVisible = panel.inited && panel.visible;
|
||
if (currentVisible !== this.lastVisible) {
|
||
this.lastVisible = currentVisible;
|
||
if (this.lastVisible) {
|
||
panel.skeleton.postEvent(SkeletonEvents.PANEL_SHOW, panel.name, panel);
|
||
// FIXME! remove this line
|
||
panel.skeleton.postEvent('leftPanel.show' as any, panel.name, panel);
|
||
} else {
|
||
panel.skeleton.postEvent(SkeletonEvents.PANEL_HIDE, panel.name, panel);
|
||
// FIXME! remove this line
|
||
panel.skeleton.postEvent('leftPanel.hide' as any, panel.name, panel);
|
||
}
|
||
}
|
||
}
|
||
|
||
render() {
|
||
const { panel, area, hideOperationRow, hideDragLine } = this.props;
|
||
if (!panel.inited) {
|
||
return null;
|
||
}
|
||
const workspace = globalContext.get('workspace');
|
||
const editor = workspace.isActive ? workspace.window.editor : globalContext.get('editor');
|
||
const panelName = area ? `${area}-${panel.name}` : panel.name;
|
||
editor?.eventBus.emit('skeleton.panel.toggle', {
|
||
name: panelName || '',
|
||
status: panel.visible ? 'show' : 'hide',
|
||
});
|
||
return (
|
||
<div
|
||
className={classNames('lc-panel', {
|
||
hidden: !panel.visible,
|
||
})}
|
||
id={panelName}
|
||
data-keep-visible-while-dragging={panel.config.props?.keepVisibleWhileDragging}
|
||
>
|
||
{!hideOperationRow && <PanelOperationRow panel={panel} />}
|
||
{panel.body}
|
||
{!hideDragLine && <DraggableLineView panel={panel} />}
|
||
</div>
|
||
);
|
||
}
|
||
}
|
||
|
||
@observer
|
||
export class TabsPanelView extends Component<{ container: WidgetContainer<Panel> }> {
|
||
render() {
|
||
const { container } = this.props;
|
||
const titles: ReactElement[] = [];
|
||
const contents: ReactElement[] = [];
|
||
container.items.forEach((item: any) => {
|
||
titles.push(<PanelTitle key={item.id} panel={item} className="lc-tab-title" />);
|
||
contents.push(<PanelView key={item.id} panel={item} hideOperationRow hideDragLine />);
|
||
});
|
||
|
||
return (
|
||
<div className="lc-tabs">
|
||
<div
|
||
className="lc-tabs-title"
|
||
onClick={(e) => {
|
||
const shell = e.currentTarget;
|
||
const t = e.target as Element;
|
||
let elt = shell.firstElementChild;
|
||
while (elt) {
|
||
if (elt.contains(t)) {
|
||
break;
|
||
}
|
||
elt = elt.nextElementSibling;
|
||
}
|
||
if (elt) {
|
||
container.active((elt as any).dataset.name);
|
||
}
|
||
}}
|
||
>
|
||
{titles}
|
||
</div>
|
||
<div className="lc-tabs-content">{contents}</div>
|
||
</div>
|
||
);
|
||
}
|
||
}
|
||
|
||
@observer
|
||
class PanelTitle extends Component<{ panel: Panel; className?: string }> {
|
||
render() {
|
||
const { panel, className } = this.props;
|
||
return (
|
||
<div
|
||
className={classNames('lc-panel-title', className, {
|
||
actived: panel.actived,
|
||
})}
|
||
data-name={panel.name}
|
||
>
|
||
<Title title={panel.title || panel.name} />
|
||
{panel.help ? <HelpTip tip={panel.help} /> : null}
|
||
</div>
|
||
);
|
||
}
|
||
}
|
||
|
||
@observer
|
||
export class WidgetView extends Component<{ widget: IWidget }> {
|
||
private lastVisible = false;
|
||
private lastDisabled: boolean | undefined = false;
|
||
|
||
componentDidMount() {
|
||
this.checkVisible();
|
||
this.checkDisabled();
|
||
}
|
||
|
||
componentDidUpdate() {
|
||
this.checkVisible();
|
||
this.checkDisabled();
|
||
}
|
||
|
||
checkVisible() {
|
||
const { widget } = this.props;
|
||
const currentVisible = widget.visible;
|
||
if (currentVisible !== this.lastVisible) {
|
||
this.lastVisible = currentVisible;
|
||
if (this.lastVisible) {
|
||
widget.skeleton.postEvent(SkeletonEvents.WIDGET_SHOW, widget.name, widget);
|
||
} else {
|
||
widget.skeleton.postEvent(SkeletonEvents.WIDGET_SHOW, widget.name, widget);
|
||
}
|
||
}
|
||
}
|
||
|
||
checkDisabled() {
|
||
const { widget } = this.props;
|
||
const currentDisabled = widget.disabled;
|
||
if (currentDisabled !== this.lastDisabled) {
|
||
this.lastDisabled = currentDisabled;
|
||
if (this.lastDisabled) {
|
||
widget.skeleton.postEvent(SkeletonEvents.WIDGET_DISABLE, widget.name, widget);
|
||
} else {
|
||
widget.skeleton.postEvent(SkeletonEvents.WIDGET_ENABLE, widget.name, widget);
|
||
}
|
||
}
|
||
}
|
||
|
||
render() {
|
||
const { widget } = this.props;
|
||
if (!widget.visible) {
|
||
return null;
|
||
}
|
||
if (widget.disabled) {
|
||
return <div className="lc-widget-disabled">{widget.body}</div>;
|
||
}
|
||
return widget.body;
|
||
}
|
||
}
|