134 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Component, Fragment } from 'react';
import classNames from 'classnames';
import { observer, Focusable, focusTracker } from '@alilc/lowcode-editor-core';
import Area from '../area';
import Panel from '../widget/panel';
@observer
export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }> {
private dispose?: () => void;
private focusing?: Focusable;
private shell: HTMLElement | null = null;
componentDidMount() {
const { area } = this.props;
const triggerClose = (e: any) => {
if (!area.visible) return;
// 当 MouseEvent 的 target 为「插入占位符」时,不关闭当前 panel
if (e.originalEvent?.target?.classList.contains('insertion')) return;
// 假如当前操作 target 祖先节点中有属性 data-keep-visible-while-dragging="true" 代表该 target 所属 panel
// 不希望 target 在 panel 范围内拖拽时关闭 panel
const panelElem = e.originalEvent?.target.closest('div[data-keep-visible-while-dragging="true"]');
if (panelElem) return;
area.setVisible(false);
};
area.skeleton.editor.on('designer.drag', triggerClose);
this.dispose = () => {
area.skeleton.editor.removeListener('designer.drag', triggerClose);
};
this.focusing = focusTracker.create({
range: (e) => {
const target = e.target as HTMLElement;
if (!target) {
return false;
}
if (this.shell?.contains(target)) {
return true;
}
// 点击了 iframe 内容,算失焦
if (document.querySelector('.lc-simulator-content-frame')
.contentWindow.document.documentElement.contains(target)) {
return false;
}
// 点击设置区
if (document.querySelector('.lc-right-area')?.contains(target)) {
return false;
}
// 点击非编辑区域的popup/dialog,插件栏左侧等不触发失焦
if (!document.querySelector('.lc-workbench')?.contains(target)) {
return true;
}
// 排除设置区iframe 之后,都不算失焦
if (document.querySelector('.lc-workbench-body')?.contains(target)) {
return true;
}
const docks = area.current?.getAssocDocks();
if (docks && docks?.length) {
return docks.some(dock => dock.getDOMNode()?.contains(target));
}
return false;
},
onEsc: () => {
this.props.area.setVisible(false);
},
onBlur: () => {
// debugger
this.props.area.setVisible(false);
},
});
this.onEffect();
}
onEffect() {
const { area } = this.props;
if (area.visible) {
this.focusing?.active();
// 关闭当前fixed区域的面板
// TODO: 看看有没有更合适的地方
const fixedContainer = area?.skeleton?.leftFixedArea?.container;
const currentFixed = fixedContainer?.current;
if (currentFixed) {
fixedContainer.unactive(currentFixed);
}
} else {
this.focusing?.suspense();
}
}
componentDidUpdate() {
this.onEffect();
}
componentWillUnmount() {
this.focusing?.purge();
this.dispose?.();
}
render() {
const { area } = this.props;
const width = area.current?.config.props?.width;
const style = width ? {
width,
} : undefined;
return (
<div
ref={(ref) => { this.shell = ref; }}
className={classNames('lc-left-float-pane', {
'lc-area-visible': area.visible,
})}
style={style}
>
<Contents area={area} />
</div>
);
}
}
@observer
class Contents extends Component<{ area: Area<any, Panel> }> {
render() {
const { area } = this.props;
return (
<Fragment>
{area.container.items.map((panel) => panel.content)}
</Fragment>
);
}
}