mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-12 17:08:14 +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
|
||||
yarn.lock
|
||||
deploy-space/packages
|
||||
deploy-space/.env
|
||||
|
||||
|
||||
# IDE
|
||||
|
||||
@ -11,11 +11,12 @@
|
||||
#### 跑起来:
|
||||
|
||||
- `npm run setup`
|
||||
- `npm start`
|
||||
|
||||
#### 开发提交:
|
||||
|
||||
- `git add <your-files>`
|
||||
- `npm run commit`
|
||||
- `npm run commit` # 在根目录
|
||||
|
||||
## 发布
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<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>
|
||||
<title>LowCodeEngine Editor 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-dom/16.9.0/umd/react-dom.development.js"></script>
|
||||
@ -16,7 +16,7 @@
|
||||
<!-- lowcode engine globals -->
|
||||
<link rel="stylesheet" href="./globals.css" />
|
||||
<!-- lowcode engine app -->
|
||||
<link rel="stylesheet" href="./lowcode-demo.css" />
|
||||
<link rel="stylesheet" href="./lowcode-editor.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -24,6 +24,6 @@
|
||||
<!-- lowcode engine globals -->
|
||||
<script src="./globals.js"></script>
|
||||
<!-- lowcode engine app -->
|
||||
<script src="./lowcode-demo.js"></script>
|
||||
<script src="./lowcode-editor.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
<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>
|
||||
<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-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>
|
||||
@ -13,9 +14,10 @@
|
||||
|
||||
<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>
|
||||
<link rel="stylesheet" href="./lowcode-preview.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="lce-container"></div>
|
||||
<script src="./lowcode-preview.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"tslib": "^1.9.3",
|
||||
"typescript": "^3.2.2"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
@ -13,5 +9,8 @@
|
||||
"**/@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": "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.
|
||||
"moduleResolution": "node",
|
||||
// Process & infer types from .js files.
|
||||
@ -34,6 +34,7 @@
|
||||
"resolveJsonModule": true,
|
||||
// skip type checking of declaration files
|
||||
"skipLibCheck": true,
|
||||
"outDir": "lib"
|
||||
},
|
||||
"exclude": ["**/test", "**/lib", "**/es", "node_modules"]
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
- 使用 `camelCase` 为属性或本地变量命名
|
||||
- 不要为私有属性名添加 `_` 前缀
|
||||
- 尽可能使用完整的单词拼写命名
|
||||
- 文件夹命名统一使用小写
|
||||
- 文件夹/文件命名统一使用小写 `get-custom-data.ts`
|
||||
|
||||
### 组件
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"lerna": "2.11.0",
|
||||
"version": "independent",
|
||||
"npmClient": "yarn",
|
||||
"npmClient": "tyarn",
|
||||
"registry": "http://registry.npm.alibaba-inc.com",
|
||||
"useWorkspaces": true,
|
||||
"packages": [
|
||||
|
||||
52
package.json
52
package.json
@ -1,14 +1,34 @@
|
||||
{
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"nohoist": [
|
||||
"**/css-modules-typescript-loader",
|
||||
"**/@alife/theme-lowcode-*"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build": "lerna run build --stream",
|
||||
"clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
|
||||
"commit": "git-cz",
|
||||
"pub": "lerna publish",
|
||||
"setup": "./scripts/setup.sh",
|
||||
"start": "./scripts/start.sh",
|
||||
"build": "lerna run build",
|
||||
"test": "lerna run test",
|
||||
"test:snapshot": "lerna run test:snapshot",
|
||||
"pub": "lerna publish",
|
||||
"commit": "git-cz"
|
||||
"test": "lerna run test --stream",
|
||||
"test:snapshot": "lerna run test:snapshot"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{tsx,ts}": [
|
||||
"eslint --quiet",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ali/lowcode-config": "^2.0.5",
|
||||
@ -26,25 +46,7 @@
|
||||
"tslib": "^1.9.3",
|
||||
"typescript": "^3.2.2"
|
||||
},
|
||||
"engines" : { "node" : "^10" },
|
||||
"workspaces": {
|
||||
"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"
|
||||
}
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
"version": "0.8.0",
|
||||
"name": "@ali/lowcode-code-generator",
|
||||
"version": "0.8.4",
|
||||
"description": "出码引擎 for LowCode Engine",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rimraf lib && tsc",
|
||||
"compile": "rimraf lib && tsc",
|
||||
"build": "rimraf lib && webpack",
|
||||
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
|
||||
"test": "ava"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ali/am-eslint-config": "*",
|
||||
"@types/prettier": "^1.19.1",
|
||||
"change-case": "^3.1.0",
|
||||
"prettier": "^2.0.2",
|
||||
"short-uuid": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^1.0.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-loader": "^6.2.2",
|
||||
"ts-node": "^7.0.1",
|
||||
"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": {
|
||||
"compileEnhancements": false,
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
ICompiledModule,
|
||||
IModuleBuilder,
|
||||
IResultFile,
|
||||
PostProcessor,
|
||||
} from '../types';
|
||||
|
||||
import { COMMON_SUB_MODULE_NAME } from '../const/generator';
|
||||
@ -17,9 +18,11 @@ import ResultFile from '../model/ResultFile';
|
||||
export function createModuleBuilder(
|
||||
options: {
|
||||
plugins: BuilderComponentPlugin[];
|
||||
postProcessors: PostProcessor[];
|
||||
mainFileName?: string;
|
||||
} = {
|
||||
plugins: [],
|
||||
postProcessors: [],
|
||||
},
|
||||
): IModuleBuilder {
|
||||
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);
|
||||
chunks.forEach(fileChunkList => {
|
||||
@ -46,6 +49,18 @@ export function createModuleBuilder(
|
||||
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 {
|
||||
files,
|
||||
};
|
||||
|
||||
@ -8,10 +8,11 @@ import {
|
||||
IResultDir,
|
||||
IResultFile,
|
||||
ISchemaParser,
|
||||
PostProcessor,
|
||||
} from '../types';
|
||||
|
||||
import ResultDir from '@/model/ResultDir';
|
||||
import SchemaParser from '@/parse/SchemaParser';
|
||||
import SchemaParser from '@/parser/SchemaParser';
|
||||
|
||||
import { createModuleBuilder } from '@/generator/ModuleBuilder';
|
||||
|
||||
@ -40,16 +41,20 @@ function getDirFromRoot(root: IResultDir, path: string[]): IResultDir {
|
||||
export class ProjectBuilder implements IProjectBuilder {
|
||||
private template: IProjectTemplate;
|
||||
private plugins: IProjectPlugins;
|
||||
private postProcessors: PostProcessor[];
|
||||
|
||||
constructor({
|
||||
template,
|
||||
plugins,
|
||||
postProcessors,
|
||||
}: {
|
||||
template: IProjectTemplate;
|
||||
plugins: IProjectPlugins;
|
||||
postProcessors: PostProcessor[];
|
||||
}) {
|
||||
this.template = template;
|
||||
this.plugins = plugins;
|
||||
this.postProcessors = postProcessors;
|
||||
}
|
||||
|
||||
public async generateProject(schema: IProjectSchema): Promise<IResultDir> {
|
||||
@ -212,45 +217,57 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
|
||||
builders.components = createModuleBuilder({
|
||||
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({
|
||||
plugins: this.plugins.router,
|
||||
mainFileName: this.template.slots.router.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.entry = createModuleBuilder({
|
||||
plugins: this.plugins.entry,
|
||||
mainFileName: this.template.slots.entry.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.globalStyle = createModuleBuilder({
|
||||
plugins: this.plugins.globalStyle,
|
||||
mainFileName: this.template.slots.globalStyle.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.htmlEntry = createModuleBuilder({
|
||||
plugins: this.plugins.htmlEntry,
|
||||
mainFileName: this.template.slots.htmlEntry.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
builders.packageJSON = createModuleBuilder({
|
||||
plugins: this.plugins.packageJSON,
|
||||
mainFileName: this.template.slots.packageJSON.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
|
||||
if (this.template.slots.constants && this.plugins.constants) {
|
||||
builders.constants = createModuleBuilder({
|
||||
plugins: this.plugins.constants,
|
||||
mainFileName: this.template.slots.constants.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
}
|
||||
if (this.template.slots.utils && this.plugins.utils) {
|
||||
builders.utils = createModuleBuilder({
|
||||
plugins: this.plugins.utils,
|
||||
mainFileName: this.template.slots.utils.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
}
|
||||
if (this.template.slots.i18n && this.plugins.i18n) {
|
||||
builders.i18n = createModuleBuilder({
|
||||
plugins: this.plugins.i18n,
|
||||
mainFileName: this.template.slots.i18n.fileName,
|
||||
postProcessors: this.postProcessors,
|
||||
});
|
||||
}
|
||||
|
||||
@ -261,12 +278,15 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
export function createProjectBuilder({
|
||||
template,
|
||||
plugins,
|
||||
postProcessors,
|
||||
}: {
|
||||
template: IProjectTemplate;
|
||||
plugins: IProjectPlugins;
|
||||
postProcessors: PostProcessor[];
|
||||
}): IProjectBuilder {
|
||||
return new ProjectBuilder({
|
||||
template,
|
||||
plugins,
|
||||
postProcessors,
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
*
|
||||
*/
|
||||
import { createProjectBuilder } from '@/generator/ProjectBuilder';
|
||||
import { createDiskPublisher } from '@/publisher/disk';
|
||||
import createIceJsProjectBuilder from '@/solutions/icejs';
|
||||
|
||||
export * from './types';
|
||||
@ -12,4 +13,7 @@ export default {
|
||||
solutions: {
|
||||
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 utils from '@/plugins/project/utils';
|
||||
|
||||
import { prettier } from '@/postprocessor';
|
||||
|
||||
export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
return createProjectBuilder({
|
||||
template,
|
||||
@ -56,5 +58,6 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
htmlEntry: [iceJsEntryHtml],
|
||||
packageJSON: [iceJsPackageJSON],
|
||||
},
|
||||
postProcessors: [prettier],
|
||||
});
|
||||
}
|
||||
|
||||
@ -141,3 +141,5 @@ export interface IProjectPlugins {
|
||||
export interface IProjectBuilder {
|
||||
generateProject(schema: IProjectSchema): Promise<IResultDir>;
|
||||
}
|
||||
|
||||
export type PostProcessor = (content: string, fileType: string) => string;
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"outDir": "lib",
|
||||
"target": "es5",
|
||||
"strictNullChecks": true,
|
||||
"inlineSources": false,
|
||||
"lib": ["es6"],
|
||||
"downlevelIteration": true,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"outDir": "./lib",
|
||||
"types": ["node"],
|
||||
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||
"baseUrl": "." /* Base directory to resolve non-absolute module names. */
|
||||
},
|
||||
"include": [
|
||||
"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": {
|
||||
"index": "src/index.jsx",
|
||||
"react-simulator-renderer": "../react-simulator-renderer/src/index.js"
|
||||
"index": "src/index.ts",
|
||||
"react-simulator-renderer": "../react-simulator-renderer/src/index.ts",
|
||||
"preview": "src/preview.ts"
|
||||
},
|
||||
"vendor": false,
|
||||
"devServer": {
|
||||
@ -15,7 +16,9 @@
|
||||
"@alifd/next": "window.Next"
|
||||
},
|
||||
"plugins": [
|
||||
["build-plugin-react-app"],
|
||||
[
|
||||
"build-plugin-react-app"
|
||||
],
|
||||
[
|
||||
"build-plugin-fusion",
|
||||
{
|
||||
@ -25,9 +28,11 @@
|
||||
[
|
||||
"build-plugin-moment-locales",
|
||||
{
|
||||
"locales": ["zh-cn"]
|
||||
"locales": [
|
||||
"zh-cn"
|
||||
]
|
||||
}
|
||||
],
|
||||
"./build.plugin.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
{
|
||||
"entry": {
|
||||
"lowcode-demo": "src/index.jsx"
|
||||
"lowcode-editor": "src/index.ts",
|
||||
"lowcode-preview": "src/preview.ts"
|
||||
},
|
||||
"vendor": false,
|
||||
"externals": {
|
||||
|
||||
@ -1,28 +1,39 @@
|
||||
{
|
||||
"name": "@ali/lowcode-demo",
|
||||
"version": "0.8.0",
|
||||
"version": "0.8.8",
|
||||
"private": true,
|
||||
"description": "低代码引擎 DEMO",
|
||||
"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": {
|
||||
"@ali/lowcode-editor-core": "^0.8",
|
||||
"@ali/lowcode-editor-core": "^0.8.4",
|
||||
"@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-settings-pane": "^0.8.0",
|
||||
"@ali/lowcode-plugin-outline-pane": "^0.8.0",
|
||||
"@ali/lowcode-plugin-undo-redo": "^0.8.0",
|
||||
"@ali/lowcode-plugin-designer": "^0.9.1",
|
||||
"@ali/lowcode-plugin-event-bind-dialog": "^0.8.0",
|
||||
"@ali/lowcode-plugin-outline-pane": "^0.8.7",
|
||||
"@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-light": "^0.1.0",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ali/iceluna-cli": "^0.0.16",
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@types/events": "^3.0.0",
|
||||
"@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 {
|
||||
version: '^1.0.2',
|
||||
module.exports = {
|
||||
skeleton: {
|
||||
config: {
|
||||
package: '@ali/lowcode-editor-skeleton',
|
||||
version: '^0.8.0'
|
||||
}
|
||||
},
|
||||
theme: {
|
||||
fusion: {
|
||||
package: '@alife/theme-lowcode-light',
|
||||
@ -22,7 +27,7 @@ export default {
|
||||
},
|
||||
config: {
|
||||
package: '@ali/lowcode-plugin-sample-logo',
|
||||
version: '1.0.0'
|
||||
version: '^0.8.0'
|
||||
},
|
||||
pluginProps: {
|
||||
logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png',
|
||||
@ -38,7 +43,7 @@ export default {
|
||||
},
|
||||
config: {
|
||||
package: '@ali/lowcode-plugin-undo-redo',
|
||||
version: '1.0.0'
|
||||
version: '^0.8.0'
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -57,7 +62,7 @@ export default {
|
||||
},
|
||||
config: {
|
||||
package: '@ali/lowcode-plugin-sample-preview',
|
||||
version: '1.0.0'
|
||||
version: '^0.8.0'
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -68,14 +73,14 @@ export default {
|
||||
props: {
|
||||
align: 'top',
|
||||
icon: 'zujianku',
|
||||
title: '组件库'
|
||||
title: '组件库',
|
||||
floatable: true,
|
||||
},
|
||||
config: {
|
||||
package: '@ali/iceluna-plugin-components-pane',
|
||||
version: '0.0.1'
|
||||
package: '@ali/lowcode-plugin-components-pane',
|
||||
version: '^0.8.0'
|
||||
},
|
||||
pluginProps: {
|
||||
disableAppComponent: true
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -83,12 +88,24 @@ export default {
|
||||
type: 'PanelIcon',
|
||||
props: {
|
||||
align: 'top',
|
||||
icon: 'dengpao',
|
||||
icon: 'shuxingkongjian',
|
||||
title: '大纲树'
|
||||
},
|
||||
config: {
|
||||
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: {}
|
||||
}
|
||||
@ -100,7 +117,7 @@ export default {
|
||||
props: {},
|
||||
config: {
|
||||
package: '@ali/lowcode-plugin-settings-pane',
|
||||
version: '^1.0.0'
|
||||
version: '^0.8.0'
|
||||
},
|
||||
pluginProps: {}
|
||||
}
|
||||
@ -110,7 +127,14 @@ export default {
|
||||
pluginKey: 'designer',
|
||||
config: {
|
||||
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 ReactDOM from 'react-dom';
|
||||
import Skeleton from '@ali/lowcode-editor-skeleton';
|
||||
import { registerSetters } from '@ali/lowcode-setters';
|
||||
import config from './config/skeleton';
|
||||
import components from './config/components';
|
||||
@ -10,7 +9,7 @@ import './global.scss';
|
||||
import './config/theme.scss';
|
||||
|
||||
registerSetters();
|
||||
|
||||
const Skeleton = components.LowcodeSkeleton;
|
||||
const LCE_CONTAINER = document.getElementById('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",
|
||||
"compilerOptions": {
|
||||
"jsx": "react",
|
||||
"target": "ES6"
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["src/*"],
|
||||
"exclude": ["node_modules", "build", "public"]
|
||||
"include": [
|
||||
"./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",
|
||||
"version": "0.8.1",
|
||||
"version": "0.9.1",
|
||||
"description": "Designer for Ali LowCode Engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,18 +15,18 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ali/lowcode-globals": "^0.9.1",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0",
|
||||
"@ali/lowcode-globals": "^0.8"
|
||||
"react-dom": "^16.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/medium-editor": "^5.0.3",
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@types/classnames": "^2.2.7",
|
||||
"@types/medium-editor": "^5.0.3",
|
||||
"@types/node": "^13.7.1",
|
||||
"@types/react": "^16",
|
||||
"@types/react-dom": "^16",
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"build-plugin-component": "^0.2.10"
|
||||
},
|
||||
"ava": {
|
||||
|
||||
@ -1,25 +1,27 @@
|
||||
.lc-insertion {
|
||||
position: absolute;
|
||||
top: -1.5px;
|
||||
top: -2px;
|
||||
left: 0;
|
||||
z-index: 12;
|
||||
pointer-events: none !important;
|
||||
background-color: var(--color-brand-light);
|
||||
height: 3px;
|
||||
height: 4px;
|
||||
|
||||
&.cover {
|
||||
top: 0;
|
||||
height: auto;
|
||||
width: auto;
|
||||
border: none;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
top: 0;
|
||||
left: -1.5px;
|
||||
width: 3px;
|
||||
left: -2px;
|
||||
width: 4px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
&.invalid {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
@ -20,11 +20,13 @@ import {
|
||||
getRectTarget,
|
||||
Rect,
|
||||
CanvasPoint,
|
||||
hotkey,
|
||||
} from '../designer';
|
||||
import { parseProps } from './utils/parse-props';
|
||||
import { isElement } from '@ali/lowcode-globals';
|
||||
import { ComponentMetadata } from '@ali/lowcode-globals';
|
||||
import { BuiltinSimulatorRenderer } from './renderer';
|
||||
import clipboard from '../designer/clipboard';
|
||||
|
||||
export interface LibraryItem {
|
||||
package: string;
|
||||
@ -196,6 +198,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
||||
// wait 准备 iframe 内容、依赖库注入
|
||||
const renderer = await createSimulator(this, iframe, vendors);
|
||||
|
||||
// TODO: !!! thinkof reload onload
|
||||
|
||||
// wait 业务组件被第一次消费,否则会渲染出错
|
||||
await this.componentsConsumer.waitFirstConsume();
|
||||
|
||||
@ -209,11 +213,17 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
||||
this._contentDocument = this._contentWindow.document;
|
||||
this.viewport.setScrollTarget(this._contentWindow);
|
||||
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() {
|
||||
// TODO: Thinkof move events control to simulator renderer
|
||||
// just listen special callback
|
||||
// because iframe maybe reload
|
||||
this.setupDragAndClick();
|
||||
this.setupHovering();
|
||||
}
|
||||
@ -786,6 +796,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
||||
const inline = el ? isChildInline(el) : false;
|
||||
const row = el ? isRowContainer(el.parentElement!) : false;
|
||||
const vertical = inline || row;
|
||||
|
||||
// TODO: fix type
|
||||
const near: any = {
|
||||
node: nearNode,
|
||||
|
||||
@ -1,9 +1,4 @@
|
||||
import {
|
||||
IconRemove,
|
||||
IconClone,
|
||||
IconPage,
|
||||
IconContainer,
|
||||
IconComponent,
|
||||
ComponentMetadata,
|
||||
NpmInfo,
|
||||
NodeData,
|
||||
@ -18,6 +13,11 @@ import {
|
||||
import { Node, NodeParent } from './document';
|
||||
import { Designer } from './designer';
|
||||
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 {
|
||||
if (!list) {
|
||||
|
||||
@ -5,6 +5,7 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
|
||||
}
|
||||
|
||||
try {
|
||||
// { componentsMap, componentsTree, ... }
|
||||
return JSON.parse(clipboardData.getData('text/plain'));
|
||||
} catch (error) {
|
||||
/*
|
||||
@ -17,11 +18,13 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
|
||||
};
|
||||
}
|
||||
*/
|
||||
// paste the text by div
|
||||
// TODO: open the parser implement
|
||||
return null;
|
||||
/*
|
||||
return {
|
||||
code: clipboardData.getData('text/plain'),
|
||||
maps: {},
|
||||
};
|
||||
};*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +36,7 @@ class Clipboard {
|
||||
this.isCopyPaster(e.target);
|
||||
}
|
||||
|
||||
isCopyPaster(el: any) {
|
||||
private isCopyPaster(el: any) {
|
||||
return this.copyPasters.includes(el);
|
||||
}
|
||||
|
||||
@ -57,6 +60,9 @@ class Clipboard {
|
||||
}
|
||||
|
||||
injectCopyPaster(document: Document) {
|
||||
if (this.copyPasters.find(x => x.ownerDocument === document)) {
|
||||
return;
|
||||
}
|
||||
const copyPaster = document.createElement<'textarea'>('textarea');
|
||||
copyPaster.style.cssText = 'position: relative;left: -9999px;';
|
||||
document.body.appendChild(copyPaster);
|
||||
@ -5,6 +5,7 @@ import BuiltinDragGhostComponent from './drag-ghost';
|
||||
import { Designer, DesignerProps } from './designer';
|
||||
import { ProjectView } from '../project';
|
||||
import './designer.less';
|
||||
import clipboard from './clipboard';
|
||||
|
||||
export class DesignerView extends Component<DesignerProps> {
|
||||
readonly designer: Designer;
|
||||
@ -32,6 +33,7 @@ export class DesignerView extends Component<DesignerProps> {
|
||||
if (onMount) {
|
||||
onMount(this.designer);
|
||||
}
|
||||
clipboard.injectCopyPaster(document)
|
||||
this.designer.postEvent('mount', this.designer);
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
autorun,
|
||||
} from '@ali/lowcode-globals';
|
||||
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 { INodeSelector } from '../simulator';
|
||||
import { Scroller, IScrollable } from './scroller';
|
||||
@ -19,6 +19,7 @@ import { ActiveTracker } from './active-tracker';
|
||||
import { Hovering } from './hovering';
|
||||
import { DropLocation, LocationData, isLocationChildrenDetail } from './location';
|
||||
import { OffsetObserver, createOffsetObserver } from './offset-observer';
|
||||
import { focusing } from './focusing';
|
||||
|
||||
export interface DesignerProps {
|
||||
className?: string;
|
||||
@ -40,7 +41,6 @@ export interface DesignerProps {
|
||||
}
|
||||
|
||||
export class Designer {
|
||||
// readonly hotkey: Hotkey;
|
||||
readonly dragon = new Dragon(this);
|
||||
readonly activeTracker = new ActiveTracker();
|
||||
readonly hovering = new Hovering();
|
||||
@ -156,6 +156,9 @@ export class Designer {
|
||||
this.postEvent('designer.init', this);
|
||||
setupSelection();
|
||||
setupHistory();
|
||||
|
||||
// TODO: 先简单实现,后期通过焦点赋值
|
||||
focusing.focusDesigner = this;
|
||||
}
|
||||
|
||||
postEvent(event: string, ...args: any[]) {
|
||||
@ -198,7 +201,7 @@ export class Designer {
|
||||
/**
|
||||
* 获得合适的插入位置
|
||||
*/
|
||||
getSuitableInsertion() {
|
||||
getSuitableInsertion(): { target: NodeParent; index?: number } | null {
|
||||
const activedDoc = this.project.currentDocument;
|
||||
if (!activedDoc) {
|
||||
return null;
|
||||
@ -296,7 +299,7 @@ export class Designer {
|
||||
}
|
||||
|
||||
setSchema(schema?: ProjectSchema) {
|
||||
this.project.setSchema(schema);
|
||||
this.project.load(schema);
|
||||
}
|
||||
|
||||
@obx.val private _componentMetasMap = new Map<string, ComponentMeta>();
|
||||
|
||||
@ -427,8 +427,9 @@ export class Dragon {
|
||||
};
|
||||
|
||||
const sourceSensor = getSourceSensor(dragObject);
|
||||
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
|
||||
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));
|
||||
if (!sensor) {
|
||||
// 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 {
|
||||
[key: number]: string;
|
||||
}
|
||||
import { Hotkey, isFormEvent } from '@ali/lowcode-globals';
|
||||
import { focusing } from './focusing';
|
||||
import { insertChildren } from '../document';
|
||||
import clipboard from './clipboard';
|
||||
|
||||
interface CtrlKeyMap {
|
||||
[key: string]: string;
|
||||
}
|
||||
export const hotkey = new Hotkey();
|
||||
|
||||
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;
|
||||
// hotkey binding
|
||||
hotkey.bind(['backspace', 'del'], (e: KeyboardEvent) => {
|
||||
const doc = focusing.focusDesigner?.currentDocument;
|
||||
if (isFormEvent(e) || !doc) {
|
||||
return;
|
||||
}
|
||||
// for non keypress events the special maps are needed
|
||||
if (MAP[keyCode]) {
|
||||
return MAP[keyCode];
|
||||
e.preventDefault();
|
||||
|
||||
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]) {
|
||||
return KEYCODE_MAP[keyCode];
|
||||
e.preventDefault();
|
||||
|
||||
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
|
||||
// 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();
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
interface KeypressEvent extends KeyboardEvent {
|
||||
type: 'keypress';
|
||||
}
|
||||
|
||||
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;
|
||||
/*
|
||||
const doc = getCurrentDocument();
|
||||
if (isFormEvent(e) || !doc || !(focusing.id === 'outline' || focusing.id === 'canvas')) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
*/
|
||||
|
||||
if (t.form || /^(INPUT|SELECT|TEXTAREA)$/.test(t.tagName)) {
|
||||
return true;
|
||||
const selected = doc.selection.getTopNodes(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;
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
clipboard.waitPasteData(e, ({ componentsTree }) => {
|
||||
if (componentsTree) {
|
||||
const { target, index } = designer.getSuitableInsertion() || {};
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (MAP.hasOwnProperty(key)) {
|
||||
REVERSE_MAP[MAP[key]] = key;
|
||||
const nodes = insertChildren(target, componentsTree, index);
|
||||
if (nodes) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ['+'];
|
||||
// command + z undo
|
||||
hotkey.bind(['command+z', 'ctrl+z'], (e) => {
|
||||
const his = focusing.focusDesigner?.currentHistory;
|
||||
if (isFormEvent(e) || !his) {
|
||||
return;
|
||||
}
|
||||
|
||||
combination = combination.replace(/\+{2}/g, '+plus');
|
||||
return combination.split('+');
|
||||
}
|
||||
e.preventDefault();
|
||||
his.back();
|
||||
});
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
// command + shift + z redo
|
||||
hotkey.bind(['command+y', 'ctrl+y', 'command+shift+z'], (e) => {
|
||||
const his = focusing.focusDesigner?.currentHistory;
|
||||
if (isFormEvent(e) || !his) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
// depending on what the key combination is
|
||||
// we will try to pick the best event for it
|
||||
action = pickBestAction(key, modifiers, action);
|
||||
his.forward();
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
hotkey.mount(window);
|
||||
|
||||
@ -86,7 +86,7 @@ export function isChildInline(child: Element | Text, win?: Window) {
|
||||
return true;
|
||||
}
|
||||
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) {
|
||||
|
||||
@ -59,6 +59,7 @@ export class DocumentModel {
|
||||
}
|
||||
|
||||
private _modalNode?: NodeParent;
|
||||
private _blank?: boolean;
|
||||
get modalNode() {
|
||||
return this._modalNode;
|
||||
}
|
||||
@ -67,7 +68,7 @@ export class DocumentModel {
|
||||
return this.modalNode || this.rootNode;
|
||||
}
|
||||
|
||||
constructor(readonly project: Project, schema: RootSchema) {
|
||||
constructor(readonly project: Project, schema?: RootSchema) {
|
||||
autorun(() => {
|
||||
this.nodes.forEach((item) => {
|
||||
if (item.parent == null && item !== this.rootNode) {
|
||||
@ -75,7 +76,16 @@ export class DocumentModel {
|
||||
}
|
||||
});
|
||||
}, true);
|
||||
this.rootNode = this.createRootNode(schema);
|
||||
|
||||
if (!schema) {
|
||||
this._blank = true;
|
||||
}
|
||||
|
||||
this.rootNode = this.createRootNode(schema || {
|
||||
componentName: 'Page',
|
||||
fileName: ''
|
||||
});
|
||||
|
||||
this.history = new History(
|
||||
() => this.schema,
|
||||
(schema) => this.import(schema as RootSchema, true),
|
||||
@ -83,6 +93,10 @@ export class DocumentModel {
|
||||
this.setupListenActiveNodes();
|
||||
}
|
||||
|
||||
@computed isBlank() {
|
||||
return this._blank && !this.isModified();
|
||||
}
|
||||
|
||||
readonly designer = this.project.designer;
|
||||
|
||||
/**
|
||||
@ -295,6 +309,7 @@ export class DocumentModel {
|
||||
}
|
||||
|
||||
private mountSimulator(simulator: ISimulatorHost) {
|
||||
// TODO: 多设备 simulator 支持
|
||||
this._simulator = simulator;
|
||||
// TODO: emit simulator mounted
|
||||
}
|
||||
@ -386,7 +401,8 @@ export class DocumentModel {
|
||||
* 从项目中移除
|
||||
*/
|
||||
remove() {
|
||||
// todo:
|
||||
// this.project.removeDocument(this);
|
||||
// todo: ...
|
||||
}
|
||||
|
||||
purge() {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { IconBase, IconProps } from "./icon-base";
|
||||
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||
|
||||
export function IconClone(props: IconProps) {
|
||||
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"/>
|
||||
</IconBase>
|
||||
</SVGIcon>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { IconBase, IconProps } from "./icon-base";
|
||||
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||
|
||||
export function IconComponent(props: IconProps) {
|
||||
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" />
|
||||
</IconBase>
|
||||
</SVGIcon>
|
||||
);
|
||||
}
|
||||
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) {
|
||||
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="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';
|
||||
@ -1,10 +1,10 @@
|
||||
import { IconBase, IconProps } from "./icon-base";
|
||||
import { SVGIcon, IconProps } from "@ali/lowcode-globals";
|
||||
|
||||
export function IconHidden(props: IconProps) {
|
||||
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" />
|
||||
</IconBase>
|
||||
</SVGIcon>
|
||||
);
|
||||
}
|
||||
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) {
|
||||
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="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" />
|
||||
</IconBase>
|
||||
</SVGIcon>
|
||||
);
|
||||
}
|
||||
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) {
|
||||
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" />
|
||||
</IconBase>
|
||||
</SVGIcon>
|
||||
);
|
||||
}
|
||||
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) {
|
||||
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="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",
|
||||
"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": "复制",
|
||||
"remove": "删除",
|
||||
"Condition Group": "条件组"
|
||||
"Condition Group": "条件组",
|
||||
"No opened document": "没有打开的页面,请选择页面打开编辑"
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import { Component } from 'react';
|
||||
import { observer } from '@ali/lowcode-globals';
|
||||
import { Designer } from '../designer';
|
||||
import { DocumentView } from '../document';
|
||||
import { intl } from '../locale';
|
||||
import './project.less';
|
||||
|
||||
@observer
|
||||
@ -9,14 +10,14 @@ export class ProjectView extends Component<{ designer: Designer }> {
|
||||
render() {
|
||||
const { designer } = this.props;
|
||||
// TODO: support splitview
|
||||
const opens = designer.project.documents.filter((doc) => doc.opened);
|
||||
return (
|
||||
<div className="lc-project">
|
||||
{designer.project.documents.map(doc => {
|
||||
if (!doc.opened) {
|
||||
return null;
|
||||
}
|
||||
return <DocumentView key={doc.id} document={doc} />;
|
||||
})}
|
||||
{opens.length > 0 ? (
|
||||
opens.map((doc) => <DocumentView key={doc.id} document={doc} />)
|
||||
) : (
|
||||
<div className="lc-project-empty">{intl('No opened document')}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -4,6 +4,14 @@
|
||||
right: 0;
|
||||
width: 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 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@ -14,11 +14,11 @@ export class Project {
|
||||
// TODO: 考虑项目级别 History
|
||||
|
||||
constructor(readonly designer: Designer, schema?: ProjectSchema) {
|
||||
this.setSchema(schema);
|
||||
this.load(schema);
|
||||
}
|
||||
|
||||
@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 {
|
||||
return {
|
||||
...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
|
||||
*
|
||||
* @param autoOpen true 自动打开文档 string 指定打开的文件
|
||||
*/
|
||||
setSchema(schema?: ProjectSchema) {
|
||||
load(schema?: ProjectSchema, autoOpen?: boolean | string) {
|
||||
this.unload();
|
||||
// load new document
|
||||
this.data = {
|
||||
version: '1.0.0',
|
||||
componentsMap: [],
|
||||
componentsTree: [],
|
||||
...schema,
|
||||
};
|
||||
if (this.documents.length > 0) {
|
||||
this.documents.forEach(doc => doc.purge());
|
||||
this.documents.length = 0;
|
||||
|
||||
if (autoOpen) {
|
||||
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,
|
||||
): 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') {
|
||||
const got = this.documents.find(item => item.fileName === doc);
|
||||
const got = this.documents.find((item) => item.fileName === doc);
|
||||
if (got) {
|
||||
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) {
|
||||
doc = new DocumentModel(this, data);
|
||||
this.documents.push(doc);
|
||||
@ -113,7 +137,7 @@ export class Project {
|
||||
}
|
||||
|
||||
checkExclusive(actived: DocumentModel) {
|
||||
this.documents.forEach(doc => {
|
||||
this.documents.forEach((doc) => {
|
||||
if (doc !== actived) {
|
||||
doc.suspense();
|
||||
}
|
||||
@ -122,7 +146,7 @@ export class Project {
|
||||
}
|
||||
|
||||
closeOthers(opened: DocumentModel) {
|
||||
this.documents.forEach(doc => {
|
||||
this.documents.forEach((doc) => {
|
||||
if (doc !== opened) {
|
||||
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",
|
||||
"version": "0.8.0",
|
||||
"version": "0.8.4",
|
||||
"description": "alibaba lowcode editor core",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -20,15 +20,15 @@
|
||||
],
|
||||
"author": "xiayang.xy",
|
||||
"dependencies": {
|
||||
"@alifd/next": "1.x",
|
||||
"debug": "^4.1.1",
|
||||
"events": "^3.1.0",
|
||||
"intl-messageformat": "^8.3.1",
|
||||
"lodash": "^4.17.15",
|
||||
"prop-types": "^15.5.8",
|
||||
"store": "^2.0.12",
|
||||
"whatwg-fetch": "^3.0.0",
|
||||
"react": "^16.8.0",
|
||||
"@alifd/next": "1.x"
|
||||
"store": "^2.0.12",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.3",
|
||||
|
||||
@ -11,6 +11,8 @@ import {
|
||||
PluginSet,
|
||||
} from './definitions';
|
||||
|
||||
import pluginFactory from './pluginFactory';
|
||||
|
||||
import * as editorUtils from './utils';
|
||||
|
||||
const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
|
||||
@ -92,7 +94,10 @@ export default class Editor extends EventEmitter {
|
||||
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
|
||||
super();
|
||||
this.config = config;
|
||||
this.components = components;
|
||||
this.components = {};
|
||||
Object.entries(components).forEach(([key, value]): void => {
|
||||
this.components[key] = pluginFactory(value);
|
||||
});
|
||||
this.utils = { ...editorUtils, ...utils };
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"target": "es6",
|
||||
"jsx": "react"
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"./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",
|
||||
"version": "0.8.0",
|
||||
"version": "0.8.5",
|
||||
"description": "alibaba lowcode editor skeleton",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -20,7 +20,7 @@
|
||||
],
|
||||
"author": "xiayang.xy",
|
||||
"dependencies": {
|
||||
"@ali/lowcode-editor-core": "^0.8.0",
|
||||
"@ali/lowcode-editor-core": "^0.8.4",
|
||||
"@alifd/next": "^1.x",
|
||||
"prop-types": "^15.5.8",
|
||||
"react": "^16.8.1",
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"target": "es6",
|
||||
"jsx": "react"
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"./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",
|
||||
"version": "0.8.0",
|
||||
"version": "0.9.1",
|
||||
"description": "Globals api for Ali lowCode engine",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
"files": [
|
||||
@ -14,6 +15,16 @@
|
||||
"test": "ava",
|
||||
"test:snapshot": "ava --update-snapshots"
|
||||
},
|
||||
"ava": {
|
||||
"compileEnhancements": false,
|
||||
"extensions": [
|
||||
"ts"
|
||||
],
|
||||
"require": [
|
||||
"ts-node/register"
|
||||
],
|
||||
"snapshotDir": "test/fixtures/__snapshots__"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@recore/obx": "^1.0.8",
|
||||
@ -23,26 +34,15 @@
|
||||
"react-dom": "^16.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@types/classnames": "^2.2.7",
|
||||
"@types/node": "^13.7.1",
|
||||
"@types/react": "^16",
|
||||
"@types/react-dom": "^16",
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"build-plugin-component": "^0.2.11",
|
||||
"build-plugin-fusion": "^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": {
|
||||
"registry": "https://registry.npm.alibaba-inc.com"
|
||||
}
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './tip';
|
||||
export * from './title';
|
||||
export * from './svg-icon';
|
||||
|
||||
@ -16,7 +16,7 @@ export interface IconProps {
|
||||
style?: object;
|
||||
}
|
||||
|
||||
export function IconBase({
|
||||
export function SVGIcon({
|
||||
fill,
|
||||
size = 'medium',
|
||||
viewBox,
|
||||
@ -16,7 +16,7 @@ function findTip(target: HTMLElement | null): TipOptions | null {
|
||||
if (target.dataset && target.dataset.tip) {
|
||||
return {
|
||||
children: target.dataset.tip,
|
||||
direction: target.dataset.direction || target.dataset.dir,
|
||||
direction: (target.dataset.direction || target.dataset.dir) as any,
|
||||
theme: target.dataset.theme,
|
||||
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 './components';
|
||||
export * from './utils';
|
||||
export * from './icons';
|
||||
export * from './types';
|
||||
export * from './di';
|
||||
export * from './obx';
|
||||
|
||||
@ -5,7 +5,7 @@ export interface TipConfig {
|
||||
className?: string;
|
||||
children?: I18nData | ReactNode;
|
||||
theme?: string;
|
||||
direction?: string; // 'n|s|w|e|top|bottom|left|right';
|
||||
direction?: 'top' | 'bottom' | 'left' | 'right';
|
||||
}
|
||||
|
||||
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 './get-public-path';
|
||||
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",
|
||||
"version": "0.8.0",
|
||||
"version": "0.9.0",
|
||||
"description": "material parser for Ali lowCode engine",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -20,6 +20,7 @@
|
||||
"jest-watch-typeahead": "^0.3.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"json-schema-to-typescript": "^8.2.0",
|
||||
"tslib": "^1.11.1",
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"scripts": {
|
||||
@ -47,6 +48,7 @@
|
||||
"@babel/parser": "^7.8.4",
|
||||
"@babel/traverse": "^7.8.4",
|
||||
"@babel/types": "^7.8.3",
|
||||
"ast-types": "^0.13.3",
|
||||
"cross-spawn-promise": "^0.10.2",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
@ -54,5 +56,8 @@
|
||||
"react-docgen": "^5.3.0",
|
||||
"semver": "^7.1.3",
|
||||
"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);
|
||||
fs.writeFileSync(JsonPath, JSON.stringify(schema, null, 2), 'utf-8');
|
||||
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);
|
||||
console.log('schema.d.ts is successfully generated');
|
||||
} 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