Merge remote-tracking branch 'origin/preset-vision/0.9.0' into release/0.9.0

# Conflicts:
#	packages/designer/src/designer/setting/utils.js
This commit is contained in:
wuji.xwt 2020-06-19 11:12:50 +08:00
commit 631bb1e1cf
129 changed files with 4725 additions and 538 deletions

View File

@ -15,9 +15,7 @@
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" /> <link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" />
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script> <script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
<!-- lowcode engine globals --> <!-- lowcode engine globals -->
<link rel="stylesheet" href="./core.css" /> <link rel="stylesheet" href="./editor-preset-vision.css" />
<!-- lowcode engine globals -->
<link rel="stylesheet" href="./vision-preset.css" />
<!-- lowcode engine app --> <!-- lowcode engine app -->
<link rel="stylesheet" href="./lowcode-editor.css" /> <link rel="stylesheet" href="./lowcode-editor.css" />
<script> <script>
@ -72,9 +70,7 @@
<body> <body>
<div id="lce-container"></div> <div id="lce-container"></div>
<!-- lowcode engine globals --> <!-- lowcode engine globals -->
<script src="./core.js"></script> <script src="./editor-preset-vision.js"></script>
<!-- lowcode engine globals -->
<script src="./vision-preset.js"></script>
<script src="https://dev.g.alicdn.com/vision/visualengine-utils/5.0.0/engine-utils.js"></script> <script src="https://dev.g.alicdn.com/vision/visualengine-utils/5.0.0/engine-utils.js"></script>
<link rel="stylesheet" type="text/css" href="//g.alicdn.com/??platform/common/s/1.1/global/global.css,uxcore/uxcore-kuma/2.2.1/orange.min.css"> <link rel="stylesheet" type="text/css" href="//g.alicdn.com/??platform/common/s/1.1/global/global.css,uxcore/uxcore-kuma/2.2.1/orange.min.css">
<!-- lowcode engine app --> <!-- lowcode engine app -->

View File

@ -4,20 +4,80 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" /> <meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>LowCodeEngine Preview DEMO</title> <title>LowCodeEngine Editor DEMO</title>
<link rel="shortcut icon" href="./favicon.png" /> <link rel="shortcut icon" href="./favicon.png" />
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script> <script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script> <script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script> <script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
<script> React.PropTypes = PropTypes; </script> <script> React.PropTypes = PropTypes; </script>
<script src="https://g.alicdn.com/platform/c/??react15-polyfill/0.0.1/dist/index.js,lodash/4.6.1/lodash.min.js,immutable/3.7.6/dist/immutable.min.js,natty-storage/2.0.2/dist/natty-storage.min.js,natty-fetch/2.6.0/dist/natty-fetch.pc.min.js,tinymce/4.2.5/tinymce-full.js"></script>
<script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script> <script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" />
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css">
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script> <script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
<link rel="stylesheet" href="./lowcode-preview.css" /> <!-- lowcode engine globals -->
<link rel="stylesheet" href="./core.css" />
<!-- lowcode engine globals -->
<link rel="stylesheet" href="./vision-preset.css" />
<!-- lowcode engine app -->
<link rel="stylesheet" href="./lowcode-editor.css" />
<script>
window.pageConfig = {
env: 'release',
locale: 'zh_CN',
pageType: 'single',
deviceType: 'web',
appName: '基础包管理后台',
appType: '',
templateType: '',
pageId: 'FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V',
slug: 'test',
appMode: 'back',
isAppAdmin: 'y',
isSuperAdmin: 'n',
isBetaDeveloper: 'n',
formType: 'display',
title: { en_US: '测试', type: 'i18n', zh_CN: '测试' },
urlPrefix: 'https://go.alibaba-inc.com',
APIUrlPrefix: 'https://mocks.alibaba-inc.com/mock/lowCodeEngine',
devVersion: '0.1.0', // 这个是子应用的变更 id
subAppType: '0.1.0',
appKey: '',
RE_VERSION: '7.1.1',
appSource: '',
isDomainDefault: 'n',
useReleaseBundle: 'n',
isDomainPkg: 'n',
medusaAppName: '',
domainCode: 'kS6SyH',
aecp: {
mdcDomain: '',
projectId: '',
appCode: '',
},
designerConfigs: {},
navConfig:
'{"appName":{"en_US":"基础包管理后台","key":"","type":"i18n","zh_CN":"基础包管理后台"},"bgColor":"white","data":[{"children":[],"hidden":false,"icon":"","inner":true,"navUuid":"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V","relateUuid":"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V","slug":"test","targetNew":false,"title":{"en_US":"测试","type":"i18n","zh_CN":"测试"}}],"isFixed":"y","isFold":"y","isFoldHorizontal":"n","languageChangeUrl":{"en_US":"/common/account/changeAccountLanguage.json","type":"i18n","zh_CN":"/common/account/changeAccountLanguage.json"},"layout":"auto","navStyle":"orange","navTheme":"light","openSubMode":false,"showAppTitle":true,"showCrumb":true,"showIcon":false,"showLanguageChange":true,"showNav":true,"showSearch":"n","singletons":{"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V":{"isFixed":"n","isFold":"n","isFoldHorizontal":"n","showAppTitle":false,"showCrumb":false,"showLanguageChange":false,"showNav":false,"showSearch":"n","singleton":false},"test":{"$ref":"$.singletons.FORM\\-3KYJN7RV\\-DIOD8LLK1WGQ89S7NHA92\\-QJVH497K\\-V"}},"type":"top_fold"}',
historyType: 'HASH',
isSinglePage: 'n',
rhino: 'n',
isMiniApp: '',
taskId: '',
appSchema: 'V5',
openSubMode: 'n',
};
window.g_config = {};
</script>
</head> </head>
<body> <body>
<script src="./lowcode-preview.js"></script> <div id="lce-container"></div>
<!-- lowcode engine globals -->
<script src="./core.js"></script>
<!-- lowcode engine globals -->
<script src="./vision-preset.js"></script>
<script src="https://dev.g.alicdn.com/vision/visualengine-utils/5.0.0/engine-utils.js"></script>
<link rel="stylesheet" type="text/css" href="//g.alicdn.com/??platform/common/s/1.1/global/global.css,uxcore/uxcore-kuma/2.2.1/orange.min.css">
<!-- lowcode engine app -->
<script src="./lowcode-editor.js"></script>
</body> </body>
</html> </html>

View File

@ -10,7 +10,7 @@
] ]
}, },
"scripts": { "scripts": {
"build": "lerna run build --stream", "build": "./scripts/build.sh",
"clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build", "clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
"commit": "git-cz", "commit": "git-cz",
"pub": "lerna publish --cd-version patch", "pub": "lerna publish --cd-version patch",
@ -48,5 +48,9 @@
}, },
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
},
"tnpm": {
"mode": "yarn",
"lockfile": "enable"
} }
} }

View File

@ -58,7 +58,7 @@ const demoData: IProjectSchema = {
componentsTree: [ componentsTree: [
{ {
componentName: 'Page', componentName: 'Page',
id: 'node$1', id: 'node_1',
meta: { meta: {
title: '测试', title: '测试',
router: '/', router: '/',
@ -74,7 +74,7 @@ const demoData: IProjectSchema = {
children: [ children: [
{ {
componentName: 'Form', componentName: 'Form',
id: 'node$2', id: 'node_2',
props: { props: {
labelCol: 4, labelCol: 4,
style: {}, style: {},
@ -83,7 +83,7 @@ const demoData: IProjectSchema = {
children: [ children: [
{ {
componentName: 'Form.Item', componentName: 'Form.Item',
id: 'node$3', id: 'node_3',
props: { props: {
label: '姓名:', label: '姓名:',
name: 'name', name: 'name',
@ -92,7 +92,7 @@ const demoData: IProjectSchema = {
children: [ children: [
{ {
componentName: 'Input', componentName: 'Input',
id: 'node$4', id: 'node_4',
props: { props: {
placeholder: '请输入', placeholder: '请输入',
size: 'medium', size: 'medium',
@ -105,7 +105,7 @@ const demoData: IProjectSchema = {
}, },
{ {
componentName: 'Form.Item', componentName: 'Form.Item',
id: 'node$5', id: 'node_5',
props: { props: {
label: '年龄:', label: '年龄:',
name: 'age', name: 'age',
@ -114,7 +114,7 @@ const demoData: IProjectSchema = {
children: [ children: [
{ {
componentName: 'NumberPicker', componentName: 'NumberPicker',
id: 'node$6', id: 'node_6',
props: { props: {
size: 'medium', size: 'medium',
type: 'normal', type: 'normal',
@ -124,7 +124,7 @@ const demoData: IProjectSchema = {
}, },
{ {
componentName: 'Form.Item', componentName: 'Form.Item',
id: 'node$7', id: 'node_7',
props: { props: {
label: '职业:', label: '职业:',
name: 'profession', name: 'profession',
@ -132,7 +132,7 @@ const demoData: IProjectSchema = {
children: [ children: [
{ {
componentName: 'Select', componentName: 'Select',
id: 'node$8', id: 'node_8',
props: { props: {
dataSource: [ dataSource: [
{ {
@ -154,7 +154,7 @@ const demoData: IProjectSchema = {
}, },
{ {
componentName: 'Div', componentName: 'Div',
id: 'node$9', id: 'node_9',
props: { props: {
style: { style: {
textAlign: 'center', textAlign: 'center',
@ -163,12 +163,12 @@ const demoData: IProjectSchema = {
children: [ children: [
{ {
componentName: 'Button.Group', componentName: 'Button.Group',
id: 'node$a', id: 'node_a',
props: {}, props: {},
children: [ children: [
{ {
componentName: 'Button', componentName: 'Button',
id: 'node$b', id: 'node_b',
props: { props: {
type: 'primary', type: 'primary',
style: { style: {
@ -180,7 +180,7 @@ const demoData: IProjectSchema = {
}, },
{ {
componentName: 'Button', componentName: 'Button',
id: 'node$d', id: 'node_d',
props: { props: {
type: 'normal', type: 'normal',
style: { style: {

View File

@ -3,6 +3,89 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.30"></a>
## [0.8.30](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.29...@ali/lowcode-demo@0.8.30) (2020-06-16)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.29"></a>
## [0.8.29](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.28...@ali/lowcode-demo@0.8.29) (2020-06-15)
### Bug Fixes
* style ([4694331](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/4694331))
<a name="0.8.28"></a>
## [0.8.28](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.27...@ali/lowcode-demo@0.8.28) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.27"></a>
## [0.8.27](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.26...@ali/lowcode-demo@0.8.27) (2020-05-19)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.26"></a>
## [0.8.26](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.25...@ali/lowcode-demo@0.8.26) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.25"></a>
## [0.8.25](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.24...@ali/lowcode-demo@0.8.25) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.24"></a>
## [0.8.24](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.23...@ali/lowcode-demo@0.8.24) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.23"></a>
## [0.8.23](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.22...@ali/lowcode-demo@0.8.23) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.22"></a>
## [0.8.22](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.21...@ali/lowcode-demo@0.8.22) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.21"></a>
## [0.8.21](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.20...@ali/lowcode-demo@0.8.21) (2020-05-15)
**Note:** Version bump only for package @ali/lowcode-demo
<a name="0.8.20"></a> <a name="0.8.20"></a>
## [0.8.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.19...@ali/lowcode-demo@0.8.20) (2020-05-15) ## [0.8.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.19...@ali/lowcode-demo@0.8.20) (2020-05-15)

View File

@ -1,6 +1,7 @@
{ {
"entry": { "entry": {
"index": "src/index.ts", "index": "src/index",
"editor-preset-vision": "../editor-preset-vision/src/index.ts",
"react-simulator-renderer": "../react-simulator-renderer/src/index.ts" "react-simulator-renderer": "../react-simulator-renderer/src/index.ts"
}, },
"vendor": false, "vendor": false,

View File

@ -7,9 +7,12 @@
"react": "window.React", "react": "window.React",
"react-dom": "window.ReactDOM", "react-dom": "window.ReactDOM",
"prop-types": "window.PropTypes", "prop-types": "window.PropTypes",
"@ali/lowcode-editor-core": "window.LCECore",
"@ali/visualengine": "window.VisualEngine", "@ali/visualengine": "window.VisualEngine",
"@ali/visualengine-utils": "window.VisualEngineUtils" "@ali/visualengine-utils": "window.VisualEngineUtils",
"@ali/lowcode-editor-preset-general": "window.LowcodeEditor",
"@ali/lowcode-editor-core": "window.LowcodeEditor",
"@ali/lowcode-editor-skeleton": "window.LowcodeEditor",
"@ali/lowcode-designer": "window.LowcodeEditor"
}, },
"minify": false, "minify": false,
"sourcemap": true, "sourcemap": true,

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-demo", "name": "@ali/lowcode-demo",
"version": "0.8.20", "version": "0.8.30",
"private": true, "private": true,
"description": "低代码引擎 DEMO", "description": "低代码引擎 DEMO",
"scripts": { "scripts": {
@ -9,21 +9,32 @@
}, },
"config": {}, "config": {},
"dependencies": { "dependencies": {
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-editor-core": "^0.8.16",
"@ali/lowcode-editor-skeleton": "^0.8.17", "@ali/lowcode-editor-skeleton": "^0.8.26",
"@ali/lowcode-plugin-components-pane": "^0.8.13", "@ali/lowcode-plugin-components-pane": "^0.8.23",
"@ali/lowcode-plugin-designer": "^0.9.11", "@ali/lowcode-plugin-designer": "^0.9.20",
"@ali/lowcode-plugin-event-bind-dialog": "^0.8.12", "@ali/lowcode-plugin-event-bind-dialog": "^0.8.16",
"@ali/lowcode-plugin-outline-pane": "^0.8.17", "@ali/lowcode-plugin-outline-pane": "^0.8.26",
"@ali/lowcode-plugin-sample-logo": "^0.8.11", "@ali/lowcode-plugin-sample-logo": "^0.8.15",
"@ali/lowcode-plugin-sample-preview": "^0.8.16", "@ali/lowcode-plugin-sample-preview": "^0.8.25",
"@ali/lowcode-plugin-settings-pane": "^0.8.8", "@ali/lowcode-plugin-settings-pane": "^0.8.8",
"@ali/lowcode-plugin-undo-redo": "^0.8.16", "@ali/lowcode-plugin-undo-redo": "^0.8.25",
"@ali/lowcode-plugin-variable-bind-dialog": "^0.8.10", "@ali/lowcode-plugin-variable-bind-dialog": "^0.8.14",
"@ali/lowcode-plugin-zh-en": "^0.8.14", "@ali/lowcode-plugin-zh-en": "^0.8.18",
"@ali/lowcode-react-renderer": "^0.8.8", "@ali/lowcode-react-renderer": "^0.8.0",
"@ali/lowcode-runtime": "^0.8.13", "@ali/lowcode-runtime": "^0.8.13",
"@ali/lowcode-utils": "^0.8.4", "@ali/lowcode-utils": "^0.8.7",
"@ali/ve-action-pane": "^4.7.0-beta.0",
"@ali/ve-datapool-pane": "^6.4.3",
"@ali/ve-history-pane": "4.0.0",
"@ali/ve-i18n-manage-pane": "^4.3.0",
"@ali/ve-i18n-pane": "^4.0.0-beta.0",
"@ali/ve-page-history": "1.2.0",
"@ali/ve-page-history-pane": "^5.0.0-beta.0",
"@ali/ve-trunk-pane": "^5.1.0-beta.14",
"@ali/vs-variable-setter": "^3.1.0",
"@ali/vu-function-parser": "^2.5.0-beta.0",
"@ali/vu-legao-design-fetch-context": "^1.0.3",
"@alifd/next": "^1.19.12", "@alifd/next": "^1.19.12",
"@alife/theme-lowcode-light": "^0.1.0", "@alife/theme-lowcode-light": "^0.1.0",
"compare-versions": "^3.0.1", "compare-versions": "^3.0.1",

View File

@ -12,13 +12,63 @@
<script> <script>
React.PropTypes = PropTypes; React.PropTypes = PropTypes;
</script> </script>
<script src="https://g.alicdn.com/platform/c/??react15-polyfill/0.0.1/dist/index.js,lodash/4.6.1/lodash.min.js,immutable/3.7.6/dist/immutable.min.js,natty-storage/2.0.2/dist/natty-storage.min.js,natty-fetch/2.6.0/dist/natty-fetch.pc.min.js,tinymce/4.2.5/tinymce-full.js"></script>
<script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script> <script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" /> <link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" />
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script> <script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
<link rel="stylesheet" href="/css/editor-preset-vision.css" />
<script>
window.pageConfig = {
env: 'release',
locale: 'zh_CN',
pageType: 'single',
deviceType: 'web',
appName: '基础包管理后台',
appType: 'legao_base_packages',
templateType: '',
pageId: 'FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V',
slug: 'test',
appMode: 'back',
isAppAdmin: 'y',
isSuperAdmin: 'n',
isBetaDeveloper: 'n',
formType: 'display',
title: { en_US: '测试', type: 'i18n', zh_CN: '测试' },
urlPrefix: 'https://go.alibaba-inc.com',
APIUrlPrefix: 'https://go.alibaba-inc.com',
devVersion: '0.1.0', // 这个是子应用的变更 id
subAppType: '0.1.0',
appKey: 'legao_base_packages',
RE_VERSION: '7.1.1',
appSource: '',
isDomainDefault: 'n',
useReleaseBundle: 'n',
isDomainPkg: 'n',
medusaAppName: '',
domainCode: 'kS6SyH',
aecp: {
mdcDomain: '',
projectId: '',
appCode: '',
},
designerConfigs: {},
navConfig:
'{"appName":{"en_US":"基础包管理后台","key":"","type":"i18n","zh_CN":"基础包管理后台"},"bgColor":"white","data":[{"children":[],"hidden":false,"icon":"","inner":true,"navUuid":"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V","relateUuid":"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V","slug":"test","targetNew":false,"title":{"en_US":"测试","type":"i18n","zh_CN":"测试"}}],"isFixed":"y","isFold":"y","isFoldHorizontal":"n","languageChangeUrl":{"en_US":"/common/account/changeAccountLanguage.json","type":"i18n","zh_CN":"/common/account/changeAccountLanguage.json"},"layout":"auto","navStyle":"orange","navTheme":"light","openSubMode":false,"showAppTitle":true,"showCrumb":true,"showIcon":false,"showLanguageChange":true,"showNav":true,"showSearch":"n","singletons":{"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V":{"isFixed":"n","isFold":"n","isFoldHorizontal":"n","showAppTitle":false,"showCrumb":false,"showLanguageChange":false,"showNav":false,"showSearch":"n","singleton":false},"test":{"$ref":"$.singletons.FORM\\-3KYJN7RV\\-DIOD8LLK1WGQ89S7NHA92\\-QJVH497K\\-V"}},"type":"top_fold"}',
historyType: 'HASH',
isSinglePage: 'n',
rhino: 'n',
isMiniApp: '',
taskId: '',
appSchema: 'V5',
openSubMode: 'n',
};
window.g_config = {};
</script>
</head> </head>
<body> <body>
<!-- lowcode engine globals --> <!-- lowcode engine globals -->
<div id="lce-container"></div> <script src="/js/editor-preset-vision.js"></script>
<script src="https://dev.g.alicdn.com/vision/visualengine-utils/5.0.0/engine-utils.js"></script>
</body> </body>
</html> </html>

View File

@ -97,22 +97,6 @@
"packageName": "@ali/vc-div", "packageName": "@ali/vc-div",
"version": "1.0.1" "version": "1.0.1"
}, },
{
"prototypeConfigsUrl": [
"https://g.alicdn.com/legao-comp/web_bundle_0724/@ali/vc-page/1.0.5/proto.899e4b1.css",
"https://g.alicdn.com/legao-comp/web_bundle_0724/@ali/vc-page/1.0.5/proto.451d5fc.js"
],
"prototypeViewsUrl": null,
"alias": "",
"library": "AliVcPage",
"urls": [
"https://g.alicdn.com/legao-comp/web_bundle_0724/@ali/vc-page/1.0.5/view.3fdc557.css",
"https://g.alicdn.com/legao-comp/web_bundle_0724/@ali/vc-page/1.0.5/view.ae881b7.js"
],
"components": null,
"packageName": "@ali/vc-page",
"version": "1.0.5"
},
{ {
"prototypeConfigsUrl": [ "prototypeConfigsUrl": [
"https://g.alicdn.com/legao-comp/web_bundle_0724/@ali/vc-deep/2.1.12/proto.611ab53.css", "https://g.alicdn.com/legao-comp/web_bundle_0724/@ali/vc-deep/2.1.12/proto.611ab53.css",

View File

@ -1,13 +1,6 @@
{ {
"componentName": "Page", "componentName": "Page",
"fileName": "test", "id": "node_1",
"dataSource": {
"list": [],
"online": []
},
"state": {
"text": "outter"
},
"props": { "props": {
"ref": "outterView", "ref": "outterView",
"autoLoading": true, "autoLoading": true,
@ -15,5 +8,884 @@
"padding": 20 "padding": 20
} }
}, },
"children": [] "fileName": "test",
"dataSource": {
"list": []
},
"state": {
"text": "outter",
"abc": [
1,
2,
3
]
},
"children": [
{
"componentName": "Steps",
"id": "node_1i",
"props": {
"dataSource": [
{
"title": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": "报名"
},
"status": "",
"content": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": "Open the refrigerator door"
},
"customSwitcher": false
},
{
"title": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": "信息收集"
},
"status": "",
"content": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": "Put the elephant in the refrigerator"
},
"customSwitcher": false
},
{
"title": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": "审核"
},
"status": "",
"content": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": "Close the refrigerator door"
},
"customSwitcher": false
}
],
"current": 1,
"shape": "circle",
"direction": "horizontal",
"labelPlacement": "vertical",
"readOnly": false,
"animation": true,
"__style__": {},
"fieldId": "steps_kadcb0ov"
}
},
{
"componentName": "Title",
"id": "node_b",
"props": {
"text": "请填写以下人员信息表单",
"type": "primary",
"noDecoration": false,
"__style__": {},
"fieldId": "title_kadcb0nw"
}
},
{
"componentName": "Paragraph",
"id": "node_e",
"props": {
"content": "人最宝贵的是生命。它给予我们只有一次。人的一生应当这样度过:当他回首往事时不因虚度年华而悔恨,也不因碌碌无为而羞耻。这样在他临死的时侯就能够说:我已把我整个的生命和全部精力都献给最壮丽的事业——为人类的解放而斗争。",
"size": "medium",
"type": "long",
"__style__": {},
"fieldId": "paragraph_kadcb0nz"
}
},
{
"componentName": "ColumnsLayout",
"id": "node_r",
"props": {
"layout": "6:6",
"columnGap": "16px",
"rowGap": "16px",
"__style__": {
"marginTop": "24px"
},
"fieldId": "columnsLayout_kadcb0ob"
},
"children": [
{
"componentName": "Column",
"id": "node_s",
"props": {
"fieldId": "column_kadcb0o9",
"__style__": {}
},
"children": [
{
"componentName": "Card",
"id": "node_n",
"props": {
"title": "基本信息",
"subTitle": {
"type": "i18n",
"zh_CN": "",
"en_US": ""
},
"extra": {
"type": "JSSlot",
"params": null,
"value": [
{
"componentName": "Icon",
"id": "node_q",
"props": {
"type": {
"useType": true,
"baseType": "smile",
"otherType": "smile"
},
"size": "medium",
"__style__": {},
"fieldId": "icon_kadcb0o8"
}
}
]
},
"showTitleBullet": true,
"showHeadDivider": true,
"dividerNoInset": false,
"contentHeight": "",
"__style__": {},
"fieldId": "card_kadcb0o7"
},
"children": [
{
"componentName": "CardContent",
"id": "node_o",
"props": {},
"children": [
{
"componentName": "Form",
"id": "node_f",
"props": {
"labelAlign": "top",
"size": "medium",
"behavior": "NORMAL",
"autoValidate": true,
"scrollToFirstError": true,
"autoUnmount": true,
"fieldOptions": {},
"__style__": {
"marginTop": "24px"
},
"fieldId": "form_kadcb0o5"
},
"children": [
{
"componentName": "TextField",
"id": "node_g",
"props": {
"__category__": "form",
"__useMediator": "value",
"label": "姓名",
"value": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"labelAlign": "top",
"labelColSpan": 4,
"labelColOffset": 0,
"wrapperColSpan": 0,
"wrapperColOffset": 0,
"labelTextAlign": "right",
"placeholder": {
"type": "i18n",
"use": "zh_CN",
"en_US": "Please enter",
"zh_CN": "请输入"
},
"tips": {
"zh_CN": "",
"en_US": "",
"type": "i18n"
},
"size": "medium",
"behavior": "NORMAL",
"labelTipsTypes": "none",
"labelTipsIcon": "",
"labelTipsText": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"htmlType": "input",
"state": "",
"rows": 4,
"autoHeight": false,
"hasClear": false,
"trim": false,
"autoFocus": false,
"addonBefore": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"addonAfter": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"validation": [],
"hasLimitHint": false,
"cutString": false,
"__style__": {},
"fieldId": "textField_kadcb0o0"
}
},
{
"componentName": "RadioField",
"id": "node_14",
"props": {
"__category__": "form",
"__useMediator": "value",
"label": "性别",
"value": "",
"labelAlign": "top",
"labelColSpan": 4,
"labelColOffset": 0,
"wrapperColSpan": 0,
"wrapperColOffset": 0,
"labelTextAlign": "right",
"tips": {
"zh_CN": "",
"en_US": "",
"type": "i18n"
},
"size": "medium",
"behavior": "NORMAL",
"labelTipsTypes": "none",
"labelTipsIcon": "",
"labelTipsText": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"shape": "default",
"itemDirection": "hoz",
"dataSource": [
{
"text": {
"zh_CN": "选项一",
"en_US": "Option 1",
"type": "i18n",
"use": "zh_CN"
},
"value": "1",
"disable": false
},
{
"text": {
"zh_CN": "选项二",
"en_US": "Option 2",
"type": "i18n",
"use": "zh_CN"
},
"value": "2",
"disable": false
},
{
"text": {
"zh_CN": "选项三",
"en_US": "Option 3",
"type": "i18n",
"use": "zh_CN"
},
"value": "3",
"disable": true
}
],
"validation": [],
"__style__": {},
"fieldId": "radioField_kadcb0ok"
}
},
{
"componentName": "SelectField",
"id": "node_h",
"props": {
"__category__": "form",
"__useMediator": "value",
"label": "学校",
"value": "",
"labelAlign": "top",
"labelColSpan": 4,
"labelColOffset": 0,
"wrapperColSpan": 0,
"wrapperColOffset": 0,
"labelTextAlign": "right",
"placeholder": {
"type": "i18n",
"use": "zh_CN",
"en_US": "please select",
"zh_CN": "请选择"
},
"tips": {
"zh_CN": "",
"en_US": "",
"type": "i18n"
},
"size": "medium",
"behavior": "NORMAL",
"labelTipsTypes": "none",
"labelTipsIcon": "",
"labelTipsText": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"mode": "single",
"hasClear": false,
"hasSelectAll": false,
"showSearch": false,
"filterLocal": true,
"dataSource": [
{
"text": {
"zh_CN": "选项一",
"en_US": "Option 1",
"type": "i18n"
},
"value": "1"
},
{
"text": {
"zh_CN": "选项二",
"en_US": "Option 2",
"type": "i18n"
},
"value": "2"
},
{
"text": {
"zh_CN": "选项三",
"en_US": "Option 3",
"type": "i18n"
},
"value": "3"
}
],
"validation": [],
"notFoundContent": {
"type": "i18n",
"use": "zh_CN",
"en_US": null
},
"hasArrow": true,
"hasBorder": true,
"autoWidth": true,
"searchDelay": 300,
"__style__": {},
"fieldId": "select_kadcb0o1"
}
},
{
"componentName": "Div",
"id": "node_i",
"props": {
"behavior": "NORMAL",
"__style__": {},
"fieldId": "div_kadcb0o4"
},
"children": [
{
"componentName": "Button",
"id": "node_j",
"props": {
"content": {
"type": "i18n",
"en_US": "Ok",
"zh_CN": "提交"
},
"type": "primary",
"size": "medium",
"behavior": "NORMAL",
"baseIcon": "",
"otherIcon": "",
"loading": false,
"triggerEventsWhenLoading": false,
"__style__": ":root {\n margin-right: 15px;\n}",
"fieldId": "button_kadcb0o2",
"onClick": {
"type": "JSExpression",
"value": "function onSubmit(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').submit(function(data, error) {\n if (data) {\n console.log(data);\n // 往后端提交数据,一般写法如下\n // this.dataSourceMap['xxx'].load(data).then(() => {\n // this.utils.toast({\n // type: 'success',\n // title: '提交成功'\n // });\n // });\n }\n });\n}",
"extType": "function",
"events": [
{
"name": "onClick",
"params": {},
"func": {
"type": "js",
"source": "function onSubmit(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').submit(function(data, error) {\n if (data) {\n console.log(data);\n // 往后端提交数据,一般写法如下\n // this.dataSourceMap['xxx'].load(data).then(() => {\n // this.utils.toast({\n // type: 'success',\n // title: '提交成功'\n // });\n // });\n }\n });\n}",
"compiled": "function onSubmit(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').submit(function(data, error) {\n if (data) {\n console.log(data);\n // 往后端提交数据,一般写法如下\n // this.dataSourceMap['xxx'].load(data).then(() => {\n // this.utils.toast({\n // type: 'success',\n // title: '提交成功'\n // });\n // });\n }\n });\n}"
}
}
]
}
}
},
{
"componentName": "Button",
"id": "node_k",
"props": {
"content": {
"type": "i18n",
"en_US": "Reset",
"zh_CN": "重置"
},
"type": "secondary",
"size": "medium",
"behavior": "NORMAL",
"baseIcon": "",
"otherIcon": "",
"loading": false,
"triggerEventsWhenLoading": false,
"__style__": {},
"fieldId": "button_kadcb0o3",
"onClick": {
"type": "JSExpression",
"value": "function onReset(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').reset();\n}",
"extType": "function",
"events": [
{
"name": "onClick",
"params": {},
"func": {
"type": "js",
"source": "function onReset(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').reset();\n}",
"compiled": "function onReset(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').reset();\n}"
}
}
]
}
}
}
]
}
]
}
]
}
]
}
]
},
{
"componentName": "Column",
"id": "node_t",
"props": {
"fieldId": "column_kadcb0oa",
"__style__": {}
},
"children": [
{
"componentName": "Card",
"id": "node_u",
"props": {
"title": {
"type": "JSSlot",
"params": null,
"value": [
{
"componentName": "Icon",
"id": "node_18",
"props": {
"type": {
"useType": true,
"baseType": "smile",
"otherType": "smile"
},
"size": "medium",
"__style__": {},
"fieldId": "icon_kadcb0on"
}
},
{
"componentName": "Link",
"id": "node_19",
"props": {
"content": {
"type": "i18n",
"use": "zh_CN",
"en_US": "link text",
"zh_CN": "扩展信息"
},
"textOverflow": false,
"link": {
"type": "page",
"page": null,
"router": {
"type": "JSExpression",
"value": "this.utils.router"
}
},
"__style__": {},
"fieldId": "link_kadcb0oo"
}
}
]
},
"subTitle": {
"type": "i18n",
"zh_CN": "",
"en_US": ""
},
"extra": {
"type": "JSSlot",
"params": null,
"value": [
{
"componentName": "Icon",
"id": "node_1a",
"props": {
"type": {
"useType": true,
"baseType": "smile",
"otherType": "smile"
},
"size": "xl",
"__style__": {},
"fieldId": "icon_kadcb0op"
}
}
]
},
"showTitleBullet": true,
"showHeadDivider": true,
"dividerNoInset": false,
"contentHeight": "",
"__style__": {},
"fieldId": "card_kadcb0oc"
},
"children": [
{
"componentName": "CardContent",
"id": "node_v",
"props": {},
"children": [
{
"componentName": "Form",
"id": "node_x",
"props": {
"labelAlign": "top",
"size": "medium",
"behavior": "NORMAL",
"autoValidate": true,
"scrollToFirstError": true,
"autoUnmount": true,
"fieldOptions": {},
"__style__": {
"marginTop": "24px"
},
"fieldId": "form_kadcb0oi"
},
"children": [
{
"componentName": "TextField",
"id": "node_y",
"props": {
"__category__": "form",
"__useMediator": "value",
"label": "职位",
"value": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"labelAlign": "top",
"labelColSpan": 4,
"labelColOffset": 0,
"wrapperColSpan": 0,
"wrapperColOffset": 0,
"labelTextAlign": "right",
"placeholder": {
"type": "i18n",
"use": "zh_CN",
"en_US": "Please enter",
"zh_CN": "请输入"
},
"tips": {
"zh_CN": "",
"en_US": "",
"type": "i18n"
},
"size": "medium",
"behavior": "NORMAL",
"labelTipsTypes": "none",
"labelTipsIcon": "",
"labelTipsText": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"htmlType": "input",
"state": "",
"rows": 4,
"autoHeight": false,
"hasClear": false,
"trim": false,
"autoFocus": false,
"addonBefore": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"addonAfter": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"validation": [],
"hasLimitHint": false,
"cutString": false,
"__style__": {},
"fieldId": "textField_kadcb0od"
}
},
{
"componentName": "DateField",
"id": "node_15",
"props": {
"__category__": "form",
"__useMediator": "value",
"label": "入职时间",
"value": "",
"labelAlign": "top",
"labelColSpan": 4,
"labelColOffset": 0,
"wrapperColSpan": 0,
"wrapperColOffset": 0,
"labelTextAlign": "right",
"placeholder": {
"type": "i18n",
"use": "zh_CN",
"en_US": "please select",
"zh_CN": "请选择"
},
"tips": {
"zh_CN": "",
"en_US": "",
"type": "i18n"
},
"size": "medium",
"behavior": "NORMAL",
"format": "YYYY-MM-DD",
"returnType": "timestamp",
"labelTipsTypes": "none",
"labelTipsIcon": "",
"labelTipsText": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"hasClear": true,
"resetTime": false,
"disabledDate": false,
"validation": [],
"__style__": {},
"fieldId": "dateField_kadcb0ol"
}
},
{
"componentName": "SelectField",
"id": "node_z",
"props": {
"__category__": "form",
"__useMediator": "value",
"label": "下拉选择",
"value": "",
"labelAlign": "top",
"labelColSpan": 4,
"labelColOffset": 0,
"wrapperColSpan": 0,
"wrapperColOffset": 0,
"labelTextAlign": "right",
"placeholder": {
"type": "i18n",
"use": "zh_CN",
"en_US": "please select",
"zh_CN": "请选择"
},
"tips": {
"zh_CN": "",
"en_US": "",
"type": "i18n"
},
"size": "medium",
"behavior": "NORMAL",
"labelTipsTypes": "none",
"labelTipsIcon": "",
"labelTipsText": {
"type": "i18n",
"use": "zh_CN",
"en_US": null,
"zh_CN": ""
},
"mode": "single",
"hasClear": false,
"hasSelectAll": false,
"showSearch": false,
"filterLocal": true,
"dataSource": [
{
"text": {
"zh_CN": "选项一",
"en_US": "Option 1",
"type": "i18n"
},
"value": "1"
},
{
"text": {
"zh_CN": "选项二",
"en_US": "Option 2",
"type": "i18n"
},
"value": "2"
},
{
"text": {
"zh_CN": "选项三",
"en_US": "Option 3",
"type": "i18n"
},
"value": "3"
}
],
"validation": [],
"notFoundContent": {
"type": "i18n",
"use": "zh_CN",
"en_US": null
},
"hasArrow": true,
"hasBorder": true,
"autoWidth": true,
"searchDelay": 300,
"__style__": {},
"fieldId": "select_kadcb0oe"
}
},
{
"componentName": "Div",
"id": "node_10",
"props": {
"behavior": "NORMAL",
"__style__": {},
"fieldId": "div_kadcb0oh"
},
"children": [
{
"componentName": "Button",
"id": "node_11",
"props": {
"content": {
"type": "i18n",
"en_US": "Ok",
"zh_CN": "提交"
},
"type": "primary",
"size": "medium",
"behavior": "NORMAL",
"baseIcon": "",
"otherIcon": "",
"loading": false,
"triggerEventsWhenLoading": false,
"__style__": ":root {\n margin-right: 15px;\n}",
"fieldId": "button_kadcb0of",
"onClick": {
"type": "JSExpression",
"value": "function onSubmit(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').submit(function(data, error) {\n if (data) {\n console.log(data);\n // 往后端提交数据,一般写法如下\n // this.dataSourceMap['xxx'].load(data).then(() => {\n // this.utils.toast({\n // type: 'success',\n // title: '提交成功'\n // });\n // });\n }\n });\n}",
"extType": "function",
"events": [
{
"name": "onClick",
"params": {},
"func": {
"type": "js",
"source": "function onSubmit(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').submit(function(data, error) {\n if (data) {\n console.log(data);\n // 往后端提交数据,一般写法如下\n // this.dataSourceMap['xxx'].load(data).then(() => {\n // this.utils.toast({\n // type: 'success',\n // title: '提交成功'\n // });\n // });\n }\n });\n}",
"compiled": "function onSubmit(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').submit(function(data, error) {\n if (data) {\n console.log(data);\n // 往后端提交数据,一般写法如下\n // this.dataSourceMap['xxx'].load(data).then(() => {\n // this.utils.toast({\n // type: 'success',\n // title: '提交成功'\n // });\n // });\n }\n });\n}"
}
}
]
}
}
},
{
"componentName": "Button",
"id": "node_12",
"props": {
"content": {
"type": "i18n",
"en_US": "Reset",
"zh_CN": "重置"
},
"type": "secondary",
"size": "medium",
"behavior": "NORMAL",
"baseIcon": "",
"otherIcon": "",
"loading": false,
"triggerEventsWhenLoading": false,
"__style__": {},
"fieldId": "button_kadcb0og",
"onClick": {
"type": "JSExpression",
"value": "function onReset(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').reset();\n}",
"extType": "function",
"events": [
{
"name": "onClick",
"params": {},
"func": {
"type": "js",
"source": "function onReset(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').reset();\n}",
"compiled": "function onReset(){\n // 请将 fieldId 替换为表单容器的 fieldId\n this.$('fieldId').reset();\n}"
}
}
]
}
}
}
]
}
]
}
]
}
]
}
]
}
]
}
]
} }

View File

@ -1 +1 @@
import './editor'; import './vision';

View File

@ -0,0 +1,517 @@
/* eslint-disable */
import { createElement } from 'react';
import { Button } from '@alifd/next';
import Engine, { Panes, Prototype } from '@ali/visualengine';
import { ActionUtil as actionUtil } from '@ali/visualengine-utils';
import getTrunkPane from '@ali/ve-trunk-pane';
import DatapoolPane from '@ali/ve-datapool-pane';
import PageHistoryManager from '@ali/ve-page-history';
import HistoryPane from '@ali/ve-history-pane';
import PageHistoryPane from '@ali/ve-page-history-pane';
// import I18nPane from '@ali/ve-i18n-pane';
import I18nManagePane from '@ali/ve-i18n-manage-pane';
import ActionPane from '@ali/ve-action-pane';
import SourceEditor from '@ali/lowcode-plugin-source-editor';
import fetchContext from '@ali/vu-legao-design-fetch-context';
import EventBindDialog from '@ali/lowcode-plugin-event-bind-dialog';
import loadUrls from './loader';
import { upgradeAssetsBundle } from './upgrade-assets';
import { isCSSUrl } from '@ali/lowcode-utils';
import VariableSetter from '@ali/vs-variable-setter';
import _isArray from "lodash/isArray";
import _isObject from "lodash/isObject";
import _get from 'lodash/get';
import funcParser from '@ali/vu-function-parser';
import {
NumberSetter,
BoolSetter,
ChoiceSetter,
CodeSetter,
ColorSetter,
DateSetter,
I18nSetter,
JsonSetter,
ListSetter,
SelectSetter,
OptionsSetter,
TextSetter,
ValidationSetter,
ActionSetter,
} from '@ali/visualengine-utils';
const { editor, skeleton, context, HOOKS, Trunk } = Engine;
Trunk.registerSetter('Input', TextSetter);
Trunk.registerSetter('StringSetter', TextSetter);
Trunk.registerSetter('TextArea', TextSetter);
Trunk.registerSetter('Object', JsonSetter);
Trunk.registerSetter('Function', ActionSetter);
Trunk.registerSetter('Node', CodeSetter);
Trunk.registerSetter('Mixin', CodeSetter);
Trunk.registerSetter('Expression', CodeSetter);
Trunk.registerSetter('List', ListSetter);
Trunk.registerSetter('Switch', BoolSetter);
Trunk.registerSetter('Number', NumberSetter);
Trunk.registerSetter('Select', SelectSetter);
Trunk.registerSetter('ActionSetter', ActionSetter);
Trunk.registerSetter('BoolSetter', BoolSetter);
Trunk.registerSetter('ChoiceSetter', ChoiceSetter);
Trunk.registerSetter('CodeSetter', CodeSetter);
Trunk.registerSetter('ColorSetter', ColorSetter);
Trunk.registerSetter('DateSetter', DateSetter);
Trunk.registerSetter('JsonSetter', JsonSetter);
Trunk.registerSetter('ListSetter', ListSetter);
Trunk.registerSetter('SelectSetter', SelectSetter);
Trunk.registerSetter('OptionsSetter', OptionsSetter);
Trunk.registerSetter('TextSetter', TextSetter);
Trunk.registerSetter('NumberSetter', NumberSetter);
Trunk.registerSetter('ValidationSetter', ValidationSetter);
// 需要额外覆盖配置的 setters
function wrapSetter(component: any, title: any, initialValueWrapper: any) {
return {
component,
title,
recommend: true,
initialValue: initialValueWrapper ? (field: any) => {
let defaultValueFromSetter;
if (component.initial) {
defaultValueFromSetter = component.initial.call(field, field.getValue());
}
const defaultValue = initialValueWrapper(defaultValueFromSetter);
return defaultValue;
} : undefined,
}
}
Trunk.registerSetter('I18nSetter', wrapSetter(
I18nSetter,
{ type: 'i18n', 'zh-CN': '国际化输入', 'en-US': 'International Input' },
(defaultValue: any) => {
if (defaultValue[defaultValue.use] && typeof defaultValue[defaultValue.use] !== 'string') {
defaultValue[defaultValue.use] = null;
}
return defaultValue;
}
));
context.use(HOOKS.VE_SETTING_FIELD_VARIABLE_SETTER, VariableSetter);
const externals = ['react', 'react-dom', 'prop-types', 'react-router', 'react-router-dom', '@ali/recore'];
async function loadAssets() {
const legaoAssets = await editor.utils.get('./legao-assets.json');
const assets = upgradeAssetsBundle(legaoAssets);
if (assets.packages) {
assets.packages.forEach((item: any) => {
if (item.package && externals.indexOf(item.package) > -1) {
item.urls = null;
}
});
}
if (assets['x-prototypes']) {
const tasks: Array<Promise<any>> = [];
const prototypeStyles: string[] = [];
assets['x-prototypes'].forEach((pkg: any) => {
if (pkg?.urls) {
const urls = Array.isArray(pkg.urls) ? pkg.urls : [pkg.urls];
urls.forEach((url: string) => {
if (isCSSUrl(url)) {
prototypeStyles.push(url);
}
});
tasks.push(loadUrls(urls));
}
});
if (prototypeStyles.length > 0) {
assets.packages.push({
library: '_prototypesStyle',
package: '_prototypes-style',
urls: prototypeStyles,
});
}
await Promise.all(tasks);
// proccess snippets
}
editor.set('legao-assets', legaoAssets);
editor.set('assets', assets);
}
async function loadSchema() {
const schema = await editor.utils.get('./schema.json');
editor.set('schema', schema);
}
// demo
function initDemoPanes() {
skeleton.add({
name: 'eventBindDialog',
type: 'Widget',
content: EventBindDialog,
});
// skeleton.add({
// area: 'left',
// name: 'sourceEditor',
// type: "PanelDock",
// content: SourceEditor,
// props: {
// align: undefined,
// description: "动作面板",
// onDestroy: undefined,
// icon: 'set',
// onInit: undefined
// },
// panelProps:{
// height: 300,
// help: undefined,
// hideTitleBar: true,
// maxHeight: 800,
// maxWidth: 1200,
// title: "动作面板",
// width: 600
// }
// });
// skeleton.add({
// area: 'leftArea',
// name: 'icon1',
// type: 'PanelDock',
// props: {
// align: 'bottom',
// icon: 'set',
// description: '设置'
// },
// });
skeleton.add({
area: 'leftArea',
name: 'icon2',
type: 'Dock',
props: {
align: 'bottom',
icon: 'help',
description: '帮助'
},
});
skeleton.add({
area: 'topArea',
type: 'Dock',
name: 'publish',
props: {
align: 'right',
},
content: createElement(Button, {
size: 'small',
type: 'secondary',
children: '发布',
}),
});
skeleton.add({
area: 'topArea',
type: 'Dock',
name: 'save',
props: {
align: 'right',
},
content: createElement(Button, {
size: 'small',
type: 'primary',
children: '保存',
}),
});
// skeleton.add({
// area: 'topArea',
// type: 'Dock',
// name: 'preview4',
// props: {
// align: 'center',
// },
// content: createElement('img', {
// src: 'https://img.alicdn.com/tfs/TB1WW.VC.z1gK0jSZLeXXb9kVXa-486-64.png',
// style: {
// height: 32,
// },
// }),
// });
skeleton.add({
area: 'topArea',
type: 'Dock',
name: 'preview1',
props: {
align: 'left',
},
content: createElement('img', {
src: 'https://img.alicdn.com/tfs/TB1zqBfDlr0gK0jSZFnXXbRRXXa-440-64.png',
style: {
height: 32,
},
}),
});
}
async function initTrunkPane() {
const assets = await editor.onceGot('legao-assets');
const config = {
disableLowCodeComponent: true,
disableComponentStore: true,
app: {
getAssetsData() {
return assets;
// return data;
},
},
};
const TrunkPane = getTrunkPane(config);
Panes.add(TrunkPane);
}
// 数据源面板
function initDataPoolPane() {
const dpConfigs = {};
if (!dpConfigs) {
return;
}
fetchContext.create('DataPoolPaneAPI', {
saveGlobalConfig: {
url: 'query/appConfig/saveGlobalConfig.json',
method: 'POST',
},
saveOrUpdateAppDataPool: {
url: 'query/appDataPool/saveOrUpdateAppDataPool.json',
method: 'POST',
},
batchSaveOrUpdateAppDataPool: {
url: 'query/appDataPool/batchSaveOrUpdateAppDataPool.json',
method: 'POST'
},
listAppDataPool: {
url: 'query/appDataPool/listAppDataPool.json',
method: 'GET',
},
getAppDataPool: {
url: 'query/appDataPool/getAppDataPool.json',
method: 'POST',
},
getEpaasApiInApp: {
url: 'query/formdesign/getEpaasApiInApp.jsonp',
method: 'GET',
},
getFormListOrder: {
url: 'query/formdesign/getFormListOrder.json',
method: 'GET',
},
// 实时修改 effectForm
operateAppDpBind: {
url: 'query/appDataPool/operateAppDpBind.json',
method: 'POST',
},
// 校验全局数据源是否被其他页面修改
checkAppDataPoolModified: {
url: 'query/appDataPool/checkAppDataPoolModified.json',
method: 'POST',
},
});
const props = {
enableGateService: true,
enableGlobalFitConfig: true,
enableOneAPIService: true,
formUuid: 'xxx',
api: fetchContext.api.DataPoolPaneAPI,
};
Panes.add(DatapoolPane, {
props,
});
}
// 国际化面板
function initI18nPane() {
fetchContext.create('I18nManagePaneAPI', {
// 绑定美杜莎
bindMedusa: {
url: 'query/app/createMedusa.json',
},
// 解除绑定
unbindMedusa: {
url: 'query/app/removeMedusa.json',
},
// 同步美杜莎
syncMedusa: {
url: 'query/formi18n/syncI18n.json',
},
});
Panes.add(I18nManagePane, {
props: {
enableMedusa: true,
api: fetchContext.api.I18nManagePaneAPI,
},
});
}
// 动作面板
function initActionPane() {
actionUtil.setActions({
module: {
compiled: "'use strict';\n\nexports.__esModule = true;\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nexports.submit = submit;\nexports.onLoadData = onLoadData;\nexports.add = add;\nexports.edit = edit;\nexports.del = del;\nexports.search = search;\nexports.reset = reset;\n/**\n* 点击弹框的“确认”\n*/\nfunction submit() {\n var _this = this;\n\n this.$('form').submit(function (data, error) {\n if (data) {\n _this.dataSourceMap['table_submit'].load(data).then(function (res) {\n _this.utils.toast({\n type: 'success',\n title: '提交成功'\n });\n _this.$('dialog').hide();\n _this.dataSourceMap['table_list'].load();\n }).catch(function () {\n _this.utils.toast({\n type: 'error',\n title: '提交失败'\n });\n });\n }\n });\n}\n\n/**\n* tablePc onLoadData\n* @param currentPage 当前页码\n* @param pageSize 每页显示条数\n* @param searchKey 搜索关键字\n* @param orderColumn 排序列\n* @param orderType 排序方式desc,asc\n* @param from 触发来源order,search,pagination\n*/\nfunction onLoadData(currentPage, pageSize, searchKey, orderColumn, orderType, from) {\n var tableParams = {\n currentPage: from === 'search' ? 1 : currentPage,\n pageSize: pageSize,\n searchKey: searchKey,\n orderColumn: orderColumn,\n orderType: orderType\n };\n this.setState({ tableParams: tableParams });\n}\n\n// 点击新增\nfunction add() {\n this.setState({\n formData: null\n });\n this.$('dialog').show();\n}\n\n// 点击编辑\nfunction edit(rowData) {\n this.setState({\n formData: rowData\n });\n this.$('dialog').show();\n}\n\n// 点击删除\nfunction del(rowData) {\n var _this2 = this;\n\n this.utils.dialog({\n method: 'confirm',\n title: '提示',\n content: '确认删除该条目吗?',\n onOk: function onOk() {\n _this2.dataSourceMap['table_delete'].load({ id: rowData.id }).then(function () {\n _this2.utils.toast({\n type: 'success',\n title: '删除成功'\n });\n _this2.dataSourceMap['table_list'].load();\n }).catch(function () {\n _this2.utils.toast({\n type: 'error',\n title: '删除失败'\n });\n });\n }\n });\n}\n\n/**\n* button onClick\n*/\nfunction search() {\n var filterData = this.$('filter').getValue();\n this.setState({\n filterData: filterData,\n tableParams: _extends({}, this.state.tableParams, {\n time: Date.now(),\n currentPage: 1\n })\n });\n}\n\n/**\n* button onClick\n*/\nfunction reset() {\n this.$('filter').reset();\n this.setState({\n filterData: {},\n tableParams: _extends({}, this.state.tableParams, {\n time: Date.now(),\n currentPage: 1\n })\n });\n}",
source: "/**\n* 点击弹框的“确认”\n*/\nexport function submit() {\n this.$('form').submit((data, error) => {\n if (data) {\n this.dataSourceMap['table_submit'].load(data).then((res) => {\n this.utils.toast({\n type: 'success',\n title: '提交成功'\n });\n this.$('dialog').hide();\n this.dataSourceMap['table_list'].load();\n }).catch(()=>{\n this.utils.toast({\n type: 'error',\n title: '提交失败'\n });\n })\n }\n })\n}\n\n/**\n* tablePc onLoadData\n* @param currentPage 当前页码\n* @param pageSize 每页显示条数\n* @param searchKey 搜索关键字\n* @param orderColumn 排序列\n* @param orderType 排序方式desc,asc\n* @param from 触发来源order,search,pagination\n*/\nexport function onLoadData(currentPage, pageSize, searchKey, orderColumn, orderType, from) {\n const tableParams = {\n currentPage: from === 'search' ? 1 : currentPage,\n pageSize,\n searchKey,\n orderColumn,\n orderType\n };\n this.setState({ tableParams });\n}\n\n// 点击新增\nexport function add() {\n this.setState({\n formData: null,\n });\n this.$('dialog').show();\n}\n\n\n// 点击编辑\nexport function edit(rowData) {\n this.setState({\n formData: rowData\n });\n this.$('dialog').show();\n}\n\n// 点击删除\nexport function del(rowData) {\n this.utils.dialog({\n method: 'confirm',\n title: '提示',\n content: '确认删除该条目吗?',\n onOk: () => {\n this.dataSourceMap['table_delete'].load({ id: rowData.id }).then(() => {\n this.utils.toast({\n type: 'success',\n title: '删除成功'\n });\n this.dataSourceMap['table_list'].load();\n }).catch(()=>{\n this.utils.toast({\n type: 'error',\n title: '删除失败'\n });\n })\n }\n })\n}\n\n/**\n* button onClick\n*/\nexport function search(){\n const filterData = this.$('filter').getValue();\n this.setState({\n filterData,\n tableParams: {\n ...this.state.tableParams,\n time: Date.now(),\n currentPage: 1\n }\n });\n}\n\n/**\n* button onClick\n*/\nexport function reset(){\n this.$('filter').reset();\n this.setState({\n filterData: {},\n tableParams: {\n ...this.state.tableParams,\n time: Date.now(),\n currentPage: 1\n }\n });\n}"
},
type: "FUNCTION",
list: [
{
"id": "submit",
"title": "submit"
},
{
"id": "onLoadData",
"title": "onLoadData"
},
{
"id": "add",
"title": "add"
},
{
"id": "edit",
"title": "edit"
},
{
"id": "del",
"title": "del"
},
{
"id": "search",
"title": "search"
},
{
"id": "reset",
"title": "reset"
}
]
});
const props = {
enableGlobalJS: false,
enableVsCodeEdit: false,
enableHeaderTip: true,
};
Panes.add(ActionPane, {
props,
});
}
function replaceFuncProp(props?: any){
const replaceProps: any = {};
for (const name in props) {
const prop = props[name];
if (!prop) {
continue;
}
if ((prop.compiled && prop.source) || prop.type === 'actionRef' || prop.type === 'js') {
replaceProps[name] = funcParser(prop);
} else if (_isObject(prop)) {
replaceFuncProp(prop);
} else if (_isArray(prop)) {
prop.map((propItem) => {
replaceFuncProp(propItem);
});
}
}
for (const name in replaceProps) {
props[name] = replaceProps[name];
}
return props;
};
// 操作历史与页面历史面板
function initHistoryPane() {
// let historyConfigs = {getDesignerModuleConfigs(
// this.designerConfigs,
// 'history',
// )};
let historyConfigs = {
enableRedoAndUndo: true,
enablePageHistory: true,
};;
const isDemoMode = false;
const isEnvSupportsHistoryPane = true;
const historyManager = PageHistoryManager.getManager();
console.log('PageHistoryManager', historyManager);
console.log('PageHistoryManager.onOpenPane', historyManager.onOpenPane);
// 历史撤销、重做以及唤起页面历史按钮
if (typeof HistoryPane === 'function') {
Panes.add(HistoryPane, {
props : {
showPageHistory:
isEnvSupportsHistoryPane
// && this.app.isForm()
&& !isDemoMode,
historyManager,
historyConfigs,
index: -940,
}
});
} else {
Panes.add(HistoryPane, {
index: -940,
});
}
// 页面历史 UI 面板
if (
PageHistoryPane
&& !isDemoMode
&& isEnvSupportsHistoryPane
) {
Panes.add(PageHistoryPane, {
props : {
historyManager: {
historyManager,
app: {
}
},
index: -940,
},
});
}
}
async function init() {
Engine.Env.setEnv('RE_VERSION', '7.2.0');
Engine.Env.setSupportFeatures({
subview: true,
i18nPane: true,
});
Prototype.addGlobalPropsReducer(replaceFuncProp);
await loadAssets();
await loadSchema();
await initTrunkPane();
// initDataPoolPane();
// initI18nPane();
// initActionPane();
initDemoPanes();
// initHistoryPane();
Engine.init();
}
init();

View File

@ -0,0 +1,172 @@
/* eslint-disable */
function getStylePoint(id, level) {
if (stylePointTable[id]) {
return stylePointTable[id];
}
const base = getBasePoint();
if (id === 'base') {
return base;
}
const point = new StylePoint(id, level || 2000);
if (level >= base.level) {
let prev = base;
let next = prev.next;
while (next && level >= next.level) {
prev = next;
next = prev.next;
}
prev.next = point;
point.prev = prev;
if (next) {
point.next = next;
next.prev = point;
}
} else {
let next = base;
let prev = next.prev;
while (prev && level < prev.level) {
next = prev;
prev = next.prev;
}
next.prev = point;
point.next = next;
if (prev) {
point.prev = prev;
prev.next = point;
}
}
point.insert();
stylePointTable[id] = point;
return point;
}
const stylePointTable = {};
function getBasePoint() {
if (!stylePointTable.base) {
stylePointTable.base = new StylePoint('base', 1000);
stylePointTable.base.insert();
}
return stylePointTable.base;
}
class StylePoint {
constructor(id, level, placeholder) {
this.lastContent = null;
this.lastUrl = null;
this.next = null;
this.prev = null;
this.id = id;
this.level = level;
if (placeholder) {
this.placeholder = placeholder;
} else {
this.placeholder = document.createTextNode('');
}
}
insert() {
if (this.next) {
document.head.insertBefore(this.placeholder, this.next.placeholder);
} else if (this.prev) {
document.head.insertBefore(this.placeholder, this.prev.placeholder.nextSibling);
} else {
document.head.appendChild(this.placeholder);
}
}
applyText(content) {
if (this.lastContent === content) {
return;
}
this.lastContent = content;
this.lastUrl = undefined;
const element = document.createElement('style');
element.setAttribute('type', 'text/css');
element.setAttribute('data-for', this.id);
element.appendChild(document.createTextNode(content));
document.head.insertBefore(element, this.placeholder);
document.head.removeChild(this.placeholder);
this.placeholder = element;
}
applyUrl(url) {
if (this.lastUrl === url) {
return;
}
this.lastContent = undefined;
this.lastUrl = url;
const element = document.createElement('link');
element.href = url;
element.rel = 'stylesheet';
element.setAttribute('data-for', this.id);
document.head.insertBefore(element, this.placeholder);
document.head.removeChild(this.placeholder);
this.placeholder = element;
}
}
function loadCSS(url) {
getStylePoint(url).applyUrl(url);
}
function isCSSUrl(url) {
return /\.css$/.test(url);
}
function loadScript(url) {
const node = document.createElement('script');
// node.setAttribute('crossorigin', 'anonymous');
node.onload = onload;
node.onerror = onload;
const i = {};
const promise = new Promise((resolve, reject) => {
i.resolve = resolve;
i.reject = reject;
});
function onload(e) {
node.onload = null;
node.onerror = null;
if (e.type === 'load') {
i.resolve();
} else {
i.reject();
}
// document.head.removeChild(node);
// node = null;
}
// node.async = true;
node.src = url;
document.head.appendChild(node);
return promise;
}
export default function loadUrls(urls) {
if (!urls || urls.length < 1) {
return Promise.resolve();
}
let promise = null;
urls.forEach((url) => {
if (isCSSUrl(url)) {
loadCSS(url);
} else if (!promise) {
promise = loadScript(url);
} else {
promise = promise.then(() => loadScript(url));
}
});
return promise || Promise.resolve();
}

13
packages/demo/src/vision/module.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
declare module '@ali/visualengine';
declare module '@ali/visualengine-utils';
declare module '@ali/ve-trunk-pane';
declare module '@ali/vs-variable-setter';
declare module '@ali/ve-datapool-pane';
declare module '@ali/ve-history-pane';
declare module '@ali/ve-page-history-pane';
declare module '@ali/ve-page-history';
declare module '@ali/ve-i18n-manage-pane';
declare module '@ali/ve-action-pane';
declare module '@ali/vu-legao-design-fetch-context';
declare module "@ali/vu-function-parser";
declare module "compare-versions";

View File

@ -0,0 +1,68 @@
/* eslint-disable */
export function upgradeAssetsBundle(assets) {
const components = [];
const xPrototypes = [];
const componentList = [];
const packages = assets.externals.map(({ urls, library, name, version }) => {
return {
package: name,
version,
urls,
library,
};
});
assets.componentDependencies.forEach((item) => {
const componentName = item.alias || item.library;
const metadata = {
componentName,
npm: {
package: item.packageName,
library: item.library,
version: item.version,
destructuring: false,
},
props: [],
};
if (item.prototypeConfigsUrl) {
xPrototypes.push({
package: item.packageName,
urls: item.prototypeConfigsUrl,
});
} else if (item.components) {
packages.push({
urls: item.urls,
library: item.library,
package: item.packageName,
version: item.version,
});
const meta = item.components[0];
metadata.componentName = meta.componentName;
metadata.configure = meta.configure;
metadata.title = meta.title;
components.push(metadata);
// TODO:
if (meta.snippets) {
componentList.push({
title: meta.category,
icon: '',
children: [
{
title: 'json格式化展示',
icon: '',
snippets: meta.snippets,
},
],
});
}
}
});
return {
"version": "1.0.0",
packages,
'x-prototypes': xPrototypes,
components,
componentList
};
}

View File

@ -3,6 +3,98 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.9.20"></a>
## [0.9.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.19...@ali/lowcode-designer@0.9.20) (2020-06-16)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.9.19"></a>
## [0.9.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.18...@ali/lowcode-designer@0.9.19) (2020-06-15)
### Bug Fixes
* force schema ([6d0a8ff](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d0a8ff))
* patch prototype ([f20bfaa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/f20bfaa))
* try get settingfield ([56f242f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56f242f))
* 禁止组件拉到 Page 的直接子节点, 以及替换 tab 组件 ([d93a291](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/d93a291))
### Features
* complete live-editing expr & i18n ([3ac08ba](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3ac08ba))
* get SettingField instead of SettingPropEntry for compatibility ([2787a12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2787a12))
* support prop.autorun ([c0a5235](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/c0a5235))
* ve事件埋点 ([700e5b0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/700e5b0))
<a name="0.9.18"></a>
## [0.9.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.17...@ali/lowcode-designer@0.9.18) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.9.17"></a>
## [0.9.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.16...@ali/lowcode-designer@0.9.17) (2020-05-19)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.9.16"></a>
## [0.9.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.15...@ali/lowcode-designer@0.9.16) (2020-05-18)
### Bug Fixes
* uniqueid ([8db52f0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/8db52f0))
<a name="0.9.15"></a>
## [0.9.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.14...@ali/lowcode-designer@0.9.15) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.9.14"></a>
## [0.9.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.13...@ali/lowcode-designer@0.9.14) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.9.13"></a>
## [0.9.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.12...@ali/lowcode-designer@0.9.13) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-designer
<a name="0.9.12"></a>
## [0.9.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.11...@ali/lowcode-designer@0.9.12) (2020-05-15)
### Features
* change reducer stage ([c2e83c7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/c2e83c7))
<a name="0.9.11"></a> <a name="0.9.11"></a>
## [0.9.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.10...@ali/lowcode-designer@0.9.11) (2020-05-15) ## [0.9.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.10...@ali/lowcode-designer@0.9.11) (2020-05-15)

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-designer", "name": "@ali/lowcode-designer",
"version": "0.9.11", "version": "0.9.20",
"description": "Designer for Ali LowCode Engine", "description": "Designer for Ali LowCode Engine",
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
@ -15,9 +15,9 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-editor-core": "^0.8.16",
"@ali/lowcode-types": "^0.8.3", "@ali/lowcode-types": "^0.8.6",
"@ali/lowcode-utils": "^0.8.4", "@ali/lowcode-utils": "^0.8.7",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"event": "^1.0.0", "event": "^1.0.0",
"react": "^16", "react": "^16",

View File

@ -1,6 +1,6 @@
import { Component, Fragment } from 'react'; import { Component, Fragment } from 'react';
import DragResizeEngine from './drag-resize-engine'; import DragResizeEngine from './drag-resize-engine';
import { observer, computed } from '@ali/lowcode-editor-core'; import { observer, computed, globalContext, Editor } from '@ali/lowcode-editor-core';
import classNames from 'classnames'; import classNames from 'classnames';
import { SimulatorContext } from '../context'; import { SimulatorContext } from '../context';
import { BuiltinSimulatorHost } from '../host'; import { BuiltinSimulatorHost } from '../host';
@ -177,6 +177,17 @@ export class BoxResizingInstance extends Component<{
e.trigger = direction; e.trigger = direction;
metaData.experimental.callbacks.onResizeStart(e, node); metaData.experimental.callbacks.onResizeStart(e, node);
} }
const editor = globalContext.get(Editor);
const npm = node?.componentMeta?.npm;
const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
editor?.emit('designer.border.resize', {
selected,
layout: node?.parent?.getPropValue('layout') || '',
});
}; };
this.dragEngine.onResize(resize); this.dragEngine.onResize(resize);

View File

@ -9,7 +9,7 @@ import {
ComponentType, ComponentType,
} from 'react'; } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { observer, computed, Tip } from '@ali/lowcode-editor-core'; import { observer, computed, Tip, globalContext, Editor } from '@ali/lowcode-editor-core';
import { createIcon, isReactComponent } from '@ali/lowcode-utils'; import { createIcon, isReactComponent } from '@ali/lowcode-utils';
import { ActionContentObject, isActionContentObject } from '@ali/lowcode-types'; import { ActionContentObject, isActionContentObject } from '@ali/lowcode-types';
import { BuiltinSimulatorHost } from '../host'; import { BuiltinSimulatorHost } from '../host';
@ -124,6 +124,16 @@ function createAction(content: ReactNode | ComponentType<any> | ActionContentObj
className="lc-borders-action" className="lc-borders-action"
onClick={() => { onClick={() => {
action && action(node); action && action(node);
const editor = globalContext.get(Editor);
const npm = node?.componentMeta?.npm;
const target =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
editor?.emit('designer.border.action', {
name: key,
target,
});
}} }}
> >
{icon && createIcon(icon)} {icon && createIcon(icon)}

View File

@ -1,6 +1,6 @@
import * as EventEmitter from 'events'; import { EventEmitter } from 'events';
import { ISimulatorHost, isSimulatorHost } from '../../../../designer/src/simulator'; import { ISimulatorHost, isSimulatorHost } from '../../simulator';
import { Designer } from '../../../../designer/src/designer/designer'; import { Designer, Point } from '../../designer';
import { setNativeSelection, cursor } from '@ali/lowcode-utils'; import { setNativeSelection, cursor } from '@ali/lowcode-utils';
// import Cursor from './cursor'; // import Cursor from './cursor';
// import Pages from './pages'; // import Pages from './pages';
@ -66,21 +66,37 @@ export default class DragResizeEngine {
*/ */
from(shell: Element, direction: string, boost: (e: MouseEvent) => any) { from(shell: Element, direction: string, boost: (e: MouseEvent) => any) {
let node: any; let node: any;
let startEvent: MouseEvent; let startEvent: Point;
if (!shell) { if (!shell) {
return () => {}; return () => {};
} }
const move = (e: MouseEvent) => { const move = (e: MouseEvent) => {
const moveX = e.clientX - startEvent.clientX; const x = createResizeEvent(e);
const moveY = e.clientY - startEvent.clientY; const moveX = x.clientX - startEvent.clientX;
const moveY = x.clientY - startEvent.clientY;
this.emitter.emit('resize', e, direction, node, moveX, moveY); this.emitter.emit('resize', e, direction, node, moveX, moveY);
}; };
const masterSensors = this.getMasterSensors(); const masterSensors = this.getMasterSensors();
const createResizeEvent = (e: MouseEvent | DragEvent): Point => {
const evt: any = {};
const sourceDocument = e.view?.document;
if (!sourceDocument || sourceDocument === document) {
return e;
}
const srcSim = masterSensors.find((sim) => sim.contentDocument === sourceDocument);
if (srcSim) {
return srcSim.viewport.toGlobalPoint(e);
}
return e;
};
const over = (e: MouseEvent) => { const over = (e: MouseEvent) => {
const handleEvents = makeEventsHandler(e, masterSensors); const handleEvents = makeEventsHandler(e, masterSensors);
handleEvents((doc) => { handleEvents((doc) => {
@ -96,7 +112,7 @@ export default class DragResizeEngine {
const mousedown = (e: MouseEvent) => { const mousedown = (e: MouseEvent) => {
node = boost(e); node = boost(e);
startEvent = e; startEvent = createResizeEvent(e);
const handleEvents = makeEventsHandler(e, masterSensors); const handleEvents = makeEventsHandler(e, masterSensors);
handleEvents((doc) => { handleEvents((doc) => {
doc.addEventListener('mousemove', move, true); doc.addEventListener('mousemove', move, true);

View File

@ -1,10 +1,10 @@
import { obx, autorun, computed, getPublicPath, hotkey, focusTracker } from '@ali/lowcode-editor-core'; import { obx, autorun, computed, getPublicPath, hotkey, focusTracker, globalContext, Editor } from '@ali/lowcode-editor-core';
import { ISimulatorHost, Component, NodeInstance, ComponentInstance } from '../simulator'; import { ISimulatorHost, Component, NodeInstance, ComponentInstance } from '../simulator';
import Viewport from './viewport'; import Viewport from './viewport';
import { createSimulator } from './create-simulator'; import { createSimulator } from './create-simulator';
import { Node, ParentalNode, DocumentModel, isNode, contains, isRootNode } from '../document'; import { Node, ParentalNode, DocumentModel, isNode, contains, isRootNode } from '../document';
import ResourceConsumer from './resource-consumer'; import ResourceConsumer from './resource-consumer';
import { AssetLevel, Asset, AssetList, assetBundle, assetItem, AssetType, isElement } from '@ali/lowcode-utils'; import { AssetLevel, Asset, AssetList, assetBundle, assetItem, AssetType, isElement, isFormEvent } from '@ali/lowcode-utils';
import { import {
DragObjectType, DragObjectType,
isShaken, isShaken,
@ -22,7 +22,7 @@ import {
CanvasPoint, CanvasPoint,
} from '../designer'; } from '../designer';
import { parseMetadata } from './utils/parse-metadata'; import { parseMetadata } from './utils/parse-metadata';
import { ComponentMetadata } from '@ali/lowcode-types'; import { ComponentMetadata, ComponentSchema } from '@ali/lowcode-types';
import { BuiltinSimulatorRenderer } from './renderer'; import { BuiltinSimulatorRenderer } from './renderer';
import clipboard from '../designer/clipboard'; import clipboard from '../designer/clipboard';
import { LiveEditing } from './live-editing/live-editing'; import { LiveEditing } from './live-editing/live-editing';
@ -227,6 +227,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
this.setupDragAndClick(); this.setupDragAndClick();
this.setupDetecting(); this.setupDetecting();
this.setupLiveEditing(); this.setupLiveEditing();
this.setupContextMenu();
} }
setupDragAndClick() { setupDragAndClick() {
@ -240,6 +241,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
doc.addEventListener( doc.addEventListener(
'mousedown', 'mousedown',
(downEvent: MouseEvent) => { (downEvent: MouseEvent) => {
// fix for popups close logic
document.dispatchEvent(new Event('mousedown'));
if (this.liveEditing.editing) { if (this.liveEditing.editing) {
return; return;
} }
@ -247,6 +250,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
downEvent.stopPropagation(); downEvent.stopPropagation();
downEvent.preventDefault(); downEvent.preventDefault();
// FIXME: dirty fix remove label-for fro liveEditing
(downEvent.target as HTMLElement).removeAttribute('for');
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element); const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element);
const node = nodeInst?.node || this.document.rootNode; const node = nodeInst?.node || this.document.rootNode;
const isMulti = downEvent.metaKey || downEvent.ctrlKey; const isMulti = downEvent.metaKey || downEvent.ctrlKey;
@ -260,6 +266,15 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
selection.remove(id); selection.remove(id);
} else { } else {
selection.select(id); selection.select(id);
const editor = globalContext.get(Editor);
const npm = node?.componentMeta?.npm;
const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
editor?.emit('designer.builtinSimulator.select', {
selected,
});
} }
} }
}; };
@ -303,9 +318,14 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
doc.addEventListener( doc.addEventListener(
'click', 'click',
(e) => { (e) => {
// fix for popups close logic
document.dispatchEvent(new Event('click'));
const target = e.target as HTMLElement;
if (isFormEvent(e) || target?.closest('.next-input-group,.next-checkbox-group,.next-date-picker,.next-input,.next-month-picker,.next-number-picker,.next-radio-group,.next-range,.next-range-picker,.next-rating,.next-select,.next-switch,.next-time-picker,.next-upload,.next-year-picker,.next-breadcrumb-item,.next-calendar-header,.next-calendar-table')) {
e.preventDefault();
e.stopPropagation();
}
// stop response document click event // stop response document click event
// e.preventDefault();
// e.stopPropagation();
// todo: catch link redirect // todo: catch link redirect
}, },
true, true,
@ -400,6 +420,30 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
} }
} }
setupContextMenu() {
const doc = this.contentDocument!;
doc.addEventListener('contextmenu', (e: MouseEvent) => {
const targetElement = e.target as HTMLElement;
const nodeInst = this.getNodeInstanceFromElement(targetElement);
if (!nodeInst) {
return;
}
const node = nodeInst.node || this.document.rootNode;
if (!node) {
return;
}
const editor = globalContext.get(Editor);
const npm = node?.componentMeta?.npm;
const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
editor?.emit('desiger.builtinSimulator.contextmenu', {
selected,
});
});
}
/** /**
* @see ISimulator * @see ISimulator
*/ */
@ -437,6 +481,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return this.renderer?.getComponent(componentName) || null; return this.renderer?.getComponent(componentName) || null;
} }
createComponent(schema: ComponentSchema): Component | null {
return this.renderer?.createComponent(schema) || null;
}
@obx.val private instancesMap = new Map<string, ComponentInstance[]>(); @obx.val private instancesMap = new Map<string, ComponentInstance[]>();
setInstance(id: string, instances: ComponentInstance[] | null) { setInstance(id: string, instances: ComponentInstance[] | null) {
if (instances == null) { if (instances == null) {
@ -739,7 +787,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
this.sensing = true; this.sensing = true;
this.scroller.scrolling(e); this.scroller.scrolling(e);
const dropContainer = this.getDropContainer(e); const dropContainer = this.getDropContainer(e);
if (!dropContainer) { if (!dropContainer ||
(typeof dropContainer.container?.componentMeta?.prototype?.options?.canDropIn === 'function' &&
!dropContainer.container?.componentMeta?.prototype?.options?.canDropIn(e.dragObject.nodes[0]))) {
return null; return null;
} }

View File

@ -1,4 +1,4 @@
import { obx } from '@ali/lowcode-editor-core'; import { obx, globalContext, Editor } from '@ali/lowcode-editor-core';
import { LiveTextEditingConfig } from '@ali/lowcode-types'; import { LiveTextEditingConfig } from '@ali/lowcode-types';
import { Node, Prop } from '../../document'; import { Node, Prop } from '../../document';
@ -42,6 +42,14 @@ export class LiveEditing {
const targetElement = event.target as HTMLElement; const targetElement = event.target as HTMLElement;
const liveTextEditing = node.componentMeta.liveTextEditing; const liveTextEditing = node.componentMeta.liveTextEditing;
const editor = globalContext.get(Editor);
const npm = node?.componentMeta?.npm;
const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') || node?.componentMeta?.componentName || '';
editor?.emit('designer.builinSimulator.LiveEditing', {
selected,
});
let setterPropElement = getSetterPropElement(targetElement, rootElement); let setterPropElement = getSetterPropElement(targetElement, rootElement);
let propTarget = setterPropElement?.dataset.setterProp; let propTarget = setterPropElement?.dataset.setterProp;
let matched: (LiveTextEditingConfig & { propElement?: HTMLElement; }) | undefined | null; let matched: (LiveTextEditingConfig & { propElement?: HTMLElement; }) | undefined | null;
@ -98,7 +106,6 @@ export class LiveEditing {
const onSaveContent = matched?.onSaveContent || saveHandlers.find(item => item.condition(prop))?.onSaveContent || defaultSaveContent; const onSaveContent = matched?.onSaveContent || saveHandlers.find(item => item.condition(prop))?.onSaveContent || defaultSaveContent;
setterPropElement.setAttribute('contenteditable', matched?.mode && matched.mode !== 'plaintext' ? 'true' : 'plaintext-only'); setterPropElement.setAttribute('contenteditable', matched?.mode && matched.mode !== 'plaintext' ? 'true' : 'plaintext-only');
setterPropElement.removeAttribute('for');
setterPropElement.classList.add('engine-live-editing'); setterPropElement.classList.add('engine-live-editing');
// be sure // be sure
setterPropElement.focus(); setterPropElement.focus();
@ -110,6 +117,13 @@ export class LiveEditing {
const keydown = (e: KeyboardEvent) => { const keydown = (e: KeyboardEvent) => {
console.info(e.code); console.info(e.code);
switch (e.code) {
case 'Enter':
// TODO: check is richtext?
case 'Escape':
case 'Tab':
setterPropElement?.blur();
}
// esc // esc
// enter // enter
// tab // tab
@ -134,9 +148,7 @@ export class LiveEditing {
// TODO: upward testing for b/i/a html elements // TODO: upward testing for b/i/a html elements
// 非文本编辑
// 国际化数据,改变当前
// JSExpression, 改变 mock 或 弹出绑定变量
} }
get editing() { get editing() {

View File

@ -1,7 +1,7 @@
import { Overlay } from '@alifd/next'; import { Overlay } from '@alifd/next';
import React from 'react'; import React from 'react';
import { Title, globalContext, Editor } from '@ali/lowcode-editor-core';
import './index.less'; import './index.less';
import { Title } from '@ali/lowcode-editor-core';
import { Node, ParentalNode } from '@ali/lowcode-designer'; import { Node, ParentalNode } from '@ali/lowcode-designer';
@ -46,6 +46,16 @@ export default class InstanceNodeSelector extends React.Component<IProps, IState
onSelect = (node: Node) => () => { onSelect = (node: Node) => () => {
if (node && typeof node.select === 'function') { if (node && typeof node.select === 'function') {
node.select(); node.select();
const editor = globalContext.get(Editor);
const npm = node?.componentMeta?.npm;
const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
editor?.emit('designer.border.action', {
name: 'select',
selected,
});
} }
}; };
onMouseOver = (node: Node) => (_: any, flag = true) => { onMouseOver = (node: Node) => (_: any, flag = true) => {

View File

@ -1,7 +1,9 @@
import { ComponentInstance, NodeInstance, Component } from '../simulator'; import { ComponentInstance, NodeInstance, Component } from '../simulator';
import { ComponentSchema } from '@ali/lowcode-types';
export interface BuiltinSimulatorRenderer { export interface BuiltinSimulatorRenderer {
readonly isSimulatorRenderer: true; readonly isSimulatorRenderer: true;
createComponent(schema: ComponentSchema): Component | null;
getComponent(componentName: string): Component; getComponent(componentName: string): Component;
getComponentInstances(id: string): ComponentInstance[] | null; getComponentInstances(id: string): ComponentInstance[] | null;
getClosestNodeInstance(from: ComponentInstance, nodeId?: string): NodeInstance<ComponentInstance> | null; getClosestNodeInstance(from: ComponentInstance, nodeId?: string): NodeInstance<ComponentInstance> | null;

View File

@ -13,7 +13,7 @@ import {
FieldConfig, FieldConfig,
} from '@ali/lowcode-types'; } from '@ali/lowcode-types';
import { computed } from '@ali/lowcode-editor-core'; import { computed } from '@ali/lowcode-editor-core';
import { Node, ParentalNode } from './document'; import { Node, ParentalNode, TransformStage } from './document';
import { Designer } from './designer'; import { Designer } from './designer';
import { intlNode } from './locale'; import { intlNode } from './locale';
import { IconContainer } from './icons/container'; import { IconContainer } from './icons/container';
@ -249,6 +249,9 @@ export class ComponentMeta {
} }
return true; return true;
} }
// compatiable vision
prototype?: any;
} }
export function isComponentMeta(obj: any): obj is ComponentMeta { export function isComponentMeta(obj: any): obj is ComponentMeta {
@ -379,8 +382,8 @@ const builtinComponentActions: ComponentAction[] = [
title: intlNode('copy'), title: intlNode('copy'),
action(node: Node) { action(node: Node) {
// node.remove(); // node.remove();
const { document: doc, parent, schema, index } = node; const { document: doc, parent, index } = node;
parent && doc.insertNode(parent, schema, index); parent && doc.insertNode(parent, node, index, true);
}, },
}, },
important: true, important: true,

View File

@ -106,7 +106,9 @@ hotkey.bind(['command+c', 'ctrl+c', 'command+x', 'ctrl+x'], (e, action) => {
if (!selected || selected.length < 1) return; if (!selected || selected.length < 1) return;
const componentsMap = {}; const componentsMap = {};
const componentsTree = selected.map((item) => item.export(TransformStage.Save)); const componentsTree = selected.map((item) => item.export(TransformStage.Clone));
// FIXME: clear node.id
const data = { type: 'nodeSchema', componentsMap, componentsTree }; const data = { type: 'nodeSchema', componentsMap, componentsTree };

View File

@ -67,10 +67,19 @@ export class Designer {
this.project = new Project(this, props.defaultSchema); this.project = new Project(this, props.defaultSchema);
let startTime: any;
let src = '';
this.dragon.onDragstart((e) => { this.dragon.onDragstart((e) => {
startTime = Date.now() / 1000;
this.detecting.enable = false; this.detecting.enable = false;
const { dragObject } = e; const { dragObject } = e;
if (isDragNodeObject(dragObject)) { if (isDragNodeObject(dragObject)) {
const node = dragObject.nodes[0]?.parent;
const npm = node?.componentMeta?.npm;
src =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
if (dragObject.nodes.length === 1) { if (dragObject.nodes.length === 1) {
if (dragObject.nodes[0].parent) { if (dragObject.nodes[0].parent) {
// ensure current selecting // ensure current selecting
@ -111,6 +120,32 @@ export class Designer {
if (nodes) { if (nodes) {
loc.document.selection.selectAll(nodes.map((o) => o.id)); loc.document.selection.selectAll(nodes.map((o) => o.id));
setTimeout(() => this.activeTracker.track(nodes![0]), 10); setTimeout(() => this.activeTracker.track(nodes![0]), 10);
const endTime: any = Date.now() / 1000;
const parent = nodes[0]?.parent;
const npm = parent?.componentMeta?.npm;
const dest =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
parent?.componentMeta?.componentName ||
'';
this.editor?.emit('designer.drag', {
time: (endTime - startTime).toFixed(2),
selected: nodes
?.map((n) => {
if (!n) {
return;
}
const npm = n?.componentMeta?.npm;
return (
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
n?.componentMeta?.componentName
);
})
.join('&'),
align: loc?.detail?.near?.align || '',
pos: loc?.detail?.near?.pos || '',
src,
dest,
});
} }
} }
} }
@ -228,7 +263,7 @@ export class Designer {
touchOffsetObserver() { touchOffsetObserver() {
this.clearOobxList(true); this.clearOobxList(true);
this.oobxList.forEach(item => item.compute()); this.oobxList.forEach((item) => item.compute());
} }
createSettingEntry(editor: IEditor, nodes: Node[]) { createSettingEntry(editor: IEditor, nodes: Node[]) {
@ -392,12 +427,17 @@ export class Designer {
@computed get componentsMap(): { [key: string]: NpmInfo | Component } { @computed get componentsMap(): { [key: string]: NpmInfo | Component } {
const maps: any = {}; const maps: any = {};
this._componentMetasMap.forEach((config, key) => { this._componentMetasMap.forEach((config, key) => {
const view = config.getMetadata().experimental?.view; const metaData = config.getMetadata();
if (metaData.devMode === 'lowcode') {
maps[key] = this.currentDocument?.simulator?.createComponent(metaData.schema!);
} else {
const view = metaData.experimental?.view;
if (view) { if (view) {
maps[key] = view; maps[key] = view;
} else if (config.npm) { } else if (config.npm) {
maps[key] = config.npm; maps[key] = config.npm;
} }
}
}); });
return maps; return maps;
} }

View File

@ -159,20 +159,15 @@ function makeEventsHandler(
const topDoc = window.top.document; const topDoc = window.top.document;
const sourceDoc = boostEvent.view?.document || topDoc; const sourceDoc = boostEvent.view?.document || topDoc;
// TODO: optimize this logic, reduce listener // TODO: optimize this logic, reduce listener
// const boostPrevented = boostEvent.defaultPrevented;
const docs = new Set<Document>(); const docs = new Set<Document>();
// if (boostPrevented || isDragEvent(boostEvent)) {
docs.add(topDoc); docs.add(topDoc);
// }
docs.add(sourceDoc); docs.add(sourceDoc);
// if (sourceDoc !== topDoc || isDragEvent(boostEvent)) {
sensors.forEach((sim) => { sensors.forEach((sim) => {
const sdoc = sim.contentDocument; const sdoc = sim.contentDocument;
if (sdoc) { if (sdoc) {
docs.add(sdoc); docs.add(sdoc);
} }
}); });
// }
return (handle: (sdoc: Document) => void) => { return (handle: (sdoc: Document) => void) => {
docs.forEach((doc) => handle(doc)); docs.forEach((doc) => handle(doc));

View File

@ -37,7 +37,7 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
this._expanded = value; this._expanded = value;
} }
constructor(readonly parent: SettingEntry, config: FieldConfig) { constructor(readonly parent: SettingEntry, config: FieldConfig, settingFieldCollector?: (name: string | number, field: SettingField) => void) {
super(parent, config.name, config.type); super(parent, config.name, config.type);
const { title, items, setter, extraProps, ...rest } = config; const { title, items, setter, extraProps, ...rest } = config;
@ -52,7 +52,9 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
// initial items // initial items
if (this.type === 'group' && items) { if (this.type === 'group' && items) {
this.initItems(items); this.initItems(items, settingFieldCollector);
} else if (settingFieldCollector && config.name) {
settingFieldCollector(config.name, this);
} }
// compatiable old config // compatiable old config
@ -65,12 +67,12 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
return this._items; return this._items;
} }
private initItems(items: Array<FieldConfig | CustomView>) { private initItems(items: Array<FieldConfig | CustomView>, settingFieldCollector?: { (name: string | number, field: SettingField): void; (name: string, field: SettingField): void; }) {
this._items = items.map((item) => { this._items = items.map((item) => {
if (isCustomView(item)) { if (isCustomView(item)) {
return item; return item;
} }
return new SettingField(this, item); return new SettingField(this, item, settingFieldCollector);
}); });
} }
@ -88,8 +90,21 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
this.disposeItems(); this.disposeItems();
} }
private hotValue: any;
// ======= compatibles for vision ====== // ======= compatibles for vision ======
setValue(val: any, isHotValue?: boolean, force?: boolean, extraOptions?: any) {
if (isHotValue) {
this.setHotValue(val, extraOptions);
return;
}
super.setValue(val, false, false, extraOptions);
}
getHotValue(): any { getHotValue(): any {
if (this.hotValue) {
return this.hotValue;
}
// avoid View modify // avoid View modify
let v = cloneDeep(this.getMockOrValue()); let v = cloneDeep(this.getMockOrValue());
if (v == null) { if (v == null) {
@ -98,7 +113,8 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
return this.transducer.toHot(v); return this.transducer.toHot(v);
} }
setHotValue(data: any) { setHotValue(data: any, options?: any) {
this.hotValue = data;
const v = this.transducer.toNative(data); const v = this.transducer.toNative(data);
if (this.isUseVariable()) { if (this.isUseVariable()) {
const ov = this.getValue(); const ov = this.getValue();
@ -106,10 +122,16 @@ export class SettingField extends SettingPropEntry implements SettingEntry {
type: 'JSExpression', type: 'JSExpression',
value: ov.value, value: ov.value,
mock: v, mock: v,
}); }, false, false, options);
} else { } else {
this.setValue(v); this.setValue(v, false, false, options);
} }
// dirty fix list setter
if (Array.isArray(data) && data[0] && data[0].__sid__) {
return;
}
this.valueChange(); this.valueChange();
} }

View File

@ -144,12 +144,15 @@ export class SettingPropEntry implements SettingEntry {
/** /**
* *
*/ */
setValue(val: any) { setValue(val: any, isHotValue?: boolean, force?: boolean, extraOptions?: any) {
if (this.type === 'field') { if (this.type === 'field') {
this.parent.setPropValue(this.name, val); this.parent.setPropValue(this.name, val);
} }
if (!extraOptions) {
extraOptions = {};
}
const { setValue } = this.extraProps; const { setValue } = this.extraProps;
if (setValue) { if (setValue && !extraOptions.disableMutator) {
setValue(this, val); setValue(this, val);
} }
} }
@ -294,6 +297,9 @@ export class SettingPropEntry implements SettingEntry {
isUseVariable() { isUseVariable() {
return isJSExpression(this.getValue()); return isJSExpression(this.getValue());
} }
get useVariable() {
return this.isUseVariable();
}
getMockOrValue() { getMockOrValue() {
const v = this.getValue(); const v = this.getValue();
if (isJSExpression(v)) { if (isJSExpression(v)) {

View File

@ -2,7 +2,7 @@ import { EventEmitter } from 'events';
import { CustomView, isCustomView, IEditor } from '@ali/lowcode-types'; import { CustomView, isCustomView, IEditor } from '@ali/lowcode-types';
import { computed } from '@ali/lowcode-editor-core'; import { computed } from '@ali/lowcode-editor-core';
import { SettingEntry } from './setting-entry'; import { SettingEntry } from './setting-entry';
import { SettingField } from './setting-field'; import { SettingField, isSettingField } from './setting-field';
import { SettingPropEntry } from './setting-prop-entry'; import { SettingPropEntry } from './setting-prop-entry';
import { Node } from '../../document'; import { Node } from '../../document';
import { ComponentMeta } from '../../component-meta'; import { ComponentMeta } from '../../component-meta';
@ -20,6 +20,7 @@ export class SettingTopEntry implements SettingEntry {
private _items: Array<SettingField | CustomView> = []; private _items: Array<SettingField | CustomView> = [];
private _componentMeta: ComponentMeta | null = null; private _componentMeta: ComponentMeta | null = null;
private _isSame: boolean = true; private _isSame: boolean = true;
private _settingFieldMap: { [prop: string]: SettingField } = {};
readonly path = []; readonly path = [];
readonly top = this; readonly top = this;
readonly parent = this; readonly parent = this;
@ -96,12 +97,17 @@ export class SettingTopEntry implements SettingEntry {
private setupItems() { private setupItems() {
if (this.componentMeta) { if (this.componentMeta) {
const settingFieldMap: { [prop: string]: SettingField } = {};
const settingFieldCollector = (name: string | number, field: SettingField) => {
settingFieldMap[name] = field;
}
this._items = this.componentMeta.configure.map((item) => { this._items = this.componentMeta.configure.map((item) => {
if (isCustomView(item)) { if (isCustomView(item)) {
return item; return item;
} }
return new SettingField(this, item as any); return new SettingField(this, item as any, settingFieldCollector);
}); });
this._settingFieldMap = settingFieldMap;
} }
} }
@ -124,7 +130,7 @@ export class SettingTopEntry implements SettingEntry {
* *
*/ */
get(propName: string | number): SettingPropEntry { get(propName: string | number): SettingPropEntry {
return new SettingPropEntry(this, propName); return this._settingFieldMap[propName] || (new SettingPropEntry(this, propName));
} }
/** /**

View File

@ -39,7 +39,7 @@ export class Transducer {
} else if (isValidElement(setter) && setter.type.displayName === 'MixedSetter') { } else if (isValidElement(setter) && setter.type.displayName === 'MixedSetter') {
setter = setter.props.setters[0]; setter = setter.props.setters[0];
} else if (typeof setter === 'object' && setter.componentName === 'MixedSetter') { } else if (typeof setter === 'object' && setter.componentName === 'MixedSetter') {
setter = setter.props.setters[0]; setter = setter.props.setters?.[0];
} }
if (isSetterConfig(setter)) { if (isSetterConfig(setter)) {
@ -47,9 +47,6 @@ export class Transducer {
} }
if (typeof setter === 'string') { if (typeof setter === 'string') {
setter = getSetter(setter)?.component; setter = getSetter(setter)?.component;
if (!setter) {
// debugger;
}
} }
this.setterTransducer = combineTransducer( this.setterTransducer = combineTransducer(

View File

@ -66,6 +66,7 @@ export class DocumentModel {
return this.modalNode || this.rootNode; return this.modalNode || this.rootNode;
} }
private inited = false;
constructor(readonly project: Project, schema?: RootSchema) { constructor(readonly project: Project, schema?: RootSchema) {
/* /*
// TODO // TODO
@ -88,10 +89,11 @@ export class DocumentModel {
); );
this.history = new History( this.history = new History(
() => this.schema, () => this.export(TransformStage.Serilize),
(schema) => this.import(schema as RootSchema, true), (schema) => this.import(schema as RootSchema, true),
); );
this.setupListenActiveNodes(); this.setupListenActiveNodes();
this.inited = true;
} }
@obx.val private willPurgeSpace: Node[] = []; @obx.val private willPurgeSpace: Node[] = [];
@ -161,6 +163,9 @@ export class DocumentModel {
} }
let node: Node | null = null; let node: Node | null = null;
if (!this.inited) {
schema.id = null;
}
if (schema.id) { if (schema.id) {
node = this.getNode(schema.id); node = this.getNode(schema.id);
if (node && node.componentName === schema.componentName) { if (node && node.componentName === schema.componentName) {
@ -483,7 +488,7 @@ export class DocumentModel {
// add toData // add toData
toData() { toData() {
const node = this.project?.currentDocument?.export(TransformStage.Serilize); const node = this.project?.currentDocument?.export(TransformStage.Save);
return { componentsTree: [node] }; return { componentsTree: [node] };
} }

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { autorun, Reaction, untracked } from '@ali/lowcode-editor-core'; import { autorun, Reaction, untracked, globalContext, Editor } from '@ali/lowcode-editor-core';
import { NodeSchema } from '@ali/lowcode-types'; import { NodeSchema } from '@ali/lowcode-types';
// TODO: cache to localStorage // TODO: cache to localStorage
@ -114,6 +114,11 @@ export class History {
} }
const cursor = this.session.cursor - 1; const cursor = this.session.cursor - 1;
this.go(cursor); this.go(cursor);
const editor = globalContext.get(Editor);
if (!editor) {
return;
}
editor.emit('history.back', cursor);
} }
forward() { forward() {
@ -122,6 +127,11 @@ export class History {
} }
const cursor = this.session.cursor + 1; const cursor = this.session.cursor + 1;
this.go(cursor); this.go(cursor);
const editor = globalContext.get(Editor);
if (!editor) {
return;
}
editor.emit('history.forward', cursor);
} }
savePoint() { savePoint() {

View File

@ -158,6 +158,13 @@ export class NodeChildren {
return this.children.indexOf(node); return this.children.indexOf(node);
} }
/**
*
*/
splice(start: number, deleteCount: number, node: Node): Node[] {
return this.children.splice(start, deleteCount, node);
}
/** /**
* *
*/ */

View File

@ -1,4 +1,4 @@
import { obx, computed } from '@ali/lowcode-editor-core'; import { obx, computed, autorun } from '@ali/lowcode-editor-core';
import { import {
isDOMText, isDOMText,
isJSExpression, isJSExpression,
@ -13,7 +13,7 @@ import {
ComponentSchema, ComponentSchema,
NodeStatus, NodeStatus,
} from '@ali/lowcode-types'; } from '@ali/lowcode-types';
import { Props, EXTRA_KEY_PREFIX } from './props/props'; import { Props, getConvertedExtraKey } from './props/props';
import { DocumentModel } from '../document-model'; import { DocumentModel } from '../document-model';
import { NodeChildren } from './node-children'; import { NodeChildren } from './node-children';
import { Prop } from './props/prop'; import { Prop } from './props/prop';
@ -144,7 +144,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
constructor(readonly document: DocumentModel, nodeSchema: Schema) { constructor(readonly document: DocumentModel, nodeSchema: Schema) {
const { componentName, id, children, props, ...extras } = nodeSchema; const { componentName, id, children, props, ...extras } = nodeSchema;
this.id = id || `node$${document.nextId()}`; this.id = id || `node_${document.nextId()}`;
this.componentName = componentName; this.componentName = componentName;
if (this.componentName === 'Leaf') { if (this.componentName === 'Leaf') {
this.props = new Props(this, { this.props = new Props(this, {
@ -155,17 +155,33 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
this._children = new NodeChildren(this as ParentalNode, this.initialChildren(children)); this._children = new NodeChildren(this as ParentalNode, this.initialChildren(children));
this._children.interalInitParent(); this._children.interalInitParent();
this.props.import(this.transformProps(props || {}), extras); this.props.import(this.transformProps(props || {}), extras);
this.setupAutoruns();
}
if (this.componentMeta.isModal) {
this.getExtraProp('hidden', true)?.setValue(true);
} }
} }
private transformProps(props: any): any { private transformProps(props: any): any {
// FIXME! support PropsList // FIXME! support PropsList
const x = this.document.designer.transformProps(props, this, TransformStage.Init); return this.document.designer.transformProps(props, this, TransformStage.Init);
return x;
// TODO: run transducers in metadata.experimental // TODO: run transducers in metadata.experimental
} }
private autoruns?: Array<() => void>;
private setupAutoruns() {
const autoruns = this.componentMeta.getMetadata().experimental?.autoruns;
if (!autoruns || autoruns.length < 1) {
return;
}
this.autoruns = autoruns.map((item) => {
return autorun(() => {
item.autorun(this.props.get(item.name, true) as any);
}, true);
});
}
private initialChildren(children: any): NodeData[] { private initialChildren(children: any): NodeData[] {
// FIXME! this is dirty code // FIXME! this is dirty code
if (children == null) { if (children == null) {
@ -368,9 +384,33 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
// todo // todo
} }
replaceWith(schema: Schema, migrate = true) { replaceWith(schema: Schema, migrate = false) {
// reuse the same id? or replaceSelection // reuse the same id? or replaceSelection
// schema = Object.assign({}, migrate ? this.export() : {}, schema);
return this.parent?.replaceChild(this, schema);
}
/**
*
*
* @param {Node} node
* @param {object} data
*/
replaceChild(node: Node, data: any) {
if (this.children?.has(node)) {
const selected = this.document.selection.has(node.id);
delete data.id;
const newNode = this.document.createNode(data);
this.insertBefore(newNode, node);
node.remove();
if (selected) {
this.document.selection.select(newNode.id);
}
}
return node;
} }
getProp(path: string, stash = true): Prop | null { getProp(path: string, stash = true): Prop | null {
@ -378,7 +418,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
} }
getExtraProp(key: string, stash = true): Prop | null { getExtraProp(key: string, stash = true): Prop | null {
return this.props.get(EXTRA_KEY_PREFIX + key, stash) || null; return this.props.get(getConvertedExtraKey(key), stash) || null;
} }
/** /**
@ -426,7 +466,6 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
return this.parent.children.indexOf(this); return this.parent.children.indexOf(this);
} }
/** /**
* *
*/ */
@ -481,13 +520,11 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
* schema * schema
*/ */
export(stage: TransformStage = TransformStage.Save): Schema { export(stage: TransformStage = TransformStage.Save): Schema {
// run transducers
// run
const baseSchema: any = { const baseSchema: any = {
componentName: this.componentName, componentName: this.componentName,
}; };
if (stage !== TransformStage.Save) { if (stage !== TransformStage.Clone) {
baseSchema.id = this.id; baseSchema.id = this.id;
} }
@ -593,6 +630,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
if (this.isParental()) { if (this.isParental()) {
this.children.purge(); this.children.purge();
} }
this.autoruns?.forEach((dispose) => dispose());
this.props.purge(); this.props.purge();
this.document.internalRemoveAndPurgeNode(this); this.document.internalRemoveAndPurgeNode(this);
} }
@ -610,7 +648,16 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
insertBefore(node: Node, ref?: Node) { insertBefore(node: Node, ref?: Node) {
this.children?.insert(node, ref ? ref.index : null); this.children?.insert(node, ref ? ref.index : null);
} }
insertAfter(node: Node, ref?: Node) { insertAfter(node: any, ref?: Node) {
if (!isNode(node)) {
if (node.getComponentName) {
node = this.document.createNode({
componentName: node.getComponentName(),
});
} else {
node = this.document.createNode(node);
}
}
this.children?.insert(node, ref ? ref.index + 1 : null); this.children?.insert(node, ref ? ref.index + 1 : null);
} }
getParent() { getParent() {
@ -689,6 +736,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
* @deprecated * @deprecated
*/ */
getSuitablePlace(node: Node, ref: any): any { getSuitablePlace(node: Node, ref: any): any {
// TODO:
if (this.isRoot()) { if (this.isRoot()) {
return { container: this, ref }; return { container: this, ref };
} }
@ -723,7 +771,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
} }
getPrototype() { getPrototype() {
return this; return this.componentMeta.prototype;
} }
getIcon() { getIcon() {
@ -827,7 +875,7 @@ export function comparePosition(node1: Node, node2: Node): PositionNO {
export function insertChild(container: ParentalNode, thing: Node | NodeData, at?: number | null, copy?: boolean): Node { export function insertChild(container: ParentalNode, thing: Node | NodeData, at?: number | null, copy?: boolean): Node {
let node: Node; let node: Node;
if (isNode(thing) && (copy || thing.isSlot())) { if (isNode(thing) && (copy || thing.isSlot())) {
thing = thing.export(TransformStage.Save); thing = thing.export(TransformStage.Clone);
} }
if (isNode(thing)) { if (isNode(thing)) {
node = thing; node = thing;

View File

@ -1,6 +1,7 @@
import { obx, autorun, untracked, computed } from '@ali/lowcode-editor-core'; import { obx, autorun, untracked, computed } from '@ali/lowcode-editor-core';
import { Prop, IPropParent, UNSET } from './prop'; import { Prop, IPropParent, UNSET } from './prop';
import { Props } from './props'; import { Props } from './props';
import { Node } from '../node';
export type PendingItem = Prop[]; export type PendingItem = Prop[];
export class PropStash implements IPropParent { export class PropStash implements IPropParent {
@ -15,8 +16,10 @@ export class PropStash implements IPropParent {
return maps; return maps;
} }
private willPurge: () => void; private willPurge: () => void;
readonly owner: Node;
constructor(readonly props: Props, write: (item: Prop) => void) { constructor(readonly props: Props, write: (item: Prop) => void) {
this.owner = props.owner;
this.willPurge = autorun(() => { this.willPurge = autorun(() => {
if (this.space.size < 1) { if (this.space.size < 1) {
return; return;

View File

@ -4,7 +4,7 @@ import { uniqueId, isPlainObject, hasOwnProperty } from '@ali/lowcode-utils';
import { PropStash } from './prop-stash'; import { PropStash } from './prop-stash';
import { valueToSource } from './value-to-source'; import { valueToSource } from './value-to-source';
import { Props } from './props'; import { Props } from './props';
import { SlotNode } from '../node'; import { SlotNode, Node } from '../node';
import { TransformStage } from '../transform-stage'; import { TransformStage } from '../transform-stage';
export const UNSET = Symbol.for('unset'); export const UNSET = Symbol.for('unset');
@ -13,12 +13,35 @@ export type UNSET = typeof UNSET;
export interface IPropParent { export interface IPropParent {
delete(prop: Prop): void; delete(prop: Prop): void;
readonly props: Props; readonly props: Props;
readonly owner: Node;
} }
export type ValueTypes = 'unset' | 'literal' | 'map' | 'list' | 'expression' | 'slot'; export type ValueTypes = 'unset' | 'literal' | 'map' | 'list' | 'expression' | 'slot';
export class Prop implements IPropParent { export class Prop implements IPropParent {
readonly isProp = true; readonly isProp = true;
readonly owner: Node;
/**
* @see SettingTarget
*/
getPropValue(propName: string | number): any {
return this.get(propName)!.getValue();
}
/**
* @see SettingTarget
*/
setPropValue(propName: string | number, value: any): void {
this.set(propName, value);
}
/**
* @see SettingTarget
*/
clearPropValue(propName: string | number): void {
this.get(propName, false)?.unset();
}
readonly id = uniqueId('prop$'); readonly id = uniqueId('prop$');
@ -74,7 +97,7 @@ export class Prop implements IPropParent {
this.items!.forEach((prop, key) => { this.items!.forEach((prop, key) => {
const v = prop.export(stage); const v = prop.export(stage);
if (v !== UNSET) { if (v !== UNSET) {
maps[key] = v; maps[prop.key == null ? key : prop.key] = v;
} }
}); });
return maps; return maps;
@ -329,6 +352,7 @@ export class Prop implements IPropParent {
key?: string | number, key?: string | number,
spread = false, spread = false,
) { ) {
this.owner = parent.owner;
this.props = parent.props; this.props = parent.props;
if (value !== UNSET) { if (value !== UNSET) {
this.setValue(value); this.setValue(value);
@ -341,7 +365,7 @@ export class Prop implements IPropParent {
* *
* @param stash * @param stash
*/ */
get(path: string | number, stash = true): Prop | null { get(path: string | number, stash: boolean = true): Prop | null {
const type = this._type; const type = this._type;
if (type !== 'map' && type !== 'list' && type !== 'unset' && !stash) { if (type !== 'map' && type !== 'list' && type !== 'unset' && !stash) {
return null; return null;
@ -588,6 +612,14 @@ export class Prop implements IPropParent {
return isMap ? fn(item, item.key) : fn(item, index); return isMap ? fn(item, item.key) : fn(item, index);
}); });
} }
getProps() {
return this.parent;
}
getNode() {
return this.owner;
}
} }
export function isProp(obj: any): obj is Prop { export function isProp(obj: any): obj is Prop {

View File

@ -7,6 +7,19 @@ import { Node } from '../node';
import { TransformStage } from '../transform-stage'; import { TransformStage } from '../transform-stage';
export const EXTRA_KEY_PREFIX = '___'; export const EXTRA_KEY_PREFIX = '___';
export function getConvertedExtraKey(key: string): string {
if (!key) {
return '';
}
let _key = key;
if (key.indexOf('.') > 0) {
_key = key.split('.')[0];
}
return EXTRA_KEY_PREFIX + _key + EXTRA_KEY_PREFIX + key.substr(_key.length);
}
export function getOriginalExtraKey(key: string): string {
return key.replace(new RegExp(`${EXTRA_KEY_PREFIX}`, 'g'), '');
}
export class Props implements IPropParent { export class Props implements IPropParent {
readonly id = uniqueId('props'); readonly id = uniqueId('props');
@ -50,7 +63,7 @@ export class Props implements IPropParent {
} }
if (extras) { if (extras) {
Object.keys(extras).forEach(key => { Object.keys(extras).forEach(key => {
this.items.push(new Prop(this, (extras as any)[key], EXTRA_KEY_PREFIX + key)); this.items.push(new Prop(this, (extras as any)[key], getConvertedExtraKey(key)));
}); });
} }
} }
@ -70,7 +83,7 @@ export class Props implements IPropParent {
} }
if (extras) { if (extras) {
Object.keys(extras).forEach(key => { Object.keys(extras).forEach(key => {
this.items.push(new Prop(this, (extras as any)[key], EXTRA_KEY_PREFIX + key)); this.items.push(new Prop(this, (extras as any)[key], getConvertedExtraKey(key)));
}); });
} }
originItems.forEach(item => item.purge()); originItems.forEach(item => item.purge());
@ -97,7 +110,7 @@ export class Props implements IPropParent {
} }
let name = item.key as string; let name = item.key as string;
if (name && typeof name === 'string' && name.startsWith(EXTRA_KEY_PREFIX)) { if (name && typeof name === 'string' && name.startsWith(EXTRA_KEY_PREFIX)) {
name = name.substr(EXTRA_KEY_PREFIX.length); name = getOriginalExtraKey(name);
extras[name] = value; extras[name] = value;
} else { } else {
props.push({ props.push({
@ -119,7 +132,7 @@ export class Props implements IPropParent {
value = null; value = null;
} }
if (typeof name === 'string' && name.startsWith(EXTRA_KEY_PREFIX)) { if (typeof name === 'string' && name.startsWith(EXTRA_KEY_PREFIX)) {
name = name.substr(EXTRA_KEY_PREFIX.length); name = getOriginalExtraKey(name);
extras[name] = value; extras[name] = value;
} else { } else {
props[name] = value; props[name] = value;

View File

@ -2,5 +2,6 @@ export enum TransformStage {
Render = 1, Render = 1,
Serilize = 2, Serilize = 2,
Save = 3, Save = 3,
Init = 4, Clone = 4,
Init = 5,
} }

View File

@ -1,5 +1,5 @@
import { Component as ReactComponent, ComponentType } from 'react'; import { Component as ReactComponent, ComponentType } from 'react';
import { ComponentMetadata } from '@ali/lowcode-types'; import { ComponentMetadata, ComponentSchema } from '@ali/lowcode-types';
import { ISensor, Point, ScrollTarget, IScrollable } from './designer'; import { ISensor, Point, ScrollTarget, IScrollable } from './designer';
import { Node } from './document'; import { Node } from './document';
@ -126,6 +126,10 @@ export interface ISimulatorHost<P = object> extends ISensor {
* *
*/ */
getComponentInstances(node: Node): ComponentInstance[] | null; getComponentInstances(node: Node): ComponentInstance[] | null;
/**
* schema
*/
createComponent(schema: ComponentSchema): Component | null;
/** /**
* *
*/ */

View File

@ -3,6 +3,43 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.16"></a>
## [0.8.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.15...@ali/lowcode-editor-core@0.8.16) (2020-06-15)
### Features
* add Monitor ([f915d19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/f915d19))
* add URL link for setter titles ([4678408](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/4678408))
* ve事件埋点 ([700e5b0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/700e5b0))
<a name="0.8.15"></a>
## [0.8.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.14...@ali/lowcode-editor-core@0.8.15) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-editor-core
<a name="0.8.14"></a>
## [0.8.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.13...@ali/lowcode-editor-core@0.8.14) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-core
<a name="0.8.13"></a>
## [0.8.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.12...@ali/lowcode-editor-core@0.8.13) (2020-05-15)
**Note:** Version bump only for package @ali/lowcode-editor-core
<a name="0.8.12"></a> <a name="0.8.12"></a>
## [0.8.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.11...@ali/lowcode-editor-core@0.8.12) (2020-05-13) ## [0.8.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.11...@ali/lowcode-editor-core@0.8.12) (2020-05-13)

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-editor-core", "name": "@ali/lowcode-editor-core",
"version": "0.8.12", "version": "0.8.16",
"description": "Core Api for Ali lowCode engine", "description": "Core Api for Ali lowCode engine",
"license": "MIT", "license": "MIT",
"main": "lib/index.js", "main": "lib/index.js",
@ -15,8 +15,8 @@
"cloud-build": "build-scripts build --skip-demo" "cloud-build": "build-scripts build --skip-demo"
}, },
"dependencies": { "dependencies": {
"@ali/lowcode-types": "^0.8.3", "@ali/lowcode-types": "^0.8.6",
"@ali/lowcode-utils": "^0.8.4", "@ali/lowcode-utils": "^0.8.7",
"@alifd/next": "^1.19.16", "@alifd/next": "^1.19.16",
"@recore/obx": "^1.0.9", "@recore/obx": "^1.0.9",
"@recore/obx-react": "^1.0.8", "@recore/obx-react": "^1.0.8",

View File

@ -1,3 +1,6 @@
import { globalContext } from './di';
import { Editor } from './editor';
interface KeyMap { interface KeyMap {
[key: number]: string; [key: number]: string;
} }
@ -329,6 +332,19 @@ function fireCallback(callback: HotkeyCallback, e: KeyboardEvent, combo?: string
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
const editor = globalContext.get(Editor);
const designer = editor.get('designer');
const node = designer?.currentSelection?.getNodes()?.[0];
const npm = node?.componentMeta?.npm;
const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') || node?.componentMeta?.componentName || '';
editor?.emit('hotkey.callback.call', {
callback,
e,
combo,
sequence,
selected,
});
} }
export class Hotkey { export class Hotkey {

View File

@ -1,11 +0,0 @@
/**
*
* @param {String} gmKey
* @param {Object} params
* @param {String} logKey
*/
export function goldlog(gmKey: string, params: object = {}, logKey: string = 'other'): void {
}

View File

@ -1,5 +1,5 @@
export * from './get-public-path'; export * from './get-public-path';
export * from './goldlog'; export * from './monitor';
export * from './obx'; export * from './obx';
export * from './request'; export * from './request';
export * from './focus-tracker'; export * from './focus-tracker';

View File

@ -0,0 +1,46 @@
class Monitor {
fn = (params: any) => {
const { AES } = window as any;
if (typeof AES.log === 'function') {
const { p1, p2, p3, p4 = 'OTHER', ...rest } = params || {};
AES.log('event', {
p1,
p2,
p3,
p4,
...rest,
});
}
};
constructor() {
(window as any).AES = (window as any).AES || {};
}
register(fn: () => any) {
if (typeof fn === 'function') {
this.fn = fn;
}
}
log(params: any) {
if (typeof this.fn === 'function') {
this.fn(params);
}
}
setConfig(key: string | object, value?: string): void {
const { AES } = window as any;
if (typeof AES?.setConfig !== 'function') {
return;
}
if (typeof key === 'string' && value) {
AES.setConfig(key, value);
} else if (typeof key === 'object') {
AES.setConfig(key);
}
}
}
const monitor = new Monitor();
export { monitor };

View File

@ -7,8 +7,26 @@ import { Tip } from '../tip';
import './title.less'; import './title.less';
export class Title extends Component<{ title: TitleContent; className?: string; onClick?: () => void }> { export class Title extends Component<{ title: TitleContent; className?: string; onClick?: () => void }> {
constructor(props: any) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e: React.MouseEvent) {
const { title, onClick } = this.props as any;
const url = title && (title.docUrl || title.url);
if (url) {
window.open(url);
// 防止触发行操作(如折叠面板)
e.stopPropagation();
}
// TODO: 操作交互冲突,目前 mixedSetter 仅有 2 个 setter 注册时用到了 onClick
onClick && onClick(e);
}
render() { render() {
let { title, className, onClick } = this.props; let { title, className } = this.props;
if (title == null) {
return null;
}
if (isValidElement(title)) { if (isValidElement(title)) {
return title; return title;
} }
@ -37,7 +55,7 @@ export class Title extends Component<{ title: TitleContent; className?: string;
'has-tip': !!tip, 'has-tip': !!tip,
'only-icon': !title.label 'only-icon': !title.label
})} })}
onClick={onClick} onClick={this.handleClick}
> >
{icon ? <b className="lc-title-icon">{icon}</b> : null} {icon ? <b className="lc-title-icon">{icon}</b> : null}
{title.label ? intl(title.label) : null} {title.label ? intl(title.label) : null}

View File

@ -0,0 +1,52 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.9.6"></a>
## [0.9.6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-general@0.9.5...@ali/lowcode-editor-preset-general@0.9.6) (2020-06-16)
**Note:** Version bump only for package @ali/lowcode-editor-preset-general
<a name="0.9.5"></a>
## [0.9.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-general@0.9.4...@ali/lowcode-editor-preset-general@0.9.5) (2020-06-15)
**Note:** Version bump only for package @ali/lowcode-editor-preset-general
<a name="0.9.4"></a>
## [0.9.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-general@0.9.3...@ali/lowcode-editor-preset-general@0.9.4) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-editor-preset-general
<a name="0.9.3"></a>
## [0.9.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-general@0.9.2...@ali/lowcode-editor-preset-general@0.9.3) (2020-05-19)
**Note:** Version bump only for package @ali/lowcode-editor-preset-general
<a name="0.9.2"></a>
## [0.9.2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-general@0.9.1...@ali/lowcode-editor-preset-general@0.9.2) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-preset-general
<a name="0.9.1"></a>
## 0.9.1 (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-preset-general

View File

@ -4,7 +4,7 @@
"build-plugin-component", "build-plugin-component",
{ {
"filename": "editor-preset-general", "filename": "editor-preset-general",
"library": "LowcodeEditorPresetGeneral", "library": "LowcodeEditor",
"libraryTarget": "umd", "libraryTarget": "umd",
"externals": { "externals": {
"react": "var window.React", "react": "var window.React",

View File

@ -1,6 +1,7 @@
{ {
"name": "@ali/lowcode-editor-preset-general", "name": "@ali/lowcode-editor-preset-general",
"version": "0.9.0", "version": "0.9.6",
"private": true,
"description": "Ali General Editor Preset", "description": "Ali General Editor Preset",
"main": "lib/index.js", "main": "lib/index.js",
"files": [ "files": [
@ -9,17 +10,17 @@
"lib" "lib"
], ],
"scripts": { "scripts": {
"build": "build-scripts build --skip-demo",
"cloud-build": "build-scripts build --skip-demo" "cloud-build": "build-scripts build --skip-demo"
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ali/lowcode-utils": "^0.8.0", "@ali/lowcode-editor-core": "^0.8.16",
"@ali/lowcode-types": "^0.8.0", "@ali/lowcode-editor-skeleton": "^0.8.26",
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-plugin-designer": "^0.9.20",
"@ali/lowcode-editor-skeleton": "^0.8.17", "@ali/lowcode-plugin-outline-pane": "^0.8.26",
"@ali/lowcode-plugin-designer": "^0.9.11", "@ali/lowcode-types": "^0.8.6",
"@ali/lowcode-plugin-outline-pane": "^0.8.17", "@ali/lowcode-utils": "^0.8.7",
"@ali/lowcode-editor-setters": "^0.9.0",
"@alifd/next": "^1.19.12", "@alifd/next": "^1.19.12",
"@alife/theme-lowcode-dark": "^0.1.0", "@alife/theme-lowcode-dark": "^0.1.0",
"@alife/theme-lowcode-light": "^0.1.0", "@alife/theme-lowcode-light": "^0.1.0",
@ -27,6 +28,7 @@
"react-dom": "^16.8.1" "react-dom": "^16.8.1"
}, },
"devDependencies": { "devDependencies": {
"@ali/lowcode-editor-setters": "^0.9.3",
"@alib/build-scripts": "^0.1.18", "@alib/build-scripts": "^0.1.18",
"@types/events": "^3.0.0", "@types/events": "^3.0.0",
"@types/react": "^16.8.3", "@types/react": "^16.8.3",
@ -35,5 +37,8 @@
"build-plugin-moment-locales": "^0.1.0", "build-plugin-moment-locales": "^0.1.0",
"build-plugin-react-app": "^1.1.2", "build-plugin-react-app": "^1.1.2",
"tsconfig-paths-webpack-plugin": "^3.2.0" "tsconfig-paths-webpack-plugin": "^3.2.0"
},
"publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com"
} }
} }

View File

@ -3,7 +3,7 @@ import { createElement } from 'react';
import { Workbench, Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton'; import { Workbench, Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton';
import { globalContext, Editor } from '@ali/lowcode-editor-core'; import { globalContext, Editor } from '@ali/lowcode-editor-core';
import { Designer } from '@ali/lowcode-designer'; import { Designer } from '@ali/lowcode-designer';
import { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane'; import Outline, { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane';
import DesignerPlugin from '@ali/lowcode-plugin-designer'; import DesignerPlugin from '@ali/lowcode-plugin-designer';
import '@ali/lowcode-editor-setters'; import '@ali/lowcode-editor-setters';
@ -30,6 +30,15 @@ skeleton.add({
type: 'Widget', type: 'Widget',
content: DesignerPlugin, content: DesignerPlugin,
}); });
skeleton.add({
area: 'leftArea',
name: 'outlinePane',
type: 'PanelDock',
content: Outline,
panelProps: {
area: 'leftFixedArea',
},
});
skeleton.add({ skeleton.add({
area: 'rightArea', area: 'rightArea',
name: 'settingsPane', name: 'settingsPane',
@ -74,7 +83,7 @@ export function init(container?: Element) {
} }
console.log( console.log(
`%cLowcodeEditorPresetGeneral %cv${version}`, `%cLowcodeEngine %cv${version}`,
"color:#000;font-weight:bold;", "color:#000;font-weight:bold;",
"color:green;font-weight:bold;" "color:green;font-weight:bold;"
); );

View File

@ -3,6 +3,113 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.21"></a>
## [0.8.21](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-vision@0.8.20...@ali/lowcode-editor-preset-vision@0.8.21) (2020-06-16)
**Note:** Version bump only for package @ali/lowcode-editor-preset-vision
<a name="0.8.20"></a>
## [0.8.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-vision@0.8.19...@ali/lowcode-editor-preset-vision@0.8.20) (2020-06-15)
### Bug Fixes
* compatiable old VE api ([45af1c5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/45af1c5))
* i18n parser & setting ([dbdd9e4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dbdd9e4))
* patch prototype ([f20bfaa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/f20bfaa))
* render children ([487f257](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/487f257))
* style ([4694331](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/4694331))
* 调整保存成功弹出框位置 ([5198dae](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/5198dae))
### Features
* complete live-editing expr & i18n ([3ac08ba](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3ac08ba))
* support prop.autorun ([c0a5235](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/c0a5235))
* ve事件埋点 ([700e5b0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/700e5b0))
<a name="0.8.19"></a>
## [0.8.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-vision@0.8.18...@ali/lowcode-editor-preset-vision@0.8.19) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-editor-preset-vision
<a name="0.8.18"></a>
## [0.8.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-vision@0.8.17...@ali/lowcode-editor-preset-vision@0.8.18) (2020-05-19)
**Note:** Version bump only for package @ali/lowcode-editor-preset-vision
<a name="0.8.17"></a>
## [0.8.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-vision@0.8.16...@ali/lowcode-editor-preset-vision@0.8.17) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-preset-vision
<a name="0.8.16"></a>
## [0.8.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-preset-vision@0.8.15...@ali/lowcode-editor-preset-vision@0.8.16) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-preset-vision
<a name="0.8.15"></a>
## 0.8.15 (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-preset-vision
<a name="0.8.14"></a>
## [0.8.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-vision-preset@0.8.13...@ali/lowcode-vision-preset@0.8.14) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-vision-preset
<a name="0.8.13"></a>
## [0.8.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-vision-preset@0.8.12...@ali/lowcode-vision-preset@0.8.13) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-vision-preset
<a name="0.8.12"></a>
## [0.8.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-vision-preset@0.8.11...@ali/lowcode-vision-preset@0.8.12) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-vision-preset
<a name="0.8.11"></a>
## [0.8.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-vision-preset@0.8.10...@ali/lowcode-vision-preset@0.8.11) (2020-05-15)
### Features
* add filter reducer ([17c6ed3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/17c6ed3))
* change reducer stage ([c2e83c7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/c2e83c7))
<a name="0.8.10"></a> <a name="0.8.10"></a>
## [0.8.10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-vision-preset@0.8.9...@ali/lowcode-vision-preset@0.8.10) (2020-05-15) ## [0.8.10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-vision-preset@0.8.9...@ali/lowcode-vision-preset@0.8.10) (2020-05-15)

View File

@ -3,8 +3,8 @@
[ [
"build-plugin-component", "build-plugin-component",
{ {
"filename": "vision-preset", "filename": "editor-preset-vision",
"library": "VisualEngine", "library": "LowcodeEditor",
"libraryTarget": "umd", "libraryTarget": "umd",
"externals": { "externals": {
"react": "var window.React", "react": "var window.React",

View File

@ -1,7 +1,7 @@
{ {
"name": "@ali/lowcode-editor-preset-vision", "name": "@ali/lowcode-editor-preset-vision",
"version": "0.8.21",
"private": true, "private": true,
"version": "0.8.10",
"description": "Vision Polyfill for Ali lowCode engine", "description": "Vision Polyfill for Ali lowCode engine",
"main": "lib/index.js", "main": "lib/index.js",
"files": [ "files": [
@ -10,15 +10,17 @@
"lib" "lib"
], ],
"scripts": { "scripts": {
"build": "build-scripts build --skip-demo",
"cloud-build": "build-scripts build --skip-demo" "cloud-build": "build-scripts build --skip-demo"
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-designer": "^0.9.20",
"@ali/lowcode-editor-skeleton": "^0.8.17", "@ali/lowcode-editor-core": "^0.8.16",
"@ali/lowcode-plugin-designer": "^0.9.11", "@ali/lowcode-editor-skeleton": "^0.8.26",
"@ali/lowcode-plugin-outline-pane": "^0.8.17", "@ali/lowcode-plugin-designer": "^0.9.20",
"@ali/ve-i18n-util": "^2.0.2", "@ali/lowcode-plugin-outline-pane": "^0.8.26",
"@ali/ve-i18n-util": "^2.0.0",
"@ali/ve-icons": "^4.1.9", "@ali/ve-icons": "^4.1.9",
"@ali/ve-less-variables": "2.0.3", "@ali/ve-less-variables": "2.0.3",
"@ali/ve-popups": "^4.2.5", "@ali/ve-popups": "^4.2.5",
@ -44,5 +46,8 @@
"build-plugin-moment-locales": "^0.1.0", "build-plugin-moment-locales": "^0.1.0",
"build-plugin-react-app": "^1.1.2", "build-plugin-react-app": "^1.1.2",
"tsconfig-paths-webpack-plugin": "^3.2.0" "tsconfig-paths-webpack-plugin": "^3.2.0"
},
"publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com"
} }
} }

View File

@ -1,5 +1,5 @@
import { ComponentType, ReactElement } from 'react'; import { ComponentType, ReactElement } from 'react';
import { ComponentMetadata, FieldConfig, InitialItem } from '@ali/lowcode-types'; import { ComponentMetadata, FieldConfig, InitialItem, FilterItem, AutorunItem } from '@ali/lowcode-types';
import { import {
ComponentMeta, ComponentMeta,
addBuiltinComponentAction, addBuiltinComponentAction,
@ -18,22 +18,42 @@ import {
import { designer } from '../editor'; import { designer } from '../editor';
import { uniqueId } from '@ali/lowcode-utils'; import { uniqueId } from '@ali/lowcode-utils';
const GlobalPropsConfigure: Array<{ position: string; initials?: InitialItem[]; config: FieldConfig }> = []; const GlobalPropsConfigure: Array<{
position: string;
initials?: InitialItem[];
filters?: FilterItem[];
autoruns?: AutorunItem[];
config: FieldConfig
}> = [];
const Overrides: { const Overrides: {
[componentName: string]: { [componentName: string]: {
initials?: InitialItem[]; initials?: InitialItem[];
filters?: FilterItem[];
autoruns?: AutorunItem[];
override: any; override: any;
}; };
} = {}; } = {};
function addGlobalPropsConfigure(config: OldGlobalPropConfig) { function addGlobalPropsConfigure(config: OldGlobalPropConfig) {
const initials: InitialItem[] = []; const initials: InitialItem[] = [];
const filters: FilterItem[] = [];
const autoruns: AutorunItem[] = [];
GlobalPropsConfigure.push({ GlobalPropsConfigure.push({
position: config.position || 'bottom', position: config.position || 'bottom',
initials, initials,
config: upgradePropConfig(config, (item) => { filters,
autoruns,
config: upgradePropConfig(config, {
addInitial: (item) => {
initials.push(item); initials.push(item);
}), },
addFilter: (item) => {
filters.push(item);
},
addAutorun: (item) => {
autoruns.push(item);
},
})
}); });
} }
function removeGlobalPropsConfigure(name: string) { function removeGlobalPropsConfigure(name: string) {
@ -46,20 +66,30 @@ function removeGlobalPropsConfigure(name: string) {
} }
function overridePropsConfigure(componentName: string, config: { [name: string]: OldPropConfig } | OldPropConfig[]) { function overridePropsConfigure(componentName: string, config: { [name: string]: OldPropConfig } | OldPropConfig[]) {
const initials: InitialItem[] = []; const initials: InitialItem[] = [];
const filters: FilterItem[] = [];
const autoruns: AutorunItem[] = [];
const addInitial = (item: InitialItem) => { const addInitial = (item: InitialItem) => {
initials.push(item); initials.push(item);
}; };
const addFilter = (item: FilterItem) => {
filters.push(item);
};
const addAutorun = (item: AutorunItem) => {
autoruns.push(item);
};
let override: any; let override: any;
if (Array.isArray(config)) { if (Array.isArray(config)) {
override = upgradeConfigure(config, addInitial); override = upgradeConfigure(config, { addInitial, addFilter, addAutorun });
} else { } else {
override = {}; override = {};
Object.keys(config).forEach(key => { Object.keys(config).forEach(key => {
override[key] = upgradePropConfig(config[key], addInitial); override[key] = upgradePropConfig(config[key], { addInitial, addFilter, addAutorun });
}); });
} }
Overrides[componentName] = { Overrides[componentName] = {
initials, initials,
filters,
autoruns,
override, override,
}; };
} }
@ -89,6 +119,7 @@ registerMetadataTransducer(
} else if (position === 'bottom') { } else if (position === 'bottom') {
bottom.push(item.config); bottom.push(item.config);
} }
// TODO: replace autoruns,initials,filters
}); });
const override = Overrides[componentName]?.override; const override = Overrides[componentName]?.override;
@ -109,6 +140,7 @@ registerMetadataTransducer(
} }
} }
} }
// TODO: replace autoruns,initials,filters
} }
return metadata; return metadata;
@ -184,7 +216,7 @@ class Prototype {
return new Prototype(config); return new Prototype(config);
} }
private id: string; readonly isPrototype = true;
private meta: ComponentMeta; private meta: ComponentMeta;
readonly options: OldPrototypeConfig | ComponentMetadata; readonly options: OldPrototypeConfig | ComponentMetadata;
@ -197,11 +229,11 @@ class Prototype {
const metadata = isNewSpec(input) ? input : upgradeMetadata(input); const metadata = isNewSpec(input) ? input : upgradeMetadata(input);
this.meta = designer.createComponentMeta(metadata); this.meta = designer.createComponentMeta(metadata);
} }
this.id = uniqueId('prototype'); (this.meta as any).prototype = this;
} }
getId() { getId() {
return this.id; return this.getComponentName();
} }
getConfig(configName?: keyof (OldPrototypeConfig | ComponentMetadata)) { getConfig(configName?: keyof (OldPrototypeConfig | ComponentMetadata)) {
@ -298,4 +330,8 @@ class Prototype {
} }
} }
export function isPrototype(obj: any): obj is Prototype {
return obj && obj.isPrototype;
}
export default Prototype; export default Prototype;

View File

@ -1,6 +1,6 @@
import { ReactElement, ComponentType } from 'react'; import { ReactElement, ComponentType } from 'react';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { registerSetter, RegisteredSetter } from '@ali/lowcode-editor-core'; import { registerSetter, RegisteredSetter, getSetter } from '@ali/lowcode-editor-core';
import Bundle from './bundle'; import Bundle from './bundle';
import { CustomView } from '@ali/lowcode-types'; import { CustomView } from '@ali/lowcode-types';
@ -41,6 +41,38 @@ export class Trunk {
return this.metaBundle.getFromMeta(name); return this.metaBundle.getFromMeta(name);
} }
getPrototypeById(id: string) {
return this.getPrototype(id);
}
listByCategory() {
const categories: any[] = [];
const categoryMap: any = {};
const categoryItems: any[] = [];
const defaultCategory = {
items: categoryItems,
name: '*',
};
categories.push(defaultCategory);
categoryMap['*'] = defaultCategory;
this.getList().forEach((prototype) => {
const cat = prototype.getCategory();
if (!cat) {
return;
}
if (!categoryMap.hasOwnProperty(cat)) {
const categoryMapItems: any[] = [];
categoryMap[cat] = {
items: categoryMapItems,
name: cat,
};
categories.push(categoryMap[cat]);
}
categoryMap[cat].items.push(prototype);
});
return categories;
}
getPrototypeView(componentName: string) { getPrototypeView(componentName: string) {
return this.getPrototype(componentName)?.getView(); return this.getPrototype(componentName)?.getView();
} }
@ -72,6 +104,14 @@ export class Trunk {
setPackages() { setPackages() {
console.warn('Trunk.setPackages is deprecated'); console.warn('Trunk.setPackages is deprecated');
} }
getSetter(type: string): any{
const setter = getSetter(type);
if (setter?.component) {
return setter.component;
}
return setter;
}
} }
export default new Trunk(); export default new Trunk();

View File

@ -1,6 +1,8 @@
import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react'; import { ComponentType, ReactElement, isValidElement, ComponentClass } from 'react';
import { isPlainObject } from '@ali/lowcode-utils'; import { isPlainObject } from '@ali/lowcode-utils';
import { isI18nData, SettingTarget, InitialItem, isJSSlot, isJSExpression } from '@ali/lowcode-types'; import { isI18nData, SettingTarget, InitialItem, FilterItem, isJSSlot, ProjectSchema, AutorunItem } from '@ali/lowcode-types';
import { untracked } from '@ali/lowcode-editor-core';
import { editor, designer } from '../editor';
type Field = SettingTarget; type Field = SettingTarget;
@ -166,6 +168,8 @@ export interface OldPrototypeConfig {
onResizeStart?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void; onResizeStart?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
onResize?: (e: MouseEvent, triggerDirection: string, dragment: Node, moveX: number, moveY: number) => void; onResize?: (e: MouseEvent, triggerDirection: string, dragment: Node, moveX: number, moveY: number) => void;
onResizeEnd?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void; onResizeEnd?: (e: MouseEvent, triggerDirection: string, dragment: Node) => void;
devMode?: string;
schema?: ProjectSchema;
} }
export interface ISetterConfig { export interface ISetterConfig {
@ -178,7 +182,7 @@ type SetterGetter = (this: Field, value: any) => ComponentClass;
type ReturnBooleanFunction = (this: Field, value: any) => boolean; type ReturnBooleanFunction = (this: Field, value: any) => boolean;
export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial) { export function upgradePropConfig(config: OldPropConfig, collector: ConfigCollector) {
const { const {
type, type,
name, name,
@ -209,7 +213,9 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
liveTextEditing, liveTextEditing,
} = config; } = config;
const extraProps: any = {}; const extraProps: any = {
display: DISPLAY_TYPE.BLOCK,
};
const newConfig: any = { const newConfig: any = {
type: type === 'group' ? 'group' : 'field', type: type === 'group' ? 'group' : 'field',
name, name,
@ -261,22 +267,9 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
} else if (hidden != null || disabled != null) { } else if (hidden != null || disabled != null) {
extraProps.condition = (field: Field) => !(isHidden(field) || isDisabled(field)); extraProps.condition = (field: Field) => !(isHidden(field) || isDisabled(field));
} }
if (ignore != null || disabled != null) {
// FIXME! addFilter
extraProps.virtual = (field: Field) => {
if (isDisabled(field)) {
return true;
}
if (typeof ignore === 'function') {
return ignore.call(field, field.getValue()) === true;
}
return ignore === true;
};
}
if (type === 'group') { if (type === 'group') {
newConfig.items = items ? upgradeConfigure(items, addInitial) : []; newConfig.items = items ? upgradeConfigure(items, collector) : [];
return newConfig; return newConfig;
} }
@ -303,18 +296,44 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
}; };
} }
if (accessor && !slotName) { if (!slotName) {
if (accessor) {
extraProps.getValue = (field: Field, fieldValue: any) => { extraProps.getValue = (field: Field, fieldValue: any) => {
return accessor.call(field, fieldValue); return accessor.call(field, fieldValue);
}; };
if (!initialFn) { }
initialFn = accessor;
if (sync || accessor) {
collector.addAutorun({
name,
autorun: (field: Field) => {
let fieldValue = untracked(() => field.getValue());
if (accessor) {
fieldValue = accessor.call(field, fieldValue)
}
if (sync) {
fieldValue = sync.call(field, fieldValue);
if (fieldValue !== undefined) {
field.setValue(fieldValue);
}
} else {
field.setValue(fieldValue);
}
}
});
}
if (mutator) {
extraProps.setValue = (field: Field, value: any) => {
mutator.call(field, value, value);
};
} }
} }
const setterInitial = getInitialFromSetter(setter); const setterInitial = getInitialFromSetter(setter);
addInitial({ collector.addInitial({
// FIXME! name could be "xxx.xxx"
name: slotName || name, name: slotName || name,
initial: (field: Field, currentValue: any) => { initial: (field: Field, currentValue: any) => {
// FIXME! read from prototype.defaultProps // FIXME! read from prototype.defaultProps
@ -334,18 +353,27 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
}, },
}); });
if (sync) { if (ignore != null || disabled != null) {
extraProps.autorun = (field: Field) => { collector.addFilter({
const value = sync.call(field, field.getValue()); // FIXME! name should be "xxx.xxx"
if (value !== undefined) { name: slotName || name,
field.setValue(value); filter: (field: Field, currentValue: any) => {
let disabledValue: boolean;
if (typeof disabled === 'function') {
disabledValue = disabled.call(field, currentValue) === true;
} }
}; else {
disabledValue = disabled === true;
} }
if (mutator && !slotName) { if (disabledValue) {
extraProps.setValue = (field: Field, value: any) => { return false;
mutator.call(field, value, value); }
}; if (typeof ignore === 'function') {
return ignore.call(field, currentValue) !== true;
}
return ignore !== true;
}
});
} }
if (slotName) { if (slotName) {
@ -371,7 +399,7 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
}, },
}, },
]; ];
if (allowTextInput !== false) { if (allowTextInput) {
setters.unshift('I18nSetter'); setters.unshift('I18nSetter');
} }
if (supportVariable) { if (supportVariable) {
@ -386,9 +414,25 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
if (type === 'composite') { if (type === 'composite') {
const initials: InitialItem[] = []; const initials: InitialItem[] = [];
const objItems = items const objItems = items
? upgradeConfigure(items, (item) => { ? upgradeConfigure(items,
{
addInitial: (item) => {
initials.push(item); initials.push(item);
}) },
addFilter: (item) => {
collector.addFilter({
name: `${name}.${item.name}`,
filter: item.filter,
});
},
addAutorun: (item) => {
collector.addAutorun({
name: `${name}.${item.name}`,
autorun: item.autorun,
});
},
}
)
: []; : [];
const initial = (target: SettingTarget, value?: any) => { const initial = (target: SettingTarget, value?: any) => {
// TODO: // TODO:
@ -400,7 +444,7 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
}); });
return data; return data;
}; };
addInitial({ collector.addInitial({
name, name,
initial, initial,
}); });
@ -460,7 +504,15 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
return newConfig; return newConfig;
} }
type AddIntial = (initialItem: InitialItem) => void; type AddInitial = (initialItem: InitialItem) => void;
type AddFilter = (filterItem: FilterItem) => void;
type AddAutorun = (autorunItem: AutorunItem) => void;
type ConfigCollector = {
addInitial: AddInitial;
addFilter: AddFilter;
addAutorun: AddAutorun;
}
function getInitialFromSetter(setter: any) { function getInitialFromSetter(setter: any) {
return setter && ( return setter && (
@ -474,7 +526,7 @@ function defaultInitial(value: any, defaultValue: any) {
} }
export function upgradeConfigure(items: OldPropConfig[], addInitial: AddIntial) { export function upgradeConfigure(items: OldPropConfig[], collector: ConfigCollector) {
const configure: any[] = []; const configure: any[] = [];
let ignoreSlotName: any = null; let ignoreSlotName: any = null;
items.forEach((config) => { items.forEach((config) => {
@ -487,7 +539,7 @@ export function upgradeConfigure(items: OldPropConfig[], addInitial: AddIntial)
} }
ignoreSlotName = null; ignoreSlotName = null;
} }
configure.push(upgradePropConfig(config, addInitial)); configure.push(upgradePropConfig(config, collector));
}); });
return configure; return configure;
} }
@ -560,6 +612,8 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
onResizeStart, // onResizeStart onResizeStart, // onResizeStart
onResize, // onResize onResize, // onResize
onResizeEnd, // onResizeEnd onResizeEnd, // onResizeEnd
devMode,
schema,
} = oldConfig; } = oldConfig;
const meta: any = { const meta: any = {
@ -567,7 +621,8 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
title, title,
icon, icon,
docUrl, docUrl,
devMode: 'procode', devMode: devMode || 'procode',
schema: schema?.componentsTree[0],
}; };
if (category) { if (category) {
@ -655,8 +710,9 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
if (initialChildren) { if (initialChildren) {
experimental.initialChildren = experimental.initialChildren =
typeof initialChildren === 'function' typeof initialChildren === 'function'
? (field: Field) => { ? (node: any) => {
return initialChildren.call(field, (field as any).props); const props = designer.createSettingEntry(editor, [ node ]);
return initialChildren.call(node, props);
} }
: initialChildren; : initialChildren;
} }
@ -724,10 +780,24 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
experimental.callbacks = callbacks; experimental.callbacks = callbacks;
const initials: InitialItem[] = []; const initials: InitialItem[] = [];
const props = upgradeConfigure(configure || [], (item) => { const filters: FilterItem[] = [];
const autoruns: AutorunItem[] = [];
const props = upgradeConfigure(configure || [],
{
addInitial: (item) => {
initials.push(item); initials.push(item);
}); },
addFilter: (item) => {
filters.push(item);
},
addAutorun: (item) => {
autoruns.push(item);
}
}
);
experimental.initials = initials; experimental.initials = initials;
experimental.filters = filters;
experimental.autoruns = autoruns;
const supports: any = {}; const supports: any = {};
if (canUseCondition != null) { if (canUseCondition != null) {

View File

@ -1,5 +1,6 @@
import logger from '@ali/vu-logger'; import logger from '@ali/vu-logger';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { editor } from './editor';
/** /**
* Bus class as an EventEmitter * Bus class as an EventEmitter
@ -19,7 +20,6 @@ export class Bus {
// alias to unsub // alias to unsub
off(event: string, func: (...args: any[]) => any) { off(event: string, func: (...args: any[]) => any) {
this.unsub(event, func); this.unsub(event, func);
} }
// alias to pub // alias to pub
@ -62,4 +62,18 @@ export class Bus {
} }
} }
export default new Bus(); const bus = new Bus();
editor.on('hotkey.callback.call', (data) => {
bus.emit('ve.hotkey.callback.call', data);
});
editor.on('history.back', (data) => {
bus.emit('ve.history.back', data);
});
editor.on('history.forward', (data) => {
bus.emit('ve.history.forward', data);
});
export default bus;

View File

@ -0,0 +1,41 @@
import Env from './env';
import { isJSSlot, isI18nData, isJSExpression } from '@ali/lowcode-types';
import { isPlainObject } from '@ali/lowcode-utils';
import i18nUtil from './i18n-util';
// FIXME: 表达式使用 mock 值未来live 模式直接使用原始值
export function deepValueParser(obj?: any): any {
if (isJSExpression(obj)) {
obj = obj.mock;
}
if (!obj) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => deepValueParser(item));
}
if (isPlainObject(obj)) {
if (isI18nData(obj)) {
// FIXME! use editor.get
let locale = Env.getLocale();
if (obj.key) {
// FIXME: 此处需要升级I18nUtil改成响应式
return i18nUtil.get(obj.key, locale);
}
if (locale !== 'zh_CN' && locale !== 'zh_TW' && !obj[locale]) {
locale = 'en_US';
}
return obj[obj.use || locale] || obj.zh_CN;
}
if (isJSSlot(obj)) {
return obj;
}
const out: any = {};
Object.keys(obj).forEach((key) => {
out[key] = deepValueParser(obj[key]);
});
return out;
}
return obj;
}

View File

@ -1,5 +1,6 @@
import { designer } from './editor'; import { designer } from './editor';
import { DragObjectType, isNode, isDragNodeDataObject } from '@ali/lowcode-designer'; import { DragObjectType, isNode, isDragNodeDataObject } from '@ali/lowcode-designer';
import { isPrototype } from './bundle/prototype';
const dragon = designer.dragon; const dragon = designer.dragon;
const DragEngine = { const DragEngine = {
@ -9,7 +10,14 @@ const DragEngine = {
if (!r) { if (!r) {
return null; return null;
} }
if (isNode(r)) { if (isPrototype(r)) {
return {
type: DragObjectType.NodeData,
data: {
componentName: r.getComponentName(),
},
};
} else if (isNode(r)) {
return { return {
type: DragObjectType.Node, type: DragObjectType.Node,
nodes: [r], nodes: [r],

View File

@ -1,16 +1,16 @@
import { isJSBlock, isJSExpression, isJSSlot } from '@ali/lowcode-types'; import { isJSBlock, isJSExpression, isJSSlot, isI18nData } from '@ali/lowcode-types';
import { isPlainObject } from '@ali/lowcode-utils'; import { isPlainObject, hasOwnProperty } from '@ali/lowcode-utils';
import { globalContext, Editor } from '@ali/lowcode-editor-core'; import { globalContext, Editor } from '@ali/lowcode-editor-core';
import { Designer, LiveEditing, TransformStage, addBuiltinComponentAction } from '@ali/lowcode-designer'; import { Designer, LiveEditing, TransformStage, Node } from '@ali/lowcode-designer';
import Outline, { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane'; import Outline, { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane';
import { toCss } from '@ali/vu-css-style'; import { toCss } from '@ali/vu-css-style';
import logger from '@ali/vu-logger';
import DesignerPlugin from '@ali/lowcode-plugin-designer'; import DesignerPlugin from '@ali/lowcode-plugin-designer';
import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton'; import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton';
import { i18nReducer } from './i18n-reducer'; import { deepValueParser } from './deep-value-parser';
import { InstanceNodeSelector } from './components'; import { liveEditingRule, liveEditingSaveHander } from './vc-live-editing';
import { liveEditingRule } from './vc-live-editing';
export const editor = new Editor(); export const editor = new Editor();
globalContext.register(editor, Editor); globalContext.register(editor, Editor);
@ -31,18 +31,48 @@ designer.addPropsReducer((props, node) => {
const newProps: any = {}; const newProps: any = {};
initials.forEach((item) => { initials.forEach((item) => {
// FIXME! this implements SettingTarget // FIXME! this implements SettingTarget
try {
// FIXME! item.name could be 'xxx.xxx'
const v = item.initial(node as any, props[item.name]); const v = item.initial(node as any, props[item.name]);
if (v !== undefined) { if (v !== undefined) {
newProps[item.name] = v; newProps[item.name] = v;
} }
} catch (e) {
if (hasOwnProperty(props, item.name)) {
newProps[item.name] = props[item.name];
}
}
}); });
return newProps; return newProps;
} }
return props; return props;
}, TransformStage.Init); }, TransformStage.Init);
// 国际化渲染时处理
designer.addPropsReducer(i18nReducer, TransformStage.Render); function filterReducer(props: any, node: Node): any {
const filters = node.componentMeta.getMetadata().experimental?.filters;
if (filters && filters.length) {
const newProps = { ...props };
filters.forEach((item) => {
// FIXME! item.name could be 'xxx.xxx'
if (!hasOwnProperty(newProps, item.name)) {
return;
}
try {
if (item.filter(node.getProp(item.name) as any, props[item.name]) === false) {
delete newProps[item.name];
}
} catch (e) {
console.warn(e);
logger.trace(e);
}
});
return newProps;
}
return props;
}
designer.addPropsReducer(filterReducer, TransformStage.Save);
designer.addPropsReducer(filterReducer, TransformStage.Render);
function upgradePropsReducer(props: any) { function upgradePropsReducer(props: any) {
if (!isPlainObject(props)) { if (!isPlainObject(props)) {
@ -72,6 +102,32 @@ function upgradePropsReducer(props: any) {
// 升级 Props // 升级 Props
designer.addPropsReducer(upgradePropsReducer, TransformStage.Init); designer.addPropsReducer(upgradePropsReducer, TransformStage.Init);
function compatiableReducer(props: any) {
if (!isPlainObject(props)) {
return props;
}
const newProps: any = {};
Object.entries<any>(props).forEach(([key, val]) => {
if (isJSSlot(val)) {
val.value
val = {
type: 'JSBlock',
value: {
componentName: 'Slot',
children: val.value,
props: {
slotTitle: val.title,
},
},
}
}
newProps[key] = val;
});
return newProps;
}
// Dirty fix: will remove this reducer
designer.addPropsReducer(compatiableReducer, TransformStage.Save);
// 设计器组件样式处理 // 设计器组件样式处理
function stylePropsReducer(props: any, node: any) { function stylePropsReducer(props: any, node: any) {
if (props && typeof props === 'object' && props.__style__) { if (props && typeof props === 'object' && props.__style__) {
@ -119,30 +175,8 @@ function appendStyleNode(props: any, styleProp: any, cssClass: string, cssId: st
} }
designer.addPropsReducer(stylePropsReducer, TransformStage.Render); designer.addPropsReducer(stylePropsReducer, TransformStage.Render);
// FIXME: 表达式使用 mock 值未来live 模式直接使用原始值 // 国际化 & Expression 渲染时处理
function expressionReducer(obj?: any): any { designer.addPropsReducer(deepValueParser, TransformStage.Render);
if (!obj) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => expressionReducer(item));
}
if (isPlainObject(obj)) {
if (isJSExpression(obj)) {
return obj.mock;
}
if (isJSSlot(obj)) {
return obj;
}
const out: any = {};
Object.keys(obj).forEach((key) => {
out[key] = expressionReducer(obj[key]);
});
return out;
}
return obj;
}
designer.addPropsReducer(expressionReducer, TransformStage.Render);
skeleton.add({ skeleton.add({
area: 'mainArea', area: 'mainArea',
@ -178,11 +212,4 @@ skeleton.add({
}); });
LiveEditing.addLiveEditingSpecificRule(liveEditingRule); LiveEditing.addLiveEditingSpecificRule(liveEditingRule);
LiveEditing.addLiveEditingSaveHandler(liveEditingSaveHander);
// 实例节点选择器,线框高亮
// addBuiltinComponentAction({
// name: 'instance-node-selector',
// content: InstanceNodeSelector,
// important: true,
// condition: 'always'
// });

View File

@ -1,38 +0,0 @@
import Env from './env';
const I18nUtil = require('@ali/ve-i18n-util');
interface I18nObject {
type?: string;
use?: string;
key?: string;
[lang: string]: string | undefined;
}
export function i18nReducer(obj?: any): any {
if (!obj) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => i18nReducer(item));
}
if (typeof obj === 'object') {
if (obj.type === 'i18n') {
// FIXME! use editor.get
let locale = Env.getLocale();
if (obj.key) {
// FIXME: 此处需要升级I18nUtil改成响应式
return I18nUtil.get(obj.key, locale);
}
if (locale !== 'zh_CN' && locale !== 'zh_TW' && !obj[locale]) {
locale = 'en_US';
}
return obj[obj.use || locale] || obj.zh_CN;
}
const out: I18nObject = {};
Object.keys(obj).forEach((key) => {
out[key] = i18nReducer(obj[key]);
});
return out;
}
return obj;
}

View File

@ -0,0 +1,79 @@
declare enum LANGUAGES {
zh_CN = 'zh_CN',
en_US = 'en_US'
}
export interface I18nRecord {
type?: 'i18n';
[key: string]: string;
/**
* i18n unique key
*/
key?: string;
}
export interface I18nRecordData {
gmtCreate: Date;
gmtModified: Date;
i18nKey: string;
i18nText: I18nRecord;
id: number;
}
export interface II18nUtilConfigs {
items?: {};
/**
*
*/
disableInstantLoad?: boolean;
/**
*
*/
disableFullLoad?: boolean;
loader?: (configs: ILoaderConfigs) => Promise<I18nRecordData[]>;
remover?: (key: string, dic: I18nRecord) => Promise<void>;
saver?: (key: string, dic: I18nRecord) => Promise<void>;
}
export interface ILoaderConfigs {
/**
* search keywords
*/
keyword?: string;
/**
* should load all i18n items
*/
isFull?: boolean;
/**
* search i18n item based on uniqueKey
*/
key?: string;
}
export interface II18nUtil {
init(config: II18nUtilConfigs): void;
isInitialized(): boolean;
isReady(): boolean;
attach(prop: object, value: I18nRecord, updator: () => any);
search(keyword: string, silent?: boolean);
load(configs: ILoaderConfigs): Promise<I18nRecord[]>;
/**
* Get local i18n Record
* @param key
* @param lang
*/
get(key: string, lang: string): string | I18nRecord;
getFromRemote(key: string): Promise<I18nRecord>;
getItem(key: string, forceData?: boolean): any;
getItems(): I18nRecord[];
update(key: string, doc: I18nRecord, lang: LANGUAGES);
create(doc: I18nRecord, lang: LANGUAGES): string;
remove(key: string): Promise<void>;
onReady(func: () => any);
onRowsChange(func: () => any);
onChange(func: (dic: I18nRecord) => any);
}
declare const i18nUtil: II18nUtil;
export default i18nUtil;

View File

@ -0,0 +1,310 @@
import { EventEmitter } from 'events';
import { obx } from '@ali/lowcode-editor-core';
let keybase = Date.now();
function keygen(maps) {
let key;
do {
key = `i18n-${(keybase).toString(36)}`;
keybase += 1;
} while (key in maps);
return key;
}
class DocItem {
constructor(parent, doc, unInitial) {
this.parent = parent;
const { use, ...strings } = doc;
this.doc = obx.val({
type: 'i18n',
...strings,
});
this.emitter = new EventEmitter;
this.inited = unInitial !== true;
}
getKey() {
return this.doc.key;
}
getDoc(lang) {
if (lang) {
return this.doc[lang];
}
return this.doc;
}
setDoc(doc, lang, initial) {
if (lang) {
this.doc[lang] = doc;
} else {
const { use, strings } = doc || {};
Object.assign(this.doc, strings);
}
this.emitter.emit('change', this.doc);
if (initial) {
this.inited = true;
} else if (this.inited) {
this.parent._saveChange(this.doc.key, this.doc);
}
}
remove() {
if (!this.inited) return Promise.reject('not initialized');
const { key, ...doc } = this.doc; // eslint-disable-line
this.emitter.emit('change', doc);
return this.parent.remove(this.getKey());
}
onChange(func) {
this.emitter.on('change', func);
return () => {
this.emitter.removeListener('change', func);
};
}
}
class I18nUtil {
constructor() {
this.emitter = new EventEmitter;
// original data source from remote
this.i18nData = {};
// current i18n records on the left pane
this.items = [];
this.maps = {};
// full list of i18n records for synchronized call
this.fullList = [];
this.fullMap = {};
this.config = {};
this.ready = false;
this.isInited = false;
}
_prepareItems(items, isFull = false, isSilent = false) {
this[isFull ? 'fullList' : 'items'] = items.map((dict) => {
let item = this[isFull ? 'fullMap' : 'maps'][dict.key];
if (item) {
item.setDoc(dict, null, true);
} else {
item = new DocItem(this, dict);
this[isFull ? 'fullMap' : 'maps'][dict.key] = item;
}
return item;
});
if (this.ready && !isSilent) {
this.emitter.emit('rowschange');
this.emitter.emit('change');
} else {
this.ready = true;
this.emitter.emit('ready');
}
}
_load(configs = {}, silent) {
if (!this.config.loader) {
console.error(new Error('Please load loader while init I18nUtil.'));
return Promise.reject();
}
return this.config.loader(configs).then((data) => {
if (configs.i18nKey) {
return Promise.resolve(data.i18nText);
}
this._prepareItems(data.data, configs.isFull, silent);
// set pagination data to i18nData
this.i18nData = data;
if (!silent) {
this.emitter.emit('rowschange');
this.emitter.emit('change');
}
return Promise.resolve(this.items.map(i => i.getDoc()));
});
}
_saveToItems(key, dict) {
let item = null;
item = this.items.find(doc => doc.getKey() === key);
if (!item) {
item = this.fullList.find(doc => doc.getKey() === key);
}
if (item) {
item.setDoc(dict);
} else {
item = new DocItem(this, {
key,
...dict,
});
this.items.unshift(item);
this.fullList.unshift(item);
this.maps[key] = item;
this.fullMap[key] = item;
this._saveChange(key, dict, true);
}
}
_saveChange(key, dict, rowschange) {
if (rowschange) {
this.emitter.emit('rowschange');
}
this.emitter.emit('change');
if (dict === null) {
delete this.maps[key];
delete this.fullMap[key];
}
return this._save(key, dict);
}
_save(key, dict) {
const saver = dict === null ? this.config.remover : this.config.saver;
if (!saver) return Promise.reject('Saver function is not set');
return saver(key, dict);
}
init(config) {
if (this.isInited) return;
this.config = config || {};
if (this.config.items) {
// inject to current page
this._prepareItems(this.config.items);
}
if (!this.config.disableInstantLoad) {
this._load({ isFull: !this.config.disableFullLoad });
}
this.isInited = true;
}
isInitialized() {
return this.isInited;
}
isReady() {
return this.ready;
}
// add events updater when i18n record change
// we should notify engine's view to change
attach(prop, value, updator) {
const isI18nValue = value && value.type === 'i18n' && value.key;
const key = isI18nValue ? value.key : null;
if (prop.i18nLink) {
if (isI18nValue && (key === prop.i18nLink.key)) {
return prop.i18nLink;
}
prop.i18nLink.detach();
}
if (isI18nValue) {
return {
key,
detach: this.getItem(key, value).onChange(updator),
};
}
return null;
}
/**
* 搜索 i18n 词条
*
* @param {any} keyword 搜索关键字
* @param {boolean} [silent=false] 是否刷新左侧的 i18n 数据
* @returns
*
* @memberof I18nUtil
*/
search(keyword, silent = false) {
return this._load({ keyword }, silent);
}
load(configs = {}) {
return this._load(configs);
}
get(key, lang) {
const item = this.getItem(key);
if (item) {
return item.getDoc(lang);
}
return null;
}
getFromRemote(key) {
return this._load({ i18nKey: key });
}
getItem(key, forceData) {
if (forceData && !this.maps[key] && !this.fullList[key]) {
const item = new DocItem(this, {
key,
...forceData,
}, true);
this.maps[key] = item;
this.fullMap[key] = item;
this.fullList.push(item);
this.items.push(item);
}
return this.maps[key] || this.fullMap[key];
}
getItems() {
return this.items;
}
update(key, doc, lang) {
let dict = this.get(key) || {};
if (!lang) {
dict = doc;
} else {
dict[lang] = doc;
}
this._saveToItems(key, dict);
}
create(doc, lang) {
const dict = lang ? { [lang]: doc } : doc;
const key = keygen(this.fullMap);
this._saveToItems(key, dict);
return key;
}
remove(key) {
const index = this.items.findIndex(item => item.getKey() === key);
const indexG = this.fullList.findIndex(item => item.getKey() === key);
if (index > -1) {
this.items.splice(index, 1);
}
if (indexG > -1) {
this.fullList.splice(index, 1);
}
return this._saveChange(key, null, true);
}
onReady(func) {
this.emitter.on('ready', func);
return () => {
this.emitter.removeListener('ready', func);
};
}
onRowsChange(func) {
this.emitter.on('rowschange', func);
return () => {
this.emitter.removeListener('rowschange', func);
};
}
onChange(func) {
this.emitter.on('change', func);
return () => {
this.emitter.removeListener('change', func);
};
}
}
export default new I18nUtil();

View File

@ -3,7 +3,7 @@ import Popup from '@ali/ve-popups';
import Icons from '@ali/ve-icons'; import Icons from '@ali/ve-icons';
import logger from '@ali/vu-logger'; import logger from '@ali/vu-logger';
import { render } from 'react-dom'; import { render } from 'react-dom';
import I18nUtil from '@ali/ve-i18n-util'; import I18nUtil from './i18n-util';
import { hotkey as Hotkey } from '@ali/lowcode-editor-core'; import { hotkey as Hotkey } from '@ali/lowcode-editor-core';
import { createElement } from 'react'; import { createElement } from 'react';
import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS, VERSION as Version } from './base/const'; import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS, VERSION as Version } from './base/const';
@ -161,11 +161,10 @@ export {
Symbols, Symbols,
}; };
const version = '6.0.0(LowcodeEngine 0.9.0-beta)';
/*
console.log( console.log(
`%cLowcodeEngine %cv${VERSION}`, `%c VisionEngine %c v${version} `,
"color:#000;font-weight:bold;", "padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060;font-weight:bold;",
"color:green;font-weight:bold;" "padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e;font-weight:bold;"
); );
*/

View File

@ -4,33 +4,60 @@ import { DocumentModel } from '@ali/lowcode-designer';
const { project } = designer; const { project } = designer;
export interface OldPageData { export interface PageDataV1 {
id: string;
componentsTree: RootSchema[];
layout: RootSchema;
[dataAddon: string]: any;
}
export interface PageDataV2 {
id: string; id: string;
componentsTree: RootSchema[]; componentsTree: RootSchema[];
[dataAddon: string]: any; [dataAddon: string]: any;
} }
function isPageDataV1(obj: any): obj is PageDataV1 {
return obj && obj.layout;
}
function isPageDataV2(obj: any): obj is PageDataV2 {
return obj && obj.componentsTree && Array.isArray(obj.componentsTree);
}
type OldPageData = PageDataV1 | PageDataV2;
const pages = Object.assign(project, { const pages = Object.assign(project, {
setPages(pages: OldPageData[]) { setPages(pages: OldPageData[]) {
if (!pages || !Array.isArray(pages) || pages.length === 0) { if (!pages || !Array.isArray(pages) || pages.length === 0) {
throw new Error('pages schema 不合法'); throw new Error('pages schema 不合法');
} }
if (pages[0].componentsTree[0]) { let componentsTree: any;
pages[0].componentsTree[0].componentName = 'Page'; if (isPageDataV1(pages[0])) {
componentsTree = [pages[0].layout];
} else {
componentsTree = pages[0].componentsTree;
if (componentsTree[0]) {
componentsTree[0].componentName = 'Page';
// FIXME // FIXME
pages[0].componentsTree[0].lifeCycles = {}; componentsTree[0].lifeCycles = {};
pages[0].componentsTree[0].methods = {}; componentsTree[0].methods = {};
}
} }
project.load({ project.load({
version: '1.0.0', version: '1.0.0',
componentsMap: [], componentsMap: [],
componentsTree: pages[0].componentsTree, componentsTree,
}, true); }, true);
}, },
addPage(data: OldPageData) { addPage(data: OldPageData | RootSchema) {
return project.open(data.layout); if (isPageDataV1(data)) {
data = data.layout;
} else if (isPageDataV2(data)) {
data = data.componentsTree[0];
}
return project.open(data);
}, },
getPage(fnOrIndex: ((page: DocumentModel) => boolean) | number) { getPage(fnOrIndex: ((page: DocumentModel) => boolean) | number) {
if (typeof fnOrIndex === 'number') { if (typeof fnOrIndex === 'number') {

View File

@ -2,6 +2,7 @@ import { skeleton, editor } from './editor';
import { ReactElement } from 'react'; import { ReactElement } from 'react';
import { IWidgetBaseConfig, Skeleton } from '@ali/lowcode-editor-skeleton'; import { IWidgetBaseConfig, Skeleton } from '@ali/lowcode-editor-skeleton';
import { uniqueId } from '@ali/lowcode-utils'; import { uniqueId } from '@ali/lowcode-utils';
import bus from './bus';
export interface IContentItemConfig { export interface IContentItemConfig {
title: string; title: string;
@ -92,6 +93,7 @@ function upgradeConfig(config: OldPaneConfig): IWidgetBaseConfig & { area: strin
type: 'Panel', type: 'Panel',
name: typeof title === 'string' ? title : `${name}:${index}`, name: typeof title === 'string' ? title : `${name}:${index}`,
content, content,
contentProps: props,
props: { props: {
title, title,
help: tip, help: tip,
@ -132,7 +134,18 @@ function add(config: (() => OldPaneConfig) | OldPaneConfig, extraConfig?: any) {
config = { ...config, ...extraConfig }; config = { ...config, ...extraConfig };
} }
skeleton.add(upgradeConfig(config)); const upgraded = upgradeConfig(config);
if (upgraded.area === 'stages') {
if (upgraded.id) {
upgraded.name = upgraded.id;
} else if (!upgraded.name) {
upgraded.name = uniqueId('stage');
}
const stage = skeleton.add(upgraded);
return stage?.getName();
} else {
return skeleton.add(upgraded);
}
} }
const actionPane = Object.assign(skeleton.topArea, { const actionPane = Object.assign(skeleton.topArea, {
@ -164,6 +177,7 @@ const dockPane = Object.assign(skeleton.leftArea, {
console.warn(`Could not find pane with name ${name}`); console.warn(`Could not find pane with name ${name}`);
} }
pane?.active(); pane?.active();
bus.emit('ve.dock_pane.active_doc', pane);
}, },
/** /**

View File

@ -1,4 +1,4 @@
class Project { export class Project {
private schema: any; private schema: any;
constructor() { constructor() {

View File

@ -1,7 +1,7 @@
import { EditingTarget, Node as DocNode } from '@ali/lowcode-designer'; import { EditingTarget, Node as DocNode, SaveHandler } from '@ali/lowcode-designer';
import Env from './env'; import Env from './env';
import { isJSExpression } from '@ali/lowcode-types'; import { isJSExpression, isI18nData } from '@ali/lowcode-types';
const I18nUtil = require('@ali/ve-i18n-util'); import i18nUtil from './i18n-util';
interface I18nObject { interface I18nObject {
type?: string; type?: string;
@ -13,7 +13,7 @@ interface I18nObject {
function getI18nText(obj: I18nObject) { function getI18nText(obj: I18nObject) {
let locale = Env.getLocale(); let locale = Env.getLocale();
if (obj.key) { if (obj.key) {
return I18nUtil.get(obj.key, locale); return i18nUtil.get(obj.key, locale);
} }
if (locale !== 'zh_CN' && locale !== 'zh_TW' && !obj[locale]) { if (locale !== 'zh_CN' && locale !== 'zh_TW' && !obj[locale]) {
locale = 'en_US'; locale = 'en_US';
@ -26,7 +26,10 @@ function getText(node: DocNode, prop: string) {
if (!p || p.isUnset()) { if (!p || p.isUnset()) {
return null; return null;
} }
const v = p.getValue(); let v = p.getValue();
if (isJSExpression(v)) {
v = v.mock;
}
if (v == null) { if (v == null) {
return null; return null;
} }
@ -36,9 +39,7 @@ function getText(node: DocNode, prop: string) {
if ((v as any).type === 'i18n') { if ((v as any).type === 'i18n') {
return getI18nText(v as any); return getI18nText(v as any);
} }
if (isJSExpression(v)) { return Symbol.for('not-literal');
return v.mock;
}
} }
export function liveEditingRule(target: EditingTarget) { export function liveEditingRule(target: EditingTarget) {
@ -53,8 +54,7 @@ export function liveEditingRule(target: EditingTarget) {
const innerText = targetElement.innerText; const innerText = targetElement.innerText;
const propTarget = ['title', 'label', 'text', 'content'].find(prop => { const propTarget = ['title', 'label', 'text', 'content'].find(prop => {
// TODO: enhance compare text logic return equalText(getText(node, prop), innerText);
return getText(node, prop) === innerText;
}); });
if (propTarget) { if (propTarget) {
@ -66,7 +66,51 @@ export function liveEditingRule(target: EditingTarget) {
return null; return null;
} }
// TODO: function equalText(v: any, innerText: string) {
export function liveEditingSaveHander() { // TODO: enhance compare text logic
if (typeof v !== 'string') {
return false;
}
return v.trim() === innerText
} }
export const liveEditingSaveHander: SaveHandler = {
condition: (prop) => {
const v = prop.getValue();
return prop.type === 'expression' || isI18nData(v);
},
onSaveContent: (content, prop) => {
const v = prop.getValue();
const locale = Env.getLocale();
let data = v;
if (isJSExpression(v)) {
data = v.mock;
}
if (isI18nData(data)) {
const i18n = data.key ? i18nUtil.getItem(data.key) : null;
if (i18n) {
i18n.setDoc(content, locale);
return;
}
data = {
...(data as any),
[locale]: content,
};
} else {
data = content;
}
if (isJSExpression(v)) {
prop.setValue({
type: 'JSExpression',
value: v.value,
mock: data,
});
} else {
prop.setValue(data);
}
}
}
// TODO:
// 非文本编辑
// 国际化数据,改变当前
// JSExpression, 改变 mock 或 弹出绑定变量

View File

@ -43,7 +43,7 @@ html {
} }
html.engine-blur #engine { html.engine-blur #engine {
-webkit-filter: blur(4px); filter: blur(4px);
} }
.engine-main { .engine-main {
@ -98,6 +98,11 @@ html.engine-blur #engine {
} }
} }
.vs-icon .vs-icon-del, .vs-icon .vs-icon-entry {
width: 16px!important;
height: 16px!important;
}
.lc-left-float-pane { .lc-left-float-pane {
font-size: 14px; font-size: 14px;
} }
@ -107,3 +112,13 @@ html.engine-preview-mode {
display: none !important; display: none !important;
} }
} }
.ve-popups .ve-message {
right: 290px;
.ve-message-content {
display: flex;
align-items: center;
line-height: 22px;
}
}

View File

@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.9.3"></a>
## [0.9.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-setters@0.9.2...@ali/lowcode-editor-setters@0.9.3) (2020-06-15)
**Note:** Version bump only for package @ali/lowcode-editor-setters
<a name="0.9.2"></a>
## [0.9.2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-setters@0.9.1...@ali/lowcode-editor-setters@0.9.2) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-editor-setters
<a name="0.9.1"></a>
## 0.9.1 (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-setters
<a name="0.8.15"></a>
## [0.8.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-setters@0.8.14...@ali/lowcode-setters@0.8.15) (2020-05-15)
**Note:** Version bump only for package @ali/lowcode-setters
<a name="0.8.14"></a> <a name="0.8.14"></a>
## [0.8.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-setters@0.8.13...@ali/lowcode-setters@0.8.14) (2020-05-13) ## [0.8.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-setters@0.8.13...@ali/lowcode-setters@0.8.14) (2020-05-13)

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-editor-setters", "name": "@ali/lowcode-editor-setters",
"version": "0.9.0", "version": "0.9.3",
"description": "Builtin setters for Ali lowCode engine", "description": "Builtin setters for Ali lowCode engine",
"files": [ "files": [
"es", "es",
@ -22,7 +22,7 @@
"@ali/iceluna-comp-react-node": "^1.0.5", "@ali/iceluna-comp-react-node": "^1.0.5",
"@ali/iceluna-sdk": "^1.0.5-beta.24", "@ali/iceluna-sdk": "^1.0.5-beta.24",
"@ali/lc-style-setter": "^0.0.1", "@ali/lc-style-setter": "^0.0.1",
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-editor-core": "^0.8.16",
"@alifd/next": "^1.19.16", "@alifd/next": "^1.19.16",
"acorn": "^6.4.1", "acorn": "^6.4.1",
"classnames": "^2.2.6", "classnames": "^2.2.6",

View File

@ -3,6 +3,93 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.26"></a>
## [0.8.26](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.25...@ali/lowcode-editor-skeleton@0.8.26) (2020-06-16)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.25"></a>
## [0.8.25](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.24...@ali/lowcode-editor-skeleton@0.8.25) (2020-06-15)
### Bug Fixes
* 修复bool类型对应的setter ([2df6230](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2df6230))
* 禁止组件拉到 Page 的直接子节点, 以及替换 tab 组件 ([d93a291](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/d93a291))
* 调整保存成功弹出框位置 ([5198dae](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/5198dae))
### Features
* add URL link for setter titles ([4678408](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/4678408))
* panel增加自动埋点 ([afc7758](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/afc7758))
* 自动埋点 ([fecf34d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fecf34d))
<a name="0.8.24"></a>
## [0.8.24](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.23...@ali/lowcode-editor-skeleton@0.8.24) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.23"></a>
## [0.8.23](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.22...@ali/lowcode-editor-skeleton@0.8.23) (2020-05-19)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.22"></a>
## [0.8.22](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.21...@ali/lowcode-editor-skeleton@0.8.22) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.21"></a>
## [0.8.21](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.20...@ali/lowcode-editor-skeleton@0.8.21) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.20"></a>
## [0.8.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.19...@ali/lowcode-editor-skeleton@0.8.20) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.19"></a>
## [0.8.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.18...@ali/lowcode-editor-skeleton@0.8.19) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
<a name="0.8.18"></a>
## [0.8.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.17...@ali/lowcode-editor-skeleton@0.8.18) (2020-05-15)
### Bug Fixes
* 解决点击数据源,自动隐藏的问题 ([7dcd61c](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/7dcd61c))
<a name="0.8.17"></a> <a name="0.8.17"></a>
## [0.8.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.16...@ali/lowcode-editor-skeleton@0.8.17) (2020-05-15) ## [0.8.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.16...@ali/lowcode-editor-skeleton@0.8.17) (2020-05-15)

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-editor-skeleton", "name": "@ali/lowcode-editor-skeleton",
"version": "0.8.17", "version": "0.8.26",
"description": "alibaba lowcode editor skeleton", "description": "alibaba lowcode editor skeleton",
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
@ -19,11 +19,11 @@
"editor" "editor"
], ],
"dependencies": { "dependencies": {
"@ali/lowcode-designer": "^0.9.11", "@ali/lowcode-designer": "^0.9.20",
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-editor-core": "^0.8.16",
"@ali/lowcode-types": "^0.8.3", "@ali/lowcode-types": "^0.8.6",
"@ali/lowcode-utils": "^0.8.4", "@ali/lowcode-utils": "^0.8.7",
"@alifd/next": "^1.x", "@alifd/next": "^1.20.12",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"react": "^16.8.1", "react": "^16.8.1",
"react-dom": "^16.8.1" "react-dom": "^16.8.1"

View File

@ -12,6 +12,7 @@ import InlineTip from './inlinetip';
export interface FieldProps { export interface FieldProps {
className?: string; className?: string;
meta?: { package: string; componentName: string } | string;
title?: TitleContent | null; title?: TitleContent | null;
defaultDisplay?: 'accordion' | 'inline' | 'block'; defaultDisplay?: 'accordion' | 'inline' | 'block';
collapsed?: boolean; collapsed?: boolean;
@ -28,6 +29,11 @@ export class Field extends Component<FieldProps> {
display: this.props.defaultDisplay || 'inline', display: this.props.defaultDisplay || 'inline',
}; };
constructor(props: any) {
super(props);
this.handleClear = this.handleClear.bind(this);
}
private toggleExpand = () => { private toggleExpand = () => {
const { onExpandChange } = this.props; const { onExpandChange } = this.props;
const collapsed = !this.state.collapsed; const collapsed = !this.state.collapsed;
@ -68,6 +74,10 @@ export class Field extends Component<FieldProps> {
}); });
this.dispose = () => observer.disconnect(); this.dispose = () => observer.disconnect();
} }
private handleClear(e: React.MouseEvent) {
e.stopPropagation();
this.props.onClear && this.props.onClear();
}
componentDidMount() { componentDidMount() {
const { defaultDisplay } = this.props; const { defaultDisplay } = this.props;
if (!defaultDisplay || defaultDisplay === 'inline') { if (!defaultDisplay || defaultDisplay === 'inline') {
@ -106,19 +116,27 @@ export class Field extends Component<FieldProps> {
} }
render() { render() {
const { className, children, title, valueState, onClear, name: propName, tip } = this.props; const { className, children, meta, title, valueState, onClear, name: propName, tip } = this.props;
const { display, collapsed } = this.state; const { display, collapsed } = this.state;
const isAccordion = display === 'accordion'; const isAccordion = display === 'accordion';
let hostName = '';
if (typeof meta === 'object') {
hostName = `${meta?.package || ''}-${meta.componentName || ''}`;
} else if (typeof meta === 'string') {
hostName = meta;
}
const id = `${hostName}-${propName || (title as any)['en-US'] || (title as any)['zh-CN']}`;
const tipContent = this.getTipContent(propName!, tip); const tipContent = this.getTipContent(propName!, tip);
return ( return (
<div <div
className={classNames(`lc-field lc-${display}-field`, className, { className={classNames(`lc-field lc-${display}-field`, className, {
'lc-field-is-collapsed': isAccordion && collapsed, 'lc-field-is-collapsed': isAccordion && collapsed,
})} })}
id={id}
> >
<div className="lc-field-head" onClick={isAccordion ? this.toggleExpand : undefined}> <div className="lc-field-head" onClick={isAccordion ? this.toggleExpand : undefined}>
<div className="lc-field-title"> <div className="lc-field-title">
{createValueState(valueState, onClear)} {createValueState(valueState, this.handleClear)}
<Title title={title || ''} /> <Title title={title || ''} />
<InlineTip position="top">{tipContent}</InlineTip> <InlineTip position="top">{tipContent}</InlineTip>
</div> </div>
@ -143,7 +161,7 @@ export class Field extends Component<FieldProps> {
* *
* TODO: turn number to enum * TODO: turn number to enum
*/ */
function createValueState(valueState?: number, onClear?: () => void) { function createValueState(valueState?: number, onClear?: (e: React.MouseEvent) => void) {
let tip: any = null; let tip: any = null;
let className = 'lc-valuestate'; let className = 'lc-valuestate';
let icon: any = null; let icon: any = null;

View File

@ -67,16 +67,16 @@
} }
} }
&.lc-plain-field { // &.lc-plain-field {
// for top-level style // // for top-level style
// padding: 8px 10px; // // padding: 8px 10px;
> .lc-field-body { // > .lc-field-body {
flex: 1; // flex: 1;
min-width: 0; // min-width: 0;
display: flex; // display: flex;
align-items: center; // align-items: center;
} // }
} // }
&.lc-inline-field { &.lc-inline-field {
display: flex; display: flex;
@ -211,14 +211,14 @@
} }
// 3rd level field title width should short // 3rd level field title width should short
.lc-field-body .lc-inline-field { // .lc-field-body .lc-inline-field {
> .lc-field-head { // > .lc-field-head {
width: 50px; // width: 50px;
.lc-title-label { // .lc-title-label {
width: 50px; // width: 50px;
} // }
} // }
} // }
>.lc-block-setter { >.lc-block-setter {
flex: 1; flex: 1;
} }

View File

@ -59,8 +59,8 @@ export class PopupPipe {
} }
} }
export default class PopupService extends Component<{ actionKey?: string; safeId?: string }> { export default class PopupService extends Component<{ popupPipe?: PopupPipe; actionKey?: string; safeId?: string }> {
private popupPipe = new PopupPipe(); private popupPipe = this.props.popupPipe || new PopupPipe();
componentWillUnmount() { componentWillUnmount() {
this.popupPipe.purge(); this.popupPipe.purge();
@ -121,6 +121,7 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
className="lc-ballon" className="lc-ballon"
align="l" align="l"
id={this.props.safeId} id={this.props.safeId}
alignEdge
safeNode={id} safeNode={id}
visible={visible} visible={visible}
style={{ width }} style={{ width }}
@ -135,7 +136,7 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
trigger={<div className="lc-popup-placeholder" style={pos} />} trigger={<div className="lc-popup-placeholder" style={pos} />}
triggerType="click" triggerType="click"
animation={false} animation={false}
// needAdjust needAdjust
shouldUpdatePosition shouldUpdatePosition
> >
<div className="lc-ballon-title">{title}</div> <div className="lc-ballon-title">{title}</div>

View File

@ -13,10 +13,16 @@
} }
.lc-ballon-content { .lc-ballon-content {
margin-top: 10px; margin-top: 10px;
// width: 300px; // FIXME: popup position is bad
max-height: calc(60vh);
overflow-x: hidden;
overflow-y: auto;
}
&.next-balloon-closable {
padding: 10px !important;
} }
.next-balloon-close { .next-balloon-close {
top: 4px; top: 4px !important;
right: 4px; right: 4px !important;
} }
} }

View File

@ -1,11 +1,13 @@
import { Component } from 'react'; import { Component, MouseEvent } from 'react';
import { shallowIntl, createSetterContent, observer } from '@ali/lowcode-editor-core'; import { shallowIntl, createSetterContent, observer } from '@ali/lowcode-editor-core';
import { createContent } from '@ali/lowcode-utils'; import { createContent } from '@ali/lowcode-utils';
import { Field, createField } from '../field'; import { Field, createField } from '../field';
import PopupService from '../popup'; import PopupService, { PopupPipe } from '../popup';
import { SkeletonContext } from '../../context';
import { SettingField, isSettingField, SettingTopEntry, SettingEntry } from '@ali/lowcode-designer'; import { SettingField, isSettingField, SettingTopEntry, SettingEntry } from '@ali/lowcode-designer';
import { isSetterConfig, CustomView } from '@ali/lowcode-types'; import { isSetterConfig, CustomView } from '@ali/lowcode-types';
import { intl } from '../../locale'; import { intl } from '../../locale';
import { Skeleton } from 'editor-skeleton/src/skeleton';
@observer @observer
class SettingFieldView extends Component<{ field: SettingField }> { class SettingFieldView extends Component<{ field: SettingField }> {
@ -61,6 +63,7 @@ class SettingFieldView extends Component<{ field: SettingField }> {
return createField( return createField(
{ {
meta: field?.componentMeta?.npm || field?.componentMeta?.componentName || '',
title: field.title, title: field.title,
collapsed: !field.expanded, collapsed: !field.expanded,
valueState: field.isRequired ? 10 : field.valueState, valueState: field.isRequired ? 10 : field.valueState,
@ -119,6 +122,7 @@ class SettingGroupView extends Component<{ field: SettingField }> {
return ( return (
<Field <Field
defaultDisplay="accordion" defaultDisplay="accordion"
meta={field?.componentMeta?.npm || field?.componentMeta?.componentName || ''}
title={field.title} title={field.title}
collapsed={!field.expanded} collapsed={!field.expanded}
onExpandChange={(expandState) => { onExpandChange={(expandState) => {
@ -145,17 +149,54 @@ export function createSettingFieldView(item: SettingField | CustomView, field: S
@observer @observer
export class SettingsPane extends Component<{ target: SettingTopEntry | SettingField }> { export class SettingsPane extends Component<{ target: SettingTopEntry | SettingField }> {
static contextType = SkeletonContext;
shouldComponentUpdate() { shouldComponentUpdate() {
return false; return false;
} }
private popupPipe = new PopupPipe();
private pipe = this.popupPipe.create();
private handleClick = (e: MouseEvent) => {
// compatiable vision stageBox
// TODO: optimize these codes
const pane = e.currentTarget as HTMLDivElement;
let entry: any;
function getTarget(node: any): any {
if (!pane.contains(node) || (node.nodeName === 'A' && node.getAttribute('href'))) {
return null;
}
const target = node.dataset ? node.dataset.stageTarget : null;
if (target) {
entry = node;
return target;
}
return getTarget(node.parentNode);
}
const target = getTarget(e.target);
if (!target) {
return;
}
const skeleton = this.context as Skeleton;
if (!skeleton || !skeleton.stages) {
return;
}
const stage = skeleton.stages.container.get(target);
if (stage) {
this.pipe.send(stage.content, stage.title);
this.pipe.show(entry);
}
};
render() { render() {
const { target } = this.props; const { target } = this.props;
const items = target.items; const items = target.items;
return ( return (
<div className="lc-settings-pane"> <div className="lc-settings-pane" onClick={this.handleClick}>
{/* todo: add head for single use */} {/* todo: add head for single use */}
<PopupService> <PopupService popupPipe={this.popupPipe}>
<div className="lc-settings-content"> <div className="lc-settings-content">
{items.map((item, index) => createSettingFieldView(item, target, index))} {items.map((item, index) => createSettingFieldView(item, target, index))}
</div> </div>

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Tab, Breadcrumb } from '@alifd/next'; import { Tab, Breadcrumb } from '@alifd/next';
import { Title, observer, Editor } from '@ali/lowcode-editor-core'; import { Title, observer, Editor, obx, globalContext } from '@ali/lowcode-editor-core';
import { Node, isSettingField, SettingField } from '@ali/lowcode-designer'; import { Node, isSettingField, SettingField, Designer } from '@ali/lowcode-designer';
import { SettingsMain } from './main'; import { SettingsMain } from './main';
import { SettingsPane } from './settings-pane'; import { SettingsPane } from './settings-pane';
import { createIcon } from '@ali/lowcode-utils'; import { createIcon } from '@ali/lowcode-utils';
@ -10,6 +10,8 @@ import { createIcon } from '@ali/lowcode-utils';
export class SettingsPrimaryPane extends Component<{ editor: Editor }> { export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
private main = new SettingsMain(this.props.editor); private main = new SettingsMain(this.props.editor);
@obx.ref private _activeKey?: any;
shouldComponentUpdate() { shouldComponentUpdate() {
return false; return false;
} }
@ -26,13 +28,16 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
if (settings.isMultiple) { if (settings.isMultiple) {
return ( return (
<div className="lc-settings-navigator"> <div className="lc-settings-navigator">
{createIcon(settings.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})} {createIcon(settings.componentMeta?.icon, { className: 'lc-settings-navigator-icon' })}
<Title title={settings.componentMeta!.title} /> <Title title={settings.componentMeta!.title} />
<span>x {settings.nodes.length}</span> <span>x {settings.nodes.length}</span>
</div> </div>
); );
} }
const editor = globalContext.get(Editor);
const designer = editor.get(Designer);
const current = designer?.currentSelection?.getNodes()?.[0];
let node: Node | null = settings.first; let node: Node | null = settings.first;
const items = []; const items = [];
let l = 3; let l = 3;
@ -43,15 +48,33 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
: { : {
onMouseOver: hoverNode.bind(null, node, true), onMouseOver: hoverNode.bind(null, node, true),
onMouseOut: hoverNode.bind(null, node, false), onMouseOut: hoverNode.bind(null, node, false),
onClick: selectNode.bind(null, node), onClick: () => {
selectNode.call(null, node);
const getName = (node) => {
const npm = node?.componentMeta?.npm;
return [npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
}; };
items.unshift(<Breadcrumb.Item {...props} key={node.id}><Title title={node.title} /></Breadcrumb.Item>); const selected = getName(current);
const target = getName(node);
editor?.emit('skeleton.settingsPane.Breadcrumb', {
selected,
target,
});
},
};
items.unshift(
<Breadcrumb.Item {...props} key={node.id}>
<Title title={node.title} />
</Breadcrumb.Item>,
);
node = node.parent; node = node.parent;
} }
return ( return (
<div className="lc-settings-navigator"> <div className="lc-settings-navigator">
{createIcon(this.main.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})} {createIcon(this.main.componentMeta?.icon, { className: 'lc-settings-navigator-icon' })}
<Breadcrumb className="lc-settings-node-breadcrumb">{items}</Breadcrumb> <Breadcrumb className="lc-settings-node-breadcrumb">{items}</Breadcrumb>
</div> </div>
); );
@ -82,7 +105,7 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
} }
const { items } = settings; const { items } = settings;
if (items.length > 5 || items.some(item => !isSettingField(item) || !item.isGroup)) { if (items.length > 5 || items.some((item) => !isSettingField(item) || !item.isGroup)) {
return ( return (
<div className="lc-settings-main"> <div className="lc-settings-main">
{this.renderBreadcrumb()} {this.renderBreadcrumb()}
@ -93,21 +116,34 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
); );
} }
let matched = false;
const tabs = (items as SettingField[]).map((field) => {
if (this._activeKey === field.name) {
matched = true;
}
return (
<Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}>
<SettingsPane target={field} key={field.id} />
</Tab.Item>
);
});
const activeKey = matched ? this._activeKey : (items[0] as SettingField).name;
return ( return (
<div className="lc-settings-main"> <div className="lc-settings-main">
<Tab <Tab
key={settings.id} activeKey={activeKey}
onChange={(tabKey) => {
this._activeKey = tabKey;
}}
navClassName="lc-settings-tabs" navClassName="lc-settings-tabs"
animation={false} animation={false}
excessMode="dropdown" excessMode="dropdown"
contentClassName="lc-settings-tabs-content" contentClassName="lc-settings-tabs-content"
disableKeyboard={true}
extra={this.renderBreadcrumb()} extra={this.renderBreadcrumb()}
> >
{(items as SettingField[]).map(field => ( {tabs}
<Tab.Item className="lc-settings-tab-item" title={<Title title={field.title} />} key={field.name}>
<SettingsPane target={field} key={field.id} />
</Tab.Item>
))}
</Tab> </Tab>
</div> </div>
); );

View File

@ -1,7 +1,7 @@
import { Component, ReactElement } from 'react'; import { Component, ReactElement } from 'react';
import { Icon } from '@alifd/next'; import { Icon } from '@alifd/next';
import classNames from 'classnames'; import classNames from 'classnames';
import { Title, observer, Tip } from '@ali/lowcode-editor-core'; import { Title, observer, Tip, globalContext, Editor } from '@ali/lowcode-editor-core';
import { DockProps } from '../types'; import { DockProps } from '../types';
import PanelDock from '../widget/panel-dock'; import PanelDock from '../widget/panel-dock';
import { composeTitle } from '../widget/utils'; import { composeTitle } from '../widget/utils';
@ -27,7 +27,7 @@ function HelpTip({ tip }: any) {
return ( return (
<div> <div>
<a href={tip.url} target="_blank" rel="noopener noreferrer"> <a href={tip.url} target="_blank" rel="noopener noreferrer">
<Icon type="help" size="small" className="lc-help-tip"/> <Icon type="help" size="small" className="lc-help-tip" />
</a> </a>
<Tip>{tip.content}</Tip> <Tip>{tip.content}</Tip>
</div> </div>
@ -35,10 +35,10 @@ function HelpTip({ tip }: any) {
} }
return ( return (
<div> <div>
<Icon type="help" size="small" className="lc-help-tip"/> <Icon type="help" size="small" className="lc-help-tip" />
<Tip>{tip.content}</Tip> <Tip>{tip.content}</Tip>
</div> </div>
) );
} }
@observer @observer
@ -49,7 +49,7 @@ export class PanelDockView extends Component<DockProps & { dock: PanelDock }> {
componentDidUpdate() { componentDidUpdate() {
this.checkActived(); this.checkActived();
} }
private lastActived: boolean = false; private lastActived = false;
checkActived() { checkActived() {
const { dock } = this.props; const { dock } = this.props;
if (dock.actived !== this.lastActived) { if (dock.actived !== this.lastActived) {
@ -77,12 +77,10 @@ export class PanelDockView extends Component<DockProps & { dock: PanelDock }> {
} }
} }
export class DialogDockView extends Component { export class DialogDockView extends Component {}
}
@observer @observer
export class TitledPanelView extends Component<{ panel: Panel }> { export class TitledPanelView extends Component<{ panel: Panel; area?: string }> {
shouldComponentUpdate() { shouldComponentUpdate() {
return false; return false;
} }
@ -92,7 +90,7 @@ export class TitledPanelView extends Component<{ panel: Panel }> {
componentDidUpdate() { componentDidUpdate() {
this.checkVisible(); this.checkVisible();
} }
private lastVisible: boolean = false; private lastVisible = false;
checkVisible() { checkVisible() {
const { panel } = this.props; const { panel } = this.props;
const currentVisible = panel.inited && panel.visible; const currentVisible = panel.inited && panel.visible;
@ -106,14 +104,23 @@ export class TitledPanelView extends Component<{ panel: Panel }> {
} }
} }
render() { render() {
const { panel } = this.props; const { panel, area } = this.props;
if (!panel.inited) { if (!panel.inited) {
return null; return null;
} }
const editor = globalContext.get(Editor);
const panelName = area ? `${area}-${panel.name}` : panel.name;
editor?.emit('skeleton.panel.toggle', {
name: panelName || '',
status: panel.visible ? 'show' : 'hide',
});
return ( return (
<div className={classNames('lc-titled-panel', { <div
className={classNames('lc-titled-panel', {
hidden: !panel.visible, hidden: !panel.visible,
})}> })}
id={panelName}
>
<PanelTitle panel={panel} /> <PanelTitle panel={panel} />
<div className="lc-panel-body">{panel.body}</div> <div className="lc-panel-body">{panel.body}</div>
</div> </div>
@ -122,7 +129,7 @@ export class TitledPanelView extends Component<{ panel: Panel }> {
} }
@observer @observer
export class PanelView extends Component<{ panel: Panel }> { export class PanelView extends Component<{ panel: Panel; area?: string }> {
shouldComponentUpdate() { shouldComponentUpdate() {
return false; return false;
} }
@ -132,7 +139,7 @@ export class PanelView extends Component<{ panel: Panel }> {
componentDidUpdate() { componentDidUpdate() {
this.checkVisible(); this.checkVisible();
} }
private lastVisible: boolean = false; private lastVisible = false;
checkVisible() { checkVisible() {
const { panel } = this.props; const { panel } = this.props;
const currentVisible = panel.inited && panel.visible; const currentVisible = panel.inited && panel.visible;
@ -150,15 +157,22 @@ export class PanelView extends Component<{ panel: Panel }> {
} }
} }
render() { render() {
const { panel } = this.props; const { panel, area } = this.props;
if (!panel.inited) { if (!panel.inited) {
return null; return null;
} }
const editor = globalContext.get(Editor);
const panelName = area ? `${area}-${panel.name}` : panel.name;
editor?.emit('skeleton.panel.toggle', {
name: panelName || '',
status: panel.visible ? 'show' : 'hide',
});
return ( return (
<div <div
className={classNames('lc-panel', { className={classNames('lc-panel', {
hidden: !panel.visible, hidden: !panel.visible,
})} })}
id={panelName}
> >
{panel.body} {panel.body}
</div> </div>
@ -233,7 +247,7 @@ export class WidgetView extends Component<{ widget: IWidget }> {
componentDidUpdate() { componentDidUpdate() {
this.checkVisible(); this.checkVisible();
} }
private lastVisible: boolean = false; private lastVisible = false;
checkVisible() { checkVisible() {
const { widget } = this.props; const { widget } = this.props;
const currentVisible = widget.visible; const currentVisible = widget.visible;

View File

@ -0,0 +1,4 @@
import { createContext } from 'react';
import { Skeleton } from './skeleton';
export const SkeletonContext = createContext<Skeleton>({} as any);

View File

@ -3,5 +3,6 @@ export * from './skeleton';
export * from './types'; export * from './types';
export * from './components/settings'; export * from './components/settings';
export * from './components/field'; export * from './components/field';
export * from './context';
import './register-defaults'; import './register-defaults';

View File

@ -24,11 +24,12 @@ class Contents extends Component<{ area: Area }> {
const { area } = this.props; const { area } = this.props;
const top: any[] = []; const top: any[] = [];
const bottom: any[] = []; const bottom: any[] = [];
area.container.items.forEach(item => { area.container.items.forEach((item) => {
const content = <div id={`left-area-${item.name}`}>{item.content}</div>;
if (item.align === 'bottom') { if (item.align === 'bottom') {
bottom.push(item.content); bottom.push(content);
} else { } else {
top.push(item.content); top.push(content);
} }
}); });
return ( return (

View File

@ -25,8 +25,7 @@ export default class LeftFixedPane extends Component<{ area: Area<PanelConfig, P
'lc-area-visible': area.visible, 'lc-area-visible': area.visible,
})} })}
> >
{ {!hideTitleBar && (
!hideTitleBar && (
<Button <Button
text text
className="lc-pane-close" className="lc-pane-close"
@ -36,8 +35,7 @@ export default class LeftFixedPane extends Component<{ area: Area<PanelConfig, P
> >
<Icon type="close" /> <Icon type="close" />
</Button> </Button>
) )}
}
<Contents area={area} /> <Contents area={area} />
</div> </div>
); );
@ -51,10 +49,6 @@ class Contents extends Component<{ area: Area<PanelConfig, Panel> }> {
} }
render() { render() {
const { area } = this.props; const { area } = this.props;
return ( return <Fragment>{area.container.items.map((panel) => panel.content)}</Fragment>;
<Fragment>
{area.container.items.map((panel) => panel.content)}
</Fragment>
);
} }
} }

View File

@ -31,6 +31,15 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
if (this.shell?.contains(target)) { if (this.shell?.contains(target)) {
return true; return true;
} }
// 点击了 iframe 内容,算失焦
if (document.querySelector('.lc-simulator-content-frame')
.contentWindow.document.documentElement.contains(target)) {
return false;
}
// 点击非编辑区域的 popup / dialog 等,不触发失焦
if (!document.querySelector('.lc-workbench')?.contains(target)) {
return true;
}
const docks = area.current?.getAssocDocks(); const docks = area.current?.getAssocDocks();
if (docks && docks?.length) { if (docks && docks?.length) {
return docks.some(dock => dock.getDOMNode()?.contains(target)); return docks.some(dock => dock.getDOMNode()?.contains(target));
@ -41,6 +50,7 @@ export default class LeftFloatPane extends Component<{ area: Area<any, Panel> }>
this.props.area.setVisible(false); this.props.area.setVisible(false);
}, },
onBlur: () => { onBlur: () => {
// debugger
this.props.area.setVisible(false); this.props.area.setVisible(false);
}, },
}); });

View File

@ -30,7 +30,7 @@ class Contents extends Component<{ area: Area, itemClassName?: string }> {
return index1 === index2 ? 0 : (index1 > index2 ? 1 : -1); return index1 === index2 ? 0 : (index1 > index2 ? 1 : -1);
}).forEach(item => { }).forEach(item => {
const content = ( const content = (
<div className={itemClassName || ''}> <div className={itemClassName || ''} id={`top-area-${item.name}`}>
{item.content} {item.content}
</div> </div>
); );

View File

@ -11,6 +11,7 @@ import MainArea from './main-area';
import BottomArea from './bottom-area'; import BottomArea from './bottom-area';
import RightArea from './right-area'; import RightArea from './right-area';
import './workbench.less'; import './workbench.less';
import { SkeletonContext } from '../context';
import { EditorConfig, PluginClassSet } from '@ali/lowcode-types'; import { EditorConfig, PluginClassSet } from '@ali/lowcode-types';
@observer @observer
@ -28,6 +29,7 @@ export class Workbench extends Component<{ skeleton: Skeleton; config?: EditorCo
const { skeleton, className, topAreaItemClassName } = this.props; const { skeleton, className, topAreaItemClassName } = this.props;
return ( return (
<div className={classNames('lc-workbench', className)}> <div className={classNames('lc-workbench', className)}>
<SkeletonContext.Provider value={this.props.skeleton}>
<TopArea area={skeleton.topArea} itemClassName={topAreaItemClassName} /> <TopArea area={skeleton.topArea} itemClassName={topAreaItemClassName} />
<div className="lc-workbench-body"> <div className="lc-workbench-body">
<LeftArea area={skeleton.leftArea} /> <LeftArea area={skeleton.leftArea} />
@ -41,6 +43,7 @@ export class Workbench extends Component<{ skeleton: Skeleton; config?: EditorCo
<RightArea area={skeleton.rightArea} /> <RightArea area={skeleton.rightArea} />
</div> </div>
<TipContainer /> <TipContainer />
</SkeletonContext.Provider>
</div> </div>
); );
} }

View File

@ -294,7 +294,7 @@ export class Skeleton {
let { area } = parsedConfig; let { area } = parsedConfig;
if (!area) { if (!area) {
if (parsedConfig.type === 'Panel') { if (parsedConfig.type === 'Panel') {
area = 'leftFloatArea' area = 'leftFloatArea';
} else if (parsedConfig.type === 'Widget') { } else if (parsedConfig.type === 'Widget') {
area = 'mainArea'; area = 'mainArea';
} else { } else {

View File

@ -1,5 +1,6 @@
import { TransformedComponentMetadata, FieldConfig, SettingTarget } from '@ali/lowcode-types'; import { TransformedComponentMetadata, FieldConfig, SettingTarget } from '@ali/lowcode-types';
import { IconSlot } from '../icons/slot'; import { IconSlot } from '../icons/slot';
import { getConvertedExtraKey } from '@ali/lowcode-designer';
export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata { export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata {
const { componentName, configure = {} } = metadata; const { componentName, configure = {} } = metadata;
@ -86,7 +87,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
if (componentName === 'Slot') { if (componentName === 'Slot') {
basicInfo.icon = IconSlot; basicInfo.icon = IconSlot;
propsGroup = [{ propsGroup = [{
name: '___title', name: getConvertedExtraKey('title'),
title: { title: {
type: 'i18n', type: 'i18n',
'en-US': 'Slot Title', 'en-US': 'Slot Title',
@ -203,7 +204,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
if (!isRoot) { if (!isRoot) {
if (supports.condition !== false) { if (supports.condition !== false) {
advanceGroup.push({ advanceGroup.push({
name: '___condition', name: getConvertedExtraKey('condition'),
title: { type: 'i18n', 'zh-CN': '是否渲染', 'en-US': 'Condition' }, title: { type: 'i18n', 'zh-CN': '是否渲染', 'en-US': 'Condition' },
defaultValue: true, defaultValue: true,
setter: [{ setter: [{
@ -219,7 +220,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
title: { type: 'i18n', 'zh-CN': '循环', 'en-US': 'Loop' }, title: { type: 'i18n', 'zh-CN': '循环', 'en-US': 'Loop' },
items: [ items: [
{ {
name: '___loop', name: getConvertedExtraKey('loop'),
title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' }, title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' },
defaultValue: [], defaultValue: [],
setter: [{ setter: [{
@ -232,7 +233,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
}], }],
}, },
{ {
name: '___loopArgs.0', name: getConvertedExtraKey('loopArgs.0'),
title: { type: 'i18n', 'zh-CN': '迭代变量名', 'en-US': 'Loop Item' }, title: { type: 'i18n', 'zh-CN': '迭代变量名', 'en-US': 'Loop Item' },
setter: { setter: {
componentName: 'StringSetter', componentName: 'StringSetter',
@ -242,7 +243,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
}, },
}, },
{ {
name: '___loopArgs.1', name: getConvertedExtraKey('loopArgs.1'),
title: { type: 'i18n', 'zh-CN': '索引变量名', 'en-US': 'Loop Index' }, title: { type: 'i18n', 'zh-CN': '索引变量名', 'en-US': 'Loop Index' },
setter: { setter: {
componentName: 'StringSetter', componentName: 'StringSetter',

View File

@ -53,7 +53,7 @@ function propTypeToSetter(propType: PropType): SetterType {
}; };
case 'bool': case 'bool':
return { return {
componentName: 'NumberSetter', componentName: 'BoolSetter',
isRequired, isRequired,
initialValue: false, initialValue: false,
}; };

View File

@ -18,6 +18,7 @@ export interface WidgetConfig extends IWidgetBaseConfig {
props?: { props?: {
align?: "left" | "right" | "bottom" | "center" | "top"; align?: "left" | "right" | "bottom" | "center" | "top";
onInit?: (widget: IWidget) => void; onInit?: (widget: IWidget) => void;
title?: TitleContent;
}; };
content?: string | ReactElement | ComponentType<any>; // children content?: string | ReactElement | ComponentType<any>; // children
} }

View File

@ -53,13 +53,16 @@ export default class Panel implements IWidget {
} }
get content(): ReactNode { get content(): ReactNode {
const area = this.config?.area || this.parent?.name;
console.log(area);
if (this.plain) { if (this.plain) {
return createElement(PanelView, { return createElement(PanelView, {
panel: this, panel: this,
key: this.id, key: this.id,
area,
}); });
} }
return createElement(TitledPanelView, { panel: this, key: this.id }); return createElement(TitledPanelView, { panel: this, key: this.id, area });
} }
readonly title: TitleContent; readonly title: TitleContent;

View File

@ -4,6 +4,7 @@ import { createContent, uniqueId } from '@ali/lowcode-utils';
import { WidgetConfig, IWidgetBaseConfig } from '../types'; import { WidgetConfig, IWidgetBaseConfig } from '../types';
import { Skeleton } from '../skeleton'; import { Skeleton } from '../skeleton';
import { WidgetView } from '../components/widget-views'; import { WidgetView } from '../components/widget-views';
import { TitleContent } from '@ali/lowcode-types';
export interface IWidget { export interface IWidget {
readonly name: string; readonly name: string;
@ -56,10 +57,13 @@ export default class Widget implements IWidget {
}); });
} }
readonly title: TitleContent;
constructor(readonly skeleton: Skeleton, readonly config: WidgetConfig) { constructor(readonly skeleton: Skeleton, readonly config: WidgetConfig) {
const { props = {}, name } = config; const { props = {}, name } = config;
this.name = name; this.name = name;
this.align = props.align; this.align = props.align;
this.title = props.title || name;
if (props.onInit) { if (props.onInit) {
props.onInit.call(this, this); props.onInit.call(this, this);
} }

View File

@ -3,6 +3,89 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.8.23"></a>
## [0.8.23](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.22...@ali/lowcode-plugin-components-pane@0.8.23) (2020-06-16)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.22"></a>
## [0.8.22](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.21...@ali/lowcode-plugin-components-pane@0.8.22) (2020-06-15)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.21"></a>
## [0.8.21](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.20...@ali/lowcode-plugin-components-pane@0.8.21) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.20"></a>
## [0.8.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.19...@ali/lowcode-plugin-components-pane@0.8.20) (2020-05-19)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.19"></a>
## [0.8.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.18...@ali/lowcode-plugin-components-pane@0.8.19) (2020-05-18)
### Features
* use new ComponentPane ([56ae5ad](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56ae5ad))
<a name="0.8.18"></a>
## [0.8.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.17...@ali/lowcode-plugin-components-pane@0.8.18) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.17"></a>
## [0.8.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.16...@ali/lowcode-plugin-components-pane@0.8.17) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.16"></a>
## [0.8.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.15...@ali/lowcode-plugin-components-pane@0.8.16) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.15"></a>
## [0.8.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.14...@ali/lowcode-plugin-components-pane@0.8.15) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.14"></a>
## [0.8.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.13...@ali/lowcode-plugin-components-pane@0.8.14) (2020-05-15)
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
<a name="0.8.13"></a> <a name="0.8.13"></a>
## [0.8.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.12...@ali/lowcode-plugin-components-pane@0.8.13) (2020-05-15) ## [0.8.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-components-pane@0.8.12...@ali/lowcode-plugin-components-pane@0.8.13) (2020-05-15)

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-plugin-components-pane", "name": "@ali/lowcode-plugin-components-pane",
"version": "0.8.13", "version": "0.8.23",
"description": "alibaba lowcode editor component-list plugin", "description": "alibaba lowcode editor component-list plugin",
"files": [ "files": [
"es/", "es/",
@ -20,11 +20,11 @@
], ],
"author": "xiayang.xy", "author": "xiayang.xy",
"dependencies": { "dependencies": {
"@ali/lowcode-designer": "^0.9.11", "@ali/lowcode-designer": "^0.9.20",
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-editor-core": "^0.8.16",
"@ali/lowcode-types": "^0.8.3", "@ali/lowcode-types": "^0.8.6",
"@alifd/next": "^1.19.19",
"@ali/ve-component-list": "^1.1.1", "@ali/ve-component-list": "^1.1.1",
"@alifd/next": "^1.19.19",
"react": "^16.8.1" "react": "^16.8.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -3,6 +3,78 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.9.20"></a>
## [0.9.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.19...@ali/lowcode-plugin-designer@0.9.20) (2020-06-16)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.19"></a>
## [0.9.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.18...@ali/lowcode-plugin-designer@0.9.19) (2020-06-15)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.18"></a>
## [0.9.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.17...@ali/lowcode-plugin-designer@0.9.18) (2020-05-20)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.17"></a>
## [0.9.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.16...@ali/lowcode-plugin-designer@0.9.17) (2020-05-19)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.16"></a>
## [0.9.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.15...@ali/lowcode-plugin-designer@0.9.16) (2020-05-18)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.15"></a>
## [0.9.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.14...@ali/lowcode-plugin-designer@0.9.15) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.14"></a>
## [0.9.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.13...@ali/lowcode-plugin-designer@0.9.14) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.13"></a>
## [0.9.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.12...@ali/lowcode-plugin-designer@0.9.13) (2020-05-16)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.12"></a>
## [0.9.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.11...@ali/lowcode-plugin-designer@0.9.12) (2020-05-15)
**Note:** Version bump only for package @ali/lowcode-plugin-designer
<a name="0.9.11"></a> <a name="0.9.11"></a>
## [0.9.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.10...@ali/lowcode-plugin-designer@0.9.11) (2020-05-15) ## [0.9.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-designer@0.9.10...@ali/lowcode-plugin-designer@0.9.11) (2020-05-15)

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-plugin-designer", "name": "@ali/lowcode-plugin-designer",
"version": "0.9.11", "version": "0.9.20",
"description": "alibaba lowcode editor designer plugin", "description": "alibaba lowcode editor designer plugin",
"files": [ "files": [
"es", "es",
@ -20,8 +20,8 @@
], ],
"author": "xiayang.xy", "author": "xiayang.xy",
"dependencies": { "dependencies": {
"@ali/lowcode-designer": "^0.9.11", "@ali/lowcode-designer": "^0.9.20",
"@ali/lowcode-editor-core": "^0.8.12", "@ali/lowcode-editor-core": "^0.8.16",
"react": "^16.8.1", "react": "^16.8.1",
"react-dom": "^16.8.1" "react-dom": "^16.8.1"
}, },

Some files were not shown because too many files have changed in this diff Show More