167 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. 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 '@ali/lowcode-editor-core';
import { Button, Icon } from '@alifd/next';
import { IconFix } from '../icons/fix';
import Area from '../area';
import Panel from '../widget/panel';
@observer
export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }> {
shouldComponentUpdate() {
return false;
}
private dispose?: () => void;
private focusing?: Focusable;
private shell: HTMLElement | null = null;
componentDidMount() {
const { area } = this.props;
const triggerClose = () => area.setVisible(false);
area.skeleton.editor.on('designer.dragstart', triggerClose);
this.dispose = () => {
area.skeleton.editor.removeListener('designer.dragstart', 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;
}
// 点击非编辑区域的 popup / dialog 等,不触发失焦
if (!document.querySelector('.lc-workbench')?.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?.();
}
// 固定
setFixed() {
const { area } = this.props;
const { current } = area;
if (!current) {
return;
}
area.skeleton.leftFloatArea.remove(current);
area.skeleton.leftFixedArea.add(current);
area.skeleton.leftFixedArea.container.active(current);
}
render() {
const { area } = this.props;
const width = area.current?.config.props?.width;
// can be set fixed by default
let canSetFixed = true;
if (area.current?.config.props?.canSetFixed === false) {
canSetFixed = false;
}
const hideTitleBar = area.current?.config.props?.hideTitleBar;
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}
>
{
!hideTitleBar && (
<Fragment>
{
canSetFixed && (
<Button
text
className="lc-pane-icon-fix"
onClick={this.setFixed.bind(this)}
>
<IconFix />
</Button>
)
}
<Button
text
className="lc-pane-icon-close"
onClick={() => {
area.setVisible(false);
}}
>
<Icon type="close" />
</Button>
</Fragment>
)
}
<Contents area={area} />
</div>
);
}
}
@observer
class Contents extends Component<{ area: Area<any, Panel> }> {
shouldComponentUpdate() {
return false;
}
render() {
const { area } = this.props;
return (
<Fragment>
{area.container.items.map((panel) => panel.content)}
</Fragment>
);
}
}