mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-04 17:27:09 +00:00
feat: 加上 plugin-outline-pane
This commit is contained in:
parent
e599acd2f0
commit
83c0772bc5
106
packages/plugin-outline-pane/.gitignore
vendored
Normal file
106
packages/plugin-outline-pane/.gitignore
vendored
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# project custom
|
||||||
|
build
|
||||||
|
dist
|
||||||
|
packages/*/lib/
|
||||||
|
packages/*/es/
|
||||||
|
packages/*/dist/
|
||||||
|
packages/*/output/
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
deploy-space/packages
|
||||||
|
deploy-space/.env
|
||||||
|
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
lib
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# mac config files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# codealike
|
||||||
|
codealike.json
|
||||||
665
packages/plugin-outline-pane/CHANGELOG.md
Normal file
665
packages/plugin-outline-pane/CHANGELOG.md
Normal file
@ -0,0 +1,665 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="1.0.21"></a>
|
||||||
|
## [1.0.21](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.20...@ali/lowcode-plugin-outline-pane@1.0.21) (2020-11-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.20"></a>
|
||||||
|
## [1.0.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.19...@ali/lowcode-plugin-outline-pane@1.0.20) (2020-11-10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.19"></a>
|
||||||
|
## [1.0.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.18...@ali/lowcode-plugin-outline-pane@1.0.19) (2020-11-10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.18"></a>
|
||||||
|
## [1.0.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.17...@ali/lowcode-plugin-outline-pane@1.0.18) (2020-11-05)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.17"></a>
|
||||||
|
## [1.0.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.16...@ali/lowcode-plugin-outline-pane@1.0.17) (2020-11-05)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.16"></a>
|
||||||
|
## [1.0.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.15...@ali/lowcode-plugin-outline-pane@1.0.16) (2020-11-05)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.15"></a>
|
||||||
|
## [1.0.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.14...@ali/lowcode-plugin-outline-pane@1.0.15) (2020-11-04)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.14"></a>
|
||||||
|
## [1.0.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.13...@ali/lowcode-plugin-outline-pane@1.0.14) (2020-11-04)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.13"></a>
|
||||||
|
## [1.0.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.12...@ali/lowcode-plugin-outline-pane@1.0.13) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.12"></a>
|
||||||
|
## [1.0.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.11...@ali/lowcode-plugin-outline-pane@1.0.12) (2020-10-20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.11"></a>
|
||||||
|
## [1.0.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.10...@ali/lowcode-plugin-outline-pane@1.0.11) (2020-10-19)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.10"></a>
|
||||||
|
## [1.0.10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.9...@ali/lowcode-plugin-outline-pane@1.0.10) (2020-09-29)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.9"></a>
|
||||||
|
## [1.0.9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.8...@ali/lowcode-plugin-outline-pane@1.0.9) (2020-09-28)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.8"></a>
|
||||||
|
## [1.0.8](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.8-0...@ali/lowcode-plugin-outline-pane@1.0.8) (2020-09-28)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.8-0"></a>
|
||||||
|
## [1.0.8-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.61...@ali/lowcode-plugin-outline-pane@1.0.8-0) (2020-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 合并master分支 ([bd2c6ad](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/bd2c6ad))
|
||||||
|
* 兼容modal模式 ([1092ee9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/1092ee9))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="1.0.7-0"></a>
|
||||||
|
## [1.0.7-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.6-0...@ali/lowcode-plugin-outline-pane@1.0.7-0) (2020-09-02)
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.61"></a>
|
||||||
|
## [0.8.61](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.60...@ali/lowcode-plugin-outline-pane@0.8.61) (2020-09-08)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.60"></a>
|
||||||
|
## [0.8.60](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.59...@ali/lowcode-plugin-outline-pane@0.8.60) (2020-09-03)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.59"></a>
|
||||||
|
## [0.8.59](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.58...@ali/lowcode-plugin-outline-pane@0.8.59) (2020-09-03)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.58"></a>
|
||||||
|
## [0.8.58](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.57...@ali/lowcode-plugin-outline-pane@0.8.58) (2020-08-27)
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.6-0"></a>
|
||||||
|
## [1.0.6-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.58...@ali/lowcode-plugin-outline-pane@1.0.6-0) (2020-09-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 合并master分支 ([bd2c6ad](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/bd2c6ad))
|
||||||
|
* 兼容modal模式 ([1092ee9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/1092ee9))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="1.0.5-0"></a>
|
||||||
|
## [1.0.5-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.4-0...@ali/lowcode-plugin-outline-pane@1.0.5-0) (2020-08-20)
|
||||||
|
<a name="0.8.54"></a>
|
||||||
|
## [0.8.54](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.53...@ali/lowcode-plugin-outline-pane@0.8.54) (2020-08-20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.4-0"></a>
|
||||||
|
## [1.0.4-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.3-0...@ali/lowcode-plugin-outline-pane@1.0.4-0) (2020-08-20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.3-0"></a>
|
||||||
|
## [1.0.3-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.2-0...@ali/lowcode-plugin-outline-pane@1.0.3-0) (2020-08-20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.2-0"></a>
|
||||||
|
## [1.0.2-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@1.0.1-0...@ali/lowcode-plugin-outline-pane@1.0.2-0) (2020-08-20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="1.0.1-0"></a>
|
||||||
|
## [1.0.1-0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.53...@ali/lowcode-plugin-outline-pane@1.0.1-0) (2020-08-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 兼容modal模式 ([1092ee9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/1092ee9))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="1.0.0"></a>
|
||||||
|
# [1.0.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.13.0...@ali/lowcode-plugin-outline-pane@1.0.0) (2020-08-17)
|
||||||
|
<a name="0.8.53"></a>
|
||||||
|
## [0.8.53](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.52...@ali/lowcode-plugin-outline-pane@0.8.53) (2020-08-19)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.52"></a>
|
||||||
|
## [0.8.52](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.51...@ali/lowcode-plugin-outline-pane@0.8.52) (2020-08-19)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.51"></a>
|
||||||
|
## [0.8.51](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.50...@ali/lowcode-plugin-outline-pane@0.8.51) (2020-08-19)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.50"></a>
|
||||||
|
## [0.8.50](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.49...@ali/lowcode-plugin-outline-pane@0.8.50) (2020-08-17)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.49"></a>
|
||||||
|
## [0.8.49](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.48...@ali/lowcode-plugin-outline-pane@0.8.49) (2020-08-14)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.13.0"></a>
|
||||||
|
# [0.13.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.12.0...@ali/lowcode-plugin-outline-pane@0.13.0) (2020-08-17)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.12.0"></a>
|
||||||
|
# [0.12.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.10.0...@ali/lowcode-plugin-outline-pane@0.12.0) (2020-08-17)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.11.0"></a>
|
||||||
|
# [0.11.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.10.0...@ali/lowcode-plugin-outline-pane@0.11.0) (2020-08-17)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.10.0"></a>
|
||||||
|
# [0.10.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.9.0...@ali/lowcode-plugin-outline-pane@0.10.0) (2020-08-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.9.0"></a>
|
||||||
|
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.43...@ali/lowcode-plugin-outline-pane@0.9.0) (2020-08-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 兼容modal模式 ([1092ee9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/1092ee9))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.43"></a>
|
||||||
|
## [0.8.43](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.42...@ali/lowcode-plugin-outline-pane@0.8.43) (2020-08-04)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.42"></a>
|
||||||
|
## [0.8.42](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.40...@ali/lowcode-plugin-outline-pane@0.8.42) (2020-08-04)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.41"></a>
|
||||||
|
## [0.8.41](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.40...@ali/lowcode-plugin-outline-pane@0.8.41) (2020-08-04)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.40"></a>
|
||||||
|
## [0.8.40](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.39...@ali/lowcode-plugin-outline-pane@0.8.40) (2020-07-29)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.39"></a>
|
||||||
|
## [0.8.39](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.38...@ali/lowcode-plugin-outline-pane@0.8.39) (2020-07-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 getPrototype is undefined ([95b3409](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/95b3409))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.38"></a>
|
||||||
|
## [0.8.38](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.37...@ali/lowcode-plugin-outline-pane@0.8.38) (2020-07-23)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.37"></a>
|
||||||
|
## [0.8.37](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.36...@ali/lowcode-plugin-outline-pane@0.8.37) (2020-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.36"></a>
|
||||||
|
## [0.8.36](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.35...@ali/lowcode-plugin-outline-pane@0.8.36) (2020-07-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复导入的组件拖入画布报错 ([caf9915](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/caf9915))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.35"></a>
|
||||||
|
## [0.8.35](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.34...@ali/lowcode-plugin-outline-pane@0.8.35) (2020-07-21)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.34"></a>
|
||||||
|
## [0.8.34](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.33...@ali/lowcode-plugin-outline-pane@0.8.34) (2020-07-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* modal node locate ([9a72dd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/9a72dd7))
|
||||||
|
* 大纲树节点显示隐藏埋点 ([e91ab1f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/e91ab1f))
|
||||||
|
* 没有 modal node 时不显示模态视图 ([555824c](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/555824c))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 大纲树展开折叠埋点 ([d9828f2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/d9828f2))
|
||||||
|
* 大纲树支持模态视图 ([3785e1c](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3785e1c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.33"></a>
|
||||||
|
## [0.8.33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.32...@ali/lowcode-plugin-outline-pane@0.8.33) (2020-07-14)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.32"></a>
|
||||||
|
## [0.8.32](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.31...@ali/lowcode-plugin-outline-pane@0.8.32) (2020-07-13)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.31"></a>
|
||||||
|
## [0.8.31](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.30...@ali/lowcode-plugin-outline-pane@0.8.31) (2020-07-12)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.30"></a>
|
||||||
|
## [0.8.30](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.29...@ali/lowcode-plugin-outline-pane@0.8.30) (2020-07-12)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.29"></a>
|
||||||
|
## [0.8.29](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.27...@ali/lowcode-plugin-outline-pane@0.8.29) (2020-06-23)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.27"></a>
|
||||||
|
## [0.8.27](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.26...@ali/lowcode-plugin-outline-pane@0.8.27) (2020-06-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 大纲树埋点 ([fa24821](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fa24821))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.26"></a>
|
||||||
|
## [0.8.26](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.25...@ali/lowcode-plugin-outline-pane@0.8.26) (2020-06-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.25"></a>
|
||||||
|
## [0.8.25](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.24...@ali/lowcode-plugin-outline-pane@0.8.25) (2020-06-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.24"></a>
|
||||||
|
## [0.8.24](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.23...@ali/lowcode-plugin-outline-pane@0.8.24) (2020-05-20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.23"></a>
|
||||||
|
## [0.8.23](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.22...@ali/lowcode-plugin-outline-pane@0.8.23) (2020-05-19)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.22"></a>
|
||||||
|
## [0.8.22](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.21...@ali/lowcode-plugin-outline-pane@0.8.22) (2020-05-18)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.21"></a>
|
||||||
|
## [0.8.21](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.20...@ali/lowcode-plugin-outline-pane@0.8.21) (2020-05-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.20"></a>
|
||||||
|
## [0.8.20](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.19...@ali/lowcode-plugin-outline-pane@0.8.20) (2020-05-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.19"></a>
|
||||||
|
## [0.8.19](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.18...@ali/lowcode-plugin-outline-pane@0.8.19) (2020-05-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.18"></a>
|
||||||
|
## [0.8.18](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.17...@ali/lowcode-plugin-outline-pane@0.8.18) (2020-05-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.17"></a>
|
||||||
|
## [0.8.17](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.16...@ali/lowcode-plugin-outline-pane@0.8.17) (2020-05-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.16"></a>
|
||||||
|
## [0.8.16](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.15...@ali/lowcode-plugin-outline-pane@0.8.16) (2020-05-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.15"></a>
|
||||||
|
## [0.8.15](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.14...@ali/lowcode-plugin-outline-pane@0.8.15) (2020-05-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* show value state ([bd49e50](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/bd49e50))
|
||||||
|
* support plaintext liveediting ([ea62f12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ea62f12))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.14"></a>
|
||||||
|
## [0.8.14](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.13...@ali/lowcode-plugin-outline-pane@0.8.14) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.13"></a>
|
||||||
|
## [0.8.13](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.12...@ali/lowcode-plugin-outline-pane@0.8.13) (2020-05-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* intl ([8a061ab](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/8a061ab))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.12"></a>
|
||||||
|
## [0.8.12](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.11...@ali/lowcode-plugin-outline-pane@0.8.12) (2020-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.11"></a>
|
||||||
|
## [0.8.11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.10...@ali/lowcode-plugin-outline-pane@0.8.11) (2020-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.10"></a>
|
||||||
|
## [0.8.10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.9...@ali/lowcode-plugin-outline-pane@0.8.10) (2020-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.9"></a>
|
||||||
|
## [0.8.9](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.8...@ali/lowcode-plugin-outline-pane@0.8.9) (2020-04-16)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.8"></a>
|
||||||
|
## [0.8.8](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.7...@ali/lowcode-plugin-outline-pane@0.8.8) (2020-04-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* plugin-designer ([2dfbcd4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2dfbcd4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.7"></a>
|
||||||
|
## [0.8.7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.6...@ali/lowcode-plugin-outline-pane@0.8.7) (2020-03-31)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.6"></a>
|
||||||
|
## [0.8.6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.5...@ali/lowcode-plugin-outline-pane@0.8.6) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.5"></a>
|
||||||
|
## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.4...@ali/lowcode-plugin-outline-pane@0.8.5) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-plugin-outline-pane@0.8.3...@ali/lowcode-plugin-outline-pane@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## 0.8.3 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.2"></a>
|
||||||
|
## 0.8.2 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
|
||||||
1
packages/plugin-outline-pane/README.md
Normal file
1
packages/plugin-outline-pane/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
大纲面板
|
||||||
9
packages/plugin-outline-pane/build.json
Normal file
9
packages/plugin-outline-pane/build.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"build-plugin-component",
|
||||||
|
"build-plugin-fusion",
|
||||||
|
["build-plugin-moment-locales", {
|
||||||
|
"locales": ["zh-cn"]
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
||||||
50
packages/plugin-outline-pane/package.json
Normal file
50
packages/plugin-outline-pane/package.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "@ali/lowcode-plugin-outline-pane",
|
||||||
|
"version": "1.0.21",
|
||||||
|
"description": "Outline pane for Ali lowCode engine",
|
||||||
|
"files": [
|
||||||
|
"es",
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"module": "es/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "build-scripts build --skip-demo",
|
||||||
|
"test": "ava",
|
||||||
|
"test:snapshot": "ava --update-snapshots"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ali/lowcode-designer": "^1.0.22",
|
||||||
|
"@ali/lowcode-editor-core": "^1.0.22",
|
||||||
|
"@ali/lowcode-types": "^1.0.20",
|
||||||
|
"@ali/lowcode-utils": "^1.0.21",
|
||||||
|
"@alifd/next": "^1.19.16",
|
||||||
|
"classnames": "^2.2.6",
|
||||||
|
"react": "^16",
|
||||||
|
"react-dom": "^16.7.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@alib/build-scripts": "^0.1.18",
|
||||||
|
"@types/classnames": "^2.2.7",
|
||||||
|
"@types/node": "^13.7.1",
|
||||||
|
"@types/react": "^16",
|
||||||
|
"@types/react-dom": "^16",
|
||||||
|
"build-plugin-component": "^0.2.10",
|
||||||
|
"build-plugin-fusion": "^0.1.1",
|
||||||
|
"build-plugin-moment-locales": "^0.1.0"
|
||||||
|
},
|
||||||
|
"ava": {
|
||||||
|
"compileEnhancements": false,
|
||||||
|
"snapshotDir": "test/fixtures/__snapshots__",
|
||||||
|
"extensions": [
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
|
"require": [
|
||||||
|
"ts-node/register"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npm.alibaba-inc.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
packages/plugin-outline-pane/src/README.md
Normal file
1
packages/plugin-outline-pane/src/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
大纲树
|
||||||
55
packages/plugin-outline-pane/src/helper/dwell-timer.ts
Normal file
55
packages/plugin-outline-pane/src/helper/dwell-timer.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { ParentalNode, DropLocation, isLocationChildrenDetail, LocateEvent } from '@ali/lowcode-designer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停留检查计时器
|
||||||
|
*/
|
||||||
|
export default class DwellTimer {
|
||||||
|
private timer: number | undefined;
|
||||||
|
|
||||||
|
private previous?: ParentalNode;
|
||||||
|
|
||||||
|
private event?: LocateEvent;
|
||||||
|
|
||||||
|
private decide: (node: ParentalNode, event: LocateEvent) => void;
|
||||||
|
|
||||||
|
private timeout = 500;
|
||||||
|
|
||||||
|
constructor(decide: (node: ParentalNode, event: LocateEvent) => void, timeout = 500) {
|
||||||
|
this.decide = decide;
|
||||||
|
this.timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
focus(node: ParentalNode, event: LocateEvent) {
|
||||||
|
this.event = event;
|
||||||
|
if (this.previous === node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.reset();
|
||||||
|
this.previous = node;
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.previous && this.decide(this.previous, this.event!);
|
||||||
|
this.reset();
|
||||||
|
}, this.timeout) as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
tryFocus(loc?: DropLocation | null) {
|
||||||
|
if (!loc || !isLocationChildrenDetail(loc.detail)) {
|
||||||
|
this.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (loc.detail.focus?.type === 'node') {
|
||||||
|
this.focus(loc.detail.focus.node, loc.event);
|
||||||
|
} else {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
if (this.timer) {
|
||||||
|
clearTimeout(this.timer);
|
||||||
|
this.timer = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.previous = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
54
packages/plugin-outline-pane/src/helper/indent-track.ts
Normal file
54
packages/plugin-outline-pane/src/helper/indent-track.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { DropLocation, ParentalNode, isLocationChildrenDetail } from '@ali/lowcode-designer';
|
||||||
|
|
||||||
|
const IndentSensitive = 15;
|
||||||
|
export class IndentTrack {
|
||||||
|
private indentStart: number | null = null;
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.indentStart = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIndentParent(lastLoc: DropLocation, loc: DropLocation): [ParentalNode, number] | null {
|
||||||
|
if (
|
||||||
|
lastLoc.target !== loc.target ||
|
||||||
|
!isLocationChildrenDetail(lastLoc.detail) ||
|
||||||
|
!isLocationChildrenDetail(loc.detail) ||
|
||||||
|
lastLoc.source !== loc.source ||
|
||||||
|
lastLoc.detail.index !== loc.detail.index ||
|
||||||
|
loc.detail.index == null
|
||||||
|
) {
|
||||||
|
this.indentStart = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (this.indentStart == null) {
|
||||||
|
this.indentStart = lastLoc.event.globalX;
|
||||||
|
}
|
||||||
|
const delta = loc.event.globalX - this.indentStart;
|
||||||
|
const indent = Math.floor(Math.abs(delta) / IndentSensitive);
|
||||||
|
if (indent < 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.indentStart = loc.event.globalX;
|
||||||
|
const direction = delta < 0 ? 'left' : 'right';
|
||||||
|
|
||||||
|
let parent = loc.target;
|
||||||
|
const { index } = loc.detail;
|
||||||
|
|
||||||
|
if (direction === 'left') {
|
||||||
|
if (!parent.parent || index < parent.children.size || parent.isSlot()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return [(parent as any).parent, parent.index + 1];
|
||||||
|
} else {
|
||||||
|
if (index === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
parent = parent.children.get(index - 1) as any;
|
||||||
|
if (parent && parent.isContainer()) {
|
||||||
|
return [parent, parent.children.size];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
packages/plugin-outline-pane/src/icons/arrow-right.tsx
Normal file
11
packages/plugin-outline-pane/src/icons/arrow-right.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconArrowRight(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M512.002047 771.904425c-10.152221 0.518816-20.442588-2.800789-28.202319-10.598382L77.902254 315.937602c-14.548344-14.618952-14.548344-38.318724 0-52.933583 14.544251-14.614859 38.118156-14.614859 52.662407 0l381.437385 418.531212L893.432269 263.004019c14.544251-14.614859 38.125319-14.614859 52.662407 0 14.552437 14.614859 14.552437 38.314631 0 52.933583L540.205389 761.307066C532.451798 769.103636 522.158361 772.424264 512.002047 771.904425z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconArrowRight.displayName = 'IconArrowRight';
|
||||||
11
packages/plugin-outline-pane/src/icons/cond.tsx
Normal file
11
packages/plugin-outline-pane/src/icons/cond.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconCond(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M479.552 276.544l296.896 2.752v75.712L960 249.024l-183.552-106.048v92.48h-271.36l-46.656-2.752-190.784 203.648 30.976 30.976 180.928-190.784z m296.896 484.928l-253.056-2.816-262.976-263.04H64v43.904h175.296l262.912 262.976 274.176 2.816v75.712L960 774.976l-183.616-105.984 0.064 92.48z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconCond.displayName = 'IconCond';
|
||||||
12
packages/plugin-outline-pane/src/icons/eye-close.tsx
Normal file
12
packages/plugin-outline-pane/src/icons/eye-close.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconEyeClose(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M512.7 700.9c-102.1 0-184.9-82.8-184.9-184.9 0-28.6 6.5-55.6 18-79.7l-93.7-93.7C138.9 418.1 65.2 514 65.2 514s200.4 260.7 447.6 260.7c50.2 0 98.6-10.8 143.6-27.9l-63.9-63.9c-24.2 11.5-51.2 18-79.8 18z" />
|
||||||
|
<path d="M960.3 514S759.9 253.3 512.7 253.3c-49.5 0-97.2 10.5-141.7 27.2L243.5 153.1l-45.3 45.3 262.3 262.2c-13.1 13.3-21.2 31.5-21.2 51.6 0 40.6 32.9 73.4 73.4 73.4 20.1 0 38.4-8.1 51.6-21.2l260.9 260.8 45.3-45.3-95.6-95.6C887.2 609.1 960.3 514 960.3 514z m-376.7-20.9c-6.8-25.2-26.6-45.1-51.9-51.9L437.5 347c23-10.3 48.5-16 75.3-16 102.1 0 184.9 82.8 184.9 184.9 0 26.8-5.7 52.2-15.9 75.2l-98.2-98z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconEyeClose.displayName = 'IconEyeClose';
|
||||||
12
packages/plugin-outline-pane/src/icons/eye.tsx
Normal file
12
packages/plugin-outline-pane/src/icons/eye.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconEye(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M512 256c-163.8 0-291.4 97.6-448 256 134.8 135.4 248 256 448 256 199.8 0 346.8-152.8 448-253.2C856.4 397.2 709.6 256 512 256z m0 438.6c-98.8 0-179.2-82-179.2-182.6 0-100.8 80.4-182.6 179.2-182.6s179.2 82 179.2 182.6c0 100.8-80.4 182.6-179.2 182.6z" />
|
||||||
|
<path d="M512 448c0-15.8 5.8-30.2 15.2-41.4-5-0.8-10-1.2-15.2-1.2-57.6 0-104.6 47.8-104.6 106.6s47 106.6 104.6 106.6 104.6-47.8 104.6-106.6c0-4.6-0.4-9.2-0.8-13.8-11 8.6-24.6 13.8-39.6 13.8-35.6 0-64.2-28.6-64.2-64z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconEye.displayName = 'IconEye';
|
||||||
11
packages/plugin-outline-pane/src/icons/lock.tsx
Normal file
11
packages/plugin-outline-pane/src/icons/lock.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconLock(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM540 701v53c0 4.4-3.6 8-8 8h-40c-4.4 0-8-3.6-8-8v-53c-12.1-8.7-20-22.9-20-39 0-26.5 21.5-48 48-48s48 21.5 48 48c0 16.1-7.9 30.3-20 39z m152-237H332V240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconLock.displayName = 'IconLock';
|
||||||
11
packages/plugin-outline-pane/src/icons/loop.tsx
Normal file
11
packages/plugin-outline-pane/src/icons/loop.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconLoop(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M60.235294 542.117647c0 132.879059 103.062588 240.941176 229.677176 240.941176l0 60.235294c-159.864471 0-289.912471-135.107765-289.912471-301.176471s130.048-301.176471 289.912471-301.176471l254.735059 0-99.147294-99.147294 42.586353-42.586353 171.911529 171.851294-171.851294 171.911529-42.646588-42.646588 99.207529-99.147294-254.795294 0c-126.614588 0-229.677176 108.062118-229.677176 240.941176zM734.087529 240.941176l0 60.235294c126.614588 0 229.677176 108.062118 229.677176 240.941176s-103.062588 240.941176-229.677176 240.941176l-254.795294 0 99.147294-99.147294-42.586353-42.586353-171.851294 171.851294 171.911529 171.911529 42.586353-42.586353-99.207529-99.207529 254.735059 0c159.924706 0 289.972706-135.107765 289.972706-301.176471s-130.048-301.176471-289.912471-301.176471z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconLoop.displayName = 'IconLoop';
|
||||||
12
packages/plugin-outline-pane/src/icons/outline.tsx
Normal file
12
packages/plugin-outline-pane/src/icons/outline.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconOutline(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M128 96h512a64 64 0 0 1 64 64v64a64 64 0 0 1-64 64H128a64 64 0 0 1-64-64V160a64 64 0 0 1 64-64z m32 64a32 32 0 1 0 0 64h448a32 32 0 0 0 0-64H160z m224 576h512a64 64 0 0 1 64 64v64a64 64 0 0 1-64 64H384a64 64 0 0 1-64-64v-64a64 64 0 0 1 64-64z m32 64a32 32 0 0 0 0 64h448a32 32 0 0 0 0-64H416z m-32-384h512a64 64 0 0 1 64 64v64a64 64 0 0 1-64 64H384a64 64 0 0 1-64-64v-64a64 64 0 0 1 64-64z m32 64a32 32 0 0 0 0 64h448a32 32 0 0 0 0-64H416z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconOutline.displayName = 'IconOutline';
|
||||||
|
|
||||||
12
packages/plugin-outline-pane/src/icons/radio-active.tsx
Normal file
12
packages/plugin-outline-pane/src/icons/radio-active.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconRadioActive(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024z m0-256a256 256 0 1 0 0-512 256 256 0 0 0 0 512z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconRadioActive.displayName = 'IconRadioActive';
|
||||||
|
|
||||||
12
packages/plugin-outline-pane/src/icons/radio.tsx
Normal file
12
packages/plugin-outline-pane/src/icons/radio.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconRadio(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024z m0-64A448 448 0 1 0 512 64a448 448 0 0 0 0 896z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconRadio.displayName = 'IconRadio';
|
||||||
|
|
||||||
12
packages/plugin-outline-pane/src/icons/unlock.tsx
Normal file
12
packages/plugin-outline-pane/src/icons/unlock.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconUnlock(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M832 464H332V240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v68c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-68c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32z m-40 376H232V536h560v304z" />
|
||||||
|
<path d="M484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53c12.1-8.7 20-22.9 20-39 0-26.5-21.5-48-48-48s-48 21.5-48 48c0 16.1 7.9 30.3 20 39z" />
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconUnlock.displayName = 'IconUnlock';
|
||||||
16
packages/plugin-outline-pane/src/index.ts
Normal file
16
packages/plugin-outline-pane/src/index.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { OutlinePane } from './views/pane';
|
||||||
|
import { OutlineBackupPane } from './views/backup-pane';
|
||||||
|
import { IconOutline } from './icons/outline';
|
||||||
|
import { intlNode } from './locale';
|
||||||
|
import { getTreeMaster } from './tree-master';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'outline-pane',
|
||||||
|
props: {
|
||||||
|
icon: IconOutline,
|
||||||
|
description: intlNode('Outline Tree'),
|
||||||
|
},
|
||||||
|
content: OutlinePane,
|
||||||
|
};
|
||||||
|
|
||||||
|
export { OutlinePane, OutlineBackupPane, getTreeMaster };
|
||||||
14
packages/plugin-outline-pane/src/locale/en-US.json
Normal file
14
packages/plugin-outline-pane/src/locale/en-US.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"Initializing": "Initializing",
|
||||||
|
"Hide": "Hide",
|
||||||
|
"Show": "Show",
|
||||||
|
"Lock": "Lock",
|
||||||
|
"Unlock": "Unlock",
|
||||||
|
"Expand": "Expand",
|
||||||
|
"Collapse": "Collapse",
|
||||||
|
"Conditional": "Condition",
|
||||||
|
"Loop": "Loop",
|
||||||
|
"Slots": "Slots",
|
||||||
|
"Slot for {prop}": "Slot for {prop}",
|
||||||
|
"Outline Tree": "Outline Tree"
|
||||||
|
}
|
||||||
10
packages/plugin-outline-pane/src/locale/index.ts
Normal file
10
packages/plugin-outline-pane/src/locale/index.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { createIntl } from '@ali/lowcode-editor-core';
|
||||||
|
import en_US from './en-US.json';
|
||||||
|
import zh_CN from './zh-CN.json';
|
||||||
|
|
||||||
|
const { intl, intlNode, getLocale, setLocale } = createIntl({
|
||||||
|
'en-US': en_US,
|
||||||
|
'zh-CN': zh_CN,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { intl, intlNode, getLocale, setLocale };
|
||||||
14
packages/plugin-outline-pane/src/locale/zh-CN.json
Normal file
14
packages/plugin-outline-pane/src/locale/zh-CN.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"Initializing": "正在初始化",
|
||||||
|
"Hide": "隐藏",
|
||||||
|
"Show": "显示",
|
||||||
|
"Lock": "锁定",
|
||||||
|
"Unlock": "解锁",
|
||||||
|
"Expand": "展开",
|
||||||
|
"Collapse": "收起",
|
||||||
|
"Conditional": "条件式",
|
||||||
|
"Loop": "循环",
|
||||||
|
"Slots": "插槽",
|
||||||
|
"Slot for {prop}": "属性 {prop} 的插槽",
|
||||||
|
"Outline Tree": "大纲树"
|
||||||
|
}
|
||||||
667
packages/plugin-outline-pane/src/main.ts
Normal file
667
packages/plugin-outline-pane/src/main.ts
Normal file
@ -0,0 +1,667 @@
|
|||||||
|
import { computed, obx } from '@ali/lowcode-editor-core';
|
||||||
|
import {
|
||||||
|
Designer,
|
||||||
|
ISensor,
|
||||||
|
LocateEvent,
|
||||||
|
isDragNodeObject,
|
||||||
|
isDragAnyObject,
|
||||||
|
DragObject,
|
||||||
|
Scroller,
|
||||||
|
ScrollTarget,
|
||||||
|
IScrollable,
|
||||||
|
DropLocation,
|
||||||
|
isLocationChildrenDetail,
|
||||||
|
LocationChildrenDetail,
|
||||||
|
LocationDetailType,
|
||||||
|
ParentalNode,
|
||||||
|
contains,
|
||||||
|
Node,
|
||||||
|
} from '@ali/lowcode-designer';
|
||||||
|
import TreeNode from './tree-node';
|
||||||
|
import { IndentTrack } from './helper/indent-track';
|
||||||
|
import DwellTimer from './helper/dwell-timer';
|
||||||
|
import { uniqueId } from '@ali/lowcode-utils';
|
||||||
|
import { Backup } from './views/backup-pane';
|
||||||
|
import { IEditor } from '@ali/lowcode-types';
|
||||||
|
import { ITreeBoard, TreeMaster, getTreeMaster } from './tree-master';
|
||||||
|
|
||||||
|
export class OutlineMain implements ISensor, ITreeBoard, IScrollable {
|
||||||
|
private _designer?: Designer;
|
||||||
|
|
||||||
|
@obx.ref private _master?: TreeMaster;
|
||||||
|
|
||||||
|
get master() {
|
||||||
|
return this._master;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get currentTree() {
|
||||||
|
return this._master?.currentTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly id = uniqueId('outline');
|
||||||
|
|
||||||
|
@obx.ref _visible = false;
|
||||||
|
|
||||||
|
get visible() {
|
||||||
|
return this._visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly editor: IEditor;
|
||||||
|
|
||||||
|
readonly at: string | symbol;
|
||||||
|
|
||||||
|
constructor(editor: IEditor, at: string | symbol) {
|
||||||
|
this.editor = editor;
|
||||||
|
this.at = at;
|
||||||
|
let inited = false;
|
||||||
|
const setup = async () => {
|
||||||
|
if (inited) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
inited = true;
|
||||||
|
const designer = await editor.onceGot(Designer);
|
||||||
|
this.setupDesigner(designer);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (at === Backup) {
|
||||||
|
setup();
|
||||||
|
} else {
|
||||||
|
editor.on('skeleton.panel.show', (key: string) => {
|
||||||
|
if (key === at) {
|
||||||
|
setup();
|
||||||
|
this._visible = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.on('skeleton.panel.hide', (key: string) => {
|
||||||
|
if (key === at) {
|
||||||
|
this._visible = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ISensor
|
||||||
|
*/
|
||||||
|
fixEvent(e: LocateEvent): LocateEvent {
|
||||||
|
if (e.fixed) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
const notMyEvent = e.originalEvent.view?.document !== document;
|
||||||
|
|
||||||
|
if (!e.target || notMyEvent) {
|
||||||
|
e.target = document.elementFromPoint(e.canvasX!, e.canvasY!);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentModel : 目标文档
|
||||||
|
e.documentModel = this._designer?.currentDocument;
|
||||||
|
|
||||||
|
// 事件已订正
|
||||||
|
e.fixed = true;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private indentTrack = new IndentTrack();
|
||||||
|
|
||||||
|
private dwell = new DwellTimer((target, event) => {
|
||||||
|
const { document } = target;
|
||||||
|
const { designer } = document;
|
||||||
|
let index: any;
|
||||||
|
let focus: any;
|
||||||
|
let valid = true;
|
||||||
|
if (target.hasSlots()) {
|
||||||
|
index = null;
|
||||||
|
focus = { type: 'slots' };
|
||||||
|
} else {
|
||||||
|
index = 0;
|
||||||
|
valid = document.checkNesting(target, event.dragObject as any);
|
||||||
|
}
|
||||||
|
designer.createLocation({
|
||||||
|
target,
|
||||||
|
source: this.id,
|
||||||
|
event,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index,
|
||||||
|
focus,
|
||||||
|
valid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ISensor
|
||||||
|
*/
|
||||||
|
locate(e: LocateEvent): DropLocation | undefined | null {
|
||||||
|
this.sensing = true;
|
||||||
|
this.scroller?.scrolling(e);
|
||||||
|
const { globalY, dragObject } = e;
|
||||||
|
const { nodes } = dragObject;
|
||||||
|
|
||||||
|
const tree = this._master?.currentTree;
|
||||||
|
if (!tree || !this._shell) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const operationalNodes = nodes?.filter((node: any) => {
|
||||||
|
const onMoveHook = node.componentMeta?.getMetadata()?.experimental?.callbacks?.onMoveHook;
|
||||||
|
const canMove = onMoveHook && typeof onMoveHook === 'function' ? onMoveHook() : true;
|
||||||
|
|
||||||
|
return canMove;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!operationalNodes || operationalNodes.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { document } = tree;
|
||||||
|
const { designer } = document;
|
||||||
|
const pos = getPosFromEvent(e, this._shell);
|
||||||
|
const irect = this.getInsertionRect();
|
||||||
|
const originLoc = document.dropLocation;
|
||||||
|
|
||||||
|
const componentMeta = e.dragObject.nodes ? e.dragObject.nodes[0].componentMeta : null;
|
||||||
|
if (e.dragObject.type === 'node' && componentMeta && componentMeta.isModal) {
|
||||||
|
return designer.createLocation({
|
||||||
|
target: document.rootNode,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index: 0,
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originLoc && ((pos && pos === 'unchanged') || (irect && globalY >= irect.top && globalY <= irect.bottom))) {
|
||||||
|
const loc = originLoc.clone(e);
|
||||||
|
const indented = this.indentTrack.getIndentParent(originLoc, loc);
|
||||||
|
if (indented) {
|
||||||
|
const [parent, index] = indented;
|
||||||
|
if (checkRecursion(parent, dragObject)) {
|
||||||
|
if (tree.getTreeNode(parent).expanded) {
|
||||||
|
this.dwell.reset();
|
||||||
|
return designer.createLocation({
|
||||||
|
target: parent,
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index,
|
||||||
|
valid: document.checkNesting(parent, e.dragObject as any),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
(originLoc.detail as LocationChildrenDetail).focus = {
|
||||||
|
type: 'node',
|
||||||
|
node: parent,
|
||||||
|
};
|
||||||
|
// focus try expand go on
|
||||||
|
this.dwell.focus(parent, e);
|
||||||
|
} else {
|
||||||
|
this.dwell.reset();
|
||||||
|
}
|
||||||
|
// FIXME: recreate new location
|
||||||
|
} else if ((originLoc.detail as LocationChildrenDetail).near) {
|
||||||
|
(originLoc.detail as LocationChildrenDetail).near = undefined;
|
||||||
|
this.dwell.reset();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.indentTrack.reset();
|
||||||
|
|
||||||
|
if (pos && pos !== 'unchanged') {
|
||||||
|
let treeNode = tree.getTreeNodeById(pos.nodeId);
|
||||||
|
if (treeNode) {
|
||||||
|
let { focusSlots } = pos;
|
||||||
|
let { node } = treeNode;
|
||||||
|
if (isDragNodeObject(dragObject)) {
|
||||||
|
const newNodes = operationalNodes;
|
||||||
|
let i = newNodes.length;
|
||||||
|
let p: any = node;
|
||||||
|
while (i-- > 0) {
|
||||||
|
if (contains(newNodes[i], p)) {
|
||||||
|
p = newNodes[i].parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p !== node) {
|
||||||
|
node = p || document.rootNode;
|
||||||
|
treeNode = tree.getTreeNode(node);
|
||||||
|
focusSlots = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (focusSlots) {
|
||||||
|
this.dwell.reset();
|
||||||
|
return designer.createLocation({
|
||||||
|
target: node as ParentalNode,
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index: null,
|
||||||
|
valid: false,
|
||||||
|
focus: { type: 'slots' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!treeNode.isRoot()) {
|
||||||
|
const loc = this.getNear(treeNode, e);
|
||||||
|
this.dwell.tryFocus(loc);
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loc = this.drillLocate(tree.root, e);
|
||||||
|
this.dwell.tryFocus(loc);
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getNear(treeNode: TreeNode, e: LocateEvent, index?: number, rect?: DOMRect) {
|
||||||
|
const { document } = treeNode.tree;
|
||||||
|
const { designer } = document;
|
||||||
|
const { globalY, dragObject } = e;
|
||||||
|
// TODO: check dragObject is anyData
|
||||||
|
const { node, expanded } = treeNode;
|
||||||
|
if (!rect) {
|
||||||
|
rect = this.getTreeNodeRect(treeNode);
|
||||||
|
if (!rect) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == null) {
|
||||||
|
index = node.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.isSlot()) {
|
||||||
|
// 是个插槽根节点
|
||||||
|
if (!treeNode.isContainer() && !treeNode.hasSlots()) {
|
||||||
|
return designer.createLocation({
|
||||||
|
target: node.parent!,
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index: null,
|
||||||
|
near: { node, pos: 'replace' },
|
||||||
|
valid: true, // TODO: future validation the slot limit
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const loc1 = this.drillLocate(treeNode, e);
|
||||||
|
if (loc1) {
|
||||||
|
return loc1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return designer.createLocation({
|
||||||
|
target: node.parent!,
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index: null,
|
||||||
|
valid: false,
|
||||||
|
focus: { type: 'slots' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let focusNode: Node | undefined;
|
||||||
|
// focus
|
||||||
|
if (!expanded && (treeNode.isContainer() || treeNode.hasSlots())) {
|
||||||
|
focusNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// before
|
||||||
|
const titleRect = this.getTreeTitleRect(treeNode) || rect;
|
||||||
|
if (globalY < titleRect.top + titleRect.height / 2) {
|
||||||
|
return designer.createLocation({
|
||||||
|
target: node.parent!,
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index,
|
||||||
|
valid: document.checkNesting(node.parent!, dragObject as any),
|
||||||
|
near: { node, pos: 'before' },
|
||||||
|
focus: checkRecursion(focusNode, dragObject) ? { type: 'node', node: focusNode } : undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalY > titleRect.bottom) {
|
||||||
|
focusNode = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expanded) {
|
||||||
|
// drill
|
||||||
|
const loc = this.drillLocate(treeNode, e);
|
||||||
|
if (loc) {
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// after
|
||||||
|
return designer.createLocation({
|
||||||
|
target: node.parent!,
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
detail: {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
index: index + 1,
|
||||||
|
valid: document.checkNesting(node.parent!, dragObject as any),
|
||||||
|
near: { node, pos: 'after' },
|
||||||
|
focus: checkRecursion(focusNode, dragObject) ? { type: 'node', node: focusNode } : undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private drillLocate(treeNode: TreeNode, e: LocateEvent): DropLocation | null {
|
||||||
|
const { document } = treeNode.tree;
|
||||||
|
const { designer } = document;
|
||||||
|
const { dragObject, globalY } = e;
|
||||||
|
|
||||||
|
if (!checkRecursion(treeNode.node, dragObject)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDragAnyObject(dragObject)) {
|
||||||
|
// TODO: future
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = treeNode.node as ParentalNode;
|
||||||
|
const detail: LocationChildrenDetail = {
|
||||||
|
type: LocationDetailType.Children,
|
||||||
|
};
|
||||||
|
const locationData: any = {
|
||||||
|
target: container,
|
||||||
|
detail,
|
||||||
|
source: this.id,
|
||||||
|
event: e,
|
||||||
|
};
|
||||||
|
const isSlotContainer = treeNode.hasSlots();
|
||||||
|
const isContainer = treeNode.isContainer();
|
||||||
|
|
||||||
|
if (container.isSlot() && !treeNode.expanded) {
|
||||||
|
// 未展开,直接定位到内部第一个节点
|
||||||
|
if (isSlotContainer) {
|
||||||
|
detail.index = null;
|
||||||
|
detail.focus = { type: 'slots' };
|
||||||
|
detail.valid = false;
|
||||||
|
} else {
|
||||||
|
detail.index = 0;
|
||||||
|
detail.valid = document.checkNesting(container, dragObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let items: TreeNode[] | null = null;
|
||||||
|
let slotsRect: DOMRect | undefined;
|
||||||
|
let focusSlots = false;
|
||||||
|
// isSlotContainer
|
||||||
|
if (isSlotContainer) {
|
||||||
|
slotsRect = this.getTreeSlotsRect(treeNode);
|
||||||
|
if (slotsRect) {
|
||||||
|
if (globalY <= slotsRect.bottom) {
|
||||||
|
focusSlots = true;
|
||||||
|
items = treeNode.slots;
|
||||||
|
} else if (!isContainer) {
|
||||||
|
// 不在 slots 范围,又不是 container 的情况,高亮 slots 区
|
||||||
|
detail.index = null;
|
||||||
|
detail.focus = { type: 'slots' };
|
||||||
|
detail.valid = false;
|
||||||
|
return designer.createLocation(locationData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!items && isContainer) {
|
||||||
|
items = treeNode.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!items) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const l = items.length;
|
||||||
|
let index = 0;
|
||||||
|
let before = l < 1;
|
||||||
|
let current: TreeNode | undefined;
|
||||||
|
let currentIndex = index;
|
||||||
|
for (; index < l; index++) {
|
||||||
|
current = items[index];
|
||||||
|
currentIndex = index;
|
||||||
|
const rect = this.getTreeNodeRect(current);
|
||||||
|
if (!rect) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rect
|
||||||
|
if (globalY < rect.top) {
|
||||||
|
before = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalY > rect.bottom) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loc = this.getNear(current, e, index, rect);
|
||||||
|
if (loc) {
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (focusSlots) {
|
||||||
|
detail.focus = { type: 'slots' };
|
||||||
|
detail.valid = false;
|
||||||
|
detail.index = null;
|
||||||
|
} else {
|
||||||
|
if (current) {
|
||||||
|
detail.index = before ? currentIndex : currentIndex + 1;
|
||||||
|
detail.near = { node: current.node, pos: before ? 'before' : 'after' };
|
||||||
|
} else {
|
||||||
|
detail.index = l;
|
||||||
|
}
|
||||||
|
detail.valid = document.checkNesting(container, dragObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return designer.createLocation(locationData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ISensor
|
||||||
|
*/
|
||||||
|
isEnter(e: LocateEvent): boolean {
|
||||||
|
if (!this._shell) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const rect = this._shell.getBoundingClientRect();
|
||||||
|
return e.globalY >= rect.top && e.globalY <= rect.bottom && e.globalX >= rect.left && e.globalX <= rect.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private tryScrollAgain: number | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IScrollBoard
|
||||||
|
*/
|
||||||
|
scrollToNode(treeNode: TreeNode, detail?: any, tryTimes = 0) {
|
||||||
|
if (tryTimes < 1 && this.tryScrollAgain) {
|
||||||
|
(window as any).cancelIdleCallback(this.tryScrollAgain);
|
||||||
|
this.tryScrollAgain = null;
|
||||||
|
}
|
||||||
|
if (this.sensing || !this.bounds || !this.scroller || !this.scrollTarget) {
|
||||||
|
// is a active sensor
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rect: ClientRect | undefined;
|
||||||
|
if (detail && isLocationChildrenDetail(detail)) {
|
||||||
|
rect = this.getInsertionRect();
|
||||||
|
} else {
|
||||||
|
rect = this.getTreeNodeRect(treeNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rect) {
|
||||||
|
if (tryTimes < 3) {
|
||||||
|
this.tryScrollAgain = (window as any).requestIdleCallback(() => this.scrollToNode(treeNode, detail, tryTimes + 1));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { scrollHeight, top: scrollTop } = this.scrollTarget;
|
||||||
|
const { height, top, bottom } = this.bounds;
|
||||||
|
if (rect.top < top || rect.bottom > bottom) {
|
||||||
|
const opt: any = {};
|
||||||
|
opt.top = Math.min(rect.top + rect.height / 2 + scrollTop - top - height / 2, scrollHeight - height);
|
||||||
|
if (rect.height >= height) {
|
||||||
|
opt.top = Math.min(scrollTop + rect.top - top, opt.top);
|
||||||
|
}
|
||||||
|
this.scroller.scrollTo(opt);
|
||||||
|
}
|
||||||
|
// make tail scroll be sure
|
||||||
|
if (tryTimes < 4) {
|
||||||
|
this.tryScrollAgain = (window as any).requestIdleCallback(() => this.scrollToNode(treeNode, detail, 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sensing = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ISensor
|
||||||
|
*/
|
||||||
|
deactiveSensor() {
|
||||||
|
this.sensing = false;
|
||||||
|
this.scroller?.cancel();
|
||||||
|
this.dwell.reset();
|
||||||
|
this.indentTrack.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IScrollable
|
||||||
|
*/
|
||||||
|
get bounds(): DOMRect | null {
|
||||||
|
if (!this._shell) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this._shell.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _scrollTarget?: ScrollTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IScrollable
|
||||||
|
*/
|
||||||
|
get scrollTarget() {
|
||||||
|
return this._scrollTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
private scroller?: Scroller;
|
||||||
|
|
||||||
|
private setupDesigner(designer: Designer) {
|
||||||
|
this._designer = designer;
|
||||||
|
this._master = getTreeMaster(designer);
|
||||||
|
this._master.addBoard(this);
|
||||||
|
designer.dragon.addSensor(this);
|
||||||
|
this.scroller = designer.createScroller(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
purge() {
|
||||||
|
this._designer?.dragon.removeSensor(this);
|
||||||
|
this._master?.removeBoard(this);
|
||||||
|
// todo purge treeMaster if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
private _sensorAvailable = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ISensor
|
||||||
|
*/
|
||||||
|
get sensorAvailable() {
|
||||||
|
return this._sensorAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _shell: HTMLDivElement | null = null;
|
||||||
|
|
||||||
|
mount(shell: HTMLDivElement | null) {
|
||||||
|
if (this._shell === shell) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._shell = shell;
|
||||||
|
if (shell) {
|
||||||
|
this._scrollTarget = new ScrollTarget(shell);
|
||||||
|
this._sensorAvailable = true;
|
||||||
|
} else {
|
||||||
|
this._scrollTarget = undefined;
|
||||||
|
this._sensorAvailable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getInsertionRect(): DOMRect | undefined {
|
||||||
|
if (!this._shell) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this._shell.querySelector('.insertion')?.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTreeNodeRect(treeNode: TreeNode): DOMRect | undefined {
|
||||||
|
if (!this._shell) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this._shell.querySelector(`.tree-node[data-id="${treeNode.id}"]`)?.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTreeTitleRect(treeNode: TreeNode): DOMRect | undefined {
|
||||||
|
if (!this._shell) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this._shell.querySelector(`.tree-node-title[data-id="${treeNode.id}"]`)?.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTreeSlotsRect(treeNode: TreeNode): DOMRect | undefined {
|
||||||
|
if (!this._shell) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this._shell.querySelector(`.tree-node-slots[data-id="${treeNode.id}"]`)?.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkRecursion(parent: Node | undefined | null, dragObject: DragObject): parent is ParentalNode {
|
||||||
|
if (!parent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isDragNodeObject(dragObject)) {
|
||||||
|
const { nodes } = dragObject;
|
||||||
|
if (nodes.some((node) => node.contains(parent))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPosFromEvent(
|
||||||
|
{ target }: LocateEvent,
|
||||||
|
stop: Element,
|
||||||
|
): null | 'unchanged' | { nodeId: string; focusSlots: boolean } {
|
||||||
|
if (!target || !stop.contains(target)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (target.matches('.insertion')) {
|
||||||
|
return 'unchanged';
|
||||||
|
}
|
||||||
|
target = target.closest('[data-id]');
|
||||||
|
if (!target || !stop.contains(target)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeId = (target as HTMLDivElement).dataset.id!;
|
||||||
|
return {
|
||||||
|
focusSlots: target.matches('.tree-node-slots'),
|
||||||
|
nodeId,
|
||||||
|
};
|
||||||
|
}
|
||||||
122
packages/plugin-outline-pane/src/tree-master.ts
Normal file
122
packages/plugin-outline-pane/src/tree-master.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import { computed, obx } from '@ali/lowcode-editor-core';
|
||||||
|
import { Designer, isLocationChildrenDetail } from '@ali/lowcode-designer';
|
||||||
|
import TreeNode from './tree-node';
|
||||||
|
import { Tree } from './tree';
|
||||||
|
import { Backup } from './views/backup-pane';
|
||||||
|
|
||||||
|
export interface ITreeBoard {
|
||||||
|
readonly visible: boolean;
|
||||||
|
readonly at: string | symbol;
|
||||||
|
scrollToNode(treeNode: TreeNode, detail?: any): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TreeMaster {
|
||||||
|
readonly designer: Designer;
|
||||||
|
|
||||||
|
constructor(designer: Designer) {
|
||||||
|
this.designer = designer;
|
||||||
|
let startTime: any;
|
||||||
|
designer.dragon.onDragstart(() => {
|
||||||
|
startTime = Date.now() / 1000;
|
||||||
|
// needs?
|
||||||
|
this.toVision();
|
||||||
|
});
|
||||||
|
designer.activeTracker.onChange(({ node, detail }) => {
|
||||||
|
const tree = this.currentTree;
|
||||||
|
if (!tree || node.document !== tree.document) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const treeNode = tree.getTreeNode(node);
|
||||||
|
if (detail && isLocationChildrenDetail(detail)) {
|
||||||
|
treeNode.expand(true);
|
||||||
|
} else {
|
||||||
|
treeNode.expandParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.boards.forEach((board) => {
|
||||||
|
board.scrollToNode(treeNode, detail);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
designer.dragon.onDragend(() => {
|
||||||
|
const endTime: any = Date.now() / 1000;
|
||||||
|
const editor = designer?.editor;
|
||||||
|
const nodes = designer.currentSelection?.getNodes();
|
||||||
|
editor?.emit('outlinePane.drag', {
|
||||||
|
selected: nodes
|
||||||
|
?.map((n) => {
|
||||||
|
if (!n) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const npm = n?.componentMeta?.npm;
|
||||||
|
return (
|
||||||
|
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') || n?.componentMeta?.componentName
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.join('&'),
|
||||||
|
time: (endTime - startTime).toFixed(2),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
designer.editor.on('designer.document.remove', ({ id }) => {
|
||||||
|
this.treeMap.delete(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private toVision() {
|
||||||
|
const tree = this.currentTree;
|
||||||
|
if (tree) {
|
||||||
|
tree.document.selection.getTopNodes().forEach((node) => {
|
||||||
|
tree.getTreeNode(node).setExpanded(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@obx.val private boards = new Set<ITreeBoard>();
|
||||||
|
|
||||||
|
addBoard(board: ITreeBoard) {
|
||||||
|
this.boards.add(board);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBoard(board: ITreeBoard) {
|
||||||
|
this.boards.delete(board);
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed hasVisibleTreeBoard() {
|
||||||
|
for (const item of this.boards) {
|
||||||
|
if (item.visible && item.at !== Backup) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
purge() {
|
||||||
|
// todo others purge
|
||||||
|
}
|
||||||
|
|
||||||
|
private treeMap = new Map<string, Tree>();
|
||||||
|
|
||||||
|
@computed get currentTree(): Tree | null {
|
||||||
|
const doc = this.designer?.currentDocument;
|
||||||
|
if (doc) {
|
||||||
|
const { id } = doc;
|
||||||
|
if (this.treeMap.has(id)) {
|
||||||
|
return this.treeMap.get(id)!;
|
||||||
|
}
|
||||||
|
const tree = new Tree(doc);
|
||||||
|
this.treeMap.set(id, tree);
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mastersMap = new Map<Designer, TreeMaster>();
|
||||||
|
export function getTreeMaster(designer: Designer): TreeMaster {
|
||||||
|
let master = mastersMap.get(designer);
|
||||||
|
if (!master) {
|
||||||
|
master = new TreeMaster(designer);
|
||||||
|
mastersMap.set(designer, master);
|
||||||
|
}
|
||||||
|
return master;
|
||||||
|
}
|
||||||
235
packages/plugin-outline-pane/src/tree-node.ts
Normal file
235
packages/plugin-outline-pane/src/tree-node.ts
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
import { TitleContent, isI18nData } from '@ali/lowcode-types';
|
||||||
|
import { computed, obx, intl } from '@ali/lowcode-editor-core';
|
||||||
|
import { Node, DocumentModel, isLocationChildrenDetail, LocationChildrenDetail, Designer } from '@ali/lowcode-designer';
|
||||||
|
import { Tree } from './tree';
|
||||||
|
|
||||||
|
export default class TreeNode {
|
||||||
|
get id(): string {
|
||||||
|
return this.node.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否可以展开
|
||||||
|
*/
|
||||||
|
@computed get expandable(): boolean {
|
||||||
|
return this.hasChildren() || this.hasSlots() || this.dropDetail?.index != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入"线"位置信息
|
||||||
|
*/
|
||||||
|
@computed get dropDetail(): LocationChildrenDetail | undefined | null {
|
||||||
|
const loc = this.node.document.dropLocation;
|
||||||
|
return loc && this.isResponseDropping() && isLocationChildrenDetail(loc.detail) ? loc.detail : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get depth(): number {
|
||||||
|
return this.node.zLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
isRoot() {
|
||||||
|
return this.tree.root === this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是响应投放区
|
||||||
|
*/
|
||||||
|
@computed isResponseDropping(): boolean {
|
||||||
|
const loc = this.node.document.dropLocation;
|
||||||
|
if (!loc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return loc.target === this.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed isFocusingNode(): boolean {
|
||||||
|
const loc = this.node.document.dropLocation;
|
||||||
|
if (!loc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
isLocationChildrenDetail(loc.detail) && loc.detail.focus?.type === 'node' && loc.detail.focus.node === this.node
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认为折叠状态
|
||||||
|
* 在初始化根节点时,设置为展开状态
|
||||||
|
*/
|
||||||
|
@obx.ref private _expanded = false;
|
||||||
|
|
||||||
|
get expanded(): boolean {
|
||||||
|
return this.isRoot() || (this.expandable && this._expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
setExpanded(value: boolean) {
|
||||||
|
this._expanded = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get detecting() {
|
||||||
|
return this.designer.detecting.current === this.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get hidden(): boolean {
|
||||||
|
const cv = this.node.isConditionalVisible();
|
||||||
|
if (cv == null) {
|
||||||
|
return !this.node.getVisible();
|
||||||
|
}
|
||||||
|
return !cv;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHidden(flag: boolean) {
|
||||||
|
if (this.node.conditionGroup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.node.setVisible(!flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get locked(): boolean {
|
||||||
|
return this.node.getExtraProp('locked', false)?.getValue() === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLocked(flag: boolean) {
|
||||||
|
if (flag) {
|
||||||
|
this.node.getExtraProp('locked', true)?.setValue(true);
|
||||||
|
} else {
|
||||||
|
this.node.getExtraProp('locked', false)?.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get selected(): boolean {
|
||||||
|
// TODO: check is dragging
|
||||||
|
const { selection } = this.document;
|
||||||
|
return selection.has(this.node.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get title(): TitleContent {
|
||||||
|
return this.node.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get titleLabel() {
|
||||||
|
let { title } = this;
|
||||||
|
if (!title) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if ((title as any).label) {
|
||||||
|
title = (title as any).label;
|
||||||
|
}
|
||||||
|
if (typeof title === 'string') {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
if (isI18nData(title)) {
|
||||||
|
return intl(title) as string;
|
||||||
|
}
|
||||||
|
return this.node.componentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitleLabel(label: string) {
|
||||||
|
const origLabel = this.titleLabel;
|
||||||
|
if (label === origLabel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (label === '') {
|
||||||
|
this.node.getExtraProp('title', false)?.remove();
|
||||||
|
} else {
|
||||||
|
this.node.getExtraProp('title', true)?.setValue(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get icon() {
|
||||||
|
return this.node.componentMeta.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get parent() {
|
||||||
|
const { parent } = this.node;
|
||||||
|
if (parent) {
|
||||||
|
return this.tree.getTreeNode(parent);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get slots(): TreeNode[] {
|
||||||
|
// todo: shallowEqual
|
||||||
|
return this.node.slots.map((node) => this.tree.getTreeNode(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get children(): TreeNode[] | null {
|
||||||
|
return this.node.children?.map((node) => this.tree.getTreeNode(node)) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是容器,允许子节点拖入
|
||||||
|
*/
|
||||||
|
isContainer(): boolean {
|
||||||
|
return this.node.isContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否有"插槽"
|
||||||
|
*/
|
||||||
|
hasSlots(): boolean {
|
||||||
|
return this.node.hasSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
hasChildren(): boolean {
|
||||||
|
return !!(this.isContainer() && this.node.children?.notEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
select(isMulti: boolean) {
|
||||||
|
const { node } = this;
|
||||||
|
|
||||||
|
const { selection } = node.document;
|
||||||
|
if (isMulti) {
|
||||||
|
selection.add(node.id);
|
||||||
|
} else {
|
||||||
|
selection.select(node.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展开节点,支持依次展开父节点
|
||||||
|
*/
|
||||||
|
expand(tryExpandParents = false) {
|
||||||
|
// 这边不能直接使用 expanded,需要额外判断是否可以展开
|
||||||
|
// 如果只使用 expanded,会漏掉不可以展开的情况,即在不可以展开的情况下,会触发展开
|
||||||
|
if (this.expandable && !this._expanded) {
|
||||||
|
this.setExpanded(true);
|
||||||
|
}
|
||||||
|
if (tryExpandParents) {
|
||||||
|
this.expandParents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expandParents() {
|
||||||
|
let p = this.node.parent;
|
||||||
|
while (p) {
|
||||||
|
this.tree.getTreeNode(p).setExpanded(true);
|
||||||
|
p = p.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly designer: Designer;
|
||||||
|
|
||||||
|
readonly document: DocumentModel;
|
||||||
|
|
||||||
|
@obx.ref private _node: Node;
|
||||||
|
|
||||||
|
get node() {
|
||||||
|
return this._node;
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly tree: Tree;
|
||||||
|
|
||||||
|
constructor(tree: Tree, node: Node) {
|
||||||
|
this.tree = tree;
|
||||||
|
this.document = node.document;
|
||||||
|
this.designer = this.document.designer;
|
||||||
|
this._node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
setNode(node: Node) {
|
||||||
|
if (this._node !== node) {
|
||||||
|
this._node = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
packages/plugin-outline-pane/src/tree.ts
Normal file
34
packages/plugin-outline-pane/src/tree.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { DocumentModel, Node } from '@ali/lowcode-designer';
|
||||||
|
import TreeNode from './tree-node';
|
||||||
|
|
||||||
|
export class Tree {
|
||||||
|
private treeNodesMap = new Map<string, TreeNode>();
|
||||||
|
|
||||||
|
readonly root: TreeNode;
|
||||||
|
|
||||||
|
readonly id: string;
|
||||||
|
|
||||||
|
readonly document: DocumentModel;
|
||||||
|
|
||||||
|
constructor(document: DocumentModel) {
|
||||||
|
this.document = document;
|
||||||
|
this.root = this.getTreeNode(document.rootNode);
|
||||||
|
this.id = document.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTreeNode(node: Node): TreeNode {
|
||||||
|
if (this.treeNodesMap.has(node.id)) {
|
||||||
|
const tnode = this.treeNodesMap.get(node.id)!;
|
||||||
|
tnode.setNode(node);
|
||||||
|
return tnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const treeNode = new TreeNode(this, node);
|
||||||
|
this.treeNodesMap.set(node.id, treeNode);
|
||||||
|
return treeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTreeNodeById(id: string) {
|
||||||
|
return this.treeNodesMap.get(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
packages/plugin-outline-pane/src/views/backup-pane.tsx
Normal file
18
packages/plugin-outline-pane/src/views/backup-pane.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { PureComponent } from 'react';
|
||||||
|
import { PluginProps } from '@ali/lowcode-types';
|
||||||
|
import { OutlinePane } from './pane';
|
||||||
|
|
||||||
|
export const Backup = Symbol.for('backup-outline');
|
||||||
|
|
||||||
|
export class OutlineBackupPane extends PureComponent<PluginProps> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<OutlinePane
|
||||||
|
editor={this.props.editor}
|
||||||
|
config={{
|
||||||
|
name: Backup,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
packages/plugin-outline-pane/src/views/pane.tsx
Normal file
40
packages/plugin-outline-pane/src/views/pane.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
|
import { intl } from '../locale';
|
||||||
|
import { OutlineMain } from '../main';
|
||||||
|
import TreeView from './tree';
|
||||||
|
import './style.less';
|
||||||
|
import { IEditor } from '@ali/lowcode-types';
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class OutlinePane extends Component<{ config: any; editor: IEditor }> {
|
||||||
|
private main = new OutlineMain(this.props.editor, this.props.config.name || this.props.config.pluginKey);
|
||||||
|
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.main.purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const tree = this.main.currentTree;
|
||||||
|
|
||||||
|
if (!tree) {
|
||||||
|
return (
|
||||||
|
<div className="lc-outline-pane">
|
||||||
|
<p className="lc-outline-notice">{intl('Initializing')}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="lc-outline-pane">
|
||||||
|
<div ref={(shell) => this.main.mount(shell)} className="lc-outline-tree-container">
|
||||||
|
<TreeView key={tree.id} tree={tree} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
94
packages/plugin-outline-pane/src/views/root-tree-node.tsx
Normal file
94
packages/plugin-outline-pane/src/views/root-tree-node.tsx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { Component } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
|
import TreeNode from '../tree-node';
|
||||||
|
import TreeTitle from './tree-title';
|
||||||
|
import TreeBranches from './tree-branches';
|
||||||
|
import { ModalNodesManager } from '@ali/lowcode-designer';
|
||||||
|
import { IconEyeClose } from '../icons/eye-close';
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class ModalTreeNodeView extends Component<{ treeNode: TreeNode }> {
|
||||||
|
private modalNodesManager: ModalNodesManager;
|
||||||
|
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
// 模态管理对象
|
||||||
|
this.modalNodesManager = props.treeNode.document.modalNodesManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hideAllNodes() {
|
||||||
|
this.modalNodesManager.hideModalNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
const modalNodes = treeNode.children?.filter((item) => {
|
||||||
|
return item.node.componentMeta.isModal;
|
||||||
|
});
|
||||||
|
if (!modalNodes || modalNodes.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasVisibleModalNode = !!this.modalNodesManager.getVisibleModalNode();
|
||||||
|
return (
|
||||||
|
<div className="tree-node-modal">
|
||||||
|
<div className="tree-node-modal-title">
|
||||||
|
<span>模态视图层</span>
|
||||||
|
<div
|
||||||
|
className="tree-node-modal-title-visible-icon"
|
||||||
|
onClick={this.hideAllNodes.bind(this)}
|
||||||
|
>
|
||||||
|
{hasVisibleModalNode ? <IconEyeClose /> : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="tree-pane-modal-content">
|
||||||
|
<TreeBranches treeNode={treeNode} isModal />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class RootTreeNodeView extends Component<{ treeNode: TreeNode }> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
const className = classNames('tree-node', {
|
||||||
|
// 是否展开
|
||||||
|
expanded: treeNode.expanded,
|
||||||
|
// 是否悬停中
|
||||||
|
detecting: treeNode.detecting,
|
||||||
|
// 是否选中的
|
||||||
|
selected: treeNode.selected,
|
||||||
|
// 是否隐藏的
|
||||||
|
hidden: treeNode.hidden,
|
||||||
|
// 是否忽略的
|
||||||
|
// ignored: treeNode.ignored,
|
||||||
|
// 是否锁定的
|
||||||
|
locked: treeNode.locked,
|
||||||
|
// 是否投放响应
|
||||||
|
dropping: treeNode.dropDetail?.index != null,
|
||||||
|
'is-root': treeNode.isRoot(),
|
||||||
|
'condition-flow': treeNode.node.conditionGroup != null,
|
||||||
|
highlight: treeNode.isFocusingNode(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={className} data-id={treeNode.id}>
|
||||||
|
<TreeTitle treeNode={treeNode} />
|
||||||
|
<ModalTreeNodeView treeNode={treeNode} />
|
||||||
|
<TreeBranches treeNode={treeNode} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
388
packages/plugin-outline-pane/src/views/style.less
Normal file
388
packages/plugin-outline-pane/src/views/style.less
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
.lc-outline-pane {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
> .lc-outline-tree-container {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
position: absolute;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lc-outline-tree {
|
||||||
|
@treeNodeHeight: 30px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: @treeNodeHeight;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.tree-node-modal {
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid rgba(31, 56, 88, 0.2);
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 1px 4px 0 rgba(31, 56, 88, 0.15);
|
||||||
|
|
||||||
|
.tree-node-modal-title {
|
||||||
|
position: relative;
|
||||||
|
background: rgba(31, 56, 88, 0.04);
|
||||||
|
padding: 0 10px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-bottom: 1px solid rgba(31, 56, 88, 0.2);
|
||||||
|
|
||||||
|
.tree-node-modal-title-visible-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-pane-modal-content {
|
||||||
|
& > .tree-node-branches::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-modal-radio, .tree-node-modal-radio-active {
|
||||||
|
margin-right: 4px;
|
||||||
|
opacity: 0.8;
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
.tree-node-modal-radio-active {
|
||||||
|
color: #006cff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-branches::before {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: 0;
|
||||||
|
border-left: 1px solid transparent;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 6px;
|
||||||
|
content: ' ';
|
||||||
|
z-index: 2;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.tree-node-branches::before {
|
||||||
|
border-left-color: #ddd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.insertion {
|
||||||
|
pointer-events: all !important;
|
||||||
|
border: 1px dashed var(--color-brand-light);
|
||||||
|
height: @treeNodeHeight;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transform: translateZ(0);
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
&.invalid {
|
||||||
|
border-color: red;
|
||||||
|
background-color: rgba(240, 154, 154, 0.719);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.condition-group-container {
|
||||||
|
border-bottom: 1px solid #7b605b;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: 0;
|
||||||
|
border-left: 0.5px solid #7b605b;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
content: ' ';
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
>.condition-group-title {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #7b605b;
|
||||||
|
height: 14px;
|
||||||
|
> .lc-title {
|
||||||
|
font-size: 12px;
|
||||||
|
transform: scale(0.8);
|
||||||
|
transform-origin: top;
|
||||||
|
color: white;
|
||||||
|
text-shadow: 0px 0px 2px black;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tree-node-slots {
|
||||||
|
border-bottom: 1px solid rgb(144, 94, 190);
|
||||||
|
position: relative;
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: 0;
|
||||||
|
border-left: 0.5px solid rgb(144, 94, 190);
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
content: ' ';
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
>.tree-node-slots-title {
|
||||||
|
text-align: center;
|
||||||
|
background-color: rgb(144, 94, 190);
|
||||||
|
height: 14px;
|
||||||
|
> .lc-title {
|
||||||
|
font-size: 12px;
|
||||||
|
transform: scale(0.8);
|
||||||
|
transform-origin: top;
|
||||||
|
color: white;
|
||||||
|
text-shadow: 0px 0px 2px black;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.insertion-at-slots {
|
||||||
|
padding-bottom: @treeNodeHeight;
|
||||||
|
border-bottom-color: rgb(182, 55, 55);
|
||||||
|
>.tree-node-slots-title {
|
||||||
|
background-color: rgb(182, 55, 55);
|
||||||
|
}
|
||||||
|
&::before {
|
||||||
|
border-left-color: rgb(182, 55, 55);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node {
|
||||||
|
.tree-node-expand-btn {
|
||||||
|
width: 12px;
|
||||||
|
line-height: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: color 200ms ease;
|
||||||
|
color: var(--color-icon-normal);
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-icon-hover);
|
||||||
|
}
|
||||||
|
> svg {
|
||||||
|
transform-origin: center;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
transition: transform 100ms ease;
|
||||||
|
}
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
.tree-node-expand-placeholder {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-icon {
|
||||||
|
transform: translateZ(0);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 4px;
|
||||||
|
color: var(--color-text);
|
||||||
|
|
||||||
|
& > svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
* {
|
||||||
|
fill: var(--color-icon-normal, rgba(31, 56, 88, 0.4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > img {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
* {
|
||||||
|
fill: var(--color-icon-normal, rgba(31, 56, 88, 0.4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-title {
|
||||||
|
font-size: var(--font-size-text);
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--color-pane-background);
|
||||||
|
border-bottom: 1px solid var(--color-line-normal, rgba(31, 56, 88, 0.1));
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: @treeNodeHeight;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
transform: translateZ(0);
|
||||||
|
padding-right: 5px;
|
||||||
|
& > :first-child {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-title-label {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
align-self: stretch;
|
||||||
|
overflow: visible;
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
.tree-node-title-input {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid var(--color-brand-light);
|
||||||
|
background-color: var(--color-pane-background);
|
||||||
|
color: var(--color-text);
|
||||||
|
line-height: 18px;
|
||||||
|
padding: 2px;
|
||||||
|
outline: none;
|
||||||
|
margin-left: -3px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-hide-btn, .tree-node-lock-btn {
|
||||||
|
opacity: 0;
|
||||||
|
color: var(--color-text);
|
||||||
|
line-height: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 22px;
|
||||||
|
&:hover {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.tree-node-hide-btn, .tree-node-lock-btn {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.lc-cursor-dragging & {
|
||||||
|
// FIXME: only hide hover shows
|
||||||
|
.tree-node-hide-btn, .tree-node-lock-btn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.editing {
|
||||||
|
& > .tree-node-hide-btn, & >.tree-node-lock-btn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-tag {
|
||||||
|
margin-left: 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 0;
|
||||||
|
&.cond {
|
||||||
|
color: rgb(179, 52, 6);
|
||||||
|
}
|
||||||
|
&.loop {
|
||||||
|
color: rgb(103, 187, 187);
|
||||||
|
}
|
||||||
|
&.slot {
|
||||||
|
color: rgb(211, 90, 211);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-root {
|
||||||
|
> .tree-node-title {
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
& > .tree-node-title > .tree-node-expand-btn > svg {
|
||||||
|
transform: rotate(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.detecting > .tree-node-title {
|
||||||
|
background: var(--color-block-background-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中节点处理
|
||||||
|
&.selected {
|
||||||
|
& > .tree-node-title {
|
||||||
|
background: var(--color-block-background-shallow);
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .tree-node-branches::before {
|
||||||
|
border-left-color: var(--color-brand-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
.tree-node-title-label {
|
||||||
|
color: #9b9b9b;
|
||||||
|
}
|
||||||
|
& > .tree-node-title > .tree-node-hide-btn {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.tree-node-branches {
|
||||||
|
.tree-node-hide-btn {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.condition-flow {
|
||||||
|
& > .tree-node-title > .tree-node-hide-btn {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
&.hidden > .tree-node-title > .tree-node-hide-btn {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.locked {
|
||||||
|
& > .tree-node-title > .tree-node-lock-btn {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.tree-node-branches {
|
||||||
|
.tree-node-lock-btn, .tree-node-hide-btn {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理拖入节点
|
||||||
|
&.dropping {
|
||||||
|
& > .tree-node-branches::before {
|
||||||
|
border-left: 1px solid var(--color-brand);
|
||||||
|
}
|
||||||
|
& > .tree-node-title {
|
||||||
|
.tree-node-expand-btn {
|
||||||
|
color: var(--color-brand);
|
||||||
|
}
|
||||||
|
.tree-node-icon {
|
||||||
|
color: var(--color-brand);
|
||||||
|
}
|
||||||
|
.tree-node-title-label > .lc-title {
|
||||||
|
color: var(--color-brand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.highlight {
|
||||||
|
& > .tree-node-title {
|
||||||
|
background: var(--color-block-background-shallow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-branches {
|
||||||
|
padding-left: 12px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
140
packages/plugin-outline-pane/src/views/tree-branches.tsx
Normal file
140
packages/plugin-outline-pane/src/views/tree-branches.tsx
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import { Component } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { observer, Title } from '@ali/lowcode-editor-core';
|
||||||
|
import { ExclusiveGroup } from '@ali/lowcode-designer';
|
||||||
|
import TreeNode from '../tree-node';
|
||||||
|
import TreeNodeView from './tree-node';
|
||||||
|
import { intlNode } from '../locale';
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class TreeBranches extends Component<{
|
||||||
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
|
}> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode, isModal } = this.props;
|
||||||
|
const { expanded } = treeNode;
|
||||||
|
|
||||||
|
if (!expanded) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="tree-node-branches">
|
||||||
|
{
|
||||||
|
!isModal && <TreeNodeSlots treeNode={treeNode} />
|
||||||
|
}
|
||||||
|
<TreeNodeChildren treeNode={treeNode} isModal={isModal || false} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class TreeNodeChildren extends Component<{
|
||||||
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
|
}> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode, isModal } = this.props;
|
||||||
|
const children: any = [];
|
||||||
|
let groupContents: any[] = [];
|
||||||
|
let currentGrp: ExclusiveGroup;
|
||||||
|
const endGroup = () => {
|
||||||
|
if (groupContents.length > 0) {
|
||||||
|
children.push(
|
||||||
|
<div key={currentGrp.id} className="condition-group-container" data-id={currentGrp.firstNode.id}>
|
||||||
|
<div className="condition-group-title">
|
||||||
|
<Title title={currentGrp.title} />
|
||||||
|
</div>
|
||||||
|
{groupContents}
|
||||||
|
</div>,
|
||||||
|
);
|
||||||
|
groupContents = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { dropDetail } = treeNode;
|
||||||
|
const dropIndex = dropDetail?.index;
|
||||||
|
const insertion = (
|
||||||
|
<div
|
||||||
|
key="insertion"
|
||||||
|
className={classNames('insertion', {
|
||||||
|
invalid: dropDetail?.valid === false,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
treeNode.children?.forEach((child, index) => {
|
||||||
|
const childIsModal = child.node.componentMeta.isModal || false;
|
||||||
|
if (isModal != childIsModal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { conditionGroup } = child.node;
|
||||||
|
if (conditionGroup !== currentGrp) {
|
||||||
|
endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conditionGroup) {
|
||||||
|
currentGrp = conditionGroup;
|
||||||
|
if (index === dropIndex) {
|
||||||
|
if (groupContents.length > 0) {
|
||||||
|
groupContents.push(insertion);
|
||||||
|
} else {
|
||||||
|
children.push(insertion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupContents.push(<TreeNodeView key={child.id} treeNode={child} isModal={isModal} />);
|
||||||
|
} else {
|
||||||
|
if (index === dropIndex) {
|
||||||
|
children.push(insertion);
|
||||||
|
}
|
||||||
|
children.push(<TreeNodeView key={child.id} treeNode={child} isModal={isModal} />);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
endGroup();
|
||||||
|
const length = treeNode.children?.length || 0;
|
||||||
|
if (dropIndex != null && dropIndex >= length) {
|
||||||
|
children.push(insertion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="tree-node-children">{children}</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class TreeNodeSlots extends Component<{
|
||||||
|
treeNode: TreeNode;
|
||||||
|
}> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
if (!treeNode.hasSlots()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames('tree-node-slots', {
|
||||||
|
'insertion-at-slots': treeNode.dropDetail?.focus?.type === 'slots',
|
||||||
|
})}
|
||||||
|
data-id={treeNode.id}
|
||||||
|
>
|
||||||
|
<div className="tree-node-slots-title">
|
||||||
|
<Title title={{ type: 'i18n', intl: intlNode('Slots') }} />
|
||||||
|
</div>
|
||||||
|
{treeNode.slots.map(tnode => (
|
||||||
|
<TreeNodeView key={tnode.id} treeNode={tnode} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
packages/plugin-outline-pane/src/views/tree-node.tsx
Normal file
46
packages/plugin-outline-pane/src/views/tree-node.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Component } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
|
import TreeNode from '../tree-node';
|
||||||
|
import TreeTitle from './tree-title';
|
||||||
|
import TreeBranches from './tree-branches';
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class TreeNodeView extends Component<{
|
||||||
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
|
}> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode, isModal } = this.props;
|
||||||
|
const className = classNames('tree-node', {
|
||||||
|
// 是否展开
|
||||||
|
expanded: treeNode.expanded,
|
||||||
|
// 是否悬停中
|
||||||
|
detecting: treeNode.detecting,
|
||||||
|
// 是否选中的
|
||||||
|
selected: treeNode.selected,
|
||||||
|
// 是否隐藏的
|
||||||
|
hidden: treeNode.hidden,
|
||||||
|
// 是否忽略的
|
||||||
|
// ignored: treeNode.ignored,
|
||||||
|
// 是否锁定的
|
||||||
|
locked: treeNode.locked,
|
||||||
|
// 是否投放响应
|
||||||
|
dropping: treeNode.dropDetail?.index != null,
|
||||||
|
'is-root': treeNode.isRoot(),
|
||||||
|
'condition-flow': treeNode.node.conditionGroup != null,
|
||||||
|
highlight: treeNode.isFocusingNode(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={className} data-id={treeNode.id}>
|
||||||
|
<TreeTitle treeNode={treeNode} isModal={isModal} />
|
||||||
|
<TreeBranches treeNode={treeNode} isModal={false} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
295
packages/plugin-outline-pane/src/views/tree-title.tsx
Normal file
295
packages/plugin-outline-pane/src/views/tree-title.tsx
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
import { Component, KeyboardEvent, FocusEvent, Fragment } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { observer, Title, Tip, globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||||
|
import { IconArrowRight } from '../icons/arrow-right';
|
||||||
|
import { IconEyeClose } from '../icons/eye-close';
|
||||||
|
import { intl, intlNode } from '../locale';
|
||||||
|
import TreeNode from '../tree-node';
|
||||||
|
import { IconEye } from '../icons/eye';
|
||||||
|
import { IconCond } from '../icons/cond';
|
||||||
|
import { IconLoop } from '../icons/loop';
|
||||||
|
import { IconRadioActive } from '../icons/radio-active';
|
||||||
|
import { IconRadio } from '../icons/radio';
|
||||||
|
import { createIcon } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
function emitOutlineEvent(type: string, treeNode: TreeNode, rest?: Record<string, unknown>) {
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
const node = treeNode?.node;
|
||||||
|
const npm = node?.componentMeta?.npm;
|
||||||
|
const selected =
|
||||||
|
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') || node?.componentMeta?.componentName || '';
|
||||||
|
editor?.emit(`outlinePane.${type}`, {
|
||||||
|
selected,
|
||||||
|
...rest,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class TreeTitle extends Component<{
|
||||||
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
|
}> {
|
||||||
|
state: {
|
||||||
|
editing: boolean;
|
||||||
|
} = {
|
||||||
|
editing: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
private enableEdit = () => {
|
||||||
|
this.setState({
|
||||||
|
editing: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private cancelEdit() {
|
||||||
|
this.setState({
|
||||||
|
editing: false,
|
||||||
|
});
|
||||||
|
this.lastInput = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private saveEdit = (e: FocusEvent<HTMLInputElement> | KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
const value = (e.target as HTMLInputElement).value || '';
|
||||||
|
treeNode.setTitleLabel(value);
|
||||||
|
emitOutlineEvent('rename', treeNode, { value });
|
||||||
|
this.cancelEdit();
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleKeyUp = (e: KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
this.saveEdit(e);
|
||||||
|
}
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
this.cancelEdit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private lastInput?: HTMLInputElement;
|
||||||
|
|
||||||
|
private setCaret = (input: HTMLInputElement | null) => {
|
||||||
|
if (!input || this.lastInput === input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input.focus();
|
||||||
|
input.select();
|
||||||
|
// 光标定位最后一个
|
||||||
|
// input.selectionStart = input.selectionEnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode, isModal } = this.props;
|
||||||
|
const { editing } = this.state;
|
||||||
|
const isCNode = !treeNode.isRoot();
|
||||||
|
const { node } = treeNode;
|
||||||
|
const isNodeParent = node.isParental();
|
||||||
|
let style: any;
|
||||||
|
if (isCNode) {
|
||||||
|
const { depth } = treeNode;
|
||||||
|
const indent = depth * 12;
|
||||||
|
style = {
|
||||||
|
paddingLeft: indent + (isModal ? 12 : 0),
|
||||||
|
marginLeft: -indent,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames('tree-node-title', {
|
||||||
|
editing,
|
||||||
|
})}
|
||||||
|
style={style}
|
||||||
|
data-id={treeNode.id}
|
||||||
|
onClick={() => {
|
||||||
|
if (isModal) {
|
||||||
|
node.document.modalNodesManager.setVisible(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node.conditionGroup) {
|
||||||
|
node.setConditionalVisible();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isModal && node.getVisible() && (
|
||||||
|
<div onClick={() => {
|
||||||
|
node.document.modalNodesManager.setInvisible(node);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconRadioActive className="tree-node-modal-radio-active" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isModal && !node.getVisible() && (
|
||||||
|
<div onClick={() => {
|
||||||
|
node.document.modalNodesManager.setVisible(node);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconRadio className="tree-node-modal-radio" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isCNode && <ExpandBtn treeNode={treeNode} />}
|
||||||
|
<div className="tree-node-icon">{createIcon(treeNode.icon)}</div>
|
||||||
|
<div className="tree-node-title-label" onDoubleClick={isNodeParent ? this.enableEdit : undefined}>
|
||||||
|
{editing ? (
|
||||||
|
<input
|
||||||
|
className="tree-node-title-input"
|
||||||
|
defaultValue={treeNode.titleLabel}
|
||||||
|
onBlur={this.saveEdit}
|
||||||
|
ref={this.setCaret}
|
||||||
|
onKeyUp={this.handleKeyUp}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Fragment>
|
||||||
|
<Title title={treeNode.title} />
|
||||||
|
{node.slotFor && (
|
||||||
|
<a className="tree-node-tag slot">
|
||||||
|
{/* todo: click redirect to prop */}
|
||||||
|
<Tip>{intlNode('Slot for {prop}', { prop: node.slotFor.key })}</Tip>
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
{node.hasLoop() && (
|
||||||
|
<a className="tree-node-tag loop">
|
||||||
|
{/* todo: click todo something */}
|
||||||
|
<IconLoop />
|
||||||
|
<Tip>{intlNode('Loop')}</Tip>
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
{node.hasCondition() && !node.conditionGroup && (
|
||||||
|
<a className="tree-node-tag cond">
|
||||||
|
{/* todo: click todo something */}
|
||||||
|
<IconCond />
|
||||||
|
<Tip>{intlNode('Conditional')}</Tip>
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{isCNode && isNodeParent && !isModal && <HideBtn treeNode={treeNode} />}
|
||||||
|
{/* isCNode && isNodeParent && <LockBtn treeNode={treeNode} /> */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @observer
|
||||||
|
// class LockBtn extends Component<{ treeNode: TreeNode }> {
|
||||||
|
// shouldComponentUpdate() {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// render() {
|
||||||
|
// const { treeNode } = this.props;
|
||||||
|
// return (
|
||||||
|
// <div
|
||||||
|
// className="tree-node-lock-btn"
|
||||||
|
// onClick={(e) => {
|
||||||
|
// e.stopPropagation();
|
||||||
|
// treeNode.setLocked(!treeNode.locked);
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// {treeNode.locked ? <IconLock /> : <IconUnlock />}
|
||||||
|
// <Tip>{treeNode.locked ? intl('Unlock') : intl('Lock')}</Tip>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class HideBtn extends Component<{ treeNode: TreeNode }> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="tree-node-hide-btn"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
emitOutlineEvent(treeNode.hidden ? 'show' : 'hide', treeNode);
|
||||||
|
treeNode.setHidden(!treeNode.hidden);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{treeNode.hidden ? <IconEyeClose /> : <IconEye />}
|
||||||
|
<Tip>{treeNode.hidden ? intl('Show') : intl('Hide')}</Tip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class ExpandBtn extends Component<{ treeNode: TreeNode }> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
if (!treeNode.expandable) {
|
||||||
|
return <i className="tree-node-expand-placeholder" />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="tree-node-expand-btn"
|
||||||
|
onClick={(e) => {
|
||||||
|
if (treeNode.expanded) {
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
emitOutlineEvent(treeNode.expanded ? 'collapse' : 'expand', treeNode);
|
||||||
|
treeNode.setExpanded(!treeNode.expanded);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconArrowRight size="small" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
interface Point {
|
||||||
|
clientX: number;
|
||||||
|
clientY: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCaret(point: Point) {
|
||||||
|
debugger;
|
||||||
|
const range = getRangeFromPoint(point);
|
||||||
|
if (range) {
|
||||||
|
selectRange(range);
|
||||||
|
setTimeout(() => selectRange(range), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRangeFromPoint(point: Point): Range | undefined {
|
||||||
|
const x = point.clientX;
|
||||||
|
const y = point.clientY;
|
||||||
|
let range;
|
||||||
|
let pos: CaretPosition | null = null;
|
||||||
|
if (document.caretRangeFromPoint) {
|
||||||
|
range = document.caretRangeFromPoint(x, y);
|
||||||
|
} else if ((pos = document.caretPositionFromPoint(x, y))) {
|
||||||
|
range = document.createRange();
|
||||||
|
range.setStart(pos.offsetNode, pos.offset);
|
||||||
|
range.collapse(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectRange(range: Range) {
|
||||||
|
const selection = document.getSelection();
|
||||||
|
if (selection) {
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCaretAfter(elem) {
|
||||||
|
const range = document.createRange();
|
||||||
|
const node = elem.lastChild;
|
||||||
|
if (!node) return;
|
||||||
|
range.setStartAfter(node);
|
||||||
|
range.setEndAfter(node);
|
||||||
|
selectRange(range);
|
||||||
|
}
|
||||||
|
*/
|
||||||
165
packages/plugin-outline-pane/src/views/tree.tsx
Normal file
165
packages/plugin-outline-pane/src/views/tree.tsx
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import { Component, MouseEvent as ReactMouseEvent } from 'react';
|
||||||
|
import { observer, Editor, globalContext } from '@ali/lowcode-editor-core';
|
||||||
|
import { isRootNode, Node, DragObjectType, isShaken } from '@ali/lowcode-designer';
|
||||||
|
import { isFormEvent } from '@ali/lowcode-utils';
|
||||||
|
import { Tree } from '../tree';
|
||||||
|
import RootTreeNodeView from './root-tree-node';
|
||||||
|
|
||||||
|
function getTreeNodeIdByEvent(e: ReactMouseEvent, stop: Element): null | string {
|
||||||
|
let target: Element | null = e.target as Element;
|
||||||
|
if (!target || !stop.contains(target)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
target = target.closest('[data-id]');
|
||||||
|
if (!target || !stop.contains(target)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (target as HTMLDivElement).dataset.id || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class TreeView extends Component<{ tree: Tree }> {
|
||||||
|
private shell: HTMLDivElement | null = null;
|
||||||
|
|
||||||
|
private hover(e: ReactMouseEvent) {
|
||||||
|
const { tree } = this.props;
|
||||||
|
|
||||||
|
const doc = tree.document;
|
||||||
|
const { detecting } = doc.designer;
|
||||||
|
if (!detecting.enable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const node = this.getTreeNodeFromEvent(e)?.node;
|
||||||
|
detecting.capture(node || null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private onClick = (e: ReactMouseEvent) => {
|
||||||
|
if (this.ignoreUpSelected) {
|
||||||
|
this.boostEvent = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.boostEvent && isShaken(this.boostEvent, e.nativeEvent)) {
|
||||||
|
this.boostEvent = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.boostEvent = undefined;
|
||||||
|
const treeNode = this.getTreeNodeFromEvent(e);
|
||||||
|
if (!treeNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { node } = treeNode;
|
||||||
|
const { designer } = treeNode;
|
||||||
|
const doc = node.document;
|
||||||
|
const { selection } = doc;
|
||||||
|
const { id } = node;
|
||||||
|
const isMulti = e.metaKey || e.ctrlKey || e.shiftKey;
|
||||||
|
designer.activeTracker.track(node);
|
||||||
|
if (isMulti && !isRootNode(node) && selection.has(id)) {
|
||||||
|
if (!isFormEvent(e.nativeEvent)) {
|
||||||
|
selection.remove(id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selection.select(id);
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
const selectedNode = designer.currentSelection?.getNodes()?.[0];
|
||||||
|
const npm = selectedNode?.componentMeta?.npm;
|
||||||
|
const selected =
|
||||||
|
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
|
||||||
|
selectedNode?.componentMeta?.componentName ||
|
||||||
|
'';
|
||||||
|
editor?.emit('outlinePane.select', {
|
||||||
|
selected,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private onMouseOver = (e: ReactMouseEvent) => {
|
||||||
|
this.hover(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
private getTreeNodeFromEvent(e: ReactMouseEvent) {
|
||||||
|
if (!this.shell) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = getTreeNodeIdByEvent(e, this.shell);
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { tree } = this.props;
|
||||||
|
return tree.getTreeNodeById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ignoreUpSelected = false;
|
||||||
|
|
||||||
|
private boostEvent?: MouseEvent;
|
||||||
|
|
||||||
|
private onMouseDown = (e: ReactMouseEvent) => {
|
||||||
|
if (isFormEvent(e.nativeEvent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const treeNode = this.getTreeNodeFromEvent(e);
|
||||||
|
if (!treeNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { node } = treeNode;
|
||||||
|
const { designer } = treeNode;
|
||||||
|
const doc = node.document;
|
||||||
|
const { selection } = doc;
|
||||||
|
|
||||||
|
// TODO: shift selection
|
||||||
|
const isMulti = e.metaKey || e.ctrlKey || e.shiftKey;
|
||||||
|
const isLeftButton = e.button === 0;
|
||||||
|
|
||||||
|
if (isLeftButton && !isRootNode(node)) {
|
||||||
|
let nodes: Node[] = [node];
|
||||||
|
this.ignoreUpSelected = false;
|
||||||
|
if (isMulti) {
|
||||||
|
// multi select mode, directily add
|
||||||
|
if (!selection.has(node.id)) {
|
||||||
|
designer.activeTracker.track(node);
|
||||||
|
selection.add(node.id);
|
||||||
|
this.ignoreUpSelected = true;
|
||||||
|
}
|
||||||
|
selection.remove(doc.rootNode.id);
|
||||||
|
// 获得顶层 nodes
|
||||||
|
nodes = selection.getTopNodes();
|
||||||
|
} else if (selection.has(node.id)) {
|
||||||
|
nodes = selection.getTopNodes();
|
||||||
|
}
|
||||||
|
this.boostEvent = e.nativeEvent;
|
||||||
|
designer.dragon.boost(
|
||||||
|
{
|
||||||
|
type: DragObjectType.Node,
|
||||||
|
nodes,
|
||||||
|
},
|
||||||
|
this.boostEvent,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private onMouseLeave = () => {
|
||||||
|
const { tree } = this.props;
|
||||||
|
const doc = tree.document;
|
||||||
|
doc.designer.detecting.leave(doc);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { tree } = this.props;
|
||||||
|
const { root } = tree;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="lc-outline-tree"
|
||||||
|
ref={(shell) => { this.shell = shell; }}
|
||||||
|
onMouseDownCapture={this.onMouseDown}
|
||||||
|
onMouseOver={this.onMouseOver}
|
||||||
|
onClick={this.onClick}
|
||||||
|
onMouseLeave={this.onMouseLeave}
|
||||||
|
>
|
||||||
|
<RootTreeNodeView key={root.id} treeNode={root} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user