daily tag

This commit is contained in:
下羊 2020-03-15 19:13:39 +08:00
parent dd0ee40b8e
commit 7f90b0baa5
28 changed files with 497 additions and 427 deletions

View File

@ -4,9 +4,13 @@ module.exports = deepmerge(tslint, {
rules: { rules: {
"global-require": 0, "global-require": 0,
"comma-dangle": 0, "comma-dangle": 0,
"no-unused-expressions": 0,
"object-shorthand": 0,
"jsx-a11y/anchor-has-content": 0,
"react/sort-comp": 0, "react/sort-comp": 0,
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx", "ts"] }], "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx", "ts"] }],
"@typescript-eslint/interface-name-prefix": 0, "@typescript-eslint/interface-name-prefix": 0,
"@typescript-eslint/no-explicit-any": 0 "@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/explicit-member-accessibility": 0
}, },
}); });

View File

@ -5,7 +5,10 @@ export default {
title: 'fusion组件库', title: 'fusion组件库',
package: '@alifd/next', package: '@alifd/next',
version: '1.19.18', version: '1.19.18',
urls: ['https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.js', 'https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.css'], urls: [
'https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.js',
'https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.css'
],
library: 'Next' library: 'Next'
} }
}, },
@ -13,114 +16,137 @@ export default {
Button: { Button: {
componentName: 'Button', componentName: 'Button',
title: '按钮', title: '按钮',
devMode:'proCode', devMode: 'proCode',
npm: { npm: {
package: '@alifd/next', package: '@alifd/next',
version: '1.19.18', version: '1.19.18',
destructuring: true, destructuring: true,
exportName: 'Button' exportName: 'Button'
}, },
props: [{ props: [
name: 'type', {
propType: 'string'
}, {
name: 'children',
propType: 'string'
}],
configure: {
props: [{
name: 'type', name: 'type',
setter: { propType: 'string'
componentName: 'Input' },
} {
}, {
name: 'children', name: 'children',
setter: { propType: 'string'
componentName: 'Input' }
],
configure: {
props: [
{
name: 'type',
setter: {
componentName: 'Input'
}
},
{
name: 'children',
setter: {
componentName: 'Input'
}
} }
}] ]
} }
}, },
Input: { Input: {
componentName: 'Input', componentName: 'Input',
title: '输入框', title: '输入框',
devMode:'proCode', devMode: 'proCode',
npm: { npm: {
package: '@alifd/next', package: '@alifd/next',
version: '1.19.18', version: '1.19.18',
destructuring: true, destructuring: true,
exportName: 'Input' exportName: 'Input'
}, },
props: [{ props: [
name: 'placeholder', {
propType: 'string'
}],
configure: {
props: [{
name: 'placeholder', name: 'placeholder',
setter: { propType: 'string'
componentName: 'Input' }
],
configure: {
props: [
{
name: 'placeholder',
setter: {
componentName: 'Input'
}
} }
}] ]
} }
} }
}, },
componentList: [{ componentList: [
title: '基础', {
icon: '', title: '基础',
children: [{
componentName: 'Button',
title: '按钮',
icon: '', icon: '',
package: '@alife/next', children: [
snippets: [{ {
title: 'private',
screenshort: '',
schema: {
componentName: 'Button', componentName: 'Button',
props: { title: '按钮',
type: 'primary' icon: '',
}, package: '@alife/next',
children: 'Primary' snippets: [
{
title: 'private',
screenshort: '',
schema: {
componentName: 'Button',
props: {
type: 'primary'
},
children: 'Primary'
}
},
{
title: 'secondary',
screenshort: '',
schema: {
componentName: 'Button',
props: {
type: 'secondary'
},
children: 'secondary'
}
},
{
title: 'normal',
screenshort: '',
schema: {
componentName: 'Button',
props: {
type: 'normal'
},
children: 'normal'
}
}
]
} }
}, { ]
title: 'secondary', },
screenshort: '', {
schema: { title: '表单',
componentName: 'Button',
props: {
type: 'secondary'
},
children: 'secondary'
}
}, {
title: 'normal',
screenshort: '',
schema: {
componentName: 'Button',
props: {
type: 'normal'
},
children: 'normal'
}
}]
}]
}, {
title: '表单',
icon: '',
children: [{
componentName: 'Input',
title: '输入框',
icon: '', icon: '',
package: '@alife/next', children: [
snippets: [{ {
title: '普通',
screenshort: '',
schema: {
componentName: 'Input', componentName: 'Input',
props: {} title: '输入框',
icon: '',
package: '@alife/next',
snippets: [
{
title: '普通',
screenshort: '',
schema: {
componentName: 'Input',
props: {}
}
}
]
} }
}] ]
}] }
}] ]
}; };

View File

@ -4,13 +4,17 @@ import { registerSetter } from '../../../plugin-settings/src';
import { createElement } from 'react'; import { createElement } from 'react';
registerSetter('ClassNameSetter', () => { registerSetter('ClassNameSetter', () => {
return createElement('div', { return createElement(
className: 'lc-block-setter' 'div',
}, '这里是类名绑定'); {
className: 'lc-block-setter'
},
'这里是类名绑定'
);
}); });
registerSetter('EventsSetter', Input); registerSetter('EventsSetter', Input);
registerSetter('StringSetter', { component: Input, props: { placeholder: "请输入" } }); registerSetter('StringSetter', { component: Input, props: { placeholder: '请输入' } });
registerSetter('NumberSetter', NumberSetter as any); registerSetter('NumberSetter', NumberSetter as any);

View File

@ -111,7 +111,7 @@ export default {
title: 'icon', title: 'icon',
icon: 'dengpao', icon: 'dengpao',
onClick(editor) { onClick(editor) {
alert(`icon addon invoke, current activeKey: ${ editor.activeKey}`); alert(`icon addon invoke, current activeKey: ${editor.activeKey}`);
} }
}, },
config: {}, config: {},
@ -128,8 +128,8 @@ export default {
title: '组件库' title: '组件库'
}, },
config: { config: {
package: "@ali/iceluna-addon-component-list", package: '@ali/iceluna-addon-component-list',
version: "^1.0.4" version: '^1.0.4'
}, },
pluginProps: { pluginProps: {
disableAppComponent: true disableAppComponent: true
@ -218,7 +218,7 @@ export default {
title: 'icon', title: 'icon',
icon: 'dengpao', icon: 'dengpao',
onClick(editor) { onClick(editor) {
alert(`icon addon invoke, current activeKey: ${ editor.activeKey}`); alert(`icon addon invoke, current activeKey: ${editor.activeKey}`);
} }
}, },
config: {}, config: {},
@ -234,52 +234,52 @@ export default {
version: '^1.0.0' version: '^1.0.0'
}, },
pluginProps: {} pluginProps: {}
},
{
pluginKey: 'rightPanel1',
type: 'TabPanel',
props: {
title: '样式'
},
config: {
version: '^1.0.0'
},
pluginProps: {}
},
{
pluginKey: 'rightPanel2',
type: 'TabPanel',
props: {
title: '属性',
icon: 'dengpao'
},
config: {
version: '^1.0.0'
},
pluginProps: {}
},
{
pluginKey: 'rightPanel3',
type: 'TabPanel',
props: {
title: '事件'
},
config: {
version: '^1.0.0'
},
pluginProps: {}
},
{
pluginKey: 'rightPanel4',
type: 'TabPanel',
props: {
title: '数据'
},
config: {
version: '^1.0.0'
},
pluginProps: {}
} }
// {
// pluginKey: 'rightPanel1',
// type: 'TabPanel',
// props: {
// title: '样式'
// },
// config: {
// version: '^1.0.0'
// },
// pluginProps: {}
// },
// {
// pluginKey: 'rightPanel2',
// type: 'TabPanel',
// props: {
// title: '属性',
// icon: 'dengpao'
// },
// config: {
// version: '^1.0.0'
// },
// pluginProps: {}
// },
// {
// pluginKey: 'rightPanel3',
// type: 'TabPanel',
// props: {
// title: '事件'
// },
// config: {
// version: '^1.0.0'
// },
// pluginProps: {}
// },
// {
// pluginKey: 'rightPanel4',
// type: 'TabPanel',
// props: {
// title: '数据'
// },
// config: {
// version: '^1.0.0'
// },
// pluginProps: {}
// }
], ],
centerArea: [ centerArea: [
{ {
@ -295,7 +295,7 @@ export default {
shortCuts: [], shortCuts: [],
lifeCycles: { lifeCycles: {
init: function init(editor) { init: function init(editor) {
const transformMaterial = (componentList) => { const transformMaterial = componentList => {
return componentList.map(category => { return componentList.map(category => {
return { return {
name: category.title, name: category.title,
@ -318,17 +318,25 @@ export default {
}; };
const list = transformMaterial(assets.componentList); const list = transformMaterial(assets.componentList);
console.log('+++++', list);
editor.set({ editor.set({
componentsMap: assets.components, componentsMap: assets.components,
componentMaterial: { componentMaterial: {
library: [{ library: [
name: 'Fusion组件库', {
id: 1 name: 'Fusion组件库',
}], id: 1
}
],
list list
} }
}); });
editor.set('dndHelper', {
handleResourceDragStart: function(ev, tagName, schema) {
// 物料面板中组件snippet的dragStart回调
// ev: 原始的domEventtagName: 组件的描述文案schema: snippet的schema
}
});
} }
} }
}; };

View File

@ -22,7 +22,9 @@ export default class AreaManager {
const { pluginStatus } = this.editor; const { pluginStatus } = this.editor;
const list = pluginType ? this.config.filter((item): boolean => item.type === pluginType) : this.config; const list = pluginType ? this.config.filter((item): boolean => item.type === pluginType) : this.config;
const isUpdate = list.some((item): boolean => !deepEqual(pluginStatus[item.pluginKey], this.pluginStatus[item.pluginKey])); const isUpdate = list.some(
(item): boolean => !deepEqual(pluginStatus[item.pluginKey], this.pluginStatus[item.pluginKey])
);
this.pluginStatus = clone(pluginStatus); this.pluginStatus = clone(pluginStatus);
return isUpdate; return isUpdate;
} }

View File

@ -106,34 +106,37 @@ export interface I18nConfig {
'ja-JP'?: I18nMessages; 'ja-JP'?: I18nMessages;
} }
export type I18nFunction = (key: string, params: any) => string | string[]; export type I18nFunction = (key: string, params: any) => string;
export interface Utils { export interface Utils {
[key: string]: (...args) => any; [key: string]: (...args) => any;
} }
export interface PluginProps { export interface PluginProps {
editor: Editor; editor: Editor;
config: PluginConfig; config: PluginConfig;
i18n: I18nFunction; i18n?: I18nFunction;
ref?: React.RefObject<Plugin>; ref?: React.RefObject<React.ReactElement>;
[key: string]: any; [key: string]: any;
} }
export type Plugin = React.ReactNode & { export type Plugin = React.ReactNode & {
open?: () => boolean| void| Promise<any>; open?: () => boolean | void | Promise<any>;
close?: () => boolean| void| Promise<any>; close?: () => boolean | void | Promise<any>;
} };
export type HOCPlugin = React.ReactNode & {
open: () => Promise<any>;
close: () => Promise<any>;
};
export interface PluginSet { export interface PluginSet {
[key: string]: Plugin; [key: string]: HOCPlugin;
} }
export type PluginClass = React.ComponentType<PluginProps> & { export type PluginClass = React.ComponentType<PluginProps> & {
init?: (editor: Editor) => void; init?: (editor: Editor) => void;
} };
export interface PluginClassSet { export interface PluginClassSet {
[key: string]: PluginClass; [key: string]: PluginClass;
@ -149,4 +152,3 @@ export interface PluginStatus {
export interface PluginStatusSet { export interface PluginStatusSet {
[key: string]: PluginStatus; [key: string]: PluginStatus;
} }

View File

@ -1,13 +1,26 @@
import Debug from 'debug'; import Debug from 'debug';
import EventEmitter from 'events'; import EventEmitter from 'events';
import store from 'store'; import store from 'store';
import { EditorConfig, HooksConfig, LocaleType, PluginStatusSet, Utils, PluginClassSet, PluginSet } from './definitions'; import {
EditorConfig,
HooksConfig,
LocaleType,
PluginStatusSet,
Utils,
PluginClassSet,
PluginSet
} from './definitions';
import * as editorUtils from './utils'; import * as editorUtils from './utils';
const { const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
registShortCuts, transformToPromise, unRegistShortCuts
} = editorUtils; declare global {
interface Window {
__isDebug?: boolean;
__newFunc?: (funcStr: string) => (...args: any[]) => any;
}
}
// 根据url参数设置debug选项 // 根据url参数设置debug选项
const debugRegRes = /_?debug=(.*?)(&|$)/.exec(location.search); const debugRegRes = /_?debug=(.*?)(&|$)/.exec(location.search);
@ -16,6 +29,7 @@ if (debugRegRes && debugRegRes[1]) {
window.__isDebug = true; window.__isDebug = true;
store.storage.write('debug', debugRegRes[1] === 'true' ? '*' : debugRegRes[1]); store.storage.write('debug', debugRegRes[1] === 'true' ? '*' : debugRegRes[1]);
} else { } else {
// eslint-disable-next-line no-underscore-dangle
window.__isDebug = false; window.__isDebug = false;
store.remove('debug'); store.remove('debug');
} }
@ -23,13 +37,12 @@ if (debugRegRes && debugRegRes[1]) {
// 重要用于矫正画布执行new Function的window对象上下文 // 重要用于矫正画布执行new Function的window对象上下文
// eslint-disable-next-line no-underscore-dangle // eslint-disable-next-line no-underscore-dangle
window.__newFunc = (funContext: string): ((...args: any[]) => any) => { window.__newFunc = (funContext: string): ((...args: any[]) => any) => {
return new Function(funContext); // eslint-disable-next-line no-new-func
return new Function(funContext) as (...args: any[]) => any;
}; };
// 关闭浏览器前提醒,只有产生过交互才会生效 // 关闭浏览器前提醒,只有产生过交互才会生效
window.onbeforeunload = function(e: Event): string|void { window.onbeforeunload = function(e: Event): string | void {
const ev = e || window.event; const ev = e || window.event;
// 本地调试不生效 // 本地调试不生效
if (location.href.indexOf('localhost') > 0) { if (location.href.indexOf('localhost') > 0) {
@ -72,7 +85,6 @@ export default class Editor extends EventEmitter {
public plugins: PluginSet; public plugins: PluginSet;
public locale: LocaleType; public locale: LocaleType;
public emit: (msg: string, ...args) => void; public emit: (msg: string, ...args) => void;
@ -89,7 +101,7 @@ export default class Editor extends EventEmitter {
super(); super();
this.config = config; this.config = config;
this.components = components; this.components = components;
this.utils = {...editorUtils, ...utils}; this.utils = { ...editorUtils, ...utils };
instance = this; instance = this;
this.init(); this.init();
} }
@ -128,7 +140,6 @@ export default class Editor extends EventEmitter {
} }
} catch (err) { } catch (err) {
console.warn(err); console.warn(err);
} }
} }

View File

@ -1,4 +0,0 @@
interface Window {
__isDebug?: boolean;
__newFunc?: (funcStr: string) => ((...args: any[]) => any);
}

View File

@ -1,22 +1,11 @@
import React, { createRef, PureComponent } from 'react'; import React, { createRef, PureComponent } from 'react';
import EditorContext from './context'; import EditorContext from './context';
import { I18nFunction, PluginConfig, PluginClass, Plugin } from './definitions'; import { I18nFunction, PluginProps, PluginClass, Plugin } from './definitions';
import Editor from './editor'; import Editor from './editor';
import { acceptsRef, generateI18n, isEmpty, transformToPromise } from './utils'; import { acceptsRef, generateI18n, isEmpty, transformToPromise } from './utils';
export interface PluginProps { export default function pluginFactory(Comp: PluginClass): React.ComponentType<PluginProps> {
editor: Editor;
config: PluginConfig;
}
export interface InjectedPluginProps {
i18n?: I18nFunction;
}
export default function pluginFactory(
Comp: PluginClass
): React.ComponentType<PluginProps> {
class LowcodePlugin extends PureComponent<PluginProps> { class LowcodePlugin extends PureComponent<PluginProps> {
public static displayName = 'LowcodeEditorPlugin'; public static displayName = 'LowcodeEditorPlugin';
@ -24,7 +13,7 @@ export default function pluginFactory(
public static init = Comp.init; public static init = Comp.init;
public ref: React.RefObject<Plugin>; public ref: React.RefObject<React.ReactElement> & Plugin;
private editor: Editor; private editor: Editor;
@ -39,7 +28,7 @@ export default function pluginFactory(
return; return;
} }
const { locale, messages, editor } = props; const { locale, messages, editor } = props;
this.ref = createRef<Plugin>(); this.ref = createRef<React.ReactElement>();
// 注册插件 // 注册插件
this.editor = editor; this.editor = editor;
this.i18n = generateI18n(locale, messages); this.i18n = generateI18n(locale, messages);
@ -71,7 +60,6 @@ export default function pluginFactory(
return Promise.resolve(); return Promise.resolve();
}; };
public render(): React.ReactNode { public render(): React.ReactNode {
const { config } = this.props; const { config } = this.props;
const props = { const props = {

View File

@ -28,6 +28,17 @@ const ENV = {
WEB: 'WEB' WEB: 'WEB'
}; };
declare global {
interface Window {
sendIDEMessage?: (params: IDEMessageParams) => void;
goldlog?: {
record: (logKey: string, gmKey: string, goKey: string, method: 'POST' | 'GET') => (...args: any[]) => any;
};
is_theia?: boolean;
vscode?: boolean;
}
}
export interface IDEMessageParams { export interface IDEMessageParams {
action: string; action: string;
data: { data: {
@ -37,16 +48,11 @@ export interface IDEMessageParams {
}; };
} }
export interface Window {
sendIDEMessage: (msg: IDEMessageParams) => void;
is_theia?: boolean;
}
/* /*
* *
*/ */
export function generateI18n(locale: LocaleType = 'zh-CN', messages: I18nMessages = {}): I18nFunction { export function generateI18n(locale: LocaleType = 'zh-CN', messages: I18nMessages = {}): I18nFunction {
return (key: string, values): string | string[] => { return (key: string, values): string => {
if (!messages || !messages[key]) { if (!messages || !messages[key]) {
return ''; return '';
} }

View File

@ -10,12 +10,9 @@ import constants from './config/constants';
import './config/locale'; import './config/locale';
import './config/setters'; import './config/setters';
import pkg from '../package.json';
import './global.scss'; import './global.scss';
import './config/theme.scss'; import './config/theme.scss';
(window as any).__pkg = pkg;
const ICE_CONTAINER = document.getElementById('ice-container'); const ICE_CONTAINER = document.getElementById('ice-container');
if (!ICE_CONTAINER) { if (!ICE_CONTAINER) {
@ -26,7 +23,7 @@ ReactDOM.render(
<Router> <Router>
<Route <Route
path="/*" path="/*"
component={props => ( component={(props): React.ReactNode => (
<Skeleton <Skeleton
{...props} {...props}
{...(config.skeleton && config.skeleton.props)} {...(config.skeleton && config.skeleton.props)}

View File

@ -163,19 +163,15 @@ const SCHEMA = {
}; };
export default class DesignerPlugin extends PureComponent<PluginProps> { export default class DesignerPlugin extends PureComponent<PluginProps> {
static displayName: 'LowcodePluginDesigner'; displayName: 'LowcodePluginDesigner';
constructor(props) {
super(props);
}
handleDesignerMount = (designer): void => { handleDesignerMount = (designer): void => {
const {editor} = this.props; const { editor } = this.props;
editor.set('designer', designer); editor.set('designer', designer);
editor.emit('designer.ready', designer); editor.emit('designer.ready', designer);
} };
render() { render(): React.ReactNode {
const { editor } = this.props; const { editor } = this.props;
return ( return (
<Designer <Designer

View File

@ -1,19 +1,18 @@
import React from 'react'; import React from 'react';
import './index.scss'; import './index.scss';
import Editor from '../../framework/index'; import { PluginProps } from '../../framework/definitions';
import { PluginConfig } from '../../framework/definitions';
export interface PluginProps { export interface IProps {
editor: Editor;
config: PluginConfig;
logo?: string; logo?: string;
href?: string; href?: string;
} }
export default function(props: PluginProps) { const Logo: React.FC<IProps & PluginProps> = (props): React.ReactElement => {
return ( return (
<div className="lowcode-plugin-logo"> <div className="lowcode-plugin-logo">
<a className="logo" target="blank" href={props.href || '/'} style={{ backgroundImage: `url(${props.logo})` }} /> <a className="logo" target="blank" href={props.href || '/'} style={{ backgroundImage: `url(${props.logo})` }} />
</div> </div>
); );
} };
export default Logo;

View File

@ -1,70 +1,74 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import './index.scss'; import './index.scss';
import Editor from '../../framework/index'; import { PluginProps } from '../../framework/definitions';
import { PluginConfig } from '../../framework/definitions';
import TopIcon from '../../skeleton/components/TopIcon/index'; import TopIcon from '../../skeleton/components/TopIcon/index';
export interface PluginProps { export interface IProps {
editor: Editor;
config: PluginConfig;
logo?: string; logo?: string;
} }
export interface PluginState{ export interface IState {
backEnable: boolean; undoEnable: boolean;
forwardEnable: boolean; redoEnable: boolean;
}; }
export default class UndoRedo extends PureComponent<IProps & PluginProps, IState> {
public static display = 'LowcodeUndoRedo';
export default class UndoRedo extends PureComponent<PluginProps, PluginState> { private history: any;
static display = 'LowcodeUndoRedo';
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
backEnable: false, undoEnable: false,
forwardEnable: false redoEnable: false
}; };
if (props.editor.designer) { if (props.editor.designer) {
this.init(); this.init();
} else { } else {
props.editor.on('designer.ready', () => { props.editor.on('designer.ready', (): void => {
this.init(); this.init();
}); });
} }
} }
init = (): void => { init = (): void => {
const {editor} = this.props; const { editor } = this.props;
this.designer = editor.designer; this.history = editor.designer.currentHistory;
this.history = this.designer.currentHistory; this.updateState(this.history.getState());
editor.on('designer.history-change', (history) => { editor.on('designer.history-change', (history): void => {
this.history = history; this.history = history;
this.history.onStateChange(this.updateState);
});
this.history.onStateChange(this.updateState);
};
updateState = (state: number): void => {
console.log('++++', !!(state & 1), !!(state & 2));
this.setState({
undoEnable: !!(state & 1),
redoEnable: !!(state & 2)
}); });
}; };
handleBackClick = (): void => { handleUndoClick = (): void => {
if (this.history) { if (this.history) {
this.history.back(); this.history.back();
} }
}; };
handleForwardClick = (): void => { handleRedoClick = (): void => {
if (this.history) { if (this.history) {
this.history.forward(); this.history.forward();
} }
}; };
render() { render(): React.ReactNode {
const { const { undoEnable, redoEnable } = this.state;
backEnable,
forwardEnable
} = this.state;
return ( return (
<div className="lowcode-plugin-undo-redo"> <div className="lowcode-plugin-undo-redo">
<TopIcon icon="houtui" title="后退" onClick={this.handleBackClick}/> <TopIcon icon="houtui" title="后退" disabled={!undoEnable} onClick={this.handleUndoClick} />
<TopIcon icon="qianjin" title="前进" onClick={this.handleForwardClick}/> <TopIcon icon="qianjin" title="前进" disabled={!redoEnable} onClick={this.handleRedoClick} />
</div> </div>
); );
} }

View File

@ -30,7 +30,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
disabled: false, disabled: false,
marked: false, marked: false,
locked: false, locked: false,
onClick: () => {} onClick: (): void => {}
}; };
constructor(props, context) { constructor(props, context) {
@ -40,7 +40,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
}; };
} }
componentDidMount() { componentDidMount(): void {
const { config, editor } = this.props; const { config, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
if (editor && pluginKey) { if (editor && pluginKey) {
@ -49,7 +49,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
} }
} }
componentWillUnmount() { componentWillUnmount(): void {
const { config, editor } = this.props; const { config, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
if (editor && pluginKey) { if (editor && pluginKey) {
@ -58,12 +58,12 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
} }
} }
handleClose = () => { handleClose = (): void => {
const { config, editor } = this.props; const { config, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
const plugin = editor.plugins && editor.plugins[pluginKey]; const plugin = editor.plugins && editor.plugins[pluginKey];
if (plugin) { if (plugin && plugin.close) {
plugin.close().then(() => { plugin.close().then((): void => {
this.setState({ this.setState({
dialogVisible: false dialogVisible: false
}); });
@ -71,24 +71,26 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
} }
}; };
handleOpen = () => { handleOpen = (): void => {
// todo 对话框类型的插件初始时拿不到插件实例 // todo 对话框类型的插件初始时拿不到插件实例
this.setState({ this.setState({
dialogVisible: true dialogVisible: true
}); });
}; };
handleShow = () => { handleShow = (): void => {
const { disabled, config, onClick, editor } = this.props; const { disabled, config, onClick, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
if (disabled || !pluginKey) return; if (disabled || !pluginKey) return;
// 考虑到弹窗情况,延时发送消息 // 考虑到弹窗情况,延时发送消息
setTimeout(() => editor.emit(`${pluginKey}.addon.activate`), 0); setTimeout((): void => editor.emit(`${pluginKey}.plugin.activate`), 0);
this.handleOpen(); this.handleOpen();
onClick && onClick(); if (onClick) {
onClick();
}
}; };
renderIcon = clickCallback => { renderIcon = (clickCallback): React.ReactNode => {
const { active, disabled, marked, locked, onClick, config } = this.props; const { active, disabled, marked, locked, onClick, config } = this.props;
const { pluginKey, props } = config || {}; const { pluginKey, props } = config || {};
const { icon, title } = props || {}; const { icon, title } = props || {};
@ -100,10 +102,11 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
locked locked
})} })}
data-tooltip={title} data-tooltip={title}
onClick={() => { onClick={(): void => {
if (disabled) return; if (disabled) return;
// 考虑到弹窗情况,延时发送消息 // 考虑到弹窗情况,延时发送消息
clickCallback && clickCallback(); clickCallback && clickCallback();
onClick && onClick(); onClick && onClick();
}} }}
> >
@ -118,7 +121,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
); );
}; };
render() { render(): React.ReactNode {
const { marked, locked, active, disabled, config, editor, pluginClass: Comp } = this.props; const { marked, locked, active, disabled, config, editor, pluginClass: Comp } = this.props;
const { pluginKey, props, type, pluginProps } = config || {}; const { pluginKey, props, type, pluginProps } = config || {};
const { onClick, title } = props || {}; const { onClick, title } = props || {};
@ -133,7 +136,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
locked={locked} locked={locked}
disabled={disabled} disabled={disabled}
config={config} config={config}
onClick={() => { onClick={(): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
}} }}
{...pluginProps} {...pluginProps}
@ -145,24 +148,24 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
case 'LinkIcon': case 'LinkIcon':
return ( return (
<a {...(props.linkProps || {})}> <a {...(props.linkProps || {})}>
{this.renderIcon(() => { {this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
})} })}
</a> </a>
); );
case 'Icon': case 'Icon':
return this.renderIcon(() => { return this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
}); });
case 'DialogIcon': case 'DialogIcon':
return ( return (
<Fragment> <Fragment>
{this.renderIcon(() => { {this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
this.handleOpen(); this.handleOpen();
})} })}
<Dialog <Dialog
onOk={() => { onOk={(): void => {
editor.emit(`${pluginKey}.dialog.onOk`); editor.emit(`${pluginKey}.dialog.onOk`);
this.handleClose(); this.handleClose();
}} }}
@ -171,7 +174,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
title={title} title={title}
style={{ style={{
width: 500, width: 500,
...(props && props.style) ...(props.dialogProps && props.dialogProps.style)
}} }}
{...(props.dialogProps || {})} {...(props.dialogProps || {})}
visible={dialogVisible} visible={dialogVisible}
@ -183,7 +186,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
case 'BalloonIcon': case 'BalloonIcon':
return ( return (
<Balloon <Balloon
trigger={this.renderIcon(() => { trigger={this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
})} })}
align="r" align="r"
@ -194,7 +197,7 @@ export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPlugi
</Balloon> </Balloon>
); );
case 'PanelIcon': case 'PanelIcon':
return this.renderIcon(() => { return this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
this.handleOpen(); this.handleOpen();
}); });

View File

@ -37,7 +37,7 @@ export default class Panel extends PureComponent<PanelProps, PanelState> {
}; };
} }
render() { render(): React.ReactNode {
const { align, draggable, floatable, visible } = this.props; const { align, draggable, floatable, visible } = this.props;
const { width } = this.state; const { width } = this.state;
return ( return (

View File

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Icon, Button } from '@alifd/next'; import { Icon } from '@alifd/next';
import './index.scss'; import './index.scss';
@ -27,22 +27,25 @@ export default class TopIcon extends PureComponent<TopIconProps> {
icon: '', icon: '',
id: '', id: '',
locked: false, locked: false,
onClick: () => {}, onClick: (): void => {},
style: {}, style: {},
title: '' title: ''
}; };
render() { render(): React.ReactNode {
const { active, disabled, icon, locked, title, className, id, style, onClick } = this.props; const { active, disabled, icon, locked, title, className, id, style, onClick } = this.props;
return ( return (
<div className={classNames('lowcode-top-icon', className, { <div
active, className={classNames('lowcode-top-icon', className, {
disabled, active,
locked disabled,
})} data-tooltip={title} locked
id={id} })}
style={style} data-tooltip={title}
onClick={disabled ? undefined : onClick}> id={id}
style={style}
onClick={disabled ? undefined : onClick}
>
<Icon type={icon} /> <Icon type={icon} />
</div> </div>
); );

View File

@ -1,4 +1,4 @@
import React, { PureComponent, Fragment } from 'react'; import React, { PureComponent, Fragment, CSSProperties } from 'react';
import { Balloon, Badge, Dialog } from '@alifd/next'; import { Balloon, Badge, Dialog } from '@alifd/next';
import TopIcon from '../TopIcon'; import TopIcon from '../TopIcon';
@ -31,7 +31,7 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
disabled: false, disabled: false,
marked: false, marked: false,
locked: false, locked: false,
onClick: () => {} onClick: (): void => {}
}; };
constructor(props, context) { constructor(props, context) {
@ -41,7 +41,7 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
}; };
} }
componentDidMount() { componentDidMount(): void {
const { config, editor } = this.props; const { config, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
if (editor && pluginKey) { if (editor && pluginKey) {
@ -50,7 +50,7 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
} }
} }
componentWillUnmount() { componentWillUnmount(): void {
const { config, editor } = this.props; const { config, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
if (editor && pluginKey) { if (editor && pluginKey) {
@ -59,22 +59,22 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
} }
} }
handleShow = () => { handleShow = (): void => {
const { disabled, config, onClick, editor } = this.props; const { disabled, config, onClick, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
if (disabled || !pluginKey) return; if (disabled || !pluginKey) return;
// 考虑到弹窗情况,延时发送消息 // 考虑到弹窗情况,延时发送消息
setTimeout(() => editor.emit(`${pluginKey}.plugin.activate`), 0); setTimeout((): void => editor.emit(`${pluginKey}.plugin.activate`), 0);
this.handleOpen(); this.handleOpen();
onClick && onClick(); onClick && onClick();
}; };
handleClose = () => { handleClose = (): void => {
const { config, editor } = this.props; const { config, editor } = this.props;
const pluginKey = config && config.pluginKey; const pluginKey = config && config.pluginKey;
const plugin = editor.plugins && editor.plugins[pluginKey]; const plugin = editor.plugins && editor.plugins[pluginKey];
if (plugin) { if (plugin && plugin.close) {
plugin.close().then(() => { plugin.close().then((): void => {
this.setState({ this.setState({
dialogVisible: false dialogVisible: false
}); });
@ -82,14 +82,14 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
} }
}; };
handleOpen = () => { handleOpen = (): void => {
// todo dialog类型的插件初始时拿不动插件实例 // todo dialog类型的插件初始时拿不动插件实例
this.setState({ this.setState({
dialogVisible: true dialogVisible: true
}); });
}; };
renderIcon = clickCallback => { renderIcon = (clickCallback): React.ReactNode => {
const { active, disabled, marked, locked, config, onClick, editor } = this.props; const { active, disabled, marked, locked, config, onClick, editor } = this.props;
const { pluginKey, props } = config || {}; const { pluginKey, props } = config || {};
const { icon, title } = props || {}; const { icon, title } = props || {};
@ -101,10 +101,10 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
locked={locked} locked={locked}
icon={icon} icon={icon}
title={title} title={title}
onClick={() => { onClick={(): void => {
if (disabled) return; if (disabled) return;
// 考虑到弹窗情况,延时发送消息 // 考虑到弹窗情况,延时发送消息
setTimeout(() => editor.emit(`${pluginKey}.plugin.activate`), 0); setTimeout((): void => editor.emit(`${pluginKey}.plugin.activate`), 0);
clickCallback && clickCallback(); clickCallback && clickCallback();
onClick && onClick(); onClick && onClick();
}} }}
@ -113,8 +113,8 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
return marked ? <Badge dot>{node}</Badge> : node; return marked ? <Badge dot>{node}</Badge> : node;
}; };
render() { render(): React.ReactNode {
const { active, marked, locked, disabled, config, editor, pluginClass: Comp } = this.props; const { active, marked, locked, disabled, config, editor, pluginClass: Comp, style } = this.props;
const { pluginKey, pluginProps, props, type } = config || {}; const { pluginKey, pluginProps, props, type } = config || {};
const { onClick, title } = props || {}; const { onClick, title } = props || {};
const { dialogVisible } = this.state; const { dialogVisible } = this.state;
@ -127,7 +127,7 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
locked={locked} locked={locked}
disabled={disabled} disabled={disabled}
config={config} config={config}
onClick={() => { onClick={(): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
}} }}
{...pluginProps} {...pluginProps}
@ -139,24 +139,24 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
case 'LinkIcon': case 'LinkIcon':
return ( return (
<a {...props.linkProps}> <a {...props.linkProps}>
{this.renderIcon(() => { {this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
})} })}
</a> </a>
); );
case 'Icon': case 'Icon':
return this.renderIcon(() => { return this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
}); });
case 'DialogIcon': case 'DialogIcon':
return ( return (
<Fragment> <Fragment>
{this.renderIcon(() => { {this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
this.handleOpen(); this.handleOpen();
})} })}
<Dialog <Dialog
onOk={() => { onOk={(): void => {
editor.emit(`${pluginKey}.dialog.onOk`); editor.emit(`${pluginKey}.dialog.onOk`);
this.handleClose(); this.handleClose();
}} }}
@ -165,7 +165,7 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
title={title} title={title}
style={{ style={{
width: 500, width: 500,
...(props && props.style) ...(props.dialogProps && props.dialogProps.style)
}} }}
{...props.dialogProps} {...props.dialogProps}
visible={dialogVisible} visible={dialogVisible}
@ -177,7 +177,7 @@ export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginSt
case 'BalloonIcon': case 'BalloonIcon':
return ( return (
<Balloon <Balloon
trigger={this.renderIcon(() => { trigger={this.renderIcon((): void => {
onClick && onClick.call(null, editor); onClick && onClick.call(null, editor);
})} })}
triggerType={['click', 'hover']} triggerType={['click', 'hover']}

View File

@ -9,7 +9,6 @@ body {
color: $color-text1-3; color: $color-text1-3;
} }
.next-loading { .next-loading {
.next-loading-wrap { .next-loading-wrap {
height: 100%; height: 100%;

View File

@ -1,10 +1,9 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { HashRouter as Router, Route } from 'react-router-dom';
import { Loading, ConfigProvider } from '@alifd/next'; import { Loading, ConfigProvider } from '@alifd/next';
import Editor from '../framework/editor'; import Editor from '../framework/editor';
import { EditorConfig, Utils, PluginComponents } from '../framework/definitions'; import { EditorConfig, Utils, PluginClassSet } from '../framework/definitions';
import { comboEditorConfig, parseSearch } from '../framework/utils'; import { comboEditorConfig, parseSearch } from '../framework/utils';
import defaultConfig from './config/skeleton'; import defaultConfig from './config/skeleton';
@ -19,8 +18,17 @@ import './global.scss';
let renderIdx = 0; let renderIdx = 0;
declare global {
interface Window {
__ctx: {
editor: Editor;
appHelper: Editor;
};
}
}
export interface SkeletonProps { export interface SkeletonProps {
components: PluginComponents; components: PluginClassSet;
config: EditorConfig; config: EditorConfig;
history: object; history: object;
location: object; location: object;
@ -29,15 +37,15 @@ export interface SkeletonProps {
} }
export interface SkeletonState { export interface SkeletonState {
initReady: boolean; initReady?: boolean;
skeletonKey: string; skeletonKey?: string;
__hasError?: boolean; __hasError?: boolean;
} }
export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState> { export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState> {
static displayName = 'LowcodeEditorSkeleton'; static displayName = 'LowcodeEditorSkeleton';
static getDerivedStateFromError() { static getDerivedStateFromError(): SkeletonState {
return { return {
__hasError: true __hasError: true
}; };
@ -56,11 +64,11 @@ export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState
this.init(); this.init();
} }
componentWillUnmount() { componentWillUnmount(): void {
this.editor && this.editor.destroy(); this.editor && this.editor.destroy();
} }
componentDidCatch(err) { componentDidCatch(err): void {
console.error(err); console.error(err);
} }
@ -69,15 +77,17 @@ export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState
this.editor.destroy(); this.editor.destroy();
} }
const { utils, config, components } = this.props; const { utils, config, components } = this.props;
const editor = (this.editor = new Editor(comboEditorConfig(defaultConfig, config), components, { const editor = new Editor(comboEditorConfig(defaultConfig, config), components, {
...skeletonUtils, ...skeletonUtils,
...utils ...utils
})); });
this.editor = editor;
// eslint-disable-next-line no-underscore-dangle
window.__ctx = { window.__ctx = {
editor, editor,
appHelper: editor appHelper: editor
}; };
editor.once('editor.reset', () => { editor.once('editor.reset', (): void => {
this.setState({ this.setState({
initReady: false initReady: false
}); });
@ -85,14 +95,14 @@ export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState
this.init(true); this.init(true);
}); });
this.editor.init().then(() => { this.editor.init().then((): void => {
this.setState( this.setState(
{ {
initReady: true, initReady: true,
// 刷新IDE时生成新的skeletonKey保证插件生命周期重新执行 // 刷新IDE时生成新的skeletonKey保证插件生命周期重新执行
skeletonKey: isReset ? `skeleton${++renderIdx}` : this.state.skeletonKey skeletonKey: isReset ? `skeleton${++renderIdx}` : this.state.skeletonKey
}, },
() => { (): void => {
editor.emit('editor.ready'); editor.emit('editor.ready');
editor.emit('ide.ready'); editor.emit('ide.ready');
isReset && editor.emit('ide.afterReset'); isReset && editor.emit('ide.afterReset');
@ -101,7 +111,7 @@ export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState
}); });
}; };
render() { render(): React.ReactNode {
const { initReady, skeletonKey, __hasError } = this.state; const { initReady, skeletonKey, __hasError } = this.state;
const { location, history, match } = this.props; const { location, history, match } = this.props;
if (__hasError || !this.editor) { if (__hasError || !this.editor) {

View File

@ -12,6 +12,7 @@ export default class CenterArea extends PureComponent<CenterAreaProps> {
static displayName = 'LowcodeCenterArea'; static displayName = 'LowcodeCenterArea';
private editor: Editor; private editor: Editor;
private areaManager: AreaManager; private areaManager: AreaManager;
constructor(props) { constructor(props) {
@ -20,10 +21,11 @@ export default class CenterArea extends PureComponent<CenterAreaProps> {
this.areaManager = new AreaManager(this.editor, 'centerArea'); this.areaManager = new AreaManager(this.editor, 'centerArea');
} }
componentDidMount() { componentDidMount(): void {
this.editor.on('skeleton.update', this.handleSkeletonUpdate); this.editor.on('skeleton.update', this.handleSkeletonUpdate);
} }
componentWillUnmount() {
componentWillUnmount(): void {
this.editor.off('skeleton.update', this.handleSkeletonUpdate); this.editor.off('skeleton.update', this.handleSkeletonUpdate);
} }
@ -34,14 +36,16 @@ export default class CenterArea extends PureComponent<CenterAreaProps> {
} }
}; };
render() { render(): React.ReactNode {
const visiblePluginList = this.areaManager.getVisiblePluginList(); const visiblePluginList = this.areaManager.getVisiblePluginList();
return ( return (
<div className="lowcode-center-area"> <div className="lowcode-center-area">
{visiblePluginList.map(item => { {visiblePluginList.map(
const Comp = this.editor.components[item.pluginKey]; (item): React.ReactNode => {
return <Comp key={item.pluginKey} editor={this.editor} config={item} {...item.pluginProps} />; const Comp = this.editor.components[item.pluginKey];
})} return <Comp key={item.pluginKey} editor={this.editor} config={item} {...item.pluginProps} />;
}
)}
</div> </div>
); );
} }

View File

@ -21,7 +21,7 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps, LeftAre
private areaManager: AreaManager; private areaManager: AreaManager;
private cacheActiveKey: string; // private cacheActiveKey: string;
constructor(props) { constructor(props) {
super(props); super(props);
@ -31,10 +31,10 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps, LeftAre
this.state = { this.state = {
activeKey: 'none' activeKey: 'none'
}; };
this.cacheActiveKey = 'none'; // this.cacheActiveKey = 'none';
} }
componentDidMount() { componentDidMount(): void {
this.editor.on('skeleton.update', this.handleSkeletonUpdate); this.editor.on('skeleton.update', this.handleSkeletonUpdate);
this.editor.on('leftNav.change', this.handlePluginChange); this.editor.on('leftNav.change', this.handlePluginChange);
const visiblePanelPluginList = this.areaManager.getVisiblePluginList().filter(item => item.type === 'IconPanel'); const visiblePanelPluginList = this.areaManager.getVisiblePluginList().filter(item => item.type === 'IconPanel');
@ -42,7 +42,7 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps, LeftAre
this.handlePluginChange(defaultKey); this.handlePluginChange(defaultKey);
} }
componentWillUnmount() { componentWillUnmount(): void {
this.editor.off('skeleton.update', this.handleSkeletonUpdate); this.editor.off('skeleton.update', this.handleSkeletonUpdate);
this.editor.off('leftNav.change', this.handlePluginChange); this.editor.off('leftNav.change', this.handlePluginChange);
} }
@ -61,27 +61,25 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps, LeftAre
const nextPlugin = plugins[key]; const nextPlugin = plugins[key];
if (activeKey === 'none') { if (activeKey === 'none') {
if (nextPlugin) { if (nextPlugin) {
nextPlugin.open().then(() => { nextPlugin.open().then((): void => {
this.updateActiveKey(key); this.updateActiveKey(key);
}); });
} }
} else if (activeKey === key) { } else if (activeKey === key) {
if (prePlugin) { if (prePlugin) {
prePlugin.close().then(() => { prePlugin.close().then((): void => {
this.updateActiveKey('none'); this.updateActiveKey('none');
}); });
} }
} else { } else if (prePlugin) {
// 先关后开 // 先关后开
if (prePlugin) { prePlugin.close().then((): void => {
prePlugin.close().then(() => { if (nextPlugin) {
if (nextPlugin) { nextPlugin.open().then((): void => {
nextPlugin.open().then(() => { this.updateActiveKey(key);
this.updateActiveKey(key); });
}); }
} });
});
}
} }
}; };
@ -111,9 +109,9 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps, LeftAre
}; };
updateActiveKey = (key: string): void => { updateActiveKey = (key: string): void => {
if (key === 'none') { // if (key === 'none') {
this.cacheActiveKey = this.state.activeKey; // this.cacheActiveKey = this.state.activeKey;
} // }
this.editor.set('leftNav', key); this.editor.set('leftNav', key);
this.setState({ activeKey: key }); this.setState({ activeKey: key });
this.editor.emit('leftPanel.show', key); this.editor.emit('leftPanel.show', key);
@ -121,31 +119,32 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps, LeftAre
renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => { renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => {
const { activeKey } = this.state; const { activeKey } = this.state;
return list.map((item, idx) => { return list.map(
const pluginStatus = this.editor.pluginStatus[item.pluginKey]; (item): React.ReactElement => {
return ( const pluginStatus = this.editor.pluginStatus[item.pluginKey];
<LeftPlugin return (
key={item.pluginKey} <LeftPlugin
config={item} key={item.pluginKey}
editor={this.editor} config={item}
pluginClass={this.editor.components[item.pluginKey]} editor={this.editor}
onClick={() => this.handlePluginClick(item)} pluginClass={this.editor.components[item.pluginKey]}
active={activeKey === item.pluginKey} onClick={(): void => this.handlePluginClick(item)}
{...pluginStatus} active={activeKey === item.pluginKey}
/> {...pluginStatus}
); />
}); );
}
);
}; };
render() { render(): React.ReactNode {
const { activeKey } = this.state;
const topList: PluginConfig[] = []; const topList: PluginConfig[] = [];
const bottomList: PluginConfig[] = []; const bottomList: PluginConfig[] = [];
const visiblePluginList = this.areaManager.getVisiblePluginList(); const visiblePluginList = this.areaManager.getVisiblePluginList();
if (isEmpty(visiblePluginList)){ if (isEmpty(visiblePluginList)) {
return null; return null;
} }
visiblePluginList.forEach(item => { visiblePluginList.forEach((item): void => {
const align = item.props && item.props.align === 'bottom' ? 'bottom' : 'top'; const align = item.props && item.props.align === 'bottom' ? 'bottom' : 'top';
if (align === 'bottom') { if (align === 'bottom') {
bottomList.push(item); bottomList.push(item);

View File

@ -16,6 +16,7 @@ export default class LeftAreaPanel extends PureComponent<LeftAreaPanelProps, Lef
static displayName = 'LowcodeLeftAreaPanel'; static displayName = 'LowcodeLeftAreaPanel';
private editor: Editor; private editor: Editor;
private areaManager: AreaManager; private areaManager: AreaManager;
constructor(props) { constructor(props) {
@ -28,11 +29,12 @@ export default class LeftAreaPanel extends PureComponent<LeftAreaPanelProps, Lef
}; };
} }
componentDidMount() { componentDidMount(): void {
this.editor.on('skeleton.update', this.handleSkeletonUpdate); this.editor.on('skeleton.update', this.handleSkeletonUpdate);
this.editor.on('leftPanel.show', this.handlePluginChange); this.editor.on('leftPanel.show', this.handlePluginChange);
} }
componentWillUnmount() {
componentWillUnmount(): void {
this.editor.off('skeleton.update', this.handleSkeletonUpdate); this.editor.off('skeleton.update', this.handleSkeletonUpdate);
this.editor.off('leftPanel.show', this.handlePluginChange); this.editor.off('leftPanel.show', this.handlePluginChange);
} }
@ -50,20 +52,26 @@ export default class LeftAreaPanel extends PureComponent<LeftAreaPanelProps, Lef
}); });
}; };
render() { render(): React.ReactNode {
const { activeKey } = this.state; const { activeKey } = this.state;
const list = this.areaManager.getVisiblePluginList('PanelIcon'); const list = this.areaManager.getVisiblePluginList('PanelIcon');
return ( return (
<Fragment> <Fragment>
{list.map((item, idx) => { {list.map(
const Comp = this.editor.components[item.pluginKey]; (item): React.ReactElement => {
return ( const Comp = this.editor.components[item.pluginKey];
<Panel key={item.pluginKey} visible={item.pluginKey === activeKey} {...(item.props && item.props.panelProps)}> return (
<Comp editor={this.editor} config={item} {...item.pluginProps} /> <Panel
</Panel> key={item.pluginKey}
); visible={item.pluginKey === activeKey}
})} {...(item.props && item.props.panelProps)}
>
<Comp editor={this.editor} config={item} {...item.pluginProps} />
</Panel>
);
}
)}
</Fragment> </Fragment>
); );
} }

View File

@ -6,7 +6,7 @@
.right-panel { .right-panel {
overflow: auto; overflow: auto;
border-top: 2px solid $color-line1-1; // border-top: 2px solid $color-line1-1;
} }
//tab定义 //tab定义

View File

@ -30,7 +30,7 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
}; };
} }
componentDidMount() { componentDidMount(): void {
this.editor.on('skeleton.update', this.handleSkeletonUpdate); this.editor.on('skeleton.update', this.handleSkeletonUpdate);
this.editor.on('rightNav.change', this.handlePluginChange); this.editor.on('rightNav.change', this.handlePluginChange);
const visiblePluginList = this.areaManager.getVisiblePluginList('TabPanel'); const visiblePluginList = this.areaManager.getVisiblePluginList('TabPanel');
@ -38,7 +38,7 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
this.handlePluginChange(defaultKey, true); this.handlePluginChange(defaultKey, true);
} }
componentWillUnmount() { componentWillUnmount(): void {
this.editor.off('skeleton.update', this.handleSkeletonUpdate); this.editor.off('skeleton.update', this.handleSkeletonUpdate);
this.editor.off('rightNav.change', this.handlePluginChange); this.editor.off('rightNav.change', this.handlePluginChange);
} }
@ -53,12 +53,12 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
} else { } else {
const currentPlugin = this.editor.plugins[activeKey]; const currentPlugin = this.editor.plugins[activeKey];
if (currentPlugin) { if (currentPlugin) {
currentPlugin.close().then(() => { currentPlugin.close().then((): void => {
this.setState( this.setState(
{ {
activeKey: '' activeKey: ''
}, },
() => { (): void => {
const visiblePluginList = this.areaManager.getVisiblePluginList(); const visiblePluginList = this.areaManager.getVisiblePluginList();
const firstPlugin = visiblePluginList && visiblePluginList[0]; const firstPlugin = visiblePluginList && visiblePluginList[0];
if (firstPlugin) { if (firstPlugin) {
@ -75,12 +75,12 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
handlePluginChange = (key: string, isinit?: boolean): void => { handlePluginChange = (key: string, isinit?: boolean): void => {
const activeKey = this.state.activeKey; const activeKey = this.state.activeKey;
const plugins = this.editor.plugins || {}; const plugins = this.editor.plugins || {};
const openPlugin = () => { const openPlugin = (): void => {
if (!plugins[key]) { if (!plugins[key]) {
console.error(`plugin ${key} has not regist in the editor`); console.error(`plugin ${key} has not regist in the editor`);
return; return;
} }
plugins[key].open().then(() => { plugins[key].open().then((): void => {
this.editor.set('rightNav', key); this.editor.set('rightNav', key);
this.setState({ this.setState({
activeKey: key activeKey: key
@ -89,7 +89,7 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
}; };
if (key === activeKey && !isinit) return; if (key === activeKey && !isinit) return;
if (activeKey && plugins[activeKey]) { if (activeKey && plugins[activeKey]) {
plugins[activeKey].close().then(() => { plugins[activeKey].close().then((): void => {
openPlugin(); openPlugin();
}); });
} else { } else {
@ -109,12 +109,7 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
disabled ? 'disabled' : '' disabled ? 'disabled' : ''
}`} }`}
> >
{!!icon && ( {!!icon && <Icon size="xs" type={icon} />}
<Icon
size="xs"
type={icon}
/>
)}
{title} {title}
</div> </div>
); );
@ -124,7 +119,7 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
return renderTitle(); return renderTitle();
}; };
renderTabPanels = (list: PluginConfig[], height: string): void => { renderTabPanels = (list: PluginConfig[], height: string): React.ReactNode => {
if (isEmpty(list)) { if (isEmpty(list)) {
return null; return null;
} }
@ -138,37 +133,41 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
lazyLoad={false} lazyLoad={false}
onChange={this.handlePluginChange} onChange={this.handlePluginChange}
> >
{list.map((item, idx) => { {list.map(
const Comp = this.editor.components[item.pluginKey]; (item): React.ReactElement => {
return ( const Comp = this.editor.components[item.pluginKey];
<Tab.Item return (
key={item.pluginKey} <Tab.Item
title={this.renderTabTitle(item)} key={item.pluginKey}
disabled={this.editor.pluginStatus[item.pluginKey].disabled} title={this.renderTabTitle(item)}
style={{ disabled={this.editor.pluginStatus[item.pluginKey].disabled}
width: `${100/list.length}%` style={{
}} width: `${100 / list.length}%`
> }}
<Comp editor={this.editor} config={item} {...item.pluginProps} /> >
</Tab.Item> <Comp editor={this.editor} config={item} {...item.pluginProps} />
); </Tab.Item>
})} );
}
)}
</Tab> </Tab>
); );
} };
renderPanels = (list: PluginConfig[], height: string): void => { renderPanels = (list: PluginConfig[], height: string): React.ReactNode => {
return list.map((item) => { return list.map(
const Comp = this.editor.components[item.pluginKey]; (item): React.ReactElement => {
return ( const Comp = this.editor.components[item.pluginKey];
<div className="right-panel" style={{height}} key={item.pluginKey}> return (
<Comp editor={this.editor} config={item} {...item.pluginProps} /> <div className="right-panel" style={{ height }} key={item.pluginKey}>
</div> <Comp editor={this.editor} config={item} {...item.pluginProps} />
); </div>
}); );
} }
);
};
render() { render(): React.ReactNode {
const tabList = this.areaManager.getVisiblePluginList('TabPanel'); const tabList = this.areaManager.getVisiblePluginList('TabPanel');
const panelList = this.areaManager.getVisiblePluginList('Panel'); const panelList = this.areaManager.getVisiblePluginList('Panel');
if (isEmpty(panelList) && isEmpty(tabList)) { if (isEmpty(panelList) && isEmpty(tabList)) {

View File

@ -4,7 +4,7 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 50px; height: 50px;
background-color: $card-background; background-color: $card-background;
border-bottom: 2px solid $color-line1-1; border-bottom: 2px solid $color-line1-1;
user-select: none; user-select: none;
.divider { .divider {

View File

@ -25,11 +25,11 @@ export default class TopArea extends PureComponent<TopAreaProps> {
this.areaManager = new AreaManager(props.editor, 'topArea'); this.areaManager = new AreaManager(props.editor, 'topArea');
} }
componentDidMount() { componentDidMount(): void {
this.editor.on('skeleton.update', this.handleSkeletonUpdate); this.editor.on('skeleton.update', this.handleSkeletonUpdate);
} }
componentWillUnmount() { componentWillUnmount(): void {
this.editor.off('skeleton.update', this.handleSkeletonUpdate); this.editor.off('skeleton.update', this.handleSkeletonUpdate);
} }
@ -41,30 +41,32 @@ export default class TopArea extends PureComponent<TopAreaProps> {
}; };
renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => { renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => {
return list.map((item, idx) => { return list.map(
const isDivider = item.type === 'Divider'; (item, idx): React.ReactElement => {
return ( const isDivider = item.type === 'Divider';
<Col return (
className={isDivider ? 'divider' : ''} <Col
key={isDivider ? idx : item.pluginKey} className={isDivider ? 'divider' : ''}
style={{ key={isDivider ? idx : item.pluginKey}
width: (item.props && item.props.width) || 36, style={{
flex: 'none' width: (item.props && item.props.width) || 36,
}} flex: 'none'
> }}
{!isDivider && ( >
<TopPlugin config={item} pluginClass={this.editor.components[item.pluginKey]} editor={this.editor} /> {!isDivider && (
)} <TopPlugin config={item} pluginClass={this.editor.components[item.pluginKey]} editor={this.editor} />
</Col> )}
); </Col>
}); );
}
);
}; };
render() { render(): React.ReactNode {
const leftList: PluginConfig[] = []; const leftList: PluginConfig[] = [];
const rightList: PluginConfig[] = []; const rightList: PluginConfig[] = [];
const visiblePluginList = this.areaManager.getVisiblePluginList(); const visiblePluginList = this.areaManager.getVisiblePluginList();
visiblePluginList.forEach(item => { visiblePluginList.forEach((item): void => {
const align = item.props && item.props.align === 'right' ? 'right' : 'left'; const align = item.props && item.props.align === 'right' ? 'right' : 'left';
// 分隔符不允许相邻 // 分隔符不允许相邻
if (item.type === 'Divider') { if (item.type === 'Divider') {