mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-04-20 04:18:05 +00:00
feat:editor-framework,editor-skeleton拆包
This commit is contained in:
parent
f7baf5be32
commit
9df6769016
@ -7,6 +7,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/iceluna-sdk": "^1.0.5-beta.12",
|
"@ali/iceluna-sdk": "^1.0.5-beta.12",
|
||||||
|
"@ali/lowcode-editor-framework": "^0.0.1",
|
||||||
"@recore/obx": "^1.0.8",
|
"@recore/obx": "^1.0.8",
|
||||||
"@recore/obx-react": "^1.0.7",
|
"@recore/obx-react": "^1.0.7",
|
||||||
"@types/medium-editor": "^5.0.3",
|
"@types/medium-editor": "^5.0.3",
|
||||||
|
|||||||
@ -1,5 +1,16 @@
|
|||||||
const { eslint, deepmerge } = require('@ice/spec');
|
const { tslint, deepmerge } = require('@ice/spec');
|
||||||
|
|
||||||
module.exports = deepmerge(eslint, {
|
module.exports = deepmerge(tslint, {
|
||||||
rules: {},
|
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/explicit-member-accessibility": 0
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
15
packages/editor-framework/es/areaManager.d.ts
vendored
Normal file
15
packages/editor-framework/es/areaManager.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { PluginConfig, PluginStatus, PluginClass, HOCPlugin } from './definitions';
|
||||||
|
import Editor from './index';
|
||||||
|
export default class AreaManager {
|
||||||
|
private pluginStatus;
|
||||||
|
private config;
|
||||||
|
private editor;
|
||||||
|
private area;
|
||||||
|
constructor(editor: Editor, area: string);
|
||||||
|
isPluginStatusUpdate(pluginType?: string, notUpdateStatus?: boolean): boolean;
|
||||||
|
getVisiblePluginList(pluginType?: string): PluginConfig[];
|
||||||
|
getPlugin(pluginKey: string): HOCPlugin | void;
|
||||||
|
getPluginConfig(pluginKey?: string): PluginConfig[] | PluginConfig | undefined;
|
||||||
|
getPluginClass(pluginKey: string): PluginClass | void;
|
||||||
|
getPluginStatus(pluginKey: string): PluginStatus | void;
|
||||||
|
}
|
||||||
77
packages/editor-framework/es/areaManager.js
Normal file
77
packages/editor-framework/es/areaManager.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { clone, deepEqual } from './utils';
|
||||||
|
|
||||||
|
var AreaManager = /*#__PURE__*/function () {
|
||||||
|
function AreaManager(editor, area) {
|
||||||
|
this.pluginStatus = void 0;
|
||||||
|
this.config = void 0;
|
||||||
|
this.editor = void 0;
|
||||||
|
this.area = void 0;
|
||||||
|
this.editor = editor;
|
||||||
|
this.area = area;
|
||||||
|
this.config = editor && editor.config && editor.config.plugins && editor.config.plugins[this.area] || [];
|
||||||
|
this.pluginStatus = clone(editor.pluginStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
var _proto = AreaManager.prototype;
|
||||||
|
|
||||||
|
_proto.isPluginStatusUpdate = function isPluginStatusUpdate(pluginType, notUpdateStatus) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var pluginStatus = this.editor.pluginStatus;
|
||||||
|
var list = pluginType ? this.config.filter(function (item) {
|
||||||
|
return item.type === pluginType;
|
||||||
|
}) : this.config;
|
||||||
|
var isUpdate = list.some(function (item) {
|
||||||
|
return !deepEqual(pluginStatus[item.pluginKey], _this.pluginStatus[item.pluginKey]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!notUpdateStatus) {
|
||||||
|
this.pluginStatus = clone(pluginStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isUpdate;
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.getVisiblePluginList = function getVisiblePluginList(pluginType) {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
var res = this.config.filter(function (item) {
|
||||||
|
return !!(!_this2.pluginStatus[item.pluginKey] || _this2.pluginStatus[item.pluginKey].visible);
|
||||||
|
});
|
||||||
|
return pluginType ? res.filter(function (item) {
|
||||||
|
return item.type === pluginType;
|
||||||
|
}) : res;
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.getPlugin = function getPlugin(pluginKey) {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.editor && this.editor.plugins && this.editor.plugins[pluginKey];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.getPluginConfig = function getPluginConfig(pluginKey) {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.config.find(function (item) {
|
||||||
|
return item.pluginKey === pluginKey;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.config;
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.getPluginClass = function getPluginClass(pluginKey) {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.editor && this.editor.components && this.editor.components[pluginKey];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.getPluginStatus = function getPluginStatus(pluginKey) {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.editor && this.editor.pluginStatus && this.editor.pluginStatus[pluginKey];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return AreaManager;
|
||||||
|
}();
|
||||||
|
|
||||||
|
export { AreaManager as default };
|
||||||
130
packages/editor-framework/es/definitions.d.ts
vendored
Normal file
130
packages/editor-framework/es/definitions.d.ts
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import Editor from './editor';
|
||||||
|
export interface EditorConfig {
|
||||||
|
skeleton?: SkeletonConfig;
|
||||||
|
theme?: ThemeConfig;
|
||||||
|
plugins?: PluginsConfig;
|
||||||
|
hooks?: HooksConfig;
|
||||||
|
shortCuts?: ShortCutsConfig;
|
||||||
|
utils?: UtilsConfig;
|
||||||
|
constants?: ConstantsConfig;
|
||||||
|
lifeCycles?: LifeCyclesConfig;
|
||||||
|
i18n?: I18nConfig;
|
||||||
|
}
|
||||||
|
export interface NpmConfig {
|
||||||
|
version: string;
|
||||||
|
package: string;
|
||||||
|
main?: string;
|
||||||
|
exportName?: string;
|
||||||
|
subName?: string;
|
||||||
|
destructuring?: boolean;
|
||||||
|
}
|
||||||
|
export interface SkeletonConfig {
|
||||||
|
config: NpmConfig;
|
||||||
|
props?: object;
|
||||||
|
handler?: (config: EditorConfig) => EditorConfig;
|
||||||
|
}
|
||||||
|
export interface FusionTheme {
|
||||||
|
package: string;
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
export interface ThemeConfig {
|
||||||
|
fusion?: FusionTheme;
|
||||||
|
}
|
||||||
|
export interface PluginsConfig {
|
||||||
|
[key: string]: PluginConfig[];
|
||||||
|
}
|
||||||
|
export interface PluginConfig {
|
||||||
|
pluginKey: string;
|
||||||
|
type: string;
|
||||||
|
props: {
|
||||||
|
icon?: string;
|
||||||
|
title?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
visible?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
align?: 'left' | 'right' | 'top' | 'bottom';
|
||||||
|
onClick?: () => void;
|
||||||
|
dialogProps?: object;
|
||||||
|
balloonProps?: object;
|
||||||
|
panelProps?: object;
|
||||||
|
linkProps?: object;
|
||||||
|
};
|
||||||
|
config?: NpmConfig;
|
||||||
|
pluginProps?: object;
|
||||||
|
}
|
||||||
|
export declare type HooksConfig = HookConfig[];
|
||||||
|
export interface HookConfig {
|
||||||
|
message: string;
|
||||||
|
type: 'on' | 'once';
|
||||||
|
handler: (editor: Editor, ...args: []) => void;
|
||||||
|
}
|
||||||
|
export declare type ShortCutsConfig = ShortCutConfig[];
|
||||||
|
export interface ShortCutConfig {
|
||||||
|
keyboard: string;
|
||||||
|
handler: (editor: Editor, ev: Event, keymaster: any) => void;
|
||||||
|
}
|
||||||
|
export declare type UtilsConfig = UtilConfig[];
|
||||||
|
export interface UtilConfig {
|
||||||
|
name: string;
|
||||||
|
type: 'npm' | 'function';
|
||||||
|
content: NpmConfig | ((...args: []) => any);
|
||||||
|
}
|
||||||
|
export declare type ConstantsConfig = object;
|
||||||
|
export interface LifeCyclesConfig {
|
||||||
|
init?: (editor: Editor) => any;
|
||||||
|
destroy?: (editor: Editor) => any;
|
||||||
|
}
|
||||||
|
export declare type LocaleType = 'zh-CN' | 'zh-TW' | 'en-US' | 'ja-JP';
|
||||||
|
export interface I18nMessages {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
export interface I18nConfig {
|
||||||
|
'zh-CN'?: I18nMessages;
|
||||||
|
'zh-TW'?: I18nMessages;
|
||||||
|
'en-US'?: I18nMessages;
|
||||||
|
'ja-JP'?: I18nMessages;
|
||||||
|
}
|
||||||
|
export declare 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<React.ReactElement>;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
export declare type Plugin = React.ReactNode & {
|
||||||
|
open?: () => boolean | void | Promise<any>;
|
||||||
|
close?: () => boolean | void | Promise<any>;
|
||||||
|
};
|
||||||
|
export declare type HOCPlugin = React.ReactNode & {
|
||||||
|
open: () => Promise<any>;
|
||||||
|
close: () => Promise<any>;
|
||||||
|
};
|
||||||
|
export interface PluginSet {
|
||||||
|
[key: string]: HOCPlugin;
|
||||||
|
}
|
||||||
|
export declare type PluginClass = React.ComponentType<PluginProps> & {
|
||||||
|
init?: (editor: Editor) => void;
|
||||||
|
defaultProps?: {
|
||||||
|
locale?: LocaleType;
|
||||||
|
messages?: I18nMessages;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export interface PluginClassSet {
|
||||||
|
[key: string]: PluginClass;
|
||||||
|
}
|
||||||
|
export interface PluginStatus {
|
||||||
|
disabled?: boolean;
|
||||||
|
visible?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
locked?: boolean;
|
||||||
|
}
|
||||||
|
export interface PluginStatusSet {
|
||||||
|
[key: string]: PluginStatus;
|
||||||
|
}
|
||||||
33
packages/editor-framework/es/editor.d.ts
vendored
Normal file
33
packages/editor-framework/es/editor.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { EditorConfig, LocaleType, PluginStatusSet, Utils, PluginClassSet, PluginSet } from './definitions';
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__isDebug?: boolean;
|
||||||
|
__newFunc?: (funcStr: string) => (...args: any[]) => any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export interface HooksFuncs {
|
||||||
|
[idx: number]: (msg: string, handler: (...args: any[]) => void) => void;
|
||||||
|
}
|
||||||
|
export default class Editor extends EventEmitter {
|
||||||
|
static getInstance: (config: EditorConfig, components: PluginClassSet, utils?: Utils) => Editor;
|
||||||
|
config: EditorConfig;
|
||||||
|
components: PluginClassSet;
|
||||||
|
utils: Utils;
|
||||||
|
pluginStatus: PluginStatusSet;
|
||||||
|
plugins: PluginSet;
|
||||||
|
locale: LocaleType;
|
||||||
|
private hooksFuncs;
|
||||||
|
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils);
|
||||||
|
init(): Promise<any>;
|
||||||
|
destroy(): void;
|
||||||
|
get(key: string): any;
|
||||||
|
set(key: string | object, val: any): void;
|
||||||
|
batchOn(events: string[], lisenter: (...args: any[]) => void): void;
|
||||||
|
batchOnce(events: string[], lisenter: (...args: any[]) => void): void;
|
||||||
|
batchOff(events: string[], lisenter: (...args: any[]) => void): void;
|
||||||
|
private destroyHooks;
|
||||||
|
private initHooks;
|
||||||
|
private initPluginStatus;
|
||||||
|
}
|
||||||
283
packages/editor-framework/es/editor.js
Normal file
283
packages/editor-framework/es/editor.js
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
|
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
|
||||||
|
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
|
||||||
|
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
||||||
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
|
|
||||||
|
function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
||||||
|
|
||||||
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
||||||
|
|
||||||
|
import Debug from 'debug';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import store from 'store';
|
||||||
|
import * as editorUtils from './utils';
|
||||||
|
var registShortCuts = editorUtils.registShortCuts,
|
||||||
|
transformToPromise = editorUtils.transformToPromise,
|
||||||
|
unRegistShortCuts = editorUtils.unRegistShortCuts;
|
||||||
|
// 根据url参数设置debug选项
|
||||||
|
var debugRegRes = /_?debug=(.*?)(&|$)/.exec(location.search);
|
||||||
|
|
||||||
|
if (debugRegRes && debugRegRes[1]) {
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
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');
|
||||||
|
} // 重要,用于矫正画布执行new Function的window对象上下文
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
|
||||||
|
|
||||||
|
window.__newFunc = function (funContext) {
|
||||||
|
// eslint-disable-next-line no-new-func
|
||||||
|
return new Function(funContext);
|
||||||
|
}; // 关闭浏览器前提醒,只有产生过交互才会生效
|
||||||
|
|
||||||
|
|
||||||
|
window.onbeforeunload = function (e) {
|
||||||
|
var ev = e || window.event; // 本地调试不生效
|
||||||
|
|
||||||
|
if (location.href.indexOf('localhost') > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg = '您确定要离开此页面吗?';
|
||||||
|
ev.cancelBubble = true;
|
||||||
|
ev.returnValue = true;
|
||||||
|
|
||||||
|
if (e.stopPropagation) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
var instance;
|
||||||
|
var debug = Debug('editor');
|
||||||
|
EventEmitter.defaultMaxListeners = 100;
|
||||||
|
|
||||||
|
var Editor = /*#__PURE__*/function (_EventEmitter) {
|
||||||
|
_inheritsLoose(Editor, _EventEmitter);
|
||||||
|
|
||||||
|
var _super = _createSuper(Editor);
|
||||||
|
|
||||||
|
function Editor(config, components, utils) {
|
||||||
|
var _this;
|
||||||
|
|
||||||
|
_this = _EventEmitter.call(this) || this;
|
||||||
|
_this.config = void 0;
|
||||||
|
_this.components = void 0;
|
||||||
|
_this.utils = void 0;
|
||||||
|
_this.pluginStatus = void 0;
|
||||||
|
_this.plugins = void 0;
|
||||||
|
_this.locale = void 0;
|
||||||
|
_this.hooksFuncs = void 0;
|
||||||
|
_this.config = config;
|
||||||
|
_this.components = components;
|
||||||
|
_this.utils = _extends({}, editorUtils, {}, utils);
|
||||||
|
instance = _assertThisInitialized(_this);
|
||||||
|
|
||||||
|
_this.init();
|
||||||
|
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _proto = Editor.prototype;
|
||||||
|
|
||||||
|
_proto.init = function init() {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
var _ref = this.config || {},
|
||||||
|
hooks = _ref.hooks,
|
||||||
|
_ref$shortCuts = _ref.shortCuts,
|
||||||
|
shortCuts = _ref$shortCuts === void 0 ? [] : _ref$shortCuts,
|
||||||
|
lifeCycles = _ref.lifeCycles;
|
||||||
|
|
||||||
|
this.locale = store.get('lowcode-editor-locale') || 'zh-CN'; // this.messages = this.messagesSet[this.locale];
|
||||||
|
// this.i18n = generateI18n(this.locale, this.messages);
|
||||||
|
|
||||||
|
this.pluginStatus = this.initPluginStatus();
|
||||||
|
this.initHooks(hooks || []);
|
||||||
|
this.emit('editor.beforeInit');
|
||||||
|
|
||||||
|
var init = lifeCycles && lifeCycles.init || function () {}; // 用户可以通过设置extensions.init自定义初始化流程;
|
||||||
|
|
||||||
|
|
||||||
|
return transformToPromise(init(this)).then(function () {
|
||||||
|
// 注册快捷键
|
||||||
|
registShortCuts(shortCuts, _this2);
|
||||||
|
|
||||||
|
_this2.emit('editor.afterInit');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.destroy = function destroy() {
|
||||||
|
debug('destroy');
|
||||||
|
|
||||||
|
try {
|
||||||
|
var _this$config = this.config,
|
||||||
|
_this$config$hooks = _this$config.hooks,
|
||||||
|
hooks = _this$config$hooks === void 0 ? [] : _this$config$hooks,
|
||||||
|
_this$config$shortCut = _this$config.shortCuts,
|
||||||
|
shortCuts = _this$config$shortCut === void 0 ? [] : _this$config$shortCut,
|
||||||
|
_this$config$lifeCycl = _this$config.lifeCycles,
|
||||||
|
lifeCycles = _this$config$lifeCycl === void 0 ? {} : _this$config$lifeCycl;
|
||||||
|
unRegistShortCuts(shortCuts);
|
||||||
|
this.destroyHooks(hooks);
|
||||||
|
|
||||||
|
if (lifeCycles.destroy) {
|
||||||
|
lifeCycles.destroy(this);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.get = function get(key) {
|
||||||
|
return this[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.set = function set(key, val) {
|
||||||
|
var _this3 = this;
|
||||||
|
|
||||||
|
if (typeof key === 'string') {
|
||||||
|
if (['init', 'destroy', 'get', 'set', 'batchOn', 'batchOff', 'batchOnce'].includes(key)) {
|
||||||
|
console.error('init, destroy, get, set, batchOn, batchOff, batchOnce is private attribute');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this[key] = val;
|
||||||
|
} else if (typeof key === 'object') {
|
||||||
|
Object.keys(key).forEach(function (item) {
|
||||||
|
_this3[item] = key[item];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.batchOn = function batchOn(events, lisenter) {
|
||||||
|
var _this4 = this;
|
||||||
|
|
||||||
|
if (!Array.isArray(events)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.forEach(function (event) {
|
||||||
|
_this4.on(event, lisenter);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.batchOnce = function batchOnce(events, lisenter) {
|
||||||
|
var _this5 = this;
|
||||||
|
|
||||||
|
if (!Array.isArray(events)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.forEach(function (event) {
|
||||||
|
_this5.once(event, lisenter);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.batchOff = function batchOff(events, lisenter) {
|
||||||
|
var _this6 = this;
|
||||||
|
|
||||||
|
if (!Array.isArray(events)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.forEach(function (event) {
|
||||||
|
_this6.off(event, lisenter);
|
||||||
|
});
|
||||||
|
} // 销毁hooks中的消息监听
|
||||||
|
;
|
||||||
|
|
||||||
|
_proto.destroyHooks = function destroyHooks(hooks) {
|
||||||
|
var _this7 = this;
|
||||||
|
|
||||||
|
if (hooks === void 0) {
|
||||||
|
hooks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks.forEach(function (item, idx) {
|
||||||
|
if (typeof _this7.hooksFuncs[idx] === 'function') {
|
||||||
|
_this7.off(item.message, _this7.hooksFuncs[idx]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
delete this.hooksFuncs;
|
||||||
|
} // 初始化hooks中的消息监听
|
||||||
|
;
|
||||||
|
|
||||||
|
_proto.initHooks = function initHooks(hooks) {
|
||||||
|
var _this8 = this;
|
||||||
|
|
||||||
|
if (hooks === void 0) {
|
||||||
|
hooks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hooksFuncs = hooks.map(function (item) {
|
||||||
|
var func = function func() {
|
||||||
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
args[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
item.handler.apply(item, [_this8].concat(args));
|
||||||
|
};
|
||||||
|
|
||||||
|
_this8[item.type](item.message, func);
|
||||||
|
|
||||||
|
return func;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.initPluginStatus = function initPluginStatus() {
|
||||||
|
var _this9 = this;
|
||||||
|
|
||||||
|
var _this$config$plugins = this.config.plugins,
|
||||||
|
plugins = _this$config$plugins === void 0 ? {} : _this$config$plugins;
|
||||||
|
var pluginAreas = Object.keys(plugins);
|
||||||
|
var res = {};
|
||||||
|
pluginAreas.forEach(function (area) {
|
||||||
|
(plugins[area] || []).forEach(function (plugin) {
|
||||||
|
if (plugin.type === 'Divider') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ref2 = plugin.props || {},
|
||||||
|
visible = _ref2.visible,
|
||||||
|
disabled = _ref2.disabled,
|
||||||
|
marked = _ref2.marked;
|
||||||
|
|
||||||
|
res[plugin.pluginKey] = {
|
||||||
|
visible: typeof visible === 'boolean' ? visible : true,
|
||||||
|
disabled: typeof disabled === 'boolean' ? disabled : false,
|
||||||
|
marked: typeof marked === 'boolean' ? marked : false
|
||||||
|
};
|
||||||
|
var pluginClass = _this9.components[plugin.pluginKey]; // 判断如果编辑器插件有init静态方法,则在此执行init方法
|
||||||
|
|
||||||
|
if (pluginClass && pluginClass.init) {
|
||||||
|
pluginClass.init(_this9);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Editor;
|
||||||
|
}(EventEmitter);
|
||||||
|
|
||||||
|
Editor.getInstance = function (config, components, utils) {
|
||||||
|
if (!instance) {
|
||||||
|
instance = new Editor(config, components, utils);
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Editor as default };
|
||||||
8
packages/editor-framework/es/index.d.ts
vendored
Normal file
8
packages/editor-framework/es/index.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import Editor from './editor';
|
||||||
|
import * as utils from './utils';
|
||||||
|
import * as definitions from './definitions';
|
||||||
|
export { default as PluginFactory } from './pluginFactory';
|
||||||
|
export { default as EditorContext } from './context';
|
||||||
|
export { default as AreaManager } from './areaManager';
|
||||||
|
export default Editor;
|
||||||
|
export { utils, definitions };
|
||||||
8
packages/editor-framework/es/index.js
Normal file
8
packages/editor-framework/es/index.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import Editor from './editor';
|
||||||
|
import * as utils from './utils';
|
||||||
|
import * as definitions from './definitions';
|
||||||
|
export { default as PluginFactory } from './pluginFactory';
|
||||||
|
export { default as EditorContext } from './context';
|
||||||
|
export { default as AreaManager } from './areaManager';
|
||||||
|
export default Editor;
|
||||||
|
export { utils, definitions };
|
||||||
3
packages/editor-framework/es/pluginFactory.d.ts
vendored
Normal file
3
packages/editor-framework/es/pluginFactory.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { PluginProps, PluginClass } from './definitions';
|
||||||
|
export default function pluginFactory(Comp: PluginClass): React.ComponentType<PluginProps>;
|
||||||
98
packages/editor-framework/es/pluginFactory.js
Normal file
98
packages/editor-framework/es/pluginFactory.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
|
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
|
||||||
|
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
|
||||||
|
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
||||||
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
|
|
||||||
|
function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
||||||
|
|
||||||
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
||||||
|
|
||||||
|
import React, { createRef, PureComponent } from 'react';
|
||||||
|
import EditorContext from './context';
|
||||||
|
import { acceptsRef, generateI18n, isEmpty, transformToPromise } from './utils';
|
||||||
|
export default function pluginFactory(Comp) {
|
||||||
|
var LowcodePlugin = /*#__PURE__*/function (_PureComponent) {
|
||||||
|
_inheritsLoose(LowcodePlugin, _PureComponent);
|
||||||
|
|
||||||
|
var _super = _createSuper(LowcodePlugin);
|
||||||
|
|
||||||
|
function LowcodePlugin(props, context) {
|
||||||
|
var _extends2;
|
||||||
|
|
||||||
|
var _this;
|
||||||
|
|
||||||
|
_this = _PureComponent.call(this, props, context) || this;
|
||||||
|
_this.ref = void 0;
|
||||||
|
_this.editor = void 0;
|
||||||
|
_this.pluginKey = void 0;
|
||||||
|
_this.i18n = void 0;
|
||||||
|
|
||||||
|
_this.open = function () {
|
||||||
|
if (_this.ref && _this.ref.open && typeof _this.ref.open === 'function') {
|
||||||
|
return transformToPromise(_this.ref.open());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.close = function () {
|
||||||
|
if (_this.ref && _this.ref.close && typeof _this.ref.close === 'function') {
|
||||||
|
return transformToPromise(_this.ref.close());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isEmpty(props.config) || !props.config.pluginKey) {
|
||||||
|
console.warn('lowcode editor plugin has wrong config');
|
||||||
|
return _assertThisInitialized(_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
var editor = props.editor;
|
||||||
|
_this.ref = createRef(); // 注册插件
|
||||||
|
|
||||||
|
_this.editor = editor;
|
||||||
|
_this.pluginKey = props.config.pluginKey;
|
||||||
|
var defaultProps = Comp.defaultProps || {};
|
||||||
|
var locale = _this.editor.get('locale') || defaultProps.locale || 'zh-CN';
|
||||||
|
var editorMessages = _this.editor.get('messages') || {};
|
||||||
|
var messages = editorMessages[_this.pluginKey] || defaultProps.messages || {};
|
||||||
|
_this.i18n = generateI18n(locale, messages);
|
||||||
|
editor.set('plugins', _extends({}, editor.plugins, (_extends2 = {}, _extends2[_this.pluginKey] = _assertThisInitialized(_this), _extends2)));
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _proto = LowcodePlugin.prototype;
|
||||||
|
|
||||||
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
|
// 销毁插件
|
||||||
|
if (this.pluginKey && this.editor && this.editor.plugins) {
|
||||||
|
delete this.editor.plugins[this.pluginKey];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.render = function render() {
|
||||||
|
var config = this.props.config;
|
||||||
|
|
||||||
|
var props = _extends({
|
||||||
|
i18n: this.i18n,
|
||||||
|
editor: this.editor,
|
||||||
|
config: config
|
||||||
|
}, config.pluginProps);
|
||||||
|
|
||||||
|
if (acceptsRef(Comp)) {
|
||||||
|
props.ref = this.ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
return /*#__PURE__*/React.createElement(Comp, props);
|
||||||
|
};
|
||||||
|
|
||||||
|
return LowcodePlugin;
|
||||||
|
}(PureComponent);
|
||||||
|
|
||||||
|
LowcodePlugin.displayName = 'LowcodeEditorPlugin';
|
||||||
|
LowcodePlugin.contextType = EditorContext;
|
||||||
|
LowcodePlugin.init = Comp.init;
|
||||||
|
return LowcodePlugin;
|
||||||
|
}
|
||||||
1
packages/editor-framework/es/style.js
Normal file
1
packages/editor-framework/es/style.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
//empty file
|
||||||
71
packages/editor-framework/es/utils.d.ts
vendored
Normal file
71
packages/editor-framework/es/utils.d.ts
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/// <reference types="react" />
|
||||||
|
import Editor from './editor';
|
||||||
|
import { EditorConfig, I18nFunction, I18nMessages, LocaleType, ShortCutsConfig } from './definitions';
|
||||||
|
export declare const pick: any;
|
||||||
|
export declare const deepEqual: any;
|
||||||
|
export declare const clone: any;
|
||||||
|
export declare const isEmpty: any;
|
||||||
|
export declare const throttle: any;
|
||||||
|
export declare const debounce: any;
|
||||||
|
export declare const serialize: any;
|
||||||
|
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: {
|
||||||
|
logKey: string;
|
||||||
|
gmKey: string;
|
||||||
|
goKey: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export declare function generateI18n(locale?: LocaleType, messages?: I18nMessages): I18nFunction;
|
||||||
|
/**
|
||||||
|
* 序列化参数
|
||||||
|
*/
|
||||||
|
export declare function serializeParams(obj: object): string;
|
||||||
|
/**
|
||||||
|
* 黄金令箭埋点
|
||||||
|
* @param {String} gmKey 为黄金令箭业务类型
|
||||||
|
* @param {Object} params 参数
|
||||||
|
* @param {String} logKey 属性串
|
||||||
|
*/
|
||||||
|
export declare function goldlog(gmKey: string, params?: object, logKey?: string): void;
|
||||||
|
/**
|
||||||
|
* 获取当前编辑器环境
|
||||||
|
*/
|
||||||
|
export declare function getEnv(): string;
|
||||||
|
export declare function registShortCuts(config: ShortCutsConfig, editor: Editor): void;
|
||||||
|
export declare function unRegistShortCuts(config: ShortCutsConfig): void;
|
||||||
|
/**
|
||||||
|
* 将函数返回结果转成promise形式,如果函数有返回值则根据返回值的bool类型判断是reject还是resolve,若函数无返回值默认执行resolve
|
||||||
|
*/
|
||||||
|
export declare function transformToPromise(input: any): Promise<{}>;
|
||||||
|
/**
|
||||||
|
* 将数组类型转换为Map类型
|
||||||
|
*/
|
||||||
|
interface MapOf<T> {
|
||||||
|
[propName: string]: T;
|
||||||
|
}
|
||||||
|
export declare function transformArrayToMap<T>(arr: T[], key: string, overwrite?: boolean): MapOf<T>;
|
||||||
|
/**
|
||||||
|
* 解析url的查询参数
|
||||||
|
*/
|
||||||
|
interface Query {
|
||||||
|
[propName: string]: string;
|
||||||
|
}
|
||||||
|
export declare function parseSearch(search: string): Query;
|
||||||
|
export declare function comboEditorConfig(defaultConfig: EditorConfig, customConfig: EditorConfig): EditorConfig;
|
||||||
|
/**
|
||||||
|
* 判断当前组件是否能够设置ref
|
||||||
|
* @param {*} Comp 需要判断的组件
|
||||||
|
*/
|
||||||
|
export declare function acceptsRef(Comp: React.ReactNode): boolean;
|
||||||
|
export {};
|
||||||
270
packages/editor-framework/es/utils.js
Normal file
270
packages/editor-framework/es/utils.js
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
|
import IntlMessageFormat from 'intl-messageformat';
|
||||||
|
import keymaster from 'keymaster';
|
||||||
|
import _clone from 'lodash/cloneDeep';
|
||||||
|
import _debounce from 'lodash/debounce';
|
||||||
|
import _isEmpty from 'lodash/isEmpty';
|
||||||
|
import _deepEqual from 'lodash/isEqualWith';
|
||||||
|
import _pick from 'lodash/pick';
|
||||||
|
import _throttle from 'lodash/throttle';
|
||||||
|
import _serialize from 'serialize-javascript';
|
||||||
|
export var pick = _pick;
|
||||||
|
export var deepEqual = _deepEqual;
|
||||||
|
export var clone = _clone;
|
||||||
|
export var isEmpty = _isEmpty;
|
||||||
|
export var throttle = _throttle;
|
||||||
|
export var debounce = _debounce;
|
||||||
|
export var serialize = _serialize;
|
||||||
|
var ENV = {
|
||||||
|
TBE: 'TBE',
|
||||||
|
WEBIDE: 'WEB-IDE',
|
||||||
|
VSCODE: 'VSCODE',
|
||||||
|
WEB: 'WEB'
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 用于构造国际化字符串处理函数
|
||||||
|
*/
|
||||||
|
export function generateI18n(locale, messages) {
|
||||||
|
if (locale === void 0) {
|
||||||
|
locale = 'zh-CN';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messages === void 0) {
|
||||||
|
messages = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (key, values) {
|
||||||
|
if (!messages || !messages[key]) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var formater = new IntlMessageFormat(messages[key], locale);
|
||||||
|
return formater.format(values);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 序列化参数
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function serializeParams(obj) {
|
||||||
|
if (typeof obj !== 'object') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = [];
|
||||||
|
Object.entries(obj).forEach(function (_ref) {
|
||||||
|
var key = _ref[0],
|
||||||
|
val = _ref[1];
|
||||||
|
|
||||||
|
if (val === null || val === undefined || val === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof val === 'object') {
|
||||||
|
res.push(encodeURIComponent(key) + "=" + encodeURIComponent(JSON.stringify(val)));
|
||||||
|
} else {
|
||||||
|
res.push(encodeURIComponent(key) + "=" + encodeURIComponent(val));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res.join('&');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 黄金令箭埋点
|
||||||
|
* @param {String} gmKey 为黄金令箭业务类型
|
||||||
|
* @param {Object} params 参数
|
||||||
|
* @param {String} logKey 属性串
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function goldlog(gmKey, params, logKey) {
|
||||||
|
if (params === void 0) {
|
||||||
|
params = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logKey === void 0) {
|
||||||
|
logKey = 'other';
|
||||||
|
}
|
||||||
|
|
||||||
|
var sendIDEMessage = window.sendIDEMessage || window.parent.sendIDEMessage;
|
||||||
|
var goKey = serializeParams(_extends({
|
||||||
|
env: getEnv()
|
||||||
|
}, params));
|
||||||
|
|
||||||
|
if (sendIDEMessage) {
|
||||||
|
sendIDEMessage({
|
||||||
|
action: 'goldlog',
|
||||||
|
data: {
|
||||||
|
logKey: "/iceluna.core." + logKey,
|
||||||
|
gmKey: gmKey,
|
||||||
|
goKey: goKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.goldlog) {
|
||||||
|
window.goldlog.record("/iceluna.core." + logKey, gmKey, goKey, 'POST');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取当前编辑器环境
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function getEnv() {
|
||||||
|
var userAgent = navigator.userAgent;
|
||||||
|
var isVscode = /Electron\//.test(userAgent);
|
||||||
|
|
||||||
|
if (isVscode) {
|
||||||
|
return ENV.VSCODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isTheia = window.is_theia === true;
|
||||||
|
|
||||||
|
if (isTheia) {
|
||||||
|
return ENV.WEBIDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ENV.WEB;
|
||||||
|
} // 注册快捷键
|
||||||
|
|
||||||
|
export function registShortCuts(config, editor) {
|
||||||
|
(config || []).forEach(function (item) {
|
||||||
|
keymaster(item.keyboard, function (ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
item.handler(editor, ev, keymaster);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} // 取消注册快捷
|
||||||
|
|
||||||
|
export function unRegistShortCuts(config) {
|
||||||
|
(config || []).forEach(function (item) {
|
||||||
|
keymaster.unbind(item.keyboard);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (window.parent.vscode) {
|
||||||
|
keymaster.unbind('command+c');
|
||||||
|
keymaster.unbind('command+v');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 将函数返回结果转成promise形式,如果函数有返回值则根据返回值的bool类型判断是reject还是resolve,若函数无返回值默认执行resolve
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function transformToPromise(input) {
|
||||||
|
if (input instanceof Promise) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
if (input || input === undefined) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 将数组类型转换为Map类型
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function transformArrayToMap(arr, key, overwrite) {
|
||||||
|
if (overwrite === void 0) {
|
||||||
|
overwrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty(arr) || !Array.isArray(arr)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = {};
|
||||||
|
arr.forEach(function (item) {
|
||||||
|
var curKey = item[key];
|
||||||
|
|
||||||
|
if (item[key] === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res[curKey] && !overwrite) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res[curKey] = item;
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 解析url的查询参数
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function parseSearch(search) {
|
||||||
|
if (!search || typeof search !== 'string') {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var str = search.replace(/^\?/, '');
|
||||||
|
var paramStr = str.split('&');
|
||||||
|
var res = {};
|
||||||
|
paramStr.forEach(function (item) {
|
||||||
|
var regRes = item.split('=');
|
||||||
|
|
||||||
|
if (regRes[0] && regRes[1]) {
|
||||||
|
res[regRes[0]] = decodeURIComponent(regRes[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
export function comboEditorConfig(defaultConfig, customConfig) {
|
||||||
|
if (defaultConfig === void 0) {
|
||||||
|
defaultConfig = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ref2 = customConfig || {},
|
||||||
|
skeleton = _ref2.skeleton,
|
||||||
|
theme = _ref2.theme,
|
||||||
|
plugins = _ref2.plugins,
|
||||||
|
hooks = _ref2.hooks,
|
||||||
|
shortCuts = _ref2.shortCuts,
|
||||||
|
lifeCycles = _ref2.lifeCycles,
|
||||||
|
constants = _ref2.constants,
|
||||||
|
utils = _ref2.utils,
|
||||||
|
i18n = _ref2.i18n;
|
||||||
|
|
||||||
|
if (skeleton && skeleton.handler && typeof skeleton.handler === 'function') {
|
||||||
|
return skeleton.handler(_extends({
|
||||||
|
skeleton: skeleton
|
||||||
|
}, defaultConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultShortCuts = transformArrayToMap(defaultConfig.shortCuts || [], 'keyboard');
|
||||||
|
var customShortCuts = transformArrayToMap(shortCuts || [], 'keyboard');
|
||||||
|
var localeList = ['zh-CN', 'zh-TW', 'en-US', 'ja-JP'];
|
||||||
|
var i18nConfig = {};
|
||||||
|
localeList.forEach(function (key) {
|
||||||
|
i18nConfig[key] = _extends({}, defaultConfig.i18n && defaultConfig.i18n[key], {}, i18n && i18n[key]);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
skeleton: skeleton,
|
||||||
|
theme: _extends({}, defaultConfig.theme, {}, theme),
|
||||||
|
plugins: _extends({}, defaultConfig.plugins, {}, plugins),
|
||||||
|
hooks: [].concat(defaultConfig.hooks || [], hooks || []),
|
||||||
|
shortCuts: Object.values(_extends({}, defaultShortCuts, {}, customShortCuts)),
|
||||||
|
lifeCycles: _extends({}, defaultConfig.lifeCycles, {}, lifeCycles),
|
||||||
|
constants: _extends({}, defaultConfig.constants, {}, constants),
|
||||||
|
utils: [].concat(defaultConfig.utils || [], utils || []),
|
||||||
|
i18n: i18nConfig
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 判断当前组件是否能够设置ref
|
||||||
|
* @param {*} Comp 需要判断的组件
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function acceptsRef(Comp) {
|
||||||
|
var hasSymbol = typeof Symbol === 'function' && Symbol["for"];
|
||||||
|
var 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;
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-engine-editor",
|
"name": "@ali/lowcode-editor-framework",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "alibaba lowcode editor core",
|
"description": "alibaba lowcode editor core",
|
||||||
"files": [
|
"files": [
|
||||||
@ -13,7 +13,7 @@
|
|||||||
"stylePath": "style.js",
|
"stylePath": "style.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "build-scripts start",
|
"start": "build-scripts start",
|
||||||
"build": "build-scripts build",
|
"build": "build-scripts build --skip-demo",
|
||||||
"prepublishOnly": "npm run prettier && npm run build",
|
"prepublishOnly": "npm run prettier && npm run build",
|
||||||
"lint": "eslint --cache --ext .js,.jsx ./",
|
"lint": "eslint --cache --ext .js,.jsx ./",
|
||||||
"prettier": "prettier --write \"./src/**/*.{ts,tsx,js,jsx,ejs,less,css,scss,json}\" "
|
"prettier": "prettier --write \"./src/**/*.{ts,tsx,js,jsx,ejs,less,css,scss,json}\" "
|
||||||
@ -51,5 +51,5 @@
|
|||||||
"@alifd/next": "1.x"
|
"@alifd/next": "1.x"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://unpkg.com/editor-framework@0.0.1/build/index.html"
|
"homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-editor-framework@0.0.1/build/index.html"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { PluginConfig, PluginStatus } from './definitions';
|
import { PluginConfig, PluginStatus, PluginClass, HOCPlugin } from './definitions';
|
||||||
import Editor from './index';
|
import Editor from './index';
|
||||||
import { clone, deepEqual } from './utils';
|
import { clone, deepEqual } from './utils';
|
||||||
|
|
||||||
@ -18,14 +18,16 @@ export default class AreaManager {
|
|||||||
this.pluginStatus = clone(editor.pluginStatus);
|
this.pluginStatus = clone(editor.pluginStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isPluginStatusUpdate(pluginType?: string): boolean {
|
public isPluginStatusUpdate(pluginType?: string, notUpdateStatus?: boolean): boolean {
|
||||||
const { pluginStatus } = this.editor;
|
const { pluginStatus } = this.editor;
|
||||||
const list = pluginType ? this.config.filter((item): boolean => item.type === pluginType) : this.config;
|
const list = pluginType ? this.config.filter((item): boolean => item.type === pluginType) : this.config;
|
||||||
|
|
||||||
const isUpdate = list.some(
|
const isUpdate = list.some(
|
||||||
(item): boolean => !deepEqual(pluginStatus[item.pluginKey], this.pluginStatus[item.pluginKey])
|
(item): boolean => !deepEqual(pluginStatus[item.pluginKey], this.pluginStatus[item.pluginKey]),
|
||||||
);
|
);
|
||||||
this.pluginStatus = clone(pluginStatus);
|
if (!notUpdateStatus) {
|
||||||
|
this.pluginStatus = clone(pluginStatus);
|
||||||
|
}
|
||||||
return isUpdate;
|
return isUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +38,28 @@ export default class AreaManager {
|
|||||||
return pluginType ? res.filter((item): boolean => item.type === pluginType) : res;
|
return pluginType ? res.filter((item): boolean => item.type === pluginType) : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPluginConfig(): PluginConfig[] {
|
public getPlugin(pluginKey: string): HOCPlugin | void {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.editor && this.editor.plugins && this.editor.plugins[pluginKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPluginConfig(pluginKey?: string): PluginConfig[] | PluginConfig | undefined {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.config.find(item => item.pluginKey === pluginKey);
|
||||||
|
}
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPluginClass(pluginKey: string): PluginClass | void {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.editor && this.editor.components && this.editor.components[pluginKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPluginStatus(pluginKey: string): PluginStatus | void {
|
||||||
|
if (pluginKey) {
|
||||||
|
return this.editor && this.editor.pluginStatus && this.editor.pluginStatus[pluginKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
const context = createContext({});
|
const context = createContext({});
|
||||||
export default context;
|
export default context;
|
||||||
|
|||||||
@ -1,48 +1,158 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import Editor from './editor';
|
||||||
|
|
||||||
export interface EditorConfig {
|
export interface EditorConfig {
|
||||||
|
skeleton?: SkeletonConfig;
|
||||||
};
|
theme?: ThemeConfig;
|
||||||
|
plugins?: PluginsConfig;
|
||||||
|
hooks?: HooksConfig;
|
||||||
|
shortCuts?: ShortCutsConfig;
|
||||||
|
utils?: UtilsConfig;
|
||||||
|
constants?: ConstantsConfig;
|
||||||
|
lifeCycles?: LifeCyclesConfig;
|
||||||
|
i18n?: I18nConfig;
|
||||||
|
}
|
||||||
|
|
||||||
export interface NpmConfig {
|
export interface NpmConfig {
|
||||||
version: string,
|
version: string;
|
||||||
package: string,
|
package: string;
|
||||||
main?: string,
|
main?: string;
|
||||||
exportName?: string,
|
exportName?: string;
|
||||||
subName?: string,
|
subName?: string;
|
||||||
destructuring?: boolean
|
destructuring?: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface SkeletonConfig {
|
export interface SkeletonConfig {
|
||||||
config: NpmConfig,
|
config: NpmConfig;
|
||||||
props?: object,
|
props?: object;
|
||||||
handler?: (EditorConfig) => EditorConfig
|
handler?: (config: EditorConfig) => EditorConfig;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface FusionTheme {
|
export interface FusionTheme {
|
||||||
package: string,
|
package: string;
|
||||||
version: string
|
version: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface ThemeConfig {
|
export interface ThemeConfig {
|
||||||
fusion?: FusionTheme
|
fusion?: FusionTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PluginsConfig {
|
export interface PluginsConfig {
|
||||||
[key]: Array<PluginConfig>
|
[key: string]: PluginConfig[];
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface PluginConfig {
|
export interface PluginConfig {
|
||||||
pluginKey: string,
|
pluginKey: string;
|
||||||
type: string,
|
type: string;
|
||||||
props: object,
|
props: {
|
||||||
config: NpmConfig,
|
icon?: string;
|
||||||
pluginProps: object
|
title?: string;
|
||||||
};
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
visible?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
align?: 'left' | 'right' | 'top' | 'bottom';
|
||||||
|
onClick?: () => void;
|
||||||
|
dialogProps?: object;
|
||||||
|
balloonProps?: object;
|
||||||
|
panelProps?: object;
|
||||||
|
linkProps?: object;
|
||||||
|
};
|
||||||
|
config?: NpmConfig;
|
||||||
|
pluginProps?: object;
|
||||||
|
}
|
||||||
|
|
||||||
export type HooksConfig = Array<HookConfig>;
|
export type HooksConfig = HookConfig[];
|
||||||
|
|
||||||
export interface HookConfig {
|
export interface HookConfig {
|
||||||
|
message: string;
|
||||||
|
type: 'on' | 'once';
|
||||||
|
handler: (editor: Editor, ...args: []) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ShortCutsConfig = ShortCutConfig[];
|
||||||
|
|
||||||
|
export interface ShortCutConfig {
|
||||||
|
keyboard: string;
|
||||||
|
handler: (editor: Editor, ev: Event, keymaster: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UtilsConfig = UtilConfig[];
|
||||||
|
|
||||||
|
export interface UtilConfig {
|
||||||
|
name: string;
|
||||||
|
type: 'npm' | 'function';
|
||||||
|
content: NpmConfig | ((...args: []) => any);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ConstantsConfig = object;
|
||||||
|
|
||||||
|
export interface LifeCyclesConfig {
|
||||||
|
init?: (editor: Editor) => any;
|
||||||
|
destroy?: (editor: Editor) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LocaleType = 'zh-CN' | 'zh-TW' | 'en-US' | 'ja-JP';
|
||||||
|
|
||||||
|
export interface I18nMessages {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface I18nConfig {
|
||||||
|
'zh-CN'?: I18nMessages;
|
||||||
|
'zh-TW'?: I18nMessages;
|
||||||
|
'en-US'?: I18nMessages;
|
||||||
|
'ja-JP'?: I18nMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<React.ReactElement>;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Plugin = React.ReactNode & {
|
||||||
|
open?: () => boolean | void | Promise<any>;
|
||||||
|
close?: () => boolean | void | Promise<any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type HOCPlugin = React.ReactNode & {
|
||||||
|
open: () => Promise<any>;
|
||||||
|
close: () => Promise<any>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface PluginSet {
|
||||||
|
[key: string]: HOCPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PluginClass = React.ComponentType<PluginProps> & {
|
||||||
|
init?: (editor: Editor) => void;
|
||||||
|
defaultProps?: {
|
||||||
|
locale?: LocaleType;
|
||||||
|
messages?: I18nMessages;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface PluginClassSet {
|
||||||
|
[key: string]: PluginClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PluginStatus {
|
||||||
|
disabled?: boolean;
|
||||||
|
visible?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
locked?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PluginStatusSet {
|
||||||
|
[key: string]: PluginStatus;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,37 +1,56 @@
|
|||||||
import EventEmitter from 'events';
|
|
||||||
import Debug from 'debug';
|
import Debug from 'debug';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
unRegistShortCuts,
|
EditorConfig,
|
||||||
registShortCuts,
|
HooksConfig,
|
||||||
transformToPromise,
|
LocaleType,
|
||||||
generateI18n
|
PluginStatusSet,
|
||||||
} from './utils';
|
Utils,
|
||||||
|
PluginClassSet,
|
||||||
|
PluginSet,
|
||||||
|
} from './definitions';
|
||||||
|
|
||||||
|
import * as editorUtils from './utils';
|
||||||
|
|
||||||
|
const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__isDebug?: boolean;
|
||||||
|
__newFunc?: (funcStr: string) => (...args: any[]) => any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 根据url参数设置debug选项
|
// 根据url参数设置debug选项
|
||||||
const res = /_?debug=(.*?)(&|$)/.exec(location.search);
|
const debugRegRes = /_?debug=(.*?)(&|$)/.exec(location.search);
|
||||||
if (res && res[1]) {
|
if (debugRegRes && debugRegRes[1]) {
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
window.__isDebug = true;
|
window.__isDebug = true;
|
||||||
store.storage.write('debug', res[1] === 'true' ? '*' : res[1]);
|
store.storage.write('debug', debugRegRes[1] === 'true' ? '*' : debugRegRes[1]);
|
||||||
} else {
|
} else {
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
window.__isDebug = false;
|
window.__isDebug = false;
|
||||||
store.remove('debug');
|
store.remove('debug');
|
||||||
}
|
}
|
||||||
|
|
||||||
//重要,用于矫正画布执行new Function的window对象上下文
|
// 重要,用于矫正画布执行new Function的window对象上下文
|
||||||
window.__newFunc = funContext => {
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
return new Function(funContext);
|
window.__newFunc = (funContext: string): ((...args: any[]) => any) => {
|
||||||
|
// eslint-disable-next-line no-new-func
|
||||||
|
return new Function(funContext) as (...args: any[]) => any;
|
||||||
};
|
};
|
||||||
|
|
||||||
//关闭浏览器前提醒,只有产生过交互才会生效
|
// 关闭浏览器前提醒,只有产生过交互才会生效
|
||||||
window.onbeforeunload = function(e) {
|
window.onbeforeunload = function(e: Event): string | void {
|
||||||
e = e || window.event;
|
const ev = e || window.event;
|
||||||
// 本地调试不生效
|
// 本地调试不生效
|
||||||
if (location.href.indexOf('localhost') > 0) return;
|
if (location.href.indexOf('localhost') > 0) {
|
||||||
var msg = '您确定要离开此页面吗?';
|
return;
|
||||||
e.cancelBubble = true;
|
}
|
||||||
e.returnValue = msg;
|
const msg = '您确定要离开此页面吗?';
|
||||||
|
ev.cancelBubble = true;
|
||||||
|
ev.returnValue = true;
|
||||||
if (e.stopPropagation) {
|
if (e.stopPropagation) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -39,142 +58,165 @@ window.onbeforeunload = function(e) {
|
|||||||
return msg;
|
return msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let instance: Editor;
|
||||||
|
|
||||||
let instance = null;
|
|
||||||
const debug = Debug('editor');
|
const debug = Debug('editor');
|
||||||
EventEmitter.defaultMaxListeners = 100;
|
EventEmitter.defaultMaxListeners = 100;
|
||||||
|
|
||||||
export interface editor {
|
export interface HooksFuncs {
|
||||||
|
[idx: number]: (msg: string, handler: (...args) => void) => void;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class Editor extends EventEmitter {
|
export default class Editor extends EventEmitter {
|
||||||
static getInstance = () => {
|
public static getInstance = (config: EditorConfig, components: PluginClassSet, utils?: Utils): Editor => {
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
instance = new Editor();
|
instance = new Editor(config, components, utils);
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(config) {
|
public config: EditorConfig;
|
||||||
|
|
||||||
|
public components: PluginClassSet;
|
||||||
|
|
||||||
|
public utils: Utils;
|
||||||
|
|
||||||
|
public pluginStatus: PluginStatusSet;
|
||||||
|
|
||||||
|
public plugins: PluginSet;
|
||||||
|
|
||||||
|
public locale: LocaleType;
|
||||||
|
|
||||||
|
private hooksFuncs: HooksFuncs;
|
||||||
|
|
||||||
|
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
|
||||||
super();
|
super();
|
||||||
|
this.config = config;
|
||||||
|
this.components = components;
|
||||||
|
this.utils = { ...editorUtils, ...utils };
|
||||||
instance = this;
|
instance = this;
|
||||||
Object.assign(this, config);
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
public init(): Promise<any> {
|
||||||
const {
|
const { hooks, shortCuts = [], lifeCycles } = this.config || {};
|
||||||
hooks,
|
|
||||||
shortCuts,
|
|
||||||
lifeCycles
|
|
||||||
} = this.config || {};
|
|
||||||
this.destroy();
|
|
||||||
this.locale = store.get('lowcode-editor-locale') || 'zh-CN';
|
this.locale = store.get('lowcode-editor-locale') || 'zh-CN';
|
||||||
this.messages = this.messagesSet[this.locale];
|
// this.messages = this.messagesSet[this.locale];
|
||||||
this.i18n = generateI18n(this.locale, this.messages);
|
// this.i18n = generateI18n(this.locale, this.messages);
|
||||||
this.pluginStatus = this.initPluginStatus();
|
this.pluginStatus = this.initPluginStatus();
|
||||||
this.initHooks(hooks, appHelper);
|
this.initHooks(hooks || []);
|
||||||
|
|
||||||
appHelper.emit('editor.beforeInit');
|
this.emit('editor.beforeInit');
|
||||||
const init = lifeCycles && lifeCycles.init || () => {};
|
const init = (lifeCycles && lifeCycles.init) || ((): void => {});
|
||||||
// 用户可以通过设置extensions.init自定义初始化流程;
|
// 用户可以通过设置extensions.init自定义初始化流程;
|
||||||
transformToPromise(init(this))
|
return transformToPromise(init(this))
|
||||||
.then(() => {
|
.then((): boolean => {
|
||||||
// 注册快捷键
|
// 注册快捷键
|
||||||
registShortCuts(shortCuts, this);
|
registShortCuts(shortCuts, this);
|
||||||
this.emit('editor.afterInit');
|
this.emit('editor.afterInit');
|
||||||
|
return true;
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch((err): void => {
|
||||||
console.warn(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
public destroy(): void {
|
||||||
|
debug('destroy');
|
||||||
try {
|
try {
|
||||||
const {
|
const { hooks = [], shortCuts = [], lifeCycles = {} } = this.config;
|
||||||
hooks = [],
|
unRegistShortCuts(shortCuts);
|
||||||
shortCuts = [],
|
this.destroyHooks(hooks);
|
||||||
lifeCycles = {}
|
if (lifeCycles.destroy) {
|
||||||
} = this.config;
|
lifeCycles.destroy(this);
|
||||||
unRegistShortCuts(shortCuts);
|
|
||||||
this.destroyHooks(hooks);
|
|
||||||
lifeCycles.destroy && lifeCycles.destroy();
|
|
||||||
} catch (err) {
|
|
||||||
console.warn(err);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get(key:string):any {
|
public get(key: string): any {
|
||||||
return this[key];
|
return this[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
set(key:string|object, val:any):void {
|
public set(key: string | object, val: any): void {
|
||||||
if (typeof key === 'string') {
|
if (typeof key === 'string') {
|
||||||
if (['init', 'destroy', 'get', 'set', 'batchOn', 'batchOff', 'batchOnce'].includes(key)) {
|
if (['init', 'destroy', 'get', 'set', 'batchOn', 'batchOff', 'batchOnce'].includes(key)) {
|
||||||
console.warning('init, destroy, get, set, batchOn, batchOff, batchOnce is private attribute');
|
console.error('init, destroy, get, set, batchOn, batchOff, batchOnce is private attribute');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this[key] = val;
|
this[key] = val;
|
||||||
} else if (typeof key === 'object') {
|
} else if (typeof key === 'object') {
|
||||||
Object.keys(key).forEach(item => {
|
Object.keys(key).forEach((item): void => {
|
||||||
this[item] = key[item];
|
this[item] = key[item];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
batchOn(events:Array<string>, lisenter:function):void {
|
public batchOn(events: string[], lisenter: (...args) => void): void {
|
||||||
if (!Array.isArray(events)) return;
|
if (!Array.isArray(events)) {
|
||||||
events.forEach(event => this.on(event, lisenter));
|
return;
|
||||||
|
}
|
||||||
|
events.forEach((event): void => {
|
||||||
|
this.on(event, lisenter);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
batchOnce(events:Array<string>, lisenter:function):void {
|
public batchOnce(events: string[], lisenter: (...args) => void): void {
|
||||||
if (!Array.isArray(events)) return;
|
if (!Array.isArray(events)) {
|
||||||
events.forEach(event => this.once(event, lisenter));
|
return;
|
||||||
|
}
|
||||||
|
events.forEach((event): void => {
|
||||||
|
this.once(event, lisenter);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
batchOff(events:Array<string>, lisenter:function):void {
|
public batchOff(events: string[], lisenter: (...args) => void): void {
|
||||||
if (!Array.isArray(events)) return;
|
if (!Array.isArray(events)) {
|
||||||
events.forEach(event => this.off(event, lisenter));
|
return;
|
||||||
|
}
|
||||||
|
events.forEach((event): void => {
|
||||||
|
this.off(event, lisenter);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//销毁hooks中的消息监听
|
// 销毁hooks中的消息监听
|
||||||
private destroyHooks(hooks = []) {
|
private destroyHooks(hooks: HooksConfig = []): void {
|
||||||
hooks.forEach((item, idx) => {
|
hooks.forEach((item, idx): void => {
|
||||||
if (typeof this.__hooksFuncs[idx] === 'function') {
|
if (typeof this.hooksFuncs[idx] === 'function') {
|
||||||
this.appHelper.off(item.message, this.__hooksFuncs[idx]);
|
this.off(item.message, this.hooksFuncs[idx]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
delete this.__hooksFuncs;
|
delete this.hooksFuncs;
|
||||||
};
|
}
|
||||||
|
|
||||||
//初始化hooks中的消息监听
|
// 初始化hooks中的消息监听
|
||||||
private initHooks(hooks = []) {
|
private initHooks(hooks: HooksConfig = []): void {
|
||||||
this.__hooksFuncs = hooks.map(item => {
|
this.hooksFuncs = hooks.map((item): ((...arg) => void) => {
|
||||||
const func = (...args) => {
|
const func = (...args): void => {
|
||||||
item.handler(this, ...args);
|
item.handler(this, ...args);
|
||||||
};
|
};
|
||||||
this[item.type](item.message, func);
|
this[item.type](item.message, func);
|
||||||
return func;
|
return func;
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
private initPluginStatus(): PluginStatusSet {
|
||||||
private initPluginStatus () {
|
const { plugins = {} } = this.config;
|
||||||
const {plugins = {}} = this.config;
|
|
||||||
const pluginAreas = Object.keys(plugins);
|
const pluginAreas = Object.keys(plugins);
|
||||||
const res = {};
|
const res: PluginStatusSet = {};
|
||||||
pluginAreas.forEach(area => {
|
pluginAreas.forEach((area): void => {
|
||||||
(plugins[area] || []).forEach(plugin => {
|
(plugins[area] || []).forEach((plugin): void => {
|
||||||
if (plugin.type === 'Divider') return;
|
if (plugin.type === 'Divider') {
|
||||||
const { visible, disabled, dotted } = plugin.props || {};
|
return;
|
||||||
|
}
|
||||||
|
const { visible, disabled, marked } = plugin.props || {};
|
||||||
res[plugin.pluginKey] = {
|
res[plugin.pluginKey] = {
|
||||||
visible: typeof visible === 'boolean' ? visible : true,
|
visible: typeof visible === 'boolean' ? visible : true,
|
||||||
disabled: typeof disabled === 'boolean' ? disabled : false,
|
disabled: typeof disabled === 'boolean' ? disabled : false,
|
||||||
dotted: typeof dotted === 'boolean' ? dotted : false
|
marked: typeof marked === 'boolean' ? marked : false,
|
||||||
};
|
};
|
||||||
const pluginClass = this.props.components[skeletonUtils.generateAddonCompName(addon.addonKey)];
|
const pluginClass = this.components[plugin.pluginKey];
|
||||||
// 判断如果编辑器插件有init静态方法,则在此执行init方法
|
// 判断如果编辑器插件有init静态方法,则在此执行init方法
|
||||||
if (pluginClass && pluginClass.init) {
|
if (pluginClass && pluginClass.init) {
|
||||||
pluginClass.init(this);
|
pluginClass.init(this);
|
||||||
@ -182,5 +224,5 @@ export default class Editor extends EventEmitter {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,12 @@
|
|||||||
import Editor from './editor';
|
import Editor from './editor';
|
||||||
|
|
||||||
|
import * as utils from './utils';
|
||||||
|
import * as definitions from './definitions';
|
||||||
|
|
||||||
|
export { default as PluginFactory } from './pluginFactory';
|
||||||
|
export { default as EditorContext } from './context';
|
||||||
|
export { default as AreaManager } from './areaManager';
|
||||||
|
|
||||||
export default Editor;
|
export default Editor;
|
||||||
|
|
||||||
|
export { utils, definitions };
|
||||||
|
|||||||
@ -1,129 +0,0 @@
|
|||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
import EditorContext from './context';
|
|
||||||
import { isEmpty, generateI18n, goldlog } from './utils';
|
|
||||||
|
|
||||||
export interface pluginProps {
|
|
||||||
config: object,
|
|
||||||
editor: object,
|
|
||||||
locale: string,
|
|
||||||
messages: object
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function plugin(Comp) {
|
|
||||||
|
|
||||||
class Plugin extends PureComponent<pluginProps> {
|
|
||||||
static displayName = 'lowcode-editor-plugin';
|
|
||||||
static defaultProps = {
|
|
||||||
config: {}
|
|
||||||
};
|
|
||||||
static contextType = EditorContext;
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
if (isEmpty(props.config) || !props.config.pluginKey) {
|
|
||||||
console.warn('lowcode editor plugin has wrong config');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { locale, messages, editor } = props;
|
|
||||||
// 注册插件
|
|
||||||
this.editor = editor;
|
|
||||||
this.i18n = generateI18n(locale, messages);
|
|
||||||
this.pluginKey = props.config.pluginKey;
|
|
||||||
editor.plugins = editor.plugins || {};
|
|
||||||
editor.plugins[this.pluginKey] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
// 销毁插件
|
|
||||||
if (this.editor && this.editor.plugins) {
|
|
||||||
delete this.editor.plugins[this.pluginKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
config
|
|
||||||
} = this.props;
|
|
||||||
return <Comp i18n={this.i18n} editor={this.editor} config={config} {...config.pluginProps}/>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class Plugin extends PureComponent<pluginProps> {
|
|
||||||
static displayName = 'lowcode-editor-plugin';
|
|
||||||
static defaultProps = {
|
|
||||||
config: {}
|
|
||||||
};
|
|
||||||
static contextType = EditorContext;
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
if (isEmpty(props.config) || !props.config.addonKey) {
|
|
||||||
console.warn('luna addon has wrong config');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const { locale, messages, editor } = props;
|
|
||||||
// 注册插件
|
|
||||||
this.editor = editor;
|
|
||||||
this.i18n = generateI18n(locale, messages);
|
|
||||||
this.pluginKey = props.config.pluginKey;
|
|
||||||
editor.plugins = editor.plugins || {};
|
|
||||||
editor.plugins[this.pluginKey] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
async componentWillUnmount() {
|
|
||||||
// 销毁插件
|
|
||||||
if (this.editor && this.editor.plugins) {
|
|
||||||
delete this.editor.plugins[this.pluginKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open = () => {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
close = () => {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
goldlog = (goKey:string, params:any) => {
|
|
||||||
const { pluginKey, config = {} } = this.props.config || {};
|
|
||||||
goldlog(
|
|
||||||
goKey,
|
|
||||||
{
|
|
||||||
pluginKey,
|
|
||||||
package: config.package,
|
|
||||||
version: config.version,
|
|
||||||
...this.editor.logParams,
|
|
||||||
...params
|
|
||||||
},
|
|
||||||
'addon'
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
get utils() {
|
|
||||||
return this.editor.utils;
|
|
||||||
}
|
|
||||||
|
|
||||||
get constants() {
|
|
||||||
return this.editor.constants;
|
|
||||||
}
|
|
||||||
|
|
||||||
get history() {
|
|
||||||
return this.editor.history;
|
|
||||||
}
|
|
||||||
|
|
||||||
get location() {
|
|
||||||
return this.editor.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -27,21 +27,26 @@ export default function pluginFactory(Comp: PluginClass): React.ComponentType<Pl
|
|||||||
console.warn('lowcode editor plugin has wrong config');
|
console.warn('lowcode editor plugin has wrong config');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { locale, messages, editor } = props;
|
const { editor } = props;
|
||||||
this.ref = createRef<React.ReactElement>();
|
this.ref = createRef<React.ReactElement>();
|
||||||
// 注册插件
|
// 注册插件
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.i18n = generateI18n(locale, messages);
|
|
||||||
this.pluginKey = props.config.pluginKey;
|
this.pluginKey = props.config.pluginKey;
|
||||||
|
const defaultProps = Comp.defaultProps || {};
|
||||||
|
const locale = this.editor.get('locale') || defaultProps.locale || 'zh-CN';
|
||||||
|
const editorMessages = this.editor.get('messages') || {};
|
||||||
|
const messages = editorMessages[this.pluginKey] || defaultProps.messages || {};
|
||||||
|
this.i18n = generateI18n(locale, messages);
|
||||||
|
|
||||||
editor.set('plugins', {
|
editor.set('plugins', {
|
||||||
...editor.plugins,
|
...editor.plugins,
|
||||||
[this.pluginKey]: this
|
[this.pluginKey]: this,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount(): void {
|
public componentWillUnmount(): void {
|
||||||
// 销毁插件
|
// 销毁插件
|
||||||
if (this.editor && this.editor.plugins) {
|
if (this.pluginKey && this.editor && this.editor.plugins) {
|
||||||
delete this.editor.plugins[this.pluginKey];
|
delete this.editor.plugins[this.pluginKey];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +71,7 @@ export default function pluginFactory(Comp: PluginClass): React.ComponentType<Pl
|
|||||||
i18n: this.i18n,
|
i18n: this.i18n,
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
config,
|
config,
|
||||||
...config.pluginProps
|
...config.pluginProps,
|
||||||
};
|
};
|
||||||
if (acceptsRef(Comp)) {
|
if (acceptsRef(Comp)) {
|
||||||
props.ref = this.ref;
|
props.ref = this.ref;
|
||||||
@ -1,17 +1,61 @@
|
|||||||
|
|
||||||
import IntlMessageFormat from 'intl-messageformat';
|
import IntlMessageFormat from 'intl-messageformat';
|
||||||
|
import keymaster from 'keymaster';
|
||||||
|
|
||||||
|
import _clone from 'lodash/cloneDeep';
|
||||||
|
import _debounce from 'lodash/debounce';
|
||||||
import _isEmpty from 'lodash/isEmpty';
|
import _isEmpty from 'lodash/isEmpty';
|
||||||
|
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;
|
||||||
export const isEmpty = _isEmpty;
|
export const isEmpty = _isEmpty;
|
||||||
|
export const throttle = _throttle;
|
||||||
|
export const debounce = _debounce;
|
||||||
|
|
||||||
/**
|
export const serialize = _serialize;
|
||||||
|
|
||||||
|
const ENV = {
|
||||||
|
TBE: 'TBE',
|
||||||
|
WEBIDE: 'WEB-IDE',
|
||||||
|
VSCODE: 'VSCODE',
|
||||||
|
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: {
|
||||||
|
logKey: string;
|
||||||
|
gmKey: string;
|
||||||
|
goKey: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
* 用于构造国际化字符串处理函数
|
* 用于构造国际化字符串处理函数
|
||||||
* @param {*} locale 国际化标识,例如 zh-CN、en-US
|
|
||||||
* @param {*} messages 国际化语言包
|
|
||||||
*/
|
*/
|
||||||
export function generateI18n(locale = 'zh-CN', messages = {}) {
|
export function generateI18n(locale: LocaleType = 'zh-CN', messages: I18nMessages = {}): I18nFunction {
|
||||||
return (key, values = {}) => {
|
return (key: string, values): string => {
|
||||||
if (!messages || !messages[key]) return '';
|
if (!messages || !messages[key]) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
const formater = new IntlMessageFormat(messages[key], locale);
|
const formater = new IntlMessageFormat(messages[key], locale);
|
||||||
return formater.format(values);
|
return formater.format(values);
|
||||||
};
|
};
|
||||||
@ -19,14 +63,16 @@ export function generateI18n(locale = 'zh-CN', messages = {}) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化参数
|
* 序列化参数
|
||||||
* @param {*} obj 参数
|
|
||||||
*/
|
*/
|
||||||
export function serializeParams(obj:object):string {
|
export function serializeParams(obj: object): string {
|
||||||
if (typeof obj !== 'object') return '';
|
if (typeof obj !== 'object') {
|
||||||
|
return '';
|
||||||
const res:Array<string> = [];
|
}
|
||||||
Object.entries(obj).forEach(([key, val]) => {
|
const res: string[] = [];
|
||||||
if (val === null || val === undefined || val === '') return;
|
Object.entries(obj).forEach(([key, val]): void => {
|
||||||
|
if (val === null || val === undefined || val === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (typeof val === 'object') {
|
if (typeof val === 'object') {
|
||||||
res.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}`);
|
res.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}`);
|
||||||
} else {
|
} else {
|
||||||
@ -42,12 +88,11 @@ export function serializeParams(obj:object):string {
|
|||||||
* @param {Object} params 参数
|
* @param {Object} params 参数
|
||||||
* @param {String} logKey 属性串
|
* @param {String} logKey 属性串
|
||||||
*/
|
*/
|
||||||
export function goldlog(gmKey, params = {}, logKey = 'other') {
|
export function goldlog(gmKey: string, params: object = {}, logKey: string = 'other'): void {
|
||||||
const sendIDEMessage = window.sendIDEMessage || window.parent.sendIDEMessage;
|
const sendIDEMessage = window.sendIDEMessage || window.parent.sendIDEMessage;
|
||||||
const goKey = serializeParams({
|
const goKey = serializeParams({
|
||||||
sdkVersion: pkg.version,
|
|
||||||
env: getEnv(),
|
env: getEnv(),
|
||||||
...params
|
...params,
|
||||||
});
|
});
|
||||||
if (sendIDEMessage) {
|
if (sendIDEMessage) {
|
||||||
sendIDEMessage({
|
sendIDEMessage({
|
||||||
@ -55,155 +100,60 @@ export function goldlog(gmKey, params = {}, logKey = 'other') {
|
|||||||
data: {
|
data: {
|
||||||
logKey: `/iceluna.core.${logKey}`,
|
logKey: `/iceluna.core.${logKey}`,
|
||||||
gmKey,
|
gmKey,
|
||||||
goKey
|
goKey,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
window.goldlog && window.goldlog.record(`/iceluna.core.${logKey}`, gmKey, goKey, 'POST');
|
if (window.goldlog) {
|
||||||
|
window.goldlog.record(`/iceluna.core.${logKey}`, gmKey, goKey, 'POST');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前编辑器环境
|
* 获取当前编辑器环境
|
||||||
*/
|
*/
|
||||||
export function getEnv() {
|
export function getEnv(): string {
|
||||||
const userAgent = navigator.userAgent;
|
const userAgent = navigator.userAgent;
|
||||||
const isVscode = /Electron\//.test(userAgent);
|
const isVscode = /Electron\//.test(userAgent);
|
||||||
if (isVscode) return ENV.VSCODE;
|
if (isVscode) {
|
||||||
|
return ENV.VSCODE;
|
||||||
|
}
|
||||||
const isTheia = window.is_theia === true;
|
const isTheia = window.is_theia === true;
|
||||||
if (isTheia) return ENV.WEBIDE;
|
if (isTheia) {
|
||||||
|
return ENV.WEBIDE;
|
||||||
|
}
|
||||||
return ENV.WEB;
|
return ENV.WEB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册快捷键
|
// 注册快捷键
|
||||||
export function registShortCuts(config, editor) {
|
export function registShortCuts(config: ShortCutsConfig, editor: Editor): void {
|
||||||
const keyboardFilter = (keymaster.filter = event => {
|
(config || []).forEach((item): void => {
|
||||||
let eTarget = event.target || event.srcElement;
|
keymaster(item.keyboard, (ev: Event): void => {
|
||||||
let tagName = eTarget.tagName;
|
|
||||||
let isInput = !!(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
|
||||||
let isContenteditable = !!eTarget.getAttribute('contenteditable');
|
|
||||||
if (isInput || isContenteditable) {
|
|
||||||
if (event.metaKey === true && [70, 83].includes(event.keyCode)) event.preventDefault(); //禁止触发chrome原生的页面保存或查找
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ideMessage = appHelper.utils && appHelper.utils.ideMessage;
|
|
||||||
|
|
||||||
//复制
|
|
||||||
if (!document.copyListener) {
|
|
||||||
document.copyListener = e => {
|
|
||||||
if (!keyboardFilter(e) || appHelper.isCopying) return;
|
|
||||||
const schema = appHelper.schemaHelper && appHelper.schemaHelper.schemaMap[appHelper.activeKey];
|
|
||||||
if (!schema || !isSchema(schema)) return;
|
|
||||||
appHelper.isCopying = true;
|
|
||||||
const schemaStr = serialize(transformSchemaToPure(schema), {
|
|
||||||
unsafe: true
|
|
||||||
});
|
|
||||||
setClipboardData(schemaStr)
|
|
||||||
.then(() => {
|
|
||||||
ideMessage && ideMessage('success', '当前内容已复制到剪贴板,请使用快捷键Command+v进行粘贴');
|
|
||||||
appHelper.emit('schema.copy', schemaStr, schema);
|
|
||||||
appHelper.isCopying = false;
|
|
||||||
})
|
|
||||||
.catch(errMsg => {
|
|
||||||
ideMessage && ideMessage('error', errMsg);
|
|
||||||
appHelper.isCopying = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
document.addEventListener('copy', document.copyListener);
|
|
||||||
if (window.parent.vscode) {
|
|
||||||
keymaster('command+c', document.copyListener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//粘贴
|
|
||||||
if (!document.pasteListener) {
|
|
||||||
const doPaste = (e, text) => {
|
|
||||||
if (!keyboardFilter(e) || appHelper.isPasting) return;
|
|
||||||
const schemaHelper = appHelper.schemaHelper;
|
|
||||||
let targetKey = appHelper.activeKey;
|
|
||||||
let direction = 'after';
|
|
||||||
const topKey = schemaHelper.schema && schemaHelper.schema.__ctx && schemaHelper.schema.__ctx.lunaKey;
|
|
||||||
if (!targetKey || topKey === targetKey) {
|
|
||||||
const schemaHelper = appHelper.schemaHelper;
|
|
||||||
const topKey = schemaHelper.schema && schemaHelper.schema.__ctx && schemaHelper.schema.__ctx.lunaKey;
|
|
||||||
if (!topKey) return;
|
|
||||||
targetKey = topKey;
|
|
||||||
direction = 'in';
|
|
||||||
}
|
|
||||||
appHelper.isPasting = true;
|
|
||||||
const schema = parseObj(text);
|
|
||||||
if (!isSchema(schema)) {
|
|
||||||
appHelper.emit('illegalSchema.paste', text);
|
|
||||||
// ideMessage && ideMessage('error', '当前内容不是模型结构,不能粘贴进来!');
|
|
||||||
console.warn('paste schema illegal');
|
|
||||||
appHelper.isPasting = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
appHelper.emit('material.add', {
|
|
||||||
schema,
|
|
||||||
targetKey,
|
|
||||||
direction
|
|
||||||
});
|
|
||||||
appHelper.isPasting = false;
|
|
||||||
appHelper.emit('schema.paste', schema);
|
|
||||||
};
|
|
||||||
document.pasteListener = e => {
|
|
||||||
const clipboardData = e.clipboardData || window.clipboardData;
|
|
||||||
const text = clipboardData && clipboardData.getData('text');
|
|
||||||
doPaste(e, text);
|
|
||||||
};
|
|
||||||
document.addEventListener('paste', document.pasteListener);
|
|
||||||
if (window.parent.vscode) {
|
|
||||||
keymaster('command+v', e => {
|
|
||||||
const sendIDEMessage = window.parent.sendIDEMessage;
|
|
||||||
sendIDEMessage &&
|
|
||||||
sendIDEMessage({
|
|
||||||
action: 'readClipboard'
|
|
||||||
})
|
|
||||||
.then(text => {
|
|
||||||
doPaste(e, text);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.warn(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(config || []).forEach(item => {
|
|
||||||
keymaster(item.keyboard, ev => {
|
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
item.handler(ev, appHelper, keymaster);
|
item.handler(editor, ev, keymaster);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消注册快捷
|
// 取消注册快捷
|
||||||
export function unRegistShortCuts(config) {
|
export function unRegistShortCuts(config: ShortCutsConfig): void {
|
||||||
(config || []).forEach(item => {
|
(config || []).forEach((item): void => {
|
||||||
keymaster.unbind(item.keyboard);
|
keymaster.unbind(item.keyboard);
|
||||||
});
|
});
|
||||||
if (window.parent.vscode) {
|
if (window.parent.vscode) {
|
||||||
keymaster.unbind('command+c');
|
keymaster.unbind('command+c');
|
||||||
keymaster.unbind('command+v');
|
keymaster.unbind('command+v');
|
||||||
}
|
}
|
||||||
if (document.copyListener) {
|
|
||||||
document.removeEventListener('copy', document.copyListener);
|
|
||||||
delete document.copyListener;
|
|
||||||
}
|
|
||||||
if (document.pasteListener) {
|
|
||||||
document.removeEventListener('paste', document.pasteListener);
|
|
||||||
delete document.pasteListener;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将函数返回结果转成promise形式,如果函数有返回值则根据返回值的bool类型判断是reject还是resolve,若函数无返回值默认执行resolve
|
/**
|
||||||
export function transformToPromise(input) {
|
* 将函数返回结果转成promise形式,如果函数有返回值则根据返回值的bool类型判断是reject还是resolve,若函数无返回值默认执行resolve
|
||||||
if (input instanceof Promise) return input;
|
*/
|
||||||
return new Promise((resolve, reject) => {
|
export function transformToPromise(input: any): Promise<{}> {
|
||||||
|
if (input instanceof Promise) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject): void => {
|
||||||
if (input || input === undefined) {
|
if (input || input === undefined) {
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
@ -212,31 +162,111 @@ export function transformToPromise(input) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function comboEditorConfig(defaultConfig, customConfig) {
|
/**
|
||||||
const { ideConfig = {}, utils = {} } = this.props;
|
* 将数组类型转换为Map类型
|
||||||
const comboShortCuts = () => {
|
*/
|
||||||
const defaultShortCuts = defaultIdeConfig.shortCuts;
|
interface MapOf<T> {
|
||||||
const shortCuts = ideConfig.shortCuts || [];
|
[propName: string]: T;
|
||||||
const configMap = skeletonUtils.transformArrayToMap(defaultShortCuts, 'keyboard');
|
}
|
||||||
(shortCuts || []).forEach(item => {
|
export function transformArrayToMap<T>(arr: T[], key: string, overwrite: boolean = true): MapOf<T> {
|
||||||
configMap[item.keyboard] = item;
|
if (isEmpty(arr) || !Array.isArray(arr)) {
|
||||||
});
|
return {};
|
||||||
return Object.keys(configMap).map(key => configMap[key]);
|
}
|
||||||
};
|
const res = {};
|
||||||
return {
|
arr.forEach((item): void => {
|
||||||
...ideConfig,
|
const curKey = item[key];
|
||||||
utils: {
|
if (item[key] === undefined) {
|
||||||
...skeletonUtils,
|
return;
|
||||||
...utils
|
}
|
||||||
},
|
if (res[curKey] && !overwrite) {
|
||||||
constants: {
|
return;
|
||||||
...defaultIdeConfig.constants,
|
}
|
||||||
...ideConfig.constants
|
res[curKey] = item;
|
||||||
},
|
});
|
||||||
extensions: {
|
return res;
|
||||||
...defaultIdeConfig.extensions,
|
}
|
||||||
...ideConfig.extensions
|
|
||||||
},
|
/**
|
||||||
shortCuts: comboShortCuts()
|
* 解析url的查询参数
|
||||||
};
|
*/
|
||||||
|
interface Query {
|
||||||
|
[propName: string]: string;
|
||||||
|
}
|
||||||
|
export function parseSearch(search: string): Query {
|
||||||
|
if (!search || typeof search !== 'string') {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const str = search.replace(/^\?/, '');
|
||||||
|
const paramStr = str.split('&');
|
||||||
|
const res = {};
|
||||||
|
paramStr.forEach((item): void => {
|
||||||
|
const regRes = item.split('=');
|
||||||
|
if (regRes[0] && regRes[1]) {
|
||||||
|
res[regRes[0]] = decodeURIComponent(regRes[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function comboEditorConfig(defaultConfig: EditorConfig = {}, customConfig: EditorConfig): EditorConfig {
|
||||||
|
const { skeleton, theme, plugins, hooks, shortCuts, lifeCycles, constants, utils, i18n } = customConfig || {};
|
||||||
|
|
||||||
|
if (skeleton && skeleton.handler && typeof skeleton.handler === 'function') {
|
||||||
|
return skeleton.handler({
|
||||||
|
skeleton,
|
||||||
|
...defaultConfig,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultShortCuts = transformArrayToMap(defaultConfig.shortCuts || [], 'keyboard');
|
||||||
|
const customShortCuts = transformArrayToMap(shortCuts || [], 'keyboard');
|
||||||
|
const localeList = ['zh-CN', 'zh-TW', 'en-US', 'ja-JP'];
|
||||||
|
const i18nConfig = {};
|
||||||
|
localeList.forEach((key): void => {
|
||||||
|
i18nConfig[key] = {
|
||||||
|
...(defaultConfig.i18n && defaultConfig.i18n[key]),
|
||||||
|
...(i18n && i18n[key]),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
skeleton,
|
||||||
|
theme: {
|
||||||
|
...defaultConfig.theme,
|
||||||
|
...theme,
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
...defaultConfig.plugins,
|
||||||
|
...plugins,
|
||||||
|
},
|
||||||
|
hooks: [...(defaultConfig.hooks || []), ...(hooks || [])],
|
||||||
|
shortCuts: Object.values({
|
||||||
|
...defaultShortCuts,
|
||||||
|
...customShortCuts,
|
||||||
|
}),
|
||||||
|
lifeCycles: {
|
||||||
|
...defaultConfig.lifeCycles,
|
||||||
|
...lifeCycles,
|
||||||
|
},
|
||||||
|
constants: {
|
||||||
|
...defaultConfig.constants,
|
||||||
|
...constants,
|
||||||
|
},
|
||||||
|
utils: [...(defaultConfig.utils || []), ...(utils || [])],
|
||||||
|
i18n: i18nConfig,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前组件是否能够设置ref
|
||||||
|
* @param {*} Comp 需要判断的组件
|
||||||
|
*/
|
||||||
|
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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@ -1,7 +1,16 @@
|
|||||||
const { eslint, deepmerge } = require('@ice/spec');
|
const { tslint, deepmerge } = require('@ice/spec');
|
||||||
|
|
||||||
module.exports = deepmerge(eslint, {
|
module.exports = deepmerge(tslint, {
|
||||||
rules: {
|
rules: {
|
||||||
"global-require": 0,
|
"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/explicit-member-accessibility": 0
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,30 +1,36 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig, PluginClass } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class LeftAddon extends PureComponent {
|
export interface LeftPluginProps {
|
||||||
|
active?: boolean;
|
||||||
|
config: PluginConfig;
|
||||||
|
disabled?: boolean;
|
||||||
|
editor: Editor;
|
||||||
|
locked?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
|
pluginClass: PluginClass | undefined;
|
||||||
|
}
|
||||||
|
export interface LeftPluginState {
|
||||||
|
dialogVisible: boolean;
|
||||||
|
}
|
||||||
|
export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPluginState> {
|
||||||
static displayName: string;
|
static displayName: string;
|
||||||
static propTypes: {
|
|
||||||
active: any;
|
|
||||||
config: any;
|
|
||||||
disabled: any;
|
|
||||||
dotted: any;
|
|
||||||
locked: any;
|
|
||||||
onClick: any;
|
|
||||||
};
|
|
||||||
static defaultProps: {
|
static defaultProps: {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
config: {};
|
config: {};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
dotted: boolean;
|
marked: boolean;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
};
|
};
|
||||||
static contextType: any;
|
|
||||||
constructor(props: any, context: any);
|
constructor(props: any, context: any);
|
||||||
componentDidMount(): void;
|
componentDidMount(): void;
|
||||||
componentWillUnmount(): void;
|
componentWillUnmount(): void;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
handleOpen: () => void;
|
handleOpen: () => void;
|
||||||
handleShow: () => void;
|
handleShow: () => void;
|
||||||
renderIcon: (clickCallback: any) => JSX.Element;
|
renderIcon: (clickCallback: any) => any;
|
||||||
render(): JSX.Element;
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,30 @@
|
|||||||
|
import _Balloon from "@alifd/next/es/balloon";
|
||||||
|
import _Dialog from "@alifd/next/es/dialog";
|
||||||
import _extends from "@babel/runtime/helpers/extends";
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
|
import _Badge from "@alifd/next/es/badge";
|
||||||
|
import _Icon from "@alifd/next/es/icon";
|
||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import React, { PureComponent, Fragment } from 'react';
|
import React, { PureComponent, Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import AppContext from '@ali/iceluna-sdk/lib/context/appContext';
|
|
||||||
import { Balloon, Dialog, Icon, Badge } from '@alife/next';
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
var LeftAddon = /*#__PURE__*/function (_PureComponent) {
|
var LeftPlugin = /*#__PURE__*/function (_PureComponent) {
|
||||||
_inheritsLoose(LeftAddon, _PureComponent);
|
_inheritsLoose(LeftPlugin, _PureComponent);
|
||||||
|
|
||||||
function LeftAddon(_props, context) {
|
function LeftPlugin(_props, context) {
|
||||||
var _this;
|
var _this;
|
||||||
|
|
||||||
_this = _PureComponent.call(this, _props, context) || this;
|
_this = _PureComponent.call(this, _props, context) || this;
|
||||||
|
|
||||||
_this.handleClose = function () {
|
_this.handleClose = function () {
|
||||||
var addonKey = _this.props.config && _this.props.config.addonKey;
|
var _this$props = _this.props,
|
||||||
var currentAddon = _this.appHelper.addons && _this.appHelper.addons[addonKey];
|
config = _this$props.config,
|
||||||
|
editor = _this$props.editor;
|
||||||
|
var pluginKey = config && config.pluginKey;
|
||||||
|
var plugin = editor.plugins && editor.plugins[pluginKey];
|
||||||
|
|
||||||
if (currentAddon) {
|
if (plugin) {
|
||||||
_this.utils.transformToPromise(currentAddon.close()).then(function () {
|
plugin.close().then(function () {
|
||||||
_this.setState({
|
_this.setState({
|
||||||
dialogVisible: false
|
dialogVisible: false
|
||||||
});
|
});
|
||||||
@ -36,33 +40,37 @@ var LeftAddon = /*#__PURE__*/function (_PureComponent) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_this.handleShow = function () {
|
_this.handleShow = function () {
|
||||||
var _this$props = _this.props,
|
var _this$props2 = _this.props,
|
||||||
disabled = _this$props.disabled,
|
disabled = _this$props2.disabled,
|
||||||
config = _this$props.config,
|
config = _this$props2.config,
|
||||||
onClick = _this$props.onClick;
|
onClick = _this$props2.onClick,
|
||||||
var addonKey = config && config.addonKey;
|
editor = _this$props2.editor;
|
||||||
if (disabled || !addonKey) return; //考虑到弹窗情况,延时发送消息
|
var pluginKey = config && config.pluginKey;
|
||||||
|
if (disabled || !pluginKey) return;
|
||||||
|
|
||||||
|
_this.handleOpen(); // 考虑到弹窗情况,延时发送消息
|
||||||
|
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
return _this.appHelper.emit(addonKey + ".addon.activate");
|
editor.emit(pluginKey + ".plugin.activate");
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
_this.handleOpen();
|
if (onClick) {
|
||||||
|
onClick();
|
||||||
onClick && onClick();
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_this.renderIcon = function (clickCallback) {
|
_this.renderIcon = function (clickCallback) {
|
||||||
var _this$props2 = _this.props,
|
var _this$props3 = _this.props,
|
||||||
active = _this$props2.active,
|
active = _this$props3.active,
|
||||||
disabled = _this$props2.disabled,
|
disabled = _this$props3.disabled,
|
||||||
dotted = _this$props2.dotted,
|
marked = _this$props3.marked,
|
||||||
locked = _this$props2.locked,
|
locked = _this$props3.locked,
|
||||||
_onClick = _this$props2.onClick,
|
_onClick = _this$props3.onClick,
|
||||||
config = _this$props2.config;
|
config = _this$props3.config;
|
||||||
|
|
||||||
var _ref = config || {},
|
var _ref = config || {},
|
||||||
addonKey = _ref.addonKey,
|
pluginKey = _ref.pluginKey,
|
||||||
props = _ref.props;
|
props = _ref.props;
|
||||||
|
|
||||||
var _ref2 = props || {},
|
var _ref2 = props || {},
|
||||||
@ -70,24 +78,24 @@ var LeftAddon = /*#__PURE__*/function (_PureComponent) {
|
|||||||
title = _ref2.title;
|
title = _ref2.title;
|
||||||
|
|
||||||
return React.createElement("div", {
|
return React.createElement("div", {
|
||||||
className: classNames('luna-left-addon', addonKey, {
|
className: classNames('lowcode-left-plugin', pluginKey, {
|
||||||
active: active,
|
active: active,
|
||||||
disabled: disabled,
|
disabled: disabled,
|
||||||
locked: locked
|
locked: locked
|
||||||
}),
|
}),
|
||||||
"data-tooltip": title,
|
"data-tooltip": title,
|
||||||
onClick: function onClick() {
|
onClick: function onClick() {
|
||||||
if (disabled) return; //考虑到弹窗情况,延时发送消息
|
if (disabled) return; // 考虑到弹窗情况,延时发送消息
|
||||||
|
|
||||||
clickCallback && clickCallback();
|
clickCallback && clickCallback();
|
||||||
_onClick && _onClick();
|
_onClick && _onClick();
|
||||||
}
|
}
|
||||||
}, dotted ? React.createElement(Badge, {
|
}, marked ? React.createElement(_Badge, {
|
||||||
dot: true
|
dot: true
|
||||||
}, React.createElement(Icon, {
|
}, React.createElement(_Icon, {
|
||||||
type: icon,
|
type: icon,
|
||||||
size: "small"
|
size: "small"
|
||||||
})) : React.createElement(Icon, {
|
})) : React.createElement(_Icon, {
|
||||||
type: icon,
|
type: icon,
|
||||||
size: "small"
|
size: "small"
|
||||||
}));
|
}));
|
||||||
@ -96,118 +104,106 @@ var LeftAddon = /*#__PURE__*/function (_PureComponent) {
|
|||||||
_this.state = {
|
_this.state = {
|
||||||
dialogVisible: false
|
dialogVisible: false
|
||||||
};
|
};
|
||||||
_this.appHelper = context.appHelper;
|
|
||||||
_this.utils = _this.appHelper.utils;
|
|
||||||
_this.constants = _this.appHelper.constants;
|
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _proto = LeftAddon.prototype;
|
var _proto = LeftPlugin.prototype;
|
||||||
|
|
||||||
_proto.componentDidMount = function componentDidMount() {
|
_proto.componentDidMount = function componentDidMount() {
|
||||||
var config = this.props.config;
|
var _this$props4 = this.props,
|
||||||
var addonKey = config && config.addonKey;
|
config = _this$props4.config,
|
||||||
var appHelper = this.appHelper;
|
editor = _this$props4.editor;
|
||||||
|
var pluginKey = config && config.pluginKey;
|
||||||
|
|
||||||
if (appHelper && addonKey) {
|
if (editor && pluginKey) {
|
||||||
appHelper.on(addonKey + ".dialog.show", this.handleShow);
|
editor.on(pluginKey + ".dialog.show", this.handleShow);
|
||||||
appHelper.on(addonKey + ".dialog.close", this.handleClose);
|
editor.on(pluginKey + ".dialog.close", this.handleClose);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.componentWillUnmount = function componentWillUnmount() {
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
var config = this.props.config;
|
var _this$props5 = this.props,
|
||||||
var appHelper = this.appHelper;
|
config = _this$props5.config,
|
||||||
var addonKey = config && config.addonKey;
|
editor = _this$props5.editor;
|
||||||
|
var pluginKey = config && config.pluginKey;
|
||||||
|
|
||||||
if (appHelper && addonKey) {
|
if (editor && pluginKey) {
|
||||||
appHelper.off(addonKey + ".dialog.show", this.handleShow);
|
editor.off(pluginKey + ".dialog.show", this.handleShow);
|
||||||
appHelper.off(addonKey + ".dialog.close", this.handleClose);
|
editor.off(pluginKey + ".dialog.close", this.handleClose);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.render = function render() {
|
||||||
var _this2 = this;
|
var _this2 = this;
|
||||||
|
|
||||||
var _this$props3 = this.props,
|
var _this$props6 = this.props,
|
||||||
dotted = _this$props3.dotted,
|
marked = _this$props6.marked,
|
||||||
locked = _this$props3.locked,
|
locked = _this$props6.locked,
|
||||||
active = _this$props3.active,
|
active = _this$props6.active,
|
||||||
disabled = _this$props3.disabled,
|
disabled = _this$props6.disabled,
|
||||||
config = _this$props3.config;
|
config = _this$props6.config,
|
||||||
|
editor = _this$props6.editor,
|
||||||
|
Comp = _this$props6.pluginClass;
|
||||||
|
|
||||||
var _ref3 = config || {},
|
var _ref3 = config || {},
|
||||||
addonKey = _ref3.addonKey,
|
pluginKey = _ref3.pluginKey,
|
||||||
props = _ref3.props,
|
props = _ref3.props,
|
||||||
type = _ref3.type,
|
type = _ref3.type,
|
||||||
addonProps = _ref3.addonProps;
|
pluginProps = _ref3.pluginProps;
|
||||||
|
|
||||||
var _ref4 = props || {},
|
var _ref4 = props || {},
|
||||||
_onClick2 = _ref4.onClick,
|
_onClick2 = _ref4.onClick,
|
||||||
title = _ref4.title;
|
title = _ref4.title;
|
||||||
|
|
||||||
var dialogVisible = this.state.dialogVisible;
|
var dialogVisible = this.state.dialogVisible;
|
||||||
var _this$context = this.context,
|
if (!pluginKey || !type || !props) return null;
|
||||||
appHelper = _this$context.appHelper,
|
var node = Comp ? React.createElement(Comp, _extends({
|
||||||
components = _this$context.components;
|
editor: editor,
|
||||||
if (!addonKey || !type || !props) return null;
|
|
||||||
var componentName = appHelper.utils.generateAddonCompName(addonKey);
|
|
||||||
var localeProps = {};
|
|
||||||
var locale = appHelper.locale,
|
|
||||||
messages = appHelper.messages;
|
|
||||||
|
|
||||||
if (locale) {
|
|
||||||
localeProps.locale = locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messages && messages[componentName]) {
|
|
||||||
localeProps.messages = messages[componentName];
|
|
||||||
}
|
|
||||||
|
|
||||||
var AddonComp = components && components[componentName];
|
|
||||||
var node = AddonComp && React.createElement(AddonComp, _extends({
|
|
||||||
active: active,
|
active: active,
|
||||||
locked: locked,
|
locked: locked,
|
||||||
disabled: disabled,
|
disabled: disabled,
|
||||||
config: config,
|
config: config,
|
||||||
onClick: function onClick() {
|
onClick: function onClick() {
|
||||||
_onClick2 && _onClick2.call(null, appHelper);
|
_onClick2 && _onClick2.call(null, editor);
|
||||||
}
|
}
|
||||||
}, localeProps, addonProps || {})) || null;
|
}, pluginProps)) : null;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'LinkIcon':
|
case 'LinkIcon':
|
||||||
return React.createElement("a", props.linkProps || {}, this.renderIcon(function () {
|
return React.createElement("a", props.linkProps || {}, this.renderIcon(function () {
|
||||||
_onClick2 && _onClick2.call(null, appHelper);
|
_onClick2 && _onClick2.call(null, editor);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
case 'Icon':
|
case 'Icon':
|
||||||
return this.renderIcon(function () {
|
return this.renderIcon(function () {
|
||||||
_onClick2 && _onClick2.call(null, appHelper);
|
_onClick2 && _onClick2.call(null, editor);
|
||||||
});
|
});
|
||||||
|
|
||||||
case 'DialogIcon':
|
case 'DialogIcon':
|
||||||
return React.createElement(Fragment, null, this.renderIcon(function () {
|
return React.createElement(Fragment, null, this.renderIcon(function () {
|
||||||
_onClick2 && _onClick2.call(null, appHelper);
|
_onClick2 && _onClick2.call(null, editor);
|
||||||
|
|
||||||
_this2.handleOpen();
|
_this2.handleOpen();
|
||||||
}), React.createElement(Dialog, _extends({
|
}), React.createElement(_Dialog, _extends({
|
||||||
onOk: function onOk() {
|
onOk: function onOk() {
|
||||||
appHelper.emit(addonKey + ".dialog.onOk");
|
editor.emit(pluginKey + ".dialog.onOk");
|
||||||
|
|
||||||
_this2.handleClose();
|
_this2.handleClose();
|
||||||
},
|
},
|
||||||
onCancel: this.handleClose,
|
onCancel: this.handleClose,
|
||||||
onClose: this.handleClose,
|
onClose: this.handleClose,
|
||||||
title: title
|
title: title,
|
||||||
|
style: _extends({
|
||||||
|
width: 500
|
||||||
|
}, props.dialogProps && props.dialogProps.style)
|
||||||
}, props.dialogProps || {}, {
|
}, props.dialogProps || {}, {
|
||||||
visible: dialogVisible
|
visible: dialogVisible
|
||||||
}), node));
|
}), node));
|
||||||
|
|
||||||
case 'BalloonIcon':
|
case 'BalloonIcon':
|
||||||
return React.createElement(Balloon, _extends({
|
return React.createElement(_Balloon, _extends({
|
||||||
trigger: this.renderIcon(function () {
|
trigger: this.renderIcon(function () {
|
||||||
_onClick2 && _onClick2.call(null, appHelper);
|
_onClick2 && _onClick2.call(null, editor);
|
||||||
}),
|
}),
|
||||||
align: "r",
|
align: "r",
|
||||||
triggerType: ['click', 'hover']
|
triggerType: ['click', 'hover']
|
||||||
@ -215,13 +211,11 @@ var LeftAddon = /*#__PURE__*/function (_PureComponent) {
|
|||||||
|
|
||||||
case 'PanelIcon':
|
case 'PanelIcon':
|
||||||
return this.renderIcon(function () {
|
return this.renderIcon(function () {
|
||||||
_onClick2 && _onClick2.call(null, appHelper);
|
_onClick2 && _onClick2.call(null, editor);
|
||||||
|
|
||||||
_this2.handleOpen();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
case 'Custom':
|
case 'Custom':
|
||||||
return dotted ? React.createElement(Badge, {
|
return marked ? React.createElement(_Badge, {
|
||||||
dot: true
|
dot: true
|
||||||
}, node) : node;
|
}, node) : node;
|
||||||
|
|
||||||
@ -230,30 +224,16 @@ var LeftAddon = /*#__PURE__*/function (_PureComponent) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return LeftAddon;
|
return LeftPlugin;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
LeftAddon.displayName = 'LunaLeftAddon';
|
LeftPlugin.displayName = 'LowcodeLeftPlugin';
|
||||||
LeftAddon.propTypes = {
|
LeftPlugin.defaultProps = {
|
||||||
active: PropTypes.bool,
|
|
||||||
config: PropTypes.shape({
|
|
||||||
addonKey: PropTypes.string,
|
|
||||||
addonProps: PropTypes.object,
|
|
||||||
props: PropTypes.object,
|
|
||||||
type: PropTypes.oneOf(['DialogIcon', 'BalloonIcon', 'PanelIcon', 'LinkIcon', 'Icon', 'Custom'])
|
|
||||||
}),
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
dotted: PropTypes.bool,
|
|
||||||
locked: PropTypes.bool,
|
|
||||||
onClick: PropTypes.func
|
|
||||||
};
|
|
||||||
LeftAddon.defaultProps = {
|
|
||||||
active: false,
|
active: false,
|
||||||
config: {},
|
config: {},
|
||||||
disabled: false,
|
disabled: false,
|
||||||
dotted: false,
|
marked: false,
|
||||||
locked: false,
|
locked: false,
|
||||||
onClick: function onClick() {}
|
onClick: function onClick() {}
|
||||||
};
|
};
|
||||||
LeftAddon.contextType = AppContext;
|
export { LeftPlugin as default };
|
||||||
export { LeftAddon as default };
|
|
||||||
@ -1,59 +1,60 @@
|
|||||||
.luna-left-addon {
|
.lowcode-left-plugin {
|
||||||
font-size: 16px;
|
font-size: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 36px;
|
line-height: 44px;
|
||||||
height: 36px;
|
height: 44px;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
color: #777;
|
color: $color-text1-3;
|
||||||
&.collapse {
|
|
||||||
height: 40px;
|
|
||||||
color: #8c8c8c;
|
|
||||||
border-bottom: 1px solid #bfbfbf;
|
|
||||||
}
|
|
||||||
&.locked {
|
&.locked {
|
||||||
color: red !important;
|
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 {
|
&:hover {
|
||||||
background-color: $color-brand1-1;
|
|
||||||
color: $color-brand1-6;
|
color: $color-brand1-6;
|
||||||
&:before {
|
&:before {
|
||||||
content: attr(data-tooltip);
|
content: attr(data-tooltip);
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50px;
|
left: 45px;
|
||||||
top: 5px;
|
top: 8px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding: 6px 8px;
|
padding: 6px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: rgba(0, 0, 0, 0.75);
|
background: $balloon-normal-color-bg;
|
||||||
color: #fff;
|
border: 1px solid $balloon-normal-color-border;
|
||||||
|
opacity: 0.8;
|
||||||
|
color: $color-text1-3;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
&:after {
|
&:after {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
transform: rotate(45deg);
|
||||||
left: 40px;
|
left: 40px;
|
||||||
top: 15px;
|
top: 18px;
|
||||||
border: 5px solid transparent;
|
background: $balloon-normal-color-bg;
|
||||||
border-right-color: rgba(0, 0, 0, 0.75);
|
border-left: 1px solid $balloon-normal-color-border;
|
||||||
|
border-bottom: 1px solid $balloon-normal-color-border;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.active {
|
||||||
|
color: $color-brand1-9;
|
||||||
|
&.disabled {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
color: $color-brand1-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
packages/editor-skeleton/es/components/Panel/index.d.ts
vendored
Normal file
27
packages/editor-skeleton/es/components/Panel/index.d.ts
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import './index.scss';
|
||||||
|
export interface PanelProps {
|
||||||
|
align: 'left' | 'right';
|
||||||
|
defaultWidth: number;
|
||||||
|
minWidth: number;
|
||||||
|
draggable: boolean;
|
||||||
|
floatable: boolean;
|
||||||
|
children: Plugin;
|
||||||
|
visible: boolean;
|
||||||
|
}
|
||||||
|
export interface PanelState {
|
||||||
|
width: number;
|
||||||
|
}
|
||||||
|
export default class Panel extends PureComponent<PanelProps, PanelState> {
|
||||||
|
static displayName: string;
|
||||||
|
static defaultProps: {
|
||||||
|
align: string;
|
||||||
|
defaultWidth: number;
|
||||||
|
minWidth: number;
|
||||||
|
draggable: boolean;
|
||||||
|
floatable: boolean;
|
||||||
|
visible: boolean;
|
||||||
|
};
|
||||||
|
constructor(props: any);
|
||||||
|
render(): React.ReactNode;
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
var Panel = /*#__PURE__*/function (_PureComponent) {
|
||||||
|
_inheritsLoose(Panel, _PureComponent);
|
||||||
|
|
||||||
|
function Panel(props) {
|
||||||
|
var _this;
|
||||||
|
|
||||||
|
_this = _PureComponent.call(this, props) || this;
|
||||||
|
_this.state = {
|
||||||
|
width: props.defaultWidth
|
||||||
|
};
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _proto = Panel.prototype;
|
||||||
|
|
||||||
|
_proto.render = function render() {
|
||||||
|
var _this$props = this.props,
|
||||||
|
align = _this$props.align,
|
||||||
|
draggable = _this$props.draggable,
|
||||||
|
floatable = _this$props.floatable,
|
||||||
|
visible = _this$props.visible;
|
||||||
|
var width = this.state.width;
|
||||||
|
return React.createElement("div", {
|
||||||
|
className: classNames('lowcode-panel', align, {
|
||||||
|
draggable: draggable,
|
||||||
|
floatable: floatable,
|
||||||
|
visible: visible
|
||||||
|
}),
|
||||||
|
style: {
|
||||||
|
width: width,
|
||||||
|
display: visible ? '' : 'none'
|
||||||
|
}
|
||||||
|
}, this.props.children, React.createElement("div", {
|
||||||
|
className: "drag-area"
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
return Panel;
|
||||||
|
}(PureComponent);
|
||||||
|
|
||||||
|
Panel.displayName = 'LowcodePanel';
|
||||||
|
Panel.defaultProps = {
|
||||||
|
align: 'left',
|
||||||
|
defaultWidth: 240,
|
||||||
|
minWidth: 100,
|
||||||
|
draggable: true,
|
||||||
|
floatable: false,
|
||||||
|
visible: true
|
||||||
|
};
|
||||||
|
export { Panel as default };
|
||||||
@ -1,19 +1,19 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class TopIcon extends PureComponent {
|
export interface TopIconProps {
|
||||||
|
active?: boolean;
|
||||||
|
className?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
icon: string;
|
||||||
|
id?: string;
|
||||||
|
locked?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
title?: string;
|
||||||
|
}
|
||||||
|
export default class TopIcon extends PureComponent<TopIconProps> {
|
||||||
static displayName: string;
|
static displayName: string;
|
||||||
static propTypes: {
|
|
||||||
active: any;
|
|
||||||
className: any;
|
|
||||||
disabled: any;
|
|
||||||
icon: any;
|
|
||||||
id: any;
|
|
||||||
locked: any;
|
|
||||||
onClick: any;
|
|
||||||
showTitle: any;
|
|
||||||
style: any;
|
|
||||||
title: any;
|
|
||||||
};
|
|
||||||
static defaultProps: {
|
static defaultProps: {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
className: string;
|
className: string;
|
||||||
@ -22,9 +22,8 @@ export default class TopIcon extends PureComponent {
|
|||||||
id: string;
|
id: string;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
showTitle: boolean;
|
|
||||||
style: {};
|
style: {};
|
||||||
title: string;
|
title: string;
|
||||||
};
|
};
|
||||||
render(): JSX.Element;
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import _Button from "@alifd/next/es/button";
|
|
||||||
import _Icon from "@alifd/next/es/icon";
|
import _Icon from "@alifd/next/es/icon";
|
||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
@ -25,42 +23,26 @@ var TopIcon = /*#__PURE__*/function (_PureComponent) {
|
|||||||
className = _this$props.className,
|
className = _this$props.className,
|
||||||
id = _this$props.id,
|
id = _this$props.id,
|
||||||
style = _this$props.style,
|
style = _this$props.style,
|
||||||
showTitle = _this$props.showTitle,
|
|
||||||
onClick = _this$props.onClick;
|
onClick = _this$props.onClick;
|
||||||
return React.createElement(_Button, {
|
return React.createElement("div", {
|
||||||
type: "normal",
|
className: classNames('lowcode-top-icon', className, {
|
||||||
size: "large",
|
|
||||||
text: true,
|
|
||||||
className: classNames('lowcode-top-btn', className, {
|
|
||||||
active: active,
|
active: active,
|
||||||
disabled: disabled,
|
disabled: disabled,
|
||||||
locked: locked
|
locked: locked
|
||||||
}),
|
}),
|
||||||
|
"data-tooltip": title,
|
||||||
id: id,
|
id: id,
|
||||||
style: style,
|
style: style,
|
||||||
onClick: disabled ? null : onClick
|
onClick: disabled ? undefined : onClick
|
||||||
}, React.createElement("div", null, React.createElement(_Icon, {
|
}, React.createElement(_Icon, {
|
||||||
size: "large",
|
|
||||||
type: icon
|
type: icon
|
||||||
}), showTitle && React.createElement("span", null, title)));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
return TopIcon;
|
return TopIcon;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
TopIcon.displayName = 'TopIcon';
|
TopIcon.displayName = 'LowcodeTopIcon';
|
||||||
TopIcon.propTypes = {
|
|
||||||
active: PropTypes.bool,
|
|
||||||
className: PropTypes.string,
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
icon: PropTypes.string,
|
|
||||||
id: PropTypes.string,
|
|
||||||
locked: PropTypes.bool,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
showTitle: PropTypes.bool,
|
|
||||||
style: PropTypes.object,
|
|
||||||
title: PropTypes.string
|
|
||||||
};
|
|
||||||
TopIcon.defaultProps = {
|
TopIcon.defaultProps = {
|
||||||
active: false,
|
active: false,
|
||||||
className: '',
|
className: '',
|
||||||
@ -69,7 +51,6 @@ TopIcon.defaultProps = {
|
|||||||
id: '',
|
id: '',
|
||||||
locked: false,
|
locked: false,
|
||||||
onClick: function onClick() {},
|
onClick: function onClick() {},
|
||||||
showTitle: false,
|
|
||||||
style: {},
|
style: {},
|
||||||
title: ''
|
title: ''
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,22 +1,68 @@
|
|||||||
.next-btn.next-large.lowcode-top-btn {
|
.lowcode-top-icon {
|
||||||
|
display: inline-block;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
font-size: 20px;
|
||||||
padding: 0;
|
line-height: 48px;
|
||||||
margin: 4px -2px;
|
color: $color-text1-3;
|
||||||
text-align: center;
|
position: relative;
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
color: #777;
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
color: $color-text1-1;
|
color: $color-text1-1;
|
||||||
|
&:hover {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
color: $color-brand1-9;
|
||||||
|
&:hover {
|
||||||
|
color: $color-brand1-6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.locked {
|
&.locked {
|
||||||
color: red !important;
|
color: red !important;
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
|
color: $color-brand1-6;
|
||||||
|
&:before {
|
||||||
|
content: attr(data-tooltip);
|
||||||
|
display: block;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
bottom: -32px;
|
||||||
|
line-height: 18px;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: $balloon-normal-color-bg;
|
||||||
|
border: 1px solid $balloon-normal-color-border;
|
||||||
|
opacity: 0.8;
|
||||||
|
color: $color-text1-3;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0) rotate(45deg);
|
||||||
|
bottom: -5px;
|
||||||
|
background: $balloon-normal-color-bg;
|
||||||
|
border-left: 1px solid $balloon-normal-color-border;
|
||||||
|
border-top: 1px solid $balloon-normal-color-border;
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
i.next-icon {
|
i.next-icon {
|
||||||
&:before {
|
&:before {
|
||||||
font-size: 17px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
|||||||
@ -1,12 +1,27 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig, PluginClass } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class TopPlugin extends PureComponent {
|
export interface TopPluginProps {
|
||||||
|
active?: boolean;
|
||||||
|
config: PluginConfig;
|
||||||
|
disabled?: boolean;
|
||||||
|
editor: Editor;
|
||||||
|
locked?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
|
pluginClass: PluginClass | undefined;
|
||||||
|
}
|
||||||
|
export interface TopPluginState {
|
||||||
|
dialogVisible: boolean;
|
||||||
|
}
|
||||||
|
export default class TopPlugin extends PureComponent<TopPluginProps, TopPluginState> {
|
||||||
static displayName: string;
|
static displayName: string;
|
||||||
static defaultProps: {
|
static defaultProps: {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
config: {};
|
config: {};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
dotted: boolean;
|
marked: boolean;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
};
|
};
|
||||||
@ -16,6 +31,6 @@ export default class TopPlugin extends PureComponent {
|
|||||||
handleShow: () => void;
|
handleShow: () => void;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
handleOpen: () => void;
|
handleOpen: () => void;
|
||||||
renderIcon: (clickCallback: any) => JSX.Element;
|
renderIcon: (clickCallback: any) => any;
|
||||||
render(): JSX.Element;
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,25 +19,29 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
var _this$props = _this.props,
|
var _this$props = _this.props,
|
||||||
disabled = _this$props.disabled,
|
disabled = _this$props.disabled,
|
||||||
config = _this$props.config,
|
config = _this$props.config,
|
||||||
onClick = _this$props.onClick;
|
onClick = _this$props.onClick,
|
||||||
var addonKey = config && config.addonKey;
|
editor = _this$props.editor;
|
||||||
if (disabled || !addonKey) return; //考虑到弹窗情况,延时发送消息
|
var pluginKey = config && config.pluginKey;
|
||||||
|
if (disabled || !pluginKey) return;
|
||||||
|
|
||||||
|
_this.handleOpen(); // 考虑到弹窗情况,延时发送消息
|
||||||
|
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
return _this.appHelper.emit(addonKey + ".addon.activate");
|
editor.emit(pluginKey + ".plugin.activate");
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
_this.handleOpen();
|
|
||||||
|
|
||||||
onClick && onClick();
|
onClick && onClick();
|
||||||
};
|
};
|
||||||
|
|
||||||
_this.handleClose = function () {
|
_this.handleClose = function () {
|
||||||
var addonKey = _this.props.config && _this.props.config.addonKey;
|
var _this$props2 = _this.props,
|
||||||
var currentAddon = _this.appHelper.addons && _this.appHelper.addons[addonKey];
|
config = _this$props2.config,
|
||||||
|
editor = _this$props2.editor;
|
||||||
|
var pluginKey = config && config.pluginKey;
|
||||||
|
var plugin = editor.plugins && editor.plugins[pluginKey];
|
||||||
|
|
||||||
if (currentAddon) {
|
if (plugin) {
|
||||||
_this.utils.transformToPromise(currentAddon.close()).then(function () {
|
plugin.close().then(function () {
|
||||||
_this.setState({
|
_this.setState({
|
||||||
dialogVisible: false
|
dialogVisible: false
|
||||||
});
|
});
|
||||||
@ -53,13 +57,14 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_this.renderIcon = function (clickCallback) {
|
_this.renderIcon = function (clickCallback) {
|
||||||
var _this$props2 = _this.props,
|
var _this$props3 = _this.props,
|
||||||
active = _this$props2.active,
|
active = _this$props3.active,
|
||||||
disabled = _this$props2.disabled,
|
disabled = _this$props3.disabled,
|
||||||
dotted = _this$props2.dotted,
|
marked = _this$props3.marked,
|
||||||
locked = _this$props2.locked,
|
locked = _this$props3.locked,
|
||||||
config = _this$props2.config,
|
config = _this$props3.config,
|
||||||
_onClick = _this$props2.onClick;
|
_onClick = _this$props3.onClick,
|
||||||
|
editor = _this$props3.editor;
|
||||||
|
|
||||||
var _ref = config || {},
|
var _ref = config || {},
|
||||||
pluginKey = _ref.pluginKey,
|
pluginKey = _ref.pluginKey,
|
||||||
@ -70,23 +75,23 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
title = _ref2.title;
|
title = _ref2.title;
|
||||||
|
|
||||||
var node = React.createElement(TopIcon, {
|
var node = React.createElement(TopIcon, {
|
||||||
className: "lowcode-top-addon " + pluginKey,
|
className: "lowcode-top-plugin " + pluginKey,
|
||||||
active: active,
|
active: active,
|
||||||
disabled: disabled,
|
disabled: disabled,
|
||||||
locked: locked,
|
locked: locked,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
title: title,
|
title: title,
|
||||||
onClick: function onClick() {
|
onClick: function onClick() {
|
||||||
if (disabled) return; //考虑到弹窗情况,延时发送消息
|
if (disabled) return; // 考虑到弹窗情况,延时发送消息
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
return _this.appHelper.emit(pluginKey + ".addon.activate");
|
editor.emit(pluginKey + ".plugin.activate");
|
||||||
}, 0);
|
}, 0);
|
||||||
clickCallback && clickCallback();
|
clickCallback && clickCallback();
|
||||||
_onClick && _onClick();
|
_onClick && _onClick();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return dotted ? React.createElement(_Badge, {
|
return marked ? React.createElement(_Badge, {
|
||||||
dot: true
|
dot: true
|
||||||
}, node) : node;
|
}, node) : node;
|
||||||
};
|
};
|
||||||
@ -100,34 +105,40 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
var _proto = TopPlugin.prototype;
|
var _proto = TopPlugin.prototype;
|
||||||
|
|
||||||
_proto.componentDidMount = function componentDidMount() {
|
_proto.componentDidMount = function componentDidMount() {
|
||||||
var config = this.props.config;
|
var _this$props4 = this.props,
|
||||||
var pluginKey = config && config.pluginKey; // const appHelper = this.appHelper;
|
config = _this$props4.config,
|
||||||
// if (appHelper && addonKey) {
|
editor = _this$props4.editor;
|
||||||
// appHelper.on(`${addonKey}.dialog.show`, this.handleShow);
|
var pluginKey = config && config.pluginKey;
|
||||||
// appHelper.on(`${addonKey}.dialog.close`, this.handleClose);
|
|
||||||
// }
|
if (editor && pluginKey) {
|
||||||
|
editor.on(pluginKey + ".dialog.show", this.handleShow);
|
||||||
|
editor.on(pluginKey + ".dialog.close", this.handleClose);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.componentWillUnmount = function componentWillUnmount() {// const { config } = this.props;
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
// const addonKey = config && config.addonKey;
|
var _this$props5 = this.props,
|
||||||
// const appHelper = this.appHelper;
|
config = _this$props5.config,
|
||||||
// if (appHelper && addonKey) {
|
editor = _this$props5.editor;
|
||||||
// appHelper.off(`${addonKey}.dialog.show`, this.handleShow);
|
var pluginKey = config && config.pluginKey;
|
||||||
// appHelper.off(`${addonKey}.dialog.close`, this.handleClose);
|
|
||||||
// }
|
if (editor && pluginKey) {
|
||||||
|
editor.off(pluginKey + ".dialog.show", this.handleShow);
|
||||||
|
editor.off(pluginKey + ".dialog.close", this.handleClose);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.render = function render() {
|
||||||
var _this2 = this;
|
var _this2 = this;
|
||||||
|
|
||||||
var _this$props3 = this.props,
|
var _this$props6 = this.props,
|
||||||
active = _this$props3.active,
|
active = _this$props6.active,
|
||||||
dotted = _this$props3.dotted,
|
marked = _this$props6.marked,
|
||||||
locked = _this$props3.locked,
|
locked = _this$props6.locked,
|
||||||
disabled = _this$props3.disabled,
|
disabled = _this$props6.disabled,
|
||||||
config = _this$props3.config,
|
config = _this$props6.config,
|
||||||
editor = _this$props3.editor,
|
editor = _this$props6.editor,
|
||||||
Comp = _this$props3.pluginClass;
|
Comp = _this$props6.pluginClass;
|
||||||
|
|
||||||
var _ref3 = config || {},
|
var _ref3 = config || {},
|
||||||
pluginKey = _ref3.pluginKey,
|
pluginKey = _ref3.pluginKey,
|
||||||
@ -140,8 +151,9 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
title = _ref4.title;
|
title = _ref4.title;
|
||||||
|
|
||||||
var dialogVisible = this.state.dialogVisible;
|
var dialogVisible = this.state.dialogVisible;
|
||||||
if (!pluginKey || !type || !Comp) return null;
|
if (!pluginKey || !type) return null;
|
||||||
var node = React.createElement(Comp, _extends({
|
var node = Comp ? React.createElement(Comp, _extends({
|
||||||
|
editor: editor,
|
||||||
active: active,
|
active: active,
|
||||||
locked: locked,
|
locked: locked,
|
||||||
disabled: disabled,
|
disabled: disabled,
|
||||||
@ -149,7 +161,7 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
onClick: function onClick() {
|
onClick: function onClick() {
|
||||||
_onClick2 && _onClick2.call(null, editor);
|
_onClick2 && _onClick2.call(null, editor);
|
||||||
}
|
}
|
||||||
}, pluginProps));
|
}, pluginProps)) : null;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'LinkIcon':
|
case 'LinkIcon':
|
||||||
@ -175,7 +187,10 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
},
|
},
|
||||||
onCancel: this.handleClose,
|
onCancel: this.handleClose,
|
||||||
onClose: this.handleClose,
|
onClose: this.handleClose,
|
||||||
title: title
|
title: title,
|
||||||
|
style: _extends({
|
||||||
|
width: 500
|
||||||
|
}, props.dialogProps && props.dialogProps.style)
|
||||||
}, props.dialogProps, {
|
}, props.dialogProps, {
|
||||||
visible: dialogVisible
|
visible: dialogVisible
|
||||||
}), node));
|
}), node));
|
||||||
@ -189,7 +204,7 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
}, props.balloonProps), node);
|
}, props.balloonProps), node);
|
||||||
|
|
||||||
case 'Custom':
|
case 'Custom':
|
||||||
return dotted ? React.createElement(_Badge, {
|
return marked ? React.createElement(_Badge, {
|
||||||
dot: true
|
dot: true
|
||||||
}, node) : node;
|
}, node) : node;
|
||||||
|
|
||||||
@ -201,12 +216,12 @@ var TopPlugin = /*#__PURE__*/function (_PureComponent) {
|
|||||||
return TopPlugin;
|
return TopPlugin;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
TopPlugin.displayName = 'lowcodeTopPlugin';
|
TopPlugin.displayName = 'LowcodeTopPlugin';
|
||||||
TopPlugin.defaultProps = {
|
TopPlugin.defaultProps = {
|
||||||
active: false,
|
active: false,
|
||||||
config: {},
|
config: {},
|
||||||
disabled: false,
|
disabled: false,
|
||||||
dotted: false,
|
marked: false,
|
||||||
locked: false,
|
locked: false,
|
||||||
onClick: function onClick() {}
|
onClick: function onClick() {}
|
||||||
};
|
};
|
||||||
|
|||||||
16
packages/editor-skeleton/es/config/skeleton.d.ts
vendored
16
packages/editor-skeleton/es/config/skeleton.d.ts
vendored
@ -1,14 +1,2 @@
|
|||||||
declare const routerConfig: {
|
declare const _default: {};
|
||||||
path: string;
|
export default _default;
|
||||||
component: any;
|
|
||||||
children: ({
|
|
||||||
path: string;
|
|
||||||
component: any;
|
|
||||||
redirect?: undefined;
|
|
||||||
} | {
|
|
||||||
path: string;
|
|
||||||
redirect: string;
|
|
||||||
component?: undefined;
|
|
||||||
})[];
|
|
||||||
}[];
|
|
||||||
export default routerConfig;
|
|
||||||
|
|||||||
@ -1,14 +1 @@
|
|||||||
import Dashboard from '@/pages/Dashboard';
|
export default {};
|
||||||
import BasicLayout from '@/layouts/BasicLayout';
|
|
||||||
var routerConfig = [{
|
|
||||||
path: '/',
|
|
||||||
component: BasicLayout,
|
|
||||||
children: [{
|
|
||||||
path: '/dashboard',
|
|
||||||
component: Dashboard
|
|
||||||
}, {
|
|
||||||
path: '/',
|
|
||||||
redirect: '/dashboard'
|
|
||||||
}]
|
|
||||||
}];
|
|
||||||
export default routerConfig;
|
|
||||||
@ -1,2 +1,2 @@
|
|||||||
declare const asideMenuConfig: any[];
|
declare const _default: {};
|
||||||
export { asideMenuConfig };
|
export default _default;
|
||||||
|
|||||||
@ -1,3 +1 @@
|
|||||||
// 菜单配置
|
export default {};
|
||||||
var asideMenuConfig = [];
|
|
||||||
export { asideMenuConfig };
|
|
||||||
@ -1,13 +1,14 @@
|
|||||||
body {
|
body {
|
||||||
font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma,
|
font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma, Arial, PingFang SC-Light, Microsoft YaHei;
|
||||||
Arial, PingFang SC-Light, Microsoft YaHei;
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
color: $color-text1-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.next-loading {
|
.next-loading {
|
||||||
.next-loading-wrap {
|
.next-loading-wrap {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -16,18 +17,17 @@ body {
|
|||||||
.lowcode-editor {
|
.lowcode-editor {
|
||||||
.lowcode-main-content {
|
.lowcode-main-content {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 48px;
|
top: 50px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #d8d8d8;
|
background-color: rgba(31, 56, 88, 0.06);
|
||||||
}
|
}
|
||||||
.lowcode-center-area {
|
.lowcode-center-area {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 10px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
40
packages/editor-skeleton/es/index.d.ts
vendored
40
packages/editor-skeleton/es/index.d.ts
vendored
@ -1,8 +1,42 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import { EditorConfig, Utils, PluginClassSet } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './global.scss';
|
import './global.scss';
|
||||||
export default class Skeleton extends PureComponent {
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__ctx: {
|
||||||
|
editor: Editor;
|
||||||
|
appHelper: Editor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export interface SkeletonProps {
|
||||||
|
components: PluginClassSet;
|
||||||
|
config: EditorConfig;
|
||||||
|
history: object;
|
||||||
|
location: object;
|
||||||
|
match: object;
|
||||||
|
utils: Utils;
|
||||||
|
}
|
||||||
|
export interface SkeletonState {
|
||||||
|
initReady?: boolean;
|
||||||
|
skeletonKey?: string;
|
||||||
|
__hasError?: boolean;
|
||||||
|
}
|
||||||
|
export declare class Skeleton extends PureComponent<SkeletonProps, SkeletonState> {
|
||||||
static displayName: string;
|
static displayName: string;
|
||||||
|
static getDerivedStateFromError(): SkeletonState;
|
||||||
|
private editor;
|
||||||
constructor(props: any);
|
constructor(props: any);
|
||||||
componentWillUnmount(): void;
|
componentWillUnmount(): void;
|
||||||
render(): JSX.Element;
|
componentDidCatch(err: any): void;
|
||||||
|
init: (isReset?: boolean) => void;
|
||||||
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
export interface SkeletonWithRouterProps {
|
||||||
|
components: PluginClassSet;
|
||||||
|
config: EditorConfig;
|
||||||
|
utils: Utils;
|
||||||
|
}
|
||||||
|
declare const SkeletonWithRouter: React.FC<SkeletonWithRouterProps>;
|
||||||
|
export default SkeletonWithRouter;
|
||||||
|
|||||||
@ -1,53 +1,125 @@
|
|||||||
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
|
||||||
import _ConfigProvider from "@alifd/next/es/config-provider";
|
import _ConfigProvider from "@alifd/next/es/config-provider";
|
||||||
import _Loading from "@alifd/next/es/loading";
|
import _Loading from "@alifd/next/es/loading";
|
||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import React, { PureComponent } from 'react'; // import Editor from '@ali/lowcode-engine-editor';
|
import React, { PureComponent } from 'react';
|
||||||
|
import { HashRouter as Router, Route } from 'react-router-dom';
|
||||||
|
import Editor, { utils } from '@ali/lowcode-editor-framework';
|
||||||
|
import defaultConfig from './config/skeleton';
|
||||||
|
import skeletonUtils from './config/utils';
|
||||||
import TopArea from './layouts/TopArea';
|
import TopArea from './layouts/TopArea';
|
||||||
import LeftArea from './layouts/LeftArea';
|
import LeftArea from './layouts/LeftArea';
|
||||||
import CenterArea from './layouts/CenterArea';
|
import CenterArea from './layouts/CenterArea';
|
||||||
import RightArea from './layouts/RightArea';
|
import RightArea from './layouts/RightArea';
|
||||||
import './global.scss';
|
import './global.scss';
|
||||||
|
var comboEditorConfig = utils.comboEditorConfig,
|
||||||
var Skeleton = /*#__PURE__*/function (_PureComponent) {
|
parseSearch = utils.parseSearch;
|
||||||
|
var renderIdx = 0;
|
||||||
|
export var Skeleton = /*#__PURE__*/function (_PureComponent) {
|
||||||
_inheritsLoose(Skeleton, _PureComponent);
|
_inheritsLoose(Skeleton, _PureComponent);
|
||||||
|
|
||||||
|
Skeleton.getDerivedStateFromError = function getDerivedStateFromError() {
|
||||||
|
return {
|
||||||
|
__hasError: true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function Skeleton(props) {
|
function Skeleton(props) {
|
||||||
var _this;
|
var _this;
|
||||||
|
|
||||||
_this = _PureComponent.call(this, props) || this; // this.editor = new Editor(props.config, props.utils);
|
_this = _PureComponent.call(this, props) || this;
|
||||||
|
_this.editor = void 0;
|
||||||
|
|
||||||
_this.editor = {
|
_this.init = function (isReset) {
|
||||||
on: function on() {},
|
if (isReset === void 0) {
|
||||||
off: function off() {},
|
isReset = false;
|
||||||
config: props.config,
|
}
|
||||||
pluginComponents: props.pluginComponents
|
|
||||||
|
if (_this.editor) {
|
||||||
|
_this.editor.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
var _this$props = _this.props,
|
||||||
|
utils = _this$props.utils,
|
||||||
|
config = _this$props.config,
|
||||||
|
components = _this$props.components;
|
||||||
|
var editor = new Editor(comboEditorConfig(defaultConfig, config), components, _extends({}, skeletonUtils, {}, utils));
|
||||||
|
_this.editor = editor; // eslint-disable-next-line no-underscore-dangle
|
||||||
|
|
||||||
|
window.__ctx = {
|
||||||
|
editor: editor,
|
||||||
|
appHelper: editor
|
||||||
|
};
|
||||||
|
editor.once('editor.reset', function () {
|
||||||
|
_this.setState({
|
||||||
|
initReady: false
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.emit('editor.beforeReset');
|
||||||
|
|
||||||
|
_this.init(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
_this.editor.init().then(function () {
|
||||||
|
_this.setState({
|
||||||
|
initReady: true,
|
||||||
|
// 刷新IDE时生成新的skeletonKey保证插件生命周期重新执行
|
||||||
|
skeletonKey: isReset ? "skeleton" + ++renderIdx : _this.state.skeletonKey
|
||||||
|
}, function () {
|
||||||
|
editor.emit('editor.ready');
|
||||||
|
editor.emit('ide.ready');
|
||||||
|
isReset && editor.emit('ide.afterReset');
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_this.state = {
|
||||||
|
initReady: false,
|
||||||
|
skeletonKey: "skeleton" + renderIdx
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.init();
|
||||||
|
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _proto = Skeleton.prototype;
|
var _proto = Skeleton.prototype;
|
||||||
|
|
||||||
_proto.componentWillUnmount = function componentWillUnmount() {// this.editor && this.editor.destroy();
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
// this.editor = null;
|
this.editor && this.editor.destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.componentDidCatch = function componentDidCatch(err) {
|
||||||
|
console.error(err);
|
||||||
};
|
};
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.render = function render() {
|
||||||
var _this$props = this.props,
|
var _this$state = this.state,
|
||||||
location = _this$props.location,
|
initReady = _this$state.initReady,
|
||||||
history = _this$props.history,
|
skeletonKey = _this$state.skeletonKey,
|
||||||
messages = _this$props.messages;
|
__hasError = _this$state.__hasError;
|
||||||
this.editor.location = location;
|
var _this$props2 = this.props,
|
||||||
this.editor.history = history;
|
location = _this$props2.location,
|
||||||
this.editor.messages = messages;
|
history = _this$props2.history,
|
||||||
|
match = _this$props2.match;
|
||||||
|
|
||||||
|
if (__hasError || !this.editor) {
|
||||||
|
return 'error';
|
||||||
|
}
|
||||||
|
|
||||||
|
location.query = parseSearch(location.search);
|
||||||
|
this.editor.set('location', location);
|
||||||
|
this.editor.set('history', history);
|
||||||
|
this.editor.set('match', match);
|
||||||
return React.createElement(_ConfigProvider, null, React.createElement(_Loading, {
|
return React.createElement(_ConfigProvider, null, React.createElement(_Loading, {
|
||||||
tip: "Loading",
|
tip: "Loading",
|
||||||
size: "large",
|
size: "large",
|
||||||
visible: false,
|
visible: !initReady,
|
||||||
shape: "fusion-reactor",
|
|
||||||
fullScreen: true
|
fullScreen: true
|
||||||
}, React.createElement("div", {
|
}, React.createElement("div", {
|
||||||
className: "lowcode-editor"
|
className: "lowcode-editor",
|
||||||
|
key: skeletonKey
|
||||||
}, React.createElement(TopArea, {
|
}, React.createElement(TopArea, {
|
||||||
editor: this.editor
|
editor: this.editor
|
||||||
}), React.createElement("div", {
|
}), React.createElement("div", {
|
||||||
@ -64,7 +136,23 @@ var Skeleton = /*#__PURE__*/function (_PureComponent) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return Skeleton;
|
return Skeleton;
|
||||||
}(PureComponent);
|
}(PureComponent); // 通过React-Router包裹,支持编辑器内页面根据路由切换
|
||||||
|
|
||||||
Skeleton.displayName = 'lowcodeEditorSkeleton';
|
Skeleton.displayName = 'LowcodeEditorSkeleton';
|
||||||
export { Skeleton as default };
|
;
|
||||||
|
|
||||||
|
var SkeletonWithRouter = function SkeletonWithRouter(props) {
|
||||||
|
var config = props.config,
|
||||||
|
otherProps = _objectWithoutPropertiesLoose(props, ["config"]);
|
||||||
|
|
||||||
|
return React.createElement(Router, null, React.createElement(Route, {
|
||||||
|
path: "/*",
|
||||||
|
component: function component(routerProps) {
|
||||||
|
return React.createElement(Skeleton, _extends({}, routerProps, otherProps, config.skeleton && config.skeleton.props, {
|
||||||
|
config: config
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SkeletonWithRouter;
|
||||||
@ -1,7 +1,16 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class CenterArea extends PureComponent {
|
export interface CenterAreaProps {
|
||||||
static displayName: string;
|
editor: Editor;
|
||||||
constructor(props: any);
|
}
|
||||||
render(): JSX.Element;
|
export default class CenterArea extends PureComponent<CenterAreaProps> {
|
||||||
|
static displayName: string;
|
||||||
|
private editor;
|
||||||
|
private areaManager;
|
||||||
|
constructor(props: any);
|
||||||
|
componentDidMount(): void;
|
||||||
|
componentWillUnmount(): void;
|
||||||
|
handleSkeletonUpdate: () => void;
|
||||||
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,64 @@
|
|||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import { AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
var CenterArea = /*#__PURE__*/function (_PureComponent) {
|
var CenterArea = /*#__PURE__*/function (_PureComponent) {
|
||||||
_inheritsLoose(CenterArea, _PureComponent);
|
_inheritsLoose(CenterArea, _PureComponent);
|
||||||
|
|
||||||
function CenterArea(props) {
|
function CenterArea(props) {
|
||||||
return _PureComponent.call(this, props) || this;
|
var _this;
|
||||||
|
|
||||||
|
_this = _PureComponent.call(this, props) || this;
|
||||||
|
_this.editor = void 0;
|
||||||
|
_this.areaManager = void 0;
|
||||||
|
|
||||||
|
_this.handleSkeletonUpdate = function () {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (_this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
_this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.editor = props.editor;
|
||||||
|
_this.areaManager = new AreaManager(_this.editor, 'centerArea');
|
||||||
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _proto = CenterArea.prototype;
|
var _proto = CenterArea.prototype;
|
||||||
|
|
||||||
|
_proto.componentDidMount = function componentDidMount() {
|
||||||
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
};
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.render = function render() {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
var visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
return React.createElement("div", {
|
return React.createElement("div", {
|
||||||
className: "lowcode-center-area"
|
className: "lowcode-center-area"
|
||||||
});
|
}, visiblePluginList.map(function (item) {
|
||||||
|
var Comp = _this2.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
|
||||||
|
if (Comp) {
|
||||||
|
return React.createElement(Comp, _extends({
|
||||||
|
key: item.pluginKey,
|
||||||
|
editor: _this2.editor,
|
||||||
|
config: item
|
||||||
|
}, item.pluginProps));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
return CenterArea;
|
return CenterArea;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
CenterArea.displayName = 'lowcodeCenterArea';
|
CenterArea.displayName = 'LowcodeCenterArea';
|
||||||
export { CenterArea as default };
|
export { CenterArea as default };
|
||||||
@ -1,3 +1,3 @@
|
|||||||
.lowcode-center-area {
|
.lowcode-center-area {
|
||||||
padding: 12px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,23 @@
|
|||||||
.lowcode-left-area-nav {
|
.lowcode-left-area-nav {
|
||||||
width: 48px;
|
width: 50px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: #ffffff;
|
background-color: $card-background;
|
||||||
border-right: 1px solid #e8ebee;
|
border-right: 2px solid $color-line1-1;
|
||||||
position: relative;
|
position: relative;
|
||||||
.top-area {
|
.top-area {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #ffffff;
|
padding: 12px 0;
|
||||||
|
background-color: $card-background;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
.bottom-area {
|
.bottom-area {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 20px;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #ffffff;
|
padding: 12px 0;
|
||||||
|
background-color: $card-background;
|
||||||
max-height: calc(100% - 20px);
|
max-height: calc(100% - 20px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,24 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class LeftAreaPanel extends PureComponent {
|
export interface LeftAreaNavProps {
|
||||||
static displayName: string;
|
editor: Editor;
|
||||||
constructor(props: any);
|
}
|
||||||
render(): JSX.Element;
|
export interface LeftAreaNavState {
|
||||||
|
activeKey: string;
|
||||||
|
}
|
||||||
|
export default class LeftAreaNav extends PureComponent<LeftAreaNavProps, LeftAreaNavState> {
|
||||||
|
static displayName: string;
|
||||||
|
private editor;
|
||||||
|
private areaManager;
|
||||||
|
constructor(props: any);
|
||||||
|
componentDidMount(): void;
|
||||||
|
componentWillUnmount(): void;
|
||||||
|
handleSkeletonUpdate: () => void;
|
||||||
|
handlePluginChange: (key: string) => void;
|
||||||
|
handlePluginClick: (item: PluginConfig) => void;
|
||||||
|
updateActiveKey: (key: string) => void;
|
||||||
|
renderPluginList: (list?: PluginConfig[]) => any[];
|
||||||
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,150 @@
|
|||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import LeftPlugin from '../../components/LeftPlugin';
|
||||||
|
import { utils, AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
var isEmpty = utils.isEmpty;
|
||||||
|
|
||||||
var LeftAreaPanel = /*#__PURE__*/function (_PureComponent) {
|
var LeftAreaNav = /*#__PURE__*/function (_PureComponent) {
|
||||||
_inheritsLoose(LeftAreaPanel, _PureComponent);
|
_inheritsLoose(LeftAreaNav, _PureComponent);
|
||||||
|
|
||||||
function LeftAreaPanel(props) {
|
function LeftAreaNav(props) {
|
||||||
return _PureComponent.call(this, props) || this;
|
var _this;
|
||||||
|
|
||||||
|
_this = _PureComponent.call(this, props) || this;
|
||||||
|
_this.editor = void 0;
|
||||||
|
_this.areaManager = void 0;
|
||||||
|
|
||||||
|
_this.handleSkeletonUpdate = function () {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (_this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
_this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.handlePluginChange = function (key) {
|
||||||
|
var activeKey = _this.state.activeKey;
|
||||||
|
var plugins = _this.editor.plugins;
|
||||||
|
var prePlugin = plugins[activeKey];
|
||||||
|
var nextPlugin = plugins[key];
|
||||||
|
|
||||||
|
if (activeKey === 'none') {
|
||||||
|
if (nextPlugin) {
|
||||||
|
nextPlugin.open().then(function () {
|
||||||
|
_this.updateActiveKey(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (activeKey === key) {
|
||||||
|
if (prePlugin) {
|
||||||
|
prePlugin.close().then(function () {
|
||||||
|
_this.updateActiveKey('none');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (prePlugin) {
|
||||||
|
// 先关后开
|
||||||
|
prePlugin.close().then(function () {
|
||||||
|
if (nextPlugin) {
|
||||||
|
nextPlugin.open().then(function () {
|
||||||
|
_this.updateActiveKey(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.handlePluginClick = function (item) {
|
||||||
|
if (item.type === 'PanelIcon') {
|
||||||
|
_this.handlePluginChange(item.pluginKey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.updateActiveKey = function (key) {
|
||||||
|
_this.editor.set('leftNav', key);
|
||||||
|
|
||||||
|
_this.setState({
|
||||||
|
activeKey: key
|
||||||
|
});
|
||||||
|
|
||||||
|
_this.editor.emit('leftPanel.show', key);
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.renderPluginList = function (list) {
|
||||||
|
if (list === void 0) {
|
||||||
|
list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeKey = _this.state.activeKey;
|
||||||
|
return list.map(function (item) {
|
||||||
|
var pluginStatus = _this.areaManager.getPluginStatus(item.pluginKey);
|
||||||
|
|
||||||
|
var pluginClass = _this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
|
||||||
|
return React.createElement(LeftPlugin, _extends({
|
||||||
|
key: item.pluginKey,
|
||||||
|
config: item,
|
||||||
|
editor: _this.editor,
|
||||||
|
pluginClass: pluginClass,
|
||||||
|
onClick: function onClick() {
|
||||||
|
return _this.handlePluginClick(item);
|
||||||
|
},
|
||||||
|
active: activeKey === item.pluginKey
|
||||||
|
}, pluginStatus));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.editor = props.editor;
|
||||||
|
_this.areaManager = new AreaManager(_this.editor, 'leftArea');
|
||||||
|
_this.state = {
|
||||||
|
activeKey: 'none'
|
||||||
|
};
|
||||||
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _proto = LeftAreaPanel.prototype;
|
var _proto = LeftAreaNav.prototype;
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.componentDidMount = function componentDidMount() {
|
||||||
return React.createElement("div", {
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
className: "lowcode-left-area-nav"
|
this.editor.on('leftNav.change', this.handlePluginChange);
|
||||||
});
|
var visiblePanelPluginList = this.areaManager.getVisiblePluginList('IconPanel');
|
||||||
|
var defaultKey = visiblePanelPluginList[0] && visiblePanelPluginList[0].pluginKey || 'componentAttr';
|
||||||
|
this.handlePluginChange(defaultKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
return LeftAreaPanel;
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.off('leftNav.change', this.handlePluginChange);
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.render = function render() {
|
||||||
|
var topList = [];
|
||||||
|
var bottomList = [];
|
||||||
|
var visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
|
|
||||||
|
if (isEmpty(visiblePluginList)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
visiblePluginList.forEach(function (item) {
|
||||||
|
var align = item.props && item.props.align === 'bottom' ? 'bottom' : 'top';
|
||||||
|
|
||||||
|
if (align === 'bottom') {
|
||||||
|
bottomList.push(item);
|
||||||
|
} else {
|
||||||
|
topList.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return React.createElement("div", {
|
||||||
|
className: "lowcode-left-area-nav"
|
||||||
|
}, React.createElement("div", {
|
||||||
|
className: "bottom-area"
|
||||||
|
}, this.renderPluginList(bottomList)), React.createElement("div", {
|
||||||
|
className: "top-area"
|
||||||
|
}, this.renderPluginList(topList)));
|
||||||
|
};
|
||||||
|
|
||||||
|
return LeftAreaNav;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
LeftAreaPanel.displayName = 'lowcodeLeftAreaNav';
|
LeftAreaNav.displayName = 'LowcodeLeftAreaNav';
|
||||||
export { LeftAreaPanel as default };
|
export { LeftAreaNav as default };
|
||||||
@ -1,7 +1,20 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class LeftAreaPanel extends PureComponent {
|
export interface LeftAreaPanelProps {
|
||||||
static displayName: string;
|
editor: Editor;
|
||||||
constructor(props: any);
|
}
|
||||||
render(): JSX.Element;
|
export interface LeftAreaPanelState {
|
||||||
|
activeKey: string;
|
||||||
|
}
|
||||||
|
export default class LeftAreaPanel extends PureComponent<LeftAreaPanelProps, LeftAreaPanelState> {
|
||||||
|
static displayName: string;
|
||||||
|
private editor;
|
||||||
|
private areaManager;
|
||||||
|
constructor(props: any);
|
||||||
|
componentDidMount(): void;
|
||||||
|
componentWillUnmount(): void;
|
||||||
|
handleSkeletonUpdate: () => void;
|
||||||
|
handlePluginChange: (key: string) => void;
|
||||||
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,77 @@
|
|||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent, Fragment } from 'react';
|
||||||
|
import { AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
|
import Panel from '../../components/Panel';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
var LeftAreaPanel = /*#__PURE__*/function (_PureComponent) {
|
var LeftAreaPanel = /*#__PURE__*/function (_PureComponent) {
|
||||||
_inheritsLoose(LeftAreaPanel, _PureComponent);
|
_inheritsLoose(LeftAreaPanel, _PureComponent);
|
||||||
|
|
||||||
function LeftAreaPanel(props) {
|
function LeftAreaPanel(props) {
|
||||||
return _PureComponent.call(this, props) || this;
|
var _this;
|
||||||
|
|
||||||
|
_this = _PureComponent.call(this, props) || this;
|
||||||
|
_this.editor = void 0;
|
||||||
|
_this.areaManager = void 0;
|
||||||
|
|
||||||
|
_this.handleSkeletonUpdate = function () {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (_this.areaManager.isPluginStatusUpdate('PanelIcon')) {
|
||||||
|
_this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.handlePluginChange = function (key) {
|
||||||
|
_this.setState({
|
||||||
|
activeKey: key
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.editor = props.editor;
|
||||||
|
_this.areaManager = new AreaManager(_this.editor, 'leftArea');
|
||||||
|
_this.state = {
|
||||||
|
activeKey: 'none'
|
||||||
|
};
|
||||||
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _proto = LeftAreaPanel.prototype;
|
var _proto = LeftAreaPanel.prototype;
|
||||||
|
|
||||||
|
_proto.componentDidMount = function componentDidMount() {
|
||||||
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.on('leftPanel.show', this.handlePluginChange);
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.off('leftPanel.show', this.handlePluginChange);
|
||||||
|
};
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.render = function render() {
|
||||||
return React.createElement("div", {
|
var _this2 = this;
|
||||||
className: "lowcode-left-area-panel"
|
|
||||||
});
|
var activeKey = this.state.activeKey;
|
||||||
|
var list = this.areaManager.getVisiblePluginList('PanelIcon');
|
||||||
|
return React.createElement(Fragment, null, list.map(function (item) {
|
||||||
|
var Comp = _this2.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
|
||||||
|
if (Comp) {
|
||||||
|
return React.createElement(Panel, _extends({
|
||||||
|
key: item.pluginKey,
|
||||||
|
visible: item.pluginKey === activeKey
|
||||||
|
}, item.props && item.props.panelProps), React.createElement(Comp, _extends({
|
||||||
|
editor: _this2.editor,
|
||||||
|
config: item
|
||||||
|
}, item.pluginProps)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
return LeftAreaPanel;
|
return LeftAreaPanel;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
LeftAreaPanel.displayName = 'lowcodeLeftAreaPanel';
|
LeftAreaPanel.displayName = 'LowcodeLeftAreaPanel';
|
||||||
export { LeftAreaPanel as default };
|
export { LeftAreaPanel as default };
|
||||||
@ -1,7 +1,24 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class RightArea extends PureComponent {
|
export interface RightAreaProps {
|
||||||
static displayName: string;
|
editor: Editor;
|
||||||
constructor(props: any);
|
}
|
||||||
render(): JSX.Element;
|
export interface RightAreaState {
|
||||||
|
activeKey: string;
|
||||||
|
}
|
||||||
|
export default class RightArea extends PureComponent<RightAreaProps, RightAreaState> {
|
||||||
|
static displayName: string;
|
||||||
|
private editor;
|
||||||
|
private areaManager;
|
||||||
|
constructor(props: any);
|
||||||
|
componentDidMount(): void;
|
||||||
|
componentWillUnmount(): void;
|
||||||
|
handleSkeletonUpdate: () => void;
|
||||||
|
handlePluginChange: (key: string, isinit?: boolean) => void;
|
||||||
|
renderTabTitle: (config: PluginConfig) => any;
|
||||||
|
renderTabPanels: (list: PluginConfig[], height: string) => any;
|
||||||
|
renderPanels: (list: PluginConfig[], height: string) => any;
|
||||||
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,218 @@
|
|||||||
|
import _Tab from "@alifd/next/es/tab";
|
||||||
|
import _extends from "@babel/runtime/helpers/extends";
|
||||||
|
import _Badge from "@alifd/next/es/badge";
|
||||||
|
import _Icon from "@alifd/next/es/icon";
|
||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { AreaManager, utils } from '@ali/lowcode-editor-framework';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
var isEmpty = utils.isEmpty;
|
||||||
|
|
||||||
var RightArea = /*#__PURE__*/function (_PureComponent) {
|
var RightArea = /*#__PURE__*/function (_PureComponent) {
|
||||||
_inheritsLoose(RightArea, _PureComponent);
|
_inheritsLoose(RightArea, _PureComponent);
|
||||||
|
|
||||||
function RightArea(props) {
|
function RightArea(props) {
|
||||||
return _PureComponent.call(this, props) || this;
|
var _this;
|
||||||
|
|
||||||
|
_this = _PureComponent.call(this, props) || this;
|
||||||
|
_this.editor = void 0;
|
||||||
|
_this.areaManager = void 0;
|
||||||
|
|
||||||
|
_this.handleSkeletonUpdate = function () {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (_this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
var activeKey = _this.state.activeKey;
|
||||||
|
|
||||||
|
var activePluginStatus = _this.areaManager.getPluginStatus(activeKey);
|
||||||
|
|
||||||
|
if (activePluginStatus && activePluginStatus.visible) {
|
||||||
|
_this.forceUpdate();
|
||||||
|
} else {
|
||||||
|
var currentPlugin = _this.areaManager.getPlugin(activeKey);
|
||||||
|
|
||||||
|
if (currentPlugin) {
|
||||||
|
currentPlugin.close().then(function () {
|
||||||
|
_this.setState({
|
||||||
|
activeKey: ''
|
||||||
|
}, function () {
|
||||||
|
var visiblePluginList = _this.areaManager.getVisiblePluginList('TabPanel');
|
||||||
|
|
||||||
|
var firstPlugin = visiblePluginList && visiblePluginList[0];
|
||||||
|
|
||||||
|
if (firstPlugin) {
|
||||||
|
_this.handlePluginChange(firstPlugin.pluginKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.handlePluginChange = function (key, isinit) {
|
||||||
|
var activeKey = _this.state.activeKey;
|
||||||
|
|
||||||
|
var currentPlugin = _this.areaManager.getPlugin(activeKey);
|
||||||
|
|
||||||
|
var nextPlugin = _this.areaManager.getPlugin(key);
|
||||||
|
|
||||||
|
var openPlugin = function openPlugin() {
|
||||||
|
if (!nextPlugin) {
|
||||||
|
console.error("plugin " + key + " has not regist in the editor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextPlugin.open().then(function () {
|
||||||
|
_this.editor.set('rightNav', key);
|
||||||
|
|
||||||
|
_this.setState({
|
||||||
|
activeKey: key
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (key === activeKey && !isinit) return;
|
||||||
|
|
||||||
|
if (currentPlugin) {
|
||||||
|
currentPlugin.close().then(function () {
|
||||||
|
openPlugin();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
openPlugin();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.renderTabTitle = function (config) {
|
||||||
|
var _ref = config.props || {},
|
||||||
|
icon = _ref.icon,
|
||||||
|
title = _ref.title;
|
||||||
|
|
||||||
|
var pluginStatus = _this.editor.pluginStatus[config.pluginKey];
|
||||||
|
var marked = pluginStatus.marked,
|
||||||
|
disabled = pluginStatus.disabled,
|
||||||
|
locked = pluginStatus.locked;
|
||||||
|
var active = _this.state.activeKey === config.pluginKey;
|
||||||
|
|
||||||
|
var renderTitle = function renderTitle() {
|
||||||
|
return React.createElement("div", {
|
||||||
|
className: classNames('right-plugin-title', {
|
||||||
|
active: active,
|
||||||
|
locked: locked,
|
||||||
|
disabled: disabled
|
||||||
|
})
|
||||||
|
}, !!icon && React.createElement(_Icon, {
|
||||||
|
size: "xs",
|
||||||
|
type: icon
|
||||||
|
}), title);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (marked) {
|
||||||
|
return React.createElement(_Badge, {
|
||||||
|
dot: true
|
||||||
|
}, renderTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderTitle();
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.renderTabPanels = function (list, height) {
|
||||||
|
if (isEmpty(list)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return React.createElement(_Tab, {
|
||||||
|
className: "right-tabs",
|
||||||
|
style: {
|
||||||
|
height: height
|
||||||
|
},
|
||||||
|
activeKey: _this.state.activeKey,
|
||||||
|
lazyLoad: false,
|
||||||
|
onChange: _this.handlePluginChange
|
||||||
|
}, list.map(function (item) {
|
||||||
|
var Comp = _this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
|
||||||
|
if (Comp) {
|
||||||
|
return React.createElement(_Tab.Item, {
|
||||||
|
key: item.pluginKey,
|
||||||
|
title: _this.renderTabTitle(item),
|
||||||
|
disabled: _this.editor.pluginStatus[item.pluginKey].disabled,
|
||||||
|
style: {
|
||||||
|
width: 100 / list.length + "%"
|
||||||
|
}
|
||||||
|
}, React.createElement(Comp, _extends({
|
||||||
|
editor: _this.editor,
|
||||||
|
config: item
|
||||||
|
}, item.pluginProps)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.renderPanels = function (list, height) {
|
||||||
|
return list.map(function (item) {
|
||||||
|
var Comp = _this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
|
||||||
|
if (Comp) {
|
||||||
|
return React.createElement("div", {
|
||||||
|
className: "right-panel",
|
||||||
|
style: {
|
||||||
|
height: height
|
||||||
|
},
|
||||||
|
key: item.pluginKey
|
||||||
|
}, React.createElement(Comp, _extends({
|
||||||
|
editor: _this.editor,
|
||||||
|
config: item
|
||||||
|
}, item.pluginProps)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_this.editor = props.editor;
|
||||||
|
_this.areaManager = new AreaManager(_this.editor, 'rightArea');
|
||||||
|
_this.state = {
|
||||||
|
activeKey: ''
|
||||||
|
};
|
||||||
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _proto = RightArea.prototype;
|
var _proto = RightArea.prototype;
|
||||||
|
|
||||||
|
_proto.componentDidMount = function componentDidMount() {
|
||||||
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.on('rightNav.change', this.handlePluginChange);
|
||||||
|
var visiblePluginList = this.areaManager.getVisiblePluginList('TabPanel');
|
||||||
|
var defaultKey = visiblePluginList[0] && visiblePluginList[0].pluginKey || 'componentAttr';
|
||||||
|
this.handlePluginChange(defaultKey, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.off('rightNav.change', this.handlePluginChange);
|
||||||
|
};
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.render = function render() {
|
||||||
|
var tabList = this.areaManager.getVisiblePluginList('TabPanel');
|
||||||
|
var 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
var height = Math.floor(100 / (panelList.length + (tabList.length > 0 ? 1 : 0))) + "%";
|
||||||
return React.createElement("div", {
|
return React.createElement("div", {
|
||||||
className: "lowcode-right-area"
|
className: "lowcode-right-area"
|
||||||
});
|
}, this.renderTabPanels(tabList, height), this.renderPanels(panelList, height));
|
||||||
};
|
};
|
||||||
|
|
||||||
return RightArea;
|
return RightArea;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
RightArea.displayName = 'lowcodeRightArea';
|
RightArea.displayName = 'LowcodeRightArea';
|
||||||
export { RightArea as default };
|
export { RightArea as default };
|
||||||
@ -1,155 +1,37 @@
|
|||||||
.lowcode-right-area {
|
.lowcode-right-area {
|
||||||
width: 300px;
|
width: 262px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #ffffff;
|
background-color: $card-background;
|
||||||
border-left: 1px solid #e8ebee;
|
border-left: 2px solid $color-line1-1;
|
||||||
.right-plugin-title {
|
|
||||||
&.locked {
|
.right-panel {
|
||||||
color: red !important;
|
overflow: auto;
|
||||||
}
|
// border-top: 2px solid $color-line1-1;
|
||||||
&.active {
|
|
||||||
color: $color-brand1-9 !important;
|
|
||||||
}
|
|
||||||
&.disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
color: $color-text1-1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//tab定义
|
//tab定义
|
||||||
.next-tabs-wrapped.right-tabs {
|
.right-tabs.next-tabs {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-top: -1px;
|
|
||||||
.next-tabs-bar {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.next-tabs-nav {
|
.next-tabs-nav {
|
||||||
display: block;
|
width: 100%;
|
||||||
.next-tabs-tab {
|
.next-tabs-tab-inner {
|
||||||
&:first-child {
|
padding-left: 0;
|
||||||
border-left: none;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
font-size: 14px;
|
.right-plugin-title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-right: none !important;
|
&.locked {
|
||||||
margin-right: 0 !important;
|
color: red !important;
|
||||||
width: 25%;
|
}
|
||||||
&.active {
|
&.active {
|
||||||
background: none;
|
color: $color-brand1-9 !important;
|
||||||
border-bottom-color: #f7f7f7 !important;
|
|
||||||
}
|
}
|
||||||
}
|
&.disabled {
|
||||||
}
|
cursor: not-allowed;
|
||||||
}
|
color: $color-text1-1;
|
||||||
.next-tabs-content {
|
|
||||||
flex: 1;
|
|
||||||
.next-tabs-tabpane.active {
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//组件
|
|
||||||
.select-comp {
|
|
||||||
padding: 10px 16px;
|
|
||||||
line-height: 16px;
|
|
||||||
color: #989a9c;
|
|
||||||
& > span {
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 16px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
& > .btn-wrap,
|
|
||||||
& > .next-btn {
|
|
||||||
width: auto;
|
|
||||||
margin: 0 5px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.unselected {
|
|
||||||
padding: 60px 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
//右侧属性面板样式调整;
|
|
||||||
.offset-56 {
|
|
||||||
padding-left: 56px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.fixedSpan.next-form-item {
|
|
||||||
& > .next-form-item-label {
|
|
||||||
width: 56px;
|
|
||||||
flex: none;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
& > .next-form-item-control {
|
|
||||||
padding-right: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fixedSpan.next-form-item,
|
|
||||||
.offset-56 .next-form-item {
|
|
||||||
display: flex;
|
|
||||||
& > .next-form-item-control {
|
|
||||||
width: auto;
|
|
||||||
flex: 1;
|
|
||||||
max-width: none;
|
|
||||||
.next-input,
|
|
||||||
.next-select,
|
|
||||||
.next-radio-group,
|
|
||||||
.next-number-picker,
|
|
||||||
.luna-reactnode-btn,
|
|
||||||
.luna-monaco-button button,
|
|
||||||
.luna-object-button button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.next-number-picker {
|
|
||||||
width: 100%;
|
|
||||||
.next-after {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
}
|
||||||
}
|
.next-icon {
|
||||||
.next-radio-group {
|
line-height: 15px;
|
||||||
display: flex;
|
margin-right: 2px;
|
||||||
label {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.topSpan.next-form-item {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
& > .next-form-item-control {
|
|
||||||
padding-right: 24px;
|
|
||||||
.next-input,
|
|
||||||
.next-select,
|
|
||||||
.next-radio-group,
|
|
||||||
.next-number-picker,
|
|
||||||
.luna-reactnode-btn,
|
|
||||||
.luna-monaco-button button,
|
|
||||||
.luna-object-button button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.next-number-picker {
|
|
||||||
width: 100%;
|
|
||||||
.next-after {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.next-radio-group {
|
|
||||||
display: flex;
|
|
||||||
label {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
import { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class TopArea extends PureComponent {
|
export interface TopAreaProps {
|
||||||
|
editor: Editor;
|
||||||
|
}
|
||||||
|
export default class TopArea extends PureComponent<TopAreaProps> {
|
||||||
static displayName: string;
|
static displayName: string;
|
||||||
|
private areaManager;
|
||||||
|
private editor;
|
||||||
constructor(props: any);
|
constructor(props: any);
|
||||||
componentDidMount(): void;
|
componentDidMount(): void;
|
||||||
componentWillUnmount(): void;
|
componentWillUnmount(): void;
|
||||||
handlePluginStatusChange: () => void;
|
handleSkeletonUpdate: () => void;
|
||||||
renderPluginList: (list?: any[]) => JSX.Element[];
|
renderPluginList: (list?: PluginConfig[]) => any[];
|
||||||
render(): JSX.Element;
|
render(): React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
|
||||||
import _Grid from "@alifd/next/es/grid";
|
import _Grid from "@alifd/next/es/grid";
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import { AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
import TopPlugin from '../../components/TopPlugin';
|
import TopPlugin from '../../components/TopPlugin';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
var Row = _Grid.Row,
|
var Row = _Grid.Row,
|
||||||
@ -13,8 +14,15 @@ var TopArea = /*#__PURE__*/function (_PureComponent) {
|
|||||||
var _this;
|
var _this;
|
||||||
|
|
||||||
_this = _PureComponent.call(this, props) || this;
|
_this = _PureComponent.call(this, props) || this;
|
||||||
|
_this.areaManager = void 0;
|
||||||
|
_this.editor = void 0;
|
||||||
|
|
||||||
_this.handlePluginStatusChange = function () {};
|
_this.handleSkeletonUpdate = function () {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (_this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
_this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
_this.renderPluginList = function (list) {
|
_this.renderPluginList = function (list) {
|
||||||
if (list === void 0) {
|
if (list === void 0) {
|
||||||
@ -23,41 +31,48 @@ var TopArea = /*#__PURE__*/function (_PureComponent) {
|
|||||||
|
|
||||||
return list.map(function (item, idx) {
|
return list.map(function (item, idx) {
|
||||||
var isDivider = item.type === 'Divider';
|
var isDivider = item.type === 'Divider';
|
||||||
|
|
||||||
|
var PluginClass = _this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
|
||||||
return React.createElement(Col, {
|
return React.createElement(Col, {
|
||||||
className: isDivider ? 'divider' : '',
|
className: isDivider ? 'divider' : '',
|
||||||
key: isDivider ? idx : item.pluginKey,
|
key: isDivider ? idx : item.pluginKey,
|
||||||
style: {
|
style: {
|
||||||
width: item.props && item.props.width || 40,
|
width: item.props && item.props.width || 36,
|
||||||
flex: 'none'
|
flex: 'none'
|
||||||
}
|
}
|
||||||
}, !isDivider && React.createElement(TopPlugin, {
|
}, !isDivider && React.createElement(TopPlugin, {
|
||||||
config: item,
|
config: item,
|
||||||
pluginClass: _this.editor.pluginComponents[item.pluginKey],
|
pluginClass: PluginClass,
|
||||||
status: _this.editor.pluginStatus[item.pluginKey]
|
editor: _this.editor
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_this.editor = props.editor;
|
_this.editor = props.editor;
|
||||||
_this.config = _this.editor.config.plugins && _this.editor.config.plugins.topArea;
|
_this.areaManager = new AreaManager(props.editor, 'topArea');
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var _proto = TopArea.prototype;
|
var _proto = TopArea.prototype;
|
||||||
|
|
||||||
_proto.componentDidMount = function componentDidMount() {};
|
_proto.componentDidMount = function componentDidMount() {
|
||||||
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
};
|
||||||
|
|
||||||
_proto.componentWillUnmount = function componentWillUnmount() {};
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
};
|
||||||
|
|
||||||
_proto.render = function render() {
|
_proto.render = function render() {
|
||||||
if (!this.config) return null;
|
|
||||||
var leftList = [];
|
var leftList = [];
|
||||||
var rightList = [];
|
var rightList = [];
|
||||||
this.config.forEach(function (item) {
|
var visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
|
visiblePluginList.forEach(function (item) {
|
||||||
var align = item.props && item.props.align === 'right' ? 'right' : 'left'; // 分隔符不允许相邻
|
var align = item.props && item.props.align === 'right' ? 'right' : 'left'; // 分隔符不允许相邻
|
||||||
|
|
||||||
if (item.type === 'Divider') {
|
if (item.type === 'Divider') {
|
||||||
var currentList = align === 'right' ? rightList : leftList;
|
var currList = align === 'right' ? rightList : leftList;
|
||||||
if (currList.length === 0 || currList[currList.length - 1].type === 'Divider') return;
|
if (currList.length === 0 || currList[currList.length - 1].type === 'Divider') return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,13 +86,15 @@ var TopArea = /*#__PURE__*/function (_PureComponent) {
|
|||||||
className: "lowcode-top-area"
|
className: "lowcode-top-area"
|
||||||
}, React.createElement("div", {
|
}, React.createElement("div", {
|
||||||
className: "left-area"
|
className: "left-area"
|
||||||
}, this.renderPluginList(leftList)), React.createElement("div", {
|
}, React.createElement(Row, null, this.renderPluginList(leftList))), React.createElement("div", {
|
||||||
classname: "right-area"
|
className: "right-area"
|
||||||
}, this.renderPluginList(rightList)));
|
}, React.createElement(Row, {
|
||||||
|
justify: "end"
|
||||||
|
}, this.renderPluginList(rightList))));
|
||||||
};
|
};
|
||||||
|
|
||||||
return TopArea;
|
return TopArea;
|
||||||
}(PureComponent);
|
}(PureComponent);
|
||||||
|
|
||||||
TopArea.displayName = 'lowcodeTopArea';
|
TopArea.displayName = 'LowcodeTopArea';
|
||||||
export { TopArea as default };
|
export { TopArea as default };
|
||||||
@ -1,5 +1,30 @@
|
|||||||
.lowcode-top-area {
|
.lowcode-top-area {
|
||||||
height: 48px;
|
position: absolute;
|
||||||
background-color: #ffffff;
|
top: 0;
|
||||||
border-bottom: 1px solid #e8ebee;
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background-color: $card-background;
|
||||||
|
border-bottom: 2px solid $color-line1-1;
|
||||||
|
user-select: none;
|
||||||
|
.divider {
|
||||||
|
max-width: 0;
|
||||||
|
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: 0;
|
||||||
|
top: 0;
|
||||||
|
padding: 0 16px;
|
||||||
|
height: 100%;
|
||||||
|
background: $card-background;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1 @@
|
|||||||
export default {
|
export default {};
|
||||||
loading: 'loading...',
|
|
||||||
rejectRedirect: 'Redirect is not allowed',
|
|
||||||
expand: 'Unfold',
|
|
||||||
fold: 'Fold',
|
|
||||||
pageNotExist: 'The current Page not exist',
|
|
||||||
enterFromAppCenter: 'Please enter from the app center',
|
|
||||||
noPermission: 'Sorry, you do not have the develop permission',
|
|
||||||
getPermission: 'Please connect the app owners {owners} to get the permission'
|
|
||||||
};
|
|
||||||
@ -1,10 +1 @@
|
|||||||
export default {
|
export default {};
|
||||||
loading: '加载中...',
|
|
||||||
rejectRedirect: '开发中,已阻止发生跳转',
|
|
||||||
expand: '展开',
|
|
||||||
fold: '收起',
|
|
||||||
pageNotExist: '当前访问地址不存在',
|
|
||||||
enterFromAppCenter: '请从应用中心入口重新进入',
|
|
||||||
noPermission: '抱歉,您暂无开发权限',
|
|
||||||
getPermission: '请移步应用中心申请开发权限, 或联系 {owners} 开通权限'
|
|
||||||
};
|
|
||||||
@ -1,8 +1,9 @@
|
|||||||
import '@alifd/next/es/config-provider/style';
|
import '@alifd/next/es/config-provider/style';
|
||||||
import '@alifd/next/es/loading/style';
|
import '@alifd/next/es/loading/style';
|
||||||
|
import '@ali/lowcode-editor-framework/es/style';
|
||||||
import '@alifd/next/es/grid/style';
|
import '@alifd/next/es/grid/style';
|
||||||
import '@alifd/next/es/balloon/style';
|
import '@alifd/next/es/balloon/style';
|
||||||
import '@alifd/next/es/dialog/style';
|
import '@alifd/next/es/dialog/style';
|
||||||
import '@alifd/next/es/badge/style';
|
import '@alifd/next/es/badge/style';
|
||||||
import '@alifd/next/es/button/style';
|
|
||||||
import '@alifd/next/es/icon/style';
|
import '@alifd/next/es/icon/style';
|
||||||
|
import '@alifd/next/es/tab/style';
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-engine-skeleton",
|
"name": "@ali/lowcode-editor-skeleton",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "alibaba lowcode editor skeleton",
|
"description": "alibaba lowcode editor skeleton",
|
||||||
"files": [
|
"files": [
|
||||||
@ -24,15 +24,13 @@
|
|||||||
],
|
],
|
||||||
"author": "xiayang.xy",
|
"author": "xiayang.xy",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-editor-framework": "0.0.1",
|
||||||
"@alifd/next": "^1.x",
|
"@alifd/next": "^1.x",
|
||||||
"@icedesign/theme": "^1.x",
|
|
||||||
"@types/react": "^16.8.3",
|
|
||||||
"@types/react-dom": "^16.8.2",
|
|
||||||
"moment": "^2.23.0",
|
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
"react": "^16.4.1",
|
"react": "^16.8.1",
|
||||||
"react-dom": "^16.4.1",
|
"react-dom": "^16.8.1",
|
||||||
"react-router-dom": "^5.0.1"
|
"react-router-dom": "^5.1.2",
|
||||||
|
"store": "^2.0.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alib/build-scripts": "^0.1.3",
|
"@alib/build-scripts": "^0.1.3",
|
||||||
|
|||||||
@ -1,59 +1,60 @@
|
|||||||
.luna-left-addon {
|
.lowcode-left-plugin {
|
||||||
font-size: 16px;
|
font-size: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 36px;
|
line-height: 44px;
|
||||||
height: 36px;
|
height: 44px;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
color: #777;
|
color: $color-text1-3;
|
||||||
&.collapse {
|
|
||||||
height: 40px;
|
|
||||||
color: #8c8c8c;
|
|
||||||
border-bottom: 1px solid #bfbfbf;
|
|
||||||
}
|
|
||||||
&.locked {
|
&.locked {
|
||||||
color: red !important;
|
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 {
|
&:hover {
|
||||||
background-color: $color-brand1-1;
|
|
||||||
color: $color-brand1-6;
|
color: $color-brand1-6;
|
||||||
&:before {
|
&:before {
|
||||||
content: attr(data-tooltip);
|
content: attr(data-tooltip);
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50px;
|
left: 45px;
|
||||||
top: 5px;
|
top: 8px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding: 6px 8px;
|
padding: 6px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: rgba(0, 0, 0, 0.75);
|
background: $balloon-normal-color-bg;
|
||||||
color: #fff;
|
border: 1px solid $balloon-normal-color-border;
|
||||||
|
opacity: 0.8;
|
||||||
|
color: $color-text1-3;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
&:after {
|
&:after {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
transform: rotate(45deg);
|
||||||
left: 40px;
|
left: 40px;
|
||||||
top: 15px;
|
top: 18px;
|
||||||
border: 5px solid transparent;
|
background: $balloon-normal-color-bg;
|
||||||
border-right-color: rgba(0, 0, 0, 0.75);
|
border-left: 1px solid $balloon-normal-color-border;
|
||||||
|
border-bottom: 1px solid $balloon-normal-color-border;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.active {
|
||||||
|
color: $color-brand1-9;
|
||||||
|
&.disabled {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
color: $color-brand1-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,79 +1,74 @@
|
|||||||
import React, { PureComponent, Fragment } from 'react';
|
import React, { PureComponent, Fragment } from 'react';
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import AppContext from '@ali/iceluna-sdk/lib/context/appContext';
|
import { Balloon, Dialog, Icon, Badge } from '@alifd/next';
|
||||||
import { Balloon, Dialog, Icon, Badge } from '@alife/next';
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import {
|
||||||
|
PluginConfig,
|
||||||
|
PluginClass,
|
||||||
|
} from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class LeftAddon extends PureComponent {
|
|
||||||
static displayName = 'LunaLeftAddon';
|
export interface LeftPluginProps {
|
||||||
static propTypes = {
|
active?: boolean;
|
||||||
active: PropTypes.bool,
|
config: PluginConfig;
|
||||||
config: PropTypes.shape({
|
disabled?: boolean;
|
||||||
addonKey: PropTypes.string,
|
editor: Editor;
|
||||||
addonProps: PropTypes.object,
|
locked?: boolean;
|
||||||
props: PropTypes.object,
|
marked?: boolean;
|
||||||
type: PropTypes.oneOf([
|
onClick?: () => void;
|
||||||
'DialogIcon',
|
pluginClass: PluginClass | undefined;
|
||||||
'BalloonIcon',
|
}
|
||||||
'PanelIcon',
|
|
||||||
'LinkIcon',
|
export interface LeftPluginState {
|
||||||
'Icon',
|
dialogVisible: boolean;
|
||||||
'Custom',
|
}
|
||||||
]),
|
|
||||||
}),
|
export default class LeftPlugin extends PureComponent<
|
||||||
disabled: PropTypes.bool,
|
LeftPluginProps,
|
||||||
dotted: PropTypes.bool,
|
LeftPluginState
|
||||||
locked: PropTypes.bool,
|
> {
|
||||||
onClick: PropTypes.func,
|
static displayName = 'LowcodeLeftPlugin';
|
||||||
};
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
active: false,
|
active: false,
|
||||||
config: {},
|
config: {},
|
||||||
disabled: false,
|
disabled: false,
|
||||||
dotted: false,
|
marked: false,
|
||||||
locked: false,
|
locked: false,
|
||||||
onClick: () => {},
|
onClick: (): void => {},
|
||||||
};
|
};
|
||||||
static contextType = AppContext;
|
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.state = {
|
this.state = {
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
};
|
};
|
||||||
this.appHelper = context.appHelper;
|
|
||||||
this.utils = this.appHelper.utils;
|
|
||||||
this.constants = this.appHelper.constants;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount(): void {
|
||||||
const { config } = this.props;
|
const { config, editor } = this.props;
|
||||||
const addonKey = config && config.addonKey;
|
const pluginKey = config && config.pluginKey;
|
||||||
const appHelper = this.appHelper;
|
if (editor && pluginKey) {
|
||||||
if (appHelper && addonKey) {
|
editor.on(`${pluginKey}.dialog.show`, this.handleShow);
|
||||||
appHelper.on(`${addonKey}.dialog.show`, this.handleShow);
|
editor.on(`${pluginKey}.dialog.close`, this.handleClose);
|
||||||
appHelper.on(`${addonKey}.dialog.close`, this.handleClose);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount(): void {
|
||||||
const { config } = this.props;
|
const { config, editor } = this.props;
|
||||||
const appHelper = this.appHelper;
|
const pluginKey = config && config.pluginKey;
|
||||||
const addonKey = config && config.addonKey;
|
if (editor && pluginKey) {
|
||||||
if (appHelper && addonKey) {
|
editor.off(`${pluginKey}.dialog.show`, this.handleShow);
|
||||||
appHelper.off(`${addonKey}.dialog.show`, this.handleShow);
|
editor.off(`${pluginKey}.dialog.close`, this.handleClose);
|
||||||
appHelper.off(`${addonKey}.dialog.close`, this.handleClose);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClose = () => {
|
handleClose = (): void => {
|
||||||
const addonKey = this.props.config && this.props.config.addonKey;
|
const { config, editor } = this.props;
|
||||||
const currentAddon =
|
const pluginKey = config && config.pluginKey;
|
||||||
this.appHelper.addons && this.appHelper.addons[addonKey];
|
const plugin = editor.plugins && editor.plugins[pluginKey];
|
||||||
if (currentAddon) {
|
if (plugin) {
|
||||||
this.utils.transformToPromise(currentAddon.close()).then(() => {
|
plugin.close().then((): void => {
|
||||||
this.setState({
|
this.setState({
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
});
|
});
|
||||||
@ -81,43 +76,48 @@ export default class LeftAddon extends PureComponent {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpen = () => {
|
handleOpen = (): void => {
|
||||||
// todo 对话框类型的插件初始时拿不到插件实例
|
// todo 对话框类型的插件初始时拿不到插件实例
|
||||||
this.setState({
|
this.setState({
|
||||||
dialogVisible: true,
|
dialogVisible: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleShow = () => {
|
handleShow = (): void => {
|
||||||
const { disabled, config, onClick } = this.props;
|
const { disabled, config, onClick, editor } = this.props;
|
||||||
const addonKey = config && config.addonKey;
|
const pluginKey = config && config.pluginKey;
|
||||||
if (disabled || !addonKey) return;
|
if (disabled || !pluginKey) return;
|
||||||
//考虑到弹窗情况,延时发送消息
|
|
||||||
setTimeout(() => this.appHelper.emit(`${addonKey}.addon.activate`), 0);
|
|
||||||
this.handleOpen();
|
this.handleOpen();
|
||||||
onClick && onClick();
|
// 考虑到弹窗情况,延时发送消息
|
||||||
|
setTimeout((): void => {
|
||||||
|
editor.emit(`${pluginKey}.plugin.activate`);
|
||||||
|
}, 0);
|
||||||
|
if (onClick) {
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderIcon = clickCallback => {
|
renderIcon = (clickCallback): React.ReactNode => {
|
||||||
const { active, disabled, dotted, locked, onClick, config } = this.props;
|
const { active, disabled, marked, locked, onClick, config } = this.props;
|
||||||
const { addonKey, props } = config || {};
|
const { pluginKey, props } = config || {};
|
||||||
const { icon, title } = props || {};
|
const { icon, title } = props || {};
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames('luna-left-addon', addonKey, {
|
className={classNames('lowcode-left-plugin', pluginKey, {
|
||||||
active,
|
active,
|
||||||
disabled,
|
disabled,
|
||||||
locked,
|
locked,
|
||||||
})}
|
})}
|
||||||
data-tooltip={title}
|
data-tooltip={title}
|
||||||
onClick={() => {
|
onClick={(): void => {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
//考虑到弹窗情况,延时发送消息
|
// 考虑到弹窗情况,延时发送消息
|
||||||
clickCallback && clickCallback();
|
clickCallback && clickCallback();
|
||||||
|
|
||||||
onClick && onClick();
|
onClick && onClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{dotted ? (
|
{marked ? (
|
||||||
<Badge dot>
|
<Badge dot>
|
||||||
<Icon type={icon} size="small" />
|
<Icon type={icon} size="small" />
|
||||||
</Badge>
|
</Badge>
|
||||||
@ -128,67 +128,66 @@ export default class LeftAddon extends PureComponent {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render(): React.ReactNode {
|
||||||
const { dotted, locked, active, disabled, config } = this.props;
|
const {
|
||||||
const { addonKey, props, type, addonProps } = config || {};
|
marked,
|
||||||
|
locked,
|
||||||
|
active,
|
||||||
|
disabled,
|
||||||
|
config,
|
||||||
|
editor,
|
||||||
|
pluginClass: Comp,
|
||||||
|
} = this.props;
|
||||||
|
const { pluginKey, props, type, pluginProps } = config || {};
|
||||||
const { onClick, title } = props || {};
|
const { onClick, title } = props || {};
|
||||||
const { dialogVisible } = this.state;
|
const { dialogVisible } = this.state;
|
||||||
const { appHelper, components } = this.context;
|
if (!pluginKey || !type || !props) return null;
|
||||||
if (!addonKey || !type || !props) return null;
|
|
||||||
const componentName = appHelper.utils.generateAddonCompName(addonKey);
|
|
||||||
const localeProps = {};
|
|
||||||
const { locale, messages } = appHelper;
|
|
||||||
if (locale) {
|
|
||||||
localeProps.locale = locale;
|
|
||||||
}
|
|
||||||
if (messages && messages[componentName]) {
|
|
||||||
localeProps.messages = messages[componentName];
|
|
||||||
}
|
|
||||||
const AddonComp = components && components[componentName];
|
|
||||||
const node =
|
|
||||||
(AddonComp && (
|
|
||||||
<AddonComp
|
|
||||||
active={active}
|
|
||||||
locked={locked}
|
|
||||||
disabled={disabled}
|
|
||||||
config={config}
|
|
||||||
onClick={() => {
|
|
||||||
onClick && onClick.call(null, appHelper);
|
|
||||||
}}
|
|
||||||
{...localeProps}
|
|
||||||
{...(addonProps || {})}
|
|
||||||
/>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
|
const node = Comp ? (
|
||||||
|
<Comp
|
||||||
|
editor={editor}
|
||||||
|
active={active}
|
||||||
|
locked={locked}
|
||||||
|
disabled={disabled}
|
||||||
|
config={config}
|
||||||
|
onClick={(): void => {
|
||||||
|
onClick && onClick.call(null, editor);
|
||||||
|
}}
|
||||||
|
{...pluginProps}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'LinkIcon':
|
case 'LinkIcon':
|
||||||
return (
|
return (
|
||||||
<a {...(props.linkProps || {})}>
|
<a {...(props.linkProps || {})}>
|
||||||
{this.renderIcon(() => {
|
{this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, appHelper);
|
onClick && onClick.call(null, editor);
|
||||||
})}
|
})}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
case 'Icon':
|
case 'Icon':
|
||||||
return this.renderIcon(() => {
|
return this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, appHelper);
|
onClick && onClick.call(null, editor);
|
||||||
});
|
});
|
||||||
case 'DialogIcon':
|
case 'DialogIcon':
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{this.renderIcon(() => {
|
{this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, appHelper);
|
onClick && onClick.call(null, editor);
|
||||||
this.handleOpen();
|
this.handleOpen();
|
||||||
})}
|
})}
|
||||||
<Dialog
|
<Dialog
|
||||||
onOk={() => {
|
onOk={(): void => {
|
||||||
appHelper.emit(`${addonKey}.dialog.onOk`);
|
editor.emit(`${pluginKey}.dialog.onOk`);
|
||||||
this.handleClose();
|
this.handleClose();
|
||||||
}}
|
}}
|
||||||
onCancel={this.handleClose}
|
onCancel={this.handleClose}
|
||||||
onClose={this.handleClose}
|
onClose={this.handleClose}
|
||||||
title={title}
|
title={title}
|
||||||
|
style={{
|
||||||
|
width: 500,
|
||||||
|
...(props.dialogProps && props.dialogProps.style),
|
||||||
|
}}
|
||||||
{...(props.dialogProps || {})}
|
{...(props.dialogProps || {})}
|
||||||
visible={dialogVisible}
|
visible={dialogVisible}
|
||||||
>
|
>
|
||||||
@ -199,8 +198,8 @@ export default class LeftAddon extends PureComponent {
|
|||||||
case 'BalloonIcon':
|
case 'BalloonIcon':
|
||||||
return (
|
return (
|
||||||
<Balloon
|
<Balloon
|
||||||
trigger={this.renderIcon(() => {
|
trigger={this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, appHelper);
|
onClick && onClick.call(null, editor);
|
||||||
})}
|
})}
|
||||||
align="r"
|
align="r"
|
||||||
triggerType={['click', 'hover']}
|
triggerType={['click', 'hover']}
|
||||||
@ -210,12 +209,11 @@ export default class LeftAddon extends PureComponent {
|
|||||||
</Balloon>
|
</Balloon>
|
||||||
);
|
);
|
||||||
case 'PanelIcon':
|
case 'PanelIcon':
|
||||||
return this.renderIcon(() => {
|
return this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, appHelper);
|
onClick && onClick.call(null, editor);
|
||||||
this.handleOpen();
|
|
||||||
});
|
});
|
||||||
case 'Custom':
|
case 'Custom':
|
||||||
return dotted ? <Badge dot>{node}</Badge> : node;
|
return marked ? <Badge dot>{node}</Badge> : node;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
52
packages/editor-skeleton/src/components/Panel/index.scss
Normal file
52
packages/editor-skeleton/src/components/Panel/index.scss
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
.lowcode-panel {
|
||||||
|
user-select: none;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
background: $card-background;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
height: 100%;
|
||||||
|
&.visible {
|
||||||
|
border-right: 1px solid $color-line1-1;
|
||||||
|
}
|
||||||
|
.drag-area {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&.floatable {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
&.draggable {
|
||||||
|
.drag-area {
|
||||||
|
display: block;
|
||||||
|
width: 10px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
cursor: col-resize;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
&.left {
|
||||||
|
.drag-area {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.right {
|
||||||
|
.drag-area {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.left {
|
||||||
|
&.floatable {
|
||||||
|
left: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.right {
|
||||||
|
&.floatable {
|
||||||
|
right: 48px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
export interface PanelProps {
|
||||||
|
align: 'left' | 'right';
|
||||||
|
defaultWidth: number;
|
||||||
|
minWidth: number;
|
||||||
|
draggable: boolean;
|
||||||
|
floatable: boolean;
|
||||||
|
children: Plugin;
|
||||||
|
visible: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PanelState {
|
||||||
|
width: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Panel extends PureComponent<PanelProps, PanelState> {
|
||||||
|
static displayName = 'LowcodePanel';
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
align: 'left',
|
||||||
|
defaultWidth: 240,
|
||||||
|
minWidth: 100,
|
||||||
|
draggable: true,
|
||||||
|
floatable: false,
|
||||||
|
visible: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
width: props.defaultWidth,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): React.ReactNode {
|
||||||
|
const { align, draggable, floatable, visible } = this.props;
|
||||||
|
const { width } = this.state;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames('lowcode-panel', align, {
|
||||||
|
draggable,
|
||||||
|
floatable,
|
||||||
|
visible,
|
||||||
|
})}
|
||||||
|
style={{
|
||||||
|
width,
|
||||||
|
display: visible ? '' : 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{this.props.children}
|
||||||
|
<div className="drag-area" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,22 +1,68 @@
|
|||||||
.next-btn.next-large.lowcode-top-btn {
|
.lowcode-top-icon {
|
||||||
|
display: inline-block;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
font-size: 20px;
|
||||||
padding: 0;
|
line-height: 48px;
|
||||||
margin: 4px -2px;
|
color: $color-text1-3;
|
||||||
text-align: center;
|
position: relative;
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
color: #777;
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
color: $color-text1-1;
|
color: $color-text1-1;
|
||||||
|
&:hover {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
color: $color-brand1-9;
|
||||||
|
&:hover {
|
||||||
|
color: $color-brand1-6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.locked {
|
&.locked {
|
||||||
color: red !important;
|
color: red !important;
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
|
color: $color-brand1-6;
|
||||||
|
&:before {
|
||||||
|
content: attr(data-tooltip);
|
||||||
|
display: block;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
bottom: -32px;
|
||||||
|
line-height: 18px;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: $balloon-normal-color-bg;
|
||||||
|
border: 1px solid $balloon-normal-color-border;
|
||||||
|
opacity: 0.8;
|
||||||
|
color: $color-text1-3;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0) rotate(45deg);
|
||||||
|
bottom: -5px;
|
||||||
|
background: $balloon-normal-color-bg;
|
||||||
|
border-left: 1px solid $balloon-normal-color-border;
|
||||||
|
border-top: 1px solid $balloon-normal-color-border;
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
i.next-icon {
|
i.next-icon {
|
||||||
&:before {
|
&:before {
|
||||||
font-size: 17px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
|||||||
@ -1,23 +1,25 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Icon, Button } from '@alifd/next';
|
import { Icon } from '@alifd/next';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class TopIcon extends PureComponent {
|
|
||||||
static displayName = 'TopIcon';
|
export interface TopIconProps {
|
||||||
static propTypes = {
|
active?: boolean;
|
||||||
active: PropTypes.bool,
|
className?: string;
|
||||||
className: PropTypes.string,
|
disabled?: boolean;
|
||||||
disabled: PropTypes.bool,
|
icon: string;
|
||||||
icon: PropTypes.string,
|
id?: string;
|
||||||
id: PropTypes.string,
|
locked?: boolean;
|
||||||
locked: PropTypes.bool,
|
marked?: boolean;
|
||||||
onClick: PropTypes.func,
|
onClick?: () => void;
|
||||||
showTitle: PropTypes.bool,
|
style?: React.CSSProperties;
|
||||||
style: PropTypes.object,
|
title?: string;
|
||||||
title: PropTypes.string,
|
}
|
||||||
};
|
|
||||||
|
export default class TopIcon extends PureComponent<TopIconProps> {
|
||||||
|
static displayName = 'LowcodeTopIcon';
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
active: false,
|
active: false,
|
||||||
className: '',
|
className: '',
|
||||||
@ -25,13 +27,12 @@ export default class TopIcon extends PureComponent {
|
|||||||
icon: '',
|
icon: '',
|
||||||
id: '',
|
id: '',
|
||||||
locked: false,
|
locked: false,
|
||||||
onClick: () => {},
|
onClick: (): void => {},
|
||||||
showTitle: false,
|
|
||||||
style: {},
|
style: {},
|
||||||
title: '',
|
title: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render(): React.ReactNode {
|
||||||
const {
|
const {
|
||||||
active,
|
active,
|
||||||
disabled,
|
disabled,
|
||||||
@ -41,28 +42,22 @@ export default class TopIcon extends PureComponent {
|
|||||||
className,
|
className,
|
||||||
id,
|
id,
|
||||||
style,
|
style,
|
||||||
showTitle,
|
|
||||||
onClick,
|
onClick,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<Button
|
<div
|
||||||
type="normal"
|
className={classNames('lowcode-top-icon', className, {
|
||||||
size="large"
|
|
||||||
text={true}
|
|
||||||
className={classNames('lowcode-top-btn', className, {
|
|
||||||
active,
|
active,
|
||||||
disabled,
|
disabled,
|
||||||
locked,
|
locked,
|
||||||
})}
|
})}
|
||||||
|
data-tooltip={title}
|
||||||
id={id}
|
id={id}
|
||||||
style={style}
|
style={style}
|
||||||
onClick={disabled ? null : onClick}
|
onClick={disabled ? undefined : onClick}
|
||||||
>
|
>
|
||||||
<div>
|
<Icon type={icon} />
|
||||||
<Icon size="large" type={icon} />
|
</div>
|
||||||
{showTitle && <span>{title}</span>}
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,43 @@
|
|||||||
import React, { PureComponent, Fragment } from 'react';
|
import React, { PureComponent, Fragment } from 'react';
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import TopIcon from '../TopIcon';
|
|
||||||
import { Balloon, Badge, Dialog } from '@alifd/next';
|
import { Balloon, Badge, Dialog } from '@alifd/next';
|
||||||
|
import Editor from '@ali/lowcode-editor-framework';
|
||||||
|
import {
|
||||||
|
PluginConfig,
|
||||||
|
PluginClass,
|
||||||
|
} from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
|
import TopIcon from '../TopIcon';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
export default class TopPlugin extends PureComponent {
|
|
||||||
static displayName = 'lowcodeTopPlugin';
|
export interface TopPluginProps {
|
||||||
|
active?: boolean;
|
||||||
|
config: PluginConfig;
|
||||||
|
disabled?: boolean;
|
||||||
|
editor: Editor;
|
||||||
|
locked?: boolean;
|
||||||
|
marked?: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
|
pluginClass: PluginClass | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TopPluginState {
|
||||||
|
dialogVisible: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TopPlugin extends PureComponent<
|
||||||
|
TopPluginProps,
|
||||||
|
TopPluginState
|
||||||
|
> {
|
||||||
|
static displayName = 'LowcodeTopPlugin';
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
active: false,
|
active: false,
|
||||||
config: {},
|
config: {},
|
||||||
disabled: false,
|
disabled: false,
|
||||||
dotted: false,
|
marked: false,
|
||||||
locked: false,
|
locked: false,
|
||||||
onClick: () => {},
|
onClick: (): void => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
@ -24,42 +47,42 @@ export default class TopPlugin extends PureComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount(): void {
|
||||||
const { config } = this.props;
|
const { config, editor } = this.props;
|
||||||
const pluginKey = config && config.pluginKey;
|
const pluginKey = config && config.pluginKey;
|
||||||
// const appHelper = this.appHelper;
|
if (editor && pluginKey) {
|
||||||
// if (appHelper && addonKey) {
|
editor.on(`${pluginKey}.dialog.show`, this.handleShow);
|
||||||
// appHelper.on(`${addonKey}.dialog.show`, this.handleShow);
|
editor.on(`${pluginKey}.dialog.close`, this.handleClose);
|
||||||
// appHelper.on(`${addonKey}.dialog.close`, this.handleClose);
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount(): void {
|
||||||
// const { config } = this.props;
|
const { config, editor } = this.props;
|
||||||
// const addonKey = config && config.addonKey;
|
const pluginKey = config && config.pluginKey;
|
||||||
// const appHelper = this.appHelper;
|
if (editor && pluginKey) {
|
||||||
// if (appHelper && addonKey) {
|
editor.off(`${pluginKey}.dialog.show`, this.handleShow);
|
||||||
// appHelper.off(`${addonKey}.dialog.show`, this.handleShow);
|
editor.off(`${pluginKey}.dialog.close`, this.handleClose);
|
||||||
// appHelper.off(`${addonKey}.dialog.close`, this.handleClose);
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShow = () => {
|
handleShow = (): void => {
|
||||||
const { disabled, config, onClick } = this.props;
|
const { disabled, config, onClick, editor } = this.props;
|
||||||
const addonKey = config && config.addonKey;
|
const pluginKey = config && config.pluginKey;
|
||||||
if (disabled || !addonKey) return;
|
if (disabled || !pluginKey) return;
|
||||||
//考虑到弹窗情况,延时发送消息
|
|
||||||
setTimeout(() => this.appHelper.emit(`${addonKey}.addon.activate`), 0);
|
|
||||||
this.handleOpen();
|
this.handleOpen();
|
||||||
|
// 考虑到弹窗情况,延时发送消息
|
||||||
|
setTimeout((): void => {
|
||||||
|
editor.emit(`${pluginKey}.plugin.activate`);
|
||||||
|
}, 0);
|
||||||
onClick && onClick();
|
onClick && onClick();
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClose = () => {
|
handleClose = (): void => {
|
||||||
const addonKey = this.props.config && this.props.config.addonKey;
|
const { config, editor } = this.props;
|
||||||
const currentAddon =
|
const pluginKey = config && config.pluginKey;
|
||||||
this.appHelper.addons && this.appHelper.addons[addonKey];
|
const plugin = editor.plugins && editor.plugins[pluginKey];
|
||||||
if (currentAddon) {
|
if (plugin) {
|
||||||
this.utils.transformToPromise(currentAddon.close()).then(() => {
|
plugin.close().then((): void => {
|
||||||
this.setState({
|
this.setState({
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
});
|
});
|
||||||
@ -67,85 +90,107 @@ export default class TopPlugin extends PureComponent {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpen = () => {
|
handleOpen = (): void => {
|
||||||
// todo dialog类型的插件初始时拿不动插件实例
|
// todo dialog类型的插件初始时拿不动插件实例
|
||||||
this.setState({
|
this.setState({
|
||||||
dialogVisible: true,
|
dialogVisible: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
renderIcon = clickCallback => {
|
renderIcon = (clickCallback): React.ReactNode => {
|
||||||
const { active, disabled, dotted, locked, config, onClick } = this.props;
|
const {
|
||||||
|
active,
|
||||||
|
disabled,
|
||||||
|
marked,
|
||||||
|
locked,
|
||||||
|
config,
|
||||||
|
onClick,
|
||||||
|
editor,
|
||||||
|
} = this.props;
|
||||||
const { pluginKey, props } = config || {};
|
const { pluginKey, props } = config || {};
|
||||||
const { icon, title } = props || {};
|
const { icon, title } = props || {};
|
||||||
const node = (
|
const node = (
|
||||||
<TopIcon
|
<TopIcon
|
||||||
className={`lowcode-top-addon ${pluginKey}`}
|
className={`lowcode-top-plugin ${pluginKey}`}
|
||||||
active={active}
|
active={active}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
locked={locked}
|
locked={locked}
|
||||||
icon={icon}
|
icon={icon}
|
||||||
title={title}
|
title={title}
|
||||||
onClick={() => {
|
onClick={(): void => {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
//考虑到弹窗情况,延时发送消息
|
// 考虑到弹窗情况,延时发送消息
|
||||||
setTimeout(
|
setTimeout((): void => {
|
||||||
() => this.appHelper.emit(`${pluginKey}.addon.activate`),
|
editor.emit(`${pluginKey}.plugin.activate`);
|
||||||
0,
|
}, 0);
|
||||||
);
|
|
||||||
clickCallback && clickCallback();
|
clickCallback && clickCallback();
|
||||||
onClick && onClick();
|
onClick && onClick();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
return dotted ? <Badge dot>{node}</Badge> : node;
|
return marked ? <Badge dot>{node}</Badge> : node;
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render(): React.ReactNode {
|
||||||
const { active, dotted, locked, disabled, config, editor, pluginClass: Comp } = this.props;
|
const {
|
||||||
|
active,
|
||||||
|
marked,
|
||||||
|
locked,
|
||||||
|
disabled,
|
||||||
|
config,
|
||||||
|
editor,
|
||||||
|
pluginClass: Comp,
|
||||||
|
} = this.props;
|
||||||
const { pluginKey, pluginProps, props, type } = config || {};
|
const { pluginKey, pluginProps, props, type } = config || {};
|
||||||
const { onClick, title } = props || {};
|
const { onClick, title } = props || {};
|
||||||
const { dialogVisible } = this.state;
|
const { dialogVisible } = this.state;
|
||||||
if (!pluginKey || !type || !Comp) return null;
|
if (!pluginKey || !type) return null;
|
||||||
const node = <Comp
|
const node = Comp ? (
|
||||||
active={active}
|
<Comp
|
||||||
locked={locked}
|
editor={editor}
|
||||||
disabled={disabled}
|
active={active}
|
||||||
config={config}
|
locked={locked}
|
||||||
onClick={() => {
|
disabled={disabled}
|
||||||
onClick && onClick.call(null, editor);
|
config={config}
|
||||||
}}
|
onClick={(): void => {
|
||||||
{...pluginProps}
|
onClick && onClick.call(null, editor);
|
||||||
/>;
|
}}
|
||||||
|
{...pluginProps}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'LinkIcon':
|
case 'LinkIcon':
|
||||||
return (
|
return (
|
||||||
<a {...props.linkProps}>
|
<a {...props.linkProps}>
|
||||||
{this.renderIcon(() => {
|
{this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, editor);
|
onClick && onClick.call(null, editor);
|
||||||
})}
|
})}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
case 'Icon':
|
case 'Icon':
|
||||||
return this.renderIcon(() => {
|
return this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, editor);
|
onClick && onClick.call(null, editor);
|
||||||
});
|
});
|
||||||
case 'DialogIcon':
|
case 'DialogIcon':
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{this.renderIcon(() => {
|
{this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, editor);
|
onClick && onClick.call(null, editor);
|
||||||
this.handleOpen();
|
this.handleOpen();
|
||||||
})}
|
})}
|
||||||
<Dialog
|
<Dialog
|
||||||
onOk={() => {
|
onOk={(): void => {
|
||||||
editor.emit(`${pluginKey}.dialog.onOk`);
|
editor.emit(`${pluginKey}.dialog.onOk`);
|
||||||
this.handleClose();
|
this.handleClose();
|
||||||
}}
|
}}
|
||||||
onCancel={this.handleClose}
|
onCancel={this.handleClose}
|
||||||
onClose={this.handleClose}
|
onClose={this.handleClose}
|
||||||
title={title}
|
title={title}
|
||||||
|
style={{
|
||||||
|
width: 500,
|
||||||
|
...(props.dialogProps && props.dialogProps.style),
|
||||||
|
}}
|
||||||
{...props.dialogProps}
|
{...props.dialogProps}
|
||||||
visible={dialogVisible}
|
visible={dialogVisible}
|
||||||
>
|
>
|
||||||
@ -156,7 +201,7 @@ export default class TopPlugin extends PureComponent {
|
|||||||
case 'BalloonIcon':
|
case 'BalloonIcon':
|
||||||
return (
|
return (
|
||||||
<Balloon
|
<Balloon
|
||||||
trigger={this.renderIcon(() => {
|
trigger={this.renderIcon((): void => {
|
||||||
onClick && onClick.call(null, editor);
|
onClick && onClick.call(null, editor);
|
||||||
})}
|
})}
|
||||||
triggerType={['click', 'hover']}
|
triggerType={['click', 'hover']}
|
||||||
@ -166,7 +211,7 @@ export default class TopPlugin extends PureComponent {
|
|||||||
</Balloon>
|
</Balloon>
|
||||||
);
|
);
|
||||||
case 'Custom':
|
case 'Custom':
|
||||||
return dotted ? <Badge dot>{node}</Badge> : node;
|
return marked ? <Badge dot>{node}</Badge> : node;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1 @@
|
|||||||
import Dashboard from '@/pages/Dashboard';
|
export default {};
|
||||||
import BasicLayout from '@/layouts/BasicLayout';
|
|
||||||
|
|
||||||
const routerConfig = [
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
component: BasicLayout,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/dashboard',
|
|
||||||
component: Dashboard,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
redirect: '/dashboard',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default routerConfig;
|
|
||||||
|
|||||||
@ -1,5 +1 @@
|
|||||||
// 菜单配置
|
export default {};
|
||||||
|
|
||||||
const asideMenuConfig = [];
|
|
||||||
|
|
||||||
export { asideMenuConfig };
|
|
||||||
|
|||||||
@ -7,7 +7,9 @@ body {
|
|||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
color: $color-text1-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.next-loading {
|
.next-loading {
|
||||||
.next-loading-wrap {
|
.next-loading-wrap {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -16,18 +18,17 @@ body {
|
|||||||
.lowcode-editor {
|
.lowcode-editor {
|
||||||
.lowcode-main-content {
|
.lowcode-main-content {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 48px;
|
top: 50px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #d8d8d8;
|
background-color: rgba(31, 56, 88, 0.06);
|
||||||
}
|
}
|
||||||
.lowcode-center-area {
|
.lowcode-center-area {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 10px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,56 +1,147 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
// import Editor from '@ali/lowcode-engine-editor';
|
|
||||||
import { Loading, ConfigProvider } from '@alifd/next';
|
import { Loading, ConfigProvider } from '@alifd/next';
|
||||||
|
import { HashRouter as Router, Route } from 'react-router-dom';
|
||||||
|
import Editor, { utils } from '@ali/lowcode-editor-framework';
|
||||||
|
import {
|
||||||
|
EditorConfig,
|
||||||
|
Utils,
|
||||||
|
PluginClassSet,
|
||||||
|
} from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import defaultConfig from './config/skeleton';
|
import defaultConfig from './config/skeleton';
|
||||||
|
import skeletonUtils from './config/utils';
|
||||||
|
|
||||||
import TopArea from './layouts/TopArea';
|
import TopArea from './layouts/TopArea';
|
||||||
import LeftArea from './layouts/LeftArea';
|
import LeftArea from './layouts/LeftArea';
|
||||||
import CenterArea from './layouts/CenterArea';
|
import CenterArea from './layouts/CenterArea';
|
||||||
import RightArea from './layouts/RightArea';
|
import RightArea from './layouts/RightArea';
|
||||||
|
|
||||||
import './global.scss';
|
import './global.scss';
|
||||||
|
|
||||||
export default class Skeleton extends PureComponent {
|
const { comboEditorConfig, parseSearch } = utils;
|
||||||
static displayName = 'lowcodeEditorSkeleton';
|
|
||||||
|
|
||||||
constructor(props) {
|
let renderIdx = 0;
|
||||||
super(props);
|
|
||||||
// this.editor = new Editor(props.config, props.utils);
|
declare global {
|
||||||
this.editor = {
|
interface Window {
|
||||||
on: () => {},
|
__ctx: {
|
||||||
off: () => {},
|
editor: Editor;
|
||||||
config: props.config,
|
appHelper: Editor;
|
||||||
pluginComponents: props.pluginComponents
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SkeletonProps {
|
||||||
|
components: PluginClassSet;
|
||||||
|
config: EditorConfig;
|
||||||
|
history: object;
|
||||||
|
location: object;
|
||||||
|
match: object;
|
||||||
|
utils: Utils;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SkeletonState {
|
||||||
|
initReady?: boolean;
|
||||||
|
skeletonKey?: string;
|
||||||
|
__hasError?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Skeleton extends PureComponent<SkeletonProps, SkeletonState> {
|
||||||
|
static displayName = 'LowcodeEditorSkeleton';
|
||||||
|
|
||||||
|
static getDerivedStateFromError(): SkeletonState {
|
||||||
|
return {
|
||||||
|
__hasError: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
private editor: Editor;
|
||||||
// this.editor && this.editor.destroy();
|
|
||||||
// this.editor = null;
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
initReady: false,
|
||||||
|
skeletonKey: `skeleton${renderIdx}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
componentWillUnmount(): void {
|
||||||
const { location, history, messages } = this.props;
|
this.editor && this.editor.destroy();
|
||||||
this.editor.location = location;
|
}
|
||||||
this.editor.history = history;
|
|
||||||
this.editor.messages = messages;
|
componentDidCatch(err): void {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
init = (isReset: boolean = false): void => {
|
||||||
|
if (this.editor) {
|
||||||
|
this.editor.destroy();
|
||||||
|
}
|
||||||
|
const { utils, config, components } = this.props;
|
||||||
|
const editor = new Editor(
|
||||||
|
comboEditorConfig(defaultConfig, config),
|
||||||
|
components,
|
||||||
|
{
|
||||||
|
...skeletonUtils,
|
||||||
|
...utils,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.editor = editor;
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
window.__ctx = {
|
||||||
|
editor,
|
||||||
|
appHelper: editor,
|
||||||
|
};
|
||||||
|
editor.once('editor.reset', (): void => {
|
||||||
|
this.setState({
|
||||||
|
initReady: false,
|
||||||
|
});
|
||||||
|
editor.emit('editor.beforeReset');
|
||||||
|
this.init(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
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');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): React.ReactNode {
|
||||||
|
const { initReady, skeletonKey, __hasError } = this.state;
|
||||||
|
const { location, history, match } = this.props;
|
||||||
|
if (__hasError || !this.editor) {
|
||||||
|
return 'error';
|
||||||
|
}
|
||||||
|
|
||||||
|
location.query = parseSearch(location.search);
|
||||||
|
this.editor.set('location', location);
|
||||||
|
this.editor.set('history', history);
|
||||||
|
this.editor.set('match', match);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigProvider>
|
<ConfigProvider>
|
||||||
<Loading
|
<Loading tip="Loading" size="large" visible={!initReady} fullScreen>
|
||||||
tip="Loading"
|
<div className="lowcode-editor" key={skeletonKey}>
|
||||||
size="large"
|
<TopArea editor={this.editor} />
|
||||||
visible={false}
|
|
||||||
shape="fusion-reactor"
|
|
||||||
fullScreen
|
|
||||||
>
|
|
||||||
<div className="lowcode-editor">
|
|
||||||
<TopArea editor={this.editor}/>
|
|
||||||
<div className="lowcode-main-content">
|
<div className="lowcode-main-content">
|
||||||
<LeftArea.Nav editor={this.editor}/>
|
<LeftArea.Nav editor={this.editor} />
|
||||||
<LeftArea.Panel editor={this.editor}/>
|
<LeftArea.Panel editor={this.editor} />
|
||||||
<CenterArea editor={this.editor}/>
|
<CenterArea editor={this.editor} />
|
||||||
<RightArea editor={this.editor}/>
|
<RightArea editor={this.editor} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Loading>
|
</Loading>
|
||||||
@ -58,3 +149,33 @@ export default class Skeleton extends PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通过React-Router包裹,支持编辑器内页面根据路由切换
|
||||||
|
export interface SkeletonWithRouterProps {
|
||||||
|
components: PluginClassSet;
|
||||||
|
config: EditorConfig;
|
||||||
|
utils: Utils;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SkeletonWithRouter: React.FC<SkeletonWithRouterProps> = (
|
||||||
|
props,
|
||||||
|
): React.ReactElement => {
|
||||||
|
const { config, ...otherProps } = props;
|
||||||
|
return (
|
||||||
|
<Router>
|
||||||
|
<Route
|
||||||
|
path="/*"
|
||||||
|
component={routerProps => (
|
||||||
|
<Skeleton
|
||||||
|
{...routerProps}
|
||||||
|
{...otherProps}
|
||||||
|
{...(config.skeleton && config.skeleton.props)}
|
||||||
|
config={config}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SkeletonWithRouter;
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
.lowcode-center-area {
|
.lowcode-center-area {
|
||||||
padding: 12px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,60 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import Editor, { AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
export default class CenterArea extends PureComponent {
|
export interface CenterAreaProps {
|
||||||
static displayName = 'lowcodeCenterArea';
|
editor: Editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class CenterArea extends PureComponent<CenterAreaProps> {
|
||||||
|
static displayName = 'LowcodeCenterArea';
|
||||||
|
|
||||||
|
private editor: Editor;
|
||||||
|
|
||||||
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.editor = props.editor;
|
||||||
|
this.areaManager = new AreaManager(this.editor, 'centerArea');
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
componentDidMount(): void {
|
||||||
return <div className="lowcode-center-area"></div>;
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSkeletonUpdate = (): void => {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): React.ReactNode {
|
||||||
|
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
|
return (
|
||||||
|
<div className="lowcode-center-area">
|
||||||
|
{visiblePluginList.map(
|
||||||
|
(item): React.ReactNode => {
|
||||||
|
const Comp = this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
if (Comp) {
|
||||||
|
return (
|
||||||
|
<Comp
|
||||||
|
key={item.pluginKey}
|
||||||
|
editor={this.editor}
|
||||||
|
config={item}
|
||||||
|
{...item.pluginProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,23 @@
|
|||||||
.lowcode-left-area-nav {
|
.lowcode-left-area-nav {
|
||||||
width: 48px;
|
width: 50px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: #ffffff;
|
background-color: $card-background;
|
||||||
border-right: 1px solid #e8ebee;
|
border-right: 2px solid $color-line1-1;
|
||||||
position: relative;
|
position: relative;
|
||||||
.top-area {
|
.top-area {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #ffffff;
|
padding: 12px 0;
|
||||||
|
background-color: $card-background;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
.bottom-area {
|
.bottom-area {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 20px;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #ffffff;
|
padding: 12px 0;
|
||||||
|
background-color: $card-background;
|
||||||
max-height: calc(100% - 20px);
|
max-height: calc(100% - 20px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,148 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import LeftPlugin from '../../components/LeftPlugin';
|
||||||
|
import Editor, { utils, AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
export default class LeftAreaPanel extends PureComponent {
|
const { isEmpty } = utils;
|
||||||
static displayName = 'lowcodeLeftAreaNav';
|
|
||||||
|
export interface LeftAreaNavProps {
|
||||||
|
editor: Editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LeftAreaNavState {
|
||||||
|
activeKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class LeftAreaNav extends PureComponent<
|
||||||
|
LeftAreaNavProps,
|
||||||
|
LeftAreaNavState
|
||||||
|
> {
|
||||||
|
static displayName = 'LowcodeLeftAreaNav';
|
||||||
|
|
||||||
|
private editor: Editor;
|
||||||
|
|
||||||
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.editor = props.editor;
|
||||||
|
this.areaManager = new AreaManager(this.editor, 'leftArea');
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
activeKey: 'none',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
componentDidMount(): void {
|
||||||
return <div className="lowcode-left-area-nav" />;
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.on('leftNav.change', this.handlePluginChange);
|
||||||
|
const visiblePanelPluginList = this.areaManager.getVisiblePluginList(
|
||||||
|
'IconPanel',
|
||||||
|
);
|
||||||
|
const defaultKey =
|
||||||
|
(visiblePanelPluginList[0] && visiblePanelPluginList[0].pluginKey) ||
|
||||||
|
'componentAttr';
|
||||||
|
this.handlePluginChange(defaultKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.off('leftNav.change', this.handlePluginChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSkeletonUpdate = (): void => {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePluginChange = (key: string): void => {
|
||||||
|
const { activeKey } = this.state;
|
||||||
|
const plugins = this.editor.plugins;
|
||||||
|
const prePlugin = plugins[activeKey];
|
||||||
|
const nextPlugin = plugins[key];
|
||||||
|
if (activeKey === 'none') {
|
||||||
|
if (nextPlugin) {
|
||||||
|
nextPlugin.open().then((): void => {
|
||||||
|
this.updateActiveKey(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (activeKey === key) {
|
||||||
|
if (prePlugin) {
|
||||||
|
prePlugin.close().then((): void => {
|
||||||
|
this.updateActiveKey('none');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (prePlugin) {
|
||||||
|
// 先关后开
|
||||||
|
prePlugin.close().then((): void => {
|
||||||
|
if (nextPlugin) {
|
||||||
|
nextPlugin.open().then((): void => {
|
||||||
|
this.updateActiveKey(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePluginClick = (item: PluginConfig): void => {
|
||||||
|
if (item.type === 'PanelIcon') {
|
||||||
|
this.handlePluginChange(item.pluginKey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateActiveKey = (key: string): void => {
|
||||||
|
this.editor.set('leftNav', key);
|
||||||
|
this.setState({ activeKey: key });
|
||||||
|
this.editor.emit('leftPanel.show', key);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => {
|
||||||
|
const { activeKey } = this.state;
|
||||||
|
return list.map(
|
||||||
|
(item): React.ReactElement => {
|
||||||
|
const pluginStatus = this.areaManager.getPluginStatus(item.pluginKey);
|
||||||
|
const pluginClass = this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
return (
|
||||||
|
<LeftPlugin
|
||||||
|
key={item.pluginKey}
|
||||||
|
config={item}
|
||||||
|
editor={this.editor}
|
||||||
|
pluginClass={pluginClass}
|
||||||
|
onClick={(): void => this.handlePluginClick(item)}
|
||||||
|
active={activeKey === item.pluginKey}
|
||||||
|
{...pluginStatus}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): React.ReactNode {
|
||||||
|
const topList: PluginConfig[] = [];
|
||||||
|
const bottomList: PluginConfig[] = [];
|
||||||
|
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
|
if (isEmpty(visiblePluginList)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
visiblePluginList.forEach((item): void => {
|
||||||
|
const align =
|
||||||
|
item.props && item.props.align === 'bottom' ? 'bottom' : 'top';
|
||||||
|
if (align === 'bottom') {
|
||||||
|
bottomList.push(item);
|
||||||
|
} else {
|
||||||
|
topList.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="lowcode-left-area-nav">
|
||||||
|
<div className="bottom-area">{this.renderPluginList(bottomList)}</div>
|
||||||
|
<div className="top-area">{this.renderPluginList(topList)}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,88 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent, Fragment } from 'react';
|
||||||
|
import Editor, { AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
|
import Panel from '../../components/Panel';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
export default class LeftAreaPanel extends PureComponent {
|
export interface LeftAreaPanelProps {
|
||||||
static displayName = 'lowcodeLeftAreaPanel';
|
editor: Editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LeftAreaPanelState {
|
||||||
|
activeKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class LeftAreaPanel extends PureComponent<
|
||||||
|
LeftAreaPanelProps,
|
||||||
|
LeftAreaPanelState
|
||||||
|
> {
|
||||||
|
static displayName = 'LowcodeLeftAreaPanel';
|
||||||
|
|
||||||
|
private editor: Editor;
|
||||||
|
|
||||||
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.editor = props.editor;
|
||||||
|
this.areaManager = new AreaManager(this.editor, 'leftArea');
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
activeKey: 'none',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
componentDidMount(): void {
|
||||||
return <div className="lowcode-left-area-panel" />;
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.on('leftPanel.show', this.handlePluginChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.off('leftPanel.show', this.handlePluginChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSkeletonUpdate = (): void => {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (this.areaManager.isPluginStatusUpdate('PanelIcon')) {
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePluginChange = (key: string): void => {
|
||||||
|
this.setState({
|
||||||
|
activeKey: key,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): React.ReactNode {
|
||||||
|
const { activeKey } = this.state;
|
||||||
|
const list = this.areaManager.getVisiblePluginList('PanelIcon');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
{list.map(
|
||||||
|
(item): React.ReactNode => {
|
||||||
|
const Comp = this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
if (Comp) {
|
||||||
|
return (
|
||||||
|
<Panel
|
||||||
|
key={item.pluginKey}
|
||||||
|
visible={item.pluginKey === activeKey}
|
||||||
|
{...(item.props && item.props.panelProps)}
|
||||||
|
>
|
||||||
|
<Comp
|
||||||
|
editor={this.editor}
|
||||||
|
config={item}
|
||||||
|
{...item.pluginProps}
|
||||||
|
/>
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,155 +1,37 @@
|
|||||||
.lowcode-right-area {
|
.lowcode-right-area {
|
||||||
width: 300px;
|
width: 262px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #ffffff;
|
background-color: $card-background;
|
||||||
border-left: 1px solid #e8ebee;
|
border-left: 2px solid $color-line1-1;
|
||||||
.right-plugin-title {
|
|
||||||
&.locked {
|
.right-panel {
|
||||||
color: red !important;
|
overflow: auto;
|
||||||
}
|
// border-top: 2px solid $color-line1-1;
|
||||||
&.active {
|
|
||||||
color: $color-brand1-9 !important;
|
|
||||||
}
|
|
||||||
&.disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
color: $color-text1-1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//tab定义
|
//tab定义
|
||||||
.next-tabs-wrapped.right-tabs {
|
.right-tabs.next-tabs {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-top: -1px;
|
|
||||||
.next-tabs-bar {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.next-tabs-nav {
|
.next-tabs-nav {
|
||||||
display: block;
|
width: 100%;
|
||||||
.next-tabs-tab {
|
.next-tabs-tab-inner {
|
||||||
&:first-child {
|
padding-left: 0;
|
||||||
border-left: none;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
font-size: 14px;
|
.right-plugin-title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-right: none !important;
|
&.locked {
|
||||||
margin-right: 0 !important;
|
color: red !important;
|
||||||
width: 25%;
|
}
|
||||||
&.active {
|
&.active {
|
||||||
background: none;
|
color: $color-brand1-9 !important;
|
||||||
border-bottom-color: #f7f7f7 !important;
|
|
||||||
}
|
}
|
||||||
}
|
&.disabled {
|
||||||
}
|
cursor: not-allowed;
|
||||||
}
|
color: $color-text1-1;
|
||||||
.next-tabs-content {
|
|
||||||
flex: 1;
|
|
||||||
.next-tabs-tabpane.active {
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//组件
|
|
||||||
.select-comp {
|
|
||||||
padding: 10px 16px;
|
|
||||||
line-height: 16px;
|
|
||||||
color: #989a9c;
|
|
||||||
& > span {
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 16px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
& > .btn-wrap,
|
|
||||||
& > .next-btn {
|
|
||||||
width: auto;
|
|
||||||
margin: 0 5px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.unselected {
|
|
||||||
padding: 60px 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
//右侧属性面板样式调整;
|
|
||||||
.offset-56 {
|
|
||||||
padding-left: 56px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.fixedSpan.next-form-item {
|
|
||||||
& > .next-form-item-label {
|
|
||||||
width: 56px;
|
|
||||||
flex: none;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
& > .next-form-item-control {
|
|
||||||
padding-right: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fixedSpan.next-form-item,
|
|
||||||
.offset-56 .next-form-item {
|
|
||||||
display: flex;
|
|
||||||
& > .next-form-item-control {
|
|
||||||
width: auto;
|
|
||||||
flex: 1;
|
|
||||||
max-width: none;
|
|
||||||
.next-input,
|
|
||||||
.next-select,
|
|
||||||
.next-radio-group,
|
|
||||||
.next-number-picker,
|
|
||||||
.luna-reactnode-btn,
|
|
||||||
.luna-monaco-button button,
|
|
||||||
.luna-object-button button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.next-number-picker {
|
|
||||||
width: 100%;
|
|
||||||
.next-after {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
}
|
||||||
}
|
.next-icon {
|
||||||
.next-radio-group {
|
line-height: 15px;
|
||||||
display: flex;
|
margin-right: 2px;
|
||||||
label {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.topSpan.next-form-item {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
& > .next-form-item-control {
|
|
||||||
padding-right: 24px;
|
|
||||||
.next-input,
|
|
||||||
.next-select,
|
|
||||||
.next-radio-group,
|
|
||||||
.next-number-picker,
|
|
||||||
.luna-reactnode-btn,
|
|
||||||
.luna-monaco-button button,
|
|
||||||
.luna-object-button button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.next-number-picker {
|
|
||||||
width: 100%;
|
|
||||||
.next-after {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.next-radio-group {
|
|
||||||
display: flex;
|
|
||||||
label {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,214 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import { Tab, Badge, Icon } from '@alifd/next';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import Editor, { AreaManager, utils } from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
export default class RightArea extends PureComponent {
|
const { isEmpty } = utils;
|
||||||
static displayName = 'lowcodeRightArea';
|
|
||||||
|
export interface RightAreaProps {
|
||||||
|
editor: Editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RightAreaState {
|
||||||
|
activeKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class RightArea extends PureComponent<
|
||||||
|
RightAreaProps,
|
||||||
|
RightAreaState
|
||||||
|
> {
|
||||||
|
static displayName = 'LowcodeRightArea';
|
||||||
|
|
||||||
|
private editor: Editor;
|
||||||
|
|
||||||
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.editor = props.editor;
|
||||||
|
this.areaManager = new AreaManager(this.editor, 'rightArea');
|
||||||
|
this.state = {
|
||||||
|
activeKey: '',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
componentDidMount(): void {
|
||||||
return <div className="lowcode-right-area" />;
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.on('rightNav.change', this.handlePluginChange);
|
||||||
|
const visiblePluginList = this.areaManager.getVisiblePluginList('TabPanel');
|
||||||
|
const defaultKey =
|
||||||
|
(visiblePluginList[0] && visiblePluginList[0].pluginKey) ||
|
||||||
|
'componentAttr';
|
||||||
|
this.handlePluginChange(defaultKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
this.editor.off('rightNav.change', this.handlePluginChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSkeletonUpdate = (): void => {
|
||||||
|
// 当前区域插件状态改变是更新区域
|
||||||
|
if (this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
const activeKey = this.state.activeKey;
|
||||||
|
const activePluginStatus = this.areaManager.getPluginStatus(activeKey);
|
||||||
|
if (activePluginStatus && activePluginStatus.visible) {
|
||||||
|
this.forceUpdate();
|
||||||
|
} else {
|
||||||
|
const currentPlugin = this.areaManager.getPlugin(activeKey);
|
||||||
|
if (currentPlugin) {
|
||||||
|
currentPlugin.close().then((): void => {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
activeKey: '',
|
||||||
|
},
|
||||||
|
(): void => {
|
||||||
|
const visiblePluginList = this.areaManager.getVisiblePluginList(
|
||||||
|
'TabPanel',
|
||||||
|
);
|
||||||
|
const firstPlugin = visiblePluginList && visiblePluginList[0];
|
||||||
|
if (firstPlugin) {
|
||||||
|
this.handlePluginChange(firstPlugin.pluginKey);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePluginChange = (key: string, isinit?: boolean): void => {
|
||||||
|
const activeKey = this.state.activeKey;
|
||||||
|
const currentPlugin = this.areaManager.getPlugin(activeKey);
|
||||||
|
const nextPlugin = this.areaManager.getPlugin(key);
|
||||||
|
const openPlugin = (): void => {
|
||||||
|
if (!nextPlugin) {
|
||||||
|
console.error(`plugin ${key} has not regist in the editor`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nextPlugin.open().then((): void => {
|
||||||
|
this.editor.set('rightNav', key);
|
||||||
|
this.setState({
|
||||||
|
activeKey: key,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (key === activeKey && !isinit) return;
|
||||||
|
if (currentPlugin) {
|
||||||
|
currentPlugin.close().then((): void => {
|
||||||
|
openPlugin();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
openPlugin();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
renderTabTitle = (config: PluginConfig): React.ReactElement => {
|
||||||
|
const { icon, title } = config.props || {};
|
||||||
|
const pluginStatus = this.editor.pluginStatus[config.pluginKey];
|
||||||
|
const { marked, disabled, locked } = pluginStatus;
|
||||||
|
const active = this.state.activeKey === config.pluginKey;
|
||||||
|
|
||||||
|
const renderTitle = (): React.ReactElement => (
|
||||||
|
<div
|
||||||
|
className={classNames('right-plugin-title', {
|
||||||
|
active,
|
||||||
|
locked,
|
||||||
|
disabled,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{!!icon && <Icon size="xs" type={icon} />}
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
if (marked) {
|
||||||
|
return <Badge dot>{renderTitle()}</Badge>;
|
||||||
|
}
|
||||||
|
return renderTitle();
|
||||||
|
};
|
||||||
|
|
||||||
|
renderTabPanels = (list: PluginConfig[], height: string): React.ReactNode => {
|
||||||
|
if (isEmpty(list)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Tab
|
||||||
|
className="right-tabs"
|
||||||
|
style={{
|
||||||
|
height,
|
||||||
|
}}
|
||||||
|
activeKey={this.state.activeKey}
|
||||||
|
lazyLoad={false}
|
||||||
|
onChange={this.handlePluginChange}
|
||||||
|
>
|
||||||
|
{list.map(
|
||||||
|
(item): React.ReactNode => {
|
||||||
|
const Comp = this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
if (Comp) {
|
||||||
|
return (
|
||||||
|
<Tab.Item
|
||||||
|
key={item.pluginKey}
|
||||||
|
title={this.renderTabTitle(item)}
|
||||||
|
disabled={this.editor.pluginStatus[item.pluginKey].disabled}
|
||||||
|
style={{
|
||||||
|
width: `${100 / list.length}%`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Comp
|
||||||
|
editor={this.editor}
|
||||||
|
config={item}
|
||||||
|
{...item.pluginProps}
|
||||||
|
/>
|
||||||
|
</Tab.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
</Tab>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderPanels = (list: PluginConfig[], height: string): React.ReactNode => {
|
||||||
|
return list.map(
|
||||||
|
(item): React.ReactNode => {
|
||||||
|
const Comp = this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
if (Comp) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="right-panel"
|
||||||
|
style={{ height }}
|
||||||
|
key={item.pluginKey}
|
||||||
|
>
|
||||||
|
<Comp editor={this.editor} config={item} {...item.pluginProps} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): React.ReactNode {
|
||||||
|
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 (
|
||||||
|
<div className="lowcode-right-area">
|
||||||
|
{this.renderTabPanels(tabList, height)}
|
||||||
|
{this.renderPanels(panelList, height)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,30 @@
|
|||||||
.lowcode-top-area {
|
.lowcode-top-area {
|
||||||
height: 48px;
|
position: absolute;
|
||||||
background-color: #ffffff;
|
top: 0;
|
||||||
border-bottom: 1px solid #e8ebee;
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background-color: $card-background;
|
||||||
|
border-bottom: 2px solid $color-line1-1;
|
||||||
|
user-select: none;
|
||||||
|
.divider {
|
||||||
|
max-width: 0;
|
||||||
|
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: 0;
|
||||||
|
top: 0;
|
||||||
|
padding: 0 16px;
|
||||||
|
height: 100%;
|
||||||
|
background: $card-background;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,61 +1,81 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { Grid } from '@alifd/next';
|
import { Grid } from '@alifd/next';
|
||||||
|
import Editor, { AreaManager } from '@ali/lowcode-editor-framework';
|
||||||
|
import { PluginConfig } from '@ali/lowcode-editor-framework/lib/definitions';
|
||||||
import TopPlugin from '../../components/TopPlugin';
|
import TopPlugin from '../../components/TopPlugin';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
const { Row, Col } = Grid;
|
const { Row, Col } = Grid;
|
||||||
|
|
||||||
export default class TopArea extends PureComponent {
|
export interface TopAreaProps {
|
||||||
static displayName = 'lowcodeTopArea';
|
editor: Editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TopArea extends PureComponent<TopAreaProps> {
|
||||||
|
static displayName = 'LowcodeTopArea';
|
||||||
|
|
||||||
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
|
private editor: Editor;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.editor = props.editor;
|
this.editor = props.editor;
|
||||||
this.config = this.editor.config.plugins && this.editor.config.plugins.topArea;
|
this.areaManager = new AreaManager(props.editor, 'topArea');
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount(): void {
|
||||||
}
|
this.editor.on('skeleton.update', this.handleSkeletonUpdate);
|
||||||
componentWillUnmount() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePluginStatusChange = () => {};
|
componentWillUnmount(): void {
|
||||||
|
this.editor.off('skeleton.update', this.handleSkeletonUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
renderPluginList = (list = []) => {
|
handleSkeletonUpdate = (): void => {
|
||||||
return list.map((item, idx) => {
|
// 当前区域插件状态改变是更新区域
|
||||||
const isDivider = item.type === 'Divider';
|
if (this.areaManager.isPluginStatusUpdate()) {
|
||||||
|
this.forceUpdate();
|
||||||
return (
|
}
|
||||||
<Col
|
|
||||||
className={isDivider ? 'divider' : ''}
|
|
||||||
key={isDivider ? idx : item.pluginKey}
|
|
||||||
style={{
|
|
||||||
width: (item.props && item.props.width) || 40,
|
|
||||||
flex: 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!isDivider && (
|
|
||||||
<TopPlugin
|
|
||||||
config={item}
|
|
||||||
pluginClass={this.editor.pluginComponents[item.pluginKey]}
|
|
||||||
status={this.editor.pluginStatus[item.pluginKey]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
renderPluginList = (list: PluginConfig[] = []): React.ReactElement[] => {
|
||||||
if (!this.config) return null;
|
return list.map(
|
||||||
const leftList = [];
|
(item, idx): React.ReactElement => {
|
||||||
const rightList = [];
|
const isDivider = item.type === 'Divider';
|
||||||
this.config.forEach(item => {
|
const PluginClass = this.areaManager.getPluginClass(item.pluginKey);
|
||||||
|
return (
|
||||||
|
<Col
|
||||||
|
className={isDivider ? 'divider' : ''}
|
||||||
|
key={isDivider ? idx : item.pluginKey}
|
||||||
|
style={{
|
||||||
|
width: (item.props && item.props.width) || 36,
|
||||||
|
flex: 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!isDivider && (
|
||||||
|
<TopPlugin
|
||||||
|
config={item}
|
||||||
|
pluginClass={PluginClass}
|
||||||
|
editor={this.editor}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): React.ReactNode {
|
||||||
|
const leftList: PluginConfig[] = [];
|
||||||
|
const rightList: PluginConfig[] = [];
|
||||||
|
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
|
visiblePluginList.forEach((item): void => {
|
||||||
const align =
|
const align =
|
||||||
item.props && item.props.align === 'right' ? 'right' : 'left';
|
item.props && item.props.align === 'right' ? 'right' : 'left';
|
||||||
// 分隔符不允许相邻
|
// 分隔符不允许相邻
|
||||||
if (item.type === 'Divider') {
|
if (item.type === 'Divider') {
|
||||||
const currentList = align === 'right' ? rightList : leftList;
|
const currList = align === 'right' ? rightList : leftList;
|
||||||
if (
|
if (
|
||||||
currList.length === 0 ||
|
currList.length === 0 ||
|
||||||
currList[currList.length - 1].type === 'Divider'
|
currList[currList.length - 1].type === 'Divider'
|
||||||
@ -68,11 +88,14 @@ export default class TopArea extends PureComponent {
|
|||||||
leftList.push(item);
|
leftList.push(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="lowcode-top-area">
|
<div className="lowcode-top-area">
|
||||||
<div className="left-area">{this.renderPluginList(leftList)}</div>
|
<div className="left-area">
|
||||||
<div classname="right-area">{this.renderPluginList(rightList)}</div>
|
<Row>{this.renderPluginList(leftList)}</Row>
|
||||||
|
</div>
|
||||||
|
<div className="right-area">
|
||||||
|
<Row justify="end">{this.renderPluginList(rightList)}</Row>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1 @@
|
|||||||
export default {
|
export default {};
|
||||||
loading: 'loading...',
|
|
||||||
rejectRedirect: 'Redirect is not allowed',
|
|
||||||
expand: 'Unfold',
|
|
||||||
fold: 'Fold',
|
|
||||||
pageNotExist: 'The current Page not exist',
|
|
||||||
enterFromAppCenter: 'Please enter from the app center',
|
|
||||||
noPermission: 'Sorry, you do not have the develop permission',
|
|
||||||
getPermission: 'Please connect the app owners {owners} to get the permission',
|
|
||||||
};
|
|
||||||
|
|||||||
@ -1,10 +1 @@
|
|||||||
export default {
|
export default {};
|
||||||
loading: '加载中...',
|
|
||||||
rejectRedirect: '开发中,已阻止发生跳转',
|
|
||||||
expand: '展开',
|
|
||||||
fold: '收起',
|
|
||||||
pageNotExist: '当前访问地址不存在',
|
|
||||||
enterFromAppCenter: '请从应用中心入口重新进入',
|
|
||||||
noPermission: '抱歉,您暂无开发权限',
|
|
||||||
getPermission: '请移步应用中心申请开发权限, 或联系 {owners} 开通权限',
|
|
||||||
};
|
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "低代码编辑器",
|
"description": "低代码编辑器",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-editor-framework": "0.0.1",
|
||||||
|
"@ali/lowcode-editor-skeleton": "0.0.1",
|
||||||
"@ali/iceluna-addon-2": "^1.0.3",
|
"@ali/iceluna-addon-2": "^1.0.3",
|
||||||
"@ali/iceluna-addon-component-list": "^1.0.11",
|
"@ali/iceluna-addon-component-list": "^1.0.11",
|
||||||
"@ali/iceluna-sdk": "^1.0.5-beta.26",
|
"@ali/iceluna-sdk": "^1.0.5-beta.26",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import assets from './assets';
|
|||||||
export default {
|
export default {
|
||||||
version: '^1.0.2',
|
version: '^1.0.2',
|
||||||
theme: {
|
theme: {
|
||||||
dpl: {
|
fusion: {
|
||||||
package: '@alife/dpl-iceluna',
|
package: '@alife/dpl-iceluna',
|
||||||
version: '^2.3.0'
|
version: '^2.3.0'
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
import { createContext } from 'react';
|
|
||||||
|
|
||||||
const context = createContext({});
|
|
||||||
export default context;
|
|
||||||
@ -1,154 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import Editor from './editor';
|
|
||||||
|
|
||||||
export interface EditorConfig {
|
|
||||||
skeleton?: SkeletonConfig;
|
|
||||||
theme?: ThemeConfig;
|
|
||||||
plugins?: PluginsConfig;
|
|
||||||
hooks?: HooksConfig;
|
|
||||||
shortCuts?: ShortCutsConfig;
|
|
||||||
utils?: UtilsConfig;
|
|
||||||
constants?: ConstantsConfig;
|
|
||||||
lifeCycles?: LifeCyclesConfig;
|
|
||||||
i18n?: I18nConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NpmConfig {
|
|
||||||
version: string;
|
|
||||||
package: string;
|
|
||||||
main?: string;
|
|
||||||
exportName?: string;
|
|
||||||
subName?: string;
|
|
||||||
destructuring?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SkeletonConfig {
|
|
||||||
config: NpmConfig;
|
|
||||||
props?: object;
|
|
||||||
handler?: (EditorConfig) => EditorConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FusionTheme {
|
|
||||||
package: string;
|
|
||||||
version: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ThemeConfig {
|
|
||||||
fusion?: FusionTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PluginsConfig {
|
|
||||||
[propName: string]: PluginConfig[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PluginConfig {
|
|
||||||
pluginKey: string;
|
|
||||||
type: string;
|
|
||||||
props: {
|
|
||||||
icon?: string;
|
|
||||||
title?: string;
|
|
||||||
width?: number;
|
|
||||||
height?: number;
|
|
||||||
visible?: boolean;
|
|
||||||
disabled?: boolean;
|
|
||||||
marked?: boolean;
|
|
||||||
align?: 'left' | 'right' | 'top' | 'bottom';
|
|
||||||
onClick?: () => void;
|
|
||||||
dialogProps?: object;
|
|
||||||
balloonProps?: object;
|
|
||||||
panelProps?: object;
|
|
||||||
linkProps?: object;
|
|
||||||
};
|
|
||||||
config?: NpmConfig;
|
|
||||||
pluginProps?: object;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type HooksConfig = HookConfig[];
|
|
||||||
|
|
||||||
export interface HookConfig {
|
|
||||||
message: string;
|
|
||||||
type: 'on' | 'once';
|
|
||||||
handler: (editor: Editor, ...args) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ShortCutsConfig = ShortCutConfig[];
|
|
||||||
|
|
||||||
export interface ShortCutConfig {
|
|
||||||
keyboard: string;
|
|
||||||
handler: (editor: Editor, ev: Event, keymaster: any) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UtilsConfig = UtilConfig[];
|
|
||||||
|
|
||||||
export interface UtilConfig {
|
|
||||||
name: string;
|
|
||||||
type: 'npm' | 'function';
|
|
||||||
content: NpmConfig | ((...args) => any);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ConstantsConfig = object;
|
|
||||||
|
|
||||||
export interface LifeCyclesConfig {
|
|
||||||
init?: (editor: Editor) => any;
|
|
||||||
destroy?: (editor: Editor) => any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type LocaleType = 'zh-CN' | 'zh-TW' | 'en-US' | 'ja-JP';
|
|
||||||
|
|
||||||
export interface I18nMessages {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface I18nConfig {
|
|
||||||
'zh-CN'?: I18nMessages;
|
|
||||||
'zh-TW'?: I18nMessages;
|
|
||||||
'en-US'?: I18nMessages;
|
|
||||||
'ja-JP'?: I18nMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
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<React.ReactElement>;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Plugin = React.ReactNode & {
|
|
||||||
open?: () => boolean | void | Promise<any>;
|
|
||||||
close?: () => boolean | void | Promise<any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type HOCPlugin = React.ReactNode & {
|
|
||||||
open: () => Promise<any>;
|
|
||||||
close: () => Promise<any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface PluginSet {
|
|
||||||
[key: string]: HOCPlugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PluginClass = React.ComponentType<PluginProps> & {
|
|
||||||
init?: (editor: Editor) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface PluginClassSet {
|
|
||||||
[key: string]: PluginClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PluginStatus {
|
|
||||||
disabled?: boolean;
|
|
||||||
visible?: boolean;
|
|
||||||
marked?: boolean;
|
|
||||||
locked?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PluginStatusSet {
|
|
||||||
[key: string]: PluginStatus;
|
|
||||||
}
|
|
||||||
@ -1,230 +0,0 @@
|
|||||||
import Debug from 'debug';
|
|
||||||
import EventEmitter from 'events';
|
|
||||||
import store from 'store';
|
|
||||||
import {
|
|
||||||
EditorConfig,
|
|
||||||
HooksConfig,
|
|
||||||
LocaleType,
|
|
||||||
PluginStatusSet,
|
|
||||||
Utils,
|
|
||||||
PluginClassSet,
|
|
||||||
PluginSet
|
|
||||||
} from './definitions';
|
|
||||||
|
|
||||||
import * as editorUtils from './utils';
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (debugRegRes && debugRegRes[1]) {
|
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重要,用于矫正画布执行new Function的window对象上下文
|
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
|
||||||
window.__newFunc = (funContext: string): ((...args: any[]) => any) => {
|
|
||||||
// eslint-disable-next-line no-new-func
|
|
||||||
return new Function(funContext) as (...args: any[]) => any;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭浏览器前提醒,只有产生过交互才会生效
|
|
||||||
window.onbeforeunload = function(e: Event): string | void {
|
|
||||||
const ev = e || window.event;
|
|
||||||
// 本地调试不生效
|
|
||||||
if (location.href.indexOf('localhost') > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const msg = '您确定要离开此页面吗?';
|
|
||||||
ev.cancelBubble = true;
|
|
||||||
ev.returnValue = true;
|
|
||||||
if (e.stopPropagation) {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
let instance: Editor;
|
|
||||||
|
|
||||||
const debug = Debug('editor');
|
|
||||||
EventEmitter.defaultMaxListeners = 100;
|
|
||||||
|
|
||||||
export interface HooksFuncs {
|
|
||||||
[idx: number]: (msg: string, handler: (...args) => void) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Editor extends EventEmitter {
|
|
||||||
public static getInstance = (config: EditorConfig, components: PluginClassSet, utils?: Utils): Editor => {
|
|
||||||
if (!instance) {
|
|
||||||
instance = new Editor(config, components, utils);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
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(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
|
|
||||||
super();
|
|
||||||
this.config = config;
|
|
||||||
this.components = components;
|
|
||||||
this.utils = { ...editorUtils, ...utils };
|
|
||||||
instance = this;
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(): Promise<any> {
|
|
||||||
const { hooks, shortCuts = [], lifeCycles } = this.config || {};
|
|
||||||
this.locale = store.get('lowcode-editor-locale') || 'zh-CN';
|
|
||||||
// this.messages = this.messagesSet[this.locale];
|
|
||||||
// this.i18n = generateI18n(this.locale, this.messages);
|
|
||||||
this.pluginStatus = this.initPluginStatus();
|
|
||||||
this.initHooks(hooks || []);
|
|
||||||
|
|
||||||
this.emit('editor.beforeInit');
|
|
||||||
const init = (lifeCycles && lifeCycles.init) || ((): void => {});
|
|
||||||
// 用户可以通过设置extensions.init自定义初始化流程;
|
|
||||||
return transformToPromise(init(this))
|
|
||||||
.then((): boolean => {
|
|
||||||
// 注册快捷键
|
|
||||||
registShortCuts(shortCuts, this);
|
|
||||||
this.emit('editor.afterInit');
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.catch((err): void => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public destroy(): void {
|
|
||||||
debug('destroy');
|
|
||||||
try {
|
|
||||||
const { hooks = [], shortCuts = [], lifeCycles = {} } = this.config;
|
|
||||||
unRegistShortCuts(shortCuts);
|
|
||||||
this.destroyHooks(hooks);
|
|
||||||
if (lifeCycles.destroy) {
|
|
||||||
lifeCycles.destroy(this);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.warn(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public get(key: string): any {
|
|
||||||
return this[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
public set(key: string | object, val: any): void {
|
|
||||||
if (typeof key === 'string') {
|
|
||||||
if (['init', 'destroy', 'get', 'set', 'batchOn', 'batchOff', 'batchOnce'].includes(key)) {
|
|
||||||
console.error('init, destroy, get, set, batchOn, batchOff, batchOnce is private attribute');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this[key] = val;
|
|
||||||
} else if (typeof key === 'object') {
|
|
||||||
Object.keys(key).forEach((item): void => {
|
|
||||||
this[item] = key[item];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public batchOn(events: string[], lisenter: (...args) => void): void {
|
|
||||||
if (!Array.isArray(events)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
events.forEach((event): void => this.on(event, lisenter));
|
|
||||||
}
|
|
||||||
|
|
||||||
public batchOnce(events: string[], lisenter: (...args) => void): void {
|
|
||||||
if (!Array.isArray(events)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
events.forEach((event): void => this.once(event, lisenter));
|
|
||||||
}
|
|
||||||
|
|
||||||
public batchOff(events: string[], lisenter: (...args) => void): void {
|
|
||||||
if (!Array.isArray(events)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
events.forEach((event): void => this.off(event, lisenter));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 销毁hooks中的消息监听
|
|
||||||
private destroyHooks(hooks: HooksConfig = []): void {
|
|
||||||
hooks.forEach((item, idx): void => {
|
|
||||||
if (typeof this.hooksFuncs[idx] === 'function') {
|
|
||||||
this.off(item.message, this.hooksFuncs[idx]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
delete this.hooksFuncs;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化hooks中的消息监听
|
|
||||||
private initHooks(hooks: HooksConfig = []): void {
|
|
||||||
this.hooksFuncs = hooks.map((item): ((...arg) => void) => {
|
|
||||||
const func = (...args): void => {
|
|
||||||
item.handler(this, ...args);
|
|
||||||
};
|
|
||||||
this[item.type](item.message, func);
|
|
||||||
return func;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private initPluginStatus(): PluginStatusSet {
|
|
||||||
const { plugins = {} } = this.config;
|
|
||||||
const pluginAreas = Object.keys(plugins);
|
|
||||||
const res: PluginStatusSet = {};
|
|
||||||
pluginAreas.forEach((area): void => {
|
|
||||||
(plugins[area] || []).forEach((plugin): void => {
|
|
||||||
if (plugin.type === 'Divider') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { visible, disabled, marked } = plugin.props || {};
|
|
||||||
res[plugin.pluginKey] = {
|
|
||||||
visible: typeof visible === 'boolean' ? visible : true,
|
|
||||||
disabled: typeof disabled === 'boolean' ? disabled : false,
|
|
||||||
marked: typeof marked === 'boolean' ? marked : false
|
|
||||||
};
|
|
||||||
const pluginClass = this.components[plugin.pluginKey];
|
|
||||||
// 判断如果编辑器插件有init静态方法,则在此执行init方法
|
|
||||||
if (pluginClass && pluginClass.init) {
|
|
||||||
pluginClass.init(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import Editor from './editor';
|
|
||||||
|
|
||||||
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;
|
|
||||||
export const definitions = editorDefinitions;
|
|
||||||
@ -1,272 +0,0 @@
|
|||||||
import IntlMessageFormat from 'intl-messageformat';
|
|
||||||
import keymaster from 'keymaster';
|
|
||||||
|
|
||||||
import _clone from 'lodash/cloneDeep';
|
|
||||||
import _debounce from 'lodash/debounce';
|
|
||||||
import _isEmpty from 'lodash/isEmpty';
|
|
||||||
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;
|
|
||||||
export const isEmpty = _isEmpty;
|
|
||||||
export const throttle = _throttle;
|
|
||||||
export const debounce = _debounce;
|
|
||||||
|
|
||||||
export const serialize = _serialize;
|
|
||||||
|
|
||||||
const ENV = {
|
|
||||||
TBE: 'TBE',
|
|
||||||
WEBIDE: 'WEB-IDE',
|
|
||||||
VSCODE: 'VSCODE',
|
|
||||||
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: {
|
|
||||||
logKey: string;
|
|
||||||
gmKey: string;
|
|
||||||
goKey: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 用于构造国际化字符串处理函数
|
|
||||||
*/
|
|
||||||
export function generateI18n(locale: LocaleType = 'zh-CN', messages: I18nMessages = {}): I18nFunction {
|
|
||||||
return (key: string, values): string => {
|
|
||||||
if (!messages || !messages[key]) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const formater = new IntlMessageFormat(messages[key], locale);
|
|
||||||
return formater.format(values);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 序列化参数
|
|
||||||
*/
|
|
||||||
export function serializeParams(obj: object): string {
|
|
||||||
if (typeof obj !== 'object') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const res: string[] = [];
|
|
||||||
Object.entries(obj).forEach(([key, val]): void => {
|
|
||||||
if (val === null || val === undefined || val === '') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof val === 'object') {
|
|
||||||
res.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}`);
|
|
||||||
} else {
|
|
||||||
res.push(`${encodeURIComponent(key)}=${encodeURIComponent(val)}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return res.join('&');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 黄金令箭埋点
|
|
||||||
* @param {String} gmKey 为黄金令箭业务类型
|
|
||||||
* @param {Object} params 参数
|
|
||||||
* @param {String} logKey 属性串
|
|
||||||
*/
|
|
||||||
export function goldlog(gmKey: string, params: object = {}, logKey: string = 'other'): void {
|
|
||||||
const sendIDEMessage = window.sendIDEMessage || window.parent.sendIDEMessage;
|
|
||||||
const goKey = serializeParams({
|
|
||||||
env: getEnv(),
|
|
||||||
...params
|
|
||||||
});
|
|
||||||
if (sendIDEMessage) {
|
|
||||||
sendIDEMessage({
|
|
||||||
action: 'goldlog',
|
|
||||||
data: {
|
|
||||||
logKey: `/iceluna.core.${logKey}`,
|
|
||||||
gmKey,
|
|
||||||
goKey
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (window.goldlog) {
|
|
||||||
window.goldlog.record(`/iceluna.core.${logKey}`, gmKey, goKey, 'POST');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前编辑器环境
|
|
||||||
*/
|
|
||||||
export function getEnv(): string {
|
|
||||||
const userAgent = navigator.userAgent;
|
|
||||||
const isVscode = /Electron\//.test(userAgent);
|
|
||||||
if (isVscode) {
|
|
||||||
return ENV.VSCODE;
|
|
||||||
}
|
|
||||||
const isTheia = window.is_theia === true;
|
|
||||||
if (isTheia) {
|
|
||||||
return ENV.WEBIDE;
|
|
||||||
}
|
|
||||||
return ENV.WEB;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册快捷键
|
|
||||||
export function registShortCuts(config: ShortCutsConfig, editor: Editor): void {
|
|
||||||
(config || []).forEach((item): void => {
|
|
||||||
keymaster(item.keyboard, (ev: Event): void => {
|
|
||||||
ev.preventDefault();
|
|
||||||
item.handler(editor, ev, keymaster);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取消注册快捷
|
|
||||||
export function unRegistShortCuts(config: ShortCutsConfig): void {
|
|
||||||
(config || []).forEach((item): void => {
|
|
||||||
keymaster.unbind(item.keyboard);
|
|
||||||
});
|
|
||||||
if (window.parent.vscode) {
|
|
||||||
keymaster.unbind('command+c');
|
|
||||||
keymaster.unbind('command+v');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将函数返回结果转成promise形式,如果函数有返回值则根据返回值的bool类型判断是reject还是resolve,若函数无返回值默认执行resolve
|
|
||||||
*/
|
|
||||||
export function transformToPromise(input: any): Promise<{}> {
|
|
||||||
if (input instanceof Promise) {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject): void => {
|
|
||||||
if (input || input === undefined) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将数组类型转换为Map类型
|
|
||||||
*/
|
|
||||||
interface MapOf<T> {
|
|
||||||
[propName: string]: T;
|
|
||||||
}
|
|
||||||
export function transformArrayToMap<T>(arr: T[], key: string, overwrite: boolean = true): MapOf<T> {
|
|
||||||
if (isEmpty(arr) || !Array.isArray(arr)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const res = {};
|
|
||||||
arr.forEach((item): void => {
|
|
||||||
const curKey = item[key];
|
|
||||||
if (item[key] === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (res[curKey] && !overwrite) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res[curKey] = item;
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析url的查询参数
|
|
||||||
*/
|
|
||||||
interface Query {
|
|
||||||
[propName: string]: string;
|
|
||||||
}
|
|
||||||
export function parseSearch(search: string): Query {
|
|
||||||
if (!search || typeof search !== 'string') {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const str = search.replace(/^\?/, '');
|
|
||||||
const paramStr = str.split('&');
|
|
||||||
const res = {};
|
|
||||||
paramStr.forEach((item): void => {
|
|
||||||
const regRes = item.split('=');
|
|
||||||
if (regRes[0] && regRes[1]) {
|
|
||||||
res[regRes[0]] = decodeURIComponent(regRes[1]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function comboEditorConfig(defaultConfig: EditorConfig = {}, customConfig: EditorConfig): EditorConfig {
|
|
||||||
const { skeleton, theme, plugins, hooks, shortCuts, lifeCycles, constants, utils, i18n } = customConfig || {};
|
|
||||||
|
|
||||||
if (skeleton && skeleton.handler && typeof skeleton.handler === 'function') {
|
|
||||||
return skeleton.handler({
|
|
||||||
skeleton,
|
|
||||||
...defaultConfig
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultShortCuts = transformArrayToMap(defaultConfig.shortCuts || [], 'keyboard');
|
|
||||||
const customShortCuts = transformArrayToMap(shortCuts || [], 'keyboard');
|
|
||||||
const localeList = ['zh-CN', 'zh-TW', 'en-US', 'ja-JP'];
|
|
||||||
const i18nConfig = {};
|
|
||||||
localeList.forEach((key): void => {
|
|
||||||
i18nConfig[key] = {
|
|
||||||
...(defaultConfig.i18n && defaultConfig.i18n[key]),
|
|
||||||
...(i18n && i18n[key])
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
skeleton,
|
|
||||||
theme: {
|
|
||||||
...defaultConfig.theme,
|
|
||||||
...theme
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
...defaultConfig.plugins,
|
|
||||||
...plugins
|
|
||||||
},
|
|
||||||
hooks: [...(defaultConfig.hooks || []), ...(hooks || [])],
|
|
||||||
shortCuts: Object.values({
|
|
||||||
...defaultShortCuts,
|
|
||||||
...customShortCuts
|
|
||||||
}),
|
|
||||||
lifeCycles: {
|
|
||||||
...defaultConfig.lifeCycles,
|
|
||||||
...lifeCycles
|
|
||||||
},
|
|
||||||
constants: {
|
|
||||||
...defaultConfig.constants,
|
|
||||||
...constants
|
|
||||||
},
|
|
||||||
utils: [...(defaultConfig.utils || []), ...(utils || [])],
|
|
||||||
i18n: i18nConfig
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断当前组件是否能够设置ref
|
|
||||||
* @param {*} Comp 需要判断的组件
|
|
||||||
*/
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
8
packages/editor/src/index.d.ts
vendored
8
packages/editor/src/index.d.ts
vendored
@ -1,8 +0,0 @@
|
|||||||
interface Window {
|
|
||||||
sendIDEMessage?: (IDEMessageParams) => void;
|
|
||||||
goldlog?: {
|
|
||||||
record: (logKey: string, gmKey: string, goKey: string, method: 'GET' | 'POST') => void;
|
|
||||||
};
|
|
||||||
is_theia?: boolean;
|
|
||||||
vscode?: boolean;
|
|
||||||
}
|
|
||||||
@ -1,12 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
// import Skeleton from '@ali/lowcode-engine-skeleton';
|
import Skeleton from '@ali/lowcode-editor-skeleton';
|
||||||
import { HashRouter as Router, Route } from 'react-router-dom';
|
|
||||||
import Skeleton from './skeleton';
|
|
||||||
import config from './config/skeleton';
|
import config from './config/skeleton';
|
||||||
import components from './config/components';
|
import components from './config/components';
|
||||||
import utils from './config/utils';
|
import utils from './config/utils';
|
||||||
import constants from './config/constants';
|
|
||||||
import './config/locale';
|
import './config/locale';
|
||||||
import './config/setters';
|
import './config/setters';
|
||||||
|
|
||||||
@ -19,21 +16,6 @@ if (!ICE_CONTAINER) {
|
|||||||
throw new Error('当前页面不存在 <div id="ice-container"></div> 节点.');
|
throw new Error('当前页面不存在 <div id="ice-container"></div> 节点.');
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(<Skeleton config={config} utils={utils} components={components}/>,
|
||||||
<Router>
|
|
||||||
<Route
|
|
||||||
path="/*"
|
|
||||||
component={(props): React.ReactNode => (
|
|
||||||
<Skeleton
|
|
||||||
{...props}
|
|
||||||
{...(config.skeleton && config.skeleton.props)}
|
|
||||||
config={config}
|
|
||||||
utils={utils}
|
|
||||||
constants={constants}
|
|
||||||
components={components}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Router>,
|
|
||||||
ICE_CONTAINER
|
ICE_CONTAINER
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,54 +0,0 @@
|
|||||||
.lowcode-left-plugin {
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 44px;
|
|
||||||
height: 44px;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
color: $color-text1-3;
|
|
||||||
&.locked {
|
|
||||||
color: red !important;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
color: $color-brand1-6;
|
|
||||||
&:before {
|
|
||||||
content: attr(data-tooltip);
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
left: 50px;
|
|
||||||
top: 5px;
|
|
||||||
line-height: 18px;
|
|
||||||
font-size: 12px;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 6px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: $balloon-tooltip-color-bg;
|
|
||||||
color: $color-text1-3;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
&:after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
left: 40px;
|
|
||||||
top: 15px;
|
|
||||||
border: 5px solid transparent;
|
|
||||||
border-right: 5px solid $balloon-tooltip-color-bg;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.active {
|
|
||||||
color: $color-brand1-9;
|
|
||||||
&.disabled {
|
|
||||||
color: $color-text1-1;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
color: $color-brand1-6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
color: $color-text1-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,210 +0,0 @@
|
|||||||
import React, { PureComponent, Fragment } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { Balloon, Dialog, Icon, Badge } from '@alifd/next';
|
|
||||||
|
|
||||||
import './index.scss';
|
|
||||||
import Editor from '../../../framework/editor';
|
|
||||||
import { PluginConfig, PluginClass } from '../../../framework/definitions';
|
|
||||||
|
|
||||||
export interface LeftPluginProps {
|
|
||||||
active?: boolean;
|
|
||||||
config: PluginConfig;
|
|
||||||
disabled?: boolean;
|
|
||||||
editor: Editor;
|
|
||||||
locked?: boolean;
|
|
||||||
marked?: boolean;
|
|
||||||
onClick?: () => void;
|
|
||||||
pluginClass: PluginClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LeftPluginState {
|
|
||||||
dialogVisible: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class LeftPlugin extends PureComponent<LeftPluginProps, LeftPluginState> {
|
|
||||||
static displayName = 'LowcodeLeftPlugin';
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
active: false,
|
|
||||||
config: {},
|
|
||||||
disabled: false,
|
|
||||||
marked: false,
|
|
||||||
locked: false,
|
|
||||||
onClick: (): void => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
this.state = {
|
|
||||||
dialogVisible: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount(): void {
|
|
||||||
const { config, editor } = this.props;
|
|
||||||
const pluginKey = config && config.pluginKey;
|
|
||||||
if (editor && pluginKey) {
|
|
||||||
editor.on(`${pluginKey}.dialog.show`, this.handleShow);
|
|
||||||
editor.on(`${pluginKey}.dialog.close`, this.handleClose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
|
||||||
const { config, editor } = this.props;
|
|
||||||
const pluginKey = config && config.pluginKey;
|
|
||||||
if (editor && pluginKey) {
|
|
||||||
editor.off(`${pluginKey}.dialog.show`, this.handleShow);
|
|
||||||
editor.off(`${pluginKey}.dialog.close`, this.handleClose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClose = (): void => {
|
|
||||||
const { config, editor } = this.props;
|
|
||||||
const pluginKey = config && config.pluginKey;
|
|
||||||
const plugin = editor.plugins && editor.plugins[pluginKey];
|
|
||||||
if (plugin && plugin.close) {
|
|
||||||
plugin.close().then((): void => {
|
|
||||||
this.setState({
|
|
||||||
dialogVisible: false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleOpen = (): void => {
|
|
||||||
// todo 对话框类型的插件初始时拿不到插件实例
|
|
||||||
this.setState({
|
|
||||||
dialogVisible: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleShow = (): void => {
|
|
||||||
const { disabled, config, onClick, editor } = this.props;
|
|
||||||
const pluginKey = config && config.pluginKey;
|
|
||||||
if (disabled || !pluginKey) return;
|
|
||||||
// 考虑到弹窗情况,延时发送消息
|
|
||||||
setTimeout((): void => editor.emit(`${pluginKey}.plugin.activate`), 0);
|
|
||||||
this.handleOpen();
|
|
||||||
if (onClick) {
|
|
||||||
onClick();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
renderIcon = (clickCallback): React.ReactNode => {
|
|
||||||
const { active, disabled, marked, locked, onClick, config } = this.props;
|
|
||||||
const { pluginKey, props } = config || {};
|
|
||||||
const { icon, title } = props || {};
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames('lowcode-left-plugin', pluginKey, {
|
|
||||||
active,
|
|
||||||
disabled,
|
|
||||||
locked
|
|
||||||
})}
|
|
||||||
data-tooltip={title}
|
|
||||||
onClick={(): void => {
|
|
||||||
if (disabled) return;
|
|
||||||
// 考虑到弹窗情况,延时发送消息
|
|
||||||
clickCallback && clickCallback();
|
|
||||||
|
|
||||||
onClick && onClick();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{marked ? (
|
|
||||||
<Badge dot>
|
|
||||||
<Icon type={icon} size="small" />
|
|
||||||
</Badge>
|
|
||||||
) : (
|
|
||||||
<Icon type={icon} size="small" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
render(): React.ReactNode {
|
|
||||||
const { marked, locked, active, disabled, config, editor, pluginClass: Comp } = this.props;
|
|
||||||
const { pluginKey, props, type, pluginProps } = config || {};
|
|
||||||
const { onClick, title } = props || {};
|
|
||||||
const { dialogVisible } = this.state;
|
|
||||||
if (!pluginKey || !type || !props) return null;
|
|
||||||
|
|
||||||
const node =
|
|
||||||
(Comp && (
|
|
||||||
<Comp
|
|
||||||
editor={editor}
|
|
||||||
active={active}
|
|
||||||
locked={locked}
|
|
||||||
disabled={disabled}
|
|
||||||
config={config}
|
|
||||||
onClick={(): void => {
|
|
||||||
onClick && onClick.call(null, editor);
|
|
||||||
}}
|
|
||||||
{...pluginProps}
|
|
||||||
/>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'LinkIcon':
|
|
||||||
return (
|
|
||||||
<a {...(props.linkProps || {})}>
|
|
||||||
{this.renderIcon((): void => {
|
|
||||||
onClick && onClick.call(null, editor);
|
|
||||||
})}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
case 'Icon':
|
|
||||||
return this.renderIcon((): void => {
|
|
||||||
onClick && onClick.call(null, editor);
|
|
||||||
});
|
|
||||||
case 'DialogIcon':
|
|
||||||
return (
|
|
||||||
<Fragment>
|
|
||||||
{this.renderIcon((): void => {
|
|
||||||
onClick && onClick.call(null, editor);
|
|
||||||
this.handleOpen();
|
|
||||||
})}
|
|
||||||
<Dialog
|
|
||||||
onOk={(): void => {
|
|
||||||
editor.emit(`${pluginKey}.dialog.onOk`);
|
|
||||||
this.handleClose();
|
|
||||||
}}
|
|
||||||
onCancel={this.handleClose}
|
|
||||||
onClose={this.handleClose}
|
|
||||||
title={title}
|
|
||||||
style={{
|
|
||||||
width: 500,
|
|
||||||
...(props.dialogProps && props.dialogProps.style)
|
|
||||||
}}
|
|
||||||
{...(props.dialogProps || {})}
|
|
||||||
visible={dialogVisible}
|
|
||||||
>
|
|
||||||
{node}
|
|
||||||
</Dialog>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
case 'BalloonIcon':
|
|
||||||
return (
|
|
||||||
<Balloon
|
|
||||||
trigger={this.renderIcon((): void => {
|
|
||||||
onClick && onClick.call(null, editor);
|
|
||||||
})}
|
|
||||||
align="r"
|
|
||||||
triggerType={['click', 'hover']}
|
|
||||||
{...(props.balloonProps || {})}
|
|
||||||
>
|
|
||||||
{node}
|
|
||||||
</Balloon>
|
|
||||||
);
|
|
||||||
case 'PanelIcon':
|
|
||||||
return this.renderIcon((): void => {
|
|
||||||
onClick && onClick.call(null, editor);
|
|
||||||
this.handleOpen();
|
|
||||||
});
|
|
||||||
case 'Custom':
|
|
||||||
return marked ? <Badge dot>{node}</Badge> : node;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
export interface PanelProps {
|
|
||||||
align: 'left' | 'right';
|
|
||||||
defaultWidth: number;
|
|
||||||
minWidth: number;
|
|
||||||
draggable: boolean;
|
|
||||||
floatable: boolean;
|
|
||||||
children: Plugin;
|
|
||||||
visible: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PanelState {
|
|
||||||
width: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Panel extends PureComponent<PanelProps, PanelState> {
|
|
||||||
static displayName = 'LowcodePanel';
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
align: 'left',
|
|
||||||
defaultWidth: 240,
|
|
||||||
minWidth: 100,
|
|
||||||
draggable: true,
|
|
||||||
floatable: false,
|
|
||||||
visible: true
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
width: props.defaultWidth
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): React.ReactNode {
|
|
||||||
const { align, draggable, floatable, visible } = this.props;
|
|
||||||
const { width } = this.state;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames('lowcode-panel', align, {
|
|
||||||
draggable,
|
|
||||||
floatable,
|
|
||||||
visible
|
|
||||||
})}
|
|
||||||
style={{
|
|
||||||
width,
|
|
||||||
display: visible ? '' : 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{this.props.children}
|
|
||||||
<div className="drag-area" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
.lowcode-top-icon {
|
|
||||||
display: inline-block;
|
|
||||||
width: 44px;
|
|
||||||
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 {
|
|
||||||
color: $color-brand1-6;
|
|
||||||
&:before {
|
|
||||||
content: attr(data-tooltip);
|
|
||||||
display: block;
|
|
||||||
height: auto;
|
|
||||||
width: auto;
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, 0);
|
|
||||||
bottom: -35px;
|
|
||||||
line-height: 18px;
|
|
||||||
font-size: 12px;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 6px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: $balloon-tooltip-color-bg;
|
|
||||||
color: $color-text1-3;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
&:after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, 0);
|
|
||||||
bottom: -5px;
|
|
||||||
border: 5px solid transparent;
|
|
||||||
border-bottom-color: $balloon-tooltip-color-bg;
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i.next-icon {
|
|
||||||
&:before {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
margin-right: 0;
|
|
||||||
line-height: 18px;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
display: block;
|
|
||||||
margin: 0px -5px 0;
|
|
||||||
line-height: 16px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px;
|
|
||||||
transform: scale(0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { Icon } from '@alifd/next';
|
|
||||||
|
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
export interface TopIconProps {
|
|
||||||
active?: boolean;
|
|
||||||
className?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
icon: string;
|
|
||||||
id?: string;
|
|
||||||
locked?: boolean;
|
|
||||||
marked?: boolean;
|
|
||||||
onClick?: () => void;
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
title?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class TopIcon extends PureComponent<TopIconProps> {
|
|
||||||
static displayName = 'LowcodeTopIcon';
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
active: false,
|
|
||||||
className: '',
|
|
||||||
disabled: false,
|
|
||||||
icon: '',
|
|
||||||
id: '',
|
|
||||||
locked: false,
|
|
||||||
onClick: (): void => {},
|
|
||||||
style: {},
|
|
||||||
title: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
render(): React.ReactNode {
|
|
||||||
const { active, disabled, icon, locked, title, className, id, style, onClick } = this.props;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames('lowcode-top-icon', className, {
|
|
||||||
active,
|
|
||||||
disabled,
|
|
||||||
locked
|
|
||||||
})}
|
|
||||||
data-tooltip={title}
|
|
||||||
id={id}
|
|
||||||
style={style}
|
|
||||||
onClick={disabled ? undefined : onClick}
|
|
||||||
>
|
|
||||||
<Icon type={icon} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user