From 3c44a68ccb0cb19c4be45f2b87c18861ce911e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8B=E7=BE=8A?= Date: Wed, 11 Mar 2020 19:15:01 +0800 Subject: [PATCH 1/5] feat:daily tag --- packages/editor/ice.config.js | 2 +- packages/editor/package.json | 2 + packages/editor/public/index.html | 2 +- packages/editor/src/config/skeleton.js | 50 ++++++++++++++++- .../skeleton/components/LeftPlugin/index.scss | 30 +++++------ .../src/skeleton/components/Panel/index.scss | 10 ++-- .../skeleton/components/TopIcon/index.scss | 4 +- packages/editor/src/skeleton/global.scss | 3 ++ .../src/skeleton/layouts/LeftArea/index.scss | 8 +-- .../src/skeleton/layouts/LeftArea/nav.tsx | 5 +- .../src/skeleton/layouts/LeftArea/panel.tsx | 2 +- .../src/skeleton/layouts/RightArea/index.scss | 11 ++-- .../src/skeleton/layouts/RightArea/index.tsx | 54 ++++++++++++------- .../src/skeleton/layouts/TopArea/index.scss | 8 +-- 14 files changed, 135 insertions(+), 56 deletions(-) diff --git a/packages/editor/ice.config.js b/packages/editor/ice.config.js index 71d81b8b1..6843f35bb 100644 --- a/packages/editor/ice.config.js +++ b/packages/editor/ice.config.js @@ -12,7 +12,7 @@ module.exports = { }, plugins: [ ['ice-plugin-fusion', { - themePackage: '@alife/dpl-iceluna', + themePackage: '@alife/theme-lowcode-light', }], ['ice-plugin-moment-locales', { locales: ['zh-cn'], diff --git a/packages/editor/package.json b/packages/editor/package.json index 62c301598..4e1f2cecb 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -7,6 +7,8 @@ "@ali/iceluna-sdk": "^1.0.5-beta.26", "@alifd/next": "^1.x", "@alife/dpl-iceluna": "^2.3.2", + "@alife/theme-lowcode-dark": "^0.1.0", + "@alife/theme-lowcode-light": "^0.1.0", "@icedesign/theme": "^1.x", "events": "^3.1.0", "intl-messageformat": "^8.2.1", diff --git a/packages/editor/public/index.html b/packages/editor/public/index.html index 9c2cc0c1a..04c747a37 100644 --- a/packages/editor/public/index.html +++ b/packages/editor/public/index.html @@ -15,7 +15,7 @@ - +
diff --git a/packages/editor/src/config/skeleton.js b/packages/editor/src/config/skeleton.js index 64826af1c..4cb8a7a87 100644 --- a/packages/editor/src/config/skeleton.js +++ b/packages/editor/src/config/skeleton.js @@ -150,7 +150,11 @@ export default { props: { align: 'top', title: 'panel2', - icon: 'dengpao' + icon: 'dengpao', + panelProps: { + defaultWidth: 400, + floatable: true + } }, config: { package: '@ali/iceluna-addon-2', @@ -212,6 +216,50 @@ export default { }, pluginProps: {} }, + { + pluginKey: 'rightPanel1', + type: 'TabPanel', + props: { + title: '样式' + }, + config: { + version: '^1.0.0' + }, + pluginProps: {} + }, + { + pluginKey: 'rightPanel2', + type: 'TabPanel', + props: { + title: '属性' + }, + 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: [ { diff --git a/packages/editor/src/skeleton/components/LeftPlugin/index.scss b/packages/editor/src/skeleton/components/LeftPlugin/index.scss index 06b6ef63a..050a8ec4d 100644 --- a/packages/editor/src/skeleton/components/LeftPlugin/index.scss +++ b/packages/editor/src/skeleton/components/LeftPlugin/index.scss @@ -6,27 +6,15 @@ position: relative; cursor: pointer; transition: all 0.3s ease; - color: #777; + color: $color-text1-3; &.collapse { height: 40px; - color: #8c8c8c; - border-bottom: 1px solid #bfbfbf; + border-bottom: 1px solid $color-line1-1; + opacity: 0.6; } &.locked { color: red !important; } - &.active { - color: #fff !important; - background-color: $color-brand1-9 !important; - &.disabled { - color: #fff; - background-color: $color-fill1-7; - } - } - &.disabled { - cursor: not-allowed; - color: $color-text1-1; - } &:hover { background-color: $color-brand1-1; color: $color-brand1-6; @@ -56,4 +44,16 @@ z-index: 100; } } + &.active { + color: $color-white; + background-color: $color-brand1-9; + &.disabled { + color: $color-white; + background-color: $color-fill1-4; + } + } + &.disabled { + cursor: not-allowed; + color: $color-text1-1; + } } diff --git a/packages/editor/src/skeleton/components/Panel/index.scss b/packages/editor/src/skeleton/components/Panel/index.scss index cd3211ab4..5f38863a9 100644 --- a/packages/editor/src/skeleton/components/Panel/index.scss +++ b/packages/editor/src/skeleton/components/Panel/index.scss @@ -2,12 +2,12 @@ user-select: none; overflow: hidden; position: relative; - background: #ffffff; + background: $card-background; transition: width 0.3s ease; transform: translate3d(0, 0, 0); height: 100%; &.visible { - border-right: 1px solid #bfbfbf; + border-right: 1px solid $color-line1-1; } .drag-area { display: none; @@ -16,7 +16,7 @@ position: absolute; top: 0; bottom: 0; - z-index: 999; + z-index: 99; } &.draggable { .drag-area { @@ -41,12 +41,12 @@ } &.left { &.floatable { - left: 44px; + left: 48px; } } &.right { &.floatable { - right: 44px; + right: 48px; } } } diff --git a/packages/editor/src/skeleton/components/TopIcon/index.scss b/packages/editor/src/skeleton/components/TopIcon/index.scss index 67622fb64..0375269d9 100644 --- a/packages/editor/src/skeleton/components/TopIcon/index.scss +++ b/packages/editor/src/skeleton/components/TopIcon/index.scss @@ -6,7 +6,7 @@ text-align: center; border-radius: 8px; border: 1px solid transparent; - color: #777; + color: $color-text1-3; &.disabled { cursor: not-allowed; color: $color-text1-1; @@ -51,7 +51,7 @@ } i.next-icon { &:before { - font-size: 17px; + font-size: 16px; } margin-right: 0; line-height: 18px; diff --git a/packages/editor/src/skeleton/global.scss b/packages/editor/src/skeleton/global.scss index d825900bc..b0ad64e06 100644 --- a/packages/editor/src/skeleton/global.scss +++ b/packages/editor/src/skeleton/global.scss @@ -6,7 +6,10 @@ body { * { box-sizing: border-box; } + color: $color-text1-3; } + + .next-loading { .next-loading-wrap { height: 100%; diff --git a/packages/editor/src/skeleton/layouts/LeftArea/index.scss b/packages/editor/src/skeleton/layouts/LeftArea/index.scss index dac1b6b0a..e96315458 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/index.scss +++ b/packages/editor/src/skeleton/layouts/LeftArea/index.scss @@ -1,21 +1,21 @@ .lowcode-left-area-nav { width: 48px; height: 100%; - background: #ffffff; - border-right: 1px solid #e8ebee; + background-color: $card-background; + border-right: 1px solid $color-line1-1; position: relative; .top-area { position: absolute; top: 0; width: 100%; - background: #ffffff; + background-color: $card-background; max-height: 100%; } .bottom-area { position: absolute; bottom: 20px; width: 100%; - background: #ffffff; + background-color: $card-background; max-height: calc(100% - 20px); } } diff --git a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx index a5ed5cd8f..bba8a824f 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx +++ b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx @@ -4,7 +4,7 @@ import './index.scss'; import Editor from '../../../framework/editor'; import { PluginConfig } from '../../../framework/definitions'; import AreaManager from '../../../framework/areaManager'; - +import { isEmpty } from '../../../framework/utils'; export interface LeftAreaNavProps { editor: Editor; } @@ -138,6 +138,9 @@ export default class LeftAreaNav extends PureComponent = []; const bottomList: Array = []; const visiblePluginList = this.areaManager.getVisiblePluginList(); + if (isEmpty(visiblePluginList)){ + return null; + } visiblePluginList.forEach(item => { const align = item.props && item.props.align === 'bottom' ? 'bottom' : 'top'; if (align === 'bottom') { diff --git a/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx b/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx index 8c03247fd..281e23246 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx +++ b/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx @@ -59,7 +59,7 @@ export default class LeftAreaPanel extends PureComponent { const Comp = this.editor.components[item.pluginKey]; return ( - + ); diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.scss b/packages/editor/src/skeleton/layouts/RightArea/index.scss index fd05f5644..fc7b4300a 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.scss +++ b/packages/editor/src/skeleton/layouts/RightArea/index.scss @@ -1,8 +1,8 @@ .lowcode-right-area { width: 300px; height: 100%; - background-color: #ffffff; - border-left: 1px solid #e8ebee; + background-color: $card-background; + border-left: 1px solid $color-line1-1; .right-plugin-title { &.locked { color: red !important; @@ -16,6 +16,11 @@ } } + .right-panel { + overflow: auto; + border-top: 1px solid $color-line1-1; + } + //tab定义 .next-tabs-wrapped.right-tabs { display: flex; @@ -37,7 +42,7 @@ width: 25%; &.active { background: none; - border-bottom-color: #f7f7f7 !important; + border-bottom-color: $color-line1-1 !important; } } } diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.tsx b/packages/editor/src/skeleton/layouts/RightArea/index.tsx index 00fd7fbe6..2284d643f 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/RightArea/index.tsx @@ -4,6 +4,7 @@ import './index.scss'; import Editor from '../../../framework/editor'; import AreaManager from '../../../framework/areaManager'; import { PluginConfig } from '../../../framework/definitions'; +import { isEmpty } from '../../../framework/utils'; export interface RightAreaProps { editor: Editor; @@ -31,7 +32,7 @@ export default class RightArea extends PureComponent; - } - const Comp = this.editor.components[pane.pluginKey]; - return ( -
- -
- ); + renderTabPanels = (list:PluginConfig[], height: string):void => { + if (isEmpty(list)) { + return null; } return ( -
- - {visiblePluginList.map((item, idx) => { + {list.map((item, idx) => { const Comp = this.editor.components[item.pluginKey]; return ( + ); + } + + renderPanels = (list:PluginConfig[], height: string):void => { + return list.map((item) => { + const Comp = this.editor.components[item.pluginKey]; + return ( +
+ +
+ ); + }); + } + + render() { + const tabList = this.areaManager.getVisiblePluginList('TabPanel'); + const panelList = this.areaManager.getVisiblePluginList('Panel'); + if (isEmpty(panelList) && isEmpty(tabList)) { + return null; + } else if (tabList.length === 1) { + panelList.unshift(tabList[0]); + tabList.splice(0, 1); + } + const height = `${Math.floor(100 / (panelList.length + (tabList.length > 0 ? 1 : 0)))}%`; + return ( +
+ {this.renderTabPanels(tabList, height)} + {this.renderPanels(panelList, height)}
); } diff --git a/packages/editor/src/skeleton/layouts/TopArea/index.scss b/packages/editor/src/skeleton/layouts/TopArea/index.scss index 98af961da..66c87c9b1 100644 --- a/packages/editor/src/skeleton/layouts/TopArea/index.scss +++ b/packages/editor/src/skeleton/layouts/TopArea/index.scss @@ -4,14 +4,14 @@ left: 0; width: 100%; height: 48px; - background-color: #ffffff; - border-bottom: 1px solid #e8ebee; + background-color: $card-background; + border-bottom: 1px solid $color-line1-1; user-select: none; .divider { max-width: 0; margin: 8px 12px; height: 30px; - border-right: 1px solid rgba(191, 191, 191, 0.3); + border-right: 1px solid $color-line1-2; } .next-col { text-align: center; @@ -21,6 +21,6 @@ right: 12px; top: 0; height: 100%; - background: #ffffff; + background: $card-background; } } From 2c013dbfc546ca085dccfd347b4425831ac6ff93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8B=E7=BE=8A?= Date: Fri, 13 Mar 2020 09:48:37 +0800 Subject: [PATCH 2/5] daily tag --- packages/editor/.eslintrc.js | 6 +++--- packages/editor/ice.config.js | 2 +- packages/editor/src/framework/definitions.ts | 15 ++++++++------- packages/editor/src/framework/editor.ts | 4 +++- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/editor/.eslintrc.js b/packages/editor/.eslintrc.js index 1c034b884..f877f9390 100644 --- a/packages/editor/.eslintrc.js +++ b/packages/editor/.eslintrc.js @@ -1,8 +1,8 @@ -const { eslint, deepmerge } = require('@ice/spec'); +const { tslint, deepmerge } = require('@ice/spec'); -module.exports = deepmerge(eslint, { +module.exports = deepmerge(tslint, { rules: { "global-require": 0, - "interface-name" : [true, "never-prefix"] + "@typescript-eslint/interface-name-prefix": 0 }, }); diff --git a/packages/editor/ice.config.js b/packages/editor/ice.config.js index 6843f35bb..4222f059d 100644 --- a/packages/editor/ice.config.js +++ b/packages/editor/ice.config.js @@ -12,7 +12,7 @@ module.exports = { }, plugins: [ ['ice-plugin-fusion', { - themePackage: '@alife/theme-lowcode-light', + themePackage: '@alife/theme-lowcode-dark', }], ['ice-plugin-moment-locales', { locales: ['zh-cn'], diff --git a/packages/editor/src/framework/definitions.ts b/packages/editor/src/framework/definitions.ts index 968a1935e..9233b660c 100644 --- a/packages/editor/src/framework/definitions.ts +++ b/packages/editor/src/framework/definitions.ts @@ -9,7 +9,7 @@ export interface EditorConfig { shortCuts?: ShortCutsConfig; utils?: UtilsConfig; constants?: ConstantsConfig; - lifeCycles?: lifeCyclesConfig; + lifeCycles?: LifeCyclesConfig; i18n?: I18nConfig; } @@ -38,7 +38,7 @@ export interface ThemeConfig { } export interface PluginsConfig { - [propName: string]: Array; + [propName: string]: PluginConfig[]; } export interface PluginConfig { @@ -63,7 +63,7 @@ export interface PluginConfig { pluginProps?: object; } -export type HooksConfig = Array; +export type HooksConfig = HookConfig[]; export interface HookConfig { message: string; @@ -71,14 +71,14 @@ export interface HookConfig { handler: (editor: Editor, ...args) => void; } -export type ShortCutsConfig = Array; +export type ShortCutsConfig = ShortCutConfig[]; export interface ShortCutConfig { keyboard: string; handler: (editor: Editor, ev: React.KeyboardEventHandler, keymaster: any) => void; } -export type UtilsConfig = Array; +export type UtilsConfig = UtilConfig[]; export interface UtilConfig { name: string; @@ -88,7 +88,7 @@ export interface UtilConfig { export type ConstantsConfig = object; -export interface lifeCyclesConfig { +export interface LifeCyclesConfig { init?: (editor: Editor) => any; destroy?: (editor: Editor) => any; } @@ -114,7 +114,7 @@ export interface Utils { export interface PluginClass extends React.ComponentClass<{ editor: Editor; - [key: string]: any + [key: string]: any; }> { init?: (editor: Editor) => void; open?: () => any; @@ -133,3 +133,4 @@ export interface PluginStatus { locked?: boolean; }; } + diff --git a/packages/editor/src/framework/editor.ts b/packages/editor/src/framework/editor.ts index 9fe46806a..6e2217884 100644 --- a/packages/editor/src/framework/editor.ts +++ b/packages/editor/src/framework/editor.ts @@ -17,9 +17,11 @@ if (res && res[1]) { // 重要,用于矫正画布执行new Function的window对象上下文 window.__newFunc = funContext => { - return new Function(funContext); +return new Function(funContext); }; + + // 关闭浏览器前提醒,只有产生过交互才会生效 window.onbeforeunload = function(e) { e = e || window.event; From 01c8054bbe6d8da639f0e14b9c51ca6c1ff6ec39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8B=E7=BE=8A?= Date: Sun, 15 Mar 2020 10:12:02 +0800 Subject: [PATCH 3/5] daily tag --- packages/editor/.eslintrc.js | 6 +- packages/editor/ice.config.js | 2 +- packages/editor/package.json | 5 +- packages/editor/src/config/skeleton.js | 16 ++-- packages/editor/src/framework/areaManager.ts | 20 +++-- packages/editor/src/framework/context.ts | 1 + packages/editor/src/framework/definitions.ts | 50 ++++++++---- packages/editor/src/framework/editor.ts | 79 +++++++++++-------- packages/editor/src/framework/index.d.ts | 4 + packages/editor/src/framework/index.ts | 6 +- .../editor/src/framework/pluginFactory.tsx | 23 +++--- packages/editor/src/framework/utils.ts | 35 +++++--- packages/editor/src/plugins/logo/index.scss | 8 +- packages/editor/src/plugins/logo/index.tsx | 3 +- .../skeleton/components/LeftPlugin/index.scss | 27 +++---- .../skeleton/components/LeftPlugin/index.tsx | 8 +- .../skeleton/components/TopIcon/index.scss | 28 ++++--- .../src/skeleton/components/TopIcon/index.tsx | 34 +++----- .../skeleton/components/TopPlugin/index.tsx | 16 ++-- packages/editor/src/skeleton/global.scss | 2 +- .../src/skeleton/layouts/LeftArea/index.scss | 8 +- .../src/skeleton/layouts/LeftArea/nav.tsx | 50 ++++++------ .../src/skeleton/layouts/RightArea/index.scss | 62 ++++++--------- .../src/skeleton/layouts/RightArea/index.tsx | 63 ++++++++------- .../src/skeleton/layouts/TopArea/index.scss | 12 ++- .../src/skeleton/layouts/TopArea/index.tsx | 10 ++- 26 files changed, 322 insertions(+), 256 deletions(-) create mode 100644 packages/editor/src/framework/index.d.ts diff --git a/packages/editor/.eslintrc.js b/packages/editor/.eslintrc.js index f877f9390..aa36c050d 100644 --- a/packages/editor/.eslintrc.js +++ b/packages/editor/.eslintrc.js @@ -3,6 +3,10 @@ const { tslint, deepmerge } = require('@ice/spec'); module.exports = deepmerge(tslint, { rules: { "global-require": 0, - "@typescript-eslint/interface-name-prefix": 0 + "comma-dangle": 0, + "react/sort-comp": 0, + "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx", "ts"] }], + "@typescript-eslint/interface-name-prefix": 0, + "@typescript-eslint/no-explicit-any": 0 }, }); diff --git a/packages/editor/ice.config.js b/packages/editor/ice.config.js index 4222f059d..6843f35bb 100644 --- a/packages/editor/ice.config.js +++ b/packages/editor/ice.config.js @@ -12,7 +12,7 @@ module.exports = { }, plugins: [ ['ice-plugin-fusion', { - themePackage: '@alife/theme-lowcode-dark', + themePackage: '@alife/theme-lowcode-light', }], ['ice-plugin-moment-locales', { locales: ['zh-cn'], diff --git a/packages/editor/package.json b/packages/editor/package.json index 4e1f2cecb..f08656a28 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -23,13 +23,14 @@ }, "devDependencies": { "@ice/spec": "^0.1.1", - "@types/react": "^16.8.3", - "@types/react-dom": "^16.8.2", "@types/debug": "^4.1.5", "@types/events": "^3.0.0", + "@types/react": "^16.8.3", + "@types/react-dom": "^16.8.2", "@types/store": "^2.0.2", "css-modules-typescript-loader": "^2.0.4", "eslint": "^6.0.1", + "husky": "^4.2.3", "ice-plugin-fusion": "^0.1.4", "ice-plugin-moment-locales": "^0.1.0", "ice-scripts": "^2.0.0", diff --git a/packages/editor/src/config/skeleton.js b/packages/editor/src/config/skeleton.js index 4cb8a7a87..e198bf617 100644 --- a/packages/editor/src/config/skeleton.js +++ b/packages/editor/src/config/skeleton.js @@ -25,7 +25,8 @@ export default { version: '1.0.0' }, pluginProps: { - logo: 'https://img.alicdn.com/tfs/TB1mHYDxQP2gK0jSZPxXXacQpXa-112-64.png' + logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png', + href: '/' } }, { @@ -71,7 +72,7 @@ export default { type: 'Custom', props: { align: 'right', - width: 90 + width: 88 }, config: { package: '@ali/lowcode-plugin-undo-redo', @@ -107,8 +108,8 @@ export default { align: 'right', title: 'icon', icon: 'dengpao', - onClick: function(editor) { - alert('icon addon invoke, current activeKey: ' + editor.activeKey); + onClick(editor) { + alert(`icon addon invoke, current activeKey: ${ editor.activeKey}`); } }, config: {}, @@ -198,8 +199,8 @@ export default { align: 'bottom', title: 'icon', icon: 'dengpao', - onClick: function(editor) { - alert('icon addon invoke, current activeKey: ' + editor.activeKey); + onClick(editor) { + alert(`icon addon invoke, current activeKey: ${ editor.activeKey}`); } }, config: {}, @@ -231,7 +232,8 @@ export default { pluginKey: 'rightPanel2', type: 'TabPanel', props: { - title: '属性' + title: '属性', + icon: 'dengpao' }, config: { version: '^1.0.0' diff --git a/packages/editor/src/framework/areaManager.ts b/packages/editor/src/framework/areaManager.ts index ac7f1ed3c..1a943d310 100644 --- a/packages/editor/src/framework/areaManager.ts +++ b/packages/editor/src/framework/areaManager.ts @@ -4,26 +4,34 @@ import { clone, deepEqual } from './utils'; export default class AreaManager { private pluginStatus: PluginStatus; + private config: PluginConfig[]; - constructor(private editor: Editor, private area: string) { + + private editor: Editor; + + private area: string; + + constructor(editor: Editor, area: string) { + this.editor = editor; + this.area = area; this.config = (editor && editor.config && editor.config.plugins && editor.config.plugins[this.area]) || []; this.pluginStatus = clone(editor.pluginStatus); } public isPluginStatusUpdate(pluginType?: string): boolean { const { pluginStatus } = this.editor; - const list = pluginType ? this.config.filter(item => item.type === pluginType) : this.config; + const list = pluginType ? this.config.filter((item): boolean => item.type === pluginType) : this.config; - const isUpdate = list.some(item => !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); return isUpdate; } public getVisiblePluginList(pluginType?: string): PluginConfig[] { - const res = this.config.filter(item => { - return !this.pluginStatus[item.pluginKey] || this.pluginStatus[item.pluginKey].visible; + const res = this.config.filter((item): boolean => { + return !!(!this.pluginStatus[item.pluginKey] || this.pluginStatus[item.pluginKey].visible); }); - return pluginType ? res.filter(item => item.type === pluginType) : res; + return pluginType ? res.filter((item): boolean => item.type === pluginType) : res; } public getPluginConfig(): PluginConfig[] { diff --git a/packages/editor/src/framework/context.ts b/packages/editor/src/framework/context.ts index 78d3ce177..859b79dc4 100644 --- a/packages/editor/src/framework/context.ts +++ b/packages/editor/src/framework/context.ts @@ -1,3 +1,4 @@ import { createContext } from 'react'; + const context = createContext({}); export default context; diff --git a/packages/editor/src/framework/definitions.ts b/packages/editor/src/framework/definitions.ts index 9233b660c..5780d7f41 100644 --- a/packages/editor/src/framework/definitions.ts +++ b/packages/editor/src/framework/definitions.ts @@ -75,7 +75,7 @@ export type ShortCutsConfig = ShortCutConfig[]; export interface ShortCutConfig { keyboard: string; - handler: (editor: Editor, ev: React.KeyboardEventHandler, keymaster: any) => void; + handler: (editor: Editor, ev: Event, keymaster: any) => void; } export type UtilsConfig = UtilConfig[]; @@ -96,7 +96,7 @@ export interface LifeCyclesConfig { export type LocaleType = 'zh-CN' | 'zh-TW' | 'en-US' | 'ja-JP'; export interface I18nMessages { - [propName: string]: string; + [key: string]: string; } export interface I18nConfig { @@ -106,31 +106,47 @@ export interface I18nConfig { 'ja-JP'?: I18nMessages; } -export type I18nFunction = (key: string, params: any) => string; +export type I18nFunction = (key: string, params: any) => string | string[]; export interface Utils { - [propName: string]: (...args) => any; + [key: string]: (...args) => any; } -export interface PluginClass extends React.ComponentClass<{ + +export interface PluginProps { editor: Editor; + config: PluginConfig; + i18n: I18nFunction; + ref?: React.RefObject; [key: string]: any; -}> { - init?: (editor: Editor) => void; - open?: () => any; - close?: () => any; } -export interface PluginComponents { - [propName: string]: PluginClass; + +export type Plugin = React.ReactNode & { + open?: () => boolean| void| Promise; + close?: () => boolean| void| Promise; +} + +export interface PluginSet { + [key: string]: Plugin; +} + +export type PluginClass = React.ComponentType & { + init?: (editor: Editor) => void; +} + +export interface PluginClassSet { + [key: string]: PluginClass; } export interface PluginStatus { - [propName: string]: { - disabled?: boolean; - visible?: boolean; - marked?: boolean; - locked?: boolean; - }; + disabled?: boolean; + visible?: boolean; + marked?: boolean; + locked?: boolean; +} + +export interface PluginStatusSet { + [key: string]: PluginStatus; } diff --git a/packages/editor/src/framework/editor.ts b/packages/editor/src/framework/editor.ts index 6e2217884..49d9e8cb1 100644 --- a/packages/editor/src/framework/editor.ts +++ b/packages/editor/src/framework/editor.ts @@ -1,37 +1,39 @@ import Debug from 'debug'; import EventEmitter from 'events'; import store from 'store'; -import { EditorConfig, HooksConfig, LocaleType, PluginComponents, PluginStatus, Utils } from './definitions'; +import { EditorConfig, HooksConfig, LocaleType, PluginStatusSet, Utils, PluginClassSet, PluginSet } from './definitions'; import { registShortCuts, transformToPromise, unRegistShortCuts } from './utils'; // 根据url参数设置debug选项 -const res = /_?debug=(.*?)(&|$)/.exec(location.search); -if (res && res[1]) { +const debugRegRes = /_?debug=(.*?)(&|$)/.exec(location.search); +if (debugRegRes && debugRegRes[1]) { + // eslint-disable-next-line no-underscore-dangle window.__isDebug = true; - store.storage.write('debug', res[1] === 'true' ? '*' : res[1]); + store.storage.write('debug', debugRegRes[1] === 'true' ? '*' : debugRegRes[1]); } else { window.__isDebug = false; store.remove('debug'); } // 重要,用于矫正画布执行new Function的window对象上下文 -window.__newFunc = funContext => { -return new Function(funContext); +// eslint-disable-next-line no-underscore-dangle +window.__newFunc = (funContext: string): ((...args: any[]) => any) => { + return new Function(funContext); }; // 关闭浏览器前提醒,只有产生过交互才会生效 -window.onbeforeunload = function(e) { - e = e || window.event; +window.onbeforeunload = function(e: Event): string|void { + const ev = e || window.event; // 本地调试不生效 if (location.href.indexOf('localhost') > 0) { return; } const msg = '您确定要离开此页面吗?'; - e.cancelBubble = true; - e.returnValue = msg; + ev.cancelBubble = true; + ev.returnValue = true; if (e.stopPropagation) { e.stopPropagation(); e.preventDefault(); @@ -49,26 +51,41 @@ export interface HooksFuncs { } export default class Editor extends EventEmitter { - public static getInstance = (config: EditorConfig, components: PluginComponents, utils?: Utils): Editor => { + public static getInstance = (config: EditorConfig, components: PluginClassSet, utils?: Utils): Editor => { if (!instance) { instance = new Editor(config, components, utils); } return instance; }; - public pluginStatus: PluginStatus; - public plugins: PluginComponents; + public config: EditorConfig; + + public components: PluginClassSet; + + public utils: Utils; + + public pluginStatus: PluginStatusSet; + + public plugins: PluginSet; + + public locale: LocaleType; public emit: (msg: string, ...args) => void; + public on: (msg: string, handler: (...args) => void) => void; + public once: (msg: string, handler: (...args) => void) => void; + public off: (msg: string, handler: (...args) => void) => void; private hooksFuncs: HooksFuncs; - constructor(public config: EditorConfig, public components: PluginComponents, public utils?: Utils) { + constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) { super(); + this.config = config; + this.components = components; + this.utils = utils || {}; instance = this; this.init(); } @@ -82,21 +99,21 @@ export default class Editor extends EventEmitter { this.initHooks(hooks || []); this.emit('editor.beforeInit'); - const init = (lifeCycles && lifeCycles.init) || (() => {}); + const init = (lifeCycles && lifeCycles.init) || ((): void => {}); // 用户可以通过设置extensions.init自定义初始化流程; return transformToPromise(init(this)) - .then(() => { + .then((): boolean => { // 注册快捷键 registShortCuts(shortCuts, this); this.emit('editor.afterInit'); return true; }) - .catch(err => { + .catch((err): void => { console.error(err); }); } - public destroy() { + public destroy(): void { debug('destroy'); try { const { hooks = [], shortCuts = [], lifeCycles = {} } = this.config; @@ -107,7 +124,7 @@ export default class Editor extends EventEmitter { } } catch (err) { console.warn(err); - return; + } } @@ -123,7 +140,7 @@ export default class Editor extends EventEmitter { } this[key] = val; } else if (typeof key === 'object') { - Object.keys(key).forEach(item => { + Object.keys(key).forEach((item): void => { this[item] = key[item]; }); } @@ -133,26 +150,26 @@ export default class Editor extends EventEmitter { if (!Array.isArray(events)) { return; } - events.forEach(event => this.on(event, lisenter)); + events.forEach((event): void => this.on(event, lisenter)); } public batchOnce(events: string[], lisenter: (...args) => void): void { if (!Array.isArray(events)) { return; } - events.forEach(event => this.once(event, lisenter)); + events.forEach((event): void => this.once(event, lisenter)); } public batchOff(events: string[], lisenter: (...args) => void): void { if (!Array.isArray(events)) { return; } - events.forEach(event => this.off(event, lisenter)); + events.forEach((event): void => this.off(event, lisenter)); } // 销毁hooks中的消息监听 - private destroyHooks(hooks: HooksConfig = []) { - hooks.forEach((item, idx) => { + private destroyHooks(hooks: HooksConfig = []): void { + hooks.forEach((item, idx): void => { if (typeof this.hooksFuncs[idx] === 'function') { this.off(item.message, this.hooksFuncs[idx]); } @@ -162,8 +179,8 @@ export default class Editor extends EventEmitter { // 初始化hooks中的消息监听 private initHooks(hooks: HooksConfig = []): void { - this.hooksFuncs = hooks.map(item => { - const func = (...args) => { + this.hooksFuncs = hooks.map((item): ((...arg) => void) => { + const func = (...args): void => { item.handler(this, ...args); }; this[item.type](item.message, func); @@ -171,12 +188,12 @@ export default class Editor extends EventEmitter { }); } - private initPluginStatus() { + private initPluginStatus(): PluginStatusSet { const { plugins = {} } = this.config; const pluginAreas = Object.keys(plugins); - const res: PluginStatus = {}; - pluginAreas.forEach(area => { - (plugins[area] || []).forEach(plugin => { + const res: PluginStatusSet = {}; + pluginAreas.forEach((area): void => { + (plugins[area] || []).forEach((plugin): void => { if (plugin.type === 'Divider') { return; } diff --git a/packages/editor/src/framework/index.d.ts b/packages/editor/src/framework/index.d.ts new file mode 100644 index 000000000..369e95da7 --- /dev/null +++ b/packages/editor/src/framework/index.d.ts @@ -0,0 +1,4 @@ +interface Window { + __isDebug?: boolean; + __newFunc?: (funcStr: string) => ((...args: any[]) => any); +} \ No newline at end of file diff --git a/packages/editor/src/framework/index.ts b/packages/editor/src/framework/index.ts index be8b55d0a..72af6e859 100644 --- a/packages/editor/src/framework/index.ts +++ b/packages/editor/src/framework/index.ts @@ -1,9 +1,11 @@ import Editor from './editor'; -export { default as PluginFactory } from './pluginFactory'; -export { default as EditorContext } from './context'; import * as editorUtils from './utils'; import * as editorDefinitions from './definitions'; + +export { default as PluginFactory } from './pluginFactory'; +export { default as EditorContext } from './context'; + export default Editor; export const utils = editorUtils; diff --git a/packages/editor/src/framework/pluginFactory.tsx b/packages/editor/src/framework/pluginFactory.tsx index dea2cd602..d5298b913 100644 --- a/packages/editor/src/framework/pluginFactory.tsx +++ b/packages/editor/src/framework/pluginFactory.tsx @@ -1,7 +1,7 @@ import React, { createRef, PureComponent } from 'react'; import EditorContext from './context'; -import { I18nFunction, PluginConfig } from './definitions'; +import { I18nFunction, PluginConfig, PluginClass, Plugin } from './definitions'; import Editor from './editor'; import { acceptsRef, generateI18n, isEmpty, transformToPromise } from './utils'; @@ -15,18 +15,21 @@ export interface InjectedPluginProps { } export default function pluginFactory( - Comp: React.ComponentType + Comp: PluginClass ): React.ComponentType { class LowcodePlugin extends PureComponent { public static displayName = 'LowcodeEditorPlugin'; - public static defaultProps = { - config: {} - }; + public static contextType = EditorContext; + public static init = Comp.init; - public ref = createRef(); + + public ref: React.RefObject; + private editor: Editor; + private pluginKey: string; + private i18n: I18nFunction; constructor(props, context) { @@ -36,6 +39,7 @@ export default function pluginFactory( return; } const { locale, messages, editor } = props; + this.ref = createRef(); // 注册插件 this.editor = editor; this.i18n = generateI18n(locale, messages); @@ -46,7 +50,7 @@ export default function pluginFactory( }); } - public componentWillUnmount() { + public componentWillUnmount(): void { // 销毁插件 if (this.editor && this.editor.plugins) { delete this.editor.plugins[this.pluginKey]; @@ -60,14 +64,15 @@ export default function pluginFactory( return Promise.resolve(); }; - public close = () => { + public close = (): Promise => { if (this.ref && this.ref.close && typeof this.ref.close === 'function') { return transformToPromise(this.ref.close()); } return Promise.resolve(); }; - public render() { + + public render(): React.ReactNode { const { config } = this.props; const props = { i18n: this.i18n, diff --git a/packages/editor/src/framework/utils.ts b/packages/editor/src/framework/utils.ts index 794b0c9d3..13cd26f80 100644 --- a/packages/editor/src/framework/utils.ts +++ b/packages/editor/src/framework/utils.ts @@ -1,7 +1,5 @@ import IntlMessageFormat from 'intl-messageformat'; import keymaster from 'keymaster'; -import { EditorConfig, I18nFunction, I18nMessages, LocaleType, ShortCutsConfig } from './definitions'; -import Editor from './editor'; import _clone from 'lodash/cloneDeep'; import _debounce from 'lodash/debounce'; @@ -10,6 +8,10 @@ import _deepEqual from 'lodash/isEqualWith'; import _pick from 'lodash/pick'; import _throttle from 'lodash/throttle'; +import _serialize from 'serialize-javascript'; +import Editor from './editor'; +import { EditorConfig, I18nFunction, I18nMessages, LocaleType, ShortCutsConfig } from './definitions'; + export const pick = _pick; export const deepEqual = _deepEqual; export const clone = _clone; @@ -17,7 +19,6 @@ export const isEmpty = _isEmpty; export const throttle = _throttle; export const debounce = _debounce; -import _serialize from 'serialize-javascript'; export const serialize = _serialize; const ENV = { @@ -36,11 +37,16 @@ export interface IDEMessageParams { }; } +export interface Window { + sendIDEMessage: (msg: IDEMessageParams) => void; + is_theia?: boolean; +} + /* * 用于构造国际化字符串处理函数 */ export function generateI18n(locale: LocaleType = 'zh-CN', messages: I18nMessages = {}): I18nFunction { - return (key: string, values): string => { + return (key: string, values): string | string[] => { if (!messages || !messages[key]) { return ''; } @@ -57,7 +63,7 @@ export function serializeParams(obj: object): string { return ''; } const res: string[] = []; - Object.entries(obj).forEach(([key, val]) => { + Object.entries(obj).forEach(([key, val]): void => { if (val === null || val === undefined || val === '') { return; } @@ -115,8 +121,8 @@ export function getEnv(): string { // 注册快捷键 export function registShortCuts(config: ShortCutsConfig, editor: Editor): void { - (config || []).forEach(item => { - keymaster(item.keyboard, ev => { + (config || []).forEach((item): void => { + keymaster(item.keyboard, (ev: Event): void => { ev.preventDefault(); item.handler(editor, ev, keymaster); }); @@ -125,7 +131,7 @@ export function registShortCuts(config: ShortCutsConfig, editor: Editor): void { // 取消注册快捷 export function unRegistShortCuts(config: ShortCutsConfig): void { - (config || []).forEach(item => { + (config || []).forEach((item): void => { keymaster.unbind(item.keyboard); }); if (window.parent.vscode) { @@ -141,7 +147,7 @@ export function transformToPromise(input: any): Promise<{}> { if (input instanceof Promise) { return input; } - return new Promise((resolve, reject) => { + return new Promise((resolve, reject): void => { if (input || input === undefined) { resolve(); } else { @@ -161,7 +167,7 @@ export function transformArrayToMap(arr: T[], key: string, overwrite: boolean return {}; } const res = {}; - arr.forEach(item => { + arr.forEach((item): void => { const curKey = item[key]; if (item[key] === undefined) { return; @@ -187,7 +193,7 @@ export function parseSearch(search: string): Query { const str = search.replace(/^\?/, ''); const paramStr = str.split('&'); const res = {}; - paramStr.forEach(item => { + paramStr.forEach((item): void => { const regRes = item.split('='); if (regRes[0] && regRes[1]) { res[regRes[0]] = decodeURIComponent(regRes[1]); @@ -210,7 +216,7 @@ export function comboEditorConfig(defaultConfig: EditorConfig = {}, customConfig const customShortCuts = transformArrayToMap(shortCuts || [], 'keyboard'); const localeList = ['zh-CN', 'zh-TW', 'en-US', 'ja-JP']; const i18nConfig = {}; - localeList.forEach(key => { + localeList.forEach((key): void => { i18nConfig[key] = { ...(defaultConfig.i18n && defaultConfig.i18n[key]), ...(i18n && i18n[key]) @@ -248,9 +254,12 @@ export function comboEditorConfig(defaultConfig: EditorConfig = {}, customConfig * 判断当前组件是否能够设置ref * @param {*} Comp 需要判断的组件 */ -export function acceptsRef(Comp: React.ComponentType) { +export function acceptsRef(Comp: React.ReactNode): boolean { const hasSymbol = typeof Symbol === 'function' && Symbol.for; const REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0; + if (!Comp || typeof Comp !== 'object' || isEmpty(Comp)) { + return false; + } return ( (Comp.$$typeof && Comp.$$typeof === REACT_FORWARD_REF_TYPE) || (Comp.prototype && Comp.prototype.isReactComponent) ); diff --git a/packages/editor/src/plugins/logo/index.scss b/packages/editor/src/plugins/logo/index.scss index e2701fbca..338b4c58a 100644 --- a/packages/editor/src/plugins/logo/index.scss +++ b/packages/editor/src/plugins/logo/index.scss @@ -1,9 +1,13 @@ .lowcode-plugin-logo { - padding: 8px 16px; + padding: 14px 8px; + padding-left: 8px; .logo { + display: block; width: 56px; - height: 32px; + height: 20px; + cursor: pointer; background-size: contain; background-position: center; + background-repeat: no-repeat; } } diff --git a/packages/editor/src/plugins/logo/index.tsx b/packages/editor/src/plugins/logo/index.tsx index c02bf7a71..5a60799a0 100644 --- a/packages/editor/src/plugins/logo/index.tsx +++ b/packages/editor/src/plugins/logo/index.tsx @@ -7,12 +7,13 @@ export interface PluginProps { editor: Editor; config: PluginConfig; logo?: string; + href?: string; } export default function(props: PluginProps) { return (
-
+
); } diff --git a/packages/editor/src/skeleton/components/LeftPlugin/index.scss b/packages/editor/src/skeleton/components/LeftPlugin/index.scss index 050a8ec4d..d237581b0 100644 --- a/packages/editor/src/skeleton/components/LeftPlugin/index.scss +++ b/packages/editor/src/skeleton/components/LeftPlugin/index.scss @@ -1,22 +1,16 @@ .lowcode-left-plugin { - font-size: 16px; + font-size: 20px; text-align: center; - line-height: 36px; - height: 36px; + line-height: 44px; + height: 44px; position: relative; cursor: pointer; transition: all 0.3s ease; color: $color-text1-3; - &.collapse { - height: 40px; - border-bottom: 1px solid $color-line1-1; - opacity: 0.6; - } &.locked { color: red !important; } &:hover { - background-color: $color-brand1-1; color: $color-brand1-6; &:before { content: attr(data-tooltip); @@ -29,8 +23,8 @@ white-space: nowrap; padding: 6px 8px; border-radius: 4px; - background: rgba(0, 0, 0, 0.75); - color: #fff; + background: $balloon-tooltip-color-bg; + color: $color-text1-3; z-index: 100; } &:after { @@ -40,17 +34,18 @@ left: 40px; top: 15px; border: 5px solid transparent; - border-right-color: rgba(0, 0, 0, 0.75); + border-right: 5px solid $balloon-tooltip-color-bg; z-index: 100; } } &.active { - color: $color-white; - background-color: $color-brand1-9; + color: $color-brand1-9; &.disabled { - color: $color-white; - background-color: $color-fill1-4; + color: $color-text1-1; } + &:hover { + color: $color-brand1-6; + } } &.disabled { cursor: not-allowed; diff --git a/packages/editor/src/skeleton/components/LeftPlugin/index.tsx b/packages/editor/src/skeleton/components/LeftPlugin/index.tsx index 6d807548c..a2cfe1571 100644 --- a/packages/editor/src/skeleton/components/LeftPlugin/index.tsx +++ b/packages/editor/src/skeleton/components/LeftPlugin/index.tsx @@ -82,7 +82,7 @@ export default class LeftPlugin extends PureComponent editor.emit(`${pluginKey}.addon.activate`), 0); this.handleOpen(); onClick && onClick(); @@ -102,7 +102,7 @@ export default class LeftPlugin extends PureComponent { if (disabled) return; - //考虑到弹窗情况,延时发送消息 + // 考虑到弹窗情况,延时发送消息 clickCallback && clickCallback(); onClick && onClick(); }} @@ -169,6 +169,10 @@ export default class LeftPlugin extends PureComponent diff --git a/packages/editor/src/skeleton/components/TopIcon/index.scss b/packages/editor/src/skeleton/components/TopIcon/index.scss index 0375269d9..2dd2e3bb7 100644 --- a/packages/editor/src/skeleton/components/TopIcon/index.scss +++ b/packages/editor/src/skeleton/components/TopIcon/index.scss @@ -1,21 +1,27 @@ -.next-btn.next-large.lowcode-top-btn { +.lowcode-top-icon { + display: inline-block; width: 44px; - height: 44px; - padding: 0; - margin: 2px -2px; - text-align: center; - border-radius: 8px; - border: 1px solid transparent; + font-size: 20px; + line-height: 48px; color: $color-text1-3; + position: relative; &.disabled { cursor: not-allowed; color: $color-text1-1; + &:hover { + color: $color-text1-1; + } + } + &.active { + color: $color-brand1-9; + &:hover { + color: $color-brand1-6; + } } &.locked { color: red !important; } &:hover { - background-color: $color-brand1-1; color: $color-brand1-6; &:before { content: attr(data-tooltip); @@ -31,8 +37,8 @@ white-space: nowrap; padding: 6px 8px; border-radius: 4px; - background: rgba(0, 0, 0, 0.75); - color: #fff; + background: $balloon-tooltip-color-bg; + color: $color-text1-3; z-index: 100; } &:after { @@ -43,7 +49,7 @@ transform: translate(-50%, 0); bottom: -5px; border: 5px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.75); + border-bottom-color: $balloon-tooltip-color-bg; opacity: 1; visibility: visible; z-index: 100; diff --git a/packages/editor/src/skeleton/components/TopIcon/index.tsx b/packages/editor/src/skeleton/components/TopIcon/index.tsx index 64d27a6d7..40750d03a 100644 --- a/packages/editor/src/skeleton/components/TopIcon/index.tsx +++ b/packages/editor/src/skeleton/components/TopIcon/index.tsx @@ -13,13 +13,13 @@ export interface TopIconProps { locked?: boolean; marked?: boolean; onClick?: () => void; - showTitle?: boolean; style?: React.CSSProperties; title?: string; } export default class TopIcon extends PureComponent { static displayName = 'LowcodeTopIcon'; + static defaultProps = { active: false, className: '', @@ -28,33 +28,23 @@ export default class TopIcon extends PureComponent { id: '', locked: false, onClick: () => {}, - showTitle: false, style: {}, title: '' }; render() { - const { active, disabled, icon, locked, title, className, id, style, showTitle, onClick } = this.props; + const { active, disabled, icon, locked, title, className, id, style, onClick } = this.props; return ( - +
+ +
); } } diff --git a/packages/editor/src/skeleton/components/TopPlugin/index.tsx b/packages/editor/src/skeleton/components/TopPlugin/index.tsx index 6c4f280d0..e51893b15 100644 --- a/packages/editor/src/skeleton/components/TopPlugin/index.tsx +++ b/packages/editor/src/skeleton/components/TopPlugin/index.tsx @@ -1,7 +1,7 @@ import React, { PureComponent, Fragment } from 'react'; -import TopIcon from '../TopIcon'; import { Balloon, Badge, Dialog } from '@alifd/next'; +import TopIcon from '../TopIcon'; import './index.scss'; import { PluginConfig, PluginClass } from '../../../framework/definitions'; @@ -63,8 +63,8 @@ export default class TopPlugin extends PureComponent editor.emit(`${pluginKey}.addon.activate`), 0); + // 考虑到弹窗情况,延时发送消息 + setTimeout(() => editor.emit(`${pluginKey}.plugin.activate`), 0); this.handleOpen(); onClick && onClick(); }; @@ -95,7 +95,7 @@ export default class TopPlugin extends PureComponent { if (disabled) return; - //考虑到弹窗情况,延时发送消息 - setTimeout(() => editor.emit(`${pluginKey}.addon.activate`), 0); + // 考虑到弹窗情况,延时发送消息 + setTimeout(() => editor.emit(`${pluginKey}.plugin.activate`), 0); clickCallback && clickCallback(); onClick && onClick(); }} @@ -163,6 +163,10 @@ export default class TopPlugin extends PureComponent diff --git a/packages/editor/src/skeleton/global.scss b/packages/editor/src/skeleton/global.scss index b0ad64e06..8eb107e0f 100644 --- a/packages/editor/src/skeleton/global.scss +++ b/packages/editor/src/skeleton/global.scss @@ -18,7 +18,7 @@ body { .lowcode-editor { .lowcode-main-content { position: absolute; - top: 48px; + top: 50px; left: 0; right: 0; bottom: 0; diff --git a/packages/editor/src/skeleton/layouts/LeftArea/index.scss b/packages/editor/src/skeleton/layouts/LeftArea/index.scss index e96315458..8c69f42fc 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/index.scss +++ b/packages/editor/src/skeleton/layouts/LeftArea/index.scss @@ -1,20 +1,22 @@ .lowcode-left-area-nav { - width: 48px; + width: 50px; height: 100%; background-color: $card-background; - border-right: 1px solid $color-line1-1; + border-right: 2px solid $color-line1-1; position: relative; .top-area { position: absolute; top: 0; width: 100%; + padding: 12px 0; background-color: $card-background; max-height: 100%; } .bottom-area { position: absolute; - bottom: 20px; + bottom: 0; width: 100%; + padding: 12px 0; background-color: $card-background; max-height: calc(100% - 20px); } diff --git a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx index bba8a824f..61ba3791a 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx +++ b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx @@ -5,6 +5,7 @@ import Editor from '../../../framework/editor'; import { PluginConfig } from '../../../framework/definitions'; import AreaManager from '../../../framework/areaManager'; import { isEmpty } from '../../../framework/utils'; + export interface LeftAreaNavProps { editor: Editor; } @@ -17,7 +18,9 @@ export default class LeftAreaNav extends PureComponent { - const { activeKey } = this.state; - if (activeKey === 'none') { - const plugin = this.editor.plugins[this.cacheActiveKey]; - if (plugin) { - plugin.open().then(() => { - this.updateActiveKey(this.cacheActiveKey); - }); - } - } else { - const plugin = this.editor.plugins[activeKey]; - if (plugin) { - plugin.close().then(() => { - this.updateActiveKey('none'); - }); - } - } - }; + // handleCollapseClick = (): void => { + // const { activeKey } = this.state; + // if (activeKey === 'none') { + // const plugin = this.editor.plugins[this.cacheActiveKey]; + // if (plugin) { + // plugin.open().then(() => { + // this.updateActiveKey(this.cacheActiveKey); + // }); + // } + // } else { + // const plugin = this.editor.plugins[activeKey]; + // if (plugin) { + // plugin.close().then(() => { + // this.updateActiveKey('none'); + // }); + // } + // } + // }; handlePluginClick = (item: PluginConfig): void => { if (item.type === 'PanelIcon') { @@ -115,7 +119,7 @@ export default class LeftAreaNav extends PureComponent = []): Array => { + renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => { const { activeKey } = this.state; return list.map((item, idx) => { const pluginStatus = this.editor.pluginStatus[item.pluginKey]; @@ -135,8 +139,8 @@ export default class LeftAreaNav extends PureComponent = []; - const bottomList: Array = []; + const topList: PluginConfig[] = []; + const bottomList: PluginConfig[] = []; const visiblePluginList = this.areaManager.getVisiblePluginList(); if (isEmpty(visiblePluginList)){ return null; @@ -154,7 +158,7 @@ export default class LeftAreaNav extends PureComponent
{this.renderPluginList(bottomList)}
- + /> */} {this.renderPluginList(topList)}
diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.scss b/packages/editor/src/skeleton/layouts/RightArea/index.scss index fc7b4300a..563179f02 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.scss +++ b/packages/editor/src/skeleton/layouts/RightArea/index.scss @@ -1,57 +1,39 @@ .lowcode-right-area { - width: 300px; + width: 262px; height: 100%; background-color: $card-background; - border-left: 1px solid $color-line1-1; - .right-plugin-title { - &.locked { - color: red !important; - } - &.active { - color: $color-brand1-9 !important; - } - &.disabled { - cursor: not-allowed; - color: $color-text1-1; - } - } + border-left: 2px solid $color-line1-1; .right-panel { overflow: auto; - border-top: 1px solid $color-line1-1; + border-top: 2px solid $color-line1-1; } //tab定义 - .next-tabs-wrapped.right-tabs { - display: flex; - flex-direction: column; - margin-top: -1px; - .next-tabs-bar { - z-index: 1; - } + .right-tabs.next-tabs { .next-tabs-nav { - display: block; - .next-tabs-tab { - &:first-child { - border-left: none; - } - font-size: 14px; + width: 100%; + .next-tabs-tab-inner { + padding-left: 0; + padding-right: 0; + } + .right-plugin-title { text-align: center; - border-right: none !important; - margin-right: 0 !important; - width: 25%; + &.locked { + color: red !important; + } &.active { - background: none; - border-bottom-color: $color-line1-1 !important; + color: $color-brand1-9 !important; + } + &.disabled { + cursor: not-allowed; + color: $color-text1-1; + } + .next-icon { + line-height: 15px; + margin-right: 2px; } } } } - .next-tabs-content { - flex: 1; - .next-tabs-tabpane.active { - height: 100%; - overflow-y: auto; - } - } } diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.tsx b/packages/editor/src/skeleton/layouts/RightArea/index.tsx index 2284d643f..8f23ba2a3 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/RightArea/index.tsx @@ -18,6 +18,7 @@ export default class RightArea extends PureComponent (
{!!icon && ( )} {title} @@ -127,43 +124,45 @@ export default class RightArea extends PureComponent { + renderTabPanels = (list: PluginConfig[], height: string): void => { if (isEmpty(list)) { return null; } return ( - {list.map((item, idx) => { - const Comp = this.editor.components[item.pluginKey]; - return ( - - - - ); - })} - + className="right-tabs" + style={{ + height + }} + activeKey={this.state.activeKey} + lazyLoad={false} + onChange={this.handlePluginChange} + > + {list.map((item, idx) => { + const Comp = this.editor.components[item.pluginKey]; + return ( + + + + ); + })} + ); } - renderPanels = (list:PluginConfig[], height: string):void => { + renderPanels = (list: PluginConfig[], height: string): void => { return list.map((item) => { const Comp = this.editor.components[item.pluginKey]; return (
- +
); }); diff --git a/packages/editor/src/skeleton/layouts/TopArea/index.scss b/packages/editor/src/skeleton/layouts/TopArea/index.scss index 66c87c9b1..10669ba51 100644 --- a/packages/editor/src/skeleton/layouts/TopArea/index.scss +++ b/packages/editor/src/skeleton/layouts/TopArea/index.scss @@ -3,23 +3,27 @@ top: 0; left: 0; width: 100%; - height: 48px; + height: 50px; background-color: $card-background; - border-bottom: 1px solid $color-line1-1; + border-bottom: 2px solid $color-line1-1; user-select: none; .divider { max-width: 0; - margin: 8px 12px; - height: 30px; + margin: 12px 16px; + height: 24px; border-right: 1px solid $color-line1-2; } .next-col { text-align: center; } + .left-area { + padding: 0 16px; + } .right-area { position: absolute; right: 12px; top: 0; + padding: 0 16px; height: 100%; background: $card-background; } diff --git a/packages/editor/src/skeleton/layouts/TopArea/index.tsx b/packages/editor/src/skeleton/layouts/TopArea/index.tsx index df8828a9d..39adbb825 100644 --- a/packages/editor/src/skeleton/layouts/TopArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/TopArea/index.tsx @@ -16,6 +16,7 @@ export default class TopArea extends PureComponent { static displayName = 'LowcodeTopArea'; private areaManager: AreaManager; + private editor: Editor; constructor(props) { @@ -27,6 +28,7 @@ export default class TopArea extends PureComponent { componentDidMount() { this.editor.on('skeleton.update', this.handleSkeletonUpdate); } + componentWillUnmount() { this.editor.off('skeleton.update', this.handleSkeletonUpdate); } @@ -38,7 +40,7 @@ export default class TopArea extends PureComponent { } }; - renderPluginList = (list: Array = []): Array => { + renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => { return list.map((item, idx) => { const isDivider = item.type === 'Divider'; return ( @@ -46,7 +48,7 @@ export default class TopArea extends PureComponent { className={isDivider ? 'divider' : ''} key={isDivider ? idx : item.pluginKey} style={{ - width: (item.props && item.props.width) || 40, + width: (item.props && item.props.width) || 36, flex: 'none' }} > @@ -59,8 +61,8 @@ export default class TopArea extends PureComponent { }; render() { - const leftList: Array = []; - const rightList: Array = []; + const leftList: PluginConfig[] = []; + const rightList: PluginConfig[] = []; const visiblePluginList = this.areaManager.getVisiblePluginList(); visiblePluginList.forEach(item => { const align = item.props && item.props.align === 'right' ? 'right' : 'left'; From dd0ee40b8ef5330e957e8220e69ede099af955c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8B=E7=BE=8A?= Date: Sun, 15 Mar 2020 16:30:45 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=E7=89=A9=E6=96=99=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/package.json | 1 + packages/editor/src/config/assets.js | 126 ++++++++++++++++++ packages/editor/src/config/components.js | 12 +- packages/editor/src/config/skeleton.js | 58 +++++++- packages/editor/src/framework/editor.ts | 8 +- .../editor/src/plugins/designer/index.tsx | 7 + .../editor/src/plugins/undoRedo/index.tsx | 69 ++++++++-- packages/editor/src/skeleton/index.tsx | 3 +- 8 files changed, 265 insertions(+), 19 deletions(-) create mode 100644 packages/editor/src/config/assets.js diff --git a/packages/editor/package.json b/packages/editor/package.json index f08656a28..19c333e76 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -4,6 +4,7 @@ "description": "低代码编辑器", "dependencies": { "@ali/iceluna-addon-2": "^1.0.3", + "@ali/iceluna-addon-component-list": "^1.0.10", "@ali/iceluna-sdk": "^1.0.5-beta.26", "@alifd/next": "^1.x", "@alife/dpl-iceluna": "^2.3.2", diff --git a/packages/editor/src/config/assets.js b/packages/editor/src/config/assets.js new file mode 100644 index 000000000..ce85f883e --- /dev/null +++ b/packages/editor/src/config/assets.js @@ -0,0 +1,126 @@ +export default { + version: '1.0.0', + packages: { + '@alifd/next': { + title: 'fusion组件库', + package: '@alifd/next', + 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'], + library: 'Next' + } + }, + components: { + Button: { + componentName: 'Button', + title: '按钮', + devMode:'proCode', + npm: { + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Button' + }, + props: [{ + name: 'type', + propType: 'string' + }, { + name: 'children', + propType: 'string' + }], + configure: { + props: [{ + name: 'type', + setter: { + componentName: 'Input' + } + }, { + name: 'children', + setter: { + componentName: 'Input' + } + }] + } + }, + Input: { + componentName: 'Input', + title: '输入框', + devMode:'proCode', + npm: { + package: '@alifd/next', + version: '1.19.18', + destructuring: true, + exportName: 'Input' + }, + props: [{ + name: 'placeholder', + propType: 'string' + }], + configure: { + props: [{ + name: 'placeholder', + setter: { + componentName: 'Input' + } + }] + } + } + }, + componentList: [{ + title: '基础', + icon: '', + children: [{ + componentName: 'Button', + title: '按钮', + icon: '', + package: '@alife/next', + 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: '表单', + icon: '', + children: [{ + componentName: 'Input', + title: '输入框', + icon: '', + package: '@alife/next', + snippets: [{ + title: '普通', + screenshort: '', + schema: { + componentName: 'Input', + props: {} + } + }] + }] + }] +}; diff --git a/packages/editor/src/config/components.js b/packages/editor/src/config/components.js index 15edcae76..823238113 100644 --- a/packages/editor/src/config/components.js +++ b/packages/editor/src/config/components.js @@ -1,7 +1,3 @@ -import logo from '../plugins/logo'; -import Designer from '../plugins/designer'; -import undoRedo from '../plugins/undoRedo'; -import Settings from '../../../plugin-settings'; import topBalloonIcon from '@ali/iceluna-addon-2'; import topDialogIcon from '@ali/iceluna-addon-2'; import leftPanelIcon from '@ali/iceluna-addon-2'; @@ -12,6 +8,11 @@ import rightPanel1 from '@ali/iceluna-addon-2'; import rightPanel2 from '@ali/iceluna-addon-2'; import rightPanel3 from '@ali/iceluna-addon-2'; import rightPanel4 from '@ali/iceluna-addon-2'; +import componentList from '@ali/iceluna-addon-component-list'; +import Settings from '../../../plugin-settings'; +import undoRedo from '../plugins/undoRedo'; +import Designer from '../plugins/designer'; +import logo from '../plugins/logo'; import PluginFactory from '../framework/pluginFactory'; @@ -29,5 +30,6 @@ export default { rightPanel1: PluginFactory(rightPanel1), rightPanel2: PluginFactory(rightPanel2), rightPanel3: PluginFactory(rightPanel3), - rightPanel4: PluginFactory(rightPanel4) + rightPanel4: PluginFactory(rightPanel4), + componentList: PluginFactory(componentList) }; diff --git a/packages/editor/src/config/skeleton.js b/packages/editor/src/config/skeleton.js index e198bf617..3e4c92b6e 100644 --- a/packages/editor/src/config/skeleton.js +++ b/packages/editor/src/config/skeleton.js @@ -1,3 +1,5 @@ +import assets from './assets'; + export default { version: '^1.0.2', theme: { @@ -117,6 +119,22 @@ export default { } ], leftArea: [ + { + pluginKey: 'componentList', + type: 'PanelIcon', + props: { + align: 'top', + icon: 'zujianku', + title: '组件库' + }, + config: { + package: "@ali/iceluna-addon-component-list", + version: "^1.0.4" + }, + pluginProps: { + disableAppComponent: true + } + }, { pluginKey: 'leftPanelIcon', type: 'PanelIcon', @@ -274,5 +292,43 @@ export default { ] }, hooks: [], - shortCuts: [] + shortCuts: [], + lifeCycles: { + init: function init(editor) { + const transformMaterial = (componentList) => { + return componentList.map(category => { + return { + name: category.title, + items: category.children.map(comp => { + return { + ...comp, + name: comp.componentName, + libraryId: 1, + snippets: comp.snippets.map(snippet => { + return { + name: snippet.title, + screenshort: snippet.screenshort, + code: JSON.stringify(snippet.schema) + }; + }) + }; + }) + }; + }); + }; + + const list = transformMaterial(assets.componentList); + console.log('+++++', list); + editor.set({ + componentsMap: assets.components, + componentMaterial: { + library: [{ + name: 'Fusion组件库', + id: 1 + }], + list + } + }); + } + } }; diff --git a/packages/editor/src/framework/editor.ts b/packages/editor/src/framework/editor.ts index 49d9e8cb1..31ffaf071 100644 --- a/packages/editor/src/framework/editor.ts +++ b/packages/editor/src/framework/editor.ts @@ -3,7 +3,11 @@ import EventEmitter from 'events'; import store from 'store'; import { EditorConfig, HooksConfig, LocaleType, PluginStatusSet, Utils, PluginClassSet, PluginSet } from './definitions'; -import { registShortCuts, transformToPromise, unRegistShortCuts } from './utils'; +import * as editorUtils from './utils'; + +const { + registShortCuts, transformToPromise, unRegistShortCuts +} = editorUtils; // 根据url参数设置debug选项 const debugRegRes = /_?debug=(.*?)(&|$)/.exec(location.search); @@ -85,7 +89,7 @@ export default class Editor extends EventEmitter { super(); this.config = config; this.components = components; - this.utils = utils || {}; + this.utils = {...editorUtils, ...utils}; instance = this; this.init(); } diff --git a/packages/editor/src/plugins/designer/index.tsx b/packages/editor/src/plugins/designer/index.tsx index 8acd749d0..df55d1f0d 100644 --- a/packages/editor/src/plugins/designer/index.tsx +++ b/packages/editor/src/plugins/designer/index.tsx @@ -169,10 +169,17 @@ export default class DesignerPlugin extends PureComponent { super(props); } + handleDesignerMount = (designer): void => { + const {editor} = this.props; + editor.set('designer', designer); + editor.emit('designer.ready', designer); + } + render() { const { editor } = this.props; return ( - - -
- ); +export interface PluginState{ + backEnable: boolean; + forwardEnable: boolean; +}; + + +export default class UndoRedo extends PureComponent { + static display = 'LowcodeUndoRedo'; + + constructor(props) { + super(props); + this.state = { + backEnable: false, + forwardEnable: false + }; + if (props.editor.designer) { + this.init(); + } else { + props.editor.on('designer.ready', () => { + this.init(); + }); + } + + } + + init = (): void => { + const {editor} = this.props; + this.designer = editor.designer; + this.history = this.designer.currentHistory; + editor.on('designer.history-change', (history) => { + this.history = history; + }); + }; + + handleBackClick = (): void => { + if (this.history) { + this.history.back(); + } + }; + + handleForwardClick = (): void => { + if (this.history) { + this.history.forward(); + } + }; + + render() { + const { + backEnable, + forwardEnable + } = this.state; + return ( +
+ + +
+ ); + } } diff --git a/packages/editor/src/skeleton/index.tsx b/packages/editor/src/skeleton/index.tsx index b721c36bb..c6eee9f53 100644 --- a/packages/editor/src/skeleton/index.tsx +++ b/packages/editor/src/skeleton/index.tsx @@ -89,11 +89,12 @@ export default class Skeleton extends PureComponent { editor.emit('editor.ready'); + editor.emit('ide.ready'); isReset && editor.emit('ide.afterReset'); } ); From 7f90b0baa58e99a1d727ca187efa5deb0308f3f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8B=E7=BE=8A?= Date: Sun, 15 Mar 2020 19:13:39 +0800 Subject: [PATCH 5/5] daily tag --- packages/editor/.eslintrc.js | 6 +- packages/editor/src/config/assets.js | 186 ++++++++++-------- packages/editor/src/config/setters.ts | 12 +- packages/editor/src/config/skeleton.js | 118 +++++------ packages/editor/src/framework/areaManager.ts | 4 +- packages/editor/src/framework/definitions.ts | 24 +-- packages/editor/src/framework/editor.ts | 33 ++-- packages/editor/src/framework/index.d.ts | 4 - .../editor/src/framework/pluginFactory.tsx | 22 +-- packages/editor/src/framework/utils.ts | 18 +- packages/editor/src/index.tsx | 5 +- .../editor/src/plugins/designer/index.tsx | 12 +- packages/editor/src/plugins/logo/index.tsx | 13 +- .../editor/src/plugins/undoRedo/index.tsx | 60 +++--- .../skeleton/components/LeftPlugin/index.scss | 2 +- .../skeleton/components/LeftPlugin/index.tsx | 45 +++-- .../src/skeleton/components/Panel/index.tsx | 2 +- .../src/skeleton/components/TopIcon/index.tsx | 25 +-- .../skeleton/components/TopPlugin/index.tsx | 44 ++--- packages/editor/src/skeleton/global.scss | 1 - packages/editor/src/skeleton/index.tsx | 38 ++-- .../src/skeleton/layouts/CenterArea/index.tsx | 18 +- .../src/skeleton/layouts/LeftArea/nav.tsx | 73 ++++--- .../src/skeleton/layouts/LeftArea/panel.tsx | 30 +-- .../src/skeleton/layouts/RightArea/index.scss | 2 +- .../src/skeleton/layouts/RightArea/index.tsx | 81 ++++---- .../src/skeleton/layouts/TopArea/index.scss | 2 +- .../src/skeleton/layouts/TopArea/index.tsx | 44 +++-- 28 files changed, 497 insertions(+), 427 deletions(-) delete mode 100644 packages/editor/src/framework/index.d.ts diff --git a/packages/editor/.eslintrc.js b/packages/editor/.eslintrc.js index aa36c050d..4d6be3c66 100644 --- a/packages/editor/.eslintrc.js +++ b/packages/editor/.eslintrc.js @@ -4,9 +4,13 @@ module.exports = deepmerge(tslint, { rules: { "global-require": 0, "comma-dangle": 0, + "no-unused-expressions": 0, + "object-shorthand": 0, + "jsx-a11y/anchor-has-content": 0, "react/sort-comp": 0, "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx", "ts"] }], "@typescript-eslint/interface-name-prefix": 0, - "@typescript-eslint/no-explicit-any": 0 + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/explicit-member-accessibility": 0 }, }); diff --git a/packages/editor/src/config/assets.js b/packages/editor/src/config/assets.js index ce85f883e..5724f4742 100644 --- a/packages/editor/src/config/assets.js +++ b/packages/editor/src/config/assets.js @@ -5,7 +5,10 @@ export default { title: 'fusion组件库', package: '@alifd/next', 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' } }, @@ -13,114 +16,137 @@ export default { Button: { componentName: 'Button', title: '按钮', - devMode:'proCode', + devMode: 'proCode', npm: { package: '@alifd/next', version: '1.19.18', destructuring: true, exportName: 'Button' }, - props: [{ - name: 'type', - propType: 'string' - }, { - name: 'children', - propType: 'string' - }], - configure: { - props: [{ + props: [ + { name: 'type', - setter: { - componentName: 'Input' - } - }, { + propType: 'string' + }, + { name: 'children', - setter: { - componentName: 'Input' + propType: 'string' + } + ], + configure: { + props: [ + { + name: 'type', + setter: { + componentName: 'Input' + } + }, + { + name: 'children', + setter: { + componentName: 'Input' + } } - }] + ] } }, Input: { componentName: 'Input', title: '输入框', - devMode:'proCode', + devMode: 'proCode', npm: { package: '@alifd/next', version: '1.19.18', destructuring: true, exportName: 'Input' }, - props: [{ - name: 'placeholder', - propType: 'string' - }], - configure: { - props: [{ + props: [ + { name: 'placeholder', - setter: { - componentName: 'Input' + propType: 'string' + } + ], + configure: { + props: [ + { + name: 'placeholder', + setter: { + componentName: 'Input' + } } - }] + ] } } }, - componentList: [{ - title: '基础', - icon: '', - children: [{ - componentName: 'Button', - title: '按钮', + componentList: [ + { + title: '基础', icon: '', - package: '@alife/next', - snippets: [{ - title: 'private', - screenshort: '', - schema: { + children: [ + { componentName: 'Button', - props: { - type: 'primary' - }, - children: 'Primary' + title: '按钮', + icon: '', + package: '@alife/next', + 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: { - componentName: 'Button', - props: { - type: 'secondary' - }, - children: 'secondary' - } - }, { - title: 'normal', - screenshort: '', - schema: { - componentName: 'Button', - props: { - type: 'normal' - }, - children: 'normal' - } - }] - }] - }, { - title: '表单', - icon: '', - children: [{ - componentName: 'Input', - title: '输入框', + ] + }, + { + title: '表单', icon: '', - package: '@alife/next', - snippets: [{ - title: '普通', - screenshort: '', - schema: { + children: [ + { componentName: 'Input', - props: {} + title: '输入框', + icon: '', + package: '@alife/next', + snippets: [ + { + title: '普通', + screenshort: '', + schema: { + componentName: 'Input', + props: {} + } + } + ] } - }] - }] - }] + ] + } + ] }; diff --git a/packages/editor/src/config/setters.ts b/packages/editor/src/config/setters.ts index 122792ca6..dc3ae6cb0 100644 --- a/packages/editor/src/config/setters.ts +++ b/packages/editor/src/config/setters.ts @@ -4,13 +4,17 @@ import { registerSetter } from '../../../plugin-settings/src'; import { createElement } from 'react'; registerSetter('ClassNameSetter', () => { - return createElement('div', { - className: 'lc-block-setter' - }, '这里是类名绑定'); + return createElement( + 'div', + { + className: 'lc-block-setter' + }, + '这里是类名绑定' + ); }); registerSetter('EventsSetter', Input); -registerSetter('StringSetter', { component: Input, props: { placeholder: "请输入" } }); +registerSetter('StringSetter', { component: Input, props: { placeholder: '请输入' } }); registerSetter('NumberSetter', NumberSetter as any); diff --git a/packages/editor/src/config/skeleton.js b/packages/editor/src/config/skeleton.js index 3e4c92b6e..e633f3a47 100644 --- a/packages/editor/src/config/skeleton.js +++ b/packages/editor/src/config/skeleton.js @@ -111,7 +111,7 @@ export default { title: 'icon', icon: 'dengpao', onClick(editor) { - alert(`icon addon invoke, current activeKey: ${ editor.activeKey}`); + alert(`icon addon invoke, current activeKey: ${editor.activeKey}`); } }, config: {}, @@ -128,8 +128,8 @@ export default { title: '组件库' }, config: { - package: "@ali/iceluna-addon-component-list", - version: "^1.0.4" + package: '@ali/iceluna-addon-component-list', + version: '^1.0.4' }, pluginProps: { disableAppComponent: true @@ -218,7 +218,7 @@ export default { title: 'icon', icon: 'dengpao', onClick(editor) { - alert(`icon addon invoke, current activeKey: ${ editor.activeKey}`); + alert(`icon addon invoke, current activeKey: ${editor.activeKey}`); } }, config: {}, @@ -234,52 +234,52 @@ export default { 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: {} } + // { + // 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: [ { @@ -295,7 +295,7 @@ export default { shortCuts: [], lifeCycles: { init: function init(editor) { - const transformMaterial = (componentList) => { + const transformMaterial = componentList => { return componentList.map(category => { return { name: category.title, @@ -318,17 +318,25 @@ export default { }; const list = transformMaterial(assets.componentList); - console.log('+++++', list); editor.set({ componentsMap: assets.components, componentMaterial: { - library: [{ - name: 'Fusion组件库', - id: 1 - }], + library: [ + { + name: 'Fusion组件库', + id: 1 + } + ], list } }); + + editor.set('dndHelper', { + handleResourceDragStart: function(ev, tagName, schema) { + // 物料面板中组件snippet的dragStart回调 + // ev: 原始的domEvent;tagName: 组件的描述文案;schema: snippet的schema + } + }); } } }; diff --git a/packages/editor/src/framework/areaManager.ts b/packages/editor/src/framework/areaManager.ts index 1a943d310..28f24eb0e 100644 --- a/packages/editor/src/framework/areaManager.ts +++ b/packages/editor/src/framework/areaManager.ts @@ -22,7 +22,9 @@ export default class AreaManager { const { pluginStatus } = this.editor; 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); return isUpdate; } diff --git a/packages/editor/src/framework/definitions.ts b/packages/editor/src/framework/definitions.ts index 5780d7f41..6bc6d2653 100644 --- a/packages/editor/src/framework/definitions.ts +++ b/packages/editor/src/framework/definitions.ts @@ -106,34 +106,37 @@ export interface I18nConfig { 'ja-JP'?: I18nMessages; } -export type I18nFunction = (key: string, params: any) => string | string[]; +export type I18nFunction = (key: string, params: any) => string; export interface Utils { [key: string]: (...args) => any; } - export interface PluginProps { editor: Editor; config: PluginConfig; - i18n: I18nFunction; - ref?: React.RefObject; + i18n?: I18nFunction; + ref?: React.RefObject; [key: string]: any; } - export type Plugin = React.ReactNode & { - open?: () => boolean| void| Promise; - close?: () => boolean| void| Promise; -} + open?: () => boolean | void | Promise; + close?: () => boolean | void | Promise; +}; + +export type HOCPlugin = React.ReactNode & { + open: () => Promise; + close: () => Promise; +}; export interface PluginSet { - [key: string]: Plugin; + [key: string]: HOCPlugin; } export type PluginClass = React.ComponentType & { init?: (editor: Editor) => void; -} +}; export interface PluginClassSet { [key: string]: PluginClass; @@ -149,4 +152,3 @@ export interface PluginStatus { export interface PluginStatusSet { [key: string]: PluginStatus; } - diff --git a/packages/editor/src/framework/editor.ts b/packages/editor/src/framework/editor.ts index 31ffaf071..cf1147e2c 100644 --- a/packages/editor/src/framework/editor.ts +++ b/packages/editor/src/framework/editor.ts @@ -1,13 +1,26 @@ import Debug from 'debug'; import EventEmitter from 'events'; 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'; -const { - registShortCuts, transformToPromise, unRegistShortCuts -} = editorUtils; +const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils; + +declare global { + interface Window { + __isDebug?: boolean; + __newFunc?: (funcStr: string) => (...args: any[]) => any; + } +} // 根据url参数设置debug选项 const debugRegRes = /_?debug=(.*?)(&|$)/.exec(location.search); @@ -16,6 +29,7 @@ if (debugRegRes && debugRegRes[1]) { window.__isDebug = true; store.storage.write('debug', debugRegRes[1] === 'true' ? '*' : debugRegRes[1]); } else { + // eslint-disable-next-line no-underscore-dangle window.__isDebug = false; store.remove('debug'); } @@ -23,13 +37,12 @@ if (debugRegRes && debugRegRes[1]) { // 重要,用于矫正画布执行new Function的window对象上下文 // eslint-disable-next-line no-underscore-dangle 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; // 本地调试不生效 if (location.href.indexOf('localhost') > 0) { @@ -72,7 +85,6 @@ export default class Editor extends EventEmitter { public plugins: PluginSet; - public locale: LocaleType; public emit: (msg: string, ...args) => void; @@ -89,7 +101,7 @@ export default class Editor extends EventEmitter { super(); this.config = config; this.components = components; - this.utils = {...editorUtils, ...utils}; + this.utils = { ...editorUtils, ...utils }; instance = this; this.init(); } @@ -128,7 +140,6 @@ export default class Editor extends EventEmitter { } } catch (err) { console.warn(err); - } } diff --git a/packages/editor/src/framework/index.d.ts b/packages/editor/src/framework/index.d.ts deleted file mode 100644 index 369e95da7..000000000 --- a/packages/editor/src/framework/index.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -interface Window { - __isDebug?: boolean; - __newFunc?: (funcStr: string) => ((...args: any[]) => any); -} \ No newline at end of file diff --git a/packages/editor/src/framework/pluginFactory.tsx b/packages/editor/src/framework/pluginFactory.tsx index d5298b913..f32edd9e9 100644 --- a/packages/editor/src/framework/pluginFactory.tsx +++ b/packages/editor/src/framework/pluginFactory.tsx @@ -1,30 +1,19 @@ import React, { createRef, PureComponent } from 'react'; import EditorContext from './context'; -import { I18nFunction, PluginConfig, PluginClass, Plugin } from './definitions'; +import { I18nFunction, PluginProps, PluginClass, Plugin } from './definitions'; import Editor from './editor'; import { acceptsRef, generateI18n, isEmpty, transformToPromise } from './utils'; -export interface PluginProps { - editor: Editor; - config: PluginConfig; -} - -export interface InjectedPluginProps { - i18n?: I18nFunction; -} - -export default function pluginFactory( - Comp: PluginClass -): React.ComponentType { +export default function pluginFactory(Comp: PluginClass): React.ComponentType { class LowcodePlugin extends PureComponent { public static displayName = 'LowcodeEditorPlugin'; public static contextType = EditorContext; public static init = Comp.init; - - public ref: React.RefObject; + + public ref: React.RefObject & Plugin; private editor: Editor; @@ -39,7 +28,7 @@ export default function pluginFactory( return; } const { locale, messages, editor } = props; - this.ref = createRef(); + this.ref = createRef(); // 注册插件 this.editor = editor; this.i18n = generateI18n(locale, messages); @@ -71,7 +60,6 @@ export default function pluginFactory( return Promise.resolve(); }; - public render(): React.ReactNode { const { config } = this.props; const props = { diff --git a/packages/editor/src/framework/utils.ts b/packages/editor/src/framework/utils.ts index 13cd26f80..aced7d318 100644 --- a/packages/editor/src/framework/utils.ts +++ b/packages/editor/src/framework/utils.ts @@ -28,6 +28,17 @@ const ENV = { 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 { action: string; 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 { - return (key: string, values): string | string[] => { + return (key: string, values): string => { if (!messages || !messages[key]) { return ''; } diff --git a/packages/editor/src/index.tsx b/packages/editor/src/index.tsx index f93e9b0e5..22e76df35 100644 --- a/packages/editor/src/index.tsx +++ b/packages/editor/src/index.tsx @@ -10,12 +10,9 @@ import constants from './config/constants'; import './config/locale'; import './config/setters'; -import pkg from '../package.json'; import './global.scss'; import './config/theme.scss'; -(window as any).__pkg = pkg; - const ICE_CONTAINER = document.getElementById('ice-container'); if (!ICE_CONTAINER) { @@ -26,7 +23,7 @@ ReactDOM.render( ( + component={(props): React.ReactNode => ( { - static displayName: 'LowcodePluginDesigner'; - - constructor(props) { - super(props); - } + displayName: 'LowcodePluginDesigner'; handleDesignerMount = (designer): void => { - const {editor} = this.props; + const { editor } = this.props; editor.set('designer', designer); editor.emit('designer.ready', designer); - } + }; - render() { + render(): React.ReactNode { const { editor } = this.props; return ( = (props): React.ReactElement => { return (
); -} +}; + +export default Logo; diff --git a/packages/editor/src/plugins/undoRedo/index.tsx b/packages/editor/src/plugins/undoRedo/index.tsx index d311eb68d..0def89cfe 100644 --- a/packages/editor/src/plugins/undoRedo/index.tsx +++ b/packages/editor/src/plugins/undoRedo/index.tsx @@ -1,70 +1,74 @@ import React, { PureComponent } from 'react'; import './index.scss'; -import Editor from '../../framework/index'; -import { PluginConfig } from '../../framework/definitions'; +import { PluginProps } from '../../framework/definitions'; import TopIcon from '../../skeleton/components/TopIcon/index'; -export interface PluginProps { - editor: Editor; - config: PluginConfig; +export interface IProps { logo?: string; } -export interface PluginState{ - backEnable: boolean; - forwardEnable: boolean; -}; +export interface IState { + undoEnable: boolean; + redoEnable: boolean; +} +export default class UndoRedo extends PureComponent { + public static display = 'LowcodeUndoRedo'; -export default class UndoRedo extends PureComponent { - static display = 'LowcodeUndoRedo'; + private history: any; constructor(props) { super(props); this.state = { - backEnable: false, - forwardEnable: false + undoEnable: false, + redoEnable: false }; if (props.editor.designer) { this.init(); } else { - props.editor.on('designer.ready', () => { + props.editor.on('designer.ready', (): void => { this.init(); }); } - } init = (): void => { - const {editor} = this.props; - this.designer = editor.designer; - this.history = this.designer.currentHistory; - editor.on('designer.history-change', (history) => { + const { editor } = this.props; + this.history = editor.designer.currentHistory; + this.updateState(this.history.getState()); + editor.on('designer.history-change', (history): void => { 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) { this.history.back(); } }; - handleForwardClick = (): void => { + handleRedoClick = (): void => { if (this.history) { this.history.forward(); } }; - render() { - const { - backEnable, - forwardEnable - } = this.state; + render(): React.ReactNode { + const { undoEnable, redoEnable } = this.state; return (
- - + +
); } diff --git a/packages/editor/src/skeleton/components/LeftPlugin/index.scss b/packages/editor/src/skeleton/components/LeftPlugin/index.scss index d237581b0..f1e7876d3 100644 --- a/packages/editor/src/skeleton/components/LeftPlugin/index.scss +++ b/packages/editor/src/skeleton/components/LeftPlugin/index.scss @@ -45,7 +45,7 @@ } &:hover { color: $color-brand1-6; - } + } } &.disabled { cursor: not-allowed; diff --git a/packages/editor/src/skeleton/components/LeftPlugin/index.tsx b/packages/editor/src/skeleton/components/LeftPlugin/index.tsx index a2cfe1571..eafe894ee 100644 --- a/packages/editor/src/skeleton/components/LeftPlugin/index.tsx +++ b/packages/editor/src/skeleton/components/LeftPlugin/index.tsx @@ -30,7 +30,7 @@ export default class LeftPlugin extends PureComponent {} + onClick: (): void => {} }; constructor(props, context) { @@ -40,7 +40,7 @@ export default class LeftPlugin extends PureComponent { + handleClose = (): void => { const { config, editor } = this.props; const pluginKey = config && config.pluginKey; const plugin = editor.plugins && editor.plugins[pluginKey]; - if (plugin) { - plugin.close().then(() => { + if (plugin && plugin.close) { + plugin.close().then((): void => { this.setState({ dialogVisible: false }); @@ -71,24 +71,26 @@ export default class LeftPlugin extends PureComponent { + handleOpen = (): void => { // todo 对话框类型的插件初始时拿不到插件实例 this.setState({ dialogVisible: true }); }; - handleShow = () => { + handleShow = (): void => { const { disabled, config, onClick, editor } = this.props; const pluginKey = config && config.pluginKey; if (disabled || !pluginKey) return; // 考虑到弹窗情况,延时发送消息 - setTimeout(() => editor.emit(`${pluginKey}.addon.activate`), 0); + setTimeout((): void => editor.emit(`${pluginKey}.plugin.activate`), 0); this.handleOpen(); - onClick && onClick(); + if (onClick) { + onClick(); + } }; - renderIcon = clickCallback => { + renderIcon = (clickCallback): React.ReactNode => { const { active, disabled, marked, locked, onClick, config } = this.props; const { pluginKey, props } = config || {}; const { icon, title } = props || {}; @@ -100,10 +102,11 @@ export default class LeftPlugin extends PureComponent { + onClick={(): void => { if (disabled) return; // 考虑到弹窗情况,延时发送消息 clickCallback && clickCallback(); + onClick && onClick(); }} > @@ -118,7 +121,7 @@ export default class LeftPlugin extends PureComponent { + onClick={(): void => { onClick && onClick.call(null, editor); }} {...pluginProps} @@ -145,24 +148,24 @@ export default class LeftPlugin extends PureComponent - {this.renderIcon(() => { + {this.renderIcon((): void => { onClick && onClick.call(null, editor); })}
); case 'Icon': - return this.renderIcon(() => { + return this.renderIcon((): void => { onClick && onClick.call(null, editor); }); case 'DialogIcon': return ( - {this.renderIcon(() => { + {this.renderIcon((): void => { onClick && onClick.call(null, editor); this.handleOpen(); })} { + onOk={(): void => { editor.emit(`${pluginKey}.dialog.onOk`); this.handleClose(); }} @@ -171,7 +174,7 @@ export default class LeftPlugin extends PureComponent { + trigger={this.renderIcon((): void => { onClick && onClick.call(null, editor); })} align="r" @@ -194,7 +197,7 @@ export default class LeftPlugin extends PureComponent ); case 'PanelIcon': - return this.renderIcon(() => { + return this.renderIcon((): void => { onClick && onClick.call(null, editor); this.handleOpen(); }); diff --git a/packages/editor/src/skeleton/components/Panel/index.tsx b/packages/editor/src/skeleton/components/Panel/index.tsx index a1b9a9a8e..611877d46 100644 --- a/packages/editor/src/skeleton/components/Panel/index.tsx +++ b/packages/editor/src/skeleton/components/Panel/index.tsx @@ -37,7 +37,7 @@ export default class Panel extends PureComponent { }; } - render() { + render(): React.ReactNode { const { align, draggable, floatable, visible } = this.props; const { width } = this.state; return ( diff --git a/packages/editor/src/skeleton/components/TopIcon/index.tsx b/packages/editor/src/skeleton/components/TopIcon/index.tsx index 40750d03a..2c14d8d33 100644 --- a/packages/editor/src/skeleton/components/TopIcon/index.tsx +++ b/packages/editor/src/skeleton/components/TopIcon/index.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import classNames from 'classnames'; -import { Icon, Button } from '@alifd/next'; +import { Icon } from '@alifd/next'; import './index.scss'; @@ -27,22 +27,25 @@ export default class TopIcon extends PureComponent { icon: '', id: '', locked: false, - onClick: () => {}, + onClick: (): void => {}, style: {}, title: '' }; - render() { + render(): React.ReactNode { const { active, disabled, icon, locked, title, className, id, style, onClick } = this.props; return ( -
+
); diff --git a/packages/editor/src/skeleton/components/TopPlugin/index.tsx b/packages/editor/src/skeleton/components/TopPlugin/index.tsx index e51893b15..70c653f4f 100644 --- a/packages/editor/src/skeleton/components/TopPlugin/index.tsx +++ b/packages/editor/src/skeleton/components/TopPlugin/index.tsx @@ -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 TopIcon from '../TopIcon'; @@ -31,7 +31,7 @@ export default class TopPlugin extends PureComponent {} + onClick: (): void => {} }; constructor(props, context) { @@ -41,7 +41,7 @@ export default class TopPlugin extends PureComponent { + handleShow = (): void => { const { disabled, config, onClick, editor } = this.props; const pluginKey = config && config.pluginKey; if (disabled || !pluginKey) return; // 考虑到弹窗情况,延时发送消息 - setTimeout(() => editor.emit(`${pluginKey}.plugin.activate`), 0); + setTimeout((): void => editor.emit(`${pluginKey}.plugin.activate`), 0); this.handleOpen(); onClick && onClick(); }; - handleClose = () => { + handleClose = (): void => { const { config, editor } = this.props; const pluginKey = config && config.pluginKey; const plugin = editor.plugins && editor.plugins[pluginKey]; - if (plugin) { - plugin.close().then(() => { + if (plugin && plugin.close) { + plugin.close().then((): void => { this.setState({ dialogVisible: false }); @@ -82,14 +82,14 @@ export default class TopPlugin extends PureComponent { + handleOpen = (): void => { // todo dialog类型的插件初始时拿不动插件实例 this.setState({ dialogVisible: true }); }; - renderIcon = clickCallback => { + renderIcon = (clickCallback): React.ReactNode => { const { active, disabled, marked, locked, config, onClick, editor } = this.props; const { pluginKey, props } = config || {}; const { icon, title } = props || {}; @@ -101,10 +101,10 @@ export default class TopPlugin extends PureComponent { + onClick={(): void => { if (disabled) return; // 考虑到弹窗情况,延时发送消息 - setTimeout(() => editor.emit(`${pluginKey}.plugin.activate`), 0); + setTimeout((): void => editor.emit(`${pluginKey}.plugin.activate`), 0); clickCallback && clickCallback(); onClick && onClick(); }} @@ -113,8 +113,8 @@ export default class TopPlugin extends PureComponent{node} : node; }; - render() { - const { active, marked, locked, disabled, config, editor, pluginClass: Comp } = this.props; + render(): React.ReactNode { + const { active, marked, locked, disabled, config, editor, pluginClass: Comp, style } = this.props; const { pluginKey, pluginProps, props, type } = config || {}; const { onClick, title } = props || {}; const { dialogVisible } = this.state; @@ -127,7 +127,7 @@ export default class TopPlugin extends PureComponent { + onClick={(): void => { onClick && onClick.call(null, editor); }} {...pluginProps} @@ -139,24 +139,24 @@ export default class TopPlugin extends PureComponent - {this.renderIcon(() => { + {this.renderIcon((): void => { onClick && onClick.call(null, editor); })} ); case 'Icon': - return this.renderIcon(() => { + return this.renderIcon((): void => { onClick && onClick.call(null, editor); }); case 'DialogIcon': return ( - {this.renderIcon(() => { + {this.renderIcon((): void => { onClick && onClick.call(null, editor); this.handleOpen(); })} { + onOk={(): void => { editor.emit(`${pluginKey}.dialog.onOk`); this.handleClose(); }} @@ -165,7 +165,7 @@ export default class TopPlugin extends PureComponent { + trigger={this.renderIcon((): void => { onClick && onClick.call(null, editor); })} triggerType={['click', 'hover']} diff --git a/packages/editor/src/skeleton/global.scss b/packages/editor/src/skeleton/global.scss index 8eb107e0f..72f7b8525 100644 --- a/packages/editor/src/skeleton/global.scss +++ b/packages/editor/src/skeleton/global.scss @@ -9,7 +9,6 @@ body { color: $color-text1-3; } - .next-loading { .next-loading-wrap { height: 100%; diff --git a/packages/editor/src/skeleton/index.tsx b/packages/editor/src/skeleton/index.tsx index c6eee9f53..c30a0fc88 100644 --- a/packages/editor/src/skeleton/index.tsx +++ b/packages/editor/src/skeleton/index.tsx @@ -1,10 +1,9 @@ import React, { PureComponent } from 'react'; -import { HashRouter as Router, Route } from 'react-router-dom'; import { Loading, ConfigProvider } from '@alifd/next'; 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 defaultConfig from './config/skeleton'; @@ -19,8 +18,17 @@ import './global.scss'; let renderIdx = 0; +declare global { + interface Window { + __ctx: { + editor: Editor; + appHelper: Editor; + }; + } +} + export interface SkeletonProps { - components: PluginComponents; + components: PluginClassSet; config: EditorConfig; history: object; location: object; @@ -29,15 +37,15 @@ export interface SkeletonProps { } export interface SkeletonState { - initReady: boolean; - skeletonKey: string; + initReady?: boolean; + skeletonKey?: string; __hasError?: boolean; } export default class Skeleton extends PureComponent { static displayName = 'LowcodeEditorSkeleton'; - static getDerivedStateFromError() { + static getDerivedStateFromError(): SkeletonState { return { __hasError: true }; @@ -56,11 +64,11 @@ export default class Skeleton extends PureComponent { + editor.once('editor.reset', (): void => { this.setState({ initReady: false }); @@ -85,14 +95,14 @@ export default class Skeleton extends PureComponent { + this.editor.init().then((): void => { this.setState( { initReady: true, // 刷新IDE时生成新的skeletonKey保证插件生命周期重新执行 skeletonKey: isReset ? `skeleton${++renderIdx}` : this.state.skeletonKey }, - () => { + (): void => { editor.emit('editor.ready'); editor.emit('ide.ready'); isReset && editor.emit('ide.afterReset'); @@ -101,7 +111,7 @@ export default class Skeleton extends PureComponent { static displayName = 'LowcodeCenterArea'; private editor: Editor; + private areaManager: AreaManager; constructor(props) { @@ -20,10 +21,11 @@ export default class CenterArea extends PureComponent { this.areaManager = new AreaManager(this.editor, 'centerArea'); } - componentDidMount() { + componentDidMount(): void { this.editor.on('skeleton.update', this.handleSkeletonUpdate); } - componentWillUnmount() { + + componentWillUnmount(): void { this.editor.off('skeleton.update', this.handleSkeletonUpdate); } @@ -34,14 +36,16 @@ export default class CenterArea extends PureComponent { } }; - render() { + render(): React.ReactNode { const visiblePluginList = this.areaManager.getVisiblePluginList(); return (
- {visiblePluginList.map(item => { - const Comp = this.editor.components[item.pluginKey]; - return ; - })} + {visiblePluginList.map( + (item): React.ReactNode => { + const Comp = this.editor.components[item.pluginKey]; + return ; + } + )}
); } diff --git a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx index 61ba3791a..cd749073a 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx +++ b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx @@ -21,7 +21,7 @@ export default class LeftAreaNav extends PureComponent item.type === 'IconPanel'); @@ -42,7 +42,7 @@ export default class LeftAreaNav extends PureComponent { + nextPlugin.open().then((): void => { this.updateActiveKey(key); }); } } else if (activeKey === key) { if (prePlugin) { - prePlugin.close().then(() => { + prePlugin.close().then((): void => { this.updateActiveKey('none'); }); } - } else { + } else if (prePlugin) { // 先关后开 - if (prePlugin) { - prePlugin.close().then(() => { - if (nextPlugin) { - nextPlugin.open().then(() => { - this.updateActiveKey(key); - }); - } - }); - } + prePlugin.close().then((): void => { + if (nextPlugin) { + nextPlugin.open().then((): void => { + this.updateActiveKey(key); + }); + } + }); } }; @@ -111,9 +109,9 @@ export default class LeftAreaNav extends PureComponent { - if (key === 'none') { - this.cacheActiveKey = this.state.activeKey; - } + // if (key === 'none') { + // this.cacheActiveKey = this.state.activeKey; + // } this.editor.set('leftNav', key); this.setState({ activeKey: key }); this.editor.emit('leftPanel.show', key); @@ -121,31 +119,32 @@ export default class LeftAreaNav extends PureComponent { const { activeKey } = this.state; - return list.map((item, idx) => { - const pluginStatus = this.editor.pluginStatus[item.pluginKey]; - return ( - this.handlePluginClick(item)} - active={activeKey === item.pluginKey} - {...pluginStatus} - /> - ); - }); + return list.map( + (item): React.ReactElement => { + const pluginStatus = this.editor.pluginStatus[item.pluginKey]; + return ( + this.handlePluginClick(item)} + active={activeKey === item.pluginKey} + {...pluginStatus} + /> + ); + } + ); }; - render() { - const { activeKey } = this.state; + render(): React.ReactNode { const topList: PluginConfig[] = []; const bottomList: PluginConfig[] = []; const visiblePluginList = this.areaManager.getVisiblePluginList(); - if (isEmpty(visiblePluginList)){ + if (isEmpty(visiblePluginList)) { return null; } - visiblePluginList.forEach(item => { + visiblePluginList.forEach((item): void => { const align = item.props && item.props.align === 'bottom' ? 'bottom' : 'top'; if (align === 'bottom') { bottomList.push(item); diff --git a/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx b/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx index 281e23246..31f2c5343 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx +++ b/packages/editor/src/skeleton/layouts/LeftArea/panel.tsx @@ -16,6 +16,7 @@ export default class LeftAreaPanel extends PureComponent - {list.map((item, idx) => { - const Comp = this.editor.components[item.pluginKey]; - return ( - - - - ); - })} + {list.map( + (item): React.ReactElement => { + const Comp = this.editor.components[item.pluginKey]; + return ( + + + + ); + } + )}
); } diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.scss b/packages/editor/src/skeleton/layouts/RightArea/index.scss index 563179f02..7373933b0 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.scss +++ b/packages/editor/src/skeleton/layouts/RightArea/index.scss @@ -6,7 +6,7 @@ .right-panel { overflow: auto; - border-top: 2px solid $color-line1-1; + // border-top: 2px solid $color-line1-1; } //tab定义 diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.tsx b/packages/editor/src/skeleton/layouts/RightArea/index.tsx index 8f23ba2a3..64c44af50 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/RightArea/index.tsx @@ -30,7 +30,7 @@ export default class RightArea extends PureComponent { + currentPlugin.close().then((): void => { this.setState( { activeKey: '' }, - () => { + (): void => { const visiblePluginList = this.areaManager.getVisiblePluginList(); const firstPlugin = visiblePluginList && visiblePluginList[0]; if (firstPlugin) { @@ -75,12 +75,12 @@ export default class RightArea extends PureComponent { const activeKey = this.state.activeKey; const plugins = this.editor.plugins || {}; - const openPlugin = () => { + const openPlugin = (): void => { if (!plugins[key]) { console.error(`plugin ${key} has not regist in the editor`); return; } - plugins[key].open().then(() => { + plugins[key].open().then((): void => { this.editor.set('rightNav', key); this.setState({ activeKey: key @@ -89,7 +89,7 @@ export default class RightArea extends PureComponent { + plugins[activeKey].close().then((): void => { openPlugin(); }); } else { @@ -109,12 +109,7 @@ export default class RightArea extends PureComponent - {!!icon && ( - - )} + {!!icon && } {title}
); @@ -124,7 +119,7 @@ export default class RightArea extends PureComponent { + renderTabPanels = (list: PluginConfig[], height: string): React.ReactNode => { if (isEmpty(list)) { return null; } @@ -138,37 +133,41 @@ export default class RightArea extends PureComponent - {list.map((item, idx) => { - const Comp = this.editor.components[item.pluginKey]; - return ( - - - - ); - })} + {list.map( + (item): React.ReactElement => { + const Comp = this.editor.components[item.pluginKey]; + return ( + + + + ); + } + )}
); - } + }; - renderPanels = (list: PluginConfig[], height: string): void => { - return list.map((item) => { - const Comp = this.editor.components[item.pluginKey]; - return ( -
- -
- ); - }); - } + renderPanels = (list: PluginConfig[], height: string): React.ReactNode => { + return list.map( + (item): React.ReactElement => { + const Comp = this.editor.components[item.pluginKey]; + return ( +
+ +
+ ); + } + ); + }; - render() { + render(): React.ReactNode { const tabList = this.areaManager.getVisiblePluginList('TabPanel'); const panelList = this.areaManager.getVisiblePluginList('Panel'); if (isEmpty(panelList) && isEmpty(tabList)) { diff --git a/packages/editor/src/skeleton/layouts/TopArea/index.scss b/packages/editor/src/skeleton/layouts/TopArea/index.scss index 10669ba51..a22456894 100644 --- a/packages/editor/src/skeleton/layouts/TopArea/index.scss +++ b/packages/editor/src/skeleton/layouts/TopArea/index.scss @@ -4,7 +4,7 @@ left: 0; width: 100%; height: 50px; - background-color: $card-background; + background-color: $card-background; border-bottom: 2px solid $color-line1-1; user-select: none; .divider { diff --git a/packages/editor/src/skeleton/layouts/TopArea/index.tsx b/packages/editor/src/skeleton/layouts/TopArea/index.tsx index 39adbb825..d6b33453c 100644 --- a/packages/editor/src/skeleton/layouts/TopArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/TopArea/index.tsx @@ -25,11 +25,11 @@ export default class TopArea extends PureComponent { this.areaManager = new AreaManager(props.editor, 'topArea'); } - componentDidMount() { + componentDidMount(): void { this.editor.on('skeleton.update', this.handleSkeletonUpdate); } - componentWillUnmount() { + componentWillUnmount(): void { this.editor.off('skeleton.update', this.handleSkeletonUpdate); } @@ -41,30 +41,32 @@ export default class TopArea extends PureComponent { }; renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => { - return list.map((item, idx) => { - const isDivider = item.type === 'Divider'; - return ( - - {!isDivider && ( - - )} - - ); - }); + return list.map( + (item, idx): React.ReactElement => { + const isDivider = item.type === 'Divider'; + return ( + + {!isDivider && ( + + )} + + ); + } + ); }; - render() { + render(): React.ReactNode { const leftList: PluginConfig[] = []; const rightList: PluginConfig[] = []; const visiblePluginList = this.areaManager.getVisiblePluginList(); - visiblePluginList.forEach(item => { + visiblePluginList.forEach((item): void => { const align = item.props && item.props.align === 'right' ? 'right' : 'left'; // 分隔符不允许相邻 if (item.type === 'Divider') {