diff --git a/.gitignore b/.gitignore
index 39e7cc176..aea751e5b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
+# package-lock.json
# Runtime data
pids
diff --git a/packages/editor/.editorconfig b/packages/demo/.editorconfig
similarity index 100%
rename from packages/editor/.editorconfig
rename to packages/demo/.editorconfig
diff --git a/packages/editor/.eslintignore b/packages/demo/.eslintignore
similarity index 100%
rename from packages/editor/.eslintignore
rename to packages/demo/.eslintignore
diff --git a/packages/editor/.eslintrc.js b/packages/demo/.eslintrc.js
similarity index 100%
rename from packages/editor/.eslintrc.js
rename to packages/demo/.eslintrc.js
diff --git a/packages/editor/.gitignore b/packages/demo/.gitignore
similarity index 100%
rename from packages/editor/.gitignore
rename to packages/demo/.gitignore
diff --git a/packages/editor/.prettierrc b/packages/demo/.prettierrc
similarity index 100%
rename from packages/editor/.prettierrc
rename to packages/demo/.prettierrc
diff --git a/packages/editor/.stylelintignore b/packages/demo/.stylelintignore
similarity index 100%
rename from packages/editor/.stylelintignore
rename to packages/demo/.stylelintignore
diff --git a/packages/editor/.stylelintrc.js b/packages/demo/.stylelintrc.js
similarity index 100%
rename from packages/editor/.stylelintrc.js
rename to packages/demo/.stylelintrc.js
diff --git a/packages/editor/README.md b/packages/demo/README.md
similarity index 100%
rename from packages/editor/README.md
rename to packages/demo/README.md
diff --git a/packages/editor/abc.json b/packages/demo/abc.json
similarity index 100%
rename from packages/editor/abc.json
rename to packages/demo/abc.json
diff --git a/packages/editor/ice.config.js b/packages/demo/ice.config.js
similarity index 100%
rename from packages/editor/ice.config.js
rename to packages/demo/ice.config.js
diff --git a/packages/editor/jsconfig.json b/packages/demo/jsconfig.json
similarity index 100%
rename from packages/editor/jsconfig.json
rename to packages/demo/jsconfig.json
diff --git a/packages/editor/package.json b/packages/demo/package.json
similarity index 84%
rename from packages/editor/package.json
rename to packages/demo/package.json
index c9864f35f..42a8da6a9 100644
--- a/packages/editor/package.json
+++ b/packages/demo/package.json
@@ -3,11 +3,14 @@
"version": "0.0.1",
"description": "低代码编辑器",
"dependencies": {
- "@ali/iceluna-addon-2": "^1.0.3",
- "@ali/iceluna-addon-component-list": "^1.0.11",
- "@ali/iceluna-sdk": "^1.0.5-beta.26",
+ "@ali/lowcode-editor-core": "0.0.1",
+ "@ali/lowcode-editor-skeleton": "0.0.1",
+ "@ali/lowcode-plugin-logo": "0.0.1",
+ "@ali/lowcode-plugin-undo-redo": "0.0.1",
+ "@ali/lowcode-plugin-save": "0.0.1",
+ "@ali/lowcode-plugin-designer": "0.0.1",
+ "@ali/lowcode-plugin-components-pane": "0.0.1",
"@alifd/next": "^1.x",
- "@alife/dpl-iceluna": "^2.3.2",
"@alife/theme-lowcode-dark": "^0.1.0",
"@alife/theme-lowcode-light": "^0.1.0",
"@icedesign/theme": "^1.x",
diff --git a/packages/demo/public/assets.json b/packages/demo/public/assets.json
new file mode 100644
index 000000000..7d86b9ed3
--- /dev/null
+++ b/packages/demo/public/assets.json
@@ -0,0 +1,1589 @@
+{
+ "version": "1.0.0",
+ "packages": {
+ "@alifd/next": {
+ "title": "fusion组件库",
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "urls": ["https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.js", "https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.css"],
+ "library": "Next"
+ }
+ },
+ "components": {
+ "Page": {
+ "componentName": "Page",
+ "title": "页面",
+ "configure": {
+ "events": {
+ "supportedLifecycles": [{
+ "description": "初始化时",
+ "name": "constructor"
+ }, {
+ "description": "装载后",
+ "name": "componentDidMount"
+ }, {
+ "description": "更新时",
+ "name": "componentDidMount"
+ }, {
+ "description": "卸载时",
+ "name": "componentWillUnmount"
+ }]
+ },
+ "component": {
+ "isContainer": true
+ }
+ }
+ },
+ "Div": {
+ "componentName": "Div",
+ "title": "容器",
+ "configure": {
+ "component": {
+ "isContainer": true
+ }
+ }
+ },
+ "Button": {
+ "componentName": "Button",
+ "title": "按钮",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "Button"
+ },
+ "props": [{
+ "name": "prefix",
+ "propType": "string",
+ "defaultValue": "next-"
+ }, {
+ "name": "rtl",
+ "propType": "bool"
+ }, {
+ "name": "type",
+ "propType": {
+ "type": "oneOf",
+ "value": ["primary", "secondary", "normal"]
+ },
+ "description": "按钮的类型",
+ "defaultValue": "normal"
+ }, {
+ "name": "size",
+ "propType": {
+ "type": "oneOf",
+ "value": ["small", "medium", "large"]
+ },
+ "description": "按钮的尺寸",
+ "defaultValue": "medium"
+ }, {
+ "name": "iconSize",
+ "propType": {
+ "type": "oneOf",
+ "value": ["xxs", "xs", "small", "medium", "large", "xl", "xxl", "xxxl"]
+ },
+ "description": "按钮中 Icon 的尺寸,用于替代 Icon 的默认大小"
+ }, {
+ "name": "htmlType",
+ "propType": {
+ "type": "oneOf",
+ "value": ["submit", "reset", "button"]
+ },
+ "description": "当 component = 'button' 时,设置 button 标签的 type 值",
+ "defaultValue": "button"
+ }, {
+ "name": "component",
+ "propType": {
+ "type": "oneOf",
+ "value": ["button", "a", "div", "span"]
+ },
+ "description": "设置标签类型",
+ "defaultValue": "button"
+ }, {
+ "name": "loading",
+ "propType": "bool",
+ "description": "设置按钮的载入状态",
+ "defaultValue": false
+ }, {
+ "name": "ghost",
+ "propType": {
+ "type": "oneOf",
+ "value": [true, false, "light", "dark"]
+ },
+ "description": "是否为幽灵按钮",
+ "defaultValue": false
+ }, {
+ "name": "text",
+ "propType": "bool",
+ "description": "是否为文本按钮",
+ "defaultValue": false
+ }, {
+ "name": "warning",
+ "propType": "bool",
+ "description": "是否为警告按钮",
+ "defaultValue": false
+ }, {
+ "name": "disabled",
+ "propType": "bool",
+ "description": "是否禁用",
+ "defaultValue": false
+ }, {
+ "name": "onClick",
+ "propType": "func",
+ "description": "点击按钮的回调\n@param {Object} e Event Object"
+ }, {
+ "name": "className",
+ "propType": "string"
+ }, {
+ "name": "onMouseUp",
+ "propType": "func"
+ }, {
+ "name": "children",
+ "propType": "node"
+ }]
+ },
+ "Button.Group": {
+ "componentName": "Button.Group",
+ "title": "按钮组",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "Button",
+ "subName": "Group"
+ },
+ "props": [{
+ "name": "rtl",
+ "propType": "bool"
+ }, {
+ "name": "prefix",
+ "propType": "string",
+ "defaultValue": "next-"
+ }, {
+ "name": "size",
+ "propType": "string",
+ "description": "统一设置 Button 组件的按钮大小",
+ "defaultValue": "medium"
+ }, {
+ "name": "className",
+ "propType": "string"
+ }, {
+ "name": "children",
+ "propType": "node"
+ }],
+ "configure": {
+ "component": {
+ "isContainer": true,
+ "nestingRule": {
+ "childWhitelist": "Button"
+ }
+ }
+ }
+ },
+ "Input": {
+ "componentName": "Input",
+ "title": "输入框",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "Input"
+ },
+ "props": [{
+ "name": "label",
+ "propType": "node",
+ "description": "label"
+ }, {
+ "name": "hasClear",
+ "propType": "bool",
+ "description": "是否出现clear按钮"
+ }, {
+ "name": "hasBorder",
+ "propType": "bool",
+ "description": "是否有边框",
+ "defaultValue": "true"
+ }, {
+ "name": "state",
+ "propType": {
+ "type": "oneOf",
+ "value": ["error", "loading", "success", "warning"]
+ },
+ "description": "状态\n@enumdesc 错误, 校验中, 成功, 警告"
+ }, {
+ "name": "size",
+ "propType": {
+ "type": "oneOf",
+ "value": ["small", "medium", "large"]
+ },
+ "description": "尺寸\n@enumdesc 小, 中, 大",
+ "defaultValue": "medium"
+ }, {
+ "name": "onPressEnter",
+ "propType": "func",
+ "description": "按下回车的回调",
+ "defaultValue": "func.noop"
+ }, {
+ "name": "onClear",
+ "propType": "func"
+ }, {
+ "name": "htmlType",
+ "propType": "string",
+ "description": "原生type"
+ }, {
+ "name": "htmlSize",
+ "propType": "string"
+ }, {
+ "name": "hint",
+ "propType": "string",
+ "description": "水印 (Icon的type类型,和hasClear占用一个地方)"
+ }, {
+ "name": "innerBefore",
+ "propType": "node",
+ "description": "文字前附加内容"
+ }, {
+ "name": "innerAfter",
+ "propType": "node",
+ "description": "文字后附加内容"
+ }, {
+ "name": "addonBefore",
+ "propType": "node",
+ "description": "输入框前附加内容"
+ }, {
+ "name": "addonAfter",
+ "propType": "node",
+ "description": "输入框后附加内容"
+ }, {
+ "name": "addonTextBefore",
+ "propType": "node",
+ "description": "输入框前附加文字"
+ }, {
+ "name": "addonTextAfter",
+ "propType": "node",
+ "description": "输入框后附加文字"
+ }, {
+ "name": "autoComplete",
+ "propType": "string",
+ "description": "(原生input支持)",
+ "defaultValue": "off"
+ }, {
+ "name": "autoFocus",
+ "propType": "bool",
+ "description": "自动聚焦(原生input支持)"
+ }, {
+ "name": "inputRender",
+ "propType": "func",
+ "defaultValue": "el => el"
+ }, {
+ "name": "extra",
+ "propType": "node"
+ }, {
+ "name": "innerBeforeClassName",
+ "propType": "string"
+ }, {
+ "name": "innerAfterClassName",
+ "propType": "string"
+ }, {
+ "name": "isPreview",
+ "propType": "bool",
+ "description": "是否为预览态",
+ "defaultValue": "false"
+ }, {
+ "name": "renderPreview",
+ "propType": "func",
+ "description": "预览态模式下渲染的内容\n@param {number} value 评分值"
+ }]
+ },
+ "Form": {
+ "componentName": "Form",
+ "title": "表单容器",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "Form"
+ },
+ "props": [{
+ "name": "prefix",
+ "propType": "string",
+ "description": "样式前缀",
+ "defaultValue": "next-"
+ }, {
+ "name": "inline",
+ "propType": "bool",
+ "description": "内联表单"
+ }, {
+ "name": "size",
+ "propType": {
+ "type": "oneOf",
+ "value": ["large", "medium", "small"]
+ },
+ "description": "单个 Item 的 size 自定义,优先级高于 Form 的 size, 并且当组件与 Item 一起使用时,组件自身设置 size 属性无效。\n@enumdesc 大, 中, 小",
+ "defaultValue": "medium"
+ }, {
+ "name": "fullWidth",
+ "propType": "bool",
+ "description": "单个 Item 中表单类组件宽度是否是100%"
+ }, {
+ "name": "labelAlign",
+ "propType": {
+ "type": "oneOf",
+ "value": ["top", "left", "inset"]
+ },
+ "description": "标签的位置\n@enumdesc 上, 左, 内",
+ "defaultValue": "left"
+ }, {
+ "name": "labelTextAlign",
+ "propType": {
+ "type": "oneOf",
+ "value": ["left", "right"]
+ },
+ "description": "标签的左右对齐方式\n@enumdesc 左, 右"
+ }, {
+ "name": "field",
+ "propType": "any",
+ "description": "field 实例, 传 false 会禁用 field"
+ }, {
+ "name": "saveField",
+ "propType": "func",
+ "description": "保存 Form 自动生成的 field 对象"
+ }, {
+ "name": "labelCol",
+ "propType": "object",
+ "description": "控制第一级 Item 的 labelCol"
+ }, {
+ "name": "wrapperCol",
+ "propType": "object",
+ "description": "控制第一级 Item 的 wrapperCol"
+ }, {
+ "name": "onSubmit",
+ "propType": "func",
+ "description": "form内有 `htmlType=\"submit\"` 的元素的时候会触发"
+ }, {
+ "name": "children",
+ "propType": "any",
+ "description": "子元素"
+ }, {
+ "name": "className",
+ "propType": "string",
+ "description": "扩展class"
+ }, {
+ "name": "style",
+ "propType": "object",
+ "description": "自定义内联样式"
+ }, {
+ "name": "value",
+ "propType": "object",
+ "description": "表单数值"
+ }, {
+ "name": "onChange",
+ "propType": "func",
+ "description": "表单变化回调\n@param {Object} values 表单数据\n@param {Object} item 详细\n@param {String} item.name 变化的组件名\n@param {String} item.value 变化的数据\n@param {Object} item.field field 实例"
+ }, {
+ "name": "component",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "func"]
+ },
+ "description": "设置标签类型",
+ "defaultValue": "form"
+ }, {
+ "name": "fieldOptions",
+ "propType": "object"
+ }, {
+ "name": "rtl",
+ "propType": "bool"
+ }, {
+ "name": "device",
+ "propType": {
+ "type": "oneOf",
+ "value": ["phone", "tablet", "desktop"]
+ },
+ "description": "预设屏幕宽度",
+ "defaultValue": "desktop"
+ }, {
+ "name": "responsive",
+ "propType": "bool",
+ "description": "是否开启内置的响应式布局 (使用ResponsiveGrid)"
+ }, {
+ "name": "isPreview",
+ "propType": "bool",
+ "description": "是否开启预览态"
+ }],
+ "configure": {
+ "component": {
+ "isContainer": true
+ }
+ }
+ },
+ "Form.Item": {
+ "componentName": "Form.Item",
+ "title": "表单项",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "Form",
+ "subName": "Item"
+ },
+ "props": [{
+ "name": "prefix",
+ "propType": "string",
+ "description": "样式前缀",
+ "defaultValue": "next-"
+ }, {
+ "name": "rtl",
+ "propType": "bool"
+ }, {
+ "name": "label",
+ "propType": "node",
+ "description": "label 标签的文本"
+ }, {
+ "name": "labelCol",
+ "propType": "object",
+ "description": "label 标签布局,通 `
` 组件,设置 span offset 值,如 {span: 8, offset: 16},该项仅在垂直表单有效"
+ }, {
+ "name": "wrapperCol",
+ "propType": "object",
+ "description": "需要为输入控件设置布局样式时,使用该属性,用法同 labelCol"
+ }, {
+ "name": "help",
+ "propType": "node",
+ "description": "自定义提示信息,如不设置,则会根据校验规则自动生成."
+ }, {
+ "name": "extra",
+ "propType": "node",
+ "description": "额外的提示信息,和 help 类似,当需要错误信息和提示文案同时出现时,可以使用这个。 位于错误信息后面"
+ }, {
+ "name": "validateState",
+ "propType": {
+ "type": "oneOf",
+ "value": ["error", "success", "loading", "warning"]
+ },
+ "description": "校验状态,如不设置,则会根据校验规则自动生成\n@enumdesc 失败, 成功, 校验中, 警告"
+ }, {
+ "name": "hasFeedback",
+ "propType": "bool",
+ "description": "配合 validateState 属性使用,是否展示 success/loading 的校验状态图标, 目前只有Input支持",
+ "defaultValue": false
+ }, {
+ "name": "style",
+ "propType": "object",
+ "description": "自定义内联样式"
+ }, {
+ "name": "id",
+ "propType": "string"
+ }, {
+ "name": "children",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["node", "func"]
+ },
+ "description": "node 或者 function(values)"
+ }, {
+ "name": "size",
+ "propType": {
+ "type": "oneOf",
+ "value": ["large", "small", "medium"]
+ },
+ "description": "单个 Item 的 size 自定义,优先级高于 Form 的 size, 并且当组件与 Item 一起使用时,组件自身设置 size 属性无效。"
+ }, {
+ "name": "fullWidth",
+ "propType": "bool",
+ "description": "单个 Item 中表单类组件宽度是否是100%"
+ }, {
+ "name": "labelAlign",
+ "propType": {
+ "type": "oneOf",
+ "value": ["top", "left", "inset"]
+ },
+ "description": "标签的位置\n@enumdesc 上, 左, 内"
+ }, {
+ "name": "labelTextAlign",
+ "propType": {
+ "type": "oneOf",
+ "value": ["left", "right"]
+ },
+ "description": "标签的左右对齐方式\n@enumdesc 左, 右"
+ }, {
+ "name": "className",
+ "propType": "string",
+ "description": "扩展class"
+ }, {
+ "name": "required",
+ "propType": "bool",
+ "description": "[表单校验] 不能为空"
+ }, {
+ "name": "asterisk",
+ "propType": "bool",
+ "description": "required 的星号是否显示"
+ }, {
+ "name": "requiredMessage",
+ "propType": "string",
+ "description": "required 自定义错误信息"
+ }, {
+ "name": "requiredTrigger",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "array"]
+ },
+ "description": "required 自定义触发方式"
+ }, {
+ "name": "min",
+ "propType": "number",
+ "description": "[表单校验] 最小值"
+ }, {
+ "name": "max",
+ "propType": "number",
+ "description": "[表单校验] 最大值"
+ }, {
+ "name": "minmaxMessage",
+ "propType": "string",
+ "description": "min/max 自定义错误信息"
+ }, {
+ "name": "minmaxTrigger",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "array"]
+ },
+ "description": "min/max 自定义触发方式"
+ }, {
+ "name": "minLength",
+ "propType": "number",
+ "description": "[表单校验] 字符串最小长度 / 数组最小个数"
+ }, {
+ "name": "maxLength",
+ "propType": "number",
+ "description": "[表单校验] 字符串最大长度 / 数组最大个数"
+ }, {
+ "name": "minmaxLengthMessage",
+ "propType": "string",
+ "description": "minLength/maxLength 自定义错误信息"
+ }, {
+ "name": "minmaxLengthTrigger",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "array"]
+ },
+ "description": "minLength/maxLength 自定义触发方式"
+ }, {
+ "name": "length",
+ "propType": "number",
+ "description": "[表单校验] 字符串精确长度 / 数组精确个数"
+ }, {
+ "name": "lengthMessage",
+ "propType": "string",
+ "description": "length 自定义错误信息"
+ }, {
+ "name": "lengthTrigger",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "array"]
+ },
+ "description": "length 自定义触发方式"
+ }, {
+ "name": "pattern",
+ "propType": "any",
+ "description": "正则校验"
+ }, {
+ "name": "patternMessage",
+ "propType": "string",
+ "description": "pattern 自定义错误信息"
+ }, {
+ "name": "patternTrigger",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "array"]
+ },
+ "description": "pattern 自定义触发方式"
+ }, {
+ "name": "format",
+ "propType": {
+ "type": "oneOf",
+ "value": ["number", "email", "url", "tel"]
+ },
+ "description": "[表单校验] 四种常用的 pattern"
+ }, {
+ "name": "formatMessage",
+ "propType": "string",
+ "description": "format 自定义错误信息"
+ }, {
+ "name": "formatTrigger",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "array"]
+ },
+ "description": "format 自定义触发方式"
+ }, {
+ "name": "validator",
+ "propType": "func",
+ "description": "[表单校验] 自定义校验函数"
+ }, {
+ "name": "validatorTrigger",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "array"]
+ },
+ "description": "validator 自定义触发方式"
+ }, {
+ "name": "autoValidate",
+ "propType": "bool",
+ "description": "是否修改数据时自动触发校验"
+ }, {
+ "name": "device",
+ "propType": {
+ "type": "oneOf",
+ "value": ["phone", "tablet", "desktop"]
+ },
+ "description": "预设屏幕宽度"
+ }, {
+ "name": "responsive",
+ "propType": "bool"
+ }, {
+ "name": "colSpan",
+ "propType": "number",
+ "description": "在响应式布局模式下,表单项占多少列"
+ }, {
+ "name": "labelWidth",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["string", "number"]
+ },
+ "description": "在响应式布局下,且label在左边时,label的宽度是多少",
+ "defaultValue": 100
+ }, {
+ "name": "isPreview",
+ "propType": "bool",
+ "description": "是否开启预览态"
+ }, {
+ "name": "renderPreview",
+ "propType": "func",
+ "description": "预览态模式下渲染的内容\n@param {any} value 根据包裹的组件的 value 类型而决定"
+ }],
+ "configure": {
+ "component": {
+ "isContainer": true,
+ "nestingRule": {
+ "parentWhitelist": "Form"
+ }
+ }
+ }
+ },
+ "NumberPicker": {
+ "componentName": "NumberPicker",
+ "title": "数字输入",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "NumberPicker"
+ },
+ "props": [{
+ "name": "prefix",
+ "propType": "string",
+ "description": "样式前缀",
+ "defaultValue": "next-"
+ }, {
+ "name": "type",
+ "propType": {
+ "type": "oneOf",
+ "value": ["normal", "inline"]
+ },
+ "description": "设置类型\n@enumdesc 普通, 内联",
+ "defaultValue": "normal"
+ }, {
+ "name": "size",
+ "propType": {
+ "type": "oneOf",
+ "value": ["large", "medium"]
+ },
+ "description": "大小",
+ "defaultValue": "medium"
+ }, {
+ "name": "value",
+ "propType": "number",
+ "description": "当前值"
+ }, {
+ "name": "defaultValue",
+ "propType": "number",
+ "description": "默认值"
+ }, {
+ "name": "disabled",
+ "propType": "bool",
+ "description": "是否禁用"
+ }, {
+ "name": "step",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["number", "string"]
+ },
+ "description": "步长",
+ "defaultValue": 1
+ }, {
+ "name": "precision",
+ "propType": "number",
+ "description": "保留小数点后位数",
+ "defaultValue": 0
+ }, {
+ "name": "editable",
+ "propType": "bool",
+ "description": "用户是否可以输入",
+ "defaultValue": true
+ }, {
+ "name": "autoFocus",
+ "propType": "bool",
+ "description": "自动焦点"
+ }, {
+ "name": "onChange",
+ "propType": "func",
+ "description": "数值被改变的事件\n@param {Number} value 数据\n@param {Event} e DOM事件对象"
+ }, {
+ "name": "onKeyDown",
+ "propType": "func",
+ "description": "键盘按下"
+ }, {
+ "name": "onFocus",
+ "propType": "func",
+ "description": "焦点获得"
+ }, {
+ "name": "onBlur",
+ "propType": "func",
+ "description": "焦点失去"
+ }, {
+ "name": "onCorrect",
+ "propType": "func",
+ "description": "数值订正后的回调\n@param {Object} obj {currentValue,oldValue:String}"
+ }, {
+ "name": "onDisabled",
+ "propType": "func"
+ }, {
+ "name": "max",
+ "propType": "number",
+ "description": "最大值",
+ "defaultValue": null
+ }, {
+ "name": "min",
+ "propType": "number",
+ "description": "最小值",
+ "defaultValue": null
+ }, {
+ "name": "className",
+ "propType": "string",
+ "description": "自定义class"
+ }, {
+ "name": "style",
+ "propType": "object",
+ "description": "自定义内联样式"
+ }, {
+ "name": "state",
+ "propType": {
+ "type": "oneOf",
+ "value": ["error"]
+ }
+ }, {
+ "name": "format",
+ "propType": "func",
+ "description": "格式化当前值\n@param {Number} value\n@return {String|Number}"
+ }, {
+ "name": "upBtnProps",
+ "propType": "object",
+ "description": "增加按钮的props"
+ }, {
+ "name": "downBtnProps",
+ "propType": "object",
+ "description": "减少按钮的props"
+ }, {
+ "name": "label",
+ "propType": "node",
+ "description": "内联 label"
+ }, {
+ "name": "innerAfter",
+ "propType": "node",
+ "description": "inner after"
+ }, {
+ "name": "rtl",
+ "propType": "bool"
+ }, {
+ "name": "isPreview",
+ "propType": "bool",
+ "description": "是否为预览态"
+ }, {
+ "name": "renderPreview",
+ "propType": "func",
+ "description": "预览态模式下渲染的内容\n@param {number} value 评分值"
+ }, {
+ "name": "device",
+ "propType": {
+ "type": "oneOf",
+ "value": ["phone", "tablet", "desktop"]
+ },
+ "description": "预设屏幕宽度"
+ }]
+ },
+ "Select": {
+ "componentName": "Select",
+ "title": "下拉",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "Select"
+ },
+ "props": [{
+ "name": "mode",
+ "propType": {
+ "type": "oneOf",
+ "value": ["single", "multiple", "tag"]
+ },
+ "description": "选择器模式",
+ "defaultValue": "single"
+ }, {
+ "name": "value",
+ "propType": "any",
+ "description": "当前值,用于受控模式"
+ }, {
+ "name": "defaultValue",
+ "propType": "any",
+ "description": "初始的默认值"
+ }, {
+ "name": "onChange",
+ "propType": "func",
+ "description": "Select发生改变时触发的回调\n@param {*} value 选中的值\n@param {String} actionType 触发的方式, 'itemClick', 'enter', 'tag'\n@param {*} item 选中的值的对象数据 (useDetailValue=false有效)"
+ }, {
+ "name": "dataSource",
+ "propType": {
+ "type": "arrayOf",
+ "value": {
+ "type": "oneOfType",
+ "value": [{
+ "type": "shape",
+ "value": [{
+ "name": "value",
+ "propType": "any"
+ }, {
+ "name": "label",
+ "propType": "any"
+ }, {
+ "name": "disabled",
+ "propType": "bool"
+ }, {
+ "name": "children",
+ "propType": "array"
+ }]
+ }, "bool", "number", "string"]
+ }
+ },
+ "description": "传入的数据源,可以动态渲染子项,详见 [dataSource的使用](#dataSource的使用)"
+ }, {
+ "name": "hasBorder",
+ "propType": "bool",
+ "description": "是否有边框"
+ }, {
+ "name": "hasArrow",
+ "propType": "bool",
+ "description": "是否有下拉箭头",
+ "defaultValue": true
+ }, {
+ "name": "showSearch",
+ "propType": "bool",
+ "description": "展开后是否能搜索(tag 模式下固定为true)",
+ "defaultValue": false
+ }, {
+ "name": "onSearch",
+ "propType": "func",
+ "description": "当搜索框值变化时回调\n@param {String} value 数据"
+ }, {
+ "name": "onSearchClear",
+ "propType": "func",
+ "description": "当搜索框值被清空时候的回调\n@param {String} actionType 触发的方式, 'select'(选择清空), 'popupClose'(弹窗关闭清空)"
+ }, {
+ "name": "hasSelectAll",
+ "propType": {
+ "type": "oneOfType",
+ "value": ["bool", "string"]
+ },
+ "description": "多选模式下是否有全选功能"
+ }, {
+ "name": "fillProps",
+ "propType": "string",
+ "description": "填充到选择框里的值的 key\b\b"
+ }, {
+ "name": "useDetailValue",
+ "propType": "bool",
+ "description": "onChange 返回的 value 使用 dataSource 的对象"
+ }, {
+ "name": "cacheValue",
+ "propType": "bool",
+ "description": "dataSource 变化的时是否保留已选的内容",
+ "defaultValue": true
+ }, {
+ "name": "valueRender",
+ "propType": "func",
+ "description": "渲染 Select 展现内容的方法\n@param {Object} item 渲染节点的item\n@return {ReactNode} 展现内容\n@default item => item.label \\|\\| item.value"
+ }, {
+ "name": "itemRender",
+ "propType": "func",
+ "description": "渲染 MenuItem 内容的方法\n@param {Object} item 渲染节点的item\n@param {String} searchValue 搜索关键字(如果开启搜索)\n@return {ReactNode} item node"
+ }, {
+ "name": "notFoundContent",
+ "propType": "node",
+ "description": "弹层内容为空的文案"
+ }, {
+ "name": "style",
+ "propType": "object"
+ }, {
+ "name": "searchValue",
+ "propType": "string",
+ "description": "受控搜索值,一般不需要设置\n@type {[type]}"
+ }, {
+ "name": "tagInline",
+ "propType": "bool",
+ "description": "是否一行显示,仅在 mode 为 multiple 的时候生效",
+ "defaultValue": false
+ }, {
+ "name": "maxTagCount",
+ "propType": "number",
+ "description": "最多显示多少个 tag"
+ }, {
+ "name": "maxTagPlaceholder",
+ "propType": "func",
+ "description": "隐藏多余 tag 时显示的内容,在 maxTagCount 生效时起作用\n@param {number} selectedValues 当前已选中的元素\n@param {number} totalValues 总待选元素"
+ }, {
+ "name": "hiddenSelected",
+ "propType": "bool",
+ "description": "选择后是否立即隐藏菜单 (mode=multiple/tag 模式生效)"
+ }, {
+ "name": "onRemove",
+ "propType": "func",
+ "description": "tag 删除回调\n@param {object} item 渲染节点的item"
+ }, {
+ "name": "onFocus",
+ "propType": "func",
+ "description": "焦点事件"
+ }, {
+ "name": "onBlur",
+ "propType": "func",
+ "description": "失去焦点事件"
+ }, {
+ "name": "onMouseEnter",
+ "propType": "func"
+ }, {
+ "name": "onMouseLeave",
+ "propType": "func"
+ }, {
+ "name": "onKeyDown",
+ "propType": "func"
+ }, {
+ "name": "locale",
+ "propType": "object"
+ }],
+ "configure": {
+ "component": {
+ "isContainer": true,
+ "nestingRule": {
+ "childWhitelist": "Select.Option"
+ }
+ },
+ "props": [{
+ "name": "mode",
+ "title": "选择器模式",
+ "setter": {
+ "componentName": "RadioGroupSetter",
+ "props": {
+ "defaultValue": "single",
+ "dataSource": [{
+ "value": "single",
+ "label": "single"
+ }, {
+ "value": "multiple",
+ "label": "multiple"
+ }, {
+ "value": "tag",
+ "label": "tag"
+ }]
+ }
+ }
+ }, {
+ "name": "mode",
+ "title": "选择器模式",
+ "setter": {
+ "componentName": "SelectSetter",
+ "props": {
+ "defaultValue": "single",
+ "dataSource": [{
+ "value": "single",
+ "label": "single"
+ }, {
+ "value": "multiple",
+ "label": "multiple"
+ }, {
+ "value": "tag",
+ "label": "tag"
+ }]
+ }
+ }
+ }, {
+ "name": "value",
+ "title": "受控值",
+ "setter": "StringSetter"
+ }, {
+ "name": "hasBorder",
+ "title": "是否有边框",
+ "setter": {
+ "componentName": "BoolSetter",
+ "props": {
+ "defaultValue": true
+ }
+ }
+ }, {
+ "name": "maxTagCount",
+ "title": "最多显示多少个 tag",
+ "setter": "NumberSetter"
+ }, {
+ "name": "maxTagCount",
+ "title": "最多显示多少个 tag",
+ "setter": "ExpressionSetter"
+ }, {
+ "name": "MixinSetter",
+ "placeholder": "混合",
+ "setter": {
+ "componentName": "MixinSetter",
+ "props": {
+ "types": [{
+ "name": "StringSetter",
+ "props": {}
+ }, {
+ "name": "TextAreaSetter",
+ "props": {}
+ }, {
+ "name": "SelectSetter",
+ "props": {
+ "hasClear": true,
+ "dataSource": [{
+ "label": "上",
+ "value": "t"
+ }, {
+ "label": "右",
+ "value": "r"
+ }, {
+ "label": "下",
+ "value": "b"
+ }, {
+ "label": "左",
+ "value": "l"
+ }]
+ }
+ }, {
+ "name": "NumberSetter",
+ "props": {}
+ }, {
+ "name": "BoolSetter",
+ "props": {}
+ }],
+ "defaultType": "SelectSetter"
+ }
+ }
+ }, {
+ "type": "group",
+ "name": "扩展 Setter",
+ "items": [{
+ "name": "TextAreaSetter",
+ "setter": "TextAreaSetter"
+ }, {
+ "name": "date",
+ "title": "测试日期",
+ "setter": "DateSetter"
+ }, {
+ "name": "date",
+ "title": "测试日期-年",
+ "setter": "DateYearSetter"
+ }, {
+ "name": "date",
+ "title": "测试日期-月",
+ "setter": "DateMonthSetter"
+ }, {
+ "name": "date",
+ "title": "测试日期-区间",
+ "setter": "DateRangeSetter"
+ }]
+ }, {
+ "type": "group",
+ "name": "ArraySetter",
+ "items": [{
+ "name": "arrayValue1",
+ "title": "字符数组",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": {
+ "componentName": "StringSetter",
+ "initialValue": ""
+ }
+ }
+ }
+ }, {
+ "name": "arrayValue2",
+ "title": "数字数组",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": {
+ "componentName": "NumberSetter",
+ "initialValue": 0
+ }
+ }
+ }
+ }, {
+ "name": "arrayValue3",
+ "title": "混合数组",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": {
+ "componentName": "MixinSetter",
+ "props": {
+ "types": [{
+ "name": "StringSetter",
+ "props": {}
+ }, {
+ "name": "ExpressionSetter",
+ "props": {}
+ }, {
+ "name": "RadioGroupSetter",
+ "props": {
+ "hasClear": true,
+ "dataSource": [{
+ "label": "上",
+ "value": "t"
+ }, {
+ "label": "右",
+ "value": "r"
+ }, {
+ "label": "下",
+ "value": "b"
+ }, {
+ "label": "左",
+ "value": "l"
+ }]
+ }
+ }],
+ "defaultType": "SelectSetter"
+ }
+ }
+ }
+ }
+ }, {
+ "name": "arrayValue4",
+ "title": "对象数组",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": {
+ "componentName": "ObjectSetter",
+ "props": {
+ "config": {
+ "items": [{
+ "name": "username",
+ "title": "姓名",
+ "setter": "StringSetter",
+ "important": true
+ }, {
+ "name": "phone",
+ "title": "电话",
+ "setter": "StringSetter",
+ "important": true
+ }, {
+ "name": "age",
+ "title": "年龄",
+ "setter": "NumberSetter"
+ }, {
+ "name": "married",
+ "title": "婚否",
+ "setter": "BoolSetter"
+ }, {
+ "type": "group",
+ "title": "work",
+ "items": [{
+ "name": "job",
+ "title": "工作岗位",
+ "setter": {
+ "componentName": "SelectSetter",
+ "props": {
+ "dataSource": [{
+ "label": "工程师",
+ "value": 1
+ }, {
+ "label": "高级工程师",
+ "value": 2
+ }, {
+ "label": "资深工程师",
+ "value": 3
+ }]
+ }
+ }
+ }, {
+ "name": "address",
+ "title": "工作地点",
+ "setter": "TextAreaSetter"
+ }]
+ }]
+ }
+ },
+ "initialValue": {}
+ }
+ }
+ }
+ }, {
+ "name": "arrayValue5",
+ "title": "对象数组",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": {
+ "componentName": "ObjectSetter",
+ "props": {
+ "config": {
+ "items": [{
+ "name": "username",
+ "title": "姓名",
+ "setter": "StringSetter",
+ "important": true
+ }, {
+ "name": "age",
+ "title": "年龄",
+ "setter": "NumberSetter",
+ "important": true
+ }, {
+ "name": "married",
+ "title": "婚否",
+ "setter": "BoolSetter",
+ "important": true
+ }, {
+ "name": "log",
+ "title": "到访记录",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": "StringSetter"
+ }
+ },
+ "important": true
+ }, {
+ "type": "group",
+ "title": "work",
+ "items": [{
+ "name": "job",
+ "title": "工作岗位",
+ "setter": {
+ "componentName": "SelectSetter",
+ "props": {
+ "dataSource": [{
+ "label": "工程师",
+ "value": 1
+ }, {
+ "label": "高级工程师",
+ "value": 2
+ }, {
+ "label": "资深工程师",
+ "value": 3
+ }]
+ }
+ }
+ }, {
+ "name": "address",
+ "title": "工作地点",
+ "setter": "TextAreaSetter"
+ }]
+ }]
+ }
+ },
+ "initialValue": {}
+ },
+ "mode": "popup"
+ }
+ }
+ }],
+ "extraProps": {
+ "defaultCollapsed": false
+ }
+ }, {
+ "type": "group",
+ "name": "ObjectSetter",
+ "items": [{
+ "name": "objectValue1",
+ "title": "对象数据1",
+ "setter": {
+ "componentName": "ObjectSetter",
+ "props": {
+ "config": {
+ "items": [{
+ "name": "username",
+ "title": "姓名",
+ "setter": "StringSetter",
+ "important": true
+ }, {
+ "name": "age",
+ "title": "年龄",
+ "setter": "NumberSetter",
+ "important": true
+ }, {
+ "name": "married",
+ "title": "婚否",
+ "setter": "BoolSetter",
+ "important": true
+ }, {
+ "name": "log",
+ "title": "到访记录",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": "StringSetter"
+ }
+ },
+ "important": true
+ }, {
+ "type": "group",
+ "title": "work",
+ "items": [{
+ "name": "job",
+ "title": "工作岗位",
+ "setter": {
+ "componentName": "SelectSetter",
+ "props": {
+ "dataSource": [{
+ "label": "工程师",
+ "value": 1
+ }, {
+ "label": "高级工程师",
+ "value": 2
+ }, {
+ "label": "资深工程师",
+ "value": 3
+ }]
+ }
+ }
+ }, {
+ "name": "address",
+ "title": "工作地点",
+ "setter": "TextAreaSetter"
+ }]
+ }]
+ }
+ },
+ "initialValue": {}
+ }
+ }, {
+ "name": "objectValue2",
+ "title": "对象数据2",
+ "setter": {
+ "componentName": "ObjectSetter",
+ "props": {
+ "mode": "popup",
+ "config": {
+ "items": [{
+ "name": "username",
+ "title": "姓名",
+ "setter": "StringSetter",
+ "important": true
+ }, {
+ "name": "age",
+ "title": "年龄",
+ "setter": "NumberSetter",
+ "important": true
+ }, {
+ "name": "married",
+ "title": "婚否",
+ "setter": "BoolSetter",
+ "important": true
+ }, {
+ "name": "log",
+ "title": "到访记录",
+ "setter": {
+ "componentName": "ArraySetter",
+ "props": {
+ "itemSetter": "StringSetter"
+ }
+ },
+ "important": true
+ }, {
+ "type": "group",
+ "title": "work",
+ "items": [{
+ "name": "job",
+ "title": "工作岗位",
+ "setter": {
+ "componentName": "SelectSetter",
+ "props": {
+ "dataSource": [{
+ "label": "工程师",
+ "value": 1
+ }, {
+ "label": "高级工程师",
+ "value": 2
+ }, {
+ "label": "资深工程师",
+ "value": 3
+ }]
+ }
+ }
+ }, {
+ "name": "address",
+ "title": "工作地点",
+ "setter": "TextAreaSetter"
+ }]
+ }]
+ }
+ },
+ "initialValue": {}
+ }
+ }]
+ }]
+ }
+ },
+ "Select.Option": {
+ "componentName": "Select.Option",
+ "title": "选择项",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@alifd/next",
+ "version": "1.19.18",
+ "destructuring": true,
+ "exportName": "Select",
+ "subName": "Option"
+ },
+ "props": [{
+ "name": "value",
+ "propType": {
+ "type": "any",
+ "isRequired": true
+ },
+ "description": "选项值"
+ }, {
+ "name": "disabled",
+ "propType": "bool",
+ "description": "是否禁用"
+ }, {
+ "name": "children",
+ "propType": "any"
+ }],
+ "configure": {
+ "component": {
+ "isContainer": true,
+ "nestingRule": {
+ "parentWhitelist": "Select"
+ }
+ }
+ }
+ }
+ },
+ "componentList": [{
+ "title": "基础",
+ "icon": "",
+ "children": [{
+ "componentName": "Button",
+ "title": "按钮",
+ "icon": "",
+ "package": "@alife/next",
+ "library": "Next",
+ "snippets": [{
+ "title": "private",
+ "screenshot": "https://img.alicdn.com/tfs/TB16gZhi.H1gK0jSZSyXXXtlpXa-192-144.png",
+ "schema": {
+ "componentName": "Button",
+ "props": {
+ "type": "primary"
+ },
+ "children": "Primary"
+ }
+ }, {
+ "title": "secondary",
+ "screenshot": "https://img.alicdn.com/tfs/TB11Hkji1H2gK0jSZFEXXcqMpXa-192-144.png",
+ "schema": {
+ "componentName": "Button",
+ "props": {
+ "type": "secondary"
+ },
+ "children": "secondary"
+ }
+ }, {
+ "title": "normal",
+ "screenshot": "",
+ "schema": {
+ "componentName": "Button",
+ "props": {
+ "type": "normal"
+ },
+ "children": "normal"
+ }
+ }]
+ }]
+ }, {
+ "title": "表单",
+ "icon": "",
+ "children": [{
+ "componentName": "Input",
+ "library": "Next",
+ "title": "输入框",
+ "icon": "",
+ "package": "@alife/next",
+ "snippets": [{
+ "title": "普通",
+ "screenshot": "",
+ "schema": {
+ "componentName": "Input",
+ "props": {}
+ }
+ }]
+ }, {
+ "componentName": "Select",
+ "library": "Next",
+ "title": "选择框",
+ "icon": "",
+ "package": "@alife/next",
+ "snippets": [{
+ "title": "默认",
+ "screenshot": "",
+ "schema": {
+ "componentName": "Select",
+ "props": {}
+ }
+ }]
+ }, {
+ "componentName": "NumberPicker",
+ "library": "Next",
+ "title": "数字",
+ "icon": "",
+ "package": "@alife/next",
+ "snippets": [{
+ "title": "默认",
+ "screenshot": "",
+ "schema": {
+ "componentName": "NumberPicker",
+ "props": {}
+ }
+ }]
+ }]
+ }, {
+ "title": "其他",
+ "icon": "",
+ "children": [{
+ "componentName": "Div",
+ "library": "Next",
+ "title": "容器",
+ "icon": "",
+ "snippets": [{
+ "title": "默认",
+ "screenshot": "",
+ "schema": {
+ "componentName": "Div",
+ "props": {}
+ }
+ }]
+ }]
+ }]
+}
diff --git a/packages/editor/public/favicon.png b/packages/demo/public/favicon.png
similarity index 100%
rename from packages/editor/public/favicon.png
rename to packages/demo/public/favicon.png
diff --git a/packages/editor/public/index.html b/packages/demo/public/index.html
similarity index 100%
rename from packages/editor/public/index.html
rename to packages/demo/public/index.html
diff --git a/packages/demo/public/schema.json b/packages/demo/public/schema.json
new file mode 100644
index 000000000..424628106
--- /dev/null
+++ b/packages/demo/public/schema.json
@@ -0,0 +1,110 @@
+{
+ "componentName": "Page",
+ "fileName": "test",
+ "dataSource": {
+ "list": []
+ },
+ "state": {
+ "text": "outter"
+ },
+ "props": {
+ "ref": "outterView",
+ "autoLoading": true,
+ "style": {
+ "padding": 20
+ }
+ },
+ "children": [{
+ "componentName": "Form",
+ "props": {
+ "labelCol": 3,
+ "style": {},
+ "ref": "testForm"
+ },
+ "children": [{
+ "componentName": "Form.Item",
+ "props": {
+ "label": "姓名:",
+ "name": "name",
+ "initValue": "李雷"
+ },
+ "children": [{
+ "componentName": "Input",
+ "props": {
+ "placeholder": "请输入",
+ "size": "medium",
+ "style": {
+ "width": 320
+ }
+ }
+ }]
+ }, {
+ "componentName": "Form.Item",
+ "props": {
+ "label": "年龄:",
+ "name": "age",
+ "initValue": "22"
+ },
+ "children": [{
+ "componentName": "NumberPicker",
+ "props": {
+ "size": "medium",
+ "type": "normal"
+ }
+ }]
+ }, {
+ "componentName": "Form.Item",
+ "props": {
+ "label": "职业:",
+ "name": "profession"
+ },
+ "children": [{
+ "componentName": "Select",
+ "props": {
+ "dataSource": [{
+ "label": "教师",
+ "value": "t"
+ }, {
+ "label": "医生",
+ "value": "d"
+ }, {
+ "label": "歌手",
+ "value": "s"
+ }]
+ }
+ }]
+ }, {
+ "componentName": "Div",
+ "props": {
+ "style": {
+ "textAlign": "center"
+ }
+ },
+ "children": [{
+ "componentName": "Button.Group",
+ "props": {},
+ "children": [{
+ "componentName": "Button",
+ "props": {
+ "type": "primary",
+ "style": {
+ "margin": "0 5px 0 5px"
+ },
+ "htmlType": "submit"
+ },
+ "children": "提交"
+ }, {
+ "componentName": "Button",
+ "props": {
+ "type": "normal",
+ "style": {
+ "margin": "0 5px 0 5px"
+ },
+ "htmlType": "reset"
+ },
+ "children": "重置"
+ }]
+ }]
+ }]
+ }]
+}
\ No newline at end of file
diff --git a/packages/editor/src/config/assets.js b/packages/demo/src/config/assets.js
similarity index 82%
rename from packages/editor/src/config/assets.js
rename to packages/demo/src/config/assets.js
index e134d2630..3668cc44f 100644
--- a/packages/editor/src/config/assets.js
+++ b/packages/demo/src/config/assets.js
@@ -1255,7 +1255,7 @@ export default {
{
name: 'value',
title: '受控值',
- setter: 'StringSetter',
+ setter: 'StringSetter'
},
{
name: 'hasBorder',
@@ -1452,57 +1452,67 @@ export default {
componentName: 'ObjectSetter',
props: {
config: {
- items: [{
- name: 'username',
- title: '姓名',
- setter: 'StringSetter',
- important: true,
- }, {
- name: 'phone',
- title: '电话',
- setter: 'StringSetter',
- important: true,
- }, {
- name: 'age',
- title: '年龄',
- setter: 'NumberSetter'
- }, {
- name: 'married',
- title: '婚否',
- setter: 'BoolSetter'
- }, {
- type: 'group',
- title: 'work',
- items: [
- {
- name: 'job',
- title: '工作岗位',
- setter: {
- componentName: 'SelectSetter',
- props: {
- dataSource: [{
- label: '工程师',
- value: 1
- }, {
- label: '高级工程师',
- value: 2
- }, {
- label: '资深工程师',
- value: 3
- }]
+ items: [
+ {
+ name: 'username',
+ title: '姓名',
+ setter: 'StringSetter',
+ important: true
+ },
+ {
+ name: 'phone',
+ title: '电话',
+ setter: 'StringSetter',
+ important: true
+ },
+ {
+ name: 'age',
+ title: '年龄',
+ setter: 'NumberSetter'
+ },
+ {
+ name: 'married',
+ title: '婚否',
+ setter: 'BoolSetter'
+ },
+ {
+ type: 'group',
+ title: 'work',
+ items: [
+ {
+ name: 'job',
+ title: '工作岗位',
+ setter: {
+ componentName: 'SelectSetter',
+ props: {
+ dataSource: [
+ {
+ label: '工程师',
+ value: 1
+ },
+ {
+ label: '高级工程师',
+ value: 2
+ },
+ {
+ label: '资深工程师',
+ value: 3
+ }
+ ]
+ }
}
+ },
+ {
+ name: 'address',
+ title: '工作地点',
+ setter: 'TextAreaSetter'
}
- },
- {
- name: 'address',
- title: '工作地点',
- setter: 'TextAreaSetter'
- }
- ]
- }],
+ ]
+ }
+ ]
}
},
- initialValue: {},
+ initialValue: {}
}
}
}
@@ -1517,72 +1527,82 @@ export default {
componentName: 'ObjectSetter',
props: {
config: {
- items: [{
- name: 'username',
- title: '姓名',
- setter: 'StringSetter',
- important: true,
- }, {
- name: 'age',
- title: '年龄',
- setter: 'NumberSetter',
- important: true,
- }, {
- name: 'married',
- title: '婚否',
- setter: 'BoolSetter',
- important: true,
- }, {
- name: 'log',
- title: '到访记录',
- setter: {
- componentName: 'ArraySetter',
- props: {
- itemSetter: 'StringSetter'
- }
+ items: [
+ {
+ name: 'username',
+ title: '姓名',
+ setter: 'StringSetter',
+ important: true
},
- important: true,
- }, {
- type: 'group',
- title: 'work',
- items: [
- {
- name: 'job',
- title: '工作岗位',
- setter: {
- componentName: 'SelectSetter',
- props: {
- dataSource: [{
- label: '工程师',
- value: 1
- }, {
- label: '高级工程师',
- value: 2
- }, {
- label: '资深工程师',
- value: 3
- }]
- }
+ {
+ name: 'age',
+ title: '年龄',
+ setter: 'NumberSetter',
+ important: true
+ },
+ {
+ name: 'married',
+ title: '婚否',
+ setter: 'BoolSetter',
+ important: true
+ },
+ {
+ name: 'log',
+ title: '到访记录',
+ setter: {
+ componentName: 'ArraySetter',
+ props: {
+ itemSetter: 'StringSetter'
}
},
- {
- name: 'address',
- title: '工作地点',
- setter: 'TextAreaSetter'
- }
- ]
- }],
+ important: true
+ },
+ {
+ type: 'group',
+ title: 'work',
+ items: [
+ {
+ name: 'job',
+ title: '工作岗位',
+ setter: {
+ componentName: 'SelectSetter',
+ props: {
+ dataSource: [
+ {
+ label: '工程师',
+ value: 1
+ },
+ {
+ label: '高级工程师',
+ value: 2
+ },
+ {
+ label: '资深工程师',
+ value: 3
+ }
+ ]
+ }
+ }
+ },
+ {
+ name: 'address',
+ title: '工作地点',
+ setter: 'TextAreaSetter'
+ }
+ ]
+ }
+ ]
}
},
- initialValue: {},
+ initialValue: {}
},
mode: 'popup'
}
}
- },
+ }
],
extraProps: {
- defaultCollapsed: false,
+ defaultCollapsed: false
}
},
{
@@ -1596,64 +1616,74 @@ export default {
componentName: 'ObjectSetter',
props: {
config: {
- items: [{
- name: 'username',
- title: '姓名',
- setter: 'StringSetter',
- important: true,
- }, {
- name: 'age',
- title: '年龄',
- setter: 'NumberSetter',
- important: true,
- }, {
- name: 'married',
- title: '婚否',
- setter: 'BoolSetter',
- important: true,
- }, {
- name: 'log',
- title: '到访记录',
- setter: {
- componentName: 'ArraySetter',
- props: {
- itemSetter: 'StringSetter'
- }
+ items: [
+ {
+ name: 'username',
+ title: '姓名',
+ setter: 'StringSetter',
+ important: true
},
- important: true,
- }, {
- type: 'group',
- title: 'work',
- items: [
- {
- name: 'job',
- title: '工作岗位',
- setter: {
- componentName: 'SelectSetter',
- props: {
- dataSource: [{
- label: '工程师',
- value: 1
- }, {
- label: '高级工程师',
- value: 2
- }, {
- label: '资深工程师',
- value: 3
- }]
- }
+ {
+ name: 'age',
+ title: '年龄',
+ setter: 'NumberSetter',
+ important: true
+ },
+ {
+ name: 'married',
+ title: '婚否',
+ setter: 'BoolSetter',
+ important: true
+ },
+ {
+ name: 'log',
+ title: '到访记录',
+ setter: {
+ componentName: 'ArraySetter',
+ props: {
+ itemSetter: 'StringSetter'
}
},
- {
- name: 'address',
- title: '工作地点',
- setter: 'TextAreaSetter'
- }
- ]
- }],
+ important: true
+ },
+ {
+ type: 'group',
+ title: 'work',
+ items: [
+ {
+ name: 'job',
+ title: '工作岗位',
+ setter: {
+ componentName: 'SelectSetter',
+ props: {
+ dataSource: [
+ {
+ label: '工程师',
+ value: 1
+ },
+ {
+ label: '高级工程师',
+ value: 2
+ },
+ {
+ label: '资深工程师',
+ value: 3
+ }
+ ]
+ }
+ }
+ },
+ {
+ name: 'address',
+ title: '工作地点',
+ setter: 'TextAreaSetter'
+ }
+ ]
+ }
+ ]
}
},
- initialValue: {},
+ initialValue: {}
}
},
{
@@ -1664,64 +1694,74 @@ export default {
props: {
mode: 'popup',
config: {
- items: [{
- name: 'username',
- title: '姓名',
- setter: 'StringSetter',
- important: true,
- }, {
- name: 'age',
- title: '年龄',
- setter: 'NumberSetter',
- important: true,
- }, {
- name: 'married',
- title: '婚否',
- setter: 'BoolSetter',
- important: true,
- }, {
- name: 'log',
- title: '到访记录',
- setter: {
- componentName: 'ArraySetter',
- props: {
- itemSetter: 'StringSetter'
- }
+ items: [
+ {
+ name: 'username',
+ title: '姓名',
+ setter: 'StringSetter',
+ important: true
},
- important: true,
- }, {
- type: 'group',
- title: 'work',
- items: [
- {
- name: 'job',
- title: '工作岗位',
- setter: {
- componentName: 'SelectSetter',
- props: {
- dataSource: [{
- label: '工程师',
- value: 1
- }, {
- label: '高级工程师',
- value: 2
- }, {
- label: '资深工程师',
- value: 3
- }]
- }
+ {
+ name: 'age',
+ title: '年龄',
+ setter: 'NumberSetter',
+ important: true
+ },
+ {
+ name: 'married',
+ title: '婚否',
+ setter: 'BoolSetter',
+ important: true
+ },
+ {
+ name: 'log',
+ title: '到访记录',
+ setter: {
+ componentName: 'ArraySetter',
+ props: {
+ itemSetter: 'StringSetter'
}
},
- {
- name: 'address',
- title: '工作地点',
- setter: 'TextAreaSetter'
- }
- ]
- }],
+ important: true
+ },
+ {
+ type: 'group',
+ title: 'work',
+ items: [
+ {
+ name: 'job',
+ title: '工作岗位',
+ setter: {
+ componentName: 'SelectSetter',
+ props: {
+ dataSource: [
+ {
+ label: '工程师',
+ value: 1
+ },
+ {
+ label: '高级工程师',
+ value: 2
+ },
+ {
+ label: '资深工程师',
+ value: 3
+ }
+ ]
+ }
+ }
+ },
+ {
+ name: 'address',
+ title: '工作地点',
+ setter: 'TextAreaSetter'
+ }
+ ]
+ }
+ ]
}
},
- initialValue: {},
+ initialValue: {}
}
}
]
diff --git a/packages/demo/src/config/components.js b/packages/demo/src/config/components.js
new file mode 100644
index 000000000..4dcb82b9b
--- /dev/null
+++ b/packages/demo/src/config/components.js
@@ -0,0 +1,19 @@
+import componentsPane from '@ali/lowcode-plugin-components-pane';
+import Settings from '../../../plugin-settings';
+import undoRedo from '@ali/lowcode-plugin-undo-redo';
+import Designer from '../plugins/designer';
+import logo from '@ali/lowcode-plugin-logo';
+import save from '@ali/lowcode-plugin-save';
+import OutlineTree from '../../../plugin-outline-tree';
+
+import { PluginFactory } from '@ali/lowcode-editor-core';
+
+export default {
+ logo: PluginFactory(logo),
+ save: PluginFactory(save),
+ designer: PluginFactory(Designer),
+ settings: PluginFactory(Settings),
+ outlineTree: PluginFactory(OutlineTree),
+ undoRedo: PluginFactory(undoRedo),
+ componentsPane: PluginFactory(componentsPane)
+};
diff --git a/packages/editor/src/config/constants.js b/packages/demo/src/config/constants.js
similarity index 100%
rename from packages/editor/src/config/constants.js
rename to packages/demo/src/config/constants.js
diff --git a/packages/editor/src/config/locale/en-US.js b/packages/demo/src/config/locale/en-US.js
similarity index 100%
rename from packages/editor/src/config/locale/en-US.js
rename to packages/demo/src/config/locale/en-US.js
diff --git a/packages/editor/src/config/locale/index.js b/packages/demo/src/config/locale/index.js
similarity index 100%
rename from packages/editor/src/config/locale/index.js
rename to packages/demo/src/config/locale/index.js
diff --git a/packages/editor/src/config/locale/ja-JP.js b/packages/demo/src/config/locale/ja-JP.js
similarity index 100%
rename from packages/editor/src/config/locale/ja-JP.js
rename to packages/demo/src/config/locale/ja-JP.js
diff --git a/packages/editor/src/config/locale/zh-CN.js b/packages/demo/src/config/locale/zh-CN.js
similarity index 100%
rename from packages/editor/src/config/locale/zh-CN.js
rename to packages/demo/src/config/locale/zh-CN.js
diff --git a/packages/editor/src/config/locale/zh-TW.js b/packages/demo/src/config/locale/zh-TW.js
similarity index 100%
rename from packages/editor/src/config/locale/zh-TW.js
rename to packages/demo/src/config/locale/zh-TW.js
diff --git a/packages/demo/src/config/skeleton.js b/packages/demo/src/config/skeleton.js
new file mode 100644
index 000000000..46fbd550f
--- /dev/null
+++ b/packages/demo/src/config/skeleton.js
@@ -0,0 +1,132 @@
+export default {
+ version: '^1.0.2',
+ theme: {
+ fusion: {
+ package: '@alife/dpl-iceluna',
+ version: '^2.3.0'
+ },
+ scss: ''
+ },
+ constants: {
+ namespace: 'page'
+ },
+ utils: [],
+ plugins: {
+ topArea: [
+ {
+ pluginKey: 'logo',
+ type: 'Custom',
+ props: {
+ align: 'left',
+ width: 100
+ },
+ config: {
+ package: '@ali/lowcode-plugin-logo',
+ version: '1.0.0'
+ },
+ pluginProps: {
+ logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png',
+ href: '/'
+ }
+ },
+ {
+ pluginKey: 'undoRedo',
+ type: 'Custom',
+ props: {
+ align: 'right',
+ width: 88
+ },
+ config: {
+ package: '@ali/lowcode-plugin-undo-redo',
+ version: '1.0.0'
+ }
+ },
+ {
+ pluginKey: 'divider',
+ type: 'Divider',
+ props: {
+ align: 'right'
+ }
+ },
+ {
+ pluginKey: 'save',
+ type: 'Custom',
+ props: {
+ align: 'right',
+ width: 64
+ },
+ config: {
+ package: '@ali/lowcode-plugin-save',
+ version: '1.0.0'
+ }
+ }
+ ],
+ leftArea: [
+ {
+ pluginKey: 'componentsPane',
+ type: 'PanelIcon',
+ props: {
+ align: 'top',
+ icon: 'zujianku',
+ title: '组件库'
+ },
+ config: {
+ package: '@ali/iceluna-plugin-components-pane',
+ version: '0.0.1'
+ },
+ pluginProps: {
+ disableAppComponent: true
+ }
+ },
+ {
+ pluginKey: 'outlineTree',
+ type: 'PanelIcon',
+ props: {
+ align: 'top',
+ icon: 'dengpao',
+ title: '大纲树'
+ },
+ config: {
+ version: '^1.0.0'
+ },
+ pluginProps: {}
+ }
+ ],
+ rightArea: [
+ {
+ pluginKey: 'settings',
+ type: 'Panel',
+ props: {},
+ config: {
+ package: '@ali/lowcode-plugin-settings-pane',
+ version: '^1.0.0'
+ },
+ pluginProps: {}
+ }
+ ],
+ centerArea: [
+ {
+ pluginKey: 'designer',
+ config: {
+ package: '@ali/lowcode-plugin-designer',
+ version: '1.0.0'
+ }
+ }
+ ]
+ },
+ hooks: [],
+ shortCuts: [],
+ lifeCycles: {
+ init: async function init(editor) {
+ const assets = await editor.utils.get('/assets.json');
+ editor.set({
+ assets,
+ componentsMap: assets.components
+ });
+
+ editor.utils.get('/schema.json').then(res => {
+ editor.emit('schema.reset', res);
+ });
+ }
+ }
+};
diff --git a/packages/editor/src/config/theme.scss b/packages/demo/src/config/theme.scss
similarity index 100%
rename from packages/editor/src/config/theme.scss
rename to packages/demo/src/config/theme.scss
diff --git a/packages/editor/src/config/utils.js b/packages/demo/src/config/utils.js
similarity index 100%
rename from packages/editor/src/config/utils.js
rename to packages/demo/src/config/utils.js
diff --git a/packages/editor/src/global.scss b/packages/demo/src/global.scss
similarity index 100%
rename from packages/editor/src/global.scss
rename to packages/demo/src/global.scss
diff --git a/packages/demo/src/index.tsx b/packages/demo/src/index.tsx
new file mode 100644
index 000000000..37b7de293
--- /dev/null
+++ b/packages/demo/src/index.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Skeleton from '@ali/lowcode-editor-skeleton';
+import config from './config/skeleton';
+import components from './config/components';
+import utils from './config/utils';
+import './config/locale';
+import '../../plugin-setters';
+
+import './global.scss';
+import './config/theme.scss';
+
+const ICE_CONTAINER = document.getElementById('ice-container');
+
+if (!ICE_CONTAINER) {
+ throw new Error('当前页面不存在 节点.');
+}
+
+ReactDOM.render(, ICE_CONTAINER);
diff --git a/packages/editor/src/plugins/designer/index.scss b/packages/demo/src/plugins/designer/index.scss
similarity index 100%
rename from packages/editor/src/plugins/designer/index.scss
rename to packages/demo/src/plugins/designer/index.scss
diff --git a/packages/editor/src/plugins/designer/index.tsx b/packages/demo/src/plugins/designer/index.tsx
similarity index 83%
rename from packages/editor/src/plugins/designer/index.tsx
rename to packages/demo/src/plugins/designer/index.tsx
index 1043308e3..52be98ec1 100644
--- a/packages/editor/src/plugins/designer/index.tsx
+++ b/packages/demo/src/plugins/designer/index.tsx
@@ -1,13 +1,11 @@
import React, { PureComponent } from 'react';
-import Editor from '../../framework/index';
-import { PluginConfig } from '../../framework/definitions';
-
+import Editor from '@ali/lowcode-editor-core';
+import { PluginConfig } from '@ali/lowcode-editor-core/lib/definitions';
+import assets from '../../config/assets';
// @ts-ignore
import Designer from '../../../../designer';
-import assets from '../../config/assets';
-
import './index.scss';
export interface PluginProps {
@@ -30,13 +28,16 @@ const SCHEMA = {
},
props: {
ref: 'outterView',
- autoLoading: true
+ autoLoading: true,
+ style: {
+ padding: 20
+ }
},
children: [
{
componentName: 'Form',
props: {
- labelCol: 4,
+ labelCol: 3,
style: {},
ref: 'testForm'
},
@@ -165,14 +166,37 @@ const SCHEMA = {
export default class DesignerPlugin extends PureComponent {
displayName: 'LowcodePluginDesigner';
+ componentDidMount(): void {
+ const { editor } = this.props;
+ editor.on('schema.reset', this.handleSchemaReset);
+ }
+
+ componentWillUmount(): void {
+ const { editor } = this.props;
+ editor.off('schema.reset', this.handleSchemaReset);
+ }
+
+ handleSchemaReset = (schema: object): void => {
+ // const {editor} = this.props;
+ // if (this.designer) {
+ // this.designer.setSchema(schema);
+ // } else {
+ // editor.once('designer.ready', (designer): void => {
+ // designer.setSchema(schema);
+ // });
+ // }
+ };
+
handleDesignerMount = (designer): void => {
const { editor } = this.props;
+ this.designer = designer;
editor.set('designer', designer);
editor.emit('designer.ready', designer);
};
render(): React.ReactNode {
const { editor } = this.props;
+ // const assets = editor.get('assets') || {};
return (
{
eventPipe={editor as any}
componentMetadatas={Object.values(assets.components) as any}
simulatorProps={{
- library: Object.values(assets.packages),
+ library: Object.values(assets.packages || {})
}}
/>
);
diff --git a/packages/editor/statics/assets.json b/packages/demo/statics/assets.json
similarity index 100%
rename from packages/editor/statics/assets.json
rename to packages/demo/statics/assets.json
diff --git a/packages/editor/statics/lowcode-renderer.js b/packages/demo/statics/lowcode-renderer.js
similarity index 100%
rename from packages/editor/statics/lowcode-renderer.js
rename to packages/demo/statics/lowcode-renderer.js
diff --git a/packages/editor-skeleton/tests/index.js b/packages/demo/tests/index.js
similarity index 100%
rename from packages/editor-skeleton/tests/index.js
rename to packages/demo/tests/index.js
diff --git a/packages/editor/tsconfig.json b/packages/demo/tsconfig.json
similarity index 100%
rename from packages/editor/tsconfig.json
rename to packages/demo/tsconfig.json
diff --git a/packages/editor-framework/.eslintignore b/packages/editor-core/.eslintignore
similarity index 100%
rename from packages/editor-framework/.eslintignore
rename to packages/editor-core/.eslintignore
diff --git a/packages/editor-core/.eslintrc.js b/packages/editor-core/.eslintrc.js
new file mode 100644
index 000000000..4d6be3c66
--- /dev/null
+++ b/packages/editor-core/.eslintrc.js
@@ -0,0 +1,16 @@
+const { tslint, deepmerge } = require('@ice/spec');
+
+module.exports = deepmerge(tslint, {
+ rules: {
+ "global-require": 0,
+ "comma-dangle": 0,
+ "no-unused-expressions": 0,
+ "object-shorthand": 0,
+ "jsx-a11y/anchor-has-content": 0,
+ "react/sort-comp": 0,
+ "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx", "ts"] }],
+ "@typescript-eslint/interface-name-prefix": 0,
+ "@typescript-eslint/no-explicit-any": 0,
+ "@typescript-eslint/explicit-member-accessibility": 0
+ },
+});
diff --git a/packages/editor-framework/.gitignore b/packages/editor-core/.gitignore
similarity index 100%
rename from packages/editor-framework/.gitignore
rename to packages/editor-core/.gitignore
diff --git a/packages/editor-framework/.prettierrc b/packages/editor-core/.prettierrc
similarity index 100%
rename from packages/editor-framework/.prettierrc
rename to packages/editor-core/.prettierrc
diff --git a/packages/editor-core/README.md b/packages/editor-core/README.md
new file mode 100644
index 000000000..6e9e79f5b
--- /dev/null
+++ b/packages/editor-core/README.md
@@ -0,0 +1,11 @@
+# demo component
+
+t-s-demo
+
+intro component
+
+## API
+
+| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |
+| ------ | ---- | ---- | ---- | ------ | ---- |
+| | | | | | |
diff --git a/packages/editor-framework/build.json b/packages/editor-core/build.json
similarity index 100%
rename from packages/editor-framework/build.json
rename to packages/editor-core/build.json
diff --git a/packages/editor-framework/package.json b/packages/editor-core/package.json
similarity index 84%
rename from packages/editor-framework/package.json
rename to packages/editor-core/package.json
index 3088159e2..1f50249c7 100644
--- a/packages/editor-framework/package.json
+++ b/packages/editor-core/package.json
@@ -1,5 +1,5 @@
{
- "name": "@ali/lowcode-editor",
+ "name": "@ali/lowcode-editor-core",
"version": "0.0.1",
"description": "alibaba lowcode editor core",
"files": [
@@ -13,7 +13,7 @@
"stylePath": "style.js",
"scripts": {
"start": "build-scripts start",
- "build": "build-scripts build",
+ "build": "build-scripts build --skip-demo",
"prepublishOnly": "npm run prettier && npm run build",
"lint": "eslint --cache --ext .js,.jsx ./",
"prettier": "prettier --write \"./src/**/*.{ts,tsx,js,jsx,ejs,less,css,scss,json}\" "
@@ -29,7 +29,8 @@
"intl-messageformat": "^7.8.4",
"lodash": "^4.17.15",
"prop-types": "^15.5.8",
- "store": "^2.0.12"
+ "store": "^2.0.12",
+ "whatwg-fetch": "^3.0.0"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.3",
@@ -51,5 +52,5 @@
"@alifd/next": "1.x"
},
"license": "MIT",
- "homepage": "https://unpkg.com/editor-framework@0.0.1/build/index.html"
+ "homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-editor-core@0.0.1/build/index.html"
}
diff --git a/packages/editor/src/framework/areaManager.ts b/packages/editor-core/src/areaManager.ts
similarity index 52%
rename from packages/editor/src/framework/areaManager.ts
rename to packages/editor-core/src/areaManager.ts
index 28f24eb0e..f6ce5e782 100644
--- a/packages/editor/src/framework/areaManager.ts
+++ b/packages/editor-core/src/areaManager.ts
@@ -1,4 +1,4 @@
-import { PluginConfig, PluginStatus } from './definitions';
+import { PluginConfig, PluginStatus, PluginClass, HOCPlugin } from './definitions';
import Editor from './index';
import { clone, deepEqual } from './utils';
@@ -18,14 +18,16 @@ export default class AreaManager {
this.pluginStatus = clone(editor.pluginStatus);
}
- public isPluginStatusUpdate(pluginType?: string): boolean {
+ public isPluginStatusUpdate(pluginType?: string, notUpdateStatus?: boolean): boolean {
const { pluginStatus } = this.editor;
const list = pluginType ? this.config.filter((item): boolean => item.type === pluginType) : this.config;
const isUpdate = list.some(
- (item): boolean => !deepEqual(pluginStatus[item.pluginKey], this.pluginStatus[item.pluginKey])
+ (item): boolean => !deepEqual(pluginStatus[item.pluginKey], this.pluginStatus[item.pluginKey]),
);
- this.pluginStatus = clone(pluginStatus);
+ if (!notUpdateStatus) {
+ this.pluginStatus = clone(pluginStatus);
+ }
return isUpdate;
}
@@ -36,7 +38,28 @@ export default class AreaManager {
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;
}
+
+ 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];
+ }
+ }
}
diff --git a/packages/editor/src/framework/context.ts b/packages/editor-core/src/context.ts
similarity index 100%
rename from packages/editor/src/framework/context.ts
rename to packages/editor-core/src/context.ts
diff --git a/packages/editor/src/framework/definitions.ts b/packages/editor-core/src/definitions.ts
similarity index 90%
rename from packages/editor/src/framework/definitions.ts
rename to packages/editor-core/src/definitions.ts
index 6bc6d2653..f9db0bd01 100644
--- a/packages/editor/src/framework/definitions.ts
+++ b/packages/editor-core/src/definitions.ts
@@ -25,7 +25,7 @@ export interface NpmConfig {
export interface SkeletonConfig {
config: NpmConfig;
props?: object;
- handler?: (EditorConfig) => EditorConfig;
+ handler?: (config: EditorConfig) => EditorConfig;
}
export interface FusionTheme {
@@ -38,7 +38,7 @@ export interface ThemeConfig {
}
export interface PluginsConfig {
- [propName: string]: PluginConfig[];
+ [key: string]: PluginConfig[];
}
export interface PluginConfig {
@@ -68,7 +68,7 @@ export type HooksConfig = HookConfig[];
export interface HookConfig {
message: string;
type: 'on' | 'once';
- handler: (editor: Editor, ...args) => void;
+ handler: (editor: Editor, ...args: []) => void;
}
export type ShortCutsConfig = ShortCutConfig[];
@@ -83,7 +83,7 @@ export type UtilsConfig = UtilConfig[];
export interface UtilConfig {
name: string;
type: 'npm' | 'function';
- content: NpmConfig | ((...args) => any);
+ content: NpmConfig | ((...args: []) => any);
}
export type ConstantsConfig = object;
@@ -109,7 +109,7 @@ export interface I18nConfig {
export type I18nFunction = (key: string, params: any) => string;
export interface Utils {
- [key: string]: (...args) => any;
+ [key: string]: (...args: []) => any;
}
export interface PluginProps {
@@ -136,6 +136,10 @@ export interface PluginSet {
export type PluginClass = React.ComponentType & {
init?: (editor: Editor) => void;
+ defaultProps?: {
+ locale?: LocaleType;
+ messages?: I18nMessages;
+ };
};
export interface PluginClassSet {
diff --git a/packages/editor/src/framework/editor.ts b/packages/editor-core/src/editor.ts
similarity index 90%
rename from packages/editor/src/framework/editor.ts
rename to packages/editor-core/src/editor.ts
index cf1147e2c..6a0b938a0 100644
--- a/packages/editor/src/framework/editor.ts
+++ b/packages/editor-core/src/editor.ts
@@ -1,5 +1,5 @@
import Debug from 'debug';
-import EventEmitter from 'events';
+import { EventEmitter } from 'events';
import store from 'store';
import {
EditorConfig,
@@ -8,7 +8,7 @@ import {
PluginStatusSet,
Utils,
PluginClassSet,
- PluginSet
+ PluginSet,
} from './definitions';
import * as editorUtils from './utils';
@@ -64,7 +64,7 @@ const debug = Debug('editor');
EventEmitter.defaultMaxListeners = 100;
export interface HooksFuncs {
- [idx: number]: (msg: string, handler: (...args) => void) => void;
+ [idx: number]: (msg: string, handler: (...args: []) => void) => void;
}
export default class Editor extends EventEmitter {
@@ -87,14 +87,6 @@ export default class Editor extends EventEmitter {
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) {
@@ -103,7 +95,6 @@ export default class Editor extends EventEmitter {
this.components = components;
this.utils = { ...editorUtils, ...utils };
instance = this;
- this.init();
}
public init(): Promise {
@@ -165,21 +156,27 @@ export default class Editor extends EventEmitter {
if (!Array.isArray(events)) {
return;
}
- events.forEach((event): void => this.on(event, lisenter));
+ events.forEach((event): void => {
+ this.on(event, lisenter);
+ });
}
public batchOnce(events: string[], lisenter: (...args) => void): void {
if (!Array.isArray(events)) {
return;
}
- events.forEach((event): void => this.once(event, lisenter));
+ events.forEach((event): void => {
+ this.once(event, lisenter);
+ });
}
public batchOff(events: string[], lisenter: (...args) => void): void {
if (!Array.isArray(events)) {
return;
}
- events.forEach((event): void => this.off(event, lisenter));
+ events.forEach((event): void => {
+ this.off(event, lisenter);
+ });
}
// 销毁hooks中的消息监听
@@ -216,7 +213,7 @@ export default class Editor extends EventEmitter {
res[plugin.pluginKey] = {
visible: typeof visible === 'boolean' ? visible : true,
disabled: typeof disabled === 'boolean' ? disabled : false,
- marked: typeof marked === 'boolean' ? marked : false
+ marked: typeof marked === 'boolean' ? marked : false,
};
const pluginClass = this.components[plugin.pluginKey];
// 判断如果编辑器插件有init静态方法,则在此执行init方法
diff --git a/packages/editor/src/framework/index.ts b/packages/editor-core/src/index.ts
similarity index 50%
rename from packages/editor/src/framework/index.ts
rename to packages/editor-core/src/index.ts
index 72af6e859..fba0e30c9 100644
--- a/packages/editor/src/framework/index.ts
+++ b/packages/editor-core/src/index.ts
@@ -1,12 +1,12 @@
import Editor from './editor';
-import * as editorUtils from './utils';
-import * as editorDefinitions from './definitions';
+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 const utils = editorUtils;
-export const definitions = editorDefinitions;
+export { utils, definitions };
diff --git a/packages/editor/src/framework/pluginFactory.tsx b/packages/editor-core/src/pluginFactory.tsx
similarity index 82%
rename from packages/editor/src/framework/pluginFactory.tsx
rename to packages/editor-core/src/pluginFactory.tsx
index f32edd9e9..2eff60e9e 100644
--- a/packages/editor/src/framework/pluginFactory.tsx
+++ b/packages/editor-core/src/pluginFactory.tsx
@@ -27,21 +27,26 @@ export default function pluginFactory(Comp: PluginClass): React.ComponentType();
// 注册插件
this.editor = editor;
- this.i18n = generateI18n(locale, messages);
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.plugins,
- [this.pluginKey]: this
+ [this.pluginKey]: this,
});
}
public componentWillUnmount(): void {
// 销毁插件
- if (this.editor && this.editor.plugins) {
+ if (this.pluginKey && this.editor && this.editor.plugins) {
delete this.editor.plugins[this.pluginKey];
}
}
@@ -66,7 +71,7 @@ export default function pluginFactory(Comp: PluginClass): React.ComponentType {
+ if (val === null || val === undefined || val === '') return;
+ if (typeof val === 'object') rst.push(`${key}=${encodeURIComponent(JSON.stringify(val))}`);
+ else rst.push(`${key}=${encodeURIComponent(val)}`);
+ });
+ return rst.join('&');
+}
+
+export function buildUrl(dataAPI: string, params: object): string {
+ const paramStr = serialize(params);
+ if (paramStr) {
+ return dataAPI.indexOf('?') > 0 ? `${dataAPI}&${paramStr}` : `${dataAPI}?${paramStr}`;
+ }
+ return dataAPI;
+}
+
+export function get(dataAPI: string, params?: object, headers?: object, otherProps?: object): Promise {
+ const fetchHeaders = {
+ Accept: 'application/json',
+ ...headers,
+ };
+ return request(buildUrl(dataAPI, params), 'GET', null, fetchHeaders, otherProps);
+}
+
+export function post(dataAPI: string, params?: object, headers?: object, otherProps?: object): Promise {
+ const fetchHeaders = {
+ Accept: 'application/json',
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ ...headers,
+ };
+ return request(
+ dataAPI,
+ 'POST',
+ fetchHeaders['Content-Type'].indexOf('application/json') > -1 || Array.isArray(params)
+ ? JSON.stringify(params)
+ : serialize(params),
+ fetchHeaders,
+ otherProps,
+ );
+}
+
+export function request(
+ dataAPI: string,
+ method: string = 'GET',
+ data?: object | string,
+ headers?: object,
+ otherProps?: object,
+): Promise {
+ return new Promise((resolve, reject): void => {
+ if (otherProps && otherProps.timeout) {
+ setTimeout((): void => {
+ reject(new Error('timeout'));
+ }, otherProps.timeout);
+ }
+ fetch(dataAPI, {
+ method,
+ credentials: 'include',
+ headers,
+ body: data,
+ ...otherProps,
+ })
+ .then((response: Response): any => {
+ switch (response.status) {
+ case 200:
+ case 201:
+ case 202:
+ return response.json();
+ case 204:
+ if (method === 'DELETE') {
+ return {
+ success: true,
+ };
+ } else {
+ return {
+ __success: false,
+ code: response.status,
+ };
+ }
+ case 400:
+ case 401:
+ case 403:
+ case 404:
+ case 406:
+ case 410:
+ case 422:
+ case 500:
+ return response
+ .json()
+ .then((res: object): any => {
+ return {
+ __success: false,
+ code: response.status,
+ data: res,
+ };
+ })
+ .catch((): object => {
+ return {
+ __success: false,
+ code: response.status,
+ };
+ });
+ default:
+ return null;
+ }
+ })
+ .then((json: object): void => {
+ if (json && json.__success !== false) {
+ resolve(json);
+ } else {
+ delete json.__success;
+ reject(json);
+ }
+ })
+ .catch((err: Error): void => {
+ debug(err);
+ reject(err);
+ });
+ });
+}
diff --git a/packages/editor/src/framework/utils.ts b/packages/editor-core/src/utils.ts
similarity index 96%
rename from packages/editor/src/framework/utils.ts
rename to packages/editor-core/src/utils.ts
index aced7d318..dd6d6d251 100644
--- a/packages/editor/src/framework/utils.ts
+++ b/packages/editor-core/src/utils.ts
@@ -9,6 +9,7 @@ import _pick from 'lodash/pick';
import _throttle from 'lodash/throttle';
import _serialize from 'serialize-javascript';
+export { get, post, request } from './request';
import Editor from './editor';
import { EditorConfig, I18nFunction, I18nMessages, LocaleType, ShortCutsConfig } from './definitions';
@@ -25,7 +26,7 @@ const ENV = {
TBE: 'TBE',
WEBIDE: 'WEB-IDE',
VSCODE: 'VSCODE',
- WEB: 'WEB'
+ WEB: 'WEB',
};
declare global {
@@ -92,7 +93,7 @@ export function goldlog(gmKey: string, params: object = {}, logKey: string = 'ot
const sendIDEMessage = window.sendIDEMessage || window.parent.sendIDEMessage;
const goKey = serializeParams({
env: getEnv(),
- ...params
+ ...params,
});
if (sendIDEMessage) {
sendIDEMessage({
@@ -100,8 +101,8 @@ export function goldlog(gmKey: string, params: object = {}, logKey: string = 'ot
data: {
logKey: `/iceluna.core.${logKey}`,
gmKey,
- goKey
- }
+ goKey,
+ },
});
}
if (window.goldlog) {
@@ -214,7 +215,7 @@ export function comboEditorConfig(defaultConfig: EditorConfig = {}, customConfig
if (skeleton && skeleton.handler && typeof skeleton.handler === 'function') {
return skeleton.handler({
skeleton,
- ...defaultConfig
+ ...defaultConfig,
});
}
@@ -225,34 +226,34 @@ export function comboEditorConfig(defaultConfig: EditorConfig = {}, customConfig
localeList.forEach((key): void => {
i18nConfig[key] = {
...(defaultConfig.i18n && defaultConfig.i18n[key]),
- ...(i18n && i18n[key])
+ ...(i18n && i18n[key]),
};
});
return {
skeleton,
theme: {
...defaultConfig.theme,
- ...theme
+ ...theme,
},
plugins: {
...defaultConfig.plugins,
- ...plugins
+ ...plugins,
},
hooks: [...(defaultConfig.hooks || []), ...(hooks || [])],
shortCuts: Object.values({
...defaultShortCuts,
- ...customShortCuts
+ ...customShortCuts,
}),
lifeCycles: {
...defaultConfig.lifeCycles,
- ...lifeCycles
+ ...lifeCycles,
},
constants: {
...defaultConfig.constants,
- ...constants
+ ...constants,
},
utils: [...(defaultConfig.utils || []), ...(utils || [])],
- i18n: i18nConfig
+ i18n: i18nConfig,
};
}
diff --git a/packages/editor-framework/tsconfig.json b/packages/editor-core/tsconfig.json
similarity index 100%
rename from packages/editor-framework/tsconfig.json
rename to packages/editor-core/tsconfig.json
diff --git a/packages/editor-framework/.eslintrc.js b/packages/editor-framework/.eslintrc.js
deleted file mode 100644
index ebda54735..000000000
--- a/packages/editor-framework/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const { eslint, deepmerge } = require('@ice/spec');
-
-module.exports = deepmerge(eslint, {
- rules: {},
-});
diff --git a/packages/editor-framework/demo/usage.md b/packages/editor-framework/demo/usage.md
deleted file mode 100644
index 9f19eae0b..000000000
--- a/packages/editor-framework/demo/usage.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-title: Simple Usage
-order: 1
----
-
-本 Demo 演示一行文字的用法。
-
-````jsx
-import React, { Component } from 'react';
-import ReactDOM from 'react-dom';
-
-class App extends Component {
- render() {
- return (
-
-
- );
- }
-}
-
-ReactDOM.render((
-
-), mountNode);
-````
diff --git a/packages/editor-framework/src/context.ts b/packages/editor-framework/src/context.ts
deleted file mode 100644
index 78d3ce177..000000000
--- a/packages/editor-framework/src/context.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { createContext } from 'react';
-const context = createContext({});
-export default context;
diff --git a/packages/editor-framework/src/definitions.ts b/packages/editor-framework/src/definitions.ts
deleted file mode 100644
index 87dd5dca2..000000000
--- a/packages/editor-framework/src/definitions.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-
-export interface EditorConfig {
-
-};
-
-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 {
- [key]: Array
-};
-
-export interface PluginConfig {
- pluginKey: string,
- type: string,
- props: object,
- config: NpmConfig,
- pluginProps: object
-};
-
-export type HooksConfig = Array;
-
-export interface HookConfig {
-
-};
-
-
diff --git a/packages/editor-framework/src/editor.ts b/packages/editor-framework/src/editor.ts
deleted file mode 100644
index b3328df2d..000000000
--- a/packages/editor-framework/src/editor.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-import EventEmitter from 'events';
-import Debug from 'debug';
-import store from 'store';
-
-import {
- unRegistShortCuts,
- registShortCuts,
- transformToPromise,
- generateI18n
-} from './utils';
-
-// 根据url参数设置debug选项
-const res = /_?debug=(.*?)(&|$)/.exec(location.search);
-if (res && res[1]) {
- window.__isDebug = true;
- store.storage.write('debug', res[1] === 'true' ? '*' : res[1]);
-} else {
- window.__isDebug = false;
- store.remove('debug');
-}
-
-//重要,用于矫正画布执行new Function的window对象上下文
-window.__newFunc = funContext => {
- return new Function(funContext);
-};
-
-//关闭浏览器前提醒,只有产生过交互才会生效
-window.onbeforeunload = function(e) {
- e = e || window.event;
- // 本地调试不生效
- if (location.href.indexOf('localhost') > 0) return;
- var msg = '您确定要离开此页面吗?';
- e.cancelBubble = true;
- e.returnValue = msg;
- if (e.stopPropagation) {
- e.stopPropagation();
- e.preventDefault();
- }
- return msg;
-};
-
-
-let instance = null;
-const debug = Debug('editor');
-EventEmitter.defaultMaxListeners = 100;
-
-export interface editor {
-
-};
-
-export default class Editor extends EventEmitter {
- static getInstance = () => {
- if (!instance) {
- instance = new Editor();
- }
- return instance;
- };
-
- constructor(config) {
- super();
- instance = this;
- Object.assign(this, config);
- this.init();
- }
-
- init() {
- const {
- hooks,
- shortCuts,
- lifeCycles
- } = this.config || {};
- this.destroy();
- 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, appHelper);
-
- appHelper.emit('editor.beforeInit');
- const init = lifeCycles && lifeCycles.init || () => {};
- // 用户可以通过设置extensions.init自定义初始化流程;
- transformToPromise(init(this))
- .then(() => {
- // 注册快捷键
- registShortCuts(shortCuts, this);
- this.emit('editor.afterInit');
- })
- .catch(err => {
- console.warn(err);
- });
- }
-
- destroy() {
- try {
- const {
- hooks = [],
- shortCuts = [],
- lifeCycles = {}
- } = this.config;
- unRegistShortCuts(shortCuts);
- this.destroyHooks(hooks);
- lifeCycles.destroy && lifeCycles.destroy();
- } catch (err) {
- console.warn(err);
- return;
- }
- }
-
- get(key:string):any {
- return this[key];
- }
-
- set(key:string|object, val:any):void {
- if (typeof key === 'string') {
- if (['init', 'destroy', 'get', 'set', 'batchOn', 'batchOff', 'batchOnce'].includes(key)) {
- console.warning('init, destroy, get, set, batchOn, batchOff, batchOnce is private attribute');
- return;
- }
- this[key] = val;
- } else if (typeof key === 'object') {
- Object.keys(key).forEach(item => {
- this[item] = key[item];
- });
- }
- }
-
- batchOn(events:Array, lisenter:function):void {
- if (!Array.isArray(events)) return;
- events.forEach(event => this.on(event, lisenter));
- }
-
- batchOnce(events:Array, lisenter:function):void {
- if (!Array.isArray(events)) return;
- events.forEach(event => this.once(event, lisenter));
- }
-
- batchOff(events:Array, lisenter:function):void {
- if (!Array.isArray(events)) return;
- events.forEach(event => this.off(event, lisenter));
- }
-
- //销毁hooks中的消息监听
- private destroyHooks(hooks = []) {
- hooks.forEach((item, idx) => {
- if (typeof this.__hooksFuncs[idx] === 'function') {
- this.appHelper.off(item.message, this.__hooksFuncs[idx]);
- }
- });
- delete this.__hooksFuncs;
- };
-
- //初始化hooks中的消息监听
- private initHooks(hooks = []) {
- this.__hooksFuncs = hooks.map(item => {
- const func = (...args) => {
- item.handler(this, ...args);
- };
- this[item.type](item.message, func);
- return func;
- });
- };
-
-
- private initPluginStatus () {
- const {plugins = {}} = this.config;
- const pluginAreas = Object.keys(plugins);
- const res = {};
- pluginAreas.forEach(area => {
- (plugins[area] || []).forEach(plugin => {
- if (plugin.type === 'Divider') return;
- const { visible, disabled, dotted } = plugin.props || {};
- res[plugin.pluginKey] = {
- visible: typeof visible === 'boolean' ? visible : true,
- disabled: typeof disabled === 'boolean' ? disabled : false,
- dotted: typeof dotted === 'boolean' ? dotted : false
- };
- const pluginClass = this.props.components[skeletonUtils.generateAddonCompName(addon.addonKey)];
- // 判断如果编辑器插件有init静态方法,则在此执行init方法
- if (pluginClass && pluginClass.init) {
- pluginClass.init(this);
- }
- });
- });
- return res;
- };
-}
diff --git a/packages/editor-framework/src/index.ts b/packages/editor-framework/src/index.ts
deleted file mode 100644
index aac18d138..000000000
--- a/packages/editor-framework/src/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import Editor from './editor';
-
-
-export default Editor;
\ No newline at end of file
diff --git a/packages/editor-framework/src/plugin.ts b/packages/editor-framework/src/plugin.ts
deleted file mode 100644
index 33d81cc48..000000000
--- a/packages/editor-framework/src/plugin.ts
+++ /dev/null
@@ -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 {
- 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
- }
- }
-
- return Plugin;
-}
-
-
-
-export class Plugin extends PureComponent {
- 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;
- }
-}
diff --git a/packages/editor-framework/src/utils.ts b/packages/editor-framework/src/utils.ts
deleted file mode 100644
index d1c5eaf2b..000000000
--- a/packages/editor-framework/src/utils.ts
+++ /dev/null
@@ -1,242 +0,0 @@
-
-import IntlMessageFormat from 'intl-messageformat';
-import _isEmpty from 'lodash/isEmpty';
-
-export const isEmpty = _isEmpty;
-
-/**
- * 用于构造国际化字符串处理函数
- * @param {*} locale 国际化标识,例如 zh-CN、en-US
- * @param {*} messages 国际化语言包
- */
-export function generateI18n(locale = 'zh-CN', messages = {}) {
- return (key, values = {}) => {
- if (!messages || !messages[key]) return '';
- const formater = new IntlMessageFormat(messages[key], locale);
- return formater.format(values);
- };
-}
-
-/**
- * 序列化参数
- * @param {*} obj 参数
- */
-export function serializeParams(obj:object):string {
- if (typeof obj !== 'object') return '';
-
- const res:Array = [];
- Object.entries(obj).forEach(([key, val]) => {
- 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 = 'other') {
- const sendIDEMessage = window.sendIDEMessage || window.parent.sendIDEMessage;
- const goKey = serializeParams({
- sdkVersion: pkg.version,
- env: getEnv(),
- ...params
- });
- if (sendIDEMessage) {
- sendIDEMessage({
- action: 'goldlog',
- data: {
- logKey: `/iceluna.core.${logKey}`,
- gmKey,
- goKey
- }
- });
- }
- window.goldlog && window.goldlog.record(`/iceluna.core.${logKey}`, gmKey, goKey, 'POST');
-}
-
-/**
- * 获取当前编辑器环境
- */
-export function getEnv() {
- 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, editor) {
- const keyboardFilter = (keymaster.filter = event => {
- let eTarget = event.target || event.srcElement;
- 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();
- item.handler(ev, appHelper, keymaster);
- });
- });
-}
-
-// 取消注册快捷
-export function unRegistShortCuts(config) {
- (config || []).forEach(item => {
- keymaster.unbind(item.keyboard);
- });
- if (window.parent.vscode) {
- keymaster.unbind('command+c');
- 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) {
- if (input instanceof Promise) return input;
- return new Promise((resolve, reject) => {
- if (input || input === undefined) {
- resolve();
- } else {
- reject();
- }
- });
-}
-
-export function comboEditorConfig(defaultConfig, customConfig) {
- const { ideConfig = {}, utils = {} } = this.props;
- const comboShortCuts = () => {
- const defaultShortCuts = defaultIdeConfig.shortCuts;
- const shortCuts = ideConfig.shortCuts || [];
- const configMap = skeletonUtils.transformArrayToMap(defaultShortCuts, 'keyboard');
- (shortCuts || []).forEach(item => {
- configMap[item.keyboard] = item;
- });
- return Object.keys(configMap).map(key => configMap[key]);
- };
- return {
- ...ideConfig,
- utils: {
- ...skeletonUtils,
- ...utils
- },
- constants: {
- ...defaultIdeConfig.constants,
- ...ideConfig.constants
- },
- extensions: {
- ...defaultIdeConfig.extensions,
- ...ideConfig.extensions
- },
- shortCuts: comboShortCuts()
- };
-}
\ No newline at end of file
diff --git a/packages/editor-skeleton/.eslintrc.js b/packages/editor-skeleton/.eslintrc.js
index 18ae6baa7..4d6be3c66 100644
--- a/packages/editor-skeleton/.eslintrc.js
+++ b/packages/editor-skeleton/.eslintrc.js
@@ -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: {
"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
},
});
diff --git a/packages/editor-skeleton/demo/usage.md b/packages/editor-skeleton/demo/usage.md
deleted file mode 100644
index 9f19eae0b..000000000
--- a/packages/editor-skeleton/demo/usage.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-title: Simple Usage
-order: 1
----
-
-本 Demo 演示一行文字的用法。
-
-````jsx
-import React, { Component } from 'react';
-import ReactDOM from 'react-dom';
-
-class App extends Component {
- render() {
- return (
-
-
- );
- }
-}
-
-ReactDOM.render((
-
-), mountNode);
-````
diff --git a/packages/editor-skeleton/package.json b/packages/editor-skeleton/package.json
index 73adadb4c..d3b4976db 100644
--- a/packages/editor-skeleton/package.json
+++ b/packages/editor-skeleton/package.json
@@ -1,5 +1,5 @@
{
- "name": "@ali/lowcode-skeleton",
+ "name": "@ali/lowcode-editor-skeleton",
"version": "0.0.1",
"description": "alibaba lowcode editor skeleton",
"files": [
@@ -24,15 +24,13 @@
],
"author": "xiayang.xy",
"dependencies": {
+ "@ali/lowcode-editor-core": "0.0.1",
"@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",
- "react": "^16.4.1",
- "react-dom": "^16.4.1",
- "react-router-dom": "^5.0.1"
+ "react": "^16.8.1",
+ "react-dom": "^16.8.1",
+ "react-router-dom": "^5.1.2",
+ "store": "^2.0.12"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.3",
diff --git a/packages/editor-skeleton/src/components/LeftIcon/index.tsx b/packages/editor-skeleton/src/components/LeftIcon/index.tsx
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/editor-skeleton/src/components/LeftPlugin/index.scss b/packages/editor-skeleton/src/components/LeftPlugin/index.scss
index 9c6922129..f78fca1ee 100644
--- a/packages/editor-skeleton/src/components/LeftPlugin/index.scss
+++ b/packages/editor-skeleton/src/components/LeftPlugin/index.scss
@@ -1,59 +1,59 @@
-.luna-left-addon {
- font-size: 16px;
+.lowcode-left-plugin {
+ font-size: 20px;
text-align: center;
- line-height: 36px;
- height: 36px;
+ line-height: 44px;
+ height: 44px;
position: relative;
cursor: pointer;
transition: all 0.3s ease;
- color: #777;
- &.collapse {
- height: 40px;
- color: #8c8c8c;
- border-bottom: 1px solid #bfbfbf;
- }
+ color: $color-text1-3;
&.locked {
color: red !important;
}
- &.active {
- color: #fff !important;
- background-color: $color-brand1-9 !important;
- &.disabled {
- color: #fff;
- background-color: $color-fill1-7;
- }
- }
- &.disabled {
- cursor: not-allowed;
- color: $color-text1-1;
- }
&:hover {
- background-color: $color-brand1-1;
color: $color-brand1-6;
&:before {
content: attr(data-tooltip);
display: block;
position: absolute;
- left: 50px;
- top: 5px;
+ left: 45px;
+ top: 8px;
line-height: 18px;
font-size: 12px;
white-space: nowrap;
padding: 6px 8px;
border-radius: 4px;
- background: rgba(0, 0, 0, 0.75);
- color: #fff;
+ background: $balloon-normal-color-bg;
+ border: 1px solid $balloon-normal-color-border;
+ color: $color-text1-3;
z-index: 100;
}
&:after {
content: '';
display: block;
position: absolute;
+ width: 10px;
+ height: 10px;
+ transform: rotate(45deg);
left: 40px;
- top: 15px;
- border: 5px solid transparent;
- border-right-color: rgba(0, 0, 0, 0.75);
+ top: 18px;
+ background: $balloon-normal-color-bg;
+ border-left: 1px solid $balloon-normal-color-border;
+ border-bottom: 1px solid $balloon-normal-color-border;
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;
+ }
}
diff --git a/packages/editor-skeleton/src/components/LeftPlugin/index.tsx b/packages/editor-skeleton/src/components/LeftPlugin/index.tsx
index d9a637a21..7770c942c 100644
--- a/packages/editor-skeleton/src/components/LeftPlugin/index.tsx
+++ b/packages/editor-skeleton/src/components/LeftPlugin/index.tsx
@@ -1,79 +1,74 @@
import React, { PureComponent, Fragment } from 'react';
-
-import PropTypes from 'prop-types';
import classNames from 'classnames';
-import AppContext from '@ali/iceluna-sdk/lib/context/appContext';
-import { Balloon, Dialog, Icon, Badge } from '@alife/next';
-
+import { Balloon, Dialog, Icon, Badge } from '@alifd/next';
+import Editor from '@ali/lowcode-editor-core';
+import {
+ PluginConfig,
+ PluginClass,
+} from '@ali/lowcode-editor-core/lib/definitions';
import './index.scss';
-export default class LeftAddon extends PureComponent {
- static displayName = 'LunaLeftAddon';
- static propTypes = {
- 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,
- };
+
+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 = 'LowcodeLeftPlugin';
+
static defaultProps = {
active: false,
config: {},
disabled: false,
- dotted: false,
+ marked: false,
locked: false,
- onClick: () => {},
+ onClick: (): void => {},
};
- static contextType = AppContext;
constructor(props, context) {
super(props, context);
this.state = {
dialogVisible: false,
};
- this.appHelper = context.appHelper;
- this.utils = this.appHelper.utils;
- this.constants = this.appHelper.constants;
}
- componentDidMount() {
- const { config } = this.props;
- const addonKey = config && config.addonKey;
- const appHelper = this.appHelper;
- if (appHelper && addonKey) {
- appHelper.on(`${addonKey}.dialog.show`, this.handleShow);
- appHelper.on(`${addonKey}.dialog.close`, this.handleClose);
+ 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() {
- const { config } = this.props;
- const appHelper = this.appHelper;
- const addonKey = config && config.addonKey;
- if (appHelper && addonKey) {
- appHelper.off(`${addonKey}.dialog.show`, this.handleShow);
- appHelper.off(`${addonKey}.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 = () => {
- const addonKey = this.props.config && this.props.config.addonKey;
- const currentAddon =
- this.appHelper.addons && this.appHelper.addons[addonKey];
- if (currentAddon) {
- this.utils.transformToPromise(currentAddon.close()).then(() => {
+ handleClose = (): void => {
+ const { config, editor } = this.props;
+ const pluginKey = config && config.pluginKey;
+ const plugin = editor.plugins && editor.plugins[pluginKey];
+ if (plugin) {
+ plugin.close().then((): void => {
this.setState({
dialogVisible: false,
});
@@ -81,43 +76,48 @@ export default class LeftAddon extends PureComponent {
}
};
- handleOpen = () => {
+ handleOpen = (): void => {
// todo 对话框类型的插件初始时拿不到插件实例
this.setState({
dialogVisible: true,
});
};
- handleShow = () => {
- const { disabled, config, onClick } = this.props;
- const addonKey = config && config.addonKey;
- if (disabled || !addonKey) return;
- //考虑到弹窗情况,延时发送消息
- setTimeout(() => this.appHelper.emit(`${addonKey}.addon.activate`), 0);
+ handleShow = (): void => {
+ const { disabled, config, onClick, editor } = this.props;
+ const pluginKey = config && config.pluginKey;
+ if (disabled || !pluginKey) return;
this.handleOpen();
- onClick && onClick();
+ // 考虑到弹窗情况,延时发送消息
+ setTimeout((): void => {
+ editor.emit(`${pluginKey}.plugin.activate`);
+ }, 0);
+ if (onClick) {
+ onClick();
+ }
};
- renderIcon = clickCallback => {
- const { active, disabled, dotted, locked, onClick, config } = this.props;
- const { addonKey, props } = config || {};
+ renderIcon = (clickCallback): React.ReactNode => {
+ const { active, disabled, marked, locked, onClick, config } = this.props;
+ const { pluginKey, props } = config || {};
const { icon, title } = props || {};
return (
{
+ onClick={(): void => {
if (disabled) return;
- //考虑到弹窗情况,延时发送消息
+ // 考虑到弹窗情况,延时发送消息
clickCallback && clickCallback();
+
onClick && onClick();
}}
>
- {dotted ? (
+ {marked ? (
@@ -128,67 +128,66 @@ export default class LeftAddon extends PureComponent {
);
};
- render() {
- const { dotted, locked, active, disabled, config } = this.props;
- const { addonKey, props, type, addonProps } = config || {};
+ 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;
- const { appHelper, components } = this.context;
- 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 && (
-
{
- onClick && onClick.call(null, appHelper);
- }}
- {...localeProps}
- {...(addonProps || {})}
- />
- )) ||
- null;
+ if (!pluginKey || !type || !props) return null;
+ const node = Comp ? (
+ {
+ onClick && onClick.call(null, editor);
+ }}
+ {...pluginProps}
+ />
+ ) : null;
switch (type) {
case 'LinkIcon':
return (
- {this.renderIcon(() => {
- onClick && onClick.call(null, appHelper);
+ {this.renderIcon((): void => {
+ onClick && onClick.call(null, editor);
})}
);
case 'Icon':
- return this.renderIcon(() => {
- onClick && onClick.call(null, appHelper);
+ return this.renderIcon((): void => {
+ onClick && onClick.call(null, editor);
});
case 'DialogIcon':
return (
- {this.renderIcon(() => {
- onClick && onClick.call(null, appHelper);
+ {this.renderIcon((): void => {
+ onClick && onClick.call(null, editor);
this.handleOpen();
})}
);
}
}
diff --git a/packages/editor-skeleton/src/components/TopPlugin/index.tsx b/packages/editor-skeleton/src/components/TopPlugin/index.tsx
index 04f5d0e59..71eccf28a 100644
--- a/packages/editor-skeleton/src/components/TopPlugin/index.tsx
+++ b/packages/editor-skeleton/src/components/TopPlugin/index.tsx
@@ -1,20 +1,43 @@
import React, { PureComponent, Fragment } from 'react';
-import PropTypes from 'prop-types';
-import TopIcon from '../TopIcon';
import { Balloon, Badge, Dialog } from '@alifd/next';
+import Editor from '@ali/lowcode-editor-core';
+import {
+ PluginConfig,
+ PluginClass,
+} from '@ali/lowcode-editor-core/lib/definitions';
+import TopIcon from '../TopIcon';
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 = {
active: false,
config: {},
disabled: false,
- dotted: false,
+ marked: false,
locked: false,
- onClick: () => {},
+ onClick: (): void => {},
};
constructor(props, context) {
@@ -24,42 +47,42 @@ export default class TopPlugin extends PureComponent {
};
}
- componentDidMount() {
- const { config } = this.props;
+ componentDidMount(): void {
+ const { config, editor } = this.props;
const pluginKey = config && config.pluginKey;
- // const appHelper = this.appHelper;
- // if (appHelper && addonKey) {
- // appHelper.on(`${addonKey}.dialog.show`, this.handleShow);
- // appHelper.on(`${addonKey}.dialog.close`, this.handleClose);
- // }
+ if (editor && pluginKey) {
+ editor.on(`${pluginKey}.dialog.show`, this.handleShow);
+ editor.on(`${pluginKey}.dialog.close`, this.handleClose);
+ }
}
- componentWillUnmount() {
- // const { config } = this.props;
- // const addonKey = config && config.addonKey;
- // const appHelper = this.appHelper;
- // if (appHelper && addonKey) {
- // appHelper.off(`${addonKey}.dialog.show`, this.handleShow);
- // appHelper.off(`${addonKey}.dialog.close`, this.handleClose);
- // }
+ componentWillUnmount(): void {
+ const { config, editor } = this.props;
+ const pluginKey = config && config.pluginKey;
+ if (editor && pluginKey) {
+ editor.off(`${pluginKey}.dialog.show`, this.handleShow);
+ editor.off(`${pluginKey}.dialog.close`, this.handleClose);
+ }
}
- handleShow = () => {
- const { disabled, config, onClick } = this.props;
- const addonKey = config && config.addonKey;
- if (disabled || !addonKey) return;
- //考虑到弹窗情况,延时发送消息
- setTimeout(() => this.appHelper.emit(`${addonKey}.addon.activate`), 0);
+ handleShow = (): void => {
+ const { disabled, config, onClick, editor } = this.props;
+ const pluginKey = config && config.pluginKey;
+ if (disabled || !pluginKey) return;
this.handleOpen();
+ // 考虑到弹窗情况,延时发送消息
+ setTimeout((): void => {
+ editor.emit(`${pluginKey}.plugin.activate`);
+ }, 0);
onClick && onClick();
};
- handleClose = () => {
- const addonKey = this.props.config && this.props.config.addonKey;
- const currentAddon =
- this.appHelper.addons && this.appHelper.addons[addonKey];
- if (currentAddon) {
- this.utils.transformToPromise(currentAddon.close()).then(() => {
+ handleClose = (): void => {
+ const { config, editor } = this.props;
+ const pluginKey = config && config.pluginKey;
+ const plugin = editor.plugins && editor.plugins[pluginKey];
+ if (plugin) {
+ plugin.close().then((): void => {
this.setState({
dialogVisible: false,
});
@@ -67,85 +90,107 @@ export default class TopPlugin extends PureComponent {
}
};
- handleOpen = () => {
+ handleOpen = (): void => {
// todo dialog类型的插件初始时拿不动插件实例
this.setState({
dialogVisible: true,
});
};
- renderIcon = clickCallback => {
- const { active, disabled, dotted, locked, config, onClick } = this.props;
+ renderIcon = (clickCallback): React.ReactNode => {
+ const {
+ active,
+ disabled,
+ marked,
+ locked,
+ config,
+ onClick,
+ editor,
+ } = this.props;
const { pluginKey, props } = config || {};
const { icon, title } = props || {};
const node = (
{
+ onClick={(): void => {
if (disabled) return;
- //考虑到弹窗情况,延时发送消息
- setTimeout(
- () => this.appHelper.emit(`${pluginKey}.addon.activate`),
- 0,
- );
+ // 考虑到弹窗情况,延时发送消息
+ setTimeout((): void => {
+ editor.emit(`${pluginKey}.plugin.activate`);
+ }, 0);
clickCallback && clickCallback();
onClick && onClick();
}}
/>
);
- return dotted ? {node} : node;
+ return marked ? {node} : node;
};
- render() {
- const { active, dotted, locked, disabled, config, editor, pluginClass: Comp } = this.props;
+ render(): React.ReactNode {
+ const {
+ active,
+ marked,
+ locked,
+ disabled,
+ config,
+ editor,
+ pluginClass: Comp,
+ } = this.props;
const { pluginKey, pluginProps, props, type } = config || {};
const { onClick, title } = props || {};
const { dialogVisible } = this.state;
- if (!pluginKey || !type || !Comp) return null;
- const node = {
- onClick && onClick.call(null, editor);
- }}
- {...pluginProps}
- />;
+ if (!pluginKey || !type) return null;
+ const node = Comp ? (
+ {
+ onClick && onClick.call(null, editor);
+ }}
+ {...pluginProps}
+ />
+ ) : null;
switch (type) {
case 'LinkIcon':
return (
- {this.renderIcon(() => {
+ {this.renderIcon((): void => {
onClick && onClick.call(null, editor);
})}
);
case 'Icon':
- return this.renderIcon(() => {
+ return this.renderIcon((): void => {
onClick && onClick.call(null, editor);
});
case 'DialogIcon':
return (
- {this.renderIcon(() => {
+ {this.renderIcon((): void => {
onClick && onClick.call(null, editor);
this.handleOpen();
})}