Compare commits

...

228 Commits

Author SHA1 Message Date
唐澜
f6305c2284
Merge pull request #3050 from alibaba/chore/update-codeowners
chore: update code owners
2024-06-11 21:12:45 +08:00
1ncounter
2892a01d29 chore: update code owners 2024-06-11 21:07:42 +08:00
GitHub Action
bd85ca3ca6 chore(release): publish 1.3.2 2024-02-23 01:51:23 +00:00
liujuping
44beb2a25a fix(workspace): fix workspace editorView is undefined 2024-02-07 13:43:39 +08:00
liujuping
86d50e0946 fix(setter): params is not shell SettingField 2024-02-04 16:42:46 +08:00
liujuping
19eb917259 refactor(plugin-command): add plugin-command package 2024-02-01 16:24:08 +08:00
GitHub Action
501ad872c4 chore(docs): publish documentation 2024-02-01 08:17:01 +00:00
liujuping
76b2a05049 docs(command): add command api docs 2024-02-01 16:15:16 +08:00
liujuping
5657d9c084 feat: update test package.yaml 2024-02-01 14:49:25 +08:00
liujuping
5b46d96df7 refactor(plugin-command): add plugin-command package 2024-02-01 14:45:41 +08:00
liujuping
24393211b4 refactor(plugin-command): add plugin-command package 2024-02-01 12:54:39 +08:00
liujuping
de95b87b1e feat: update ts defined 2024-02-01 07:01:05 +08:00
liujuping
43921cea2d fix(workspace): fix workspace.plugins.xxx api is invalid 2024-01-31 16:05:21 +08:00
liujuping
557a462b9f fix(prop): emit event when delete prop 2024-01-30 15:01:58 +08:00
liujuping
80bb7102b6 feat(command): update default commands 2024-01-30 14:38:11 +08:00
liujuping
ed7befbff0 feat(context-menu): prevent event bubbling when "menus" is empty 2024-01-30 11:05:08 +08:00
liujuping
e3a19896d7 fix(prop): emit event when unset prop 2024-01-30 11:04:54 +08:00
唐澜
dfe6878028
Merge pull request #2888 from Zeral-Zhang/develop
fix(react-simulator-renderer): detached node has children
2024-01-26 17:51:16 +08:00
liujuping
6e89d4d605 feat(setter): add field ts 2024-01-26 17:17:44 +08:00
GitHub Action
739572172a chore(docs): publish documentation 2024-01-26 08:40:59 +00:00
liujuping
b97570f10c docs(demo): add dialog use desc 2024-01-26 16:40:04 +08:00
ZeralZhang
b29c53901e fix(react-simulator-renderer): detached node has children
detached node has children will return false, causing memory leaks.
2024-01-26 09:38:37 +08:00
liujuping
b3880e9a96 feat(command): add command apis 2024-01-25 16:38:58 +08:00
liujuping
947c621822 test(utils): add more test case for checkPropTypes 2024-01-25 15:57:05 +08:00
liujuping
dca3448cbf chore(editor-core): init test 2024-01-25 15:56:41 +08:00
liujuping
0e65f02116 feat(utils): move checkPropTypes to utils module 2024-01-25 10:52:58 +08:00
liujuping
cd67a8cea3 test(designer): add parse-metadata test 2024-01-25 10:10:55 +08:00
liujuping
e6ba79b4d7 feat(utils): checkPropTypes suport IPublicTypePropType as rule for check 2024-01-25 10:10:38 +08:00
GitHub Action
de738b5d7c chore(docs): publish documentation 2024-01-18 01:06:41 +00:00
liujuping
9b19d8f889 docs: remove title level from 示例 sections in documentation 2024-01-18 09:05:49 +08:00
GitHub Action
4025a7d2e0 chore(release): publish 1.3.1 2024-01-17 06:01:02 +00:00
liujuping
8f8908c832 fix(context-menu): fix context menu component instance changed 2024-01-17 11:23:45 +08:00
liujuping
a8b9b2b5e1 chore: add "set -e" in build.sh 2024-01-16 18:23:29 +08:00
liujuping
84b4c76db2 chore: update build-plugin-lce version 2024-01-16 17:38:39 +08:00
liujuping
4dd6f7a352 feat: update comtext menu component 2024-01-16 10:40:05 +08:00
GitHub Action
7f2b2870aa chore(docs): publish documentation 2024-01-16 02:35:43 +00:00
liujuping
d8406c5bab docs: update resource docs 2024-01-16 10:34:50 +08:00
JackLian
f9fe38e65a Merge branch 'release/1.3.0' 2024-01-15 14:18:16 +08:00
GitHub Action
1943172d65 chore(release): publish 1.3.0 2024-01-15 06:12:28 +00:00
JackLian
d957be8072 chore: add pub:minor and pub:major commands 2024-01-15 14:03:23 +08:00
JackLian
e77063636c chore: add pub:minor and pub:major commands 2024-01-15 14:02:38 +08:00
eightHundreds
d1a8bacd75 fix(designer): node.ts cannot generate declaration file 2024-01-15 13:00:05 +08:00
liujuping
adb9f6b090 fix(canvas): clipboard init error 2024-01-15 10:11:09 +08:00
liujuping
1132a30483 feat: update context-menu message 2024-01-12 16:09:06 +08:00
liujuping
34a5a11b49 fix: fix clipboard.setData fial in workspace mode 2024-01-12 16:08:31 +08:00
GitHub Action
8931d8393d chore(docs): publish documentation 2024-01-12 01:17:52 +00:00
liujuping
844ca783d7 feat(context-menu): add context-menu css theme, help config, ts define 2024-01-12 09:16:53 +08:00
GitHub Action
6f9359e042 chore(docs): publish documentation 2024-01-11 10:13:55 +00:00
liujuping
ce72fc1b16 feat(common-ui): add HelpTip 2024-01-11 18:13:00 +08:00
GitHub Action
18642ee923 chore(docs): publish documentation 2024-01-11 03:17:25 +00:00
liujuping
bb5d7ddf82 feat(context-menu): update context-menu docs, details, styles 2024-01-11 11:16:31 +08:00
GitHub Action
3e7d199a7c chore(docs): publish documentation 2024-01-11 02:50:04 +00:00
liujuping
a7d3996fa2 feat(common): add common.utils.intl API 2024-01-11 10:49:12 +08:00
GitHub Action
a00c5c9b60 chore(docs): publish documentation 2024-01-10 07:21:10 +00:00
liujuping
3627ae326a feat: optimize context menu details 2024-01-10 15:20:16 +08:00
GitHub Action
14728476b6 chore(docs): publish documentation 2024-01-09 08:43:50 +00:00
liujuping
c381b85f0a fix(context-menu): fix context menu bugs 2024-01-09 16:43:01 +08:00
liujuping
8f0291fc3e fix(context-menu): fix context menu bugs 2024-01-09 09:08:40 +08:00
liujuping
6ded1a6384 chore: update CODEOWNERS 2024-01-09 09:07:59 +08:00
GitHub Action
6ce381f60a chore(docs): publish documentation 2024-01-08 07:06:58 +00:00
JackLian
6288ab9d60 fix(docs): fix invalid doc content 2024-01-08 15:06:00 +08:00
GitHub Action
3f369e446d chore(docs): publish documentation 2024-01-08 06:56:19 +00:00
liujuping
1b00c61a32 feat(engine): add context menu 2024-01-08 14:55:28 +08:00
GitHub Action
d47c2d2f91 chore(docs): publish documentation 2024-01-05 08:09:04 +00:00
liujuping
31a031ce4e feat: removed Rax packages, discontinuing support for Rax 2024-01-05 16:08:04 +08:00
Arun
ba53d6c690 ci: Use GITHUB_OUTPUT envvar instead of set-output command 2024-01-05 11:51:45 +08:00
GitHub Action
e8aebb9aa3 chore(docs): publish documentation 2024-01-05 03:44:36 +00:00
liujuping
be0456fb39 feat: add commonUI API 2024-01-05 11:42:36 +08:00
liujuping
d81eb8d75d style(outline): update selected item style 2024-01-05 11:42:13 +08:00
liujuping
c24c3d8ae5 feat: add hideComponentAction config 2024-01-05 11:41:46 +08:00
LiuTeiTei
e1f3a11c41 fix: trigger onFilterResultChanged when filtered 2024-01-05 11:10:08 +08:00
wangwei
173978ffd4 chore(release): code-gen 1.1.7 2024-01-03 15:17:40 +08:00
聪小陈
7b85a35b24
feat: zip publisher support browser (#2744) 2024-01-02 18:15:30 +08:00
GitHub Action
b2abb67440 chore(release): publish 1.2.5 2023-12-28 06:22:34 +00:00
JackLian
0d6b2b8bf8 Merge branch 'main' into develop 2023-12-28 14:04:50 +08:00
JackLian
8a1345527f Merge branch 'release/1.2.4' 2023-12-28 14:04:04 +08:00
GitHub Action
89e912ba1a chore(release): publish 1.2.4 2023-12-28 05:57:44 +00:00
liujuping
f7ba053476 fix(outline-pane): hover invalid 2023-12-26 15:09:36 +08:00
eightHundreds
f483970aef fix: trigger node.add event on mergeChildren 2023-12-26 14:51:03 +08:00
liujuping
73dacadaee style(skeleton): update setting pane styles 2023-12-26 09:50:00 +08:00
GitHub Action
733229985b chore(docs): publish documentation 2023-12-19 09:57:55 +00:00
liujuping
e79f68611a feat(skeleton): add onDisableWidget & onEnableWidget APIs 2023-12-19 17:56:18 +08:00
GitHub Action
4a502f823c chore(docs): publish documentation 2023-12-19 01:32:47 +00:00
liujuping
2bf3aa70a7 docs: add skeleton.getAreaItems docs 2023-12-19 09:31:52 +08:00
liujuping
594abc4e6c style(designer): update bem-tools index 2023-12-18 14:34:53 +08:00
liujuping
16713f4b84 feat(skeleton): Add TS defs for modules & optimize Tabs display with array contents 2023-12-18 10:03:41 +08:00
liujuping
711a5f66b9 style: remove .lc-workbench-center z-index 2023-12-18 10:02:26 +08:00
GitHub Action
c6e0025256 chore(docs): publish documentation 2023-12-14 09:28:13 +00:00
JackLian
230e63ce55 docs: add new link to video page 2023-12-14 17:27:07 +08:00
JackLian
39d030bfc3 chore(workflows/publish-docs): update config 2023-12-14 14:51:03 +08:00
JackLian
9394aecc7c chore(workflows/publish-docs): update config 2023-12-14 14:49:25 +08:00
JackLian
53078ba5f0 chore(workflows/publish-docs): update config 2023-12-14 14:46:17 +08:00
JackLian
5d08b6858d chore(workflows/publish-docs): update config 2023-12-14 14:45:01 +08:00
JackLian
729083aa01 chore(workflows/publish-docs): update config 2023-12-14 14:18:57 +08:00
GitHub Action
729b123e46 chore(docs): publish documentation 2023-12-14 06:16:05 +00:00
JackLian
b56a2a9274 chore(workflows/publish-docs): update config 2023-12-14 14:13:58 +08:00
GitHub Action
cdcc8c8a90 chore(docs): publish documentation 2023-12-14 06:04:49 +00:00
JackLian
2349599daa Merge branch 'main' into develop 2023-12-14 14:01:13 +08:00
JackLian
613142b2d8 chore(workflows/publish-docs): add workflow_dispatch trigger 2023-12-14 14:00:52 +08:00
JackLian
08401c76f9 chore(workflows/publish-docs): add workflow_dispatch trigger 2023-12-14 13:57:29 +08:00
liujuping
ec843543f0 chore: update docs publish action 2023-12-14 13:54:02 +08:00
GitHub Action
ef573d3ad9 chore(docs): publish documentation 2023-12-14 03:09:41 +00:00
JackLian
a567f12473 docs: add new link to video page 2023-12-14 11:08:47 +08:00
JackLian
bb50a20ef1 chore(docs): use tnpm as oss-syncing source 2023-12-14 10:44:34 +08:00
JackLian
9d526ebcd8 chore(workflows/publish-docs): update commit message 2023-12-14 10:22:26 +08:00
JackLian
27bf7babe5 chore: use tnpm as oss-syncing source 2023-12-14 10:17:13 +08:00
GitHub Action
c0ddba5543 Update package version 2023-12-14 02:15:38 +00:00
刘菊萍(絮黎)
f2d8fca188 docs: update workspace.md 2023-12-14 10:14:56 +08:00
JackLian
90add387ac chore: merge from release/1.2.3 2023-12-13 17:41:36 +08:00
GitHub Action
f418e5b2c1 chore(release): publish 1.2.3 2023-12-13 09:34:24 +00:00
唐澜
c3d0ffb62c Fix/component lifecycle not execute (#2692)
* fix: recover component lifecycle and avoid execute from scope __proto__
2023-12-13 17:26:26 +08:00
唐澜
2e604c9910 Fix/component lifecycle not execute (#2690)
* fix: recover component lifecycle and avoid execute from scope __proto__
2023-12-13 17:26:26 +08:00
liujuping
3c3a305c7a chore: update publish engine.yml 2023-12-13 17:23:55 +08:00
刘菊萍(絮黎)
2ec9bf7cdf chore: create publish engine.yml 2023-12-13 17:12:35 +08:00
liujuping
a25aad4975 fix(outline): fix view change bugs in workspace mode 2023-12-13 16:56:54 +08:00
liujuping
271aef4fb9 chore: add publish engine actions 2023-12-13 16:32:09 +08:00
GitHub Action
07ee7e0355 Update package version 2023-12-13 06:37:30 +00:00
liujuping
a0975428c4 docs: add faq024 2023-12-13 14:36:45 +08:00
liujuping
014834a31f style(outline): update outline-filter-icon style 2023-12-13 14:01:54 +08:00
GitHub Action
6932c3bdc7 Update package version 2023-12-07 05:49:17 +00:00
liujuping
1f214918bb style: add css themes vars 2023-12-07 13:48:33 +08:00
GitHub Action
3786b3a7ff Update package version 2023-12-05 07:38:51 +00:00
liujuping
398f069745 style: add css themes vars 2023-12-05 15:38:10 +08:00
GitHub Action
77aea1bfba Update package version 2023-12-05 07:29:34 +00:00
liujuping
a87dcaada1 chore: create publish docs.yml 2023-12-05 15:28:53 +08:00
JackLian
28fdf9a37d chore(docs): publish docs 1.2.5 2023-12-05 13:29:16 +08:00
liujuping
0a50cf5a0d docs: update participate docs 2023-12-05 13:27:06 +08:00
JackLian
70845a1eca chore(docs): publish docs 1.2.4 2023-12-05 09:32:21 +08:00
liujuping
4d03610fd3 feat: update types define 2023-12-04 10:22:50 +08:00
唐澜
ebdcc41461
fix: scope props merge defaultProps (#2716) 2023-12-01 15:27:30 +08:00
liujuping
8f5ba69813 docs: add meet docs 2023-12-01 14:24:42 +08:00
liujuping
1a328bd1f6 style: fix --workspace-left-area-width style bug 2023-11-30 17:40:25 +08:00
liujuping
19bf6ad284 style: add --color-toolbar-background 2023-11-30 08:46:02 +08:00
JackLian
d703e64ac9 chore(docs): publish docs 1.2.3 2023-11-29 11:10:29 +08:00
liujuping
d199b44eca style: add --color-toolbar-background 2023-11-29 10:00:30 +08:00
唐澜
a8051aefc3
Merge pull request #2705 from owenchen1004/main
fix: executeLifeCycleMethod return bug in renderer
2023-11-28 11:21:21 +08:00
owenchen1004
b786c8fcaa fix: coding style update 2023-11-28 11:04:37 +08:00
owenchen1004
f75b9ae61c fix: executeLifeCycleMethod return bug in renderer 2023-11-28 10:50:38 +08:00
刘菊萍(絮黎)
d41f2c13d2 docs: update material.md 2023-11-28 09:37:32 +08:00
JackLian
20bf62aed3 chore(docs): publish docs 1.2.2 2023-11-27 17:50:48 +08:00
刘菊萍(絮黎)
1c2f195e8b docs: update skeleton.md 2023-11-27 16:23:49 +08:00
1ncounter
c643c0fc4f fix(renderer-core): remove compatibility with uipaas 2023-11-23 19:58:30 +08:00
唐澜
6c7a526521
Fix/component lifecycle not execute (#2692)
* fix: recover component lifecycle and avoid execute from scope __proto__
2023-11-23 19:28:41 +08:00
唐澜
dc1e0f5a49
Fix/component lifecycle not execute (#2690)
* fix: recover component lifecycle and avoid execute from scope __proto__
2023-11-23 18:58:24 +08:00
JackLian
7e80d1f863 chore(docs): publish docs 1.2.1 2023-11-23 16:33:45 +08:00
liujuping
a3fef9c13d feat(skeleton): add registerConfigTransducer API 2023-11-23 16:27:00 +08:00
liujuping
029fd1ce67 feat(outline-pane): suport registry in workspace level 2023-11-23 16:23:11 +08:00
liujuping
ad044f49ed feat(utils): add workspace utils 2023-11-23 16:22:09 +08:00
andylili21
27e914cece
fix: Improve code and simplify logic (#2651)
* fix: Improve code and simplify logic
2023-11-23 16:05:07 +08:00
1ncounter
394b56d0ce fix: recover component lifecycle and avoid execute from scope __proto__ 2023-11-22 21:16:10 +08:00
JackLian
7c72261fef chore(docs): publish docs 1.2.0 2023-11-21 10:28:27 +08:00
chenkeyao.chenkeya
e35c672a50 feat: add new video 2023-11-21 10:26:53 +08:00
liujuping
322313cead docs: update faq list 2023-11-21 09:35:11 +08:00
liujuping
d47df9dc44 style: add --workspace-left-area-width 2023-11-20 17:50:46 +08:00
刘菊萍(絮黎)
bf50071cc8 docs: update index.md 2023-11-20 17:30:23 +08:00
刘菊萍(絮黎)
396e99aa11 docs: update index.md 2023-11-20 17:29:54 +08:00
JackLian
3c4bd1d2d0 chore(docs): publish docs 1.1.17 2023-11-20 16:45:11 +08:00
AprChell
8208dd3a32
fix(exportschema): exportSchema(IPublicEnumTransformStage.Save) type conver (#2661)
* fix(exportschema): exportSchema(IPublicEnumTransformStage.Save) type conver

* test(prop): nullProp equals null, not
2023-11-20 16:24:27 +08:00
刘菊萍(絮黎)
0f8bc82282 Update index.md 2023-11-20 16:15:20 +08:00
liujuping
8898f1c4a7 fix: fix engine-core classes is undefined 2023-11-16 09:09:13 +08:00
唐澜
629eaf84fb
Merge pull request #2654 from beautiful-boyyy/develop
fix: fixed string trim issue
2023-11-15 16:49:13 +08:00
beautiful-boyyy
3f3ad2f5bd
Merge branch 'alibaba:develop' into develop 2023-11-15 15:19:29 +08:00
beautiful-boyyy
058e184b21 fix: fixed string trim issue 2023-11-15 15:18:18 +08:00
Super-Rz
e7884fdb5a
fix: createIcon props (#2629)
* fix: createIcon props

* fix: createIcon props
2023-11-15 14:23:07 +08:00
beautiful-boyyy
6cba4bcc20 docs: update prepare.md 2023-11-15 14:21:59 +08:00
beautiful-boyyy
736cb0e965 docs: update prepare.md 2023-11-15 12:09:55 +08:00
liujuping
944012ab3f test(designer): add test ut to sequencify 2023-11-14 13:30:22 +08:00
liujuping
b697ea9ad4 feat(render-core): update logger to console 2023-11-14 13:29:31 +08:00
beautiful-boyyy
1020f98756
chore: remove useless code (#2643) 2023-11-14 09:48:36 +08:00
liujuping
9108e8cfab feat(types): add IPublicTypeInstanceOf to prop-types 2023-11-14 09:42:16 +08:00
JackLian
ef6a203a45 chore(docs): publish docs 1.1.16 2023-11-13 14:09:58 +08:00
liujuping
151748dbab docs: add before start doc 2023-11-13 14:08:19 +08:00
liujuping
621245393f test(utils): add ut to package/utils 2023-11-13 13:00:38 +08:00
JackLian
938c71fb46 chore(docs): publish docs 1.1.15 2023-11-13 12:57:02 +08:00
liujuping
04adda02fb docs: add faq-Slot组件渲染报错问题 2023-11-13 12:46:39 +08:00
JackLian
d64c7d56df chore(release): publish 1.2.2 2023-11-13 12:41:45 +08:00
liujuping
6320867cad docs: update Node to IPublicModelNode 2023-11-10 14:26:38 +08:00
JackLian
3b14a79d1b docs: publish docs 1.1.14 2023-11-10 10:03:01 +08:00
liujuping
f5c874b4bf chore(ignitor): change build config 2023-11-10 09:29:30 +08:00
刘菊萍(絮黎)
9f78f8c54a Update material.md 2023-11-10 09:28:56 +08:00
刘菊萍(絮黎)
de8dab5cb3 docs: update index.md 2023-11-10 09:28:11 +08:00
keuby
e3611dcf06
feat(utils|types): add esmodule support for component meta resources (#2603)
* feat(utils): support script type param for assest loader

* feat(types): update AssestsJson type
2023-11-07 17:20:13 +08:00
liujuping
97eb477746 feat: update engine classes exports 2023-11-07 16:31:34 +08:00
JackLian
c65c17f779 docs: publish docs 1.1.13 2023-11-03 14:05:04 +08:00
刘菊萍(絮黎)
c5ba2f3ef1 docs: update useEditor.md 2023-11-03 14:03:10 +08:00
Rainke
95a48e057f fix: import schema 之后 cache 判断错误(#2596) 2023-11-01 10:58:59 +08:00
JackLian
b3b2a03642 chore(release): publish 1.2.1 2023-10-27 13:14:57 +08:00
liujuping
055ab68a4b fix: fix document.onMountNode parameters 2023-10-26 11:49:47 +08:00
liujuping
11ee97c6da fix: fixed the problem caused by component list being overwritten by Hoc 2023-10-26 11:45:07 +08:00
JackLian
0f02080035 chore(release): publish 1.2.0 2023-10-20 15:52:31 +08:00
JackLian
e7a3ba9e9a chore(docs): publish docs 1.1.12 2023-10-19 14:19:47 +08:00
liujuping
79b9a6efa5 feat: add theme color document & optimize some theme colors 2023-10-19 14:07:54 +08:00
rainke
96fe876e33 fix: 复制时防止 ref 重复 2023-10-18 09:32:55 +08:00
rainke
d56ed6bff1 feat: make asset support es module 2023-10-18 09:32:12 +08:00
rainke
7677ad0166 fix: hoc 组件缓存 2023-10-18 09:22:56 +08:00
JackLian
a96961f588 docs: publish docs 1.1.11 2023-10-16 14:35:10 +08:00
rainke
ca6fe7c335 fix: 修复 forwardRef 组件的错误无法捕获 2023-10-16 14:28:45 +08:00
李正
3129445d60 Update specs.md
去掉重复内容
2023-10-13 09:44:09 +08:00
AndyJin
30f8066332 fix: fix rendering failure when children is number 0 2023-10-12 09:57:46 +08:00
rainke
4684d31717 chore: resolve react-error-overlay to 6.0.9 2023-10-10 18:35:22 +08:00
liujuping
82d82b9d05 feat: update Outline Tree to Component Tree 2023-10-09 08:54:33 +08:00
liujuping
fc31145f89 style: add style varibles and update some styles 2023-10-08 10:42:52 +08:00
iChengbo
f50410ae7a fix: some spell error 2023-10-08 10:42:16 +08:00
Rainke
e3e5123b31 fix: remove class prop 2023-09-26 17:43:57 +08:00
liujuping
5c139181b6 fix: fix workspace openEditorWindow API bugs 2023-09-26 17:42:30 +08:00
liujuping
4728484e7e feat: suport more locale config 2023-09-26 09:37:02 +08:00
iChengbo
7a40aff277 fix: make the color of the logger more highlighted 2023-09-25 15:14:19 +08:00
zsynuting
3658bac27f remove unnecessary dep 2023-09-19 15:08:09 +08:00
JackLian
3e75af171d chore(docs): publish docs 1.1.10 2023-09-19 09:33:40 +08:00
liujuping
cfc22f7ecc feat: add simulatorRender shell 2023-09-18 16:17:20 +08:00
Rainke
cf2f5c29bc
fix: do not parse props when condition is false or loop data is empty (#2477)
* fix: do not parse children props when condition is falsy

* fix: skip parsing children when loop data is empty
2023-09-14 10:32:38 +08:00
liujuping
1072ff36fb feat(workspace): add workspace.skeleton api 2023-09-13 14:12:51 +08:00
liujuping
6b14986e8f feat(config): add defaultSettingPanelProps config 2023-09-12 09:58:58 +08:00
JackLian
a560830db6 chore(docs): publish docs 1.1.9 2023-09-08 14:16:07 +08:00
刘菊萍(絮黎)
24cac48a32 docs: update loop.md 2023-09-08 14:07:28 +08:00
liujuping
4e0b2fae5d feat(hotkey): when text is selected, allow the default copy and paste behavior 2023-09-07 10:25:57 +08:00
liujuping
4507e83d7d feat(common): update designerCabinSymbol exports 2023-09-07 10:20:04 +08:00
liujuping
7ef62308d7 feat(common): update skeletonCabinSymbol exports 2023-09-07 09:27:15 +08:00
JackLian
34acd70659 chore(docs): publish docs 1.1.8 2023-09-05 15:51:01 +08:00
liujuping
70df59a2ce style(outline-pane): fix outline-pane styles 2023-09-05 15:49:10 +08:00
chenkeyao.chenkeya
4677d99127 feat: Modify the content of the article menu and add a video menu 2023-09-05 15:05:53 +08:00
liujuping
bfdc7a277b feat(workspace): fix onWindowRendererReady api 2023-09-04 13:47:34 +08:00
刘菊萍(絮黎)
2c2241ef73 Revert "fix(material): fix rendering is blocked, when the url in the asset fails to load"
This reverts commit 8b5e2b47c6668817e365b31277f2b2d6c9313cca.
2023-09-04 13:47:03 +08:00
达帅
f48c49c21f docs: Update summary.md
add material spec link
2023-09-01 10:37:55 +08:00
liujuping
1d572ccc0b style: udpate some style for multi theme 2023-08-31 17:26:30 +08:00
liujuping
a3b9d6ff48 fix(outline-pane): when dialog is dragged, the outline pane is not displayed visible state 2023-08-29 14:32:54 +08:00
liujuping
dc0cf5f62c fix: fix utils under appHelper will not be updated when props.appHelper is updated 2023-08-29 10:06:21 +08:00
liujuping
857685a3b4 feat(node): add getRGL api 2023-08-29 09:49:40 +08:00
400 changed files with 9012 additions and 5477 deletions

4
.github/CODEOWNERS vendored
View File

@ -2,7 +2,7 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence
* @liujuping @JackLian
* @liujuping @1ncounter
/modules/material-parser @akirakai
/modules/code-generator @leoyuan
/modules/code-generator @qingniaotonghua

34
.github/workflows/pre build.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Pre Build
on:
push:
paths:
- 'packages/**'
- '!packages/**.md'
pull_request:
paths:
- 'packages/**'
- '!packages/**.md'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install dependencies and setup
run: npm install && npm run setup
- name: Build
run: npm run build
- name: Check build status
run: |
if [ $? -eq 0 ]; then
echo "Build succeeded!"
else
echo "Build failed!"
exit 1
fi

53
.github/workflows/publish docs.yml vendored Normal file
View File

@ -0,0 +1,53 @@
name: Update and Publish Docs
on:
push:
branches:
- develop
paths:
- 'docs/docs/**'
workflow_dispatch:
jobs:
publish-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
ref: 'develop'
node-version: '16'
registry-url: 'https://registry.npmjs.org'
- run: cd docs && npm install
- run: |
cd docs
npm version patch
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add package.json
git commit -m "chore(docs): publish documentation"
git push
- run: cd docs && npm run build && npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Get version
id: get_version
run: echo "version=$(node -p "require('./docs/package.json').version")" >> $GITHUB_OUTPUT
comment-pr:
needs: publish-docs
runs-on: ubuntu-latest
steps:
- name: Comment on PR
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
uses: actions/github-script@v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🚀 New version has been released: ' + '${{ needs.publish-docs.outputs.version }}'
})

View File

@ -0,0 +1,30 @@
name: Publish Engine Beta
on:
push:
branches:
- 'release/[0-9]+.[0-9]+.[0-9]+-beta'
paths:
- 'packages/**'
jobs:
publish-engine:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
registry-url: 'https://registry.npmjs.org'
- run: npm install && npm run setup
- run: |
npm run build
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
- run: npm run pub:prerelease
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Get version
id: get_version
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT

33
.github/workflows/publish engine.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: Publish Engine
on:
workflow_dispatch:
inputs:
publishCommand:
description: 'publish command'
required: true
jobs:
publish-engine:
runs-on: ubuntu-latest
if: >-
contains(github.ref, 'refs/heads/release/') &&
(github.actor == '1ncounter' || github.actor == 'liujuping')
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
registry-url: 'https://registry.npmjs.org'
- run: npm install && npm run setup
- run: |
npm run build
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
- run: npm run ${{ github.event.inputs.publishCommand }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Get version
id: get_version
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT

View File

@ -105,4 +105,36 @@ jobs:
run: npm i && npm run setup:skip-build
- name: test
run: cd packages/utils && npm test
run: cd packages/utils && npm test
test-editor-core:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: install
run: npm i && npm run setup:skip-build
- name: test
run: cd packages/editor-core && npm test
test-plugin-command:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: install
run: npm i && npm run setup:skip-build
- name: test
run: cd packages/plugin-command && npm test

2
.gitignore vendored
View File

@ -108,3 +108,5 @@ typings/
# codealike
codealike.json
.node
.must.config.js

View File

@ -39,6 +39,12 @@ module.exports = {
position: 'left',
label: '文章',
},
{
type: 'doc',
docId: 'video/index',
position: 'left',
label: '视频',
},
{
type: 'doc',
docId: 'demoUsage/intro',

View File

@ -1,6 +1,6 @@
---
title: canvas - 画布 API
sidebar_position: 12
sidebar_position: 10
---
> **@types** [IPublicApiCanvas](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/canvas.ts)<br/>

101
docs/docs/api/command.md Normal file
View File

@ -0,0 +1,101 @@
---
title: command - 指令 API
sidebar_position: 10
---
## 模块概览
该模块使得与命令系统的交互成为可能,提供了一种全面的方式来处理、执行和管理应用程序中的命令。
## 接口
### IPublicApiCommand
与命令交互的接口。它提供了注册、注销、执行和管理命令的方法。
## 方法
### registerCommand
注册一个新命令及其处理函数。
```
typescriptCopy code
/**
* 注册一个新的命令及其处理程序。
* @param command {IPublicTypeCommand} - 要注册的命令。
*/
registerCommand(command: IPublicTypeCommand): void;
```
### unregisterCommand
注销一个已存在的命令。
```
typescriptCopy code
/**
* 注销一个已存在的命令。
* @param name {string} - 要注销的命令的名称。
*/
unregisterCommand(name: string): void;
```
### executeCommand
根据名称和提供的参数执行命令,确保参数符合命令的定义。
```
typescriptCopy code
/**
* 根据名称和提供的参数执行命令。
* @param name {string} - 要执行的命令的名称。
* @param args {IPublicTypeCommandHandlerArgs} - 命令的参数。
*/
executeCommand(name: string, args?: IPublicTypeCommandHandlerArgs): void;
```
### batchExecuteCommand
批量执行命令,在所有命令执行后进行重绘,历史记录中只记录一次。
```
typescriptCopy code
/**
* 批量执行命令,随后进行重绘,历史记录中只记录一次。
* @param commands {Array} - 命令对象的数组,包含名称和可选参数。
*/
batchExecuteCommand(commands: { name: string; args?: IPublicTypeCommandHandlerArgs }[]): void;
```
### listCommands
列出所有已注册的命令。
```
typescriptCopy code
/**
* 列出所有已注册的命令。
* @returns {IPublicTypeListCommand[]} - 已注册命令的数组。
*/
listCommands(): IPublicTypeListCommand[];
```
### onCommandError
为命令执行过程中的错误注册错误处理回调函数。
```
typescriptCopy code
/**
* 为命令执行过程中的错误注册一个回调函数。
* @param callback {(name: string, error: Error) => void} - 错误处理的回调函数。
*/
onCommandError(callback: (name: string, error: Error) => void): void;
```

View File

@ -1,6 +1,6 @@
---
title: common - 通用 API
sidebar_position: 11
sidebar_position: 10
---
> **@types** [IPublicApiCommon](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/common.ts)<br/>
@ -82,7 +82,7 @@ executeTransaction(fn: () => void, type: IPublicEnumTransitionType): void;
```
**@since v1.0.16**
##### 示例
**示例**
```typescript
import { common } from '@alilc/lowcode-engine';
import { IPublicEnumTransitionType } from '@alilc/lowcode-types';
@ -132,7 +132,8 @@ createIntl(instance: string | object): {
**@since v1.0.17**
##### 示例
**示例**
```typescript
import { common } from '@alilc/lowcode-engine';
import enUS from './en-US.json';
@ -145,6 +146,22 @@ const { intl, getLocale, setLocale } = common.utils.createIntl({
```
#### intl
i18n 转换方法
```typescript
/**
* i18n 转换方法
*/
intl(data: IPublicTypeI18nData | string, params?: object): string;
```
**示例**
```
const title = common.utils.intl(node.title)
```
### skeletonCabin
#### Workbench
编辑器框架 View

210
docs/docs/api/commonUI.md Normal file
View File

@ -0,0 +1,210 @@
---
title: commonUI - UI 组件库
sidebar_position: 10
---
## 简介
CommonUI API 是一个专为低代码引擎设计的组件 UI 库,使用它开发的插件,可以保证在不同项目和主题切换中能够保持一致性和兼容性。
## 组件列表
### Tip
提示组件
| 参数 | 说明 | 类型 | 默认值 |
|-----------|--------------|---------------------------------------|--------|
| className | className | string (optional) | |
| children | tip 的内容 | IPublicTypeI18nData \| ReactNode | |
| direction | tip 的方向 | 'top' \| 'bottom' \| 'left' \| 'right' | |
### HelpTip
带 help icon 的提示组件
| 参数 | 说明 | 类型 | 默认值 |
|-----------|--------|-----------------------------------|--------|
| help | 描述 | IPublicTypeHelpTipConfig | |
| direction | 方向 | IPublicTypeTipConfig['direction'] | 'top' |
| size | 方向 | IconProps['size'] | 'small'|
### Title
标题组件
| 参数 | 说明 | 类型 | 默认值 |
|-----------|------------|-----------------------------|--------|
| title | 标题内容 | IPublicTypeTitleContent | |
| className | className | string (optional) | |
| onClick | 点击事件 | () => void (optional) | |
### ContextMenu
| 参数 | 说明 | 类型 | 默认值 |
|--------|----------------------------------------------------|------------------------------------|--------|
| menus | 定义上下文菜单的动作数组 | IPublicTypeContextMenuAction[] | |
| children | 组件的子元素 | React.ReactElement[] | |
**IPublicTypeContextMenuAction Interface**
| 参数 | 说明 | 类型 | 默认值 |
|------------|--------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|----------------------------------------|
| name | 动作的唯一标识符<br/>Unique identifier for the action | string | |
| title | 显示的标题,可以是字符串或国际化数据<br/>Display title, can be a string or internationalized data | string \| IPublicTypeI18nData (optional) | |
| type | 菜单项类型<br/>Menu item type | IPublicEnumContextMenuType (optional) | IPublicEnumContextMenuType.MENU_ITEM |
| action | 点击时执行的动作,可选<br/>Action to execute on click, optional | (nodes: IPublicModelNode[]) => void (optional) | |
| items | 子菜单项或生成子节点的函数,可选,仅支持两级<br/>Sub-menu items or function to generate child node, optional | Omit<IPublicTypeContextMenuAction, 'items'>[] \| ((nodes: IPublicModelNode[]) => Omit<IPublicTypeContextMenuAction, 'items'>[]) (optional) | |
| condition | 显示条件函数<br/>Function to determine display condition | (nodes: IPublicModelNode[]) => boolean (optional) | |
| disabled | 禁用条件函数,可选<br/>Function to determine disabled condition, optional | (nodes: IPublicModelNode[]) => boolean (optional) | |
**ContextMenu 示例**
```typescript
const App = () => {
const menuItems: IPublicTypeContextMenuAction[] = [
{
name: 'a',
title: '选项 1',
action: () => console.log('选项 1 被点击'),
},
{
name: 'b',
title: '选项 2',
action: () => console.log('选项 2 被点击'),
},
];
const ContextMenu = ctx.commonUI.ContextMenu;
return (
<div>
<ContextMenu menus={menuItems}>
<div>右键点击这里</div>
</ContextMenu>
</div>
);
};
export default App;
```
**ContextMenu.create 示例**
```typescript
const App = () => {
const menuItems: IPublicTypeContextMenuAction[] = [
{
name: 'a',
title: '选项 1',
action: () => console.log('选项 1 被点击'),
},
{
name: 'b',
title: '选项 2',
action: () => console.log('选项 2 被点击'),
},
];
const ContextMenu = ctx.commonUI.ContextMenu;
return (
<div>
<div onClick={(e) => {
ContextMenu.create(menuItems, e);
}}>点击这里</div>
</div>
);
};
export default App;
```
### Balloon
详细文档: [Balloon Documentation](https://fusion.design/pc/component/balloon)
### Breadcrumb
详细文档: [Breadcrumb Documentation](https://fusion.design/pc/component/breadcrumb)
### Button
详细文档: [Button Documentation](https://fusion.design/pc/component/button)
### Card
详细文档:[Card Documentation](https://fusion.design/pc/component/card)
### Checkbox
详细文档:[Checkbox Documentation](https://fusion.design/pc/component/checkbox)
### DatePicker
详细文档:[DatePicker Documentation](https://fusion.design/pc/component/datepicker)
### Dialog
详细文档:[Dialog Documentation](https://fusion.design/pc/component/dialog)
### Dropdown
详细文档:[Dropdown Documentation](https://fusion.design/pc/component/dropdown)
### Form
详细文档:[Form Documentation](https://fusion.design/pc/component/form)
### Icon
详细文档:[Icon Documentation](https://fusion.design/pc/component/icon)
引擎默认主题支持的 icon 列表https://fusion.design/64063/component/icon?themeid=20133
### Input
详细文档:[Input Documentation](https://fusion.design/pc/component/input)
### Loading
详细文档:[Loading Documentation](https://fusion.design/pc/component/loading)
### Message
详细文档:[Message Documentation](https://fusion.design/pc/component/message)
### Overlay
详细文档:[Overlay Documentation](https://fusion.design/pc/component/overlay)
### Pagination
详细文档:[Pagination Documentation](https://fusion.design/pc/component/pagination)
### Radio
详细文档:[Radio Documentation](https://fusion.design/pc/component/radio)
### Search
详细文档:[Search Documentation](https://fusion.design/pc/component/search)
### Select
详细文档:[Select Documentation](https://fusion.design/pc/component/select)
### SplitButton
详细文档:[SplitButton Documentation](https://fusion.design/pc/component/splitbutton)
### Step
详细文档:[Step Documentation](https://fusion.design/pc/component/step)
### Switch
详细文档:[Switch Documentation](https://fusion.design/pc/component/switch)
### Tab
详细文档:[Tab Documentation](https://fusion.design/pc/component/tab)
### Table
详细文档:[Table Documentation](https://fusion.design/pc/component/table)
### Tree
详细文档:[Tree Documentation](https://fusion.design/pc/component/tree)
### TreeSelect
详细文档:[TreeSelect Documentation](https://fusion.design/pc/component/treeselect)
### Upload
详细文档:[Upload Documentation](https://fusion.design/pc/component/upload)
### Divider
详细文档:[Divider Documentation](https://fusion.design/pc/component/divider)
## 说明
如果需要其他组件,可以提 issue 给我们。

View File

@ -1,6 +1,6 @@
---
title: config - 配置 API
sidebar_position: 8
sidebar_position: 5
---
> **@types** [IPublicModelEngineConfig](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/engine-config.ts)<br/>
@ -24,7 +24,7 @@ sidebar_position: 8
*/
get(key: string, defaultValue?: any): any;
```
#### 示例
**示例**
```typescript
import { config } from '@alilc/lowcode-engine';
@ -43,7 +43,7 @@ config.get('keyB', { a: 1 });
*/
set(key: string, value: any): void;
```
#### 示例
**示例**
```typescript
import { config } from '@alilc/lowcode-engine';
@ -63,7 +63,7 @@ config.set('keyC', 1);
has(key: string): boolean;
```
#### 示例
**示例**
```typescript
import { config } from '@alilc/lowcode-engine';
@ -81,7 +81,7 @@ config.has('keyD');
*/
setConfig(config: { [key: string]: any }): void;
```
#### 示例
**示例**
```typescript
import { config } from '@alilc/lowcode-engine';
@ -134,7 +134,7 @@ config.getPreference().set(`${panelName}-pinned-status-isFloat`, false, 'skeleto
*/
onceGot(key: string): Promise<any>;
```
#### 示例
**示例**
```typescript
import { config } from '@alilc/lowcode-engine';
@ -160,7 +160,7 @@ const value = await config.onceGot('keyA');
*/
onGot(key: string, fn: (data: any) => void): () => void;
```
#### 示例
**示例**
```typescript
import { config } from '@alilc/lowcode-engine';

View File

@ -1,6 +1,6 @@
---
title: config options - 配置列表
sidebar_position: 13
sidebar_position: 5
---
> **@types** [IPublicTypeEngineOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/engine-options.ts)<br/>
@ -113,7 +113,7 @@ config.set('enableCondition', false)
类型定义
```typescript
focusNodeSelector?: (rootNode: Node) => Node;
focusNodeSelector?: (rootNode: IPublicModelNode) => Node;
```
#### supportVariableGlobally - 全局变量配置
@ -185,6 +185,12 @@ config.set('enableCondition', false)
`@type {boolean}` `@default {false}`
#### enableContextMenu - 开启右键菜单
`@type {boolean}` `@default {false}`
是否开启右键菜单
#### disableDetecting
`@type {boolean}` `@default {false}`
@ -216,6 +222,12 @@ config.set('enableCondition', false)
是否在只有一个 item 的时候隐藏设置 tabs
#### hideComponentAction
`@type {boolean}` `@default {false}`
隐藏设计器辅助层
#### thisRequiredInJSE
`@type {boolean}` `@default {true}`
@ -254,6 +266,16 @@ JSExpression 是否只支持使用 this 来访问上下文变量,假如需要
自定义 loading 组件
### 插件
#### defaultSettingPanelProps
内置设置面板插件的 panelProps
#### defaultOutlinePaneProps
内置大纲树面板插件的 panelProps
### 其他
#### enableStrictPluginMode
@ -282,4 +304,3 @@ customPluginTransducer: async (originPlugin: IPublicTypePlugin, ctx: IPublicMode
大纲树插件面板默认 props

View File

@ -1,6 +1,6 @@
---
title: event - 事件 API
sidebar_position: 7
sidebar_position: 10
---
> **@types** [IPublicApiEvent](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/event.ts)<br/>

View File

@ -1,6 +1,6 @@
---
title: hotkey - 快捷键 API
sidebar_position: 5
sidebar_position: 10
---
> **@types** [IPublicApiHotkey](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/hotkey.ts)<br/>

View File

@ -1,6 +1,6 @@
---
title: init - 初始化 API
sidebar_position: 10
sidebar_position: 0
---
> **@since** v1.0.0

View File

@ -1,6 +1,6 @@
---
title: logger - 日志 API
sidebar_position: 9
sidebar_position: 10
---
> **@types** [IPublicApiLogger](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/logger.ts)<br/>

View File

@ -1,6 +1,6 @@
---
title: material - 物料 API
sidebar_position: 2
sidebar_position: 10
---
> **@types** [IPublicApiMaterial](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/material.ts)<br/>
@ -39,7 +39,7 @@ setAssets(assets: IPublicTypeAssetsJson): void;
相关类型:[IPublicTypeAssetsJson](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/assets-json.ts)
##### 示例
**示例**
直接在项目中引用 npm 包
```javascript
import { material } from '@alilc/lowcode-engine';
@ -85,7 +85,7 @@ getAssets(): IPublicTypeAssetsJson;
相关类型:[IPublicTypeAssetsJson](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/assets-json.ts)
##### 示例
**示例**
```typescript
import { material } from '@alilc/lowcode-engine';
@ -106,7 +106,7 @@ loadIncrementalAssets(incrementalAssets: IPublicTypeAssetsJson): Promise<void>;
```
相关类型:[IPublicTypeAssetsJson](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/assets-json.ts)
##### 示例
**示例**
```typescript
import { material } from '@alilc/lowcode-engine';
import assets1 from '@alilc/mc-assets-<siteId>/assets.json';
@ -116,6 +116,21 @@ material.setAssets(assets1);
material.loadIncrementalAssets(assets2);
```
更新特定物料的描述文件
```typescript
import { material } from '@alilc/lowcode-engine';
material.loadIncrementalAssets({
version: '',
components: [
{
"componentName": 'Button',
"props": [{ name: 'new', title: 'new', propType: 'string' }]
}
],
})
```
### 设计器辅助层
#### addBuiltinComponentAction
在设计器辅助层增加一个扩展 action
@ -131,7 +146,7 @@ addBuiltinComponentAction(action: IPublicTypeComponentAction): void;
相关类型:[IPublicTypeComponentAction](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/component-action.ts)
##### 示例
**示例**
新增设计扩展位,并绑定事件
```typescript
import { material } from '@alilc/lowcode-engine';
@ -171,7 +186,7 @@ removeBuiltinComponentAction(name: string): void;
- lock锁定不可编辑
- unlock解锁可编辑
##### 示例
**示例**
```typescript
import { material } from '@alilc/lowcode-engine';
@ -207,7 +222,7 @@ modifyBuiltinComponentAction(
##### 示例
**示例**
给原始的 remove 扩展时间添加执行前后的日志
```typescript
import { material } from '@alilc/lowcode-engine';
@ -222,7 +237,90 @@ material.modifyBuiltinComponentAction('remove', (action) => {
});
```
### 右键菜单项
#### addContextMenuOption
添加右键菜单项
```typescript
/**
* 添加右键菜单项
* @param action
*/
addContextMenuOption(action: IPublicTypeContextMenuAction): void;
```
示例
```typescript
import { IPublicEnumContextMenuType } from '@alilc/lowcode-types';
material.addContextMenuOption({
name: 'parentItem',
title: 'Parent Item',
condition: (nodes) => true,
items: [
{
name: 'childItem1',
title: 'Child Item 1',
action: (nodes) => console.log('Child Item 1 clicked', nodes),
condition: (nodes) => true
},
// 分割线
{
type: IPublicEnumContextMenuType.SEPARATOR
name: 'separator.1'
}
// 更多子菜单项...
]
});
```
#### removeContextMenuOption
删除特定右键菜单项
```typescript
/**
* 删除特定右键菜单项
* @param name
*/
removeContextMenuOption(name: string): void;
```
#### adjustContextMenuLayout
调整右键菜单项布局,每次调用都会覆盖之前注册的调整函数,只有最后注册的函数会被应用。
```typescript
/**
* 调整右键菜单项布局
* @param actions
*/
adjustContextMenuLayout(fn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[]): void;
```
**示例**
通过 adjustContextMenuLayout 补充分割线
```typescript
material.adjustContextMenuLayout((actions: IPublicTypeContextMenuAction) => {
const names = ['a', 'b'];
const newActions = [];
actions.forEach(d => {
newActions.push(d);
if (names.include(d.name)) {
newActions.push({ type: 'separator' })
}
});
return newActions
})
```
### 物料元数据
#### getComponentMeta
获取指定名称的物料元数据
@ -237,7 +335,7 @@ getComponentMeta(componentName: string): IPublicModelComponentMeta | null;
```
相关类型:[IPublicModelComponentMeta](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/component-meta.ts)
##### 示例
**示例**
```typescript
import { material } from '@alilc/lowcode-engine';
@ -258,7 +356,7 @@ material.getComponentMeta('Input');
```
相关类型:[IPublicModelComponentMeta](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/component-meta.ts)
##### 示例
**示例**
```typescript
import { material } from '@alilc/lowcode-engine';
@ -295,7 +393,7 @@ registerMetadataTransducer(
): void;
```
##### 示例
**示例**
给每一个组件的配置添加高级配置面板,其中有一个是否渲染配置项
```typescript
import { material } from '@alilc/lowcode-engine'
@ -340,6 +438,31 @@ function addonCombine(metadata: TransformedComponentMetadata) {
material.registerMetadataTransducer(addonCombine, 1, 'parse-func');
```
删除高级 Tab
```typescript
import { material } from '@alilc/lowcode-engine';
import { IPublicTypeFieldConfig } from '@alilc/lowcode-types';
material.registerMetadataTransducer((transducer) => {
const combined: IPublicTypeFieldConfig[] = [];
transducer.configure.combined?.forEach(d => {
if (d.name !== '#advanced') {
combined.push(d);
}
});
return {
...transducer,
configure: {
...transducer.configure,
combined,
}
};
}, 111, 'parse-func');
```
#### getRegisteredMetadataTransducers
获取所有物料元数据管道函数
@ -352,7 +475,7 @@ material.registerMetadataTransducer(addonCombine, 1, 'parse-func');
getRegisteredMetadataTransducers(): IPublicTypeMetadataTransducer[];
```
##### 示例
**示例**
```typescript
import { material } from '@alilc/lowcode-engine'
@ -373,7 +496,7 @@ onChangeAssets(fn: () => void): IPublicTypeDisposable;
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
##### 示例
**示例**
```typescript
import { material } from '@alilc/lowcode-engine';

View File

@ -1,6 +1,6 @@
{
"label": "模型定义 Models",
"position": 14,
"position": 100,
"collapsed": false,
"collapsible": true
}

View File

@ -101,7 +101,7 @@ from(shell: Element, boost: (e: MouseEvent) => IPublicTypeDragNodeDataObject | n
* @param dragObject 拖拽对象
* @param boostEvent 拖拽初始时事件
*/
boost(dragObject: IPublicTypeDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: Node | IPublicModelNode): void;
boost(dragObject: IPublicTypeDragObject, boostEvent: MouseEvent | DragEvent, fromRglNode?: IPublicModelNode): void;
```
### addSensor

View File

@ -71,7 +71,7 @@ hideModalNodes(): void;
/**
* 设置指定节点为可见态
* set specific model node as visible
* @param node Node
* @param node IPublicModelNode
*/
setVisible(node: IPublicModelNode): void;
```
@ -86,7 +86,7 @@ setVisible(node: IPublicModelNode): void;
/**
* 设置指定节点为不可见态
* set specific model node as invisible
* @param node Node
* @param node IPublicModelNode
*/
setInvisible(node: IPublicModelNode): void;
```

View File

@ -657,4 +657,22 @@ setConditionalVisible(): void;
*/
getDOMNode(): HTMLElement;
```
### getRGL
获取磁贴相关信息
```typescript
/**
* 获取磁贴相关信息
*/
getRGL(): {
isContainerNode: boolean;
isEmptyNode: boolean;
isRGLContainerNode: boolean;
isRGLNode: boolean;
isRGL: boolean;
rglNode: IPublicModelNode | null;
}
```

View File

@ -15,6 +15,12 @@ sidebar_position: 13
`@type {string}`
### id
资源 id
`@type {string}`
### name
资源名字
@ -44,3 +50,9 @@ sidebar_position: 13
资源配置信息
`@type {Object}`
### config
资源配置信息
`@type {Object}`

View File

@ -0,0 +1,38 @@
---
title: SimulatorRender
sidebar_position: 6
---
> **@types** [IPublicModelSimulatorRender](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/model/simulator-render.ts)<br/>
> **@since** v1.0.0
## 基本介绍
画布节点选中模型
## 属性
### components
画布组件列表
```typescript
/**
* 画布组件列表
*/
components: {
[key: string]: any;
}
```
## 方法
### rerender
触发画布重新渲染
```typescript
/**
* 触发画布重新渲染
*/
rerender: () => void;
```

View File

@ -1,6 +1,6 @@
---
title: plugins - 插件 API
sidebar_position: 4
sidebar_position: 2
---
> **@types** [IPublicApiPlugins](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/plugins.ts)<br/>
> **@since** v1.0.0

View File

@ -1,6 +1,6 @@
---
title: project - 模型 API
sidebar_position: 3
sidebar_position: 10
---
## 模块简介
@ -201,7 +201,7 @@ addPropsTransducer(
- [IPublicTypePropsTransducer](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/props-transducer.ts)
- [IPublicEnumTransformStage](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/enum/transform-stage.ts)
#### 示例
**示例**
在保存的时候删除每一个组件的 props.hidden
```typescript
import { project } from '@alilc/lowcode-engine';

View File

@ -1,6 +1,6 @@
---
title: setters - 设置器 API
sidebar_position: 6
sidebar_position: 10
---
> **@types** [IPublicApiSetters](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/setters.ts)<br/>
> **@since** v1.0.0

View File

@ -1,6 +1,6 @@
---
title: simulatorHost - 模拟器 API
sidebar_position: 3
sidebar_position: 10
---
> **@types** [IPublicApiSimulatorHost](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/simulator-host.ts)<br/>
> **@since** v1.0.0
@ -20,7 +20,7 @@ sidebar_position: 3
*/
set(key: string, value: any): void;
```
#### 示例
**示例**
设置若干用于画布渲染的变量比如画布大小、locale 等。
以设置画布大小为例:
@ -50,11 +50,11 @@ get(key: string): any;
```
### rerender
刷新渲染画布
触发组件构建,并刷新渲染画布
```typescript
/**
* 刷新渲染画布
* 触发组件构建,并刷新渲染画布
* make simulator render again
*/
rerender(): void;

View File

@ -1,6 +1,6 @@
---
title: skeleton - 面板 API
sidebar_position: 1
sidebar_position: 10
---
> **@types** [IPublicApiSkeleton](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/api/skeleton.ts)<br/>
> **@since** v1.0.0
@ -69,6 +69,7 @@ skeleton.add({
props: {
align: "left",
icon: "wenjian",
title: '标题', // 图标下方展示的标题
description: "JS 面板",
},
panelProps: {
@ -295,6 +296,85 @@ showArea(areaName: string): void;
*/
hideArea(areaName: string): void;
```
### getAreaItems
获取某个区域下的所有面板实例
```typescript
/**
* 获取某个区域下的所有面板实例
* @param areaName IPublicTypeWidgetConfigArea
*/
getAreaItems(areaName: IPublicTypeWidgetConfigArea): IPublicModelSkeletonItem[] | undefined;
```
相关类型:[IPublicModelSkeletonItem](https://github.com/alibaba/lowcode-engine/blob/main/packages/shell/src/model/skeleton-item.ts)
### registerConfigTransducer
注册一个面板的配置转换器transducer
```typescript
/**
* 注册一个面板的配置转换器transducer
* Registers a configuration transducer for a panel.
* @param {IPublicTypeConfigTransducer} transducer
* - 要注册的转换器函数。该函数接受一个配置对象(类型为 IPublicTypeSkeletonConfig作为输入并返回修改后的配置对象。
* - The transducer function to be registered. This function takes a configuration object
*
* @param {number} level
* - 转换器的优先级。优先级较高的转换器会先执行。
* - The priority level of the transducer. Transducers with higher priority levels are executed first.
*
* @param {string} [id]
* - (可选)转换器的唯一标识符。用于在需要时引用或操作特定的转换器。
* - (Optional) A unique identifier for the transducer. Used for referencing or manipulating a specific transducer when needed.
*/
registerConfigTransducer(transducer: IPublicTypeConfigTransducer, level: number, id?: string): void;
```
使用示例
```typescript
import { IPublicModelPluginContext, IPublicTypeSkeletonConfig } from '@alilc/lowcode-types';
function updatePanelWidth(config: IPublicTypeSkeletonConfig) {
if (config.type === 'PanelDock') {
return {
...config,
panelProps: {
...(config.panelProps || {}),
width: 240,
},
}
}
return config;
}
const controlPanelWidthPlugin = (ctx: IPublicModelPluginContext) => {
const { skeleton } = ctx;
(skeleton as any).registerConfigTransducer?.(updatePanelWidth, 1, 'update-panel-width');
return {
init() {},
};
};
controlPanelWidthPlugin.pluginName = 'controlPanelWidthPlugin';
controlPanelWidthPlugin.meta = {
dependencies: [],
engines: {
lowcodeEngine: '^1.2.3', // 插件需要配合 ^1.0.0 的引擎才可运行
},
};
export default controlPanelWidthPlugin;
```
## 事件
### onShowPanel
@ -307,7 +387,7 @@ hideArea(areaName: string): void;
* @param listener
* @returns
*/
onShowPanel(listener: (...args: any[]) => void): IPublicTypeDisposable;
onShowPanel(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;
```
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
@ -323,11 +403,38 @@ onShowPanel(listener: (...args: any[]) => void): IPublicTypeDisposable;
* @param listener
* @returns
*/
onHidePanel(listener: (...args: any[]) => void): IPublicTypeDisposable;
onHidePanel(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;
```
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
### onDisableWidget
监听 Widget 实例 Disable 事件
```typescript
/**
* 监听 Widget 实例 Disable 事件
* @param listener
*/
onDisableWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;
```
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
### onEnableWidget
监听 Widget 实例 Enable 事件
```typescript
/**
* 监听 Widget 实例 Enable 事件
* @param listener
*/
onEnableWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;
```
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
### onShowWidget
@ -340,7 +447,7 @@ onHidePanel(listener: (...args: any[]) => void): IPublicTypeDisposable;
* @param listener
* @returns
*/
onShowWidget(listener: (...args: any[]) => void): IPublicTypeDisposable;
onShowWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;
```
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)
@ -356,7 +463,7 @@ onShowWidget(listener: (...args: any[]) => void): IPublicTypeDisposable;
* @param listener
* @returns
*/
onHideWidget(listener: (...args: any[]) => void): IPublicTypeDisposable;
onHideWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;
```
相关类型:[IPublicTypeDisposable](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/disposable.ts)

View File

@ -1,6 +1,6 @@
---
title: workspace - 应用级 API
sidebar_position: 12
sidebar_position: 10
---
> **[@experimental](./#experimental)**<br/>
@ -37,6 +37,16 @@ get plugins(): IPublicApiPlugins
关联模型 [IPublicApiPlugins](./plugins)
### skeleton
应用级别的面板管理
```typescript
get skeleton(): IPublicApiSkeleton
```
关联模型 [IPublicApiSkeleton](./skeleton)
### windows
当前设计器的编辑窗口
@ -77,7 +87,7 @@ registerResourceType(resourceTypeModel: IPublicTypeResourceType): void;
setResourceList(resourceList: IPublicResourceList) {}
```
相关类型:[IPublicResourceOptions](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/resource-options.ts)
相关类型:[IPublicResourceData](https://github.com/alibaba/lowcode-engine/blob/main/packages/types/src/shell/type/resource-list.ts)
### openEditorWindow

View File

@ -1,41 +1,15 @@
---
title: 低代码引擎相关文章资料
---
## 官方文章
# 官方文章
- [2023/11/09 UIPaaS | 基于 LowCodeEngine 的低代码平台孵化器](https://mp.weixin.qq.com/s/mKuv3_Wvgt5T3AGErUGBQQ)
- [2023/04/04 什么?低代码引擎可以开发应用了](https://mp.weixin.qq.com/s/dwi40gJjGBHW9MVpag5Oxg)
- [2023/03/23 低代码引擎 LowCodeEngine 茁壮成长的一年](https://mp.weixin.qq.com/s/DDt4LQLFUBQ2-F5ehZGBKg)
- [2023/02/21 基于 LowCodeEngine 的低代码组件体系的建设和实践](https://mp.weixin.qq.com/s/rnvbGHImGt6oJuX2wCtaqw)
- [2022/12/21 低代码多分支协同开发的建设与实践](https://mp.weixin.qq.com/s/DmwxL67htHfTUP1U966N-Q)
- [2022/11/24 低代码引擎半岁啦,来跟大家唠唠嗑...](https://segmentfault.com/a/1190000042884409)
- [2022/10/27 低代码技术在研发团队的应用模式探讨](https://mp.weixin.qq.com/s/Ynk_wjJbmNw7fEG6UtGZbQ)
- [2022/08/23 基于 LowCodeEngine 的调试能力建设与实践](https://mp.weixin.qq.com/s/H8KvEOylmzLPgIuuBO0S9w)
- [2022/06/23 低代码渲染那些事](https://mp.weixin.qq.com/s/yqYey76qLGYPfDtpGkVFfA)
- [2022/06/16 关于 LowCode&ProCode 混合研发的思考](https://mp.weixin.qq.com/s/TY3VXjkSmsQoT47xma3wig)
- [2022/04/07 磁贴布局在钉钉宜搭报表设计引擎中的实现](https://mp.weixin.qq.com/s/PSTut5ahAB8nlJ9kBpBaxw)
- [2022/03/23 阿里低代码引擎 LowCodeEngine 正式开源!](https://mp.weixin.qq.com/s/T66LghtWLz2Oh048XqaniA)
- [2022/01/10 阿里低代码引擎和生态建设实战及思考](https://mp.weixin.qq.com/s/MI6MrUKKydtnSdO4xq6jwA)
- [2021/04/14 2B 领域下的低代码探索之路](https://mp.weixin.qq.com/s/HAxrMHLT43dPH488RiEIdw)
## Portal 设计项目实战
#### 直播回放
[https://www.bilibili.com/video/BV1AS4y1K7DP/](https://www.bilibili.com/video/BV1AS4y1K7DP/)
#### 示例项目
- 前端: [https://github.com/mark-ck/lowcode-portal](https://github.com/mark-ck/lowcode-portal)
- 后端: [https://github.com/mark-ck/document-solution-site](https://github.com/mark-ck/document-solution-site)
- 组件库:[https://github.com/mark-ck/portal-components](https://github.com/mark-ck/portal-components)
**注意**
1. 前端项目要把代码里请求接口的域名改成本地或者自己的域名;
2. 后端项目要把 config.default.js 里的 yuque 和 oss 配置补全;
#### 视频链接
- [阿里低代码引擎项目实战 (1)-引擎 demo 部署到 faas 服务](https://www.bilibili.com/video/BV1B44y1P7GM/)
- [【有翻车】阿里低代码引擎项目实战 (2)-保存页面到远端存储](https://www.bilibili.com/video/BV1AS4y1K7DP/)
- [阿里巴巴低代码引擎项目实战 (3)-自定义组件接入](https://www.bilibili.com/video/BV1dZ4y1m76S/)
- [阿里低代码引擎项目实战 (4)-自定义插件 - 页面管理](https://www.bilibili.com/video/BV17a411i73f/)
- [阿里低代码引擎项目实战 (4)-用户登录](https://www.bilibili.com/video/BV1Wu411e7EQ/)
- [【有翻车】阿里低代码引擎项目实战 (5)-表单回显](https://www.bilibili.com/video/BV1UY4y1v7D7/)
- [阿里低代码引擎项目实战 (6)-自定义插件 - 页面管理 - 后端](https://www.bilibili.com/video/BV1uZ4y1U7Ly/)
- [阿里低代码引擎项目实战 (6)-自定义插件 - 页面管理 - 前端](https://www.bilibili.com/video/BV1Yq4y1a74P/)
- [阿里低代码引擎项目实战 (7)-自定义插件 - 页面管理 (完结)](https://www.bilibili.com/video/BV13Y4y1e7EV/)

View File

@ -15,3 +15,14 @@ sidebar_position: 0
![image.png](https://img.alicdn.com/imgextra/i4/O1CN01XQfnYL1P4wxn01oXv_!!6000000001788-2-tps-3840-1896.png)
this.index 是当前循环的索引值。
3.在事件绑定函数中使用
在事件绑定函数中使用扩展参数设置
![image](https://github.com/alibaba/lowcode-engine/assets/11935995/7274506e-decd-497a-b07f-c95941a706b4)
绑定之后在函数中使用
![image](https://github.com/alibaba/lowcode-engine/assets/11935995/9d52ee5c-9959-4991-91be-9391e639bb7e)
按钮点击效果
![image](https://github.com/alibaba/lowcode-engine/assets/11935995/6ca590c9-1f5f-4d48-94a5-439130a22e92)

View File

@ -2,6 +2,8 @@
title: 3. 如何通过按钮展示/隐藏弹窗
sidebar_position: 1
---
> 说明:这个方式依赖低代码弹窗组件是否对外保留了相关的 API不同的物料支持的方式不一样这里只针对综合场景的弹窗物料。
## 1.拖拽一个按钮
![image.png](https://img.alicdn.com/imgextra/i1/O1CN01kLaWA31D6WwTui9VW_!!6000000000167-2-tps-3584-1812.png)

31
docs/docs/faq/faq023.md Normal file
View File

@ -0,0 +1,31 @@
---
title: Slot组件渲染报错问题
sidebar_position: 23
tags: [FAQ]
---
## 问题描述
在低代码引擎的页面渲染过程中可能会遇到一个关于Slot组件的报错提示“Slot找不到”。实际上在渲染态时不应使用Slot组件。
## 问题原因
低代码引擎渲染分为两个状态:设计态和渲染态。
- **设计态**为了帮助插槽进行可视化设计引入了Slot组件。
- **渲染态**在此状态下不需要使用Slot组件。
这个问题通常是因为在渲染态错误地使用了设计态的schema。
## 解决方案
1. **区分设计态和渲染态**:通过`project.exportSchema(TransformStage.Save)`的参数来区分。
- `TransformStage.Save`代表渲染态的schema其中不包含Slot组件。
- 【默认值】`TransformStage.Render`代表设计态的schema其中包含Slot组件。
2. **使用正确的API和参数**确保在渲染态使用正确的schema避免引用设计态的Slot组件。
3. **处理脏数据问题**:如果问题是由脏数据导致,清除数据并重新拖拽组件以恢复正常。
## 注意事项
- 确保在代码和配置中正确区分设计态和渲染态。
- 如果遇到持续的问题,检查是否有脏数据或配置错误,并进行相应的清理和调整。
## 相关链接
- Issue链接[Issue #1798](https://github.com/alibaba/lowcode-engine/issues/1798)
---

133
docs/docs/faq/faq024.md Normal file
View File

@ -0,0 +1,133 @@
---
title: workspace 模式常见问题
sidebar_position: 23
tags: [FAQ]
---
#### 如何判断是否开启了IDE模式
- **通过官方API判断**:您可以通过访问 [workspace.isActive](/site/docs/api/workspace#isactive) 来判断当前是否处于IDE模式。这是阿里低代码引擎提供的一个官方API专门用于确认是否处于集成开发环境。
#### 如何使用插件的ctx来做判断在哪个模式下
- **插件是否为应用级别**:可以通过 **ctx.isPluginRegisteredInWorkspace** 方法来判断一个插件是否是应用级别的插件。这有助于理解插件在阿里低代码引擎中的作用域和潜在的使用场景。
- **插件的注册级别**:您可以使用 **ctx.registerLevel** 属性来判断插件处于哪个级别。插件级别的值包括:
- **Default**:默认级别。非 IDE 模式下的值
- **Workspace**:应用级别。
- **Resource**:资源级别。
- **EditorView**:编辑视图级别。 这些级别代表了插件可能的作用域和使用场景,有助于在开发和管理低代码应用时对插件进行更精确的控制和配置。
#### 如何在IDE模式下设置资源列表
- **设置资源列表API**在IDE模式下可以通过访问 [workspace.setResourceList](/site/docs/api/workspace#setresourcelist) 来设置或更新IDE中的资源列表。这确保您在编辑器窗口中打开的资源是最新且可访问的。
#### 如何打开视图窗口?
- **使用推荐的方法**:使用 `openEditorWindow(resource: Resource, sleep?: boolean): Promise<void>;` 来打开视图窗口。这里的 **resource** 参数指的是您要打开的特定资源,可通过 [workspace.resourceList](/site/docs/api/workspace#resourcelist) 获取。
- **不推荐使用的过时方法**:有一个过时的方法 `openEditorWindow(resourceName: string, id: string, extra: Object, viewName?: string, sleep?: boolean): Promise<void>;` 也用于打开视图窗口。虽然仍然可用,但官方不推荐使用此方法,并计划在后续版本中废弃,因为它在维护和可扩展性方面存在限制。
#### 如何在全局插件中获取视图的上下文?
- 在阿里低代码引擎的全局插件中获取视图的上下文,可以通过使用 **ProvideViewPluginContext** 函数实现。这个函数来自 **@alilc/lowcode-utils** 库,它使得您的 React 组件能够接收 **pluginContext** 作为 props进而访问和操作当前视图的状态和属性。
**步骤**
**引入依赖**:首先,确保您的插件文件中已经引入了 **ProvideViewPluginContext** 以及其他必要的依赖。
```
import { ProvideViewPluginContext } from '@alilc/lowcode-utils';
```
**定义 React 组件**:创建一个 React 组件,它将使用来自 **ProvideViewPluginContext****pluginContext**
```typescript
const MyComponent = (props) => {
const { pluginContext } = props;
// 组件逻辑
return <div>/* 组件内容 */</div>;
};
```
**定义全局插件**:定义一个函数,这个函数会在插件被注册时调用。这个函数通常接受一个上下文对象 **ctx**,它提供了对引擎功能的访问。
```javascript
const globalPlugin = (ctx) => {
const { skeleton } = ctx;
skeleton.add({
type: 'PanelDock',
name: 'datapool',
content: ProvideViewPluginContext((props) => {
// 组件内容
return (
<MyComponent {...props} />
)
}),
// 其他配置
contentProps: {
// 需要提供 pluginContext 作为参数
pluginContext: ctx,
}
});
};
```
通过这些步骤,您的全局插件中的 React 组件就能够获取并使用视图的上下文了。这为您在插件中实现更复杂的功能和交互提供了基础。
**注意事项**
- **组件重渲染**:正常情况下,**pluginsContext** 是视图的上下文。当视图切换时,组件会重新渲染。如果需要在组件中处理视图切换导致的重新渲染,可以利用 React 的 **key** 属性。
**示例代码**
```typescript
ProvideViewPluginContext(props => {
return (
<DataPoolPane
{...props}
key={props.pluginContext?.editorWindow?.id}
);
});
```
通过这种方式,当视图切换时,组件会根据视图的不同进行重新渲染,确保组件状态与当前视图的上下文保持一致。这对于在低代码平台上开发复杂插件和交互功能是非常有用的。
#### 如何判断插件是否在 Workspace 模式下注册?
**使用** **ctx.isPluginRegisteredInWorkspace()** **方法**:
通过 **ctx.isPluginRegisteredInWorkspace()** 方法,可以判断一个插件是否在 Workspace 级别注册。以下是一个示例代码片段:
```javascript
if (ctx.isPluginRegisteredInWorkspace('pluginName')) {
console.log('插件已在 Workspace 模式下注册。');
} else {
console.log('插件未在 Workspace 模式下注册。');
}
```
注意:此方法目前在 beta 版本中,可能会有 TypeScript 提示显示已移除。
**检查** **ctx.registerLevel** **的值**:
可以通过比较 **ctx.registerLevel** 的值来判断插件的注册级别。示例代码如下:
```javascript
if (ctx.registerLevel !== IPublicEnumPluginRegisterLevel.Workspace) {
console.log('插件未在 Workspace 模式下注册。');
} else {
console.log('插件已在 Workspace 模式下注册。');
}
```

View File

@ -1,7 +1,47 @@
---
title: FAQ 概述
sidebar_position: 1
sidebar_position: -1
tags: [FAQ]
---
不定期将社区常见问题及答案维护到此处
不定期将社区常见问题及答案维护到此处
## Demo 使用
- [渲染唯一标识key](/site/docs/faq/faq002)
- [点击事件如何添加参数](/site/docs/faq/faq003)
- [如何通过 API 手动调用数据源请求](/site/docs/faq/faq006)
## 设计器定制
- [如何通过 this.utils 使用第三方工具扩展](/site/docs/faq/faq005)
- [设置面板中的高级 tab 如何配置](/site/docs/faq/faq007)
- [插件面板如何调整位置](/site/docs/faq/faq010)
- [workspace 模式常见问题](/site/docs/faq/faq024)
## 源码和依赖
- [某某 npm 包对应的源码在哪里?](/site/docs/faq/faq008)
## 错误和报错
- [物料出现 Component Not Found 相关报错](/site/docs/faq/faq009)
- [VERSION_PLACEHOLDER is not defined](/site/docs/faq/faq014)
- [Cannot read property 'Icon' of Undefined](/site/docs/faq/faq016)
- [windows 下运行低代码引擎源码出现报错](/site/docs/faq/faq019)
- [Can't import the named export from non ECMAScript module](/site/docs/faq/faq020)
- [Slot组件渲染报错问题](/site/docs/faq/faq023)
## 物料相关问题
- [如何获取物料当前处于编辑态还是渲染态](/site/docs/faq/faq011)
- [Procode 物料如何调用数据源方法](/site/docs/faq/faq012)
- [已有组件如何快速接入引擎](/site/docs/faq/faq015)
- [Modal 类组件 hidden 属性被强制设置 true](/site/docs/faq/faq013)
- [最小渲染单元配置](/site/docs/faq/faq004)
- [节点无法拖拽到 Page 下](/site/docs/faq/faq022)
## 其他说明
- [vue 画布支持说明](/site/docs/faq/faq017)
- [是否可以生成 Vue 页面代码?](/site/docs/faq/faq018)
## 参与贡献
- [提交 PR 时,明明签署过 CLA仍被提示需要签署](/site/docs/faq/faq021)
## 相关依赖文档
- [build-scripts 的使用文档](/site/docs/faq/faq001)

View File

@ -12,8 +12,6 @@ sidebar_position: 3
| @alilc/lowcode-engine | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/engine |
| @alilc/lowcode-plugin-designer | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/plugin-designer |
| @alilc/lowcode-plugin-outline-pane | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/plugin-outline-pane |
| @alilc/lowcode-rax-renderer | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/rax-renderer |
| @alilc/lowcode-rax-simulator-renderer | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/rax-simulator-renderer |
| @alilc/lowcode-react-renderer | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/react-renderer |
| @alilc/lowcode-react-simulator-renderer | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/react-simulator-renderer |
| @alilc/lowcode-renderer-core | [https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) | packages/renderer-core |

View File

@ -15,15 +15,13 @@ sidebar_position: 2
5. ignitor
6. plugin-designer
7. plugin-outline-pane
8. rax-renderer
9. rax-simulator-renderer
10. react-renderer
11. react-simulator-renderer
12. renderer-core
13. types
14. utils
15. material-parser
16. code-generator
8. react-renderer
9. react-simulator-renderer
10. renderer-core
11. types
12. utils
13. material-parser
14. code-generator
## 2. 引擎官方扩展包
包含了常用的设置器setter、跟 setter 绑定的插件等

View File

@ -105,8 +105,6 @@ sidebar_position: 0
### 初始化低代码编辑器
#### 方法 2.1 使用 init 进行初始化
正确引入后,我们可以直接通过 window 上的变量进行引用,如 `window.AliLowCodeEngine.init`。您可以直接通过此方式初始化低代码引擎:
```javascript
@ -144,59 +142,5 @@ init 的功能包括但不限于:
> 本节中的低代码编辑器例子可以在 demo 中找到:[https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/index.ts](https://github.com/alibaba/lowcode-demo/blob/main/demo-general/src/index.ts)
#### 方法 2.2 使用 skeletonCabin.Workbench 方式初始化
`init()` 内部会调用 `ReactDOM.render()` 函数,因此这样初始化的内容没有办法与外部的 React 组件进行通信,也就没有办法在一些自定义的 plugin 中获取 redux 上的全局数据等内容。
因此,这种场景下您可以通过 `skeletonCabin.Workbench` 进行初始化。
> 注:**不需要**同时使用 2.1 和 2.2 的方法。根据使用场景,当且只当有需要插件和外界进行一定通信时,才需要使用 2.2 提供的方法。
```javascript
import React, { useState, useEffect } from 'react';
import { project, plugins, common, skeleton } from '@alilc/lowcode-engine';
// 此处略去若干依赖引用
async function registerPlugins() {
// 此处略去若干插件注册
}
function EditorView() {
/** 插件是否已初始化成功,因为必须要等插件初始化后才能渲染 Workbench */
const [hasPluginInited, setHasPluginInited] = useState(false);
useEffect(() => {
plugins.init().then(() => {
setHasPluginInited(true);
}).catch(err => console.error(err));
}, []);
if (!hasPluginInited) {
return null;
}
const Workbench = common.skeletonCabin.Workbench;
return <Workbench />;
}
(async function main() {
await registerPlugins();
config.setConfig({
enableCondition: true,
enableCanvasLock: true,
supportVariableGlobally: true,
requestHandlersMap: {
fetch: createFetchHandler()
}
});
ReactDOM.render(<EditorView />, document.getElementById('lce-container')!);
})();
```
> 本节中的低代码编辑器类似的例子可以在 demo 中找到:[https://github.com/alibaba/lowcode-demo/blob/main/demo-custom-initialization/src/index.tsx](https://github.com/alibaba/lowcode-demo/blob/main/demo-custom-initialization/src/index.tsx)
## 配置低代码编辑器
详见[低代码扩展简述](/site/docs/guide/expand/editor/summary)章节。

View File

@ -11,7 +11,6 @@ sidebar_position: 4
## npm 包与仓库信息
- React 框架渲染 npm 包:@alilc/lowcode-react-renderer
- Rax 框架渲染 npm 包:@alilc/lowcode-rax-renderer
- 仓库:[https://github.com/alibaba/lowcode-engine](https://github.com/alibaba/lowcode-engine) 下的
- packages/renderer-core
- packages/react-renderer

View File

@ -58,7 +58,7 @@ sidebar_position: 1
## 协议的作用
基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,各类中后台研发系统生产的物料可借助物料中心进行跨系统流通,通过丰富物料生态的共享提升各平台研发系统的效率。同时完成低代码引擎的标准统一以及低代码搭建中台能力的输出,帮助业务方快速孵化本业务域中后台研发系统。
基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,各类中后台研发系统生产的物料可借助物料中心进行跨系统流通,通过丰富物料生态的共享提升各平台研发系统的效率。同时完成低代码引擎的标准统一以及低代码搭建中台能力的输出,帮助业务方快速孵化本业务域中后台研发系统。
### 打破物料孤岛

View File

@ -20,7 +20,7 @@ sidebar_position: 0
低代码引擎分为 4 大模块,入料 - 编排 - 渲染 - 出码:
- 入料模块就是将外部的物料,比如海量的 npm 组件,按照《物料描述协议》进行描述。将描述后的数据通过引擎 API 注册后,在编辑器中使用。
- 入料模块就是将外部的物料,比如海量的 npm 组件,按照[低代码引擎物料协议规范](/site/docs/specs/material-spec)进行描述。将描述后的数据通过引擎 API 注册后,在编辑器中使用。
> **注意,这里仅是增加描述,而非重写一套,这样我们能最大程度复用 ProCode 体系已沉淀的组件。**
- 编排,本质上来讲,就是**不断在生成符合[《低代码引擎搭建协议规范》](/site/docs/specs/lowcode-spec)的页面描述,将编辑器中的所有物料,进行布局设置、组件 CRUD 操作、以及 JS / CSS 编写/ 逻辑编排 **等,最终转换成页面描述,技术细节后文会展开。
- 渲染,顾名思义,就是**将编排生成的页面描述结构渲染成视图的过程**,视图是面向用户的,所以必须处理好内部数据流、生命周期、事件绑定、国际化等。

View File

@ -1,6 +1,6 @@
---
title: 低代码生态脚手架 & 调试机制
sidebar_position: 8
sidebar_position: 10
---
## 脚手架简述

View File

@ -1,6 +1,6 @@
---
title: 图编排扩展
sidebar_position: 9
sidebar_position: 8
---
## 项目运行
### 前置准备

View File

@ -12,7 +12,7 @@ sidebar_position: 6
```typescript
import { plugins } from '@alilc/lowcode-engine';
import { IPublicModelPluginContext } from '@alilc/lowcode-types';
import { IPublicModelPluginContext, IPublicModelNode } from '@alilc/lowcode-types';
import { Icon, Message } from '@alifd/next';
const addHelloAction = (ctx: IPublicModelPluginContext) => {
@ -23,11 +23,11 @@ const addHelloAction = (ctx: IPublicModelPluginContext) => {
content: {
icon: <Icon type="atm" />,
title: 'hello',
action(node: Node) {
action(node: IPublicModelNode) {
Message.show('Welcome to Low-Code engine');
},
},
condition: (node: Node) => {
condition: (node: IPublicModelNode) => {
return node.componentMeta.componentName === 'NextTable';
},
important: true,

View File

@ -1,6 +1,6 @@
---
title: 设置器扩展
sidebar_position: 5
sidebar_position: 7
---
## 设置器简述

View File

@ -0,0 +1,157 @@
---
title: 主题色扩展
sidebar_position: 9
---
## 简介
主题色扩展允许用户定制多样的设计器主题,增加界面的个性化和品牌识别度。
## 设计器主题色定制
在 CSS 的根级别定义主题色变量可以确保这些变量在整个应用中都可用。例如:
```css
:root {
--color-brand: rgba(0, 108, 255, 1); /* 主品牌色 */
--color-brand-light: rgba(25, 122, 255, 1); /* 浅色品牌色 */
--color-brand-dark: rgba(0, 96, 229, 1); /* 深色品牌色 */
}
```
将样式文件引入到你的设计器中,定义的 CSS 变量就可以改变设计器的主题色了。
### 主题色变量
以下是低代码引擎设计器支持的主题色变量列表,以及它们的用途说明:
#### 品牌相关颜色
- `--color-brand`: 主品牌色
- `--color-brand-light`: 浅色品牌色
- `--color-brand-dark`: 深色品牌色
#### Icon 相关颜色
- `--color-icon-normal`: 默认状态
- `--color-icon-light`: icon light 状态
- `--color-icon-hover`: 鼠标悬停状态
- `--color-icon-active`: 激活状态
- `--color-icon-reverse`: 反色状态
- `--color-icon-disabled`: 禁用状态
- `--color-icon-pane`: 面板颜色
#### 线条和文本颜色
- `--color-line-normal`: 线条颜色
- `--color-line-darken`: 线条颜色(darken)
- `--color-title`: 标题颜色
- `--color-text`: 文字颜色
- `--color-text-dark`: 文字颜色(dark)
- `--color-text-light`: 文字颜色(light)
- `--color-text-reverse`: 反色情况下,文字颜色
- `--color-text-disabled`: 禁用态文字颜色
#### 菜单颜色
- `--color-context-menu-text`: 菜单项颜色
- `--color-context-menu-text-hover`: 菜单项 hover 颜色
- `--color-context-menu-text-disabled`: 菜单项 disabled 颜色
#### 字段和边框颜色
- `--color-field-label`: field 标签颜色
- `--color-field-text`: field 文本颜色
- `--color-field-placeholder`: field placeholder 颜色
- `--color-field-border`: field 边框颜色
- `--color-field-border-hover`: hover 态下field 边框颜色
- `--color-field-border-active`: active 态下field 边框颜色
- `--color-field-background`: field 背景色
#### 状态颜色
- `--color-success`: success 颜色
- `--colo-success-dark`: success 颜色(dark)
- `--color-success-light`: success 颜色(light)
- `--color-warning`: warning 颜色
- `--color-warning-dark`: warning 颜色(dark)
- `--color-warning-light`: warning 颜色(light)
- `--color-information`: information 颜色
- `--color-information-dark`: information 颜色(dark)
- `--color-information-light`: information 颜色(light)
- `--color-error`: error 颜色
- `--color-error-dark`: error 颜色(dark)
- `--color-error-light`: error 颜色(light)
- `--color-purple`: purple 颜色
- `--color-brown`: brown 颜色
#### 区块背景色
- `--color-block-background-normal`: 区块背景色
- `--color-block-background-light`: 区块背景色(light)。
- `--color-block-background-shallow`: 区块背景色 shallow
- `--color-block-background-dark`: 区块背景色(dark)
- `--color-block-background-disabled`: 区块背景色(disabled)
- `--color-block-background-active`: 区块背景色(active)
- `--color-block-background-active-light`: 区块背景色(active light)
- `--color-block-background-warning`: 区块背景色(warning)
- `--color-block-background-error`: 区块背景色(error)
- `--color-block-background-success`: 区块背景色(success)
- `--color-block-background-deep-dark`: 区块背景色(deep-dark),作用于多个组件同时拖拽的背景色。
#### 引擎相关颜色
- `--color-canvas-detecting-background`: 画布组件 hover 时遮罩背景色。
#### 其他区域背景色
- `--color-layer-mask-background`: 拖拽元素时,元素原来位置的遮罩背景色
- `--color-layer-tooltip-background`: tooltip 背景色
- `--color-pane-background`: 面板背景色
- `--color-background`: 设计器主要背景色
- `--color-top-area-background`: topArea 背景色,优先级大于 `--color-pane-background`
- `--color-left-area-background`: leftArea 背景色,优先级大于 `--color-pane-background`
- `--color-toolbar-background`: toolbar 背景色,优先级大于 `--color-pane-background`
- `--color-workspace-left-area-background`: 应用级 leftArea 背景色,优先级大于 `--color-pane-background`
- `--color-workspace-top-area-background`: 应用级 topArea 背景色,优先级大于 `--color-pane-background`
- `--color-workspace-sub-top-area-background`: 应用级二级 topArea 背景色,优先级大于 `--color-pane-background`
#### 其他变量
- `--workspace-sub-top-area-height`: 应用级二级 topArea 高度
- `--top-area-height`: 顶部区域的高度
- `--workspace-sub-top-area-margin`: 应用级二级 topArea margin
- `--workspace-sub-top-area-padding`: 应用级二级 topArea padding
- `--workspace-left-area-width`: 应用级 leftArea width
- `--left-area-width`: leftArea width
- `--simulator-top-distance`: simulator 距离容器顶部的距离
- `--simulator-bottom-distance`: simulator 距离容器底部的距离
- `--simulator-left-distance`: simulator 距离容器左边的距离
- `--simulator-right-distance`: simulator 距离容器右边的距离
- `--toolbar-padding`: toolbar 的 padding
- `--toolbar-height`: toolbar 的高度
- `--pane-title-height`: 面板标题高度
- `--pane-title-font-size`: 面板标题字体大小
- `--pane-title-padding`: 面板标题边距
- `--context-menu-item-height`: 右键菜单项高度
### 低代码引擎生态主题色定制
插件、物料、设置器等生态为了支持主题色需要对样式进行改造,需要对生态中的样式升级为 css 变量。例如:
```css
/* before */
background: #006cff;
/* after */
background: var(--color-brand, #006cff);
```
这里 `var(--color-brand, #默认色)` 表示使用 `--color-brand` 变量,如果该变量未定义,则使用默认颜色(#默认色)。
### fusion 物料进行主题色扩展
如果使用了 fusion 组件时,可以通过 [fusion 平台](https://fusion.design/) 进行主题色定制。在平台上,您可以选择不同的主题颜色,并直接应用于您的 fusion 组件,这样可以无缝地集成到您的应用设计中。

View File

@ -40,7 +40,6 @@ ReactDOM.render((
), document.getElementById('root'));
```
- rax-renderernpm 包替换为 @alilc/lowcode-rax-renderer
####
### 项目使用示例
> [设计器 demo](https://lowcode-engine.cn/demo/demo-general/index.html)

View File

@ -1,6 +1,6 @@
---
title: 试用低代码引擎 Demo
sidebar_position: 1
sidebar_position: 2
---
## 访问地址

View File

@ -1,6 +1,6 @@
---
title: 简介
sidebar_position: 0
sidebar_position: 1
---
# 阿里低代码引擎简介
@ -46,3 +46,18 @@ sidebar_position: 0
**低代码设计器研发框架**
低代码引擎的核心是设计器,通过扩展、周边生态等可以产出各式各样的设计器。它不是一套可以适合所有人的低代码平台,而是帮助低代码平台的开发者,快速生产低代码平台的工具。
## 寻找适合您的低代码解决方案
帮助用户根据个人或企业需求选择合适的低代码产品。
| 特性/产品 | 低代码引擎 | Lab平台 | UIPaaS |
|-----------------|-----------------------------------------|-----------------------------------------|--------------------------------------------|
| **适用用户** | 前端开发者 | 需要快速搭建应用/页面的用户 | 企业用户,需要大规模部署低代码解决方案的组织 |
| **产品特点** | 设计器研发框架,适合定制开发 | 低代码平台, 可视化操作界面,易于上手 | 低代码平台孵化器,企业级功能 |
| **使用场景** | 定制和开发低代码平台的设计器部分 | 通过可视化, 快速开发应用或页面 | 帮助具有一定规模软件研发团队的的企业低成本定制低代码平台 |
| **产品关系** | 开源产品 | 基于UIPaaS技术实现, 展示了UIPaaS的部分能力 | 提供完整的低代码平台解决方案,商业产品 |
| **收费情况** | 免费 | 可免费使用(有额度限制),不提供私有化部署售卖 | 仅提供私有化部署售卖 |
| **官方网站** | [低代码引擎官网](https://lowcode-engine.cn/) | [Lab平台官网](https://lab.lowcode-engine.cn/) | [UIPaaS官网](https://uipaas.net/) |
*注:请根据您的具体需求和条件选择合适的产品。如需更详细的信息,请访问各产品的官方网站。*

View File

@ -1,5 +1,5 @@
---
sidebar_position: 2
sidebar_position: 3
title: 快速开始
---

View File

@ -1,88 +0,0 @@
---
title: 工程化配置
sidebar_position: 3
---
目前引擎体系共包含 2 个 js 文件 (配套 2 个 css),即:
```html
<!-- 低代码引擎的页面框架样式 -->
<link rel="stylesheet" href="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/css/engine-core.css" />
<!-- 低代码引擎官方扩展的样式 -->
<link rel="stylesheet" href="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/css/engine-ext.css" />
<!-- 低代码引擎的主包 -->
<script crossorigin="anonymous" src="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/js/engine-core.js"></script>
<!-- 低代码引擎官方扩展的主包 -->
<script crossorigin="anonymous" src="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/js/engine-ext.js"></script>
```
> 注,这里的版本号是示例,请尽量选用最新版
工程化配置我们进行了统一,具体如下:
```shell
{
"entry": {
...
},
"library": "...",
"libraryTarget": "umd",
"externals": {
"react": "var window.React",
"react-dom": "var window.ReactDOM",
"prop-types": "var window.PropTypes",
"@alilc/lowcode-engine": "var window.AliLowCodeEngine",
"@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt",
"moment": "var moment",
"lodash": "var _",
"@alifd/next": "var Next"
},
"polyfill": false,
"outputDir": "dist",
"vendor": false,
"ignoreHtmlTemplate": true,
"sourceMap": true,
"plugins": [
"build-plugin-react-app",
["build-plugin-fusion", {
}],
["build-plugin-moment-locales", {
"locales": ["zh-CN"]
}],
"./build.plugin.js"
]
}
```
总结一下,有 2 点:
1. **都不包含 polyfill**需要应用级别单独引入 polyfill推荐动态 polyfill
2. **都不包含 lodash / moment / next**
#### 前置依赖资源:
```html
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.css">
<script src="//polyfill.alicdn.com/s/polyfill.min.js?features=default,es2017,es6,fetch,RegeneratorRuntime"></script>
<script src="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.js"></script>
<script src="//g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js"></script>
<script src="//g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
```
#### 所有资源:
```html
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.css">
<link rel="stylesheet" href="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/css/engine-core.css"/>
<link rel="stylesheet" href="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.5/dist/css/engine-ext.css"/>
<script src="//polyfill.alicdn.com/s/polyfill.min.js?features=default,es2017,es6,fetch,RegeneratorRuntime"></script>
<script src="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.js"></script>
<script src="//g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js"></script>
<script src="//g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
<!-- engine-core 引擎的 core负责引擎的基础模块 -->
<script crossorigin="anonymous" src="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/js/engine-core.js"></script>
<!-- engine-ext 引擎的扩展包,负责收拢内置 setters / plugins方便迭代 -->
<script crossorigin="anonymous" src="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.5/dist/js/engine-ext.js"></script>
```

View File

@ -1,25 +0,0 @@
---
title: 参与文档贡献
sidebar_position: 3
---
## 基本原则
### 维护方式
- 官方文档通过 github 管理文档源,官网文档与[主仓库 develop 分支](https://github.com/alibaba/lowcode-engine/tree/develop/docs)保持同步。
- 点击每篇文档下发的 `编辑此页` 可直接定位到 github 中位置。
- 欢迎 PR文档 PR 也会作为贡献者贡献,会用于贡献度统计。
- **文档同步到官方网站由官方人员进行操作**,如有需要可以通过 issue 或 贡献者群与相关人员沟通。
- 为了提供更好的阅读和使用体验,文档中的图片文件会定期转换成可信的 CDN 地址。
### PR 提交注意事项
- 指向 develop 分支。
- 涉及到图片的,需附在文档同级的 img 目录下,通过相对地址引用。
### 文档格式
本项目文档参考[文档编写指南](https://github.com/sparanoid/chinese-copywriting-guidelines)。
使用 vscode 进行编辑的朋友可以安装 vscode 插件 [huacnlee.autocorrect](https://github.com/huacnlee/autocorrect) 辅助文档 lint。

View File

@ -1,31 +1,118 @@
---
title: 贡献者指南
title: 参与贡献
sidebar_position: 0
---
### 首个 Pull Request
在写第一个 Pull Request你可以从这一系列视频中学习怎么做
[How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github)
### 环境准备
开发 LowcodeEngine 需要 Node.js 16+。
推荐使用 nvm 管理 Node.js避免权限问题的同时还能够随时切换当前使用的 Node.js 的版本。
### 贡献低代码引擎
#### clone 项目
```
git clone git@github.com:alibaba/lowcode-engine.git
cd lowcode-engine
```
#### 安装依赖并构建
```
npm install && npm run setup
```
#### 调试环境配置
本质上是将 demo 页面引入的几个 js/css 代理到 engine 项目,可以使用趁手的代理工具,这里推荐 [XSwitch](https://chrome.google.com/webstore/detail/xswitch/idkjhjggpffolpidfkikidcokdkdaogg?hl=en-US)。
本地开发代理规则如下:
```json
{
"proxy": [
[
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/engine-core.js",
"http://localhost:5555/js/AliLowCodeEngine.js"
],
[
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/engine-core.css",
"http://localhost:5555/css/AliLowCodeEngine.css"
],
[
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/react-simulator-renderer.js",
"http://localhost:5555/js/ReactSimulatorRenderer.js"
],
[
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/react-simulator-renderer.css",
"http://localhost:5555/css/ReactSimulatorRenderer.css"
]
]
}
```
#### 开发
```
npm start
```
选择一个环境进行调试,例如[低代码引擎在线 DEMO](https://lowcode-engine.cn/demo/demo-general/index.html)
开启代理之后,就可以进行开发调试了。
### 贡献低代码引擎文档
#### 开发文档
在 lowcode-engine 目录下执行下面命令
```
cd docs
npm start
```
#### 维护方式
- 官方文档通过 github 管理文档源,官网文档与[主仓库 develop 分支](https://github.com/alibaba/lowcode-engine/tree/develop/docs)保持同步。
- 点击每篇文档下发的 `编辑此页` 可直接定位到 github 中位置。
- 欢迎 PR文档 PR 也会作为贡献者贡献,会用于贡献度统计。
- **文档同步到官方网站由官方人员进行操作**,如有需要可以通过 issue 或 贡献者群与相关人员沟通。
- 为了提供更好的阅读和使用体验,文档中的图片文件会定期转换成可信的 CDN 地址。
#### 文档格式
本项目文档参考[文档编写指南](https://github.com/sparanoid/chinese-copywriting-guidelines)。
使用 vscode 进行编辑的朋友可以安装 vscode 插件 [huacnlee.autocorrect](https://github.com/huacnlee/autocorrect) 辅助文档 lint。
### 贡献低代码引擎生态
相关源码详见[NPM 包对应源码位置汇总](/site/docs/guide/appendix/npms)
开发调试方式详见[低代码生态脚手架 & 调试机制](/site/docs/guide/expand/editor/cli)
### 发布
PR 被合并之后,我们会尽快发布相关的正式版本或者 beta 版本。
### 加入 Contributor 群
提交过 Bugfix 或 Feature 类 PR 的同学,如果有兴趣一起参与维护 LowcodeEngine我们提供了一个核心贡献者交流群。
1. 可以通过[填写问卷](https://survey.taobao.com/apps/zhiliao/4YEtu9gHF)的方式,参与到其中。
2. 填写问卷后加微信号 `wxidvlalalalal` (注明 github id我们会拉你到群里。
如果你不知道可以贡献什么,可以到源码里搜 TODO 或 FIXME 找找。
为了使你能够快速上手和熟悉贡献流程,我们这里有个列表 [good first issues](https://github.com/alibaba/lowcode-engine/issues?q=is:open+is:issue+label:%22good+first+issue%22),里面有相对没那么笼统的漏洞,从这开始是个不错的选择。
如果你想解决一个 issue请确定检查了该 issue 下的评论以防有人正在处理它。如果目前没人在处理该 issue那么请留下评论去表明你想处理该 issue 以便其他人不会意外重复你的工作。
### PR 提交注意事项
如果有人留言表明要处理该 issue 但是超过两周没有跟进,你可以接手工作,不过也应该留言说明。
### 提交 Pull Request
核心团队时刻关注 pull requests我们会先评审你的 pull request之后可能会合并可能会要求再次更改也可能会关闭该 pull request 并对此作出解释。我们会尽力全程更新和反馈。
**提交 pull request 前**,请确保完成以下步骤:
1. Fork [此仓库](https://github.com/alibaba/lowcode-engine),从 main 创建分支。
2. 在仓库根目录下执行 yarn。
3. 如果你修复了 bug 或者添加了代码,而这些内容需要测试,请添加测试!
4. 确保通过测试套件yarn test
5. 请签订贡献者许可证协议Contributor License Agreement
> 如已签署 CLA 仍被提示需要签署,[解决办法](/site/docs/faq/faq021)
### 核心贡献者交流
如果你想长期参与到项目维护中,我们提供了一个核心贡献者交流群。
1. 可以通过[填写问卷](https://survey.taobao.com/apps/zhiliao/4YEtu9gHF)的方式,参与到其中。
2. 填写问卷后加微信号 `wxidvlalalalal` 说明一下。
- lowcode-engine 仓库建议从 develop 创建分支PR 指向 develop 分支。
- 其他仓库从 main 分支创建分支PR 指向 main 分支
- 如果你修复了 bug 或者添加了代码,而这些内容需要测试,请添加测试!
- 确保通过测试套件yarn test
- 请签订贡献者许可证协议Contributor License Agreement
> 如已签署 CLA 仍被提示需要签署,[解决办法](/site/docs/faq/faq021)

View File

@ -0,0 +1,55 @@
---
title: 开源社区例会
sidebar_position: 0
---
## **简介**
低代码引擎开源社区致力于共同推动低代码技术的发展和创新。本社区汇集了低代码技术领域的开发者、技术专家和行业观察者,通过定期的例会来交流思想、分享经验、讨论新技术,并探索低代码技术的未来发展方向。
## 参与要求
为了确保例会的质量和效果,我们建议以下人员参加:
- **已参与低代码引擎贡献的成员**:那些对低代码引擎有实际贡献的社区成员。
- **参考贡献指南**:可查阅[贡献指南](https://lowcode-engine.cn/site/docs/participate/)获取更多信息。
- **提供过优秀建议的成员**:那些在过去为低代码引擎提供过有价值建议的成员。
## **时间周期**
- **周期性**:月例会
### **特别说明**
- 例会周期可根据成员反馈进行调整。如果讨论的议题较多,可增加例会频率;若议题较少,单次例会可能取消。若多次取消,可能会暂停例会。
## **例会流程**
### **准备阶段**
- **定期确定议题**:会前一周确定下一次会议的议题。
- **分发会议通知**:提前发送会议时间、议程和参与方式。
### **会议阶段**
- **开场和介绍**:简短开场和自我介绍,特别是新成员加入时。
- **议题讨论**:按照议程进行议题讨论,每个议题分配一定时间,并留足够时间供讨论和提问。
- **记录要点和决定**:记录讨论要点、决策和任何行动事项。
### **后续阶段**
- **分享会议纪要**:会后将会议纪要和行动计划分发给所有成员。
- **执行和跟进**:根据会议中的讨论和决策执行相关任务,并在下次会议中进行跟进汇报。
## **开源例会议题**
开源例会议题包括但不限于:
- **共建低代码行业发展**:探讨通过开源社区合作加速低代码行业发展。
- **改进建议和反馈收集**:讨论社区成员对低代码引擎的使用体验和改进建议。
- **前端技术与低代码的结合**:针对前端开发者,讨论将前端技术与低代码引擎结合的方式。
- **低代码业务场景和经验分享**:邀请社区成员分享低代码引擎的实际应用经验。
- **低代码技术原理介绍**:深入理解低代码引擎的技术原理和实现方式。
- **低代码引擎的最新进展**:分享低代码引擎的最新进展,包括新版本发布和新功能实现等。
- **低代码技术的未来展望**:讨论低代码技术的未来发展方向。
- **最新低代码平台功能和趋势分析**:分享和讨论当前低代码平台的新功能、趋势和发展方向。

View File

@ -1,64 +0,0 @@
---
title: 调试环境配置
sidebar_position: 1
---
低代码引擎的核心仓库是不包含任何物料、插件、setter 的,它本身用于生成低代码引擎的主包。
如果您需要对低代码的主包进行开发和调试,需要用到本文里介绍的知识。
如果您需要对低代码编辑器进行定制,您可能只需要 clone [lowcode-demo 项目](https://github.com/alibaba/lowcode-demo)并进行修改,参考“[配置低代码扩展点](/site/docs/guide/expand/editor/summary)”章节。
> 前置条件:
> node 推荐使用 16.18.014.x 也可以)
### 1. 拉取代码,启动项目
```bash
git clone git@github.com:alibaba/lowcode-engine.git
cd lowcode-engine
npm install && npm run setup
npm start
git clone git@github.com:alibaba/lowcode-demo.git
cd lowcode-demo
npm install && npm start
```
### 2. 配置资源代理
本质上是将 demo 页面引入的几个 js/css 代理到 engine 项目,可以使用趁手的代理工具,这里推荐 [XSwitch](https://chrome.google.com/webstore/detail/xswitch/idkjhjggpffolpidfkikidcokdkdaogg?hl=en-US)。
本地开发代理规则如下:
```json
{
"proxy": [
[
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/engine-core.js",
"http://localhost:5555/js/engine-core.js"
],
[
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/engine-core.css",
"http://localhost:5555/css/engine-core.css"
],
[
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/react-simulator-renderer.js",
"http://localhost:5555/js/react-simulator-renderer.js"
],
[
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/react-simulator-renderer.css",
"http://localhost:5555/css/react-simulator-renderer.css"
],
[
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/rax-simulator-renderer.js",
"http://localhost:5555/js/rax-simulator-renderer.js"
],
[
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/rax-simulator-renderer.css",
"http://localhost:5555/css/rax-simulator-renderer.css"
],
]
}
```
### 3. 本地调试物料/插件/设置器
详见[低代码生态脚手架 & 调试机制](/site/docs/guide/expand/editor/cli)

View File

@ -499,7 +499,6 @@ try {
- 说明:组件即将从 DOM 中移除
- componentDidCatch(error, info)
- 说明:组件捕获到异常
- Rax目前没有使用生命周期使用 hooks 替代生命周期;
该对象由一系列 key-value 组成key 为生命周期方法名value 为 JSFunction 的描述,详见下方示例:

16
docs/docs/video/index.md Normal file
View File

@ -0,0 +1,16 @@
# 官方视频
- [2023/11/20 云栖大会|阿里开源低代码引擎及商业解决方案](https://www.bilibili.com/video/BV1Ku4y1w7Zr)
- [2023/08/03 初识低代码引擎](https://www.bilibili.com/video/BV1gu411p7TC)
# 社区视频
- [低代码从入门到实战:低代码引擎实践](https://www.bilibili.com/video/BV1aP4y1Q7Xa/)
- [低代码技术在研发团队的应用模式](https://www.bilibili.com/video/BV1L14y1Y72J/)
- [阿里低代码引擎项目实战 (1)-引擎 demo 部署到 faas 服务](https://www.bilibili.com/video/BV1B44y1P7GM/)
- [【有翻车】阿里低代码引擎项目实战 (2)-保存页面到远端存储](https://www.bilibili.com/video/BV1AS4y1K7DP/)
- [阿里巴巴低代码引擎项目实战 (3)-自定义组件接入](https://www.bilibili.com/video/BV1dZ4y1m76S/)
- [阿里低代码引擎项目实战 (4)-自定义插件 - 页面管理](https://www.bilibili.com/video/BV17a411i73f/)
- [阿里低代码引擎项目实战 (4)-用户登录](https://www.bilibili.com/video/BV1Wu411e7EQ/)
- [【有翻车】阿里低代码引擎项目实战 (5)-表单回显](https://www.bilibili.com/video/BV1UY4y1v7D7/)
- [阿里低代码引擎项目实战 (6)-自定义插件 - 页面管理 - 后端](https://www.bilibili.com/video/BV1uZ4y1U7Ly/)
- [阿里低代码引擎项目实战 (6)-自定义插件 - 页面管理 - 前端](https://www.bilibili.com/video/BV1Yq4y1a74P/)
- [阿里低代码引擎项目实战 (7)-自定义插件 - 页面管理 (完结)](https://www.bilibili.com/video/BV13Y4y1e7EV/)

View File

@ -1,6 +1,6 @@
{
"name": "@alilc/lowcode-engine-docs",
"version": "1.1.7",
"version": "1.2.31",
"description": "低代码引擎版本化文档",
"license": "MIT",
"files": [

View File

@ -19,7 +19,7 @@ const onResponse = function (res) {
chunks.push(chunk);
});
res.on('end', (chunk) => {
res.on('end', () => {
const body = Buffer.concat(chunks);
console.table(JSON.stringify(JSON.parse(body.toString()), null, 2));
});
@ -39,9 +39,9 @@ const postData = JSON.stringify({
},
],
// 可以发布指定源的 npm 包,默认公网 npm
useTnpm: false,
useTnpm: true,
});
req.write(postData);
req.end();
req.end();

View File

@ -1,6 +1,6 @@
{
"lerna": "4.0.0",
"version": "1.1.10",
"version": "1.3.2",
"npmClient": "yarn",
"useWorkspaces": true,
"packages": [

View File

@ -94,16 +94,26 @@ await CodeGenerator.init();
4. 出码
```js
const result = await CodeGenerator.generateCode({
const project = await CodeGenerator.generateCode({
solution: 'icejs', // 出码方案 (目前内置有 icejs 和 rax )
schema, // 编排搭建出来的 schema
});
console.log(result); // 出码结果(默认是递归结构描述的,可以传 flattenResult: true 以生成扁平结构的结果)
console.log(project); // 出码结果(默认是递归结构描述的,可以传 flattenResult: true 以生成扁平结构的结果)
```
注:一般来说在浏览器中出码适合做即时预览功能。
5. 下载 zip 包
```js
// 写入到 zip 包
await CodeGenerator.publishers.zip().publish({
project, // 上一步生成的 project
projectSlug: 'your-project-slug', // 项目标识 -- 对应下载 your-project-slug.zip 文件
});
```
### 5自定义出码
前端框架灵活多变,默认内置的出码方案很难满足所有人的需求,好在此代码生成器支持非常灵活的插件机制 -- 欢迎参考 ./src/plugins/xxx 来编写您自己的出码插件,然后参考 ./src/solutions/xxx 将各种插件组合成一套适合您的业务场景的出码方案。

View File

@ -1,6 +1,6 @@
{
"name": "@alilc/lowcode-code-generator",
"version": "1.1.6",
"version": "1.1.7",
"description": "出码引擎 for LowCode Engine",
"license": "MIT",
"main": "lib/index.js",
@ -80,6 +80,7 @@
"change-case": "^3.1.0",
"commander": "^6.1.0",
"debug": "^4.3.2",
"file-saver": "^2.0.5",
"fp-ts": "^2.11.9",
"fs-extra": "9.x",
"glob": "^7.2.0",
@ -109,6 +110,7 @@
"devDependencies": {
"@iceworks/spec": "^1.4.2",
"@types/babel__traverse": "^7.11.0",
"@types/file-saver": "^2.0.7",
"@types/jest": "^27.0.2",
"@types/lodash": "^4.14.162",
"@types/node": "^14.14.20",

View File

@ -2,9 +2,9 @@ import { ResultDir } from '@alilc/lowcode-types';
import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
import { getErrorMessage } from '../../utils/errors';
import { isNodeProcess, writeZipToDisk, generateProjectZip } from './utils';
import { saveAs } from 'file-saver';
// export type ZipBuffer = Buffer | Blob;
export type ZipBuffer = Buffer;
export type ZipBuffer = Buffer | Blob;
declare type ZipPublisherResponse = string | ZipBuffer;
@ -44,10 +44,16 @@ export const createZipPublisher: PublisherFactory<ZipFactoryParams, ZipPublisher
try {
const zipContent = await generateProjectZip(projectToPublish);
// If not output path is provided, zip is not written to disk
const projectOutputPath = options.outputPath || outputPath;
if (projectOutputPath && isNodeProcess()) {
await writeZipToDisk(projectOutputPath, zipContent, zipName);
if (isNodeProcess()) {
// If not output path is provided on the node side, zip is not written to disk
const projectOutputPath = options.outputPath || outputPath;
if (projectOutputPath) {
await writeZipToDisk(projectOutputPath, zipContent, zipName);
}
} else {
// the browser end does not require a path
// auto download zip files
saveAs(zipContent as Blob, `${zipName}.zip`);
}
return { success: true, payload: zipContent };

View File

@ -40,8 +40,7 @@ export const writeZipToDisk = (
export const generateProjectZip = async (project: ResultDir): Promise<ZipBuffer> => {
let zip = new JSZip();
zip = writeFolderToZip(project, zip, true);
// const zipType = isNodeProcess() ? 'nodebuffer' : 'blob';
const zipType = 'nodebuffer'; // 目前先只支持 node 调用
const zipType = isNodeProcess() ? 'nodebuffer' : 'blob';
return zip.generateAsync({ type: zipType });
};

View File

@ -1,6 +1,14 @@
import CodeGen from '../../../../src';
import fileSaver from 'file-saver';
import * as utils from '../../../../src/publisher/zip/utils';
jest.mock('file-saver');
describe('public/publisher/zip/zip', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('should works', async () => {
const zip = CodeGen.publishers.zip({
outputPath: 'demo-output',
@ -19,15 +27,15 @@ describe('public/publisher/zip/zip', () => {
],
};
expect(zip.getOutputPath()).toMatchInlineSnapshot(`"demo-output"`);
expect(zip.getOutputPath()).toMatchInlineSnapshot('"demo-output"');
expect(zip.getProject()).toMatchInlineSnapshot(`undefined`);
expect(zip.getProject()).toMatchInlineSnapshot('undefined');
zip.setProject(demoProject);
expect(zip.getProject()).toBeTruthy();
expect(zip.getOutputPath()).toMatchInlineSnapshot(`"demo-output"`);
expect(zip.getOutputPath()).toMatchInlineSnapshot('"demo-output"');
expect(zip.setOutputPath('output')).toBe(undefined);
expect(zip.getOutputPath()).toMatchInlineSnapshot(`"output"`);
expect(zip.getOutputPath()).toMatchInlineSnapshot('"output"');
const publishRes = await zip.publish({
project: demoProject,
@ -41,4 +49,39 @@ describe('public/publisher/zip/zip', () => {
const zip = CodeGen.publishers.zip({});
expect(zip.publish()).rejects.toBeTruthy();
});
it('should publish the project as a zip file in the browser', async () => {
const zipContent = 'zip content';
const zipName = 'example-project';
jest.spyOn(utils, 'isNodeProcess').mockReturnValue(false);
// new Zip 里面也有平台判断,所以这里 mock
jest.spyOn(utils, 'generateProjectZip').mockResolvedValue(zipContent as any);
const spy = jest.spyOn(fileSaver, 'saveAs');
const zip = CodeGen.publishers.zip({
projectSlug: zipName,
});
const demoProject = {
name: 'demo',
dirs: [],
files: [
{
name: 'package',
ext: 'json',
content: '{ "name": "demo", "version": "1.0.0" }',
},
],
};
zip.setProject(demoProject);
const publishRes = await zip.publish({
project: demoProject,
});
expect(publishRes.success).toBeTruthy();
expect(spy).toBeCalledWith(zipContent, `${zipName}.zip`);
spy.mockReset();
spy.mockRestore();
});
});

View File

@ -20,11 +20,13 @@
"lint:fix": "f2elint fix -i ./packages/*/src",
"lint:modules": "f2elint scan -q -i ./modules/*/src",
"lint:modules:fix": "f2elint fix -i ./modules/*/src",
"pub": "npm run watchdog:build && lerna publish patch --force-publish --exact --no-changelog",
"pub": "npm run watchdog:build && lerna publish patch --yes --force-publish --exact --no-changelog",
"pub:minor": "npm run watchdog:build && lerna publish minor --yes --force-publish --exact --no-changelog",
"pub:major": "npm run watchdog:build && lerna publish major --yes --force-publish --exact --no-changelog",
"pub:premajor": "npm run watchdog:build && lerna publish premajor --force-publish --exact --dist-tag beta --preid beta --no-changelog",
"pub:preminor": "npm run watchdog:build && lerna publish preminor --force-publish --exact --dist-tag beta --preid beta --no-changelog",
"pub:prepatch": "npm run watchdog:build && lerna publish prepatch --force-publish --exact --dist-tag beta --preid beta --no-changelog",
"pub:prerelease": "npm run watchdog:build && lerna publish prerelease --force-publish --exact --dist-tag beta --preid beta --no-changelog",
"pub:prerelease": "npm run watchdog:build && lerna publish prerelease --yes --force-publish --exact --dist-tag beta --preid beta --no-changelog",
"setup": "node ./scripts/setup.js",
"setup:test": "./scripts/setup-for-test.sh",
"setup:skip-build": "./scripts/setup-skip-build.sh",
@ -52,7 +54,7 @@
"yarn": "^1.22.17",
"rimraf": "^3.0.2",
"@types/react-router": "5.1.18",
"@alilc/build-plugin-lce": "^0.0.3",
"@alilc/build-plugin-lce": "^0.0.5",
"babel-jest": "^26.5.2",
"@alilc/lowcode-test-mate": "^1.0.1"
},
@ -64,7 +66,8 @@
"lockfile": "enable"
},
"resolutions": {
"typescript": "4.6.2"
"typescript": "4.6.2",
"react-error-overlay": "6.0.9"
},
"repository": "git@github.com:alibaba/lowcode-engine.git"
}

View File

@ -20,6 +20,8 @@ const jestConfig = {
// testMatch: ['**/node.test.ts'],
// testMatch: ['**/builtin-hotkey.test.ts'],
// testMatch: ['**/selection.test.ts'],
// testMatch: ['**/plugin/sequencify.test.ts'],
// testMatch: ['**/builtin-simulator/utils/parse-metadata.test.ts'],
transformIgnorePatterns: [
`/node_modules/(?!${esModules})/`,
],

View File

@ -1,6 +1,6 @@
{
"name": "@alilc/lowcode-designer",
"version": "1.1.10",
"version": "1.3.2",
"description": "Designer for Ali LowCode Engine",
"main": "lib/index.js",
"module": "es/index.js",
@ -15,10 +15,9 @@
},
"license": "MIT",
"dependencies": {
"@alilc/build-plugin-lce": "^0.0.4-beta.2",
"@alilc/lowcode-editor-core": "1.1.10",
"@alilc/lowcode-types": "1.1.10",
"@alilc/lowcode-utils": "1.1.10",
"@alilc/lowcode-editor-core": "1.3.2",
"@alilc/lowcode-types": "1.3.2",
"@alilc/lowcode-utils": "1.3.2",
"classnames": "^2.2.6",
"react": "^16",
"react-dom": "^16.7.0",

View File

@ -6,5 +6,5 @@
bottom: 0;
right: 0;
overflow: visible;
z-index: 800;
z-index: 1;
}

View File

@ -9,7 +9,7 @@ import {
ComponentType,
} from 'react';
import classNames from 'classnames';
import { observer, computed, Tip } from '@alilc/lowcode-editor-core';
import { observer, computed, Tip, engineConfig } from '@alilc/lowcode-editor-core';
import { createIcon, isReactComponent, isActionContentObject } from '@alilc/lowcode-utils';
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
import { BuiltinSimulatorHost } from '../host';
@ -47,14 +47,18 @@ export class BorderSelectingInstance extends Component<{
});
const { hideSelectTools } = observed.node.componentMeta.advanced;
const hideComponentAction = engineConfig.get('hideComponentAction');
if (hideSelectTools) {
return null;
}
return (
<div className={className} style={style}>
{!dragging && <Toolbar observed={observed} />}
<div
className={className}
style={style}
>
{(!dragging && !hideComponentAction) ? <Toolbar observed={observed} /> : null}
</div>
);
}
@ -143,7 +147,7 @@ function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActio
});
}}
>
{icon && createIcon(icon)}
{icon && createIcon(icon, { key, node: node.internalToShellNode() })}
<Tip>{title}</Tip>
</div>
);

View File

@ -17,7 +17,7 @@
}
& > &-status {
margin-left: 5px;
color: #3c3c3c;
color: var(--color-text, #3c3c3c);
transform: translateY(-100%);
font-weight: lighter;
}
@ -46,7 +46,7 @@
opacity: 1;
max-height: 100%;
overflow: hidden;
color: white;
color: var(--color-icon-reverse, white);
&:hover {
background: var(--color-brand-light, #006cff);
}
@ -56,8 +56,8 @@
display: inline-block;
width: 8px;
height: 8px;
border: 1px solid #197aff;
background: #fff;
border: 1px solid var(--color-brand, #197aff);
background: var(--color-block-background-normal, #fff);
pointer-events: auto;
z-index: 2;
}
@ -73,11 +73,9 @@
&:after {
content: "";
display: block;
border: 1px solid #197aff;
background: #fff;
// background: #738397;
border: 1px solid var(--color-brand, #197aff);
background: var(--color-block-background-normal, #fff);
border-radius: 2px;
// animation: flashing 1.5s infinite linear;
}
&.e,
@ -85,7 +83,6 @@
cursor: ew-resize;
&:after {
width: 4px;
// height: calc(100% - 20px);
min-height: 50%;
}
}
@ -94,62 +91,24 @@
&.s {
cursor: ns-resize;
&:after {
// width: calc(100% - 20px);
min-width: 50%;
height: 4px;
}
}
}
// &&-hovering {
&&-detecting {
z-index: 1;
border-style: dashed;
background: rgba(0,121,242,.04);
&.x-loop {
border-color: rgba(138, 93, 226, 0.8);
background: rgba(138, 93, 226, 0.04);
>.@{scope}-title {
color: rgba(138, 93, 226, 1.0);
}
}
&.x-condition {
border-color: rgba(255, 99, 8, 0.8);
background: rgba(255, 99, 8, 0.04);
>.@{scope}-title {
color: rgb(255, 99, 8);
}
}
background: var(--color-canvas-detecting-background, rgba(0,121,242,.04));
}
&&-selecting {
z-index: 2;
border-width: 2px;
&.x-loop {
border-color: rgba(147, 112, 219, 1.0);
background: rgba(147, 112, 219, 0.04);
>@{scope}-title {
color: rgba(147, 112, 219, 1.0);
}
&.highlight {
background: transparent;
}
}
&.x-condition {
border-color: rgb(255, 99, 8);
>@{scope}-title {
color: rgb(255, 99, 8);
}
}
&.dragging {
background: rgba(182, 178, 178, 0.8);
background: var(--color-layer-mask-background, rgba(182, 178, 178, 0.8));
border: none;
}
}

View File

@ -23,6 +23,6 @@
}
&.invalid {
background-color: red;
background-color: var(--color-error, var(--color-function-error, red));
}
}

View File

@ -56,12 +56,13 @@ export function createSimulator(
}
const id = asset.id ? ` data-id="${asset.id}"` : '';
const lv = asset.level || level || AssetLevel.Environment;
const scriptType = asset.scriptType ? ` type="${asset.scriptType}"` : '';
if (asset.type === AssetType.JSUrl) {
scripts[lv].push(
`<script src="${asset.content}"${id}></script>`,
`<script src="${asset.content}"${id}${scriptType}></script>`,
);
} else if (asset.type === AssetType.JSText) {
scripts[lv].push(`<script${id}>${asset.content}</script>`);
scripts[lv].push(`<script${id}${scriptType}>${asset.content}</script>`);
} else if (asset.type === AssetType.CSSUrl) {
styles[lv].push(
`<link rel="stylesheet" href="${asset.content}"${id} />`,

View File

@ -31,7 +31,7 @@
max-height: calc(100% - 32px);
max-width: calc(100% - 32px);
transform: translateX(-50%);
box-shadow: 0 2px 10px 0 rgba(31,56,88,.15);
box-shadow: 0 2px 10px 0 var(--color-block-background-shallow, rgba(31,56,88,.15));
}
&-device-iphonex { // 增加默认的小程序的壳
@ -44,7 +44,7 @@
background: url(https://img.alicdn.com/tfs/TB1b4DHilFR4u4jSZFPXXanzFXa-750-1574.png) no-repeat top;
background-size: 375px 812px;
border-radius: 44px;
box-shadow: rgba(0, 0, 0, 0.1) 0 36px 42px;
box-shadow: var(--color-block-background-shallow, rgba(0, 0, 0, 0.1)) 0 36px 42px;
.@{scope}-canvas-viewport {
width: auto;
top: 50px;
@ -73,12 +73,12 @@
}
&-device-default {
top: 16px;
right: 16px;
bottom: 16px;
left: 16px;
top: var(--simulator-top-distance, 16px);
right: var(--simulator-right-distance, 16px);
bottom: var(--simulator-bottom-distance, 16px);
left: var(--simulator-left-distance, 16px);
width: auto;
box-shadow: 0 1px 4px 0 rgba(31, 50, 88, 0.125);
box-shadow: 0 1px 4px 0 var(--color-block-background-shallow, rgba(31, 50, 88, 0.125));
}
&-content {

View File

@ -39,6 +39,7 @@ import {
isDragAnyObject,
isDragNodeObject,
isLocationData,
Logger,
} from '@alilc/lowcode-utils';
import {
isShaken,
@ -72,6 +73,8 @@ import { IScroller } from '../designer/scroller';
import { isElementNode, isDOMNodeVisible } from '../utils/misc';
import { debounce } from 'lodash';
const logger = new Logger({ level: 'warn', bizName: 'designer' });
export type LibraryItem = IPublicTypePackage & {
package: string;
library: string;
@ -122,21 +125,6 @@ const defaultSimulatorUrl = (() => {
return urls;
})();
const defaultRaxSimulatorUrl = (() => {
const publicPath = getPublicPath();
let urls;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, prefix = '', dev] = /^(.+?)(\/js)?\/?$/.exec(publicPath) || [];
if (dev) {
urls = [`${prefix}/css/rax-simulator-renderer.css`, `${prefix}/js/rax-simulator-renderer.js`];
} else if (process.env.NODE_ENV === 'production') {
urls = [`${prefix}/rax-simulator-renderer.css`, `${prefix}/rax-simulator-renderer.js`];
} else {
urls = [`${prefix}/rax-simulator-renderer.css`, `${prefix}/rax-simulator-renderer.js`];
}
return urls;
})();
const defaultEnvironment = [
// https://g.alicdn.com/mylib/??react/16.11.0/umd/react.production.min.js,react-dom/16.8.6/umd/react-dom.production.min.js,prop-types/15.7.2/prop-types.min.js
assetItem(
@ -151,17 +139,6 @@ const defaultEnvironment = [
),
];
const defaultRaxEnvironment = [
assetItem(
AssetType.JSText,
'window.Rax=parent.Rax;window.React=parent.React;window.ReactDOM=parent.ReactDOM;window.VisualEngineUtils=parent.VisualEngineUtils;window.VisualEngine=parent.VisualEngine',
),
assetItem(
AssetType.JSText,
'window.PropTypes=parent.PropTypes;React.PropTypes=parent.PropTypes; window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;',
),
];
export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProps> {
readonly isSimulator = true;
@ -467,11 +444,15 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const libraryAsset: AssetList = this.buildLibrary();
if (this.renderEnv === 'rax') {
logger.error('After LowcodeEngine v1.3.0, Rax is no longer supported.');
}
const vendors = [
// required & use once
assetBundle(
this.get('environment') ||
(this.renderEnv === 'rax' ? defaultRaxEnvironment : defaultEnvironment),
defaultEnvironment,
AssetLevel.Environment,
),
// required & use once
@ -484,7 +465,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// required & use once
assetBundle(
this.get('simulatorUrl') ||
(this.renderEnv === 'rax' ? defaultRaxSimulatorUrl : defaultSimulatorUrl),
defaultSimulatorUrl,
AssetLevel.Runtime,
),
];
@ -851,16 +832,22 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
doc.addEventListener('contextmenu', (e: MouseEvent) => {
const targetElement = e.target as HTMLElement;
const nodeInst = this.getNodeInstanceFromElement(targetElement);
const editor = this.designer?.editor;
if (!nodeInst) {
editor?.eventBus.emit('designer.builtinSimulator.contextmenu', {
originalEvent: e,
});
return;
}
const node = nodeInst.node || this.project.currentDocument?.focusNode;
if (!node) {
editor?.eventBus.emit('designer.builtinSimulator.contextmenu', {
originalEvent: e,
});
return;
}
// dirty code should refector
const editor = this.designer?.editor;
const npm = node?.componentMeta?.npm;
const selected =
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
@ -1069,15 +1056,15 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
return null;
}
const nodeIntance = this.getClosestNodeInstance(target);
if (!nodeIntance) {
const nodeInstance = this.getClosestNodeInstance(target);
if (!nodeInstance) {
return null;
}
const { docId } = nodeIntance;
const { docId } = nodeInstance;
const doc = this.project.getDocument(docId)!;
const node = doc.getNode(nodeIntance.nodeId);
const node = doc.getNode(nodeInstance.nodeId);
return {
...nodeIntance,
...nodeInstance,
node,
};
}

View File

@ -2,3 +2,4 @@ export * from './host';
export * from './host-view';
export * from './renderer';
export * from './live-editing/live-editing';
export { LowcodeTypes } from './utils/parse-metadata';

View File

@ -48,7 +48,7 @@
margin-top: 2px;
&-content {
padding-left: 6px;
background: #78869a;
background: var(--color-layer-tooltip-background, #78869a);
display: inline-flex;
border-radius: 3px;
align-items: center;

View File

@ -16,8 +16,16 @@ export const primitiveTypes = [
'any',
];
interface LowcodeCheckType {
// isRequired, props, propName, componentName, location, propFullName, secret
(props: any, propName: string, componentName: string, ...rest: any[]): Error | null;
// (...reset: any[]): Error | null;
isRequired?: LowcodeCheckType;
type?: string | object;
}
// eslint-disable-next-line @typescript-eslint/ban-types
function makeRequired(propType: any, lowcodeType: string | object) {
function makeRequired(propType: any, lowcodeType: string | object): LowcodeCheckType {
function lowcodeCheckTypeIsRequired(...rest: any[]) {
return propType.isRequired(...rest);
}
@ -34,7 +42,7 @@ function makeRequired(propType: any, lowcodeType: string | object) {
}
// eslint-disable-next-line @typescript-eslint/ban-types
function define(propType: any = PropTypes.any, lowcodeType: string | object = {}) {
function define(propType: any = PropTypes.any, lowcodeType: string | object = {}): LowcodeCheckType {
if (!propType._inner && propType.name !== 'lowcodeCheckType') {
propType.lowcodeType = lowcodeType;
}
@ -46,13 +54,15 @@ function define(propType: any = PropTypes.any, lowcodeType: string | object = {}
return lowcodeCheckType;
}
const LowcodeTypes: any = {
export const LowcodeTypes: any = {
...PropTypes,
define,
};
(window as any).PropTypes = LowcodeTypes;
(window as any).React.PropTypes = LowcodeTypes;
if ((window as any).React) {
(window as any).React.PropTypes = LowcodeTypes;
}
// override primitive type checkers
primitiveTypes.forEach((type) => {

View File

@ -1,4 +1,4 @@
import { IPublicTypeComponentAction, IPublicTypeMetadataTransducer } from '@alilc/lowcode-types';
import { IPublicModelNode, IPublicTypeComponentAction, IPublicTypeMetadataTransducer } from '@alilc/lowcode-types';
import { engineConfig } from '@alilc/lowcode-editor-core';
import { intlNode } from './locale';
import {
@ -8,10 +8,19 @@ import {
IconClone,
IconHidden,
} from './icons';
import { Node } from './document';
import { componentDefaults, legacyIssues } from './transducers';
function deduplicateRef(node: IPublicModelNode | null | undefined) {
const currentRef = node?.getPropValue('ref');
if (currentRef) {
node?.setPropValue('ref', `${node.componentName.toLowerCase()}-${Math.random().toString(36).slice(2, 9)}`);
}
node?.children?.forEach(deduplicateRef);
}
export class ComponentActions {
private metadataTransducers: IPublicTypeMetadataTransducer[] = [];
actions: IPublicTypeComponentAction[] = [
{
name: 'remove',
@ -19,7 +28,7 @@ export class ComponentActions {
icon: IconRemove,
title: intlNode('remove'),
/* istanbul ignore next */
action(node: Node) {
action(node: IPublicModelNode) {
node.remove();
},
},
@ -31,13 +40,13 @@ export class ComponentActions {
icon: IconHidden,
title: intlNode('hide'),
/* istanbul ignore next */
action(node: Node) {
node.setVisible(false);
action(node: IPublicModelNode) {
node.visible = false;
},
},
/* istanbul ignore next */
condition: (node: Node) => {
return node.componentMeta.isModal;
condition: (node: IPublicModelNode) => {
return node.componentMeta?.isModal;
},
important: true,
},
@ -47,25 +56,26 @@ export class ComponentActions {
icon: IconClone,
title: intlNode('copy'),
/* istanbul ignore next */
action(node: Node) {
action(node: IPublicModelNode) {
// node.remove();
const { document: doc, parent, index } = node;
if (parent) {
const newNode = doc.insertNode(parent, node, index + 1, true);
newNode.select();
const { isRGL, rglNode } = node.getRGL();
const newNode = doc?.insertNode(parent, node, (index ?? 0) + 1, true);
deduplicateRef(newNode);
newNode?.select();
const { isRGL, rglNode } = node?.getRGL();
if (isRGL) {
// 复制 layout 信息
const layout = rglNode.getPropValue('layout') || [];
const curLayout = layout.filter((item) => item.i === node.getPropValue('fieldId'));
const layout: any = rglNode?.getPropValue('layout') || [];
const curLayout = layout.filter((item: any) => item.i === node.getPropValue('fieldId'));
if (curLayout && curLayout[0]) {
layout.push({
...curLayout[0],
i: newNode.getPropValue('fieldId'),
i: newNode?.getPropValue('fieldId'),
});
rglNode.setPropValue('layout', layout);
rglNode?.setPropValue('layout', layout);
// 如果是磁贴块复制,则需要滚动到影响位置
setTimeout(() => newNode.document.simulator?.scrollToNode(newNode), 10);
setTimeout(() => newNode?.document?.project?.simulatorHost?.scrollToNode(newNode), 10);
}
}
}
@ -79,13 +89,13 @@ export class ComponentActions {
icon: IconLock, // 锁定 icon
title: intlNode('lock'),
/* istanbul ignore next */
action(node: Node) {
action(node: IPublicModelNode) {
node.lock();
},
},
/* istanbul ignore next */
condition: (node: Node) => {
return engineConfig.get('enableCanvasLock', false) && node.isContainer() && !node.isLocked;
condition: (node: IPublicModelNode) => {
return engineConfig.get('enableCanvasLock', false) && node.isContainerNode && !node.isLocked;
},
important: true,
},
@ -95,13 +105,13 @@ export class ComponentActions {
icon: IconUnlock, // 解锁 icon
title: intlNode('unlock'),
/* istanbul ignore next */
action(node: Node) {
action(node: IPublicModelNode) {
node.lock(false);
},
},
/* istanbul ignore next */
condition: (node: Node) => {
return engineConfig.get('enableCanvasLock', false) && node.isContainer() && node.isLocked;
condition: (node: IPublicModelNode) => {
return engineConfig.get('enableCanvasLock', false) && node.isContainerNode && node.isLocked;
},
important: true,
},
@ -132,8 +142,6 @@ export class ComponentActions {
}
}
private metadataTransducers: IPublicTypeMetadataTransducer[] = [];
registerMetadataTransducer(
transducer: IPublicTypeMetadataTransducer,
level = 100,

View File

@ -48,13 +48,17 @@ export function buildFilter(rule?: string | string[] | RegExp | IPublicTypeNesti
return rule;
}
if (isRegExp(rule)) {
return (testNode: Node | IPublicTypeNodeSchema) => rule.test(testNode.componentName);
return (testNode: Node | IPublicTypeNodeSchema) => {
return rule.test(testNode.componentName);
};
}
const list = ensureAList(rule);
if (!list) {
return null;
}
return (testNode: Node | IPublicTypeNodeSchema) => list.includes(testNode.componentName);
return (testNode: Node | IPublicTypeNodeSchema) => {
return list.includes(testNode.componentName);
};
}
export interface IComponentMeta extends IPublicModelComponentMeta<INode> {

View File

@ -0,0 +1,10 @@
.engine-context-menu {
&.next-menu.next-ver .next-menu-item {
padding-right: 30px;
.next-menu-item-inner {
height: var(--context-menu-item-height, 30px);
line-height: var(--context-menu-item-height, 30px);
}
}
}

View File

@ -0,0 +1,233 @@
import { IPublicTypeContextMenuAction, IPublicEnumContextMenuType, IPublicTypeContextMenuItem, IPublicApiMaterial, IPublicModelPluginContext } from '@alilc/lowcode-types';
import { IDesigner, INode } from './designer';
import { createContextMenu, parseContextMenuAsReactNode, parseContextMenuProperties, uniqueId } from '@alilc/lowcode-utils';
import { Menu } from '@alifd/next';
import { engineConfig } from '@alilc/lowcode-editor-core';
import './context-menu-actions.scss';
export interface IContextMenuActions {
actions: IPublicTypeContextMenuAction[];
adjustMenuLayoutFn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[];
addMenuAction: IPublicApiMaterial['addContextMenuOption'];
removeMenuAction: IPublicApiMaterial['removeContextMenuOption'];
adjustMenuLayout: IPublicApiMaterial['adjustContextMenuLayout'];
}
let adjustMenuLayoutFn: Function = (actions: IPublicTypeContextMenuAction[]) => actions;
export class GlobalContextMenuActions {
enableContextMenu: boolean;
dispose: Function[];
contextMenuActionsMap: Map<string, ContextMenuActions> = new Map();
constructor() {
this.dispose = [];
engineConfig.onGot('enableContextMenu', (enable) => {
if (this.enableContextMenu === enable) {
return;
}
this.enableContextMenu = enable;
this.dispose.forEach(d => d());
if (enable) {
this.initEvent();
}
});
}
handleContextMenu = (
event: MouseEvent,
) => {
event.stopPropagation();
event.preventDefault();
const actions: IPublicTypeContextMenuAction[] = [];
let contextMenu: ContextMenuActions = this.contextMenuActionsMap.values().next().value;
this.contextMenuActionsMap.forEach((contextMenu) => {
actions.push(...contextMenu.actions);
});
let destroyFn: Function | undefined;
const destroy = () => {
destroyFn?.();
};
const pluginContext: IPublicModelPluginContext = contextMenu.designer.editor.get('pluginContext') as IPublicModelPluginContext;
const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, {
nodes: [],
destroy,
event,
pluginContext,
});
if (!menus.length) {
return;
}
const layoutMenu = adjustMenuLayoutFn(menus);
const menuNode = parseContextMenuAsReactNode(layoutMenu, {
destroy,
nodes: [],
pluginContext,
});
const target = event.target;
const { top, left } = target?.getBoundingClientRect();
const menuInstance = Menu.create({
target: event.target,
offset: [event.clientX - left, event.clientY - top],
children: menuNode,
className: 'engine-context-menu',
});
destroyFn = (menuInstance as any).destroy;
};
initEvent() {
this.dispose.push(
(() => {
const handleContextMenu = (e: MouseEvent) => {
this.handleContextMenu(e);
};
document.addEventListener('contextmenu', handleContextMenu);
return () => {
document.removeEventListener('contextmenu', handleContextMenu);
};
})(),
);
}
registerContextMenuActions(contextMenu: ContextMenuActions) {
this.contextMenuActionsMap.set(contextMenu.id, contextMenu);
}
}
const globalContextMenuActions = new GlobalContextMenuActions();
export class ContextMenuActions implements IContextMenuActions {
actions: IPublicTypeContextMenuAction[] = [];
designer: IDesigner;
dispose: Function[];
enableContextMenu: boolean;
id: string = uniqueId('contextMenu');;
constructor(designer: IDesigner) {
this.designer = designer;
this.dispose = [];
engineConfig.onGot('enableContextMenu', (enable) => {
if (this.enableContextMenu === enable) {
return;
}
this.enableContextMenu = enable;
this.dispose.forEach(d => d());
if (enable) {
this.initEvent();
}
});
globalContextMenuActions.registerContextMenuActions(this);
}
handleContextMenu = (
nodes: INode[],
event: MouseEvent,
) => {
const designer = this.designer;
event.stopPropagation();
event.preventDefault();
const actions = designer.contextMenuActions.actions;
const { bounds } = designer.project.simulator?.viewport || { bounds: { left: 0, top: 0 } };
const { left: simulatorLeft, top: simulatorTop } = bounds;
let destroyFn: Function | undefined;
const destroy = () => {
destroyFn?.();
};
const pluginContext: IPublicModelPluginContext = this.designer.editor.get('pluginContext') as IPublicModelPluginContext;
const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, {
nodes: nodes.map(d => designer.shellModelFactory.createNode(d)!),
destroy,
event,
pluginContext,
});
if (!menus.length) {
return;
}
const layoutMenu = adjustMenuLayoutFn(menus);
const menuNode = parseContextMenuAsReactNode(layoutMenu, {
destroy,
nodes: nodes.map(d => designer.shellModelFactory.createNode(d)!),
pluginContext,
});
destroyFn = createContextMenu(menuNode, {
event,
offset: [simulatorLeft, simulatorTop],
});
};
initEvent() {
const designer = this.designer;
this.dispose.push(
designer.editor.eventBus.on('designer.builtinSimulator.contextmenu', ({
node,
originalEvent,
}: {
node: INode;
originalEvent: MouseEvent;
}) => {
originalEvent.stopPropagation();
originalEvent.preventDefault();
// 如果右键的节点不在 当前选中的节点中,选中该节点
if (!designer.currentSelection.has(node.id)) {
designer.currentSelection.select(node.id);
}
const nodes = designer.currentSelection.getNodes();
this.handleContextMenu(nodes, originalEvent);
}),
);
}
addMenuAction(action: IPublicTypeContextMenuAction) {
this.actions.push({
type: IPublicEnumContextMenuType.MENU_ITEM,
...action,
});
}
removeMenuAction(name: string) {
const i = this.actions.findIndex((action) => action.name === name);
if (i > -1) {
this.actions.splice(i, 1);
}
}
adjustMenuLayout(fn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[]) {
adjustMenuLayoutFn = fn;
}
}

View File

@ -36,6 +36,10 @@ class Clipboard implements IClipboard {
private waitFn?: (data: any, e: ClipboardEvent) => void;
constructor() {
this.injectCopyPaster(document);
}
isCopyPasteEvent(e: Event) {
this.isCopyPaster(e.target);
}
@ -69,7 +73,13 @@ class Clipboard implements IClipboard {
}
const copyPaster = document.createElement<'textarea'>('textarea');
copyPaster.style.cssText = 'position: absolute;left: -9999px;top:-100px';
document.body.appendChild(copyPaster);
if (document.body) {
document.body.appendChild(copyPaster);
} else {
document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(copyPaster);
});
}
const dispose = this.initCopyPaster(copyPaster);
return () => {
dispose();

View File

@ -4,7 +4,6 @@ import BuiltinDragGhostComponent from './drag-ghost';
import { Designer, DesignerProps } from './designer';
import { ProjectView } from '../project';
import './designer.less';
import { clipboard } from './clipboard';
type IProps = DesignerProps & {
designer?: Designer;
@ -44,7 +43,6 @@ export class DesignerView extends Component<IProps> {
if (onMount) {
onMount(this.designer);
}
clipboard.injectCopyPaster(document);
this.designer.postEvent('mount', this.designer);
}

View File

@ -18,9 +18,9 @@ import {
IPublicEnumTransformStage,
IPublicModelLocateEvent,
} from '@alilc/lowcode-types';
import { megreAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils';
import { mergeAssets, IPublicTypeAssetsJson, isNodeSchema, isDragNodeObject, isDragNodeDataObject, isLocationChildrenDetail, Logger } from '@alilc/lowcode-utils';
import { IProject, Project } from '../project';
import { Node, DocumentModel, insertChildren, INode } from '../document';
import { Node, DocumentModel, insertChildren, INode, ISelection } from '../document';
import { ComponentMeta, IComponentMeta } from '../component-meta';
import { INodeSelector, Component } from '../simulator';
import { Scroller } from './scroller';
@ -32,6 +32,7 @@ import { OffsetObserver, createOffsetObserver } from './offset-observer';
import { ISettingTopEntry, SettingTopEntry } from './setting';
import { BemToolsManager } from '../builtin-simulator/bem-tools/manager';
import { ComponentActions } from '../component-actions';
import { ContextMenuActions, IContextMenuActions } from '../context-menu-actions';
const logger = new Logger({ level: 'warn', bizName: 'designer' });
@ -72,12 +73,16 @@ export interface IDesigner {
get componentActions(): ComponentActions;
get contextMenuActions(): ContextMenuActions;
get editor(): IPublicModelEditor;
get detecting(): Detecting;
get simulatorComponent(): ComponentType<any> | undefined;
get currentSelection(): ISelection;
createScroller(scrollable: IPublicTypeScrollable): IPublicModelScroller;
refreshComponentMetasMap(): void;
@ -122,6 +127,8 @@ export class Designer implements IDesigner {
readonly componentActions = new ComponentActions();
readonly contextMenuActions: IContextMenuActions;
readonly activeTracker = new ActiveTracker();
readonly detecting = new Detecting();
@ -198,6 +205,8 @@ export class Designer implements IDesigner {
this.postEvent('dragstart', e);
});
this.contextMenuActions = new ContextMenuActions(this);
this.dragon.onDrag((e) => {
if (this.props?.onDrag) {
this.props.onDrag(e);
@ -458,7 +467,7 @@ export class Designer implements IDesigner {
if (components) {
// 合并 assets
let assets = this.editor.get('assets') || {};
let newAssets = megreAssets(assets, incrementalAssets);
let newAssets = mergeAssets(assets, incrementalAssets);
// 对于 assets 存在需要二次网络下载的过程,必须 await 等待结束之后,再进行事件触发
await this.editor.set('assets', newAssets);
}

View File

@ -7,8 +7,8 @@
flex-direction: column;
align-items: center;
pointer-events: none;
background-color: rgba(0, 0, 0, 0.4);
box-shadow: 0 0 6px grey;
background-color: var(--color-block-background-deep-dark, rgba(0, 0, 0, 0.4));
box-shadow: 0 0 6px var(--color-block-background-shallow, grey);
transform: translate(-10%, -50%);
.lc-ghost {
.lc-ghost-title {

View File

@ -46,7 +46,7 @@ function easing(n: number) {
return Math.sin((n * Math.PI) / 2);
}
const SCROLL_ACCURCY = 30;
const SCROLL_ACCURACY = 30;
export interface IScroller extends IPublicModelScroller {
@ -142,15 +142,15 @@ export class Scroller implements IScroller {
let sy = scrollTarget.top;
let ax = 0;
let ay = 0;
if (y < bounds.top + SCROLL_ACCURCY) {
ay = -Math.min(Math.max(bounds.top + SCROLL_ACCURCY - y, 10), 50) / scale;
} else if (y > bounds.bottom - SCROLL_ACCURCY) {
ay = Math.min(Math.max(y + SCROLL_ACCURCY - bounds.bottom, 10), 50) / scale;
if (y < bounds.top + SCROLL_ACCURACY) {
ay = -Math.min(Math.max(bounds.top + SCROLL_ACCURACY - y, 10), 50) / scale;
} else if (y > bounds.bottom - SCROLL_ACCURACY) {
ay = Math.min(Math.max(y + SCROLL_ACCURACY - bounds.bottom, 10), 50) / scale;
}
if (x < bounds.left + SCROLL_ACCURCY) {
ax = -Math.min(Math.max(bounds.top + SCROLL_ACCURCY - y, 10), 50) / scale;
} else if (x > bounds.right - SCROLL_ACCURCY) {
ax = Math.min(Math.max(x + SCROLL_ACCURCY - bounds.right, 10), 50) / scale;
if (x < bounds.left + SCROLL_ACCURACY) {
ax = -Math.min(Math.max(bounds.top + SCROLL_ACCURACY - y, 10), 50) / scale;
} else if (x > bounds.right - SCROLL_ACCURACY) {
ax = Math.min(Math.max(x + SCROLL_ACCURACY - bounds.right, 10), 50) / scale;
}
if (!ax && !ay) {

View File

@ -1,4 +1,4 @@
import { IPublicTypeCustomView, IPublicModelEditor, IPublicModelSettingTopEntry } from '@alilc/lowcode-types';
import { IPublicTypeCustomView, IPublicModelEditor, IPublicModelSettingTopEntry, IPublicApiSetters } from '@alilc/lowcode-types';
import { isCustomView } from '@alilc/lowcode-utils';
import { computed, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core';
import { ISettingEntry } from './setting-entry-type';
@ -6,7 +6,6 @@ import { ISettingField, SettingField } from './setting-field';
import { INode } from '../../document';
import type { IComponentMeta } from '../../component-meta';
import { IDesigner } from '../designer';
import { Setters } from '@alilc/lowcode-shell';
function generateSessionId(nodes: INode[]) {
return nodes
@ -19,18 +18,18 @@ export interface ISettingTopEntry extends ISettingEntry, IPublicModelSettingTopE
INode,
ISettingField
> {
purge(): void;
items: Array<ISettingField | IPublicTypeCustomView>;
readonly top: ISettingTopEntry;
readonly parent: ISettingTopEntry;
readonly path: never[];
items: Array<ISettingField | IPublicTypeCustomView>;
componentMeta: IComponentMeta | null;
purge(): void;
getExtraPropValue(propName: string): void;
setExtraPropValue(propName: string, value: any): void;
@ -92,7 +91,7 @@ export class SettingTopEntry implements ISettingTopEntry {
readonly designer: IDesigner | undefined;
readonly setters: Setters;
readonly setters: IPublicApiSetters;
disposeFunctions: any[] = [];
@ -103,7 +102,7 @@ export class SettingTopEntry implements ISettingTopEntry {
this.id = generateSessionId(nodes);
this.first = nodes[0];
this.designer = this.first.document?.designer;
this.setters = editor.get('setters') as Setters;
this.setters = editor.get('setters') as IPublicApiSetters;
// setups
this.setupComponentMeta();

View File

@ -70,7 +70,7 @@ export class Transducer {
}
if (isDynamicSetter(setter) && isDynamic) {
try {
setter = setter.call(context, context);
setter = setter.call(context.internalToShellField(), context.internalToShellField());
} catch (e) { console.error(e); }
}

View File

@ -74,7 +74,6 @@ export interface IDocumentModel extends Omit<IPublicModelDocumentModel<
'onRemoveNode' |
'onChangeDetecting' |
'onChangeSelection' |
'onMountNode' |
'onChangeNodeProp' |
'onImportSchema' |
'isDetectingNode' |
@ -414,6 +413,14 @@ export class DocumentModel implements IDocumentModel {
return node ? !node.isPurged : false;
}
onMountNode(fn: (payload: { node: INode }) => void) {
this.designer.editor.eventBus.on('node.add', fn as any);
return () => {
this.designer.editor.eventBus.off('node.add', fn as any);
};
}
/**
* schema
*/

View File

@ -462,6 +462,9 @@ export class NodeChildren implements INodeChildren {
const node: INode = this.owner.document?.createNode(child);
this.children.push(node);
node.internalSetParent(this.owner);
/* istanbul ignore next */
const editor = node.document?.designer.editor;
editor?.eventBus.emit('node.add', { node });
});
changed = true;
}

View File

@ -392,7 +392,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
this.isInited = true;
this.emitter = createModuleEventBus('Node');
const editor = this.document.designer.editor;
const { editor } = this.document.designer;
this.onVisibleChange((visible: boolean) => {
editor?.eventBus.emit(EDITOR_EVENT.NODE_VISIBLE_CHANGE, this, visible);
});
@ -440,23 +440,23 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
}
private initialChildren(children: IPublicTypeNodeData | IPublicTypeNodeData[] | undefined): IPublicTypeNodeData[] {
// FIXME! this is dirty code
const { initialChildren } = this.componentMeta.advanced;
if (children == null) {
const { initialChildren } = this.componentMeta.advanced;
if (initialChildren) {
if (typeof initialChildren === 'function') {
return initialChildren(this.internalToShellNode()!) || [];
}
return initialChildren;
}
}
if (Array.isArray(children)) {
return children;
} else if (children) {
return [children];
} else {
return [];
}
if (Array.isArray(children)) {
return children;
}
return [children];
}
isContainer(): boolean {
@ -1094,7 +1094,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
}
/**
* action
* action
*/
canPerformAction(actionName: string): boolean {
const availableActions =
@ -1219,13 +1219,20 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
/**
*
*/
getRGL() {
getRGL(): {
isContainerNode: boolean;
isEmptyNode: boolean;
isRGLContainerNode: boolean;
isRGLNode: boolean;
isRGL: boolean;
rglNode: Node | null;
} {
const isContainerNode = this.isContainer();
const isEmptyNode = this.isEmpty();
const isRGLContainerNode = this.isRGLContainer;
const isRGLNode = this.getParent()?.isRGLContainer;
const isRGLNode = (this.getParent()?.isRGLContainer) as boolean;
const isRGL = isRGLContainerNode || (isRGLNode && (!isContainerNode || !isEmptyNode));
let rglNode = isRGLContainerNode ? this : isRGL ? this?.getParent() : {};
let rglNode = isRGLContainerNode ? this : isRGL ? this?.getParent() : null;
return { isContainerNode, isEmptyNode, isRGLContainerNode, isRGLNode, isRGL, rglNode };
}

View File

@ -290,10 +290,6 @@ export class Prop implements IProp, IPropParent {
}
if (type === 'literal' || type === 'expression') {
// TODO 后端改造之后删除此逻辑
if (this._value === null && stage === IPublicEnumTransformStage.Save) {
return '';
}
return this._value;
}
@ -357,7 +353,6 @@ export class Prop implements IProp, IPropParent {
@action
setValue(val: IPublicTypeCompositeValue) {
if (val === this._value) return;
const editor = this.owner.document?.designer.editor;
const oldValue = this._value;
this._value = val;
this._code = null;
@ -390,22 +385,31 @@ export class Prop implements IProp, IPropParent {
this.setupItems();
if (oldValue !== this._value) {
const propsInfo = {
key: this.key,
prop: this,
oldValue,
newValue: this._value,
};
editor?.eventBus.emit(GlobalEvent.Node.Prop.InnerChange, {
node: this.owner as any,
...propsInfo,
});
this.owner?.emitPropChange?.(propsInfo);
this.emitChange({ oldValue });
}
}
emitChange = ({
oldValue,
}: {
oldValue: IPublicTypeCompositeValue | UNSET;
}) => {
const editor = this.owner.document?.designer.editor;
const propsInfo = {
key: this.key,
prop: this,
oldValue,
newValue: this.type === 'unset' ? undefined : this._value,
};
editor?.eventBus.emit(GlobalEvent.Node.Prop.InnerChange, {
node: this.owner as any,
...propsInfo,
});
this.owner?.emitPropChange?.(propsInfo);
};
getValue(): IPublicTypeCompositeValue {
return this.export(IPublicEnumTransformStage.Serilize);
}
@ -466,7 +470,12 @@ export class Prop implements IProp, IPropParent {
*/
@action
unset() {
this._type = 'unset';
if (this._type !== 'unset') {
this._type = 'unset';
this.emitChange({
oldValue: this._value,
});
}
}
/**
@ -561,6 +570,7 @@ export class Prop implements IProp, IPropParent {
@action
remove() {
this.parent.delete(this);
this.unset();
}
/**

View File

@ -6,3 +6,4 @@ export * from './project';
export * from './builtin-simulator';
export * from './plugin';
export * from './types';
export * from './context-menu-actions';

View File

@ -99,19 +99,19 @@
@brand-link-hover: #2e76a6;
// F1-1-7 A10
@brand-danger-alpha-7: rgba(240, 70, 49, 0.9);
@brand-danger-alpha-7: rgba(240, 70, 49, 0.1);
// F1-1-8 A6
@brand-danger-alpha-8: rgba(240, 70, 49, 0.8);
// F2-1-2 A80
@brand-warning-alpha-2: rgba(250, 189, 14, 0.8);
// F2-1-7 A10
@brand-warning-alpha-7: rgba(250, 189, 14, 0.9);
@brand-warning-alpha-7: rgba(250, 189, 14, 0.1);
// F3-1-2 A80
@brand-success-alpha-2: rgba(102, 188, 92, 0.8);
// F3-1-7 A10
@brand-success-alpha-7: rgba(102, 188, 92, 0.9);
@brand-success-alpha-7: rgba(102, 188, 92, 0.1);
// F4-1-7 A10
@brand-link-alpha-7: rgba(102, 188, 92, 0.9);
@brand-link-alpha-7: rgba(102, 188, 92, 0.1);
// 文本色
@text-primary-color: @dark-alpha-3;

View File

@ -19,6 +19,7 @@ import {
IPublicApiWorkspace,
IPublicEnumPluginRegisterLevel,
IPublicModelWindow,
IPublicApiCommonUI,
} from '@alilc/lowcode-types';
import {
IPluginContextOptions,
@ -45,6 +46,8 @@ export default class PluginContext implements
workspace: IPublicApiWorkspace;
registerLevel: IPublicEnumPluginRegisterLevel;
editorWindow: IPublicModelWindow;
commonUI: IPublicApiCommonUI;
isPluginRegisteredInWorkspace: false;
constructor(
options: IPluginContextOptions,

View File

@ -18,6 +18,8 @@ import {
IPublicTypePluginRegisterOptions,
IPublicModelWindow,
IPublicEnumPluginRegisterLevel,
IPublicApiCommonUI,
IPublicApiCommand,
} from '@alilc/lowcode-types';
import PluginContext from './plugin-context';
@ -60,6 +62,9 @@ export interface ILowCodePluginContextPrivate {
set workspace(workspace: IPublicApiWorkspace);
set editorWindow(window: IPublicModelWindow);
set registerLevel(level: IPublicEnumPluginRegisterLevel);
set isPluginRegisteredInWorkspace(flag: boolean);
set commonUI(commonUI: IPublicApiCommonUI);
set command(command: IPublicApiCommand);
}
export interface ILowCodePluginContextApiAssembler {
assembleApis(

View File

@ -1,19 +1,50 @@
function sequence(tasks, names, results, missing, recursive, nest) {
interface ITaks {
[key: string]: {
name: string;
dep: string[];
};
}
export function sequence({
tasks,
names,
results,
missing,
recursive,
nest,
parentName,
}: {
tasks: ITaks;
names: string[];
results: string[];
missing: string[];
recursive: string[][];
nest: string[];
parentName: string;
}) {
names.forEach((name) => {
if (results.indexOf(name) !== -1) {
return; // de-dup results
}
const node = tasks[name];
if (!node) {
missing.push(name);
missing.push([parentName, name].filter((d => !!d)).join('.'));
} else if (nest.indexOf(name) > -1) {
nest.push(name);
recursive.push(nest.slice(0));
nest.pop(name);
nest.pop();
} else if (node.dep.length) {
nest.push(name);
sequence(tasks, node.dep, results, missing, recursive, nest); // recurse
nest.pop(name);
sequence({
tasks,
parentName: name,
names: node.dep,
results,
missing,
recursive,
nest,
}); // recurse
nest.pop();
}
results.push(name);
});
@ -21,12 +52,19 @@ function sequence(tasks, names, results, missing, recursive, nest) {
// tasks: object with keys as task names
// names: array of task names
export default function (tasks, names) {
let results = []; // the final sequence
const missing = []; // missing tasks
const recursive = []; // recursive task dependencies
export default function (tasks: ITaks, names: string[]) {
let results: string[] = []; // the final sequence
const missing: string[] = []; // missing tasks
const recursive: string[][] = []; // recursive task dependencies
sequence(tasks, names, results, missing, recursive, []);
sequence({
tasks,
names,
results,
missing,
recursive,
nest: [],
});
if (missing.length || recursive.length) {
results = []; // results are incomplete at best, completely wrong at worst, remove them to avoid confusion

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