mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-04-20 12:28:08 +00:00
Merge branch 'master' into polyfill/vision
This commit is contained in:
commit
eb5f0871bb
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,7 @@ packages/*/dist/
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
yarn.lock
|
yarn.lock
|
||||||
deploy-space/packages
|
deploy-space/packages
|
||||||
|
deploy-space/.env
|
||||||
|
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
|
|||||||
@ -11,11 +11,12 @@
|
|||||||
#### 跑起来:
|
#### 跑起来:
|
||||||
|
|
||||||
- `npm run setup`
|
- `npm run setup`
|
||||||
|
- `npm start`
|
||||||
|
|
||||||
#### 开发提交:
|
#### 开发提交:
|
||||||
|
|
||||||
- `git add <your-files>`
|
- `git add <your-files>`
|
||||||
- `npm run commit`
|
- `npm run commit` # 在根目录
|
||||||
|
|
||||||
## 发布
|
## 发布
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<title>LowCodeEngine DEMO</title>
|
<title>LowCodeEngine Editor DEMO</title>
|
||||||
<link rel="shortcut icon" href="./favicon.png" />
|
<link rel="shortcut icon" href="./favicon.png" />
|
||||||
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
|
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
|
||||||
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
|
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<!-- lowcode engine globals -->
|
<!-- lowcode engine globals -->
|
||||||
<link rel="stylesheet" href="./globals.css" />
|
<link rel="stylesheet" href="./globals.css" />
|
||||||
<!-- lowcode engine app -->
|
<!-- lowcode engine app -->
|
||||||
<link rel="stylesheet" href="./lowcode-demo.css" />
|
<link rel="stylesheet" href="./lowcode-editor.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -24,6 +24,6 @@
|
|||||||
<!-- lowcode engine globals -->
|
<!-- lowcode engine globals -->
|
||||||
<script src="./globals.js"></script>
|
<script src="./globals.js"></script>
|
||||||
<!-- lowcode engine app -->
|
<!-- lowcode engine app -->
|
||||||
<script src="./lowcode-demo.js"></script>
|
<script src="./lowcode-editor.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<title>LowCodeEngine DEMO</title>
|
<title>LowCodeEngine Preview DEMO</title>
|
||||||
|
<link rel="shortcut icon" href="./favicon.png" />
|
||||||
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
|
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
|
||||||
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
|
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
|
||||||
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
|
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
|
||||||
@ -13,9 +14,10 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css">
|
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css">
|
||||||
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
|
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="./lowcode-preview.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="lce-container"></div>
|
<script src="./lowcode-preview.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^1.9.3",
|
|
||||||
"typescript": "^3.2.2"
|
|
||||||
},
|
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
@ -13,5 +9,8 @@
|
|||||||
"**/@alife/theme-lowcode-*"
|
"**/@alife/theme-lowcode-*"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"engines" : { "node" : "^10" }
|
"dependencies": {
|
||||||
|
"tslib": "^1.11.1",
|
||||||
|
"typescript": "^3.8.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
// Target latest version of ECMAScript.
|
// Target latest version of ECMAScript.
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
// Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
|
// Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
|
||||||
"module": "commonjs",
|
"module": "esnext",
|
||||||
// Search under node_modules for non-relative imports.
|
// Search under node_modules for non-relative imports.
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
// Process & infer types from .js files.
|
// Process & infer types from .js files.
|
||||||
@ -34,6 +34,7 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
// skip type checking of declaration files
|
// skip type checking of declaration files
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"outDir": "lib"
|
||||||
},
|
},
|
||||||
"exclude": ["**/test", "**/lib", "**/es", "node_modules"]
|
"exclude": ["**/test", "**/lib", "**/es", "node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
- 使用 `camelCase` 为属性或本地变量命名
|
- 使用 `camelCase` 为属性或本地变量命名
|
||||||
- 不要为私有属性名添加 `_` 前缀
|
- 不要为私有属性名添加 `_` 前缀
|
||||||
- 尽可能使用完整的单词拼写命名
|
- 尽可能使用完整的单词拼写命名
|
||||||
- 文件夹命名统一使用小写
|
- 文件夹/文件命名统一使用小写 `get-custom-data.ts`
|
||||||
|
|
||||||
### 组件
|
### 组件
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"lerna": "2.11.0",
|
"lerna": "2.11.0",
|
||||||
"version": "independent",
|
"version": "independent",
|
||||||
"npmClient": "yarn",
|
"npmClient": "tyarn",
|
||||||
"registry": "http://registry.npm.alibaba-inc.com",
|
"registry": "http://registry.npm.alibaba-inc.com",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"packages": [
|
"packages": [
|
||||||
|
|||||||
52
package.json
52
package.json
@ -1,14 +1,34 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"workspaces": {
|
||||||
|
"packages": [
|
||||||
|
"packages/*"
|
||||||
|
],
|
||||||
|
"nohoist": [
|
||||||
|
"**/css-modules-typescript-loader",
|
||||||
|
"**/@alife/theme-lowcode-*"
|
||||||
|
]
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "lerna run build --stream",
|
||||||
"clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
|
"clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
|
||||||
|
"commit": "git-cz",
|
||||||
|
"pub": "lerna publish",
|
||||||
"setup": "./scripts/setup.sh",
|
"setup": "./scripts/setup.sh",
|
||||||
"start": "./scripts/start.sh",
|
"start": "./scripts/start.sh",
|
||||||
"build": "lerna run build",
|
"test": "lerna run test --stream",
|
||||||
"test": "lerna run test",
|
"test:snapshot": "lerna run test:snapshot"
|
||||||
"test:snapshot": "lerna run test:snapshot",
|
},
|
||||||
"pub": "lerna publish",
|
"lint-staged": {
|
||||||
"commit": "git-cz"
|
"*.{tsx,ts}": [
|
||||||
|
"eslint --quiet",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"commitizen": {
|
||||||
|
"path": "node_modules/cz-conventional-changelog"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ali/lowcode-config": "^2.0.5",
|
"@ali/lowcode-config": "^2.0.5",
|
||||||
@ -26,25 +46,7 @@
|
|||||||
"tslib": "^1.9.3",
|
"tslib": "^1.9.3",
|
||||||
"typescript": "^3.2.2"
|
"typescript": "^3.2.2"
|
||||||
},
|
},
|
||||||
"engines" : { "node" : "^10" },
|
"engines": {
|
||||||
"workspaces": {
|
"node": ">=10.0.0"
|
||||||
"packages": [
|
|
||||||
"packages/*"
|
|
||||||
],
|
|
||||||
"nohoist": [
|
|
||||||
"**/css-modules-typescript-loader",
|
|
||||||
"**/@alife/theme-lowcode-*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lint-staged": {
|
|
||||||
"*.{tsx,ts}": [
|
|
||||||
"eslint --quiet",
|
|
||||||
"git add"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"commitizen": {
|
|
||||||
"path": "node_modules/cz-conventional-changelog"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
packages/code-generator/CHANGELOG.md
Normal file
52
packages/code-generator/CHANGELOG.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-code-generator@0.8.3...@ali/lowcode-code-generator@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-code-generator
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-code-generator@0.8.2...@ali/lowcode-code-generator@0.8.3) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-code-generator
|
||||||
|
|
||||||
|
<a name="0.8.2"></a>
|
||||||
|
## 0.8.2 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* code generator main process ([021d6e0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/021d6e0))
|
||||||
|
* demo schema & complex children type ([a5ee6bd](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a5ee6bd))
|
||||||
|
* fix gaps ([32af3d3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/32af3d3))
|
||||||
|
* project builder fix & publish demo to disk ([26983b3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/26983b3))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.1"></a>
|
||||||
|
## 0.8.1 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* code generator main process ([021d6e0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/021d6e0))
|
||||||
|
* demo schema & complex children type ([a5ee6bd](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a5ee6bd))
|
||||||
|
* fix gaps ([32af3d3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/32af3d3))
|
||||||
|
* project builder fix & publish demo to disk ([26983b3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/26983b3))
|
||||||
|
=======
|
||||||
|
* code generator main process ([021d6e0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/021d6e0fe9fb29a8b6c1c5d5f4d06ec71896faa5))
|
||||||
|
* demo schema & complex children type ([a5ee6bd](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a5ee6bd55806fc9aea695096ccd4c7f50b8e31c4))
|
||||||
|
* fix gaps ([32af3d3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/32af3d3a3ca4d5aca15be25e05c840c8ea0cb6ae))
|
||||||
|
* project builder fix & publish demo to disk ([26983b3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/26983b38c2b0f1d39d79964eb54d8ce60250dd82))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
@ -1,27 +1,34 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-engine-code-generator",
|
"name": "@ali/lowcode-code-generator",
|
||||||
"version": "0.8.0",
|
"version": "0.8.4",
|
||||||
"description": "出码引擎 for LowCode Engine",
|
"description": "出码引擎 for LowCode Engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rimraf lib && tsc",
|
"compile": "rimraf lib && tsc",
|
||||||
|
"build": "rimraf lib && webpack",
|
||||||
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
|
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
|
||||||
"test": "ava"
|
"test": "ava"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/am-eslint-config": "*",
|
"@ali/am-eslint-config": "*",
|
||||||
|
"@types/prettier": "^1.19.1",
|
||||||
"change-case": "^3.1.0",
|
"change-case": "^3.1.0",
|
||||||
|
"prettier": "^2.0.2",
|
||||||
"short-uuid": "^3.1.1"
|
"short-uuid": "^3.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "^1.0.1",
|
"ava": "^1.0.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
|
"ts-loader": "^6.2.2",
|
||||||
"ts-node": "^7.0.1",
|
"ts-node": "^7.0.1",
|
||||||
"tsconfig-paths": "^3.9.0",
|
"tsconfig-paths": "^3.9.0",
|
||||||
"typescript": "^3.8.3"
|
"tsconfig-paths-webpack-plugin": "^3.2.0",
|
||||||
|
"webpack": "^4.42.1",
|
||||||
|
"webpack-cli": "^3.3.11",
|
||||||
|
"webpack-node-externals": "^1.7.2"
|
||||||
},
|
},
|
||||||
"ava": {
|
"ava": {
|
||||||
"compileEnhancements": false,
|
"compileEnhancements": false,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import {
|
|||||||
ICompiledModule,
|
ICompiledModule,
|
||||||
IModuleBuilder,
|
IModuleBuilder,
|
||||||
IResultFile,
|
IResultFile,
|
||||||
|
PostProcessor,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
import { COMMON_SUB_MODULE_NAME } from '../const/generator';
|
import { COMMON_SUB_MODULE_NAME } from '../const/generator';
|
||||||
@ -17,9 +18,11 @@ import ResultFile from '../model/ResultFile';
|
|||||||
export function createModuleBuilder(
|
export function createModuleBuilder(
|
||||||
options: {
|
options: {
|
||||||
plugins: BuilderComponentPlugin[];
|
plugins: BuilderComponentPlugin[];
|
||||||
|
postProcessors: PostProcessor[];
|
||||||
mainFileName?: string;
|
mainFileName?: string;
|
||||||
} = {
|
} = {
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
postProcessors: [],
|
||||||
},
|
},
|
||||||
): IModuleBuilder {
|
): IModuleBuilder {
|
||||||
const chunkGenerator = new ChunkBuilder(options.plugins);
|
const chunkGenerator = new ChunkBuilder(options.plugins);
|
||||||
@ -33,7 +36,7 @@ export function createModuleBuilder(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const files: IResultFile[] = [];
|
let files: IResultFile[] = [];
|
||||||
|
|
||||||
const { chunks } = await chunkGenerator.run(input);
|
const { chunks } = await chunkGenerator.run(input);
|
||||||
chunks.forEach(fileChunkList => {
|
chunks.forEach(fileChunkList => {
|
||||||
@ -46,6 +49,18 @@ export function createModuleBuilder(
|
|||||||
files.push(file);
|
files.push(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (options.postProcessors.length > 0) {
|
||||||
|
files = files.map(file => {
|
||||||
|
let content = file.content;
|
||||||
|
const type = file.ext;
|
||||||
|
options.postProcessors.forEach(processer => {
|
||||||
|
content = processer(content, type);
|
||||||
|
});
|
||||||
|
|
||||||
|
return new ResultFile(file.name, type, content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
files,
|
files,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,10 +8,11 @@ import {
|
|||||||
IResultDir,
|
IResultDir,
|
||||||
IResultFile,
|
IResultFile,
|
||||||
ISchemaParser,
|
ISchemaParser,
|
||||||
|
PostProcessor,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
import ResultDir from '@/model/ResultDir';
|
import ResultDir from '@/model/ResultDir';
|
||||||
import SchemaParser from '@/parse/SchemaParser';
|
import SchemaParser from '@/parser/SchemaParser';
|
||||||
|
|
||||||
import { createModuleBuilder } from '@/generator/ModuleBuilder';
|
import { createModuleBuilder } from '@/generator/ModuleBuilder';
|
||||||
|
|
||||||
@ -40,16 +41,20 @@ function getDirFromRoot(root: IResultDir, path: string[]): IResultDir {
|
|||||||
export class ProjectBuilder implements IProjectBuilder {
|
export class ProjectBuilder implements IProjectBuilder {
|
||||||
private template: IProjectTemplate;
|
private template: IProjectTemplate;
|
||||||
private plugins: IProjectPlugins;
|
private plugins: IProjectPlugins;
|
||||||
|
private postProcessors: PostProcessor[];
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
template,
|
template,
|
||||||
plugins,
|
plugins,
|
||||||
|
postProcessors,
|
||||||
}: {
|
}: {
|
||||||
template: IProjectTemplate;
|
template: IProjectTemplate;
|
||||||
plugins: IProjectPlugins;
|
plugins: IProjectPlugins;
|
||||||
|
postProcessors: PostProcessor[];
|
||||||
}) {
|
}) {
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.plugins = plugins;
|
this.plugins = plugins;
|
||||||
|
this.postProcessors = postProcessors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async generateProject(schema: IProjectSchema): Promise<IResultDir> {
|
public async generateProject(schema: IProjectSchema): Promise<IResultDir> {
|
||||||
@ -212,45 +217,57 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
|
|
||||||
builders.components = createModuleBuilder({
|
builders.components = createModuleBuilder({
|
||||||
plugins: this.plugins.components,
|
plugins: this.plugins.components,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
|
});
|
||||||
|
builders.pages = createModuleBuilder({
|
||||||
|
plugins: this.plugins.pages,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
builders.pages = createModuleBuilder({ plugins: this.plugins.pages });
|
|
||||||
builders.router = createModuleBuilder({
|
builders.router = createModuleBuilder({
|
||||||
plugins: this.plugins.router,
|
plugins: this.plugins.router,
|
||||||
mainFileName: this.template.slots.router.fileName,
|
mainFileName: this.template.slots.router.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
builders.entry = createModuleBuilder({
|
builders.entry = createModuleBuilder({
|
||||||
plugins: this.plugins.entry,
|
plugins: this.plugins.entry,
|
||||||
mainFileName: this.template.slots.entry.fileName,
|
mainFileName: this.template.slots.entry.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
builders.globalStyle = createModuleBuilder({
|
builders.globalStyle = createModuleBuilder({
|
||||||
plugins: this.plugins.globalStyle,
|
plugins: this.plugins.globalStyle,
|
||||||
mainFileName: this.template.slots.globalStyle.fileName,
|
mainFileName: this.template.slots.globalStyle.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
builders.htmlEntry = createModuleBuilder({
|
builders.htmlEntry = createModuleBuilder({
|
||||||
plugins: this.plugins.htmlEntry,
|
plugins: this.plugins.htmlEntry,
|
||||||
mainFileName: this.template.slots.htmlEntry.fileName,
|
mainFileName: this.template.slots.htmlEntry.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
builders.packageJSON = createModuleBuilder({
|
builders.packageJSON = createModuleBuilder({
|
||||||
plugins: this.plugins.packageJSON,
|
plugins: this.plugins.packageJSON,
|
||||||
mainFileName: this.template.slots.packageJSON.fileName,
|
mainFileName: this.template.slots.packageJSON.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.template.slots.constants && this.plugins.constants) {
|
if (this.template.slots.constants && this.plugins.constants) {
|
||||||
builders.constants = createModuleBuilder({
|
builders.constants = createModuleBuilder({
|
||||||
plugins: this.plugins.constants,
|
plugins: this.plugins.constants,
|
||||||
mainFileName: this.template.slots.constants.fileName,
|
mainFileName: this.template.slots.constants.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (this.template.slots.utils && this.plugins.utils) {
|
if (this.template.slots.utils && this.plugins.utils) {
|
||||||
builders.utils = createModuleBuilder({
|
builders.utils = createModuleBuilder({
|
||||||
plugins: this.plugins.utils,
|
plugins: this.plugins.utils,
|
||||||
mainFileName: this.template.slots.utils.fileName,
|
mainFileName: this.template.slots.utils.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (this.template.slots.i18n && this.plugins.i18n) {
|
if (this.template.slots.i18n && this.plugins.i18n) {
|
||||||
builders.i18n = createModuleBuilder({
|
builders.i18n = createModuleBuilder({
|
||||||
plugins: this.plugins.i18n,
|
plugins: this.plugins.i18n,
|
||||||
mainFileName: this.template.slots.i18n.fileName,
|
mainFileName: this.template.slots.i18n.fileName,
|
||||||
|
postProcessors: this.postProcessors,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,12 +278,15 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
export function createProjectBuilder({
|
export function createProjectBuilder({
|
||||||
template,
|
template,
|
||||||
plugins,
|
plugins,
|
||||||
|
postProcessors,
|
||||||
}: {
|
}: {
|
||||||
template: IProjectTemplate;
|
template: IProjectTemplate;
|
||||||
plugins: IProjectPlugins;
|
plugins: IProjectPlugins;
|
||||||
|
postProcessors: PostProcessor[];
|
||||||
}): IProjectBuilder {
|
}): IProjectBuilder {
|
||||||
return new ProjectBuilder({
|
return new ProjectBuilder({
|
||||||
template,
|
template,
|
||||||
plugins,
|
plugins,
|
||||||
|
postProcessors,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
import { createProjectBuilder } from '@/generator/ProjectBuilder';
|
import { createProjectBuilder } from '@/generator/ProjectBuilder';
|
||||||
|
import { createDiskPublisher } from '@/publisher/disk';
|
||||||
import createIceJsProjectBuilder from '@/solutions/icejs';
|
import createIceJsProjectBuilder from '@/solutions/icejs';
|
||||||
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
@ -12,4 +13,7 @@ export default {
|
|||||||
solutions: {
|
solutions: {
|
||||||
icejs: createIceJsProjectBuilder,
|
icejs: createIceJsProjectBuilder,
|
||||||
},
|
},
|
||||||
|
publishers: {
|
||||||
|
disk: createDiskPublisher,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
3
packages/code-generator/src/postprocessor/index.ts
Normal file
3
packages/code-generator/src/postprocessor/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import prettier from './prettier';
|
||||||
|
|
||||||
|
export { prettier };
|
||||||
22
packages/code-generator/src/postprocessor/prettier/index.ts
Normal file
22
packages/code-generator/src/postprocessor/prettier/index.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import prettier from 'prettier';
|
||||||
|
|
||||||
|
import { PostProcessor } from '@/types';
|
||||||
|
|
||||||
|
const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue'];
|
||||||
|
|
||||||
|
const codePrettier: PostProcessor = (content: string, fileType: string) => {
|
||||||
|
let parser: prettier.BuiltInParserName;
|
||||||
|
if (fileType === 'js' || fileType === 'jsx') {
|
||||||
|
parser = 'babel';
|
||||||
|
} else if (PARSERS.indexOf(fileType) >= 0) {
|
||||||
|
parser = fileType as prettier.BuiltInParserName;
|
||||||
|
} else {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prettier.format(content, {
|
||||||
|
parser,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default codePrettier;
|
||||||
@ -21,6 +21,8 @@ import template from '@/plugins/project/framework/icejs/template';
|
|||||||
import i18n from '@/plugins/project/i18n';
|
import i18n from '@/plugins/project/i18n';
|
||||||
import utils from '@/plugins/project/utils';
|
import utils from '@/plugins/project/utils';
|
||||||
|
|
||||||
|
import { prettier } from '@/postprocessor';
|
||||||
|
|
||||||
export default function createIceJsProjectBuilder(): IProjectBuilder {
|
export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||||
return createProjectBuilder({
|
return createProjectBuilder({
|
||||||
template,
|
template,
|
||||||
@ -56,5 +58,6 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
|||||||
htmlEntry: [iceJsEntryHtml],
|
htmlEntry: [iceJsEntryHtml],
|
||||||
packageJSON: [iceJsPackageJSON],
|
packageJSON: [iceJsPackageJSON],
|
||||||
},
|
},
|
||||||
|
postProcessors: [prettier],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -141,3 +141,5 @@ export interface IProjectPlugins {
|
|||||||
export interface IProjectBuilder {
|
export interface IProjectBuilder {
|
||||||
generateProject(schema: IProjectSchema): Promise<IResultDir>;
|
generateProject(schema: IProjectSchema): Promise<IResultDir>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PostProcessor = (content: string, fileType: string) => string;
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es6",
|
"target": "es5",
|
||||||
"module": "commonjs",
|
"strictNullChecks": true,
|
||||||
"outDir": "lib",
|
"inlineSources": false,
|
||||||
|
"lib": ["es6"],
|
||||||
|
"downlevelIteration": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
"outDir": "./lib",
|
||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
"baseUrl": "." /* Base directory to resolve non-absolute module names. */
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*"
|
"src/**/*"
|
||||||
|
|||||||
31
packages/code-generator/webpack.config.js
Normal file
31
packages/code-generator/webpack.config.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const nodeExternals = require('webpack-node-externals');
|
||||||
|
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'production',
|
||||||
|
target: 'node',
|
||||||
|
entry: {
|
||||||
|
index: './src/index.ts',
|
||||||
|
// demo: './src/demo/main.ts',
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [ '.tsx', '.ts', '.js' ],
|
||||||
|
plugins: [new TsconfigPathsPlugin({/* options: see below */})],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
// filename: 'bundle.js',
|
||||||
|
filename: '[name].js',
|
||||||
|
path: path.resolve(__dirname, 'lib'),
|
||||||
|
},
|
||||||
|
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
|
||||||
|
};
|
||||||
81
packages/demo/CHANGELOG.md
Normal file
81
packages/demo/CHANGELOG.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.8.8"></a>
|
||||||
|
## [0.8.8](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.7...@ali/lowcode-demo@0.8.8) (2020-03-31)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-demo
|
||||||
|
|
||||||
|
<a name="0.8.7"></a>
|
||||||
|
## [0.8.7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.6...@ali/lowcode-demo@0.8.7) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-demo
|
||||||
|
|
||||||
|
<a name="0.8.6"></a>
|
||||||
|
## [0.8.6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.5...@ali/lowcode-demo@0.8.6) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-demo
|
||||||
|
|
||||||
|
<a name="0.8.5"></a>
|
||||||
|
## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.4...@ali/lowcode-demo@0.8.5) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* depend ([c90996d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/c90996d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.3...@ali/lowcode-demo@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-demo
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-demo@0.8.2...@ali/lowcode-demo@0.8.3) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-demo
|
||||||
|
|
||||||
|
<a name="0.8.2"></a>
|
||||||
|
## 0.8.2 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* complet preview ([56c16ff](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56c16ff))
|
||||||
|
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.1"></a>
|
||||||
|
## 0.8.1 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* complet preview ([56c16ff](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56c16ff))
|
||||||
|
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
|
||||||
|
=======
|
||||||
|
* complet preview ([56c16ff](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/56c16ffa5c39c2d01abd9cfa90fea49a4539da1d))
|
||||||
|
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7c0c488ef24f825760750a13d3fa083c96))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"entry": {
|
"entry": {
|
||||||
"index": "src/index.jsx",
|
"index": "src/index.ts",
|
||||||
"react-simulator-renderer": "../react-simulator-renderer/src/index.js"
|
"react-simulator-renderer": "../react-simulator-renderer/src/index.ts",
|
||||||
|
"preview": "src/preview.ts"
|
||||||
},
|
},
|
||||||
"vendor": false,
|
"vendor": false,
|
||||||
"devServer": {
|
"devServer": {
|
||||||
@ -15,7 +16,9 @@
|
|||||||
"@alifd/next": "window.Next"
|
"@alifd/next": "window.Next"
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
["build-plugin-react-app"],
|
[
|
||||||
|
"build-plugin-react-app"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"build-plugin-fusion",
|
"build-plugin-fusion",
|
||||||
{
|
{
|
||||||
@ -25,7 +28,9 @@
|
|||||||
[
|
[
|
||||||
"build-plugin-moment-locales",
|
"build-plugin-moment-locales",
|
||||||
{
|
{
|
||||||
"locales": ["zh-cn"]
|
"locales": [
|
||||||
|
"zh-cn"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"./build.plugin.js"
|
"./build.plugin.js"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"entry": {
|
"entry": {
|
||||||
"lowcode-demo": "src/index.jsx"
|
"lowcode-editor": "src/index.ts",
|
||||||
|
"lowcode-preview": "src/preview.ts"
|
||||||
},
|
},
|
||||||
"vendor": false,
|
"vendor": false,
|
||||||
"externals": {
|
"externals": {
|
||||||
|
|||||||
@ -1,28 +1,39 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-demo",
|
"name": "@ali/lowcode-demo",
|
||||||
"version": "0.8.0",
|
"version": "0.8.8",
|
||||||
|
"private": true,
|
||||||
"description": "低代码引擎 DEMO",
|
"description": "低代码引擎 DEMO",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "build-scripts start",
|
"cloud-build": "build-scripts build --config cloud-build.json",
|
||||||
"cloud-build": "build-scripts build --config cloud-build.json"
|
"gen": "npm run genSkeleton && tyarn",
|
||||||
|
"genSkeleton": "iceluna gen lowcode -c ./skeleton.config.js -t ./src/editor/config",
|
||||||
|
"start": "build-scripts start"
|
||||||
},
|
},
|
||||||
|
"config": {},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-editor-core": "^0.8",
|
"@ali/lowcode-editor-core": "^0.8.4",
|
||||||
"@ali/lowcode-editor-skeleton": "^0.8.0",
|
"@ali/lowcode-editor-skeleton": "^0.8.0",
|
||||||
"@ali/lowcode-plugin-designer": "^0.8.0",
|
|
||||||
"@ali/lowcode-setters": "^0.8.0",
|
|
||||||
"@ali/lowcode-plugin-components-pane": "^0.8.0",
|
"@ali/lowcode-plugin-components-pane": "^0.8.0",
|
||||||
"@ali/lowcode-plugin-settings-pane": "^0.8.0",
|
"@ali/lowcode-plugin-designer": "^0.9.1",
|
||||||
"@ali/lowcode-plugin-outline-pane": "^0.8.0",
|
"@ali/lowcode-plugin-event-bind-dialog": "^0.8.0",
|
||||||
"@ali/lowcode-plugin-undo-redo": "^0.8.0",
|
"@ali/lowcode-plugin-outline-pane": "^0.8.7",
|
||||||
"@ali/lowcode-plugin-sample-logo": "^0.8.0",
|
"@ali/lowcode-plugin-sample-logo": "^0.8.0",
|
||||||
"@ali/lowcode-plugin-sample-preview": "^0.8.0",
|
"@ali/lowcode-plugin-sample-preview": "^0.8.6",
|
||||||
|
"@ali/lowcode-plugin-settings-pane": "^0.8.8",
|
||||||
|
"@ali/lowcode-plugin-undo-redo": "^0.8.0",
|
||||||
|
"@ali/lowcode-plugin-variable-bind-dialog": "^0.8.2",
|
||||||
|
"@ali/lowcode-plugin-zh-en": "^0.8.6",
|
||||||
|
"@ali/lowcode-react-renderer": "^0.8.4",
|
||||||
|
"@ali/lowcode-runtime": "^0.8.7",
|
||||||
|
"@ali/lowcode-setters": "^0.8.6",
|
||||||
|
"@alifd/next": "^1.19.12",
|
||||||
"@alife/theme-lowcode-dark": "^0.1.0",
|
"@alife/theme-lowcode-dark": "^0.1.0",
|
||||||
"@alife/theme-lowcode-light": "^0.1.0",
|
"@alife/theme-lowcode-light": "^0.1.0",
|
||||||
"react": "^16.8.1",
|
"react": "^16.8.1",
|
||||||
"react-dom": "^16.8.1"
|
"react-dom": "^16.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@ali/iceluna-cli": "^0.0.16",
|
||||||
"@alib/build-scripts": "^0.1.18",
|
"@alib/build-scripts": "^0.1.18",
|
||||||
"@types/events": "^3.0.0",
|
"@types/events": "^3.0.0",
|
||||||
"@types/react": "^16.8.3",
|
"@types/react": "^16.8.3",
|
||||||
|
|||||||
21
packages/demo/public/preview.html
Normal file
21
packages/demo/public/preview.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<title>LowCodeEngine DEMO</title>
|
||||||
|
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
|
||||||
|
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
|
||||||
|
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
|
||||||
|
<script> React.PropTypes = PropTypes; </script>
|
||||||
|
<script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css">
|
||||||
|
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="lce-container"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,5 +1,10 @@
|
|||||||
export default {
|
module.exports = {
|
||||||
version: '^1.0.2',
|
skeleton: {
|
||||||
|
config: {
|
||||||
|
package: '@ali/lowcode-editor-skeleton',
|
||||||
|
version: '^0.8.0'
|
||||||
|
}
|
||||||
|
},
|
||||||
theme: {
|
theme: {
|
||||||
fusion: {
|
fusion: {
|
||||||
package: '@alife/theme-lowcode-light',
|
package: '@alife/theme-lowcode-light',
|
||||||
@ -22,7 +27,7 @@ export default {
|
|||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/lowcode-plugin-sample-logo',
|
package: '@ali/lowcode-plugin-sample-logo',
|
||||||
version: '1.0.0'
|
version: '^0.8.0'
|
||||||
},
|
},
|
||||||
pluginProps: {
|
pluginProps: {
|
||||||
logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png',
|
logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png',
|
||||||
@ -38,7 +43,7 @@ export default {
|
|||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/lowcode-plugin-undo-redo',
|
package: '@ali/lowcode-plugin-undo-redo',
|
||||||
version: '1.0.0'
|
version: '^0.8.0'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -57,7 +62,7 @@ export default {
|
|||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/lowcode-plugin-sample-preview',
|
package: '@ali/lowcode-plugin-sample-preview',
|
||||||
version: '1.0.0'
|
version: '^0.8.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -68,14 +73,14 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
align: 'top',
|
align: 'top',
|
||||||
icon: 'zujianku',
|
icon: 'zujianku',
|
||||||
title: '组件库'
|
title: '组件库',
|
||||||
|
floatable: true,
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/iceluna-plugin-components-pane',
|
package: '@ali/lowcode-plugin-components-pane',
|
||||||
version: '0.0.1'
|
version: '^0.8.0'
|
||||||
},
|
},
|
||||||
pluginProps: {
|
pluginProps: {
|
||||||
disableAppComponent: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -83,12 +88,24 @@ export default {
|
|||||||
type: 'PanelIcon',
|
type: 'PanelIcon',
|
||||||
props: {
|
props: {
|
||||||
align: 'top',
|
align: 'top',
|
||||||
icon: 'dengpao',
|
icon: 'shuxingkongjian',
|
||||||
title: '大纲树'
|
title: '大纲树'
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/lowcode-plugin-outline-pane',
|
package: '@ali/lowcode-plugin-outline-pane',
|
||||||
version: '^1.0.0'
|
version: '^0.8.0'
|
||||||
|
},
|
||||||
|
pluginProps: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pluginKey: 'zhEn',
|
||||||
|
type: 'Custom',
|
||||||
|
props: {
|
||||||
|
align: 'bottom',
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
package: '@ali/lowcode-plugin-zh-en',
|
||||||
|
version: '^0.8.0'
|
||||||
},
|
},
|
||||||
pluginProps: {}
|
pluginProps: {}
|
||||||
}
|
}
|
||||||
@ -100,7 +117,7 @@ export default {
|
|||||||
props: {},
|
props: {},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/lowcode-plugin-settings-pane',
|
package: '@ali/lowcode-plugin-settings-pane',
|
||||||
version: '^1.0.0'
|
version: '^0.8.0'
|
||||||
},
|
},
|
||||||
pluginProps: {}
|
pluginProps: {}
|
||||||
}
|
}
|
||||||
@ -110,7 +127,14 @@ export default {
|
|||||||
pluginKey: 'designer',
|
pluginKey: 'designer',
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/lowcode-plugin-designer',
|
package: '@ali/lowcode-plugin-designer',
|
||||||
version: '1.0.0'
|
version: '^0.8.0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pluginKey: 'eventBindDialog',
|
||||||
|
config: {
|
||||||
|
package: '@ali/lowcode-plugin-event-bind-dialog',
|
||||||
|
version: '^0.8.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
21
packages/demo/src/app/config/app.ts
Normal file
21
packages/demo/src/app/config/app.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export default {
|
||||||
|
sdkVersion: '1.0.3',
|
||||||
|
history: 'hash', // 浏览器路由:brower 哈希路由:hash
|
||||||
|
containerId: 'lce-container',
|
||||||
|
layout: {
|
||||||
|
componentName: 'BasicLayout',
|
||||||
|
props: {
|
||||||
|
name: '低代码引擎预览 demo',
|
||||||
|
logo: {
|
||||||
|
src: 'https://img.alicdn.com/tfs/TB1L.1QAeL2gK0jSZFmXXc7iXXa-90-90.png',
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
package: '@alife/theme-fusion',
|
||||||
|
version: '^0.1.0',
|
||||||
|
},
|
||||||
|
compDependencies: [],
|
||||||
|
};
|
||||||
5
packages/demo/src/app/config/components.ts
Normal file
5
packages/demo/src/app/config/components.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* 内置组件
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {};
|
||||||
53
packages/demo/src/app/config/componentsMap.ts
Normal file
53
packages/demo/src/app/config/componentsMap.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
export default {
|
||||||
|
Button: {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Button',
|
||||||
|
},
|
||||||
|
'Button.Group': {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Button',
|
||||||
|
subName: 'Group',
|
||||||
|
},
|
||||||
|
Input: {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Input',
|
||||||
|
},
|
||||||
|
Form: {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Form',
|
||||||
|
},
|
||||||
|
'Form.Item': {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Form',
|
||||||
|
subName: 'Item',
|
||||||
|
},
|
||||||
|
NumberPicker: {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'NumberPicker',
|
||||||
|
},
|
||||||
|
Select: {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Select',
|
||||||
|
},
|
||||||
|
'Select.Option': {
|
||||||
|
package: '@alifd/next',
|
||||||
|
version: '1.19.18',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Select',
|
||||||
|
subName: 'Option',
|
||||||
|
},
|
||||||
|
};
|
||||||
1
packages/demo/src/app/config/utils.ts
Normal file
1
packages/demo/src/app/config/utils.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
||||||
20
packages/demo/src/app/index.ts
Normal file
20
packages/demo/src/app/index.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { app } from '@ali/lowcode-runtime';
|
||||||
|
import Renderer from '@ali/lowcode-react-renderer';
|
||||||
|
import FusionLoading from './plugins/loading/fusion';
|
||||||
|
import BasicLayout from './layouts/BasicLayout';
|
||||||
|
import Preview from './plugins/provider';
|
||||||
|
|
||||||
|
// 注册渲染模块
|
||||||
|
app.registerRenderer(Renderer);
|
||||||
|
|
||||||
|
// 注册布局组件,可注册多个
|
||||||
|
app.registerLayout('BasicLayout', BasicLayout);
|
||||||
|
|
||||||
|
// 注册页面 Loading
|
||||||
|
app.registerLoading(FusionLoading);
|
||||||
|
|
||||||
|
// appKey:应用唯一标识
|
||||||
|
app.registerProvider(Preview);
|
||||||
|
|
||||||
|
// 启动应用
|
||||||
|
app.run();
|
||||||
24
packages/demo/src/app/layouts/BasicLayout/index.scss
Normal file
24
packages/demo/src/app/layouts/BasicLayout/index.scss
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
$header-height: 52px;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basic-shell {
|
||||||
|
min-height: 100vh;
|
||||||
|
.next-shell-header {
|
||||||
|
height: $header-height;
|
||||||
|
}
|
||||||
|
.next-shell-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
min-height: calc(100% - $header-height);
|
||||||
|
.next-shell-sub-main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
packages/demo/src/app/layouts/BasicLayout/index.tsx
Normal file
34
packages/demo/src/app/layouts/BasicLayout/index.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { Search, Icon, Shell } from '@alifd/next';
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
export default ({
|
||||||
|
name,
|
||||||
|
children,
|
||||||
|
logo,
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
children: any;
|
||||||
|
logo: { src: string; width: number; height: number };
|
||||||
|
}) => (
|
||||||
|
<Shell className="basic-shell" style={{ border: '1px solid #eee' }}>
|
||||||
|
<Shell.Branding>
|
||||||
|
<img src={logo.src} width={logo.width} height={logo.height} alt="logo" />
|
||||||
|
<span style={{ marginLeft: 10 }}>{name}</span>
|
||||||
|
</Shell.Branding>
|
||||||
|
<Shell.Navigation direction="hoz">
|
||||||
|
<Search key="2" shape="simple" type="dark" style={{ width: '200px' }} />
|
||||||
|
</Shell.Navigation>
|
||||||
|
<Shell.Action>
|
||||||
|
<Icon type="ic_tongzhi" />
|
||||||
|
<img src="https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png" className="avatar" alt="用户头像" />
|
||||||
|
<span style={{ marginLeft: 10 }}>MyName</span>
|
||||||
|
</Shell.Action>
|
||||||
|
|
||||||
|
<Shell.Content className="content">{children}</Shell.Content>
|
||||||
|
|
||||||
|
<Shell.Footer>
|
||||||
|
<span>Alibaba Fusion</span>
|
||||||
|
<span>@ 2019 Alibaba Piecework 版权所有</span>
|
||||||
|
</Shell.Footer>
|
||||||
|
</Shell>
|
||||||
|
);
|
||||||
9
packages/demo/src/app/plugins/loading/fusion/index.scss
Normal file
9
packages/demo/src/app/plugins/loading/fusion/index.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.fusion-loading {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: -24px;
|
||||||
|
margin-left: -24px;
|
||||||
|
}
|
||||||
4
packages/demo/src/app/plugins/loading/fusion/index.tsx
Normal file
4
packages/demo/src/app/plugins/loading/fusion/index.tsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { Loading } from '@alifd/next';
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
export default () => <Loading tip="加载中..." className="fusion-loading" />;
|
||||||
51
packages/demo/src/app/plugins/provider.ts
Normal file
51
packages/demo/src/app/plugins/provider.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { ReactProvider, Utils } from '@ali/lowcode-runtime';
|
||||||
|
import appConfig from '../config/app';
|
||||||
|
import builtInComps from '../config/components';
|
||||||
|
import componentsMap from '../config/componentsMap';
|
||||||
|
import constants from '../config/constants';
|
||||||
|
import utils from '../config/utils';
|
||||||
|
|
||||||
|
// 定制加载应用配置的逻辑
|
||||||
|
export default class Preview extends ReactProvider {
|
||||||
|
// 定制获取、处理应用配置(组件、插件、路由模式、布局等)的逻辑
|
||||||
|
async getAppData(): Promise<any> {
|
||||||
|
const { history, layout, containerId } = appConfig;
|
||||||
|
const appSchemaStr: any = localStorage.getItem('lce-dev-store');
|
||||||
|
if (!appSchemaStr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const appSchema = JSON.parse(appSchemaStr);
|
||||||
|
if (!appSchema) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const routes: any = {};
|
||||||
|
appSchema.componentsTree.forEach((page: any) => {
|
||||||
|
if (!page.fileName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pageId = page.fileName;
|
||||||
|
routes[pageId] = `/${pageId}`;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
history,
|
||||||
|
layout,
|
||||||
|
routes,
|
||||||
|
containerId,
|
||||||
|
components: { ...builtInComps, ...Utils.buildComponents({ '@alifd/next': 'Next' }, componentsMap) },
|
||||||
|
componentsMap,
|
||||||
|
utils: utils,
|
||||||
|
constants,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定制获取、处理页面 schema 的逻辑
|
||||||
|
async getPageData(pageId: string) {
|
||||||
|
const appSchemaStr = localStorage.getItem('lce-dev-store');
|
||||||
|
const appSchema = JSON.parse(appSchemaStr || '');
|
||||||
|
const idx = appSchema.componentsTree.findIndex(
|
||||||
|
(page: any, idx: number) => (page.fileName || `page${idx}`) === pageId,
|
||||||
|
);
|
||||||
|
const schema = appSchema.componentsTree[idx];
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import undoRedo from '@ali/lowcode-plugin-undo-redo';
|
|
||||||
import logo from '@ali/lowcode-plugin-sample-logo';
|
|
||||||
import SamplePreview from '@ali/lowcode-plugin-sample-preview';
|
|
||||||
import Designer from '@ali/lowcode-plugin-designer';
|
|
||||||
import SettingsPane from '@ali/lowcode-plugin-settings-pane';
|
|
||||||
import componentsPane from '@ali/lowcode-plugin-components-pane';
|
|
||||||
import OutlinePane from '@ali/lowcode-plugin-outline-pane';
|
|
||||||
import { PluginFactory } from '@ali/lowcode-editor-core';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
logo: PluginFactory(logo),
|
|
||||||
samplePreview: PluginFactory(SamplePreview),
|
|
||||||
undoRedo: PluginFactory(undoRedo),
|
|
||||||
designer: PluginFactory(Designer),
|
|
||||||
componentsPane: PluginFactory(componentsPane),
|
|
||||||
settingsPane: PluginFactory(SettingsPane),
|
|
||||||
outlinePane: PluginFactory(OutlinePane),
|
|
||||||
};
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
export default {
|
|
||||||
namespace: 'page'
|
|
||||||
};
|
|
||||||
22
packages/demo/src/editor/config/components.js
Normal file
22
packages/demo/src/editor/config/components.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import LowcodeSkeleton from '@ali/lowcode-editor-skeleton';
|
||||||
|
import logo from '@ali/lowcode-plugin-sample-logo';
|
||||||
|
import undoRedo from '@ali/lowcode-plugin-undo-redo';
|
||||||
|
import samplePreview from '@ali/lowcode-plugin-sample-preview';
|
||||||
|
import componentsPane from '@ali/lowcode-plugin-components-pane';
|
||||||
|
import outlinePane from '@ali/lowcode-plugin-outline-pane';
|
||||||
|
import zhEn from '@ali/lowcode-plugin-zh-en';
|
||||||
|
import settingsPane from '@ali/lowcode-plugin-settings-pane';
|
||||||
|
import designer from '@ali/lowcode-plugin-designer';
|
||||||
|
import eventBindDialog from '@ali/lowcode-plugin-event-bind-dialog';
|
||||||
|
export default {
|
||||||
|
LowcodeSkeleton,
|
||||||
|
logo,
|
||||||
|
undoRedo,
|
||||||
|
samplePreview,
|
||||||
|
componentsPane,
|
||||||
|
outlinePane,
|
||||||
|
zhEn,
|
||||||
|
settingsPane,
|
||||||
|
designer,
|
||||||
|
eventBindDialog
|
||||||
|
};
|
||||||
3
packages/demo/src/editor/config/constants.js
Normal file
3
packages/demo/src/editor/config/constants.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
"namespace": "page"
|
||||||
|
}
|
||||||
1
packages/demo/src/editor/config/locale/en-US.js
Normal file
1
packages/demo/src/editor/config/locale/en-US.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
||||||
10
packages/demo/src/editor/config/locale/index.js
Normal file
10
packages/demo/src/editor/config/locale/index.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import en_us from './en-US';
|
||||||
|
import zh_cn from './zh-CN';
|
||||||
|
import zh_tw from './zh-TW';
|
||||||
|
import ja_jp from './ja-JP';
|
||||||
|
export default {
|
||||||
|
'en-US': en_us,
|
||||||
|
'zh-CN': zh_cn,
|
||||||
|
'zh-TW': zh_tw,
|
||||||
|
'ja-JP': ja_jp
|
||||||
|
};
|
||||||
1
packages/demo/src/editor/config/locale/ja-JP.js
Normal file
1
packages/demo/src/editor/config/locale/ja-JP.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
||||||
1
packages/demo/src/editor/config/locale/zh-CN.js
Normal file
1
packages/demo/src/editor/config/locale/zh-CN.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
||||||
1
packages/demo/src/editor/config/locale/zh-TW.js
Normal file
1
packages/demo/src/editor/config/locale/zh-TW.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
||||||
140
packages/demo/src/editor/config/skeleton.js
Normal file
140
packages/demo/src/editor/config/skeleton.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
export default {
|
||||||
|
"skeleton": {
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-editor-skeleton",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"theme": {
|
||||||
|
"fusion": {
|
||||||
|
"package": "@alife/theme-lowcode-light",
|
||||||
|
"version": "^0.1.0"
|
||||||
|
},
|
||||||
|
"scss": ""
|
||||||
|
},
|
||||||
|
"constants": {
|
||||||
|
"namespace": "page"
|
||||||
|
},
|
||||||
|
"utils": [],
|
||||||
|
"plugins": {
|
||||||
|
"topArea": [{
|
||||||
|
"pluginKey": "logo",
|
||||||
|
"type": "Custom",
|
||||||
|
"props": {
|
||||||
|
"align": "left",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-sample-logo",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
},
|
||||||
|
"pluginProps": {
|
||||||
|
"logo": "https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png",
|
||||||
|
"href": "/"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"pluginKey": "undoRedo",
|
||||||
|
"type": "Custom",
|
||||||
|
"props": {
|
||||||
|
"align": "right",
|
||||||
|
"width": 88
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-undo-redo",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"pluginKey": "divider",
|
||||||
|
"type": "Divider",
|
||||||
|
"props": {
|
||||||
|
"align": "right"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"pluginKey": "samplePreview",
|
||||||
|
"type": "Custom",
|
||||||
|
"props": {
|
||||||
|
"align": "right",
|
||||||
|
"width": 64
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-sample-preview",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"leftArea": [{
|
||||||
|
"pluginKey": "componentsPane",
|
||||||
|
"type": "PanelIcon",
|
||||||
|
"props": {
|
||||||
|
"align": "top",
|
||||||
|
"icon": "zujianku",
|
||||||
|
"title": "组件库",
|
||||||
|
"floatable": true
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-components-pane",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
},
|
||||||
|
"pluginProps": {}
|
||||||
|
}, {
|
||||||
|
"pluginKey": "outlinePane",
|
||||||
|
"type": "PanelIcon",
|
||||||
|
"props": {
|
||||||
|
"align": "top",
|
||||||
|
"icon": "shuxingkongjian",
|
||||||
|
"title": "大纲树"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-outline-pane",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
},
|
||||||
|
"pluginProps": {}
|
||||||
|
}, {
|
||||||
|
"pluginKey": "zhEn",
|
||||||
|
"type": "Custom",
|
||||||
|
"props": {
|
||||||
|
"align": "bottom"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-zh-en",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
},
|
||||||
|
"pluginProps": {}
|
||||||
|
}],
|
||||||
|
"rightArea": [{
|
||||||
|
"pluginKey": "settingsPane",
|
||||||
|
"type": "Panel",
|
||||||
|
"props": {},
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-settings-pane",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
},
|
||||||
|
"pluginProps": {}
|
||||||
|
}],
|
||||||
|
"centerArea": [{
|
||||||
|
"pluginKey": "designer",
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-designer",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"pluginKey": "eventBindDialog",
|
||||||
|
"config": {
|
||||||
|
"package": "@ali/lowcode-plugin-event-bind-dialog",
|
||||||
|
"version": "^0.8.0"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"hooks": [],
|
||||||
|
"shortCuts": [],
|
||||||
|
"lifeCycles": {
|
||||||
|
"init": async function init(editor) {
|
||||||
|
const assets = await editor.utils.get('./assets.json');
|
||||||
|
editor.set('assets', assets);
|
||||||
|
editor.emit('assets.loaded', assets);
|
||||||
|
|
||||||
|
const schema = await editor.utils.get('./schema.json');
|
||||||
|
editor.set('schema', schema);
|
||||||
|
editor.emit('schema.loaded', schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
3
packages/demo/src/editor/config/utils.js
Normal file
3
packages/demo/src/editor/config/utils.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
|
||||||
|
};
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import Skeleton from '@ali/lowcode-editor-skeleton';
|
|
||||||
import { registerSetters } from '@ali/lowcode-setters';
|
import { registerSetters } from '@ali/lowcode-setters';
|
||||||
import config from './config/skeleton';
|
import config from './config/skeleton';
|
||||||
import components from './config/components';
|
import components from './config/components';
|
||||||
@ -10,7 +9,7 @@ import './global.scss';
|
|||||||
import './config/theme.scss';
|
import './config/theme.scss';
|
||||||
|
|
||||||
registerSetters();
|
registerSetters();
|
||||||
|
const Skeleton = components.LowcodeSkeleton;
|
||||||
const LCE_CONTAINER = document.getElementById('lce-container');
|
const LCE_CONTAINER = document.getElementById('lce-container');
|
||||||
|
|
||||||
if (!LCE_CONTAINER) {
|
if (!LCE_CONTAINER) {
|
||||||
1
packages/demo/src/index.ts
Normal file
1
packages/demo/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './editor';
|
||||||
1
packages/demo/src/preview.ts
Normal file
1
packages/demo/src/preview.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './app';
|
||||||
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react",
|
"outDir": "lib"
|
||||||
"target": "ES6"
|
|
||||||
},
|
},
|
||||||
"include": ["src/*"],
|
"include": [
|
||||||
"exclude": ["node_modules", "build", "public"]
|
"./src/"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
74
packages/designer/CHANGELOG.md
Normal file
74
packages/designer/CHANGELOG.md
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.9.1"></a>
|
||||||
|
## [0.9.1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.9.0...@ali/lowcode-designer@0.9.1) (2020-03-31)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-designer
|
||||||
|
|
||||||
|
<a name="0.9.0"></a>
|
||||||
|
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.8.5...@ali/lowcode-designer@0.9.0) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **designer:** fix insertion style ([82c10d2](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/82c10d2))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **designer:** add blank page logic ([aeeb9ba](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/aeeb9ba))
|
||||||
|
* **designer:** add builtin hotkeys ([2ec5883](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2ec5883))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.5"></a>
|
||||||
|
## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.8.4...@ali/lowcode-designer@0.8.5) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-designer
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-designer@0.8.3...@ali/lowcode-designer@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-designer
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## 0.8.3 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
|
||||||
|
* history log ([fbb3577](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fbb3577))
|
||||||
|
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.2"></a>
|
||||||
|
## 0.8.2 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
|
||||||
|
* history log ([fbb3577](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fbb3577))
|
||||||
|
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
|
||||||
|
=======
|
||||||
|
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c2869a0bc901d855279735fe86b84dabaa04d))
|
||||||
|
* history log ([fbb3577](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/fbb3577bd434c0ac77cc907abc36e3efe110fe8c))
|
||||||
|
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e661686e4693e69279c496f3be1dd173703c55e))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-designer",
|
"name": "@ali/lowcode-designer",
|
||||||
"version": "0.8.1",
|
"version": "0.9.1",
|
||||||
"description": "Designer for Ali LowCode Engine",
|
"description": "Designer for Ali LowCode Engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
@ -15,18 +15,18 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-globals": "^0.9.1",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"react": "^16",
|
"react": "^16",
|
||||||
"react-dom": "^16.7.0",
|
"react-dom": "^16.7.0"
|
||||||
"@ali/lowcode-globals": "^0.8"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/medium-editor": "^5.0.3",
|
"@alib/build-scripts": "^0.1.18",
|
||||||
"@types/classnames": "^2.2.7",
|
"@types/classnames": "^2.2.7",
|
||||||
|
"@types/medium-editor": "^5.0.3",
|
||||||
"@types/node": "^13.7.1",
|
"@types/node": "^13.7.1",
|
||||||
"@types/react": "^16",
|
"@types/react": "^16",
|
||||||
"@types/react-dom": "^16",
|
"@types/react-dom": "^16",
|
||||||
"@alib/build-scripts": "^0.1.18",
|
|
||||||
"build-plugin-component": "^0.2.10"
|
"build-plugin-component": "^0.2.10"
|
||||||
},
|
},
|
||||||
"ava": {
|
"ava": {
|
||||||
|
|||||||
@ -1,25 +1,27 @@
|
|||||||
.lc-insertion {
|
.lc-insertion {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -1.5px;
|
top: -2px;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 12;
|
z-index: 12;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
background-color: var(--color-brand-light);
|
background-color: var(--color-brand-light);
|
||||||
height: 3px;
|
height: 4px;
|
||||||
|
|
||||||
&.cover {
|
&.cover {
|
||||||
top: 0;
|
top: 0;
|
||||||
height: auto;
|
height: auto;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
border: none;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.vertical {
|
&.vertical {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -1.5px;
|
left: -2px;
|
||||||
width: 3px;
|
width: 4px;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.invalid {
|
&.invalid {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,11 +20,13 @@ import {
|
|||||||
getRectTarget,
|
getRectTarget,
|
||||||
Rect,
|
Rect,
|
||||||
CanvasPoint,
|
CanvasPoint,
|
||||||
|
hotkey,
|
||||||
} from '../designer';
|
} from '../designer';
|
||||||
import { parseProps } from './utils/parse-props';
|
import { parseProps } from './utils/parse-props';
|
||||||
import { isElement } from '@ali/lowcode-globals';
|
import { isElement } from '@ali/lowcode-globals';
|
||||||
import { ComponentMetadata } from '@ali/lowcode-globals';
|
import { ComponentMetadata } from '@ali/lowcode-globals';
|
||||||
import { BuiltinSimulatorRenderer } from './renderer';
|
import { BuiltinSimulatorRenderer } from './renderer';
|
||||||
|
import clipboard from '../designer/clipboard';
|
||||||
|
|
||||||
export interface LibraryItem {
|
export interface LibraryItem {
|
||||||
package: string;
|
package: string;
|
||||||
@ -196,6 +198,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
// wait 准备 iframe 内容、依赖库注入
|
// wait 准备 iframe 内容、依赖库注入
|
||||||
const renderer = await createSimulator(this, iframe, vendors);
|
const renderer = await createSimulator(this, iframe, vendors);
|
||||||
|
|
||||||
|
// TODO: !!! thinkof reload onload
|
||||||
|
|
||||||
// wait 业务组件被第一次消费,否则会渲染出错
|
// wait 业务组件被第一次消费,否则会渲染出错
|
||||||
await this.componentsConsumer.waitFirstConsume();
|
await this.componentsConsumer.waitFirstConsume();
|
||||||
|
|
||||||
@ -209,11 +213,17 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
this._contentDocument = this._contentWindow.document;
|
this._contentDocument = this._contentWindow.document;
|
||||||
this.viewport.setScrollTarget(this._contentWindow);
|
this.viewport.setScrollTarget(this._contentWindow);
|
||||||
this.setupEvents();
|
this.setupEvents();
|
||||||
// hotkey.mount(this.contentWindow);
|
|
||||||
// clipboard.injectCopyPaster(this.ownerDocument);
|
// bind hotkey & clipboard
|
||||||
|
hotkey.mount(this._contentWindow);
|
||||||
|
clipboard.injectCopyPaster(this._contentDocument);
|
||||||
|
// TODO: dispose the bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
setupEvents() {
|
setupEvents() {
|
||||||
|
// TODO: Thinkof move events control to simulator renderer
|
||||||
|
// just listen special callback
|
||||||
|
// because iframe maybe reload
|
||||||
this.setupDragAndClick();
|
this.setupDragAndClick();
|
||||||
this.setupHovering();
|
this.setupHovering();
|
||||||
}
|
}
|
||||||
@ -786,6 +796,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
const inline = el ? isChildInline(el) : false;
|
const inline = el ? isChildInline(el) : false;
|
||||||
const row = el ? isRowContainer(el.parentElement!) : false;
|
const row = el ? isRowContainer(el.parentElement!) : false;
|
||||||
const vertical = inline || row;
|
const vertical = inline || row;
|
||||||
|
|
||||||
// TODO: fix type
|
// TODO: fix type
|
||||||
const near: any = {
|
const near: any = {
|
||||||
node: nearNode,
|
node: nearNode,
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
IconRemove,
|
|
||||||
IconClone,
|
|
||||||
IconPage,
|
|
||||||
IconContainer,
|
|
||||||
IconComponent,
|
|
||||||
ComponentMetadata,
|
ComponentMetadata,
|
||||||
NpmInfo,
|
NpmInfo,
|
||||||
NodeData,
|
NodeData,
|
||||||
@ -18,6 +13,11 @@ import {
|
|||||||
import { Node, NodeParent } from './document';
|
import { Node, NodeParent } from './document';
|
||||||
import { Designer } from './designer';
|
import { Designer } from './designer';
|
||||||
import { intl } from './locale';
|
import { intl } from './locale';
|
||||||
|
import { IconContainer } from './icons/container';
|
||||||
|
import { IconPage } from './icons/page';
|
||||||
|
import { IconComponent } from './icons/component';
|
||||||
|
import { IconRemove } from './icons/remove';
|
||||||
|
import { IconClone } from './icons/clone';
|
||||||
|
|
||||||
function ensureAList(list?: string | string[]): string[] | null {
|
function ensureAList(list?: string | string[]): string[] | null {
|
||||||
if (!list) {
|
if (!list) {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// { componentsMap, componentsTree, ... }
|
||||||
return JSON.parse(clipboardData.getData('text/plain'));
|
return JSON.parse(clipboardData.getData('text/plain'));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/*
|
/*
|
||||||
@ -17,11 +18,13 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// paste the text by div
|
// TODO: open the parser implement
|
||||||
|
return null;
|
||||||
|
/*
|
||||||
return {
|
return {
|
||||||
code: clipboardData.getData('text/plain'),
|
code: clipboardData.getData('text/plain'),
|
||||||
maps: {},
|
maps: {},
|
||||||
};
|
};*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +36,7 @@ class Clipboard {
|
|||||||
this.isCopyPaster(e.target);
|
this.isCopyPaster(e.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCopyPaster(el: any) {
|
private isCopyPaster(el: any) {
|
||||||
return this.copyPasters.includes(el);
|
return this.copyPasters.includes(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +60,9 @@ class Clipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
injectCopyPaster(document: Document) {
|
injectCopyPaster(document: Document) {
|
||||||
|
if (this.copyPasters.find(x => x.ownerDocument === document)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const copyPaster = document.createElement<'textarea'>('textarea');
|
const copyPaster = document.createElement<'textarea'>('textarea');
|
||||||
copyPaster.style.cssText = 'position: relative;left: -9999px;';
|
copyPaster.style.cssText = 'position: relative;left: -9999px;';
|
||||||
document.body.appendChild(copyPaster);
|
document.body.appendChild(copyPaster);
|
||||||
@ -5,6 +5,7 @@ import BuiltinDragGhostComponent from './drag-ghost';
|
|||||||
import { Designer, DesignerProps } from './designer';
|
import { Designer, DesignerProps } from './designer';
|
||||||
import { ProjectView } from '../project';
|
import { ProjectView } from '../project';
|
||||||
import './designer.less';
|
import './designer.less';
|
||||||
|
import clipboard from './clipboard';
|
||||||
|
|
||||||
export class DesignerView extends Component<DesignerProps> {
|
export class DesignerView extends Component<DesignerProps> {
|
||||||
readonly designer: Designer;
|
readonly designer: Designer;
|
||||||
@ -32,6 +33,7 @@ export class DesignerView extends Component<DesignerProps> {
|
|||||||
if (onMount) {
|
if (onMount) {
|
||||||
onMount(this.designer);
|
onMount(this.designer);
|
||||||
}
|
}
|
||||||
|
clipboard.injectCopyPaster(document)
|
||||||
this.designer.postEvent('mount', this.designer);
|
this.designer.postEvent('mount', this.designer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
autorun,
|
autorun,
|
||||||
} from '@ali/lowcode-globals';
|
} from '@ali/lowcode-globals';
|
||||||
import { Project } from '../project';
|
import { Project } from '../project';
|
||||||
import { Node, DocumentModel, insertChildren, isRootNode } from '../document';
|
import { Node, DocumentModel, insertChildren, isRootNode, NodeParent } from '../document';
|
||||||
import { ComponentMeta } from '../component-meta';
|
import { ComponentMeta } from '../component-meta';
|
||||||
import { INodeSelector } from '../simulator';
|
import { INodeSelector } from '../simulator';
|
||||||
import { Scroller, IScrollable } from './scroller';
|
import { Scroller, IScrollable } from './scroller';
|
||||||
@ -19,6 +19,7 @@ import { ActiveTracker } from './active-tracker';
|
|||||||
import { Hovering } from './hovering';
|
import { Hovering } from './hovering';
|
||||||
import { DropLocation, LocationData, isLocationChildrenDetail } from './location';
|
import { DropLocation, LocationData, isLocationChildrenDetail } from './location';
|
||||||
import { OffsetObserver, createOffsetObserver } from './offset-observer';
|
import { OffsetObserver, createOffsetObserver } from './offset-observer';
|
||||||
|
import { focusing } from './focusing';
|
||||||
|
|
||||||
export interface DesignerProps {
|
export interface DesignerProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -40,7 +41,6 @@ export interface DesignerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Designer {
|
export class Designer {
|
||||||
// readonly hotkey: Hotkey;
|
|
||||||
readonly dragon = new Dragon(this);
|
readonly dragon = new Dragon(this);
|
||||||
readonly activeTracker = new ActiveTracker();
|
readonly activeTracker = new ActiveTracker();
|
||||||
readonly hovering = new Hovering();
|
readonly hovering = new Hovering();
|
||||||
@ -156,6 +156,9 @@ export class Designer {
|
|||||||
this.postEvent('designer.init', this);
|
this.postEvent('designer.init', this);
|
||||||
setupSelection();
|
setupSelection();
|
||||||
setupHistory();
|
setupHistory();
|
||||||
|
|
||||||
|
// TODO: 先简单实现,后期通过焦点赋值
|
||||||
|
focusing.focusDesigner = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
postEvent(event: string, ...args: any[]) {
|
postEvent(event: string, ...args: any[]) {
|
||||||
@ -198,7 +201,7 @@ export class Designer {
|
|||||||
/**
|
/**
|
||||||
* 获得合适的插入位置
|
* 获得合适的插入位置
|
||||||
*/
|
*/
|
||||||
getSuitableInsertion() {
|
getSuitableInsertion(): { target: NodeParent; index?: number } | null {
|
||||||
const activedDoc = this.project.currentDocument;
|
const activedDoc = this.project.currentDocument;
|
||||||
if (!activedDoc) {
|
if (!activedDoc) {
|
||||||
return null;
|
return null;
|
||||||
@ -296,7 +299,7 @@ export class Designer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setSchema(schema?: ProjectSchema) {
|
setSchema(schema?: ProjectSchema) {
|
||||||
this.project.setSchema(schema);
|
this.project.load(schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.val private _componentMetasMap = new Map<string, ComponentMeta>();
|
@obx.val private _componentMetasMap = new Map<string, ComponentMeta>();
|
||||||
|
|||||||
@ -427,8 +427,9 @@ export class Dragon {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const sourceSensor = getSourceSensor(dragObject);
|
const sourceSensor = getSourceSensor(dragObject);
|
||||||
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
|
|
||||||
const chooseSensor = (e: LocateEvent) => {
|
const chooseSensor = (e: LocateEvent) => {
|
||||||
|
// this.sensors will change on dragstart
|
||||||
|
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
|
||||||
let sensor = e.sensor && e.sensor.isEnter(e) ? e.sensor : sensors.find((s) => s.sensorAvailable && s.isEnter(e));
|
let sensor = e.sensor && e.sensor.isEnter(e) ? e.sensor : sensors.find((s) => s.sensorAvailable && s.isEnter(e));
|
||||||
if (!sensor) {
|
if (!sensor) {
|
||||||
// TODO: enter some area like componentspanel cancel
|
// TODO: enter some area like componentspanel cancel
|
||||||
|
|||||||
9
packages/designer/src/designer/focusing.ts
Normal file
9
packages/designer/src/designer/focusing.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Designer } from './designer';
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// 当前激活区域管理
|
||||||
|
class Focusing {
|
||||||
|
focusDesigner?: Designer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const focusing = new Focusing();
|
||||||
@ -1,618 +1,117 @@
|
|||||||
interface KeyMap {
|
import { Hotkey, isFormEvent } from '@ali/lowcode-globals';
|
||||||
[key: number]: string;
|
import { focusing } from './focusing';
|
||||||
}
|
import { insertChildren } from '../document';
|
||||||
|
import clipboard from './clipboard';
|
||||||
|
|
||||||
interface CtrlKeyMap {
|
export const hotkey = new Hotkey();
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ActionEvent {
|
// hotkey binding
|
||||||
type: string;
|
hotkey.bind(['backspace', 'del'], (e: KeyboardEvent) => {
|
||||||
}
|
const doc = focusing.focusDesigner?.currentDocument;
|
||||||
|
if (isFormEvent(e) || !doc) {
|
||||||
interface HotkeyCallbacks {
|
return;
|
||||||
[key: string]: HotkeyCallbackCfg[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HotkeyDirectMap {
|
|
||||||
[key: string]: HotkeyCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type HotkeyCallback = (e: KeyboardEvent, combo?: string) => any | false;
|
|
||||||
|
|
||||||
interface HotkeyCallbackCfg {
|
|
||||||
callback: HotkeyCallback;
|
|
||||||
modifiers: string[];
|
|
||||||
action: string;
|
|
||||||
seq?: string;
|
|
||||||
level?: number;
|
|
||||||
combo?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface KeyInfo {
|
|
||||||
key: string;
|
|
||||||
modifiers: string[];
|
|
||||||
action: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SequenceLevels {
|
|
||||||
[key: string]: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAP: KeyMap = {
|
|
||||||
8: 'backspace',
|
|
||||||
9: 'tab',
|
|
||||||
13: 'enter',
|
|
||||||
16: 'shift',
|
|
||||||
17: 'ctrl',
|
|
||||||
18: 'alt',
|
|
||||||
20: 'capslock',
|
|
||||||
27: 'esc',
|
|
||||||
32: 'space',
|
|
||||||
33: 'pageup',
|
|
||||||
34: 'pagedown',
|
|
||||||
35: 'end',
|
|
||||||
36: 'home',
|
|
||||||
37: 'left',
|
|
||||||
38: 'up',
|
|
||||||
39: 'right',
|
|
||||||
40: 'down',
|
|
||||||
45: 'ins',
|
|
||||||
46: 'del',
|
|
||||||
91: 'meta',
|
|
||||||
93: 'meta',
|
|
||||||
224: 'meta',
|
|
||||||
};
|
|
||||||
|
|
||||||
const KEYCODE_MAP: KeyMap = {
|
|
||||||
106: '*',
|
|
||||||
107: '+',
|
|
||||||
109: '-',
|
|
||||||
110: '.',
|
|
||||||
111: '/',
|
|
||||||
186: ';',
|
|
||||||
187: '=',
|
|
||||||
188: ',',
|
|
||||||
189: '-',
|
|
||||||
190: '.',
|
|
||||||
191: '/',
|
|
||||||
192: '`',
|
|
||||||
219: '[',
|
|
||||||
220: '\\',
|
|
||||||
221: ']',
|
|
||||||
222: "'",
|
|
||||||
};
|
|
||||||
|
|
||||||
const SHIFT_MAP: CtrlKeyMap = {
|
|
||||||
'~': '`',
|
|
||||||
'!': '1',
|
|
||||||
'@': '2',
|
|
||||||
'#': '3',
|
|
||||||
$: '4',
|
|
||||||
'%': '5',
|
|
||||||
'^': '6',
|
|
||||||
'&': '7',
|
|
||||||
'*': '8',
|
|
||||||
'(': '9',
|
|
||||||
')': '0',
|
|
||||||
_: '-',
|
|
||||||
'+': '=',
|
|
||||||
':': ';',
|
|
||||||
'"': "'",
|
|
||||||
'<': ',',
|
|
||||||
'>': '.',
|
|
||||||
'?': '/',
|
|
||||||
'|': '\\',
|
|
||||||
};
|
|
||||||
|
|
||||||
const SPECIAL_ALIASES: CtrlKeyMap = {
|
|
||||||
option: 'alt',
|
|
||||||
command: 'meta',
|
|
||||||
return: 'enter',
|
|
||||||
escape: 'esc',
|
|
||||||
plus: '+',
|
|
||||||
mod: /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl',
|
|
||||||
};
|
|
||||||
|
|
||||||
let REVERSE_MAP: CtrlKeyMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* loop through the f keys, f1 to f19 and add them to the map
|
|
||||||
* programatically
|
|
||||||
*/
|
|
||||||
for (let i = 1; i < 20; ++i) {
|
|
||||||
MAP[111 + i] = 'f' + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* loop through to map numbers on the numeric keypad
|
|
||||||
*/
|
|
||||||
for (let i = 0; i <= 9; ++i) {
|
|
||||||
MAP[i + 96] = String(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* takes the event and returns the key character
|
|
||||||
*/
|
|
||||||
function characterFromEvent(e: KeyboardEvent): string {
|
|
||||||
const keyCode = e.keyCode || e.which;
|
|
||||||
// for keypress events we should return the character as is
|
|
||||||
if (e.type === 'keypress') {
|
|
||||||
let character = String.fromCharCode(keyCode);
|
|
||||||
// if the shift key is not pressed then it is safe to assume
|
|
||||||
// that we want the character to be lowercase. this means if
|
|
||||||
// you accidentally have caps lock on then your key bindings
|
|
||||||
// will continue to work
|
|
||||||
//
|
|
||||||
// the only side effect that might not be desired is if you
|
|
||||||
// bind something like 'A' cause you want to trigger an
|
|
||||||
// event when capital A is pressed caps lock will no longer
|
|
||||||
// trigger the event. shift+a will though.
|
|
||||||
if (!e.shiftKey) {
|
|
||||||
character = character.toLowerCase();
|
|
||||||
}
|
|
||||||
return character;
|
|
||||||
}
|
}
|
||||||
// for non keypress events the special maps are needed
|
e.preventDefault();
|
||||||
if (MAP[keyCode]) {
|
|
||||||
return MAP[keyCode];
|
const sel = doc.selection;
|
||||||
|
const topItems = sel.getTopNodes();
|
||||||
|
// TODO: check can remove
|
||||||
|
topItems.forEach(node => {
|
||||||
|
doc.removeNode(node);
|
||||||
|
});
|
||||||
|
sel.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
hotkey.bind('escape', (e: KeyboardEvent) => {
|
||||||
|
// const currentFocus = focusing.current;
|
||||||
|
const sel = focusing.focusDesigner?.currentDocument?.selection;
|
||||||
|
if (isFormEvent(e) || !sel) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (KEYCODE_MAP[keyCode]) {
|
e.preventDefault();
|
||||||
return KEYCODE_MAP[keyCode];
|
|
||||||
|
sel.clear();
|
||||||
|
// currentFocus.esc();
|
||||||
|
});
|
||||||
|
|
||||||
|
// command + c copy command + x cut
|
||||||
|
hotkey.bind(['command+c', 'ctrl+c', 'command+x', 'ctrl+x'], (e, action) => {
|
||||||
|
const doc = focusing.focusDesigner?.currentDocument;
|
||||||
|
if (isFormEvent(e) || !doc) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// if it is not in the special map
|
e.preventDefault();
|
||||||
// with keydown and keyup events the character seems to always
|
|
||||||
// come in as an uppercase character whether you are pressing shift
|
|
||||||
// or not. we should make sure it is always lowercase for comparisons
|
|
||||||
return String.fromCharCode(keyCode).toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface KeypressEvent extends KeyboardEvent {
|
/*
|
||||||
type: 'keypress';
|
const doc = getCurrentDocument();
|
||||||
}
|
if (isFormEvent(e) || !doc || !(focusing.id === 'outline' || focusing.id === 'canvas')) {
|
||||||
|
return;
|
||||||
function isPressEvent(e: KeyboardEvent | ActionEvent): e is KeypressEvent {
|
|
||||||
return e.type === 'keypress';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isFormEvent(e: KeyboardEvent) {
|
|
||||||
const t = e.target as HTMLFormElement;
|
|
||||||
if (!t) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
*/
|
||||||
|
|
||||||
if (t.form || /^(INPUT|SELECT|TEXTAREA)$/.test(t.tagName)) {
|
const selected = doc.selection.getTopNodes(true);
|
||||||
return true;
|
if (!selected || selected.length < 1) return;
|
||||||
|
|
||||||
|
const componentsMap = {};
|
||||||
|
const componentsTree = selected.map(item => item.export(false));
|
||||||
|
|
||||||
|
const data = { type: 'nodeSchema', componentsMap, componentsTree };
|
||||||
|
|
||||||
|
clipboard.setData(data);
|
||||||
|
/*
|
||||||
|
const cutMode = action.indexOf('x') > 0;
|
||||||
|
if (cutMode) {
|
||||||
|
const parentNode = selected.getParent();
|
||||||
|
parentNode.select();
|
||||||
|
selected.remove();
|
||||||
}
|
}
|
||||||
if (/write/.test(window.getComputedStyle(t).getPropertyValue('-webkit-user-modify'))) {
|
*/
|
||||||
return true;
|
});
|
||||||
|
|
||||||
|
// command + v paste
|
||||||
|
hotkey.bind(['command+v', 'ctrl+v'], (e) => {
|
||||||
|
const designer = focusing.focusDesigner;
|
||||||
|
const doc = designer?.currentDocument;
|
||||||
|
if (isFormEvent(e) || !designer || !doc) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return false;
|
clipboard.waitPasteData(e, ({ componentsTree }) => {
|
||||||
}
|
if (componentsTree) {
|
||||||
/**
|
const { target, index } = designer.getSuitableInsertion() || {};
|
||||||
* checks if two arrays are equal
|
if (!target) {
|
||||||
*/
|
return;
|
||||||
function modifiersMatch(modifiers1: string[], modifiers2: string[]): boolean {
|
|
||||||
return modifiers1.sort().join(',') === modifiers2.sort().join(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* takes a key event and figures out what the modifiers are
|
|
||||||
*/
|
|
||||||
function eventModifiers(e: KeyboardEvent): string[] {
|
|
||||||
const modifiers = [];
|
|
||||||
|
|
||||||
if (e.shiftKey) {
|
|
||||||
modifiers.push('shift');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.altKey) {
|
|
||||||
modifiers.push('alt');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.ctrlKey) {
|
|
||||||
modifiers.push('ctrl');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.metaKey) {
|
|
||||||
modifiers.push('meta');
|
|
||||||
}
|
|
||||||
|
|
||||||
return modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* determines if the keycode specified is a modifier key or not
|
|
||||||
*/
|
|
||||||
function isModifier(key: string): boolean {
|
|
||||||
return key === 'shift' || key === 'ctrl' || key === 'alt' || key === 'meta';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reverses the map lookup so that we can look for specific keys
|
|
||||||
* to see what can and can't use keypress
|
|
||||||
*
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
function getReverseMap(): CtrlKeyMap {
|
|
||||||
if (!REVERSE_MAP) {
|
|
||||||
REVERSE_MAP = {};
|
|
||||||
for (const key in MAP) {
|
|
||||||
// pull out the numeric keypad from here cause keypress should
|
|
||||||
// be able to detect the keys from the character
|
|
||||||
if (Number(key) > 95 && Number(key) < 112) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
const nodes = insertChildren(target, componentsTree, index);
|
||||||
if (MAP.hasOwnProperty(key)) {
|
if (nodes) {
|
||||||
REVERSE_MAP[MAP[key]] = key;
|
doc.selection.selectAll(nodes.map(o => o.id));
|
||||||
|
setTimeout(() => designer.activeTracker.track(nodes[0]), 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return REVERSE_MAP;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* picks the best action based on the key combination
|
|
||||||
*/
|
|
||||||
function pickBestAction(key: string, modifiers: string[], action?: string): string {
|
|
||||||
// if no action was picked in we should try to pick the one
|
|
||||||
// that we think would work best for this key
|
|
||||||
if (!action) {
|
|
||||||
action = getReverseMap()[key] ? 'keydown' : 'keypress';
|
|
||||||
}
|
|
||||||
// modifier keys don't work as expected with keypress,
|
|
||||||
// switch to keydown
|
|
||||||
if (action === 'keypress' && modifiers.length) {
|
|
||||||
action = 'keydown';
|
|
||||||
}
|
|
||||||
return action;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// command + z undo
|
||||||
* Converts from a string key combination to an array
|
hotkey.bind(['command+z', 'ctrl+z'], (e) => {
|
||||||
*
|
const his = focusing.focusDesigner?.currentHistory;
|
||||||
* @param {string} combination like "command+shift+l"
|
if (isFormEvent(e) || !his) {
|
||||||
* @return {Array}
|
return;
|
||||||
*/
|
|
||||||
function keysFromString(combination: string): string[] {
|
|
||||||
if (combination === '+') {
|
|
||||||
return ['+'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
combination = combination.replace(/\+{2}/g, '+plus');
|
e.preventDefault();
|
||||||
return combination.split('+');
|
his.back();
|
||||||
}
|
});
|
||||||
|
|
||||||
/**
|
// command + shift + z redo
|
||||||
* Gets info for a specific key combination
|
hotkey.bind(['command+y', 'ctrl+y', 'command+shift+z'], (e) => {
|
||||||
*
|
const his = focusing.focusDesigner?.currentHistory;
|
||||||
* @param combination key combination ("command+s" or "a" or "*")
|
if (isFormEvent(e) || !his) {
|
||||||
*/
|
return;
|
||||||
function getKeyInfo(combination: string, action?: string): KeyInfo {
|
|
||||||
let keys: string[] = [];
|
|
||||||
let key = '';
|
|
||||||
let i: number;
|
|
||||||
const modifiers: string[] = [];
|
|
||||||
|
|
||||||
// take the keys from this pattern and figure out what the actual
|
|
||||||
// pattern is all about
|
|
||||||
keys = keysFromString(combination);
|
|
||||||
|
|
||||||
for (i = 0; i < keys.length; ++i) {
|
|
||||||
key = keys[i];
|
|
||||||
|
|
||||||
// normalize key names
|
|
||||||
if (SPECIAL_ALIASES[key]) {
|
|
||||||
key = SPECIAL_ALIASES[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this is not a keypress event then we should
|
|
||||||
// be smart about using shift keys
|
|
||||||
// this will only work for US keyboards however
|
|
||||||
if (action && action !== 'keypress' && SHIFT_MAP[key]) {
|
|
||||||
key = SHIFT_MAP[key];
|
|
||||||
modifiers.push('shift');
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this key is a modifier then add it to the list of modifiers
|
|
||||||
if (isModifier(key)) {
|
|
||||||
modifiers.push(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
// depending on what the key combination is
|
his.forward();
|
||||||
// we will try to pick the best event for it
|
});
|
||||||
action = pickBestAction(key, modifiers, action);
|
|
||||||
|
|
||||||
return {
|
hotkey.mount(window);
|
||||||
key,
|
|
||||||
modifiers,
|
|
||||||
action,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* actually calls the callback function
|
|
||||||
*
|
|
||||||
* if your callback function returns false this will use the jquery
|
|
||||||
* convention - prevent default and stop propogation on the event
|
|
||||||
*/
|
|
||||||
function fireCallback(callback: HotkeyCallback, e: KeyboardEvent, combo?: string, sequence?: string): void {
|
|
||||||
if (callback(e, combo) === false) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Hotkey {
|
|
||||||
private callBacks: HotkeyCallbacks = {};
|
|
||||||
private directMap: HotkeyDirectMap = {};
|
|
||||||
private sequenceLevels: SequenceLevels = {};
|
|
||||||
private resetTimer = 0;
|
|
||||||
private ignoreNextKeyup: boolean | string = false;
|
|
||||||
private ignoreNextKeypress = false;
|
|
||||||
private nextExpectedAction: boolean | string = false;
|
|
||||||
|
|
||||||
mount(window: Window) {
|
|
||||||
const document = window.document;
|
|
||||||
const handleKeyEvent = this.handleKeyEvent.bind(this);
|
|
||||||
document.addEventListener('keypress', handleKeyEvent, false);
|
|
||||||
document.addEventListener('keydown', handleKeyEvent, false);
|
|
||||||
document.addEventListener('keyup', handleKeyEvent, false);
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener('keypress', handleKeyEvent, false);
|
|
||||||
document.removeEventListener('keydown', handleKeyEvent, false);
|
|
||||||
document.removeEventListener('keyup', handleKeyEvent, false);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(combos: string[] | string, callback: HotkeyCallback, action?: string): Hotkey {
|
|
||||||
this.bindMultiple(Array.isArray(combos) ? combos : [combos], callback, action);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* resets all sequence counters except for the ones passed in
|
|
||||||
*/
|
|
||||||
private resetSequences(doNotReset?: SequenceLevels): void {
|
|
||||||
// doNotReset = doNotReset || {};
|
|
||||||
let activeSequences = false;
|
|
||||||
let key = '';
|
|
||||||
for (key in this.sequenceLevels) {
|
|
||||||
if (doNotReset && doNotReset[key]) {
|
|
||||||
activeSequences = true;
|
|
||||||
} else {
|
|
||||||
this.sequenceLevels[key] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!activeSequences) {
|
|
||||||
this.nextExpectedAction = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* finds all callbacks that match based on the keycode, modifiers,
|
|
||||||
* and action
|
|
||||||
*/
|
|
||||||
private getMatches(
|
|
||||||
character: string,
|
|
||||||
modifiers: string[],
|
|
||||||
e: KeyboardEvent | ActionEvent,
|
|
||||||
sequenceName?: string,
|
|
||||||
combination?: string,
|
|
||||||
level?: number,
|
|
||||||
): HotkeyCallbackCfg[] {
|
|
||||||
let i: number;
|
|
||||||
let callback: HotkeyCallbackCfg;
|
|
||||||
const matches: HotkeyCallbackCfg[] = [];
|
|
||||||
const action: string = e.type;
|
|
||||||
|
|
||||||
// if there are no events related to this keycode
|
|
||||||
if (!this.callBacks[character]) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a modifier key is coming up on its own we should allow it
|
|
||||||
if (action === 'keyup' && isModifier(character)) {
|
|
||||||
modifiers = [character];
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop through all callbacks for the key that was pressed
|
|
||||||
// and see if any of them match
|
|
||||||
for (i = 0; i < this.callBacks[character].length; ++i) {
|
|
||||||
callback = this.callBacks[character][i];
|
|
||||||
|
|
||||||
// if a sequence name is not specified, but this is a sequence at
|
|
||||||
// the wrong level then move onto the next match
|
|
||||||
if (!sequenceName && callback.seq && this.sequenceLevels[callback.seq] !== callback.level) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the action we are looking for doesn't match the action we got
|
|
||||||
// then we should keep going
|
|
||||||
if (action !== callback.action) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this is a keypress event and the meta key and control key
|
|
||||||
// are not pressed that means that we need to only look at the
|
|
||||||
// character, otherwise check the modifiers as well
|
|
||||||
//
|
|
||||||
// chrome will not fire a keypress if meta or control is down
|
|
||||||
// safari will fire a keypress if meta or meta+shift is down
|
|
||||||
// firefox will fire a keypress if meta or control is down
|
|
||||||
if ((isPressEvent(e) && !e.metaKey && !e.ctrlKey) || modifiersMatch(modifiers, callback.modifiers)) {
|
|
||||||
const deleteCombo = !sequenceName && callback.combo === combination;
|
|
||||||
const deleteSequence = sequenceName && callback.seq === sequenceName && callback.level === level;
|
|
||||||
if (deleteCombo || deleteSequence) {
|
|
||||||
this.callBacks[character].splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
matches.push(callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleKey(character: string, modifiers: string[], e: KeyboardEvent): void {
|
|
||||||
const callbacks: HotkeyCallbackCfg[] = this.getMatches(character, modifiers, e);
|
|
||||||
let i: number;
|
|
||||||
const doNotReset: SequenceLevels = {};
|
|
||||||
let maxLevel = 0;
|
|
||||||
let processedSequenceCallback = false;
|
|
||||||
|
|
||||||
// Calculate the maxLevel for sequences so we can only execute the longest callback sequence
|
|
||||||
for (i = 0; i < callbacks.length; ++i) {
|
|
||||||
if (callbacks[i].seq) {
|
|
||||||
maxLevel = Math.max(maxLevel, callbacks[i].level || 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop through matching callbacks for this key event
|
|
||||||
for (i = 0; i < callbacks.length; ++i) {
|
|
||||||
// fire for all sequence callbacks
|
|
||||||
// this is because if for example you have multiple sequences
|
|
||||||
// bound such as "g i" and "g t" they both need to fire the
|
|
||||||
// callback for matching g cause otherwise you can only ever
|
|
||||||
// match the first one
|
|
||||||
if (callbacks[i].seq) {
|
|
||||||
// only fire callbacks for the maxLevel to prevent
|
|
||||||
// subsequences from also firing
|
|
||||||
//
|
|
||||||
// for example 'a option b' should not cause 'option b' to fire
|
|
||||||
// even though 'option b' is part of the other sequence
|
|
||||||
//
|
|
||||||
// any sequences that do not match here will be discarded
|
|
||||||
// below by the resetSequences call
|
|
||||||
if (callbacks[i].level !== maxLevel) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
processedSequenceCallback = true;
|
|
||||||
|
|
||||||
// keep a list of which sequences were matches for later
|
|
||||||
doNotReset[callbacks[i].seq || ''] = 1;
|
|
||||||
fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there were no sequence matches but we are still here
|
|
||||||
// that means this is a regular match so we should fire that
|
|
||||||
if (!processedSequenceCallback) {
|
|
||||||
fireCallback(callbacks[i].callback, e, callbacks[i].combo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ignoreThisKeypress = e.type === 'keypress' && this.ignoreNextKeypress;
|
|
||||||
if (e.type === this.nextExpectedAction && !isModifier(character) && !ignoreThisKeypress) {
|
|
||||||
this.resetSequences(doNotReset);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ignoreNextKeypress = processedSequenceCallback && e.type === 'keydown';
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleKeyEvent(e: KeyboardEvent): void {
|
|
||||||
const character = characterFromEvent(e);
|
|
||||||
|
|
||||||
// no character found then stop
|
|
||||||
if (!character) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to use === for the character check because the character can be 0
|
|
||||||
if (e.type === 'keyup' && this.ignoreNextKeyup === character) {
|
|
||||||
this.ignoreNextKeyup = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.handleKey(character, eventModifiers(e), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private resetSequenceTimer(): void {
|
|
||||||
if (this.resetTimer) {
|
|
||||||
clearTimeout(this.resetTimer);
|
|
||||||
}
|
|
||||||
this.resetTimer = window.setTimeout(this.resetSequences, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bindSequence(combo: string, keys: string[], callback: HotkeyCallback, action?: string): void {
|
|
||||||
// const self: any = this;
|
|
||||||
this.sequenceLevels[combo] = 0;
|
|
||||||
const increaseSequence = (nextAction: string) => {
|
|
||||||
return () => {
|
|
||||||
this.nextExpectedAction = nextAction;
|
|
||||||
++this.sequenceLevels[combo];
|
|
||||||
this.resetSequenceTimer();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
const callbackAndReset = (e: KeyboardEvent): void => {
|
|
||||||
fireCallback(callback, e, combo);
|
|
||||||
|
|
||||||
if (action !== 'keyup') {
|
|
||||||
this.ignoreNextKeyup = characterFromEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(this.resetSequences, 10);
|
|
||||||
};
|
|
||||||
for (let i = 0; i < keys.length; ++i) {
|
|
||||||
const isFinal = i + 1 === keys.length;
|
|
||||||
const wrappedCallback = isFinal ? callbackAndReset : increaseSequence(action || getKeyInfo(keys[i + 1]).action);
|
|
||||||
this.bindSingle(keys[i], wrappedCallback, action, combo, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bindSingle(
|
|
||||||
combination: string,
|
|
||||||
callback: HotkeyCallback,
|
|
||||||
action?: string,
|
|
||||||
sequenceName?: string,
|
|
||||||
level?: number,
|
|
||||||
): void {
|
|
||||||
// store a direct mapped reference for use with HotKey.trigger
|
|
||||||
this.directMap[`${combination}:${action}`] = callback;
|
|
||||||
|
|
||||||
// make sure multiple spaces in a row become a single space
|
|
||||||
combination = combination.replace(/\s+/g, ' ');
|
|
||||||
|
|
||||||
const sequence: string[] = combination.split(' ');
|
|
||||||
let info: KeyInfo;
|
|
||||||
|
|
||||||
// if this pattern is a sequence of keys then run through this method
|
|
||||||
// to reprocess each pattern one key at a time
|
|
||||||
if (sequence.length > 1) {
|
|
||||||
this.bindSequence(combination, sequence, callback, action);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
info = getKeyInfo(combination, action);
|
|
||||||
|
|
||||||
// make sure to initialize array if this is the first time
|
|
||||||
// a callback is added for this key
|
|
||||||
this.callBacks[info.key] = this.callBacks[info.key] || [];
|
|
||||||
|
|
||||||
// remove an existing match if there is one
|
|
||||||
this.getMatches(info.key, info.modifiers, { type: info.action }, sequenceName, combination, level);
|
|
||||||
|
|
||||||
// add this call back to the array
|
|
||||||
// if it is a sequence put it at the beginning
|
|
||||||
// if not put it at the end
|
|
||||||
//
|
|
||||||
// this is important because the way these are processed expects
|
|
||||||
// the sequence ones to come first
|
|
||||||
this.callBacks[info.key][sequenceName ? 'unshift' : 'push']({
|
|
||||||
callback,
|
|
||||||
modifiers: info.modifiers,
|
|
||||||
action: info.action,
|
|
||||||
seq: sequenceName,
|
|
||||||
level,
|
|
||||||
combo: combination,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private bindMultiple(combinations: string[], callback: HotkeyCallback, action?: string) {
|
|
||||||
for (const item of combinations) {
|
|
||||||
this.bindSingle(item, callback, action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -86,7 +86,7 @@ export function isChildInline(child: Element | Text, win?: Window) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const style = (win || getWindow(child)).getComputedStyle(child);
|
const style = (win || getWindow(child)).getComputedStyle(child);
|
||||||
return /^inline/.test(style.getPropertyValue('display'));
|
return /^inline/.test(style.getPropertyValue('display')) || /^(left|right)$/.test(style.getPropertyValue('float'));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRectTarget(rect: Rect | null) {
|
export function getRectTarget(rect: Rect | null) {
|
||||||
|
|||||||
@ -59,6 +59,7 @@ export class DocumentModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _modalNode?: NodeParent;
|
private _modalNode?: NodeParent;
|
||||||
|
private _blank?: boolean;
|
||||||
get modalNode() {
|
get modalNode() {
|
||||||
return this._modalNode;
|
return this._modalNode;
|
||||||
}
|
}
|
||||||
@ -67,7 +68,7 @@ export class DocumentModel {
|
|||||||
return this.modalNode || this.rootNode;
|
return this.modalNode || this.rootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(readonly project: Project, schema: RootSchema) {
|
constructor(readonly project: Project, schema?: RootSchema) {
|
||||||
autorun(() => {
|
autorun(() => {
|
||||||
this.nodes.forEach((item) => {
|
this.nodes.forEach((item) => {
|
||||||
if (item.parent == null && item !== this.rootNode) {
|
if (item.parent == null && item !== this.rootNode) {
|
||||||
@ -75,7 +76,16 @@ export class DocumentModel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, true);
|
}, true);
|
||||||
this.rootNode = this.createRootNode(schema);
|
|
||||||
|
if (!schema) {
|
||||||
|
this._blank = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rootNode = this.createRootNode(schema || {
|
||||||
|
componentName: 'Page',
|
||||||
|
fileName: ''
|
||||||
|
});
|
||||||
|
|
||||||
this.history = new History(
|
this.history = new History(
|
||||||
() => this.schema,
|
() => this.schema,
|
||||||
(schema) => this.import(schema as RootSchema, true),
|
(schema) => this.import(schema as RootSchema, true),
|
||||||
@ -83,6 +93,10 @@ export class DocumentModel {
|
|||||||
this.setupListenActiveNodes();
|
this.setupListenActiveNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed isBlank() {
|
||||||
|
return this._blank && !this.isModified();
|
||||||
|
}
|
||||||
|
|
||||||
readonly designer = this.project.designer;
|
readonly designer = this.project.designer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,6 +309,7 @@ export class DocumentModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private mountSimulator(simulator: ISimulatorHost) {
|
private mountSimulator(simulator: ISimulatorHost) {
|
||||||
|
// TODO: 多设备 simulator 支持
|
||||||
this._simulator = simulator;
|
this._simulator = simulator;
|
||||||
// TODO: emit simulator mounted
|
// TODO: emit simulator mounted
|
||||||
}
|
}
|
||||||
@ -386,7 +401,8 @@ export class DocumentModel {
|
|||||||
* 从项目中移除
|
* 从项目中移除
|
||||||
*/
|
*/
|
||||||
remove() {
|
remove() {
|
||||||
// todo:
|
// this.project.removeDocument(this);
|
||||||
|
// todo: ...
|
||||||
}
|
}
|
||||||
|
|
||||||
purge() {
|
purge() {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { IconBase, IconProps } from "./icon-base";
|
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||||
|
|
||||||
export function IconClone(props: IconProps) {
|
export function IconClone(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconBase viewBox="0 0 1024 1024" {...props}>
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
<path d="M192 256.16C192 220.736 220.704 192 256.16 192h639.68C931.264 192 960 220.704 960 256.16v639.68A64.16 64.16 0 0 1 895.84 960H256.16A64.16 64.16 0 0 1 192 895.84V256.16z m64 31.584v576.512a32 32 0 0 0 31.744 31.744h576.512a32 32 0 0 0 31.744-31.744V287.744A32 32 0 0 0 864.256 256H287.744A32 32 0 0 0 256 287.744zM288 192v64h64V192H288z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m96 96v64h64V288h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m-96 96v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64H288z m-96-96v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64V288H192z m160 416c0-17.664 14.592-32 32.064-32h319.872a31.968 31.968 0 1 1 0 64h-319.872A31.968 31.968 0 0 1 352 704z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 576z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 448z m512 47.936V192h-64V159.968A31.776 31.776 0 0 0 768.032 128H160A31.776 31.776 0 0 0 128 159.968V768c0 17.92 14.304 31.968 31.968 31.968H192v64h303.936H128.128A63.968 63.968 0 0 1 64 799.872V128.128C64 92.704 92.48 64 128.128 64h671.744C835.296 64 864 92.48 864 128.128v367.808z"/>
|
<path d="M192 256.16C192 220.736 220.704 192 256.16 192h639.68C931.264 192 960 220.704 960 256.16v639.68A64.16 64.16 0 0 1 895.84 960H256.16A64.16 64.16 0 0 1 192 895.84V256.16z m64 31.584v576.512a32 32 0 0 0 31.744 31.744h576.512a32 32 0 0 0 31.744-31.744V287.744A32 32 0 0 0 864.256 256H287.744A32 32 0 0 0 256 287.744zM288 192v64h64V192H288z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m96 96v64h64V288h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m-96 96v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64H288z m-96-96v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64V288H192z m160 416c0-17.664 14.592-32 32.064-32h319.872a31.968 31.968 0 1 1 0 64h-319.872A31.968 31.968 0 0 1 352 704z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 576z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 448z m512 47.936V192h-64V159.968A31.776 31.776 0 0 0 768.032 128H160A31.776 31.776 0 0 0 128 159.968V768c0 17.92 14.304 31.968 31.968 31.968H192v64h303.936H128.128A63.968 63.968 0 0 1 64 799.872V128.128C64 92.704 92.48 64 128.128 64h671.744C835.296 64 864 92.48 864 128.128v367.808z"/>
|
||||||
</IconBase>
|
</SVGIcon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { IconBase, IconProps } from "./icon-base";
|
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||||
|
|
||||||
export function IconComponent(props: IconProps) {
|
export function IconComponent(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconBase viewBox="0 0 1024 1024" {...props}>
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
<path d="M783.5648 437.4528h-18.0224V336.6912c0-43.8272-35.6352-79.4624-79.4624-79.4624h-110.592V241.664c0-90.9312-73.728-164.6592-164.6592-164.6592-90.9312 0-164.6592 73.728-164.6592 164.6592v15.5648H155.2384c-43.8272 0-79.4624 35.6352-79.4624 79.4624v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h56.1152c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192H106.496c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 43.8272 35.6352 79.4624 79.4624 79.4624h531.2512c43.8272 0 79.4624-35.6352 79.4624-79.4624v-100.7616h18.0224c90.9312 0 164.6592-73.728 164.6592-164.6592-0.4096-90.9312-74.1376-164.6592-165.0688-164.6592z m0 267.8784h-48.7424c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 9.8304-8.192 18.0224-18.0224 18.0224H155.2384c-9.8304 0-18.0224-8.192-18.0224-18.0224v-100.7616h25.3952c90.9312 0 164.6592-73.728 164.6592-164.6592 0-90.9312-73.728-164.6592-164.6592-164.6592h-25.3952V336.6912c0-9.8304 8.192-18.0224 18.0224-18.0224h121.6512c16.7936 0 30.72-13.9264 30.72-30.72V241.664c0-56.9344 46.2848-103.2192 103.2192-103.2192s103.2192 46.2848 103.2192 103.2192v46.2848c0 16.7936 13.9264 30.72 30.72 30.72h141.312c9.8304 0 18.0224 8.192 18.0224 18.0224v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h48.7424c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192z" />
|
<path d="M783.5648 437.4528h-18.0224V336.6912c0-43.8272-35.6352-79.4624-79.4624-79.4624h-110.592V241.664c0-90.9312-73.728-164.6592-164.6592-164.6592-90.9312 0-164.6592 73.728-164.6592 164.6592v15.5648H155.2384c-43.8272 0-79.4624 35.6352-79.4624 79.4624v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h56.1152c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192H106.496c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 43.8272 35.6352 79.4624 79.4624 79.4624h531.2512c43.8272 0 79.4624-35.6352 79.4624-79.4624v-100.7616h18.0224c90.9312 0 164.6592-73.728 164.6592-164.6592-0.4096-90.9312-74.1376-164.6592-165.0688-164.6592z m0 267.8784h-48.7424c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 9.8304-8.192 18.0224-18.0224 18.0224H155.2384c-9.8304 0-18.0224-8.192-18.0224-18.0224v-100.7616h25.3952c90.9312 0 164.6592-73.728 164.6592-164.6592 0-90.9312-73.728-164.6592-164.6592-164.6592h-25.3952V336.6912c0-9.8304 8.192-18.0224 18.0224-18.0224h121.6512c16.7936 0 30.72-13.9264 30.72-30.72V241.664c0-56.9344 46.2848-103.2192 103.2192-103.2192s103.2192 46.2848 103.2192 103.2192v46.2848c0 16.7936 13.9264 30.72 30.72 30.72h141.312c9.8304 0 18.0224 8.192 18.0224 18.0224v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h48.7424c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192z" />
|
||||||
</IconBase>
|
</SVGIcon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
IconComponent.displayName = 'Component';
|
IconComponent.displayName = 'Component';
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import { IconBase, IconProps } from "./icon-base";
|
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||||
|
|
||||||
export function IconContainer(props: IconProps) {
|
export function IconContainer(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconBase viewBox="0 0 1024 1024" {...props}>
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
<path d="M800 800h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-256 0h64v64h-64v-64z m0-640h64v64h-64v-64z m128 640h64v64h-64v-64zM160 672h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m640 384h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z" />
|
<path d="M800 800h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-256 0h64v64h-64v-64z m0-640h64v64h-64v-64z m128 640h64v64h-64v-64zM160 672h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m640 384h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z" />
|
||||||
<path d="M896 64H128c-35.2 0-64 28.8-64 64v768c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V128c0-35.2-28.8-64-64-64z m0 800c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V160c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v704z" />
|
<path d="M896 64H128c-35.2 0-64 28.8-64 64v768c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V128c0-35.2-28.8-64-64-64z m0 800c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V160c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v704z" />
|
||||||
</IconBase>
|
</SVGIcon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
IconContainer.displayName = 'Container';
|
IconContainer.displayName = 'Container';
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { IconBase, IconProps } from "./icon-base";
|
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||||
|
|
||||||
export function IconHidden(props: IconProps) {
|
export function IconHidden(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconBase viewBox="0 0 1024 1024" {...props}>
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
<path d="M183.423543 657.078213l163.499771-98.484012c-4.233418-14.908548-6.646374-30.585599-6.646374-46.852074 0-94.665033 76.739778-171.404812 171.404812-171.404812 45.983287 0 87.641059 18.20871 118.42518 47.679929l129.791042-78.17957c-73.254398-41.73145-157.866471-65.812915-248.216221-65.812915-192.742792 0-360.068705 108.505249-444.453604 267.715321C96.636944 567.228859 136.301316 616.355743 183.423543 657.078213zM841.253886 367.552144l-164.382884 99.015108c3.934612 14.415314 6.215562 29.513174 6.215562 45.174875 0 94.665033-76.739778 171.404812-171.404812 171.404812-45.361117 0-86.484723-17.747199-117.142977-46.515407l-129.419582 77.955466c72.874751 41.149189 156.893306 64.871473 246.563582 64.871473 192.742792 0 360.068705-108.505249 444.453604-267.717368C927.000805 456.773188 887.794875 408.054603 841.253886 367.552144zM420.280042 511.741104c0 0.550539 0.152473 1.060145 0.161682 1.608637l135.080511-81.366146c-13.065574-7.198959-27.854395-11.658528-43.826158-11.658528C461.20922 420.325068 420.280042 461.254246 420.280042 511.741104zM447.739441 576.947198l69.02098-41.574884L948.364369 275.395234c10.812253-6.512321 14.297634-20.558222 7.785314-31.369452-6.512321-10.812253-20.556175-14.296611-31.368428-7.785314L575.654762 446.537056l0 0-151.20577 91.078345 0 0L75.027787 748.090043c-10.812253 6.512321-14.297634 20.556175-7.785314 31.368428 6.512321 10.812253 20.556175 14.297634 31.369452 7.785314L447.739441 576.947198 447.739441 576.947198zM511.696078 603.157139c50.487881 0 91.416036-40.928155 91.416036-91.416036 0-0.549515-0.152473-1.057075-0.161682-1.605567l-135.079488 81.364099C480.935494 598.699618 495.724315 603.157139 511.696078 603.157139z" />
|
<path d="M183.423543 657.078213l163.499771-98.484012c-4.233418-14.908548-6.646374-30.585599-6.646374-46.852074 0-94.665033 76.739778-171.404812 171.404812-171.404812 45.983287 0 87.641059 18.20871 118.42518 47.679929l129.791042-78.17957c-73.254398-41.73145-157.866471-65.812915-248.216221-65.812915-192.742792 0-360.068705 108.505249-444.453604 267.715321C96.636944 567.228859 136.301316 616.355743 183.423543 657.078213zM841.253886 367.552144l-164.382884 99.015108c3.934612 14.415314 6.215562 29.513174 6.215562 45.174875 0 94.665033-76.739778 171.404812-171.404812 171.404812-45.361117 0-86.484723-17.747199-117.142977-46.515407l-129.419582 77.955466c72.874751 41.149189 156.893306 64.871473 246.563582 64.871473 192.742792 0 360.068705-108.505249 444.453604-267.717368C927.000805 456.773188 887.794875 408.054603 841.253886 367.552144zM420.280042 511.741104c0 0.550539 0.152473 1.060145 0.161682 1.608637l135.080511-81.366146c-13.065574-7.198959-27.854395-11.658528-43.826158-11.658528C461.20922 420.325068 420.280042 461.254246 420.280042 511.741104zM447.739441 576.947198l69.02098-41.574884L948.364369 275.395234c10.812253-6.512321 14.297634-20.558222 7.785314-31.369452-6.512321-10.812253-20.556175-14.296611-31.368428-7.785314L575.654762 446.537056l0 0-151.20577 91.078345 0 0L75.027787 748.090043c-10.812253 6.512321-14.297634 20.556175-7.785314 31.368428 6.512321 10.812253 20.556175 14.297634 31.369452 7.785314L447.739441 576.947198 447.739441 576.947198zM511.696078 603.157139c50.487881 0 91.416036-40.928155 91.416036-91.416036 0-0.549515-0.152473-1.057075-0.161682-1.605567l-135.079488 81.364099C480.935494 598.699618 495.724315 603.157139 511.696078 603.157139z" />
|
||||||
</IconBase>
|
</SVGIcon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
IconHidden.displayName = 'Hidden';
|
IconHidden.displayName = 'Hidden';
|
||||||
@ -1,12 +1,12 @@
|
|||||||
import { IconBase, IconProps } from "./icon-base";
|
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||||
|
|
||||||
export function IconPage(props: IconProps) {
|
export function IconPage(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconBase viewBox="0 0 1024 1024" {...props}>
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
<path d="M381.6 864H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0.1-5.7-5.5-10.3-12.3-10.3zM382 780.6H162c-6.9 0-12.5 4.6-12.5 10.3v19.3c0 5.7 5.6 10.3 12.5 10.3h220c6.9 0 12.5-4.6 12.5-10.3v-19.3c0-5.7-5.6-10.3-12.5-10.3zM162.4 737.2h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0-5.7-5.6-10.3-12.4-10.3H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3z" />
|
<path d="M381.6 864H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0.1-5.7-5.5-10.3-12.3-10.3zM382 780.6H162c-6.9 0-12.5 4.6-12.5 10.3v19.3c0 5.7 5.6 10.3 12.5 10.3h220c6.9 0 12.5-4.6 12.5-10.3v-19.3c0-5.7-5.6-10.3-12.5-10.3zM162.4 737.2h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0-5.7-5.6-10.3-12.4-10.3H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3z" />
|
||||||
<path d="M977.1 0H46.9C21 0 0 21 0 46.9v930.2c0 25.9 21 46.9 46.9 46.9h930.2c25.9 0 46.9-21 46.9-46.9V46.9C1024 21 1003 0 977.1 0z m-18.7 911.6c0 25.9-21 46.9-46.9 46.9H112.4c-25.9 0-46.9-21-46.9-47V112.4c0-25.9 21-46.9 46.9-46.9h799.1c25.9 0 46.9 21 46.9 46.9v799.2z" />
|
<path d="M977.1 0H46.9C21 0 0 21 0 46.9v930.2c0 25.9 21 46.9 46.9 46.9h930.2c25.9 0 46.9-21 46.9-46.9V46.9C1024 21 1003 0 977.1 0z m-18.7 911.6c0 25.9-21 46.9-46.9 46.9H112.4c-25.9 0-46.9-21-46.9-47V112.4c0-25.9 21-46.9 46.9-46.9h799.1c25.9 0 46.9 21 46.9 46.9v799.2z" />
|
||||||
<path d="M207.9 342.7h608.2c32 0 57.9-25.9 57.9-57.9v-83c0-32-25.9-57.9-57.9-57.9H207.9c-32 0-57.9 25.9-57.9 57.9v83c0 32 25.9 57.9 57.9 57.9zM200 201.8c0-4.4 3.5-7.9 7.9-7.9h608.2c4.4 0 7.9 3.5 7.9 7.9v83c0 4.4-3.5 7.9-7.9 7.9H207.9c-4.4 0-7.9-3.5-7.9-7.9v-83zM806.4 405.7h-277c-37.3 0-67.6 30.2-67.6 67.6v363.2c0 37.3 30.2 67.6 67.6 67.6h277c37.3 0 67.6-30.2 67.6-67.6V473.3c0-37.4-30.2-67.6-67.6-67.6zM824 836.4c0 9.7-7.9 17.6-17.6 17.6h-277c-9.7 0-17.6-7.9-17.6-17.6V473.3c0-9.7 7.9-17.6 17.6-17.6h277c9.7 0 17.6 7.9 17.6 17.6v363.1zM272 649.7c67.4 0 122-54.6 122-122s-54.6-122-122-122-122 54.6-122 122 54.6 122 122 122z m0-204c45.2 0 82 36.8 82 82s-36.8 82-82 82-82-36.8-82-82 36.8-82 82-82z" />
|
<path d="M207.9 342.7h608.2c32 0 57.9-25.9 57.9-57.9v-83c0-32-25.9-57.9-57.9-57.9H207.9c-32 0-57.9 25.9-57.9 57.9v83c0 32 25.9 57.9 57.9 57.9zM200 201.8c0-4.4 3.5-7.9 7.9-7.9h608.2c4.4 0 7.9 3.5 7.9 7.9v83c0 4.4-3.5 7.9-7.9 7.9H207.9c-4.4 0-7.9-3.5-7.9-7.9v-83zM806.4 405.7h-277c-37.3 0-67.6 30.2-67.6 67.6v363.2c0 37.3 30.2 67.6 67.6 67.6h277c37.3 0 67.6-30.2 67.6-67.6V473.3c0-37.4-30.2-67.6-67.6-67.6zM824 836.4c0 9.7-7.9 17.6-17.6 17.6h-277c-9.7 0-17.6-7.9-17.6-17.6V473.3c0-9.7 7.9-17.6 17.6-17.6h277c9.7 0 17.6 7.9 17.6 17.6v363.1zM272 649.7c67.4 0 122-54.6 122-122s-54.6-122-122-122-122 54.6-122 122 54.6 122 122 122z m0-204c45.2 0 82 36.8 82 82s-36.8 82-82 82-82-36.8-82-82 36.8-82 82-82z" />
|
||||||
</IconBase>
|
</SVGIcon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
IconPage.displayName = 'Page';
|
IconPage.displayName = 'Page';
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { IconBase, IconProps } from './icon-base';
|
import { SVGIcon, IconProps } from '@ali/lowcode-globals';
|
||||||
|
|
||||||
export function IconRemove(props: IconProps) {
|
export function IconRemove(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconBase viewBox="0 0 1024 1024" {...props}>
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
<path d="M224 256v639.84A64 64 0 0 0 287.84 960h448.32A64 64 0 0 0 800 895.84V256h64a32 32 0 1 0 0-64H160a32 32 0 1 0 0 64h64zM384 96c0-17.664 14.496-32 31.904-32h192.192C625.696 64 640 78.208 640 96c0 17.664-14.496 32-31.904 32H415.904A31.872 31.872 0 0 1 384 96z m-96 191.744C288 270.208 302.4 256 320.224 256h383.552C721.6 256 736 270.56 736 287.744v576.512C736 881.792 721.6 896 703.776 896H320.224A32.224 32.224 0 0 1 288 864.256V287.744zM352 352c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z" />
|
<path d="M224 256v639.84A64 64 0 0 0 287.84 960h448.32A64 64 0 0 0 800 895.84V256h64a32 32 0 1 0 0-64H160a32 32 0 1 0 0 64h64zM384 96c0-17.664 14.496-32 31.904-32h192.192C625.696 64 640 78.208 640 96c0 17.664-14.496 32-31.904 32H415.904A31.872 31.872 0 0 1 384 96z m-96 191.744C288 270.208 302.4 256 320.224 256h383.552C721.6 256 736 270.56 736 287.744v576.512C736 881.792 721.6 896 703.776 896H320.224A32.224 32.224 0 0 1 288 864.256V287.744zM352 352c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z" />
|
||||||
</IconBase>
|
</SVGIcon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
IconRemove.displayName = 'Remove';
|
IconRemove.displayName = 'Remove';
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import { IconBase, IconProps } from './icon-base';
|
import { SVGIcon, IconProps } from '@ali/lowcode-globals';
|
||||||
|
|
||||||
export function IconSetting(props: IconProps) {
|
export function IconSetting(props: IconProps) {
|
||||||
return (
|
return (
|
||||||
<IconBase viewBox="0 0 1024 1024" {...props}>
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
<path d="M965.824 405.952a180.48 180.48 0 0 1-117.12-85.376 174.464 174.464 0 0 1-16-142.08 22.208 22.208 0 0 0-7.04-23.552 480.576 480.576 0 0 0-153.6-89.216 23.104 23.104 0 0 0-24.32 5.76 182.208 182.208 0 0 1-135.68 57.92 182.208 182.208 0 0 1-133.12-56.64 23.104 23.104 0 0 0-26.88-7.04 478.656 478.656 0 0 0-153.6 89.856 22.208 22.208 0 0 0-7.04 23.552 174.464 174.464 0 0 1-16 141.44A180.48 180.48 0 0 1 58.24 405.952a22.4 22.4 0 0 0-17.28 17.792 455.08 455.08 0 0 0 0 176.512 22.4 22.4 0 0 0 17.28 17.792 180.48 180.48 0 0 1 117.12 84.736c25.408 42.944 31.232 94.592 16 142.08a22.208 22.208 0 0 0 7.04 23.552A480.576 480.576 0 0 0 352 957.632h7.68a23.04 23.04 0 0 0 16.64-7.04 184.128 184.128 0 0 1 266.944 0c6.592 8.96 18.752 11.968 28.8 7.04a479.36 479.36 0 0 0 156.16-88.576 22.208 22.208 0 0 0 7.04-23.552 174.464 174.464 0 0 1 13.44-142.72 180.48 180.48 0 0 1 117.12-84.736 22.4 22.4 0 0 0 17.28-17.792 452.613 452.613 0 0 0 0-176.512 23.04 23.04 0 0 0-17.28-17.792z m-42.88 169.408a218.752 218.752 0 0 0-128 98.112 211.904 211.904 0 0 0-21.76 156.736 415.936 415.936 0 0 1-112 63.68 217.472 217.472 0 0 0-149.12-63.68 221.312 221.312 0 0 0-149.12 63.68 414.592 414.592 0 0 1-112-63.68c12.8-53.12 4.288-109.12-23.68-156.096A218.752 218.752 0 0 0 101.12 575.36a386.176 386.176 0 0 1 0-127.36 218.752 218.752 0 0 0 128-98.112c27.2-47.552 34.944-103.68 21.76-156.8a415.296 415.296 0 0 1 112-63.68A221.44 221.44 0 0 0 512 187.392a218.24 218.24 0 0 0 149.12-57.984 413.952 413.952 0 0 1 112 63.744 211.904 211.904 0 0 0 23.04 156.096 218.752 218.752 0 0 0 128 98.112 386.65 386.65 0 0 1 0 127.36l-1.28 0.64z" />
|
<path d="M965.824 405.952a180.48 180.48 0 0 1-117.12-85.376 174.464 174.464 0 0 1-16-142.08 22.208 22.208 0 0 0-7.04-23.552 480.576 480.576 0 0 0-153.6-89.216 23.104 23.104 0 0 0-24.32 5.76 182.208 182.208 0 0 1-135.68 57.92 182.208 182.208 0 0 1-133.12-56.64 23.104 23.104 0 0 0-26.88-7.04 478.656 478.656 0 0 0-153.6 89.856 22.208 22.208 0 0 0-7.04 23.552 174.464 174.464 0 0 1-16 141.44A180.48 180.48 0 0 1 58.24 405.952a22.4 22.4 0 0 0-17.28 17.792 455.08 455.08 0 0 0 0 176.512 22.4 22.4 0 0 0 17.28 17.792 180.48 180.48 0 0 1 117.12 84.736c25.408 42.944 31.232 94.592 16 142.08a22.208 22.208 0 0 0 7.04 23.552A480.576 480.576 0 0 0 352 957.632h7.68a23.04 23.04 0 0 0 16.64-7.04 184.128 184.128 0 0 1 266.944 0c6.592 8.96 18.752 11.968 28.8 7.04a479.36 479.36 0 0 0 156.16-88.576 22.208 22.208 0 0 0 7.04-23.552 174.464 174.464 0 0 1 13.44-142.72 180.48 180.48 0 0 1 117.12-84.736 22.4 22.4 0 0 0 17.28-17.792 452.613 452.613 0 0 0 0-176.512 23.04 23.04 0 0 0-17.28-17.792z m-42.88 169.408a218.752 218.752 0 0 0-128 98.112 211.904 211.904 0 0 0-21.76 156.736 415.936 415.936 0 0 1-112 63.68 217.472 217.472 0 0 0-149.12-63.68 221.312 221.312 0 0 0-149.12 63.68 414.592 414.592 0 0 1-112-63.68c12.8-53.12 4.288-109.12-23.68-156.096A218.752 218.752 0 0 0 101.12 575.36a386.176 386.176 0 0 1 0-127.36 218.752 218.752 0 0 0 128-98.112c27.2-47.552 34.944-103.68 21.76-156.8a415.296 415.296 0 0 1 112-63.68A221.44 221.44 0 0 0 512 187.392a218.24 218.24 0 0 0 149.12-57.984 413.952 413.952 0 0 1 112 63.744 211.904 211.904 0 0 0 23.04 156.096 218.752 218.752 0 0 0 128 98.112 386.65 386.65 0 0 1 0 127.36l-1.28 0.64z" />
|
||||||
<path d="M512 320.576c-105.984 0-192 85.568-192 191.104a191.552 191.552 0 0 0 192 191.104c106.112 0 192.064-85.568 192.064-191.104a190.72 190.72 0 0 0-56.256-135.168 192.448 192.448 0 0 0-135.744-55.936z m0 318.528c-70.656 0-128-57.088-128-127.424 0-70.4 57.344-127.36 128-127.36 70.72 0 128 56.96 128 127.36 0 33.792-13.44 66.176-37.44 90.112a128.32 128.32 0 0 1-90.496 37.312z" />
|
<path d="M512 320.576c-105.984 0-192 85.568-192 191.104a191.552 191.552 0 0 0 192 191.104c106.112 0 192.064-85.568 192.064-191.104a190.72 190.72 0 0 0-56.256-135.168 192.448 192.448 0 0 0-135.744-55.936z m0 318.528c-70.656 0-128-57.088-128-127.424 0-70.4 57.344-127.36 128-127.36 70.72 0 128 56.96 128 127.36 0 33.792-13.44 66.176-37.44 90.112a128.32 128.32 0 0 1-90.496 37.312z" />
|
||||||
</IconBase>
|
</SVGIcon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
"Condition Group": "Condition Group"
|
"Condition Group": "Condition Group",
|
||||||
|
"No opened document": "No opened document, open some document to editing"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"copy": "复制",
|
"copy": "复制",
|
||||||
"remove": "删除",
|
"remove": "删除",
|
||||||
"Condition Group": "条件组"
|
"Condition Group": "条件组",
|
||||||
|
"No opened document": "没有打开的页面,请选择页面打开编辑"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Component } from 'react';
|
|||||||
import { observer } from '@ali/lowcode-globals';
|
import { observer } from '@ali/lowcode-globals';
|
||||||
import { Designer } from '../designer';
|
import { Designer } from '../designer';
|
||||||
import { DocumentView } from '../document';
|
import { DocumentView } from '../document';
|
||||||
|
import { intl } from '../locale';
|
||||||
import './project.less';
|
import './project.less';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -9,14 +10,14 @@ export class ProjectView extends Component<{ designer: Designer }> {
|
|||||||
render() {
|
render() {
|
||||||
const { designer } = this.props;
|
const { designer } = this.props;
|
||||||
// TODO: support splitview
|
// TODO: support splitview
|
||||||
|
const opens = designer.project.documents.filter((doc) => doc.opened);
|
||||||
return (
|
return (
|
||||||
<div className="lc-project">
|
<div className="lc-project">
|
||||||
{designer.project.documents.map(doc => {
|
{opens.length > 0 ? (
|
||||||
if (!doc.opened) {
|
opens.map((doc) => <DocumentView key={doc.id} document={doc} />)
|
||||||
return null;
|
) : (
|
||||||
}
|
<div className="lc-project-empty">{intl('No opened document')}</div>
|
||||||
return <DocumentView key={doc.id} document={doc} />;
|
)}
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,14 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
.lc-project-empty {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
background: transparent url(//img.alicdn.com/tfs/TB1xLKQAbj1gK0jSZFuXXcrHpXa-90-90.png) center 30% no-repeat;
|
||||||
|
padding-top: 50%;
|
||||||
|
}
|
||||||
.lc-document {
|
.lc-document {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@ -14,11 +14,11 @@ export class Project {
|
|||||||
// TODO: 考虑项目级别 History
|
// TODO: 考虑项目级别 History
|
||||||
|
|
||||||
constructor(readonly designer: Designer, schema?: ProjectSchema) {
|
constructor(readonly designer: Designer, schema?: ProjectSchema) {
|
||||||
this.setSchema(schema);
|
this.load(schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get currentDocument() {
|
@computed get currentDocument() {
|
||||||
return this.documents.find(doc => doc.actived);
|
return this.documents.find((doc) => doc.actived);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,30 +27,45 @@ export class Project {
|
|||||||
getSchema(): ProjectSchema {
|
getSchema(): ProjectSchema {
|
||||||
return {
|
return {
|
||||||
...this.data,
|
...this.data,
|
||||||
componentsTree: this.documents.map(doc => doc.schema),
|
// todo: future change this filter
|
||||||
|
componentsTree: this.documents.filter((doc) => !doc.isBlank()).map((doc) => doc.schema),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 整体设置项目 schema
|
* 整体设置项目 schema
|
||||||
|
*
|
||||||
|
* @param autoOpen true 自动打开文档 string 指定打开的文件
|
||||||
*/
|
*/
|
||||||
setSchema(schema?: ProjectSchema) {
|
load(schema?: ProjectSchema, autoOpen?: boolean | string) {
|
||||||
|
this.unload();
|
||||||
|
// load new document
|
||||||
this.data = {
|
this.data = {
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
componentsMap: [],
|
componentsMap: [],
|
||||||
componentsTree: [],
|
componentsTree: [],
|
||||||
...schema,
|
...schema,
|
||||||
};
|
};
|
||||||
if (this.documents.length > 0) {
|
|
||||||
this.documents.forEach(doc => doc.purge());
|
if (autoOpen) {
|
||||||
this.documents.length = 0;
|
if (autoOpen === true) {
|
||||||
|
// auto open first document or open a blank page
|
||||||
|
this.open(this.data.componentsTree[0]);
|
||||||
|
} else {
|
||||||
|
// auto open should be string of fileName
|
||||||
|
this.open(autoOpen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.open(
|
}
|
||||||
this.data.componentsTree[0] || {
|
|
||||||
componentName: 'Page',
|
/**
|
||||||
fileName: '',
|
* 卸载当前项目数据
|
||||||
},
|
*/
|
||||||
);
|
unload() {
|
||||||
|
if (this.documents.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.documents.forEach((doc) => doc.remove());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,14 +101,23 @@ export class Project {
|
|||||||
| string,
|
| string,
|
||||||
): any {}
|
): any {}
|
||||||
|
|
||||||
open(doc: string | DocumentModel | RootSchema): void {
|
open(doc?: string | DocumentModel | RootSchema): void {
|
||||||
|
if (!doc) {
|
||||||
|
const got = this.documents.find((item) => item.isBlank());
|
||||||
|
if (got) {
|
||||||
|
return got.open();
|
||||||
|
}
|
||||||
|
doc = new DocumentModel(this);
|
||||||
|
this.documents.push(doc);
|
||||||
|
return doc.open();
|
||||||
|
}
|
||||||
if (typeof doc === 'string') {
|
if (typeof doc === 'string') {
|
||||||
const got = this.documents.find(item => item.fileName === doc);
|
const got = this.documents.find((item) => item.fileName === doc);
|
||||||
if (got) {
|
if (got) {
|
||||||
return got.open();
|
return got.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = this.data.componentsTree.find(data => data.fileName === doc);
|
const data = this.data.componentsTree.find((data) => data.fileName === doc);
|
||||||
if (data) {
|
if (data) {
|
||||||
doc = new DocumentModel(this, data);
|
doc = new DocumentModel(this, data);
|
||||||
this.documents.push(doc);
|
this.documents.push(doc);
|
||||||
@ -113,7 +137,7 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkExclusive(actived: DocumentModel) {
|
checkExclusive(actived: DocumentModel) {
|
||||||
this.documents.forEach(doc => {
|
this.documents.forEach((doc) => {
|
||||||
if (doc !== actived) {
|
if (doc !== actived) {
|
||||||
doc.suspense();
|
doc.suspense();
|
||||||
}
|
}
|
||||||
@ -122,7 +146,7 @@ export class Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
closeOthers(opened: DocumentModel) {
|
closeOthers(opened: DocumentModel) {
|
||||||
this.documents.forEach(doc => {
|
this.documents.forEach((doc) => {
|
||||||
if (doc !== opened) {
|
if (doc !== opened) {
|
||||||
doc.close();
|
doc.close();
|
||||||
}
|
}
|
||||||
|
|||||||
28
packages/editor-core/CHANGELOG.md
Normal file
28
packages/editor-core/CHANGELOG.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-core@0.8.3...@ali/lowcode-editor-core@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-core
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## 0.8.3 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-core
|
||||||
|
|
||||||
|
<a name="0.8.2"></a>
|
||||||
|
## 0.8.2 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-core
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-editor-core",
|
"name": "@ali/lowcode-editor-core",
|
||||||
"version": "0.8.0",
|
"version": "0.8.4",
|
||||||
"description": "alibaba lowcode editor core",
|
"description": "alibaba lowcode editor core",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
@ -20,15 +20,15 @@
|
|||||||
],
|
],
|
||||||
"author": "xiayang.xy",
|
"author": "xiayang.xy",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@alifd/next": "1.x",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"events": "^3.1.0",
|
"events": "^3.1.0",
|
||||||
"intl-messageformat": "^8.3.1",
|
"intl-messageformat": "^8.3.1",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
"store": "^2.0.12",
|
|
||||||
"whatwg-fetch": "^3.0.0",
|
|
||||||
"react": "^16.8.0",
|
"react": "^16.8.0",
|
||||||
"@alifd/next": "1.x"
|
"store": "^2.0.12",
|
||||||
|
"whatwg-fetch": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alib/build-scripts": "^0.1.3",
|
"@alib/build-scripts": "^0.1.3",
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import {
|
|||||||
PluginSet,
|
PluginSet,
|
||||||
} from './definitions';
|
} from './definitions';
|
||||||
|
|
||||||
|
import pluginFactory from './pluginFactory';
|
||||||
|
|
||||||
import * as editorUtils from './utils';
|
import * as editorUtils from './utils';
|
||||||
|
|
||||||
const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
|
const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
|
||||||
@ -92,7 +94,10 @@ export default class Editor extends EventEmitter {
|
|||||||
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
|
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
|
||||||
super();
|
super();
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.components = components;
|
this.components = {};
|
||||||
|
Object.entries(components).forEach(([key, value]): void => {
|
||||||
|
this.components[key] = pluginFactory(value);
|
||||||
|
});
|
||||||
this.utils = { ...editorUtils, ...utils };
|
this.utils = { ...editorUtils, ...utils };
|
||||||
instance = this;
|
instance = this;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "lib",
|
"outDir": "lib"
|
||||||
"target": "es6",
|
|
||||||
"jsx": "react"
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./src/"
|
"./src/"
|
||||||
|
|||||||
43
packages/editor-skeleton/CHANGELOG.md
Normal file
43
packages/editor-skeleton/CHANGELOG.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.8.5"></a>
|
||||||
|
## [0.8.5](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.4...@ali/lowcode-editor-skeleton@0.8.5) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-editor-skeleton@0.8.3...@ali/lowcode-editor-skeleton@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## 0.8.3 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.2"></a>
|
||||||
|
## 0.8.2 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c286))
|
||||||
|
=======
|
||||||
|
* 🎸 merge material-parser ([b40c286](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b40c2869a0bc901d855279735fe86b84dabaa04d))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-editor-skeleton",
|
"name": "@ali/lowcode-editor-skeleton",
|
||||||
"version": "0.8.0",
|
"version": "0.8.5",
|
||||||
"description": "alibaba lowcode editor skeleton",
|
"description": "alibaba lowcode editor skeleton",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
],
|
],
|
||||||
"author": "xiayang.xy",
|
"author": "xiayang.xy",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-editor-core": "^0.8.0",
|
"@ali/lowcode-editor-core": "^0.8.4",
|
||||||
"@alifd/next": "^1.x",
|
"@alifd/next": "^1.x",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
"react": "^16.8.1",
|
"react": "^16.8.1",
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "lib",
|
"outDir": "lib"
|
||||||
"target": "es6",
|
|
||||||
"jsx": "react"
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./src/"
|
"./src/"
|
||||||
|
|||||||
62
packages/globals/CHANGELOG.md
Normal file
62
packages/globals/CHANGELOG.md
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.9.1"></a>
|
||||||
|
## [0.9.1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.9.0...@ali/lowcode-globals@0.9.1) (2020-03-31)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-globals
|
||||||
|
|
||||||
|
<a name="0.9.0"></a>
|
||||||
|
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.8.4...@ali/lowcode-globals@0.9.0) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **designer:** add builtin hotkeys ([2ec5883](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/2ec5883))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.8.3...@ali/lowcode-globals@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-globals
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-globals@0.8.2...@ali/lowcode-globals@0.8.3) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-globals
|
||||||
|
|
||||||
|
<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))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.1"></a>
|
||||||
|
## 0.8.1 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7))
|
||||||
|
=======
|
||||||
|
* double outline & ZH_EN support ([b379bd7](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/b379bd7c0c488ef24f825760750a13d3fa083c96))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-globals",
|
"name": "@ali/lowcode-globals",
|
||||||
"version": "0.8.0",
|
"version": "0.9.1",
|
||||||
"description": "Globals api for Ali lowCode engine",
|
"description": "Globals api for Ali lowCode engine",
|
||||||
|
"license": "MIT",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
@ -14,6 +15,16 @@
|
|||||||
"test": "ava",
|
"test": "ava",
|
||||||
"test:snapshot": "ava --update-snapshots"
|
"test:snapshot": "ava --update-snapshots"
|
||||||
},
|
},
|
||||||
|
"ava": {
|
||||||
|
"compileEnhancements": false,
|
||||||
|
"extensions": [
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
|
"require": [
|
||||||
|
"ts-node/register"
|
||||||
|
],
|
||||||
|
"snapshotDir": "test/fixtures/__snapshots__"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alifd/next": "^1.19.16",
|
"@alifd/next": "^1.19.16",
|
||||||
"@recore/obx": "^1.0.8",
|
"@recore/obx": "^1.0.8",
|
||||||
@ -23,26 +34,15 @@
|
|||||||
"react-dom": "^16.7.0"
|
"react-dom": "^16.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@alib/build-scripts": "^0.1.18",
|
||||||
"@types/classnames": "^2.2.7",
|
"@types/classnames": "^2.2.7",
|
||||||
"@types/node": "^13.7.1",
|
"@types/node": "^13.7.1",
|
||||||
"@types/react": "^16",
|
"@types/react": "^16",
|
||||||
"@types/react-dom": "^16",
|
"@types/react-dom": "^16",
|
||||||
"@alib/build-scripts": "^0.1.18",
|
|
||||||
"build-plugin-component": "^0.2.11",
|
"build-plugin-component": "^0.2.11",
|
||||||
"build-plugin-fusion": "^0.1.0",
|
"build-plugin-fusion": "^0.1.0",
|
||||||
"build-plugin-moment-locales": "^0.1.0"
|
"build-plugin-moment-locales": "^0.1.0"
|
||||||
},
|
},
|
||||||
"ava": {
|
|
||||||
"compileEnhancements": false,
|
|
||||||
"snapshotDir": "test/fixtures/__snapshots__",
|
|
||||||
"extensions": [
|
|
||||||
"ts"
|
|
||||||
],
|
|
||||||
"require": [
|
|
||||||
"ts-node/register"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://registry.npm.alibaba-inc.com"
|
"registry": "https://registry.npm.alibaba-inc.com"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
export * from './tip';
|
export * from './tip';
|
||||||
export * from './title';
|
export * from './title';
|
||||||
|
export * from './svg-icon';
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export interface IconProps {
|
|||||||
style?: object;
|
style?: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function IconBase({
|
export function SVGIcon({
|
||||||
fill,
|
fill,
|
||||||
size = 'medium',
|
size = 'medium',
|
||||||
viewBox,
|
viewBox,
|
||||||
@ -16,7 +16,7 @@ function findTip(target: HTMLElement | null): TipOptions | null {
|
|||||||
if (target.dataset && target.dataset.tip) {
|
if (target.dataset && target.dataset.tip) {
|
||||||
return {
|
return {
|
||||||
children: target.dataset.tip,
|
children: target.dataset.tip,
|
||||||
direction: target.dataset.direction || target.dataset.dir,
|
direction: (target.dataset.direction || target.dataset.dir) as any,
|
||||||
theme: target.dataset.theme,
|
theme: target.dataset.theme,
|
||||||
target,
|
target,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
export * from './clone';
|
|
||||||
export * from './hidden';
|
|
||||||
export * from './remove';
|
|
||||||
export * from './setting';
|
|
||||||
export * from './icon-base';
|
|
||||||
export * from './component';
|
|
||||||
export * from './container';
|
|
||||||
export * from './page';
|
|
||||||
@ -1,7 +1,6 @@
|
|||||||
export * from './intl';
|
export * from './intl';
|
||||||
export * from './components';
|
export * from './components';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export * from './icons';
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './di';
|
export * from './di';
|
||||||
export * from './obx';
|
export * from './obx';
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export interface TipConfig {
|
|||||||
className?: string;
|
className?: string;
|
||||||
children?: I18nData | ReactNode;
|
children?: I18nData | ReactNode;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
direction?: string; // 'n|s|w|e|top|bottom|left|right';
|
direction?: 'top' | 'bottom' | 'left' | 'right';
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TipContent = string | I18nData | ReactElement | TipConfig;
|
export type TipContent = string | I18nData | ReactElement | TipConfig;
|
||||||
|
|||||||
604
packages/globals/src/utils/hotkey.ts
Normal file
604
packages/globals/src/utils/hotkey.ts
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
interface KeyMap {
|
||||||
|
[key: number]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CtrlKeyMap {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ActionEvent {
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HotkeyCallbacks {
|
||||||
|
[key: string]: HotkeyCallbackCfg[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HotkeyDirectMap {
|
||||||
|
[key: string]: HotkeyCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HotkeyCallback = (e: KeyboardEvent, combo?: string) => any | false;
|
||||||
|
|
||||||
|
interface HotkeyCallbackCfg {
|
||||||
|
callback: HotkeyCallback;
|
||||||
|
modifiers: string[];
|
||||||
|
action: string;
|
||||||
|
seq?: string;
|
||||||
|
level?: number;
|
||||||
|
combo?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface KeyInfo {
|
||||||
|
key: string;
|
||||||
|
modifiers: string[];
|
||||||
|
action: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SequenceLevels {
|
||||||
|
[key: string]: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAP: KeyMap = {
|
||||||
|
8: 'backspace',
|
||||||
|
9: 'tab',
|
||||||
|
13: 'enter',
|
||||||
|
16: 'shift',
|
||||||
|
17: 'ctrl',
|
||||||
|
18: 'alt',
|
||||||
|
20: 'capslock',
|
||||||
|
27: 'esc',
|
||||||
|
32: 'space',
|
||||||
|
33: 'pageup',
|
||||||
|
34: 'pagedown',
|
||||||
|
35: 'end',
|
||||||
|
36: 'home',
|
||||||
|
37: 'left',
|
||||||
|
38: 'up',
|
||||||
|
39: 'right',
|
||||||
|
40: 'down',
|
||||||
|
45: 'ins',
|
||||||
|
46: 'del',
|
||||||
|
91: 'meta',
|
||||||
|
93: 'meta',
|
||||||
|
224: 'meta',
|
||||||
|
};
|
||||||
|
|
||||||
|
const KEYCODE_MAP: KeyMap = {
|
||||||
|
106: '*',
|
||||||
|
107: '+',
|
||||||
|
109: '-',
|
||||||
|
110: '.',
|
||||||
|
111: '/',
|
||||||
|
186: ';',
|
||||||
|
187: '=',
|
||||||
|
188: ',',
|
||||||
|
189: '-',
|
||||||
|
190: '.',
|
||||||
|
191: '/',
|
||||||
|
192: '`',
|
||||||
|
219: '[',
|
||||||
|
220: '\\',
|
||||||
|
221: ']',
|
||||||
|
222: "'",
|
||||||
|
};
|
||||||
|
|
||||||
|
const SHIFT_MAP: CtrlKeyMap = {
|
||||||
|
'~': '`',
|
||||||
|
'!': '1',
|
||||||
|
'@': '2',
|
||||||
|
'#': '3',
|
||||||
|
$: '4',
|
||||||
|
'%': '5',
|
||||||
|
'^': '6',
|
||||||
|
'&': '7',
|
||||||
|
'*': '8',
|
||||||
|
'(': '9',
|
||||||
|
')': '0',
|
||||||
|
_: '-',
|
||||||
|
'+': '=',
|
||||||
|
':': ';',
|
||||||
|
'"': "'",
|
||||||
|
'<': ',',
|
||||||
|
'>': '.',
|
||||||
|
'?': '/',
|
||||||
|
'|': '\\',
|
||||||
|
};
|
||||||
|
|
||||||
|
const SPECIAL_ALIASES: CtrlKeyMap = {
|
||||||
|
option: 'alt',
|
||||||
|
command: 'meta',
|
||||||
|
return: 'enter',
|
||||||
|
escape: 'esc',
|
||||||
|
plus: '+',
|
||||||
|
mod: /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl',
|
||||||
|
};
|
||||||
|
|
||||||
|
let REVERSE_MAP: CtrlKeyMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loop through the f keys, f1 to f19 and add them to the map
|
||||||
|
* programatically
|
||||||
|
*/
|
||||||
|
for (let i = 1; i < 20; ++i) {
|
||||||
|
MAP[111 + i] = 'f' + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loop through to map numbers on the numeric keypad
|
||||||
|
*/
|
||||||
|
for (let i = 0; i <= 9; ++i) {
|
||||||
|
MAP[i + 96] = String(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* takes the event and returns the key character
|
||||||
|
*/
|
||||||
|
function characterFromEvent(e: KeyboardEvent): string {
|
||||||
|
const keyCode = e.keyCode || e.which;
|
||||||
|
// for keypress events we should return the character as is
|
||||||
|
if (e.type === 'keypress') {
|
||||||
|
let character = String.fromCharCode(keyCode);
|
||||||
|
// if the shift key is not pressed then it is safe to assume
|
||||||
|
// that we want the character to be lowercase. this means if
|
||||||
|
// you accidentally have caps lock on then your key bindings
|
||||||
|
// will continue to work
|
||||||
|
//
|
||||||
|
// the only side effect that might not be desired is if you
|
||||||
|
// bind something like 'A' cause you want to trigger an
|
||||||
|
// event when capital A is pressed caps lock will no longer
|
||||||
|
// trigger the event. shift+a will though.
|
||||||
|
if (!e.shiftKey) {
|
||||||
|
character = character.toLowerCase();
|
||||||
|
}
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
// for non keypress events the special maps are needed
|
||||||
|
if (MAP[keyCode]) {
|
||||||
|
return MAP[keyCode];
|
||||||
|
}
|
||||||
|
if (KEYCODE_MAP[keyCode]) {
|
||||||
|
return KEYCODE_MAP[keyCode];
|
||||||
|
}
|
||||||
|
// if it is not in the special map
|
||||||
|
// with keydown and keyup events the character seems to always
|
||||||
|
// come in as an uppercase character whether you are pressing shift
|
||||||
|
// or not. we should make sure it is always lowercase for comparisons
|
||||||
|
return String.fromCharCode(keyCode).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface KeypressEvent extends KeyboardEvent {
|
||||||
|
type: 'keypress';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPressEvent(e: KeyboardEvent | ActionEvent): e is KeypressEvent {
|
||||||
|
return e.type === 'keypress';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if two arrays are equal
|
||||||
|
*/
|
||||||
|
function modifiersMatch(modifiers1: string[], modifiers2: string[]): boolean {
|
||||||
|
return modifiers1.sort().join(',') === modifiers2.sort().join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* takes a key event and figures out what the modifiers are
|
||||||
|
*/
|
||||||
|
function eventModifiers(e: KeyboardEvent): string[] {
|
||||||
|
const modifiers = [];
|
||||||
|
|
||||||
|
if (e.shiftKey) {
|
||||||
|
modifiers.push('shift');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.altKey) {
|
||||||
|
modifiers.push('alt');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.ctrlKey) {
|
||||||
|
modifiers.push('ctrl');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.metaKey) {
|
||||||
|
modifiers.push('meta');
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determines if the keycode specified is a modifier key or not
|
||||||
|
*/
|
||||||
|
function isModifier(key: string): boolean {
|
||||||
|
return key === 'shift' || key === 'ctrl' || key === 'alt' || key === 'meta';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reverses the map lookup so that we can look for specific keys
|
||||||
|
* to see what can and can't use keypress
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
function getReverseMap(): CtrlKeyMap {
|
||||||
|
if (!REVERSE_MAP) {
|
||||||
|
REVERSE_MAP = {};
|
||||||
|
for (const key in MAP) {
|
||||||
|
// pull out the numeric keypad from here cause keypress should
|
||||||
|
// be able to detect the keys from the character
|
||||||
|
if (Number(key) > 95 && Number(key) < 112) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MAP.hasOwnProperty(key)) {
|
||||||
|
REVERSE_MAP[MAP[key]] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return REVERSE_MAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* picks the best action based on the key combination
|
||||||
|
*/
|
||||||
|
function pickBestAction(key: string, modifiers: string[], action?: string): string {
|
||||||
|
// if no action was picked in we should try to pick the one
|
||||||
|
// that we think would work best for this key
|
||||||
|
if (!action) {
|
||||||
|
action = getReverseMap()[key] ? 'keydown' : 'keypress';
|
||||||
|
}
|
||||||
|
// modifier keys don't work as expected with keypress,
|
||||||
|
// switch to keydown
|
||||||
|
if (action === 'keypress' && modifiers.length) {
|
||||||
|
action = 'keydown';
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts from a string key combination to an array
|
||||||
|
*
|
||||||
|
* @param {string} combination like "command+shift+l"
|
||||||
|
* @return {Array}
|
||||||
|
*/
|
||||||
|
function keysFromString(combination: string): string[] {
|
||||||
|
if (combination === '+') {
|
||||||
|
return ['+'];
|
||||||
|
}
|
||||||
|
|
||||||
|
combination = combination.replace(/\+{2}/g, '+plus');
|
||||||
|
return combination.split('+');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets info for a specific key combination
|
||||||
|
*
|
||||||
|
* @param combination key combination ("command+s" or "a" or "*")
|
||||||
|
*/
|
||||||
|
function getKeyInfo(combination: string, action?: string): KeyInfo {
|
||||||
|
let keys: string[] = [];
|
||||||
|
let key = '';
|
||||||
|
let i: number;
|
||||||
|
const modifiers: string[] = [];
|
||||||
|
|
||||||
|
// take the keys from this pattern and figure out what the actual
|
||||||
|
// pattern is all about
|
||||||
|
keys = keysFromString(combination);
|
||||||
|
|
||||||
|
for (i = 0; i < keys.length; ++i) {
|
||||||
|
key = keys[i];
|
||||||
|
|
||||||
|
// normalize key names
|
||||||
|
if (SPECIAL_ALIASES[key]) {
|
||||||
|
key = SPECIAL_ALIASES[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is not a keypress event then we should
|
||||||
|
// be smart about using shift keys
|
||||||
|
// this will only work for US keyboards however
|
||||||
|
if (action && action !== 'keypress' && SHIFT_MAP[key]) {
|
||||||
|
key = SHIFT_MAP[key];
|
||||||
|
modifiers.push('shift');
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this key is a modifier then add it to the list of modifiers
|
||||||
|
if (isModifier(key)) {
|
||||||
|
modifiers.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// depending on what the key combination is
|
||||||
|
// we will try to pick the best event for it
|
||||||
|
action = pickBestAction(key, modifiers, action);
|
||||||
|
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
modifiers,
|
||||||
|
action,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* actually calls the callback function
|
||||||
|
*
|
||||||
|
* if your callback function returns false this will use the jquery
|
||||||
|
* convention - prevent default and stop propogation on the event
|
||||||
|
*/
|
||||||
|
function fireCallback(callback: HotkeyCallback, e: KeyboardEvent, combo?: string, sequence?: string): void {
|
||||||
|
if (callback(e, combo) === false) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Hotkey {
|
||||||
|
private callBacks: HotkeyCallbacks = {};
|
||||||
|
private directMap: HotkeyDirectMap = {};
|
||||||
|
private sequenceLevels: SequenceLevels = {};
|
||||||
|
private resetTimer = 0;
|
||||||
|
private ignoreNextKeyup: boolean | string = false;
|
||||||
|
private ignoreNextKeypress = false;
|
||||||
|
private nextExpectedAction: boolean | string = false;
|
||||||
|
|
||||||
|
mount(window: Window) {
|
||||||
|
const document = window.document;
|
||||||
|
const handleKeyEvent = this.handleKeyEvent.bind(this);
|
||||||
|
document.addEventListener('keypress', handleKeyEvent, false);
|
||||||
|
document.addEventListener('keydown', handleKeyEvent, false);
|
||||||
|
document.addEventListener('keyup', handleKeyEvent, false);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('keypress', handleKeyEvent, false);
|
||||||
|
document.removeEventListener('keydown', handleKeyEvent, false);
|
||||||
|
document.removeEventListener('keyup', handleKeyEvent, false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(combos: string[] | string, callback: HotkeyCallback, action?: string): Hotkey {
|
||||||
|
this.bindMultiple(Array.isArray(combos) ? combos : [combos], callback, action);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resets all sequence counters except for the ones passed in
|
||||||
|
*/
|
||||||
|
private resetSequences(doNotReset?: SequenceLevels): void {
|
||||||
|
// doNotReset = doNotReset || {};
|
||||||
|
let activeSequences = false;
|
||||||
|
let key = '';
|
||||||
|
for (key in this.sequenceLevels) {
|
||||||
|
if (doNotReset && doNotReset[key]) {
|
||||||
|
activeSequences = true;
|
||||||
|
} else {
|
||||||
|
this.sequenceLevels[key] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!activeSequences) {
|
||||||
|
this.nextExpectedAction = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finds all callbacks that match based on the keycode, modifiers,
|
||||||
|
* and action
|
||||||
|
*/
|
||||||
|
private getMatches(
|
||||||
|
character: string,
|
||||||
|
modifiers: string[],
|
||||||
|
e: KeyboardEvent | ActionEvent,
|
||||||
|
sequenceName?: string,
|
||||||
|
combination?: string,
|
||||||
|
level?: number,
|
||||||
|
): HotkeyCallbackCfg[] {
|
||||||
|
let i: number;
|
||||||
|
let callback: HotkeyCallbackCfg;
|
||||||
|
const matches: HotkeyCallbackCfg[] = [];
|
||||||
|
const action: string = e.type;
|
||||||
|
|
||||||
|
// if there are no events related to this keycode
|
||||||
|
if (!this.callBacks[character]) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a modifier key is coming up on its own we should allow it
|
||||||
|
if (action === 'keyup' && isModifier(character)) {
|
||||||
|
modifiers = [character];
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop through all callbacks for the key that was pressed
|
||||||
|
// and see if any of them match
|
||||||
|
for (i = 0; i < this.callBacks[character].length; ++i) {
|
||||||
|
callback = this.callBacks[character][i];
|
||||||
|
|
||||||
|
// if a sequence name is not specified, but this is a sequence at
|
||||||
|
// the wrong level then move onto the next match
|
||||||
|
if (!sequenceName && callback.seq && this.sequenceLevels[callback.seq] !== callback.level) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the action we are looking for doesn't match the action we got
|
||||||
|
// then we should keep going
|
||||||
|
if (action !== callback.action) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is a keypress event and the meta key and control key
|
||||||
|
// are not pressed that means that we need to only look at the
|
||||||
|
// character, otherwise check the modifiers as well
|
||||||
|
//
|
||||||
|
// chrome will not fire a keypress if meta or control is down
|
||||||
|
// safari will fire a keypress if meta or meta+shift is down
|
||||||
|
// firefox will fire a keypress if meta or control is down
|
||||||
|
if ((isPressEvent(e) && !e.metaKey && !e.ctrlKey) || modifiersMatch(modifiers, callback.modifiers)) {
|
||||||
|
const deleteCombo = !sequenceName && callback.combo === combination;
|
||||||
|
const deleteSequence = sequenceName && callback.seq === sequenceName && callback.level === level;
|
||||||
|
if (deleteCombo || deleteSequence) {
|
||||||
|
this.callBacks[character].splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
matches.push(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleKey(character: string, modifiers: string[], e: KeyboardEvent): void {
|
||||||
|
const callbacks: HotkeyCallbackCfg[] = this.getMatches(character, modifiers, e);
|
||||||
|
let i: number;
|
||||||
|
const doNotReset: SequenceLevels = {};
|
||||||
|
let maxLevel = 0;
|
||||||
|
let processedSequenceCallback = false;
|
||||||
|
|
||||||
|
// Calculate the maxLevel for sequences so we can only execute the longest callback sequence
|
||||||
|
for (i = 0; i < callbacks.length; ++i) {
|
||||||
|
if (callbacks[i].seq) {
|
||||||
|
maxLevel = Math.max(maxLevel, callbacks[i].level || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop through matching callbacks for this key event
|
||||||
|
for (i = 0; i < callbacks.length; ++i) {
|
||||||
|
// fire for all sequence callbacks
|
||||||
|
// this is because if for example you have multiple sequences
|
||||||
|
// bound such as "g i" and "g t" they both need to fire the
|
||||||
|
// callback for matching g cause otherwise you can only ever
|
||||||
|
// match the first one
|
||||||
|
if (callbacks[i].seq) {
|
||||||
|
// only fire callbacks for the maxLevel to prevent
|
||||||
|
// subsequences from also firing
|
||||||
|
//
|
||||||
|
// for example 'a option b' should not cause 'option b' to fire
|
||||||
|
// even though 'option b' is part of the other sequence
|
||||||
|
//
|
||||||
|
// any sequences that do not match here will be discarded
|
||||||
|
// below by the resetSequences call
|
||||||
|
if (callbacks[i].level !== maxLevel) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
processedSequenceCallback = true;
|
||||||
|
|
||||||
|
// keep a list of which sequences were matches for later
|
||||||
|
doNotReset[callbacks[i].seq || ''] = 1;
|
||||||
|
fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there were no sequence matches but we are still here
|
||||||
|
// that means this is a regular match so we should fire that
|
||||||
|
if (!processedSequenceCallback) {
|
||||||
|
fireCallback(callbacks[i].callback, e, callbacks[i].combo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ignoreThisKeypress = e.type === 'keypress' && this.ignoreNextKeypress;
|
||||||
|
if (e.type === this.nextExpectedAction && !isModifier(character) && !ignoreThisKeypress) {
|
||||||
|
this.resetSequences(doNotReset);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ignoreNextKeypress = processedSequenceCallback && e.type === 'keydown';
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleKeyEvent(e: KeyboardEvent): void {
|
||||||
|
const character = characterFromEvent(e);
|
||||||
|
|
||||||
|
// no character found then stop
|
||||||
|
if (!character) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to use === for the character check because the character can be 0
|
||||||
|
if (e.type === 'keyup' && this.ignoreNextKeyup === character) {
|
||||||
|
this.ignoreNextKeyup = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handleKey(character, eventModifiers(e), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetSequenceTimer(): void {
|
||||||
|
if (this.resetTimer) {
|
||||||
|
clearTimeout(this.resetTimer);
|
||||||
|
}
|
||||||
|
this.resetTimer = window.setTimeout(this.resetSequences, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bindSequence(combo: string, keys: string[], callback: HotkeyCallback, action?: string): void {
|
||||||
|
// const self: any = this;
|
||||||
|
this.sequenceLevels[combo] = 0;
|
||||||
|
const increaseSequence = (nextAction: string) => {
|
||||||
|
return () => {
|
||||||
|
this.nextExpectedAction = nextAction;
|
||||||
|
++this.sequenceLevels[combo];
|
||||||
|
this.resetSequenceTimer();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const callbackAndReset = (e: KeyboardEvent): void => {
|
||||||
|
fireCallback(callback, e, combo);
|
||||||
|
|
||||||
|
if (action !== 'keyup') {
|
||||||
|
this.ignoreNextKeyup = characterFromEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(this.resetSequences, 10);
|
||||||
|
};
|
||||||
|
for (let i = 0; i < keys.length; ++i) {
|
||||||
|
const isFinal = i + 1 === keys.length;
|
||||||
|
const wrappedCallback = isFinal ? callbackAndReset : increaseSequence(action || getKeyInfo(keys[i + 1]).action);
|
||||||
|
this.bindSingle(keys[i], wrappedCallback, action, combo, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bindSingle(
|
||||||
|
combination: string,
|
||||||
|
callback: HotkeyCallback,
|
||||||
|
action?: string,
|
||||||
|
sequenceName?: string,
|
||||||
|
level?: number,
|
||||||
|
): void {
|
||||||
|
// store a direct mapped reference for use with HotKey.trigger
|
||||||
|
this.directMap[`${combination}:${action}`] = callback;
|
||||||
|
|
||||||
|
// make sure multiple spaces in a row become a single space
|
||||||
|
combination = combination.replace(/\s+/g, ' ');
|
||||||
|
|
||||||
|
const sequence: string[] = combination.split(' ');
|
||||||
|
let info: KeyInfo;
|
||||||
|
|
||||||
|
// if this pattern is a sequence of keys then run through this method
|
||||||
|
// to reprocess each pattern one key at a time
|
||||||
|
if (sequence.length > 1) {
|
||||||
|
this.bindSequence(combination, sequence, callback, action);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = getKeyInfo(combination, action);
|
||||||
|
|
||||||
|
// make sure to initialize array if this is the first time
|
||||||
|
// a callback is added for this key
|
||||||
|
this.callBacks[info.key] = this.callBacks[info.key] || [];
|
||||||
|
|
||||||
|
// remove an existing match if there is one
|
||||||
|
this.getMatches(info.key, info.modifiers, { type: info.action }, sequenceName, combination, level);
|
||||||
|
|
||||||
|
// add this call back to the array
|
||||||
|
// if it is a sequence put it at the beginning
|
||||||
|
// if not put it at the end
|
||||||
|
//
|
||||||
|
// this is important because the way these are processed expects
|
||||||
|
// the sequence ones to come first
|
||||||
|
this.callBacks[info.key][sequenceName ? 'unshift' : 'push']({
|
||||||
|
callback,
|
||||||
|
modifiers: info.modifiers,
|
||||||
|
action: info.action,
|
||||||
|
seq: sequenceName,
|
||||||
|
level,
|
||||||
|
combo: combination,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private bindMultiple(combinations: string[], callback: HotkeyCallback, action?: string) {
|
||||||
|
for (const item of combinations) {
|
||||||
|
this.bindSingle(item, callback, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,3 +19,4 @@ export * from './shallow-equal';
|
|||||||
export * from './unique-id';
|
export * from './unique-id';
|
||||||
export * from './get-public-path';
|
export * from './get-public-path';
|
||||||
export * from './is-form-event';
|
export * from './is-form-event';
|
||||||
|
export * from './hotkey';
|
||||||
|
|||||||
118
packages/material-parser/CHANGELOG.md
Normal file
118
packages/material-parser/CHANGELOG.md
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.9.0"></a>
|
||||||
|
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.4...@ali/lowcode-material-parser@0.9.0) (2020-03-31)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* [material-parser]fix bug of main field & remove useless debugger ([8fde0ec](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/8fde0ec))
|
||||||
|
* fix bug of build errors ([770a1b6](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/770a1b6))
|
||||||
|
* fix bug of missing types in material-parser ([9ce0a73](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/9ce0a73))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 support parsing fusion source code ([5895cf1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/5895cf1))
|
||||||
|
* support localizing ([e1faa84](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/e1faa84))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.4"></a>
|
||||||
|
## [0.8.4](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.3...@ali/lowcode-material-parser@0.8.4) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-material-parser
|
||||||
|
|
||||||
|
<a name="0.8.3"></a>
|
||||||
|
## [0.8.3](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.2...@ali/lowcode-material-parser@0.8.3) (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-material-parser
|
||||||
|
|
||||||
|
<a name="0.8.2"></a>
|
||||||
|
## 0.8.2 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58d))
|
||||||
|
* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f97523))
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360d))
|
||||||
|
* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f))
|
||||||
|
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
|
||||||
|
* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e1))
|
||||||
|
* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33))
|
||||||
|
* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6de))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* 🧨 use react-docgen to replace parser
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.8.1"></a>
|
||||||
|
## 0.8.1 (2020-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58d))
|
||||||
|
* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f97523))
|
||||||
|
=======
|
||||||
|
* 🐛 fix bug of transforming type ([ebbe58d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/ebbe58df70f047f4b5fe367ac4b4a08de8a65e5d))
|
||||||
|
* 🐛 fix bug of validate schema ([3f97523](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3f975232c7cd551bc9c74962095dcc9b127af489))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa))
|
||||||
|
=======
|
||||||
|
* 💡 refactor with react-docgen ([64c9daa](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/64c9daa1f451fdfeab2777e4beefc5d5e1890ba1))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360d))
|
||||||
|
* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f))
|
||||||
|
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e66168))
|
||||||
|
* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e1))
|
||||||
|
* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33))
|
||||||
|
* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6de))
|
||||||
|
=======
|
||||||
|
* complete component protocol json schema & validate method ([3df360d](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/3df360de85d425b2926ea50ff26a8df27ec36a78))
|
||||||
|
* immigrate aimake materialin ([44ac85f](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/44ac85f8a6a35bcd50f2e2b74a022e3cebe3cdef))
|
||||||
|
* import react-docgen to parse propTypes ([6e66168](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6e661686e4693e69279c496f3be1dd173703c55e))
|
||||||
|
* remove -p tslint.json for test ([6d013e1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/6d013e18f93bad5647cb9ea0a497336f64e1459a))
|
||||||
|
* remove useless codes & modify generator ([dcd1b33](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/dcd1b33d3bf8bdf5577dcc980608d9eac8d99372))
|
||||||
|
* support multiple exported components ([db1b6de](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/db1b6deaca256b0d107fe607de6cd0fc90517a9c))
|
||||||
|
>>>>>>> df955e1db90ff104cd11160def80113cfd6faccc
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* 🧨 use react-docgen to replace parser
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-material-parser",
|
"name": "@ali/lowcode-material-parser",
|
||||||
"version": "0.8.0",
|
"version": "0.9.0",
|
||||||
"description": "material parser for Ali lowCode engine",
|
"description": "material parser for Ali lowCode engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
@ -20,6 +20,7 @@
|
|||||||
"jest-watch-typeahead": "^0.3.1",
|
"jest-watch-typeahead": "^0.3.1",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"json-schema-to-typescript": "^8.2.0",
|
"json-schema-to-typescript": "^8.2.0",
|
||||||
|
"tslib": "^1.11.1",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -47,6 +48,7 @@
|
|||||||
"@babel/parser": "^7.8.4",
|
"@babel/parser": "^7.8.4",
|
||||||
"@babel/traverse": "^7.8.4",
|
"@babel/traverse": "^7.8.4",
|
||||||
"@babel/types": "^7.8.3",
|
"@babel/types": "^7.8.3",
|
||||||
|
"ast-types": "^0.13.3",
|
||||||
"cross-spawn-promise": "^0.10.2",
|
"cross-spawn-promise": "^0.10.2",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
@ -54,5 +56,8 @@
|
|||||||
"react-docgen": "^5.3.0",
|
"react-docgen": "^5.3.0",
|
||||||
"semver": "^7.1.3",
|
"semver": "^7.1.3",
|
||||||
"short-uuid": "^3.1.1"
|
"short-uuid": "^3.1.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npm.alibaba-inc.com"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ const tsPath = path.resolve(__dirname, '../src/otter-core/schema/types.ts');
|
|||||||
ajv.compile(schema);
|
ajv.compile(schema);
|
||||||
fs.writeFileSync(JsonPath, JSON.stringify(schema, null, 2), 'utf-8');
|
fs.writeFileSync(JsonPath, JSON.stringify(schema, null, 2), 'utf-8');
|
||||||
console.log('yaml file is successfully transformed into json');
|
console.log('yaml file is successfully transformed into json');
|
||||||
const ts = await compile(schema, 'IComponentMaterial');
|
const ts = await compile(schema, 'ComponentMeta');
|
||||||
fs.writeFileSync(tsPath, ts);
|
fs.writeFileSync(tsPath, ts);
|
||||||
console.log('schema.d.ts is successfully generated');
|
console.log('schema.d.ts is successfully generated');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user