220 lines
5.5 KiB
TypeScript

import React, { PureComponent, Fragment } from 'react';
import { Balloon, Badge, Dialog } from '@alifd/next';
import Editor from '@ali/lowcode-editor-framework';
import {
PluginConfig,
PluginClass,
} from '@ali/lowcode-editor-framework/lib/definitions';
import TopIcon from '../TopIcon';
import './index.scss';
export interface TopPluginProps {
active?: boolean;
config: PluginConfig;
disabled?: boolean;
editor: Editor;
locked?: boolean;
marked?: boolean;
onClick?: () => void;
pluginClass: PluginClass | undefined;
}
export interface TopPluginState {
dialogVisible: boolean;
}
export default class TopPlugin extends PureComponent<
TopPluginProps,
TopPluginState
> {
static displayName = 'LowcodeTopPlugin';
static defaultProps = {
active: false,
config: {},
disabled: false,
marked: false,
locked: false,
onClick: (): void => {},
};
constructor(props, context) {
super(props, context);
this.state = {
dialogVisible: false,
};
}
componentDidMount(): void {
const { config, editor } = this.props;
const pluginKey = config && config.pluginKey;
if (editor && pluginKey) {
editor.on(`${pluginKey}.dialog.show`, this.handleShow);
editor.on(`${pluginKey}.dialog.close`, this.handleClose);
}
}
componentWillUnmount(): void {
const { config, editor } = this.props;
const pluginKey = config && config.pluginKey;
if (editor && pluginKey) {
editor.off(`${pluginKey}.dialog.show`, this.handleShow);
editor.off(`${pluginKey}.dialog.close`, this.handleClose);
}
}
handleShow = (): void => {
const { disabled, config, onClick, editor } = this.props;
const pluginKey = config && config.pluginKey;
if (disabled || !pluginKey) return;
this.handleOpen();
// 考虑到弹窗情况,延时发送消息
setTimeout((): void => {
editor.emit(`${pluginKey}.plugin.activate`);
}, 0);
onClick && onClick();
};
handleClose = (): void => {
const { config, editor } = this.props;
const pluginKey = config && config.pluginKey;
const plugin = editor.plugins && editor.plugins[pluginKey];
if (plugin) {
plugin.close().then((): void => {
this.setState({
dialogVisible: false,
});
});
}
};
handleOpen = (): void => {
// todo dialog类型的插件初始时拿不动插件实例
this.setState({
dialogVisible: true,
});
};
renderIcon = (clickCallback): React.ReactNode => {
const {
active,
disabled,
marked,
locked,
config,
onClick,
editor,
} = this.props;
const { pluginKey, props } = config || {};
const { icon, title } = props || {};
const node = (
<TopIcon
className={`lowcode-top-plugin ${pluginKey}`}
active={active}
disabled={disabled}
locked={locked}
icon={icon}
title={title}
onClick={(): void => {
if (disabled) return;
// 考虑到弹窗情况,延时发送消息
setTimeout((): void => {
editor.emit(`${pluginKey}.plugin.activate`);
}, 0);
clickCallback && clickCallback();
onClick && onClick();
}}
/>
);
return marked ? <Badge dot>{node}</Badge> : node;
};
render(): React.ReactNode {
const {
active,
marked,
locked,
disabled,
config,
editor,
pluginClass: Comp,
} = this.props;
const { pluginKey, pluginProps, props, type } = config || {};
const { onClick, title } = props || {};
const { dialogVisible } = this.state;
if (!pluginKey || !type) return null;
const node = Comp ? (
<Comp
editor={editor}
active={active}
locked={locked}
disabled={disabled}
config={config}
onClick={(): void => {
onClick && onClick.call(null, editor);
}}
{...pluginProps}
/>
) : null;
switch (type) {
case 'LinkIcon':
return (
<a {...props.linkProps}>
{this.renderIcon((): void => {
onClick && onClick.call(null, editor);
})}
</a>
);
case 'Icon':
return this.renderIcon((): void => {
onClick && onClick.call(null, editor);
});
case 'DialogIcon':
return (
<Fragment>
{this.renderIcon((): void => {
onClick && onClick.call(null, editor);
this.handleOpen();
})}
<Dialog
onOk={(): void => {
editor.emit(`${pluginKey}.dialog.onOk`);
this.handleClose();
}}
onCancel={this.handleClose}
onClose={this.handleClose}
title={title}
style={{
width: 500,
...(props.dialogProps && props.dialogProps.style),
}}
{...props.dialogProps}
visible={dialogVisible}
>
{node}
</Dialog>
</Fragment>
);
case 'BalloonIcon':
return (
<Balloon
trigger={this.renderIcon((): void => {
onClick && onClick.call(null, editor);
})}
triggerType={['click', 'hover']}
{...props.balloonProps}
>
{node}
</Balloon>
);
case 'Custom':
return marked ? <Badge dot>{node}</Badge> : node;
default:
return null;
}
}
}