Merge branch 'master' into polyfill/vision

This commit is contained in:
kangwei 2020-04-01 17:07:57 +08:00
commit eb5f0871bb
1127 changed files with 105619 additions and 9294 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ packages/*/dist/
package-lock.json package-lock.json
yarn.lock yarn.lock
deploy-space/packages deploy-space/packages
deploy-space/.env
# IDE # IDE

View File

@ -11,11 +11,12 @@
#### 跑起来: #### 跑起来:
- `npm run setup` - `npm run setup`
- `npm start`
#### 开发提交: #### 开发提交:
- `git add <your-files>` - `git add <your-files>`
- `npm run commit` - `npm run commit` # 在根目录
## 发布 ## 发布

View File

@ -4,7 +4,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" /> <meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>LowCodeEngine DEMO</title> <title>LowCodeEngine Editor DEMO</title>
<link rel="shortcut icon" href="./favicon.png" /> <link rel="shortcut icon" href="./favicon.png" />
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script> <script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script> <script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
@ -16,7 +16,7 @@
<!-- lowcode engine globals --> <!-- lowcode engine globals -->
<link rel="stylesheet" href="./globals.css" /> <link rel="stylesheet" href="./globals.css" />
<!-- lowcode engine app --> <!-- lowcode engine app -->
<link rel="stylesheet" href="./lowcode-demo.css" /> <link rel="stylesheet" href="./lowcode-editor.css" />
</head> </head>
<body> <body>
@ -24,6 +24,6 @@
<!-- lowcode engine globals --> <!-- lowcode engine globals -->
<script src="./globals.js"></script> <script src="./globals.js"></script>
<!-- lowcode engine app --> <!-- lowcode engine app -->
<script src="./lowcode-demo.js"></script> <script src="./lowcode-editor.js"></script>
</body> </body>
</html> </html>

View File

@ -4,7 +4,8 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" /> <meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>LowCodeEngine DEMO</title> <title>LowCodeEngine Preview DEMO</title>
<link rel="shortcut icon" href="./favicon.png" />
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script> <script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script> <script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script> <script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
@ -13,9 +14,10 @@
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css"> <link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css">
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script> <script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
<link rel="stylesheet" href="./lowcode-preview.css" />
</head> </head>
<body> <body>
<div id="lce-container"></div> <script src="./lowcode-preview.js"></script>
</body> </body>
</html> </html>

View File

@ -1,9 +1,5 @@
{ {
"private": true, "private": true,
"dependencies": {
"tslib": "^1.9.3",
"typescript": "^3.2.2"
},
"workspaces": { "workspaces": {
"packages": [ "packages": [
"packages/*" "packages/*"
@ -13,5 +9,8 @@
"**/@alife/theme-lowcode-*" "**/@alife/theme-lowcode-*"
] ]
}, },
"engines" : { "node" : "^10" } "dependencies": {
"tslib": "^1.11.1",
"typescript": "^3.8.3"
}
} }

View File

@ -5,7 +5,7 @@
// Target latest version of ECMAScript. // Target latest version of ECMAScript.
"target": "esnext", "target": "esnext",
// Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
"module": "commonjs", "module": "esnext",
// Search under node_modules for non-relative imports. // Search under node_modules for non-relative imports.
"moduleResolution": "node", "moduleResolution": "node",
// Process & infer types from .js files. // Process & infer types from .js files.
@ -34,6 +34,7 @@
"resolveJsonModule": true, "resolveJsonModule": true,
// skip type checking of declaration files // skip type checking of declaration files
"skipLibCheck": true, "skipLibCheck": true,
"outDir": "lib"
}, },
"exclude": ["**/test", "**/lib", "**/es", "node_modules"] "exclude": ["**/test", "**/lib", "**/es", "node_modules"]
} }

View File

@ -10,7 +10,7 @@
- 使用 `camelCase` 为属性或本地变量命名 - 使用 `camelCase` 为属性或本地变量命名
- 不要为私有属性名添加 `_` 前缀 - 不要为私有属性名添加 `_` 前缀
- 尽可能使用完整的单词拼写命名 - 尽可能使用完整的单词拼写命名
- 文件夹命名统一使用小写 - 文件夹/文件命名统一使用小写 `get-custom-data.ts`
### 组件 ### 组件

View File

@ -1,7 +1,7 @@
{ {
"lerna": "2.11.0", "lerna": "2.11.0",
"version": "independent", "version": "independent",
"npmClient": "yarn", "npmClient": "tyarn",
"registry": "http://registry.npm.alibaba-inc.com", "registry": "http://registry.npm.alibaba-inc.com",
"useWorkspaces": true, "useWorkspaces": true,
"packages": [ "packages": [

View File

@ -1,14 +1,34 @@
{ {
"private": true, "private": true,
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/css-modules-typescript-loader",
"**/@alife/theme-lowcode-*"
]
},
"scripts": { "scripts": {
"build": "lerna run build --stream",
"clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build", "clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
"commit": "git-cz",
"pub": "lerna publish",
"setup": "./scripts/setup.sh", "setup": "./scripts/setup.sh",
"start": "./scripts/start.sh", "start": "./scripts/start.sh",
"build": "lerna run build", "test": "lerna run test --stream",
"test": "lerna run test", "test:snapshot": "lerna run test:snapshot"
"test:snapshot": "lerna run test:snapshot", },
"pub": "lerna publish", "lint-staged": {
"commit": "git-cz" "*.{tsx,ts}": [
"eslint --quiet",
"git add"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
}, },
"devDependencies": { "devDependencies": {
"@ali/lowcode-config": "^2.0.5", "@ali/lowcode-config": "^2.0.5",
@ -26,25 +46,7 @@
"tslib": "^1.9.3", "tslib": "^1.9.3",
"typescript": "^3.2.2" "typescript": "^3.2.2"
}, },
"engines" : { "node" : "^10" }, "engines": {
"workspaces": { "node": ">=10.0.0"
"packages": [
"packages/*"
],
"nohoist": [
"**/css-modules-typescript-loader",
"**/@alife/theme-lowcode-*"
]
},
"lint-staged": {
"*.{tsx,ts}": [
"eslint --quiet",
"git add"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
} }
} }

View File

@ -0,0 +1,52 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
<a name="0.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

View File

@ -1,27 +1,34 @@
{ {
"name": "@ali/lowcode-engine-code-generator", "name": "@ali/lowcode-code-generator",
"version": "0.8.0", "version": "0.8.4",
"description": "出码引擎 for LowCode Engine", "description": "出码引擎 for LowCode Engine",
"main": "lib/index.js", "main": "lib/index.js",
"files": [ "files": [
"lib" "lib"
], ],
"scripts": { "scripts": {
"build": "rimraf lib && tsc", "compile": "rimraf lib && tsc",
"build": "rimraf lib && webpack",
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts", "demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
"test": "ava" "test": "ava"
}, },
"dependencies": { "dependencies": {
"@ali/am-eslint-config": "*", "@ali/am-eslint-config": "*",
"@types/prettier": "^1.19.1",
"change-case": "^3.1.0", "change-case": "^3.1.0",
"prettier": "^2.0.2",
"short-uuid": "^3.1.1" "short-uuid": "^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"ava": "^1.0.1", "ava": "^1.0.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"ts-loader": "^6.2.2",
"ts-node": "^7.0.1", "ts-node": "^7.0.1",
"tsconfig-paths": "^3.9.0", "tsconfig-paths": "^3.9.0",
"typescript": "^3.8.3" "tsconfig-paths-webpack-plugin": "^3.2.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",
"webpack-node-externals": "^1.7.2"
}, },
"ava": { "ava": {
"compileEnhancements": false, "compileEnhancements": false,

View File

@ -5,6 +5,7 @@ import {
ICompiledModule, ICompiledModule,
IModuleBuilder, IModuleBuilder,
IResultFile, IResultFile,
PostProcessor,
} from '../types'; } from '../types';
import { COMMON_SUB_MODULE_NAME } from '../const/generator'; import { COMMON_SUB_MODULE_NAME } from '../const/generator';
@ -17,9 +18,11 @@ import ResultFile from '../model/ResultFile';
export function createModuleBuilder( export function createModuleBuilder(
options: { options: {
plugins: BuilderComponentPlugin[]; plugins: BuilderComponentPlugin[];
postProcessors: PostProcessor[];
mainFileName?: string; mainFileName?: string;
} = { } = {
plugins: [], plugins: [],
postProcessors: [],
}, },
): IModuleBuilder { ): IModuleBuilder {
const chunkGenerator = new ChunkBuilder(options.plugins); const chunkGenerator = new ChunkBuilder(options.plugins);
@ -33,7 +36,7 @@ export function createModuleBuilder(
); );
} }
const files: IResultFile[] = []; let files: IResultFile[] = [];
const { chunks } = await chunkGenerator.run(input); const { chunks } = await chunkGenerator.run(input);
chunks.forEach(fileChunkList => { chunks.forEach(fileChunkList => {
@ -46,6 +49,18 @@ export function createModuleBuilder(
files.push(file); files.push(file);
}); });
if (options.postProcessors.length > 0) {
files = files.map(file => {
let content = file.content;
const type = file.ext;
options.postProcessors.forEach(processer => {
content = processer(content, type);
});
return new ResultFile(file.name, type, content);
});
}
return { return {
files, files,
}; };

View File

@ -8,10 +8,11 @@ import {
IResultDir, IResultDir,
IResultFile, IResultFile,
ISchemaParser, ISchemaParser,
PostProcessor,
} from '../types'; } from '../types';
import ResultDir from '@/model/ResultDir'; import ResultDir from '@/model/ResultDir';
import SchemaParser from '@/parse/SchemaParser'; import SchemaParser from '@/parser/SchemaParser';
import { createModuleBuilder } from '@/generator/ModuleBuilder'; import { createModuleBuilder } from '@/generator/ModuleBuilder';
@ -40,16 +41,20 @@ function getDirFromRoot(root: IResultDir, path: string[]): IResultDir {
export class ProjectBuilder implements IProjectBuilder { export class ProjectBuilder implements IProjectBuilder {
private template: IProjectTemplate; private template: IProjectTemplate;
private plugins: IProjectPlugins; private plugins: IProjectPlugins;
private postProcessors: PostProcessor[];
constructor({ constructor({
template, template,
plugins, plugins,
postProcessors,
}: { }: {
template: IProjectTemplate; template: IProjectTemplate;
plugins: IProjectPlugins; plugins: IProjectPlugins;
postProcessors: PostProcessor[];
}) { }) {
this.template = template; this.template = template;
this.plugins = plugins; this.plugins = plugins;
this.postProcessors = postProcessors;
} }
public async generateProject(schema: IProjectSchema): Promise<IResultDir> { public async generateProject(schema: IProjectSchema): Promise<IResultDir> {
@ -212,45 +217,57 @@ export class ProjectBuilder implements IProjectBuilder {
builders.components = createModuleBuilder({ builders.components = createModuleBuilder({
plugins: this.plugins.components, plugins: this.plugins.components,
postProcessors: this.postProcessors,
});
builders.pages = createModuleBuilder({
plugins: this.plugins.pages,
postProcessors: this.postProcessors,
}); });
builders.pages = createModuleBuilder({ plugins: this.plugins.pages });
builders.router = createModuleBuilder({ builders.router = createModuleBuilder({
plugins: this.plugins.router, plugins: this.plugins.router,
mainFileName: this.template.slots.router.fileName, mainFileName: this.template.slots.router.fileName,
postProcessors: this.postProcessors,
}); });
builders.entry = createModuleBuilder({ builders.entry = createModuleBuilder({
plugins: this.plugins.entry, plugins: this.plugins.entry,
mainFileName: this.template.slots.entry.fileName, mainFileName: this.template.slots.entry.fileName,
postProcessors: this.postProcessors,
}); });
builders.globalStyle = createModuleBuilder({ builders.globalStyle = createModuleBuilder({
plugins: this.plugins.globalStyle, plugins: this.plugins.globalStyle,
mainFileName: this.template.slots.globalStyle.fileName, mainFileName: this.template.slots.globalStyle.fileName,
postProcessors: this.postProcessors,
}); });
builders.htmlEntry = createModuleBuilder({ builders.htmlEntry = createModuleBuilder({
plugins: this.plugins.htmlEntry, plugins: this.plugins.htmlEntry,
mainFileName: this.template.slots.htmlEntry.fileName, mainFileName: this.template.slots.htmlEntry.fileName,
postProcessors: this.postProcessors,
}); });
builders.packageJSON = createModuleBuilder({ builders.packageJSON = createModuleBuilder({
plugins: this.plugins.packageJSON, plugins: this.plugins.packageJSON,
mainFileName: this.template.slots.packageJSON.fileName, mainFileName: this.template.slots.packageJSON.fileName,
postProcessors: this.postProcessors,
}); });
if (this.template.slots.constants && this.plugins.constants) { if (this.template.slots.constants && this.plugins.constants) {
builders.constants = createModuleBuilder({ builders.constants = createModuleBuilder({
plugins: this.plugins.constants, plugins: this.plugins.constants,
mainFileName: this.template.slots.constants.fileName, mainFileName: this.template.slots.constants.fileName,
postProcessors: this.postProcessors,
}); });
} }
if (this.template.slots.utils && this.plugins.utils) { if (this.template.slots.utils && this.plugins.utils) {
builders.utils = createModuleBuilder({ builders.utils = createModuleBuilder({
plugins: this.plugins.utils, plugins: this.plugins.utils,
mainFileName: this.template.slots.utils.fileName, mainFileName: this.template.slots.utils.fileName,
postProcessors: this.postProcessors,
}); });
} }
if (this.template.slots.i18n && this.plugins.i18n) { if (this.template.slots.i18n && this.plugins.i18n) {
builders.i18n = createModuleBuilder({ builders.i18n = createModuleBuilder({
plugins: this.plugins.i18n, plugins: this.plugins.i18n,
mainFileName: this.template.slots.i18n.fileName, mainFileName: this.template.slots.i18n.fileName,
postProcessors: this.postProcessors,
}); });
} }
@ -261,12 +278,15 @@ export class ProjectBuilder implements IProjectBuilder {
export function createProjectBuilder({ export function createProjectBuilder({
template, template,
plugins, plugins,
postProcessors,
}: { }: {
template: IProjectTemplate; template: IProjectTemplate;
plugins: IProjectPlugins; plugins: IProjectPlugins;
postProcessors: PostProcessor[];
}): IProjectBuilder { }): IProjectBuilder {
return new ProjectBuilder({ return new ProjectBuilder({
template, template,
plugins, plugins,
postProcessors,
}); });
} }

View File

@ -3,6 +3,7 @@
* *
*/ */
import { createProjectBuilder } from '@/generator/ProjectBuilder'; import { createProjectBuilder } from '@/generator/ProjectBuilder';
import { createDiskPublisher } from '@/publisher/disk';
import createIceJsProjectBuilder from '@/solutions/icejs'; import createIceJsProjectBuilder from '@/solutions/icejs';
export * from './types'; export * from './types';
@ -12,4 +13,7 @@ export default {
solutions: { solutions: {
icejs: createIceJsProjectBuilder, icejs: createIceJsProjectBuilder,
}, },
publishers: {
disk: createDiskPublisher,
},
}; };

View File

@ -0,0 +1,3 @@
import prettier from './prettier';
export { prettier };

View 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;

View File

@ -21,6 +21,8 @@ import template from '@/plugins/project/framework/icejs/template';
import i18n from '@/plugins/project/i18n'; import i18n from '@/plugins/project/i18n';
import utils from '@/plugins/project/utils'; import utils from '@/plugins/project/utils';
import { prettier } from '@/postprocessor';
export default function createIceJsProjectBuilder(): IProjectBuilder { export default function createIceJsProjectBuilder(): IProjectBuilder {
return createProjectBuilder({ return createProjectBuilder({
template, template,
@ -56,5 +58,6 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
htmlEntry: [iceJsEntryHtml], htmlEntry: [iceJsEntryHtml],
packageJSON: [iceJsPackageJSON], packageJSON: [iceJsPackageJSON],
}, },
postProcessors: [prettier],
}); });
} }

View File

@ -141,3 +141,5 @@ export interface IProjectPlugins {
export interface IProjectBuilder { export interface IProjectBuilder {
generateProject(schema: IProjectSchema): Promise<IResultDir>; generateProject(schema: IProjectSchema): Promise<IResultDir>;
} }
export type PostProcessor = (content: string, fileType: string) => string;

View File

@ -1,14 +1,17 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"target": "es6", "target": "es5",
"module": "commonjs", "strictNullChecks": true,
"outDir": "lib", "inlineSources": false,
"lib": ["es6"],
"downlevelIteration": true,
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
}, },
"outDir": "./lib",
"types": ["node"], "types": ["node"],
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */ "baseUrl": "." /* Base directory to resolve non-absolute module names. */
}, },
"include": [ "include": [
"src/**/*" "src/**/*"

View 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
};

View 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

View File

@ -1,7 +1,8 @@
{ {
"entry": { "entry": {
"index": "src/index.jsx", "index": "src/index.ts",
"react-simulator-renderer": "../react-simulator-renderer/src/index.js" "react-simulator-renderer": "../react-simulator-renderer/src/index.ts",
"preview": "src/preview.ts"
}, },
"vendor": false, "vendor": false,
"devServer": { "devServer": {
@ -15,7 +16,9 @@
"@alifd/next": "window.Next" "@alifd/next": "window.Next"
}, },
"plugins": [ "plugins": [
["build-plugin-react-app"], [
"build-plugin-react-app"
],
[ [
"build-plugin-fusion", "build-plugin-fusion",
{ {
@ -25,7 +28,9 @@
[ [
"build-plugin-moment-locales", "build-plugin-moment-locales",
{ {
"locales": ["zh-cn"] "locales": [
"zh-cn"
]
} }
], ],
"./build.plugin.js" "./build.plugin.js"

View File

@ -1,6 +1,7 @@
{ {
"entry": { "entry": {
"lowcode-demo": "src/index.jsx" "lowcode-editor": "src/index.ts",
"lowcode-preview": "src/preview.ts"
}, },
"vendor": false, "vendor": false,
"externals": { "externals": {

View File

@ -1,28 +1,39 @@
{ {
"name": "@ali/lowcode-demo", "name": "@ali/lowcode-demo",
"version": "0.8.0", "version": "0.8.8",
"private": true,
"description": "低代码引擎 DEMO", "description": "低代码引擎 DEMO",
"scripts": { "scripts": {
"start": "build-scripts start", "cloud-build": "build-scripts build --config cloud-build.json",
"cloud-build": "build-scripts build --config cloud-build.json" "gen": "npm run genSkeleton && tyarn",
"genSkeleton": "iceluna gen lowcode -c ./skeleton.config.js -t ./src/editor/config",
"start": "build-scripts start"
}, },
"config": {},
"dependencies": { "dependencies": {
"@ali/lowcode-editor-core": "^0.8", "@ali/lowcode-editor-core": "^0.8.4",
"@ali/lowcode-editor-skeleton": "^0.8.0", "@ali/lowcode-editor-skeleton": "^0.8.0",
"@ali/lowcode-plugin-designer": "^0.8.0",
"@ali/lowcode-setters": "^0.8.0",
"@ali/lowcode-plugin-components-pane": "^0.8.0", "@ali/lowcode-plugin-components-pane": "^0.8.0",
"@ali/lowcode-plugin-settings-pane": "^0.8.0", "@ali/lowcode-plugin-designer": "^0.9.1",
"@ali/lowcode-plugin-outline-pane": "^0.8.0", "@ali/lowcode-plugin-event-bind-dialog": "^0.8.0",
"@ali/lowcode-plugin-undo-redo": "^0.8.0", "@ali/lowcode-plugin-outline-pane": "^0.8.7",
"@ali/lowcode-plugin-sample-logo": "^0.8.0", "@ali/lowcode-plugin-sample-logo": "^0.8.0",
"@ali/lowcode-plugin-sample-preview": "^0.8.0", "@ali/lowcode-plugin-sample-preview": "^0.8.6",
"@ali/lowcode-plugin-settings-pane": "^0.8.8",
"@ali/lowcode-plugin-undo-redo": "^0.8.0",
"@ali/lowcode-plugin-variable-bind-dialog": "^0.8.2",
"@ali/lowcode-plugin-zh-en": "^0.8.6",
"@ali/lowcode-react-renderer": "^0.8.4",
"@ali/lowcode-runtime": "^0.8.7",
"@ali/lowcode-setters": "^0.8.6",
"@alifd/next": "^1.19.12",
"@alife/theme-lowcode-dark": "^0.1.0", "@alife/theme-lowcode-dark": "^0.1.0",
"@alife/theme-lowcode-light": "^0.1.0", "@alife/theme-lowcode-light": "^0.1.0",
"react": "^16.8.1", "react": "^16.8.1",
"react-dom": "^16.8.1" "react-dom": "^16.8.1"
}, },
"devDependencies": { "devDependencies": {
"@ali/iceluna-cli": "^0.0.16",
"@alib/build-scripts": "^0.1.18", "@alib/build-scripts": "^0.1.18",
"@types/events": "^3.0.0", "@types/events": "^3.0.0",
"@types/react": "^16.8.3", "@types/react": "^16.8.3",

View 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>

View File

@ -1,5 +1,10 @@
export default { module.exports = {
version: '^1.0.2', skeleton: {
config: {
package: '@ali/lowcode-editor-skeleton',
version: '^0.8.0'
}
},
theme: { theme: {
fusion: { fusion: {
package: '@alife/theme-lowcode-light', package: '@alife/theme-lowcode-light',
@ -22,7 +27,7 @@ export default {
}, },
config: { config: {
package: '@ali/lowcode-plugin-sample-logo', package: '@ali/lowcode-plugin-sample-logo',
version: '1.0.0' version: '^0.8.0'
}, },
pluginProps: { pluginProps: {
logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png', logo: 'https://img.alicdn.com/tfs/TB1hoI9x1H2gK0jSZFEXXcqMpXa-146-40.png',
@ -38,7 +43,7 @@ export default {
}, },
config: { config: {
package: '@ali/lowcode-plugin-undo-redo', package: '@ali/lowcode-plugin-undo-redo',
version: '1.0.0' version: '^0.8.0'
} }
}, },
{ {
@ -57,7 +62,7 @@ export default {
}, },
config: { config: {
package: '@ali/lowcode-plugin-sample-preview', package: '@ali/lowcode-plugin-sample-preview',
version: '1.0.0' version: '^0.8.0'
} }
} }
], ],
@ -68,14 +73,14 @@ export default {
props: { props: {
align: 'top', align: 'top',
icon: 'zujianku', icon: 'zujianku',
title: '组件库' title: '组件库',
floatable: true,
}, },
config: { config: {
package: '@ali/iceluna-plugin-components-pane', package: '@ali/lowcode-plugin-components-pane',
version: '0.0.1' version: '^0.8.0'
}, },
pluginProps: { pluginProps: {
disableAppComponent: true
} }
}, },
{ {
@ -83,12 +88,24 @@ export default {
type: 'PanelIcon', type: 'PanelIcon',
props: { props: {
align: 'top', align: 'top',
icon: 'dengpao', icon: 'shuxingkongjian',
title: '大纲树' title: '大纲树'
}, },
config: { config: {
package: '@ali/lowcode-plugin-outline-pane', package: '@ali/lowcode-plugin-outline-pane',
version: '^1.0.0' version: '^0.8.0'
},
pluginProps: {}
},
{
pluginKey: 'zhEn',
type: 'Custom',
props: {
align: 'bottom',
},
config: {
package: '@ali/lowcode-plugin-zh-en',
version: '^0.8.0'
}, },
pluginProps: {} pluginProps: {}
} }
@ -100,7 +117,7 @@ export default {
props: {}, props: {},
config: { config: {
package: '@ali/lowcode-plugin-settings-pane', package: '@ali/lowcode-plugin-settings-pane',
version: '^1.0.0' version: '^0.8.0'
}, },
pluginProps: {} pluginProps: {}
} }
@ -110,7 +127,14 @@ export default {
pluginKey: 'designer', pluginKey: 'designer',
config: { config: {
package: '@ali/lowcode-plugin-designer', package: '@ali/lowcode-plugin-designer',
version: '1.0.0' version: '^0.8.0'
}
},
{
pluginKey: 'eventBindDialog',
config: {
package: '@ali/lowcode-plugin-event-bind-dialog',
version: '^0.8.0'
} }
} }
] ]

View 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: [],
};

View File

@ -0,0 +1,5 @@
/**
*
*/
export default {};

View 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',
},
};

View File

@ -0,0 +1 @@
export default {};

View 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();

View 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;
}
}
}

View 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>
);

View File

@ -0,0 +1,9 @@
.fusion-loading {
width: 48px;
height: 48px;
position: fixed;
top: 50%;
left: 50%;
margin-top: -24px;
margin-left: -24px;
}

View File

@ -0,0 +1,4 @@
import { Loading } from '@alifd/next';
import './index.scss';
export default () => <Loading tip="加载中..." className="fusion-loading" />;

View 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;
}
}

View File

@ -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),
};

View File

@ -1,3 +0,0 @@
export default {
namespace: 'page'
};

View 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
};

View File

@ -0,0 +1,3 @@
export default {
"namespace": "page"
}

View File

@ -0,0 +1 @@
export default {};

View 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
};

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1 @@
export default {};

View 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);
}
}
};

View File

@ -0,0 +1,3 @@
export default {
};

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import Skeleton from '@ali/lowcode-editor-skeleton';
import { registerSetters } from '@ali/lowcode-setters'; import { registerSetters } from '@ali/lowcode-setters';
import config from './config/skeleton'; import config from './config/skeleton';
import components from './config/components'; import components from './config/components';
@ -10,7 +9,7 @@ import './global.scss';
import './config/theme.scss'; import './config/theme.scss';
registerSetters(); registerSetters();
const Skeleton = components.LowcodeSkeleton;
const LCE_CONTAINER = document.getElementById('lce-container'); const LCE_CONTAINER = document.getElementById('lce-container');
if (!LCE_CONTAINER) { if (!LCE_CONTAINER) {

View File

@ -0,0 +1 @@
import './editor';

View File

@ -0,0 +1 @@
import './app';

View File

@ -1,9 +1,9 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"jsx": "react", "outDir": "lib"
"target": "ES6"
}, },
"include": ["src/*"], "include": [
"exclude": ["node_modules", "build", "public"] "./src/"
]
} }

View 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

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-designer", "name": "@ali/lowcode-designer",
"version": "0.8.1", "version": "0.9.1",
"description": "Designer for Ali LowCode Engine", "description": "Designer for Ali LowCode Engine",
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
@ -15,18 +15,18 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ali/lowcode-globals": "^0.9.1",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"react": "^16", "react": "^16",
"react-dom": "^16.7.0", "react-dom": "^16.7.0"
"@ali/lowcode-globals": "^0.8"
}, },
"devDependencies": { "devDependencies": {
"@types/medium-editor": "^5.0.3", "@alib/build-scripts": "^0.1.18",
"@types/classnames": "^2.2.7", "@types/classnames": "^2.2.7",
"@types/medium-editor": "^5.0.3",
"@types/node": "^13.7.1", "@types/node": "^13.7.1",
"@types/react": "^16", "@types/react": "^16",
"@types/react-dom": "^16", "@types/react-dom": "^16",
"@alib/build-scripts": "^0.1.18",
"build-plugin-component": "^0.2.10" "build-plugin-component": "^0.2.10"
}, },
"ava": { "ava": {

View File

@ -1,25 +1,27 @@
.lc-insertion { .lc-insertion {
position: absolute; position: absolute;
top: -1.5px; top: -2px;
left: 0; left: 0;
z-index: 12; z-index: 12;
pointer-events: none !important; pointer-events: none !important;
background-color: var(--color-brand-light); background-color: var(--color-brand-light);
height: 3px; height: 4px;
&.cover { &.cover {
top: 0; top: 0;
height: auto; height: auto;
width: auto; width: auto;
border: none;
opacity: 0.3; opacity: 0.3;
} }
&.vertical { &.vertical {
top: 0; top: 0;
left: -1.5px; left: -2px;
width: 3px; width: 4px;
height: auto; height: auto;
} }
&.invalid { &.invalid {
background-color: red; background-color: red;
} }

View File

@ -20,11 +20,13 @@ import {
getRectTarget, getRectTarget,
Rect, Rect,
CanvasPoint, CanvasPoint,
hotkey,
} from '../designer'; } from '../designer';
import { parseProps } from './utils/parse-props'; import { parseProps } from './utils/parse-props';
import { isElement } from '@ali/lowcode-globals'; import { isElement } from '@ali/lowcode-globals';
import { ComponentMetadata } from '@ali/lowcode-globals'; import { ComponentMetadata } from '@ali/lowcode-globals';
import { BuiltinSimulatorRenderer } from './renderer'; import { BuiltinSimulatorRenderer } from './renderer';
import clipboard from '../designer/clipboard';
export interface LibraryItem { export interface LibraryItem {
package: string; package: string;
@ -196,6 +198,8 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// wait 准备 iframe 内容、依赖库注入 // wait 准备 iframe 内容、依赖库注入
const renderer = await createSimulator(this, iframe, vendors); const renderer = await createSimulator(this, iframe, vendors);
// TODO: !!! thinkof reload onload
// wait 业务组件被第一次消费,否则会渲染出错 // wait 业务组件被第一次消费,否则会渲染出错
await this.componentsConsumer.waitFirstConsume(); await this.componentsConsumer.waitFirstConsume();
@ -209,11 +213,17 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
this._contentDocument = this._contentWindow.document; this._contentDocument = this._contentWindow.document;
this.viewport.setScrollTarget(this._contentWindow); this.viewport.setScrollTarget(this._contentWindow);
this.setupEvents(); this.setupEvents();
// hotkey.mount(this.contentWindow);
// clipboard.injectCopyPaster(this.ownerDocument); // bind hotkey & clipboard
hotkey.mount(this._contentWindow);
clipboard.injectCopyPaster(this._contentDocument);
// TODO: dispose the bindings
} }
setupEvents() { setupEvents() {
// TODO: Thinkof move events control to simulator renderer
// just listen special callback
// because iframe maybe reload
this.setupDragAndClick(); this.setupDragAndClick();
this.setupHovering(); this.setupHovering();
} }
@ -786,6 +796,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const inline = el ? isChildInline(el) : false; const inline = el ? isChildInline(el) : false;
const row = el ? isRowContainer(el.parentElement!) : false; const row = el ? isRowContainer(el.parentElement!) : false;
const vertical = inline || row; const vertical = inline || row;
// TODO: fix type // TODO: fix type
const near: any = { const near: any = {
node: nearNode, node: nearNode,

View File

@ -1,9 +1,4 @@
import { import {
IconRemove,
IconClone,
IconPage,
IconContainer,
IconComponent,
ComponentMetadata, ComponentMetadata,
NpmInfo, NpmInfo,
NodeData, NodeData,
@ -18,6 +13,11 @@ import {
import { Node, NodeParent } from './document'; import { Node, NodeParent } from './document';
import { Designer } from './designer'; import { Designer } from './designer';
import { intl } from './locale'; import { intl } from './locale';
import { IconContainer } from './icons/container';
import { IconPage } from './icons/page';
import { IconComponent } from './icons/component';
import { IconRemove } from './icons/remove';
import { IconClone } from './icons/clone';
function ensureAList(list?: string | string[]): string[] | null { function ensureAList(list?: string | string[]): string[] | null {
if (!list) { if (!list) {

View File

@ -5,6 +5,7 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
} }
try { try {
// { componentsMap, componentsTree, ... }
return JSON.parse(clipboardData.getData('text/plain')); return JSON.parse(clipboardData.getData('text/plain'));
} catch (error) { } catch (error) {
/* /*
@ -17,11 +18,13 @@ function getDataFromPasteEvent(event: ClipboardEvent) {
}; };
} }
*/ */
// paste the text by div // TODO: open the parser implement
return null;
/*
return { return {
code: clipboardData.getData('text/plain'), code: clipboardData.getData('text/plain'),
maps: {}, maps: {},
}; };*/
} }
} }
@ -33,7 +36,7 @@ class Clipboard {
this.isCopyPaster(e.target); this.isCopyPaster(e.target);
} }
isCopyPaster(el: any) { private isCopyPaster(el: any) {
return this.copyPasters.includes(el); return this.copyPasters.includes(el);
} }
@ -57,6 +60,9 @@ class Clipboard {
} }
injectCopyPaster(document: Document) { injectCopyPaster(document: Document) {
if (this.copyPasters.find(x => x.ownerDocument === document)) {
return;
}
const copyPaster = document.createElement<'textarea'>('textarea'); const copyPaster = document.createElement<'textarea'>('textarea');
copyPaster.style.cssText = 'position: relative;left: -9999px;'; copyPaster.style.cssText = 'position: relative;left: -9999px;';
document.body.appendChild(copyPaster); document.body.appendChild(copyPaster);

View File

@ -5,6 +5,7 @@ import BuiltinDragGhostComponent from './drag-ghost';
import { Designer, DesignerProps } from './designer'; import { Designer, DesignerProps } from './designer';
import { ProjectView } from '../project'; import { ProjectView } from '../project';
import './designer.less'; import './designer.less';
import clipboard from './clipboard';
export class DesignerView extends Component<DesignerProps> { export class DesignerView extends Component<DesignerProps> {
readonly designer: Designer; readonly designer: Designer;
@ -32,6 +33,7 @@ export class DesignerView extends Component<DesignerProps> {
if (onMount) { if (onMount) {
onMount(this.designer); onMount(this.designer);
} }
clipboard.injectCopyPaster(document)
this.designer.postEvent('mount', this.designer); this.designer.postEvent('mount', this.designer);
} }

View File

@ -10,7 +10,7 @@ import {
autorun, autorun,
} from '@ali/lowcode-globals'; } from '@ali/lowcode-globals';
import { Project } from '../project'; import { Project } from '../project';
import { Node, DocumentModel, insertChildren, isRootNode } from '../document'; import { Node, DocumentModel, insertChildren, isRootNode, NodeParent } from '../document';
import { ComponentMeta } from '../component-meta'; import { ComponentMeta } from '../component-meta';
import { INodeSelector } from '../simulator'; import { INodeSelector } from '../simulator';
import { Scroller, IScrollable } from './scroller'; import { Scroller, IScrollable } from './scroller';
@ -19,6 +19,7 @@ import { ActiveTracker } from './active-tracker';
import { Hovering } from './hovering'; import { Hovering } from './hovering';
import { DropLocation, LocationData, isLocationChildrenDetail } from './location'; import { DropLocation, LocationData, isLocationChildrenDetail } from './location';
import { OffsetObserver, createOffsetObserver } from './offset-observer'; import { OffsetObserver, createOffsetObserver } from './offset-observer';
import { focusing } from './focusing';
export interface DesignerProps { export interface DesignerProps {
className?: string; className?: string;
@ -40,7 +41,6 @@ export interface DesignerProps {
} }
export class Designer { export class Designer {
// readonly hotkey: Hotkey;
readonly dragon = new Dragon(this); readonly dragon = new Dragon(this);
readonly activeTracker = new ActiveTracker(); readonly activeTracker = new ActiveTracker();
readonly hovering = new Hovering(); readonly hovering = new Hovering();
@ -156,6 +156,9 @@ export class Designer {
this.postEvent('designer.init', this); this.postEvent('designer.init', this);
setupSelection(); setupSelection();
setupHistory(); setupHistory();
// TODO: 先简单实现,后期通过焦点赋值
focusing.focusDesigner = this;
} }
postEvent(event: string, ...args: any[]) { postEvent(event: string, ...args: any[]) {
@ -198,7 +201,7 @@ export class Designer {
/** /**
* *
*/ */
getSuitableInsertion() { getSuitableInsertion(): { target: NodeParent; index?: number } | null {
const activedDoc = this.project.currentDocument; const activedDoc = this.project.currentDocument;
if (!activedDoc) { if (!activedDoc) {
return null; return null;
@ -296,7 +299,7 @@ export class Designer {
} }
setSchema(schema?: ProjectSchema) { setSchema(schema?: ProjectSchema) {
this.project.setSchema(schema); this.project.load(schema);
} }
@obx.val private _componentMetasMap = new Map<string, ComponentMeta>(); @obx.val private _componentMetasMap = new Map<string, ComponentMeta>();

View File

@ -427,8 +427,9 @@ export class Dragon {
}; };
const sourceSensor = getSourceSensor(dragObject); const sourceSensor = getSourceSensor(dragObject);
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
const chooseSensor = (e: LocateEvent) => { const chooseSensor = (e: LocateEvent) => {
// this.sensors will change on dragstart
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
let sensor = e.sensor && e.sensor.isEnter(e) ? e.sensor : sensors.find((s) => s.sensorAvailable && s.isEnter(e)); let sensor = e.sensor && e.sensor.isEnter(e) ? e.sensor : sensors.find((s) => s.sensorAvailable && s.isEnter(e));
if (!sensor) { if (!sensor) {
// TODO: enter some area like componentspanel cancel // TODO: enter some area like componentspanel cancel

View File

@ -0,0 +1,9 @@
import { Designer } from './designer';
// TODO:
// 当前激活区域管理
class Focusing {
focusDesigner?: Designer;
}
export const focusing = new Focusing();

View File

@ -1,618 +1,117 @@
interface KeyMap { import { Hotkey, isFormEvent } from '@ali/lowcode-globals';
[key: number]: string; import { focusing } from './focusing';
} import { insertChildren } from '../document';
import clipboard from './clipboard';
interface CtrlKeyMap { export const hotkey = new Hotkey();
[key: string]: string;
}
interface ActionEvent { // hotkey binding
type: string; hotkey.bind(['backspace', 'del'], (e: KeyboardEvent) => {
const doc = focusing.focusDesigner?.currentDocument;
if (isFormEvent(e) || !doc) {
return;
} }
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';
}
export function isFormEvent(e: KeyboardEvent) {
const t = e.target as HTMLFormElement;
if (!t) {
return false;
}
if (t.form || /^(INPUT|SELECT|TEXTAREA)$/.test(t.tagName)) {
return true;
}
if (/write/.test(window.getComputedStyle(t).getPropertyValue('-webkit-user-modify'))) {
return true;
}
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;
}
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.preventDefault();
e.stopPropagation();
}
}
export class Hotkey { const sel = doc.selection;
private callBacks: HotkeyCallbacks = {}; const topItems = sel.getTopNodes();
private directMap: HotkeyDirectMap = {}; // TODO: check can remove
private sequenceLevels: SequenceLevels = {}; topItems.forEach(node => {
private resetTimer = 0; doc.removeNode(node);
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,
}); });
sel.clear();
});
hotkey.bind('escape', (e: KeyboardEvent) => {
// const currentFocus = focusing.current;
const sel = focusing.focusDesigner?.currentDocument?.selection;
if (isFormEvent(e) || !sel) {
return;
}
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;
}
e.preventDefault();
/*
const doc = getCurrentDocument();
if (isFormEvent(e) || !doc || !(focusing.id === 'outline' || focusing.id === 'canvas')) {
return;
}
e.preventDefault();
*/
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();
}
*/
});
// command + v paste
hotkey.bind(['command+v', 'ctrl+v'], (e) => {
const designer = focusing.focusDesigner;
const doc = designer?.currentDocument;
if (isFormEvent(e) || !designer || !doc) {
return;
}
clipboard.waitPasteData(e, ({ componentsTree }) => {
if (componentsTree) {
const { target, index } = designer.getSuitableInsertion() || {};
if (!target) {
return;
}
const nodes = insertChildren(target, componentsTree, index);
if (nodes) {
doc.selection.selectAll(nodes.map(o => o.id));
setTimeout(() => designer.activeTracker.track(nodes[0]), 10);
}
}
});
});
// command + z undo
hotkey.bind(['command+z', 'ctrl+z'], (e) => {
const his = focusing.focusDesigner?.currentHistory;
if (isFormEvent(e) || !his) {
return;
} }
private bindMultiple(combinations: string[], callback: HotkeyCallback, action?: string) { e.preventDefault();
for (const item of combinations) { his.back();
this.bindSingle(item, callback, action); });
}
} // 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();
his.forward();
});
hotkey.mount(window);

View File

@ -86,7 +86,7 @@ export function isChildInline(child: Element | Text, win?: Window) {
return true; return true;
} }
const style = (win || getWindow(child)).getComputedStyle(child); const style = (win || getWindow(child)).getComputedStyle(child);
return /^inline/.test(style.getPropertyValue('display')); return /^inline/.test(style.getPropertyValue('display')) || /^(left|right)$/.test(style.getPropertyValue('float'));
} }
export function getRectTarget(rect: Rect | null) { export function getRectTarget(rect: Rect | null) {

View File

@ -59,6 +59,7 @@ export class DocumentModel {
} }
private _modalNode?: NodeParent; private _modalNode?: NodeParent;
private _blank?: boolean;
get modalNode() { get modalNode() {
return this._modalNode; return this._modalNode;
} }
@ -67,7 +68,7 @@ export class DocumentModel {
return this.modalNode || this.rootNode; return this.modalNode || this.rootNode;
} }
constructor(readonly project: Project, schema: RootSchema) { constructor(readonly project: Project, schema?: RootSchema) {
autorun(() => { autorun(() => {
this.nodes.forEach((item) => { this.nodes.forEach((item) => {
if (item.parent == null && item !== this.rootNode) { if (item.parent == null && item !== this.rootNode) {
@ -75,7 +76,16 @@ export class DocumentModel {
} }
}); });
}, true); }, true);
this.rootNode = this.createRootNode(schema);
if (!schema) {
this._blank = true;
}
this.rootNode = this.createRootNode(schema || {
componentName: 'Page',
fileName: ''
});
this.history = new History( this.history = new History(
() => this.schema, () => this.schema,
(schema) => this.import(schema as RootSchema, true), (schema) => this.import(schema as RootSchema, true),
@ -83,6 +93,10 @@ export class DocumentModel {
this.setupListenActiveNodes(); this.setupListenActiveNodes();
} }
@computed isBlank() {
return this._blank && !this.isModified();
}
readonly designer = this.project.designer; readonly designer = this.project.designer;
/** /**
@ -295,6 +309,7 @@ export class DocumentModel {
} }
private mountSimulator(simulator: ISimulatorHost) { private mountSimulator(simulator: ISimulatorHost) {
// TODO: 多设备 simulator 支持
this._simulator = simulator; this._simulator = simulator;
// TODO: emit simulator mounted // TODO: emit simulator mounted
} }
@ -386,7 +401,8 @@ export class DocumentModel {
* *
*/ */
remove() { remove() {
// todo: // this.project.removeDocument(this);
// todo: ...
} }
purge() { purge() {

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from "./icon-base"; import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconClone(props: IconProps) { export function IconClone(props: IconProps) {
return ( return (
<IconBase viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M192 256.16C192 220.736 220.704 192 256.16 192h639.68C931.264 192 960 220.704 960 256.16v639.68A64.16 64.16 0 0 1 895.84 960H256.16A64.16 64.16 0 0 1 192 895.84V256.16z m64 31.584v576.512a32 32 0 0 0 31.744 31.744h576.512a32 32 0 0 0 31.744-31.744V287.744A32 32 0 0 0 864.256 256H287.744A32 32 0 0 0 256 287.744zM288 192v64h64V192H288z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m96 96v64h64V288h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m-96 96v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64H288z m-96-96v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64V288H192z m160 416c0-17.664 14.592-32 32.064-32h319.872a31.968 31.968 0 1 1 0 64h-319.872A31.968 31.968 0 0 1 352 704z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 576z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 448z m512 47.936V192h-64V159.968A31.776 31.776 0 0 0 768.032 128H160A31.776 31.776 0 0 0 128 159.968V768c0 17.92 14.304 31.968 31.968 31.968H192v64h303.936H128.128A63.968 63.968 0 0 1 64 799.872V128.128C64 92.704 92.48 64 128.128 64h671.744C835.296 64 864 92.48 864 128.128v367.808z"/> <path d="M192 256.16C192 220.736 220.704 192 256.16 192h639.68C931.264 192 960 220.704 960 256.16v639.68A64.16 64.16 0 0 1 895.84 960H256.16A64.16 64.16 0 0 1 192 895.84V256.16z m64 31.584v576.512a32 32 0 0 0 31.744 31.744h576.512a32 32 0 0 0 31.744-31.744V287.744A32 32 0 0 0 864.256 256H287.744A32 32 0 0 0 256 287.744zM288 192v64h64V192H288z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m128 0v64h64V192h-64z m96 96v64h64V288h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m0 128v64h64v-64h-64z m-96 96v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64h-64z m-128 0v64h64v-64H288z m-96-96v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64v-64H192z m0-128v64h64V288H192z m160 416c0-17.664 14.592-32 32.064-32h319.872a31.968 31.968 0 1 1 0 64h-319.872A31.968 31.968 0 0 1 352 704z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 576z m0-128c0-17.664 14.4-32 32.224-32h383.552c17.792 0 32.224 14.208 32.224 32 0 17.664-14.4 32-32.224 32H384.224A32.032 32.032 0 0 1 352 448z m512 47.936V192h-64V159.968A31.776 31.776 0 0 0 768.032 128H160A31.776 31.776 0 0 0 128 159.968V768c0 17.92 14.304 31.968 31.968 31.968H192v64h303.936H128.128A63.968 63.968 0 0 1 64 799.872V128.128C64 92.704 92.48 64 128.128 64h671.744C835.296 64 864 92.48 864 128.128v367.808z"/>
</IconBase> </SVGIcon>
); );
} }

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from "./icon-base"; import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconComponent(props: IconProps) { export function IconComponent(props: IconProps) {
return ( return (
<IconBase viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M783.5648 437.4528h-18.0224V336.6912c0-43.8272-35.6352-79.4624-79.4624-79.4624h-110.592V241.664c0-90.9312-73.728-164.6592-164.6592-164.6592-90.9312 0-164.6592 73.728-164.6592 164.6592v15.5648H155.2384c-43.8272 0-79.4624 35.6352-79.4624 79.4624v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h56.1152c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192H106.496c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 43.8272 35.6352 79.4624 79.4624 79.4624h531.2512c43.8272 0 79.4624-35.6352 79.4624-79.4624v-100.7616h18.0224c90.9312 0 164.6592-73.728 164.6592-164.6592-0.4096-90.9312-74.1376-164.6592-165.0688-164.6592z m0 267.8784h-48.7424c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 9.8304-8.192 18.0224-18.0224 18.0224H155.2384c-9.8304 0-18.0224-8.192-18.0224-18.0224v-100.7616h25.3952c90.9312 0 164.6592-73.728 164.6592-164.6592 0-90.9312-73.728-164.6592-164.6592-164.6592h-25.3952V336.6912c0-9.8304 8.192-18.0224 18.0224-18.0224h121.6512c16.7936 0 30.72-13.9264 30.72-30.72V241.664c0-56.9344 46.2848-103.2192 103.2192-103.2192s103.2192 46.2848 103.2192 103.2192v46.2848c0 16.7936 13.9264 30.72 30.72 30.72h141.312c9.8304 0 18.0224 8.192 18.0224 18.0224v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h48.7424c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192z" /> <path d="M783.5648 437.4528h-18.0224V336.6912c0-43.8272-35.6352-79.4624-79.4624-79.4624h-110.592V241.664c0-90.9312-73.728-164.6592-164.6592-164.6592-90.9312 0-164.6592 73.728-164.6592 164.6592v15.5648H155.2384c-43.8272 0-79.4624 35.6352-79.4624 79.4624v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h56.1152c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192H106.496c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 43.8272 35.6352 79.4624 79.4624 79.4624h531.2512c43.8272 0 79.4624-35.6352 79.4624-79.4624v-100.7616h18.0224c90.9312 0 164.6592-73.728 164.6592-164.6592-0.4096-90.9312-74.1376-164.6592-165.0688-164.6592z m0 267.8784h-48.7424c-16.7936 0-30.72 13.9264-30.72 30.72v131.4816c0 9.8304-8.192 18.0224-18.0224 18.0224H155.2384c-9.8304 0-18.0224-8.192-18.0224-18.0224v-100.7616h25.3952c90.9312 0 164.6592-73.728 164.6592-164.6592 0-90.9312-73.728-164.6592-164.6592-164.6592h-25.3952V336.6912c0-9.8304 8.192-18.0224 18.0224-18.0224h121.6512c16.7936 0 30.72-13.9264 30.72-30.72V241.664c0-56.9344 46.2848-103.2192 103.2192-103.2192s103.2192 46.2848 103.2192 103.2192v46.2848c0 16.7936 13.9264 30.72 30.72 30.72h141.312c9.8304 0 18.0224 8.192 18.0224 18.0224v131.4816c0 16.7936 13.9264 30.72 30.72 30.72h48.7424c56.9344 0 103.2192 46.2848 103.2192 103.2192s-46.2848 103.2192-103.2192 103.2192z" />
</IconBase> </SVGIcon>
); );
} }
IconComponent.displayName = 'Component'; IconComponent.displayName = 'Component';

View File

@ -1,11 +1,11 @@
import { IconBase, IconProps } from "./icon-base"; import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconContainer(props: IconProps) { export function IconContainer(props: IconProps) {
return ( return (
<IconBase viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M800 800h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-256 0h64v64h-64v-64z m0-640h64v64h-64v-64z m128 640h64v64h-64v-64zM160 672h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m640 384h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z" /> <path d="M800 800h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-256 0h64v64h-64v-64z m0-640h64v64h-64v-64z m128 640h64v64h-64v-64zM160 672h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m640 384h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m0-128h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z m-128 0h64v64h-64v-64z" />
<path d="M896 64H128c-35.2 0-64 28.8-64 64v768c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V128c0-35.2-28.8-64-64-64z m0 800c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V160c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v704z" /> <path d="M896 64H128c-35.2 0-64 28.8-64 64v768c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V128c0-35.2-28.8-64-64-64z m0 800c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V160c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v704z" />
</IconBase> </SVGIcon>
); );
} }
IconContainer.displayName = 'Container'; IconContainer.displayName = 'Container';

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from "./icon-base"; import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconHidden(props: IconProps) { export function IconHidden(props: IconProps) {
return ( return (
<IconBase viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M183.423543 657.078213l163.499771-98.484012c-4.233418-14.908548-6.646374-30.585599-6.646374-46.852074 0-94.665033 76.739778-171.404812 171.404812-171.404812 45.983287 0 87.641059 18.20871 118.42518 47.679929l129.791042-78.17957c-73.254398-41.73145-157.866471-65.812915-248.216221-65.812915-192.742792 0-360.068705 108.505249-444.453604 267.715321C96.636944 567.228859 136.301316 616.355743 183.423543 657.078213zM841.253886 367.552144l-164.382884 99.015108c3.934612 14.415314 6.215562 29.513174 6.215562 45.174875 0 94.665033-76.739778 171.404812-171.404812 171.404812-45.361117 0-86.484723-17.747199-117.142977-46.515407l-129.419582 77.955466c72.874751 41.149189 156.893306 64.871473 246.563582 64.871473 192.742792 0 360.068705-108.505249 444.453604-267.717368C927.000805 456.773188 887.794875 408.054603 841.253886 367.552144zM420.280042 511.741104c0 0.550539 0.152473 1.060145 0.161682 1.608637l135.080511-81.366146c-13.065574-7.198959-27.854395-11.658528-43.826158-11.658528C461.20922 420.325068 420.280042 461.254246 420.280042 511.741104zM447.739441 576.947198l69.02098-41.574884L948.364369 275.395234c10.812253-6.512321 14.297634-20.558222 7.785314-31.369452-6.512321-10.812253-20.556175-14.296611-31.368428-7.785314L575.654762 446.537056l0 0-151.20577 91.078345 0 0L75.027787 748.090043c-10.812253 6.512321-14.297634 20.556175-7.785314 31.368428 6.512321 10.812253 20.556175 14.297634 31.369452 7.785314L447.739441 576.947198 447.739441 576.947198zM511.696078 603.157139c50.487881 0 91.416036-40.928155 91.416036-91.416036 0-0.549515-0.152473-1.057075-0.161682-1.605567l-135.079488 81.364099C480.935494 598.699618 495.724315 603.157139 511.696078 603.157139z" /> <path d="M183.423543 657.078213l163.499771-98.484012c-4.233418-14.908548-6.646374-30.585599-6.646374-46.852074 0-94.665033 76.739778-171.404812 171.404812-171.404812 45.983287 0 87.641059 18.20871 118.42518 47.679929l129.791042-78.17957c-73.254398-41.73145-157.866471-65.812915-248.216221-65.812915-192.742792 0-360.068705 108.505249-444.453604 267.715321C96.636944 567.228859 136.301316 616.355743 183.423543 657.078213zM841.253886 367.552144l-164.382884 99.015108c3.934612 14.415314 6.215562 29.513174 6.215562 45.174875 0 94.665033-76.739778 171.404812-171.404812 171.404812-45.361117 0-86.484723-17.747199-117.142977-46.515407l-129.419582 77.955466c72.874751 41.149189 156.893306 64.871473 246.563582 64.871473 192.742792 0 360.068705-108.505249 444.453604-267.717368C927.000805 456.773188 887.794875 408.054603 841.253886 367.552144zM420.280042 511.741104c0 0.550539 0.152473 1.060145 0.161682 1.608637l135.080511-81.366146c-13.065574-7.198959-27.854395-11.658528-43.826158-11.658528C461.20922 420.325068 420.280042 461.254246 420.280042 511.741104zM447.739441 576.947198l69.02098-41.574884L948.364369 275.395234c10.812253-6.512321 14.297634-20.558222 7.785314-31.369452-6.512321-10.812253-20.556175-14.296611-31.368428-7.785314L575.654762 446.537056l0 0-151.20577 91.078345 0 0L75.027787 748.090043c-10.812253 6.512321-14.297634 20.556175-7.785314 31.368428 6.512321 10.812253 20.556175 14.297634 31.369452 7.785314L447.739441 576.947198 447.739441 576.947198zM511.696078 603.157139c50.487881 0 91.416036-40.928155 91.416036-91.416036 0-0.549515-0.152473-1.057075-0.161682-1.605567l-135.079488 81.364099C480.935494 598.699618 495.724315 603.157139 511.696078 603.157139z" />
</IconBase> </SVGIcon>
); );
} }
IconHidden.displayName = 'Hidden'; IconHidden.displayName = 'Hidden';

View File

@ -1,12 +1,12 @@
import { IconBase, IconProps } from "./icon-base"; import { SVGIcon, IconProps } from "@ali/lowcode-globals";
export function IconPage(props: IconProps) { export function IconPage(props: IconProps) {
return ( return (
<IconBase viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M381.6 864H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0.1-5.7-5.5-10.3-12.3-10.3zM382 780.6H162c-6.9 0-12.5 4.6-12.5 10.3v19.3c0 5.7 5.6 10.3 12.5 10.3h220c6.9 0 12.5-4.6 12.5-10.3v-19.3c0-5.7-5.6-10.3-12.5-10.3zM162.4 737.2h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0-5.7-5.6-10.3-12.4-10.3H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3z" /> <path d="M381.6 864H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0.1-5.7-5.5-10.3-12.3-10.3zM382 780.6H162c-6.9 0-12.5 4.6-12.5 10.3v19.3c0 5.7 5.6 10.3 12.5 10.3h220c6.9 0 12.5-4.6 12.5-10.3v-19.3c0-5.7-5.6-10.3-12.5-10.3zM162.4 737.2h219.1c6.8 0 12.4-4.6 12.4-10.3v-19.3c0-5.7-5.6-10.3-12.4-10.3H162.4c-6.9 0-12.4 4.6-12.4 10.3v19.3c0 5.7 5.6 10.3 12.4 10.3z" />
<path d="M977.1 0H46.9C21 0 0 21 0 46.9v930.2c0 25.9 21 46.9 46.9 46.9h930.2c25.9 0 46.9-21 46.9-46.9V46.9C1024 21 1003 0 977.1 0z m-18.7 911.6c0 25.9-21 46.9-46.9 46.9H112.4c-25.9 0-46.9-21-46.9-47V112.4c0-25.9 21-46.9 46.9-46.9h799.1c25.9 0 46.9 21 46.9 46.9v799.2z" /> <path d="M977.1 0H46.9C21 0 0 21 0 46.9v930.2c0 25.9 21 46.9 46.9 46.9h930.2c25.9 0 46.9-21 46.9-46.9V46.9C1024 21 1003 0 977.1 0z m-18.7 911.6c0 25.9-21 46.9-46.9 46.9H112.4c-25.9 0-46.9-21-46.9-47V112.4c0-25.9 21-46.9 46.9-46.9h799.1c25.9 0 46.9 21 46.9 46.9v799.2z" />
<path d="M207.9 342.7h608.2c32 0 57.9-25.9 57.9-57.9v-83c0-32-25.9-57.9-57.9-57.9H207.9c-32 0-57.9 25.9-57.9 57.9v83c0 32 25.9 57.9 57.9 57.9zM200 201.8c0-4.4 3.5-7.9 7.9-7.9h608.2c4.4 0 7.9 3.5 7.9 7.9v83c0 4.4-3.5 7.9-7.9 7.9H207.9c-4.4 0-7.9-3.5-7.9-7.9v-83zM806.4 405.7h-277c-37.3 0-67.6 30.2-67.6 67.6v363.2c0 37.3 30.2 67.6 67.6 67.6h277c37.3 0 67.6-30.2 67.6-67.6V473.3c0-37.4-30.2-67.6-67.6-67.6zM824 836.4c0 9.7-7.9 17.6-17.6 17.6h-277c-9.7 0-17.6-7.9-17.6-17.6V473.3c0-9.7 7.9-17.6 17.6-17.6h277c9.7 0 17.6 7.9 17.6 17.6v363.1zM272 649.7c67.4 0 122-54.6 122-122s-54.6-122-122-122-122 54.6-122 122 54.6 122 122 122z m0-204c45.2 0 82 36.8 82 82s-36.8 82-82 82-82-36.8-82-82 36.8-82 82-82z" /> <path d="M207.9 342.7h608.2c32 0 57.9-25.9 57.9-57.9v-83c0-32-25.9-57.9-57.9-57.9H207.9c-32 0-57.9 25.9-57.9 57.9v83c0 32 25.9 57.9 57.9 57.9zM200 201.8c0-4.4 3.5-7.9 7.9-7.9h608.2c4.4 0 7.9 3.5 7.9 7.9v83c0 4.4-3.5 7.9-7.9 7.9H207.9c-4.4 0-7.9-3.5-7.9-7.9v-83zM806.4 405.7h-277c-37.3 0-67.6 30.2-67.6 67.6v363.2c0 37.3 30.2 67.6 67.6 67.6h277c37.3 0 67.6-30.2 67.6-67.6V473.3c0-37.4-30.2-67.6-67.6-67.6zM824 836.4c0 9.7-7.9 17.6-17.6 17.6h-277c-9.7 0-17.6-7.9-17.6-17.6V473.3c0-9.7 7.9-17.6 17.6-17.6h277c9.7 0 17.6 7.9 17.6 17.6v363.1zM272 649.7c67.4 0 122-54.6 122-122s-54.6-122-122-122-122 54.6-122 122 54.6 122 122 122z m0-204c45.2 0 82 36.8 82 82s-36.8 82-82 82-82-36.8-82-82 36.8-82 82-82z" />
</IconBase> </SVGIcon>
); );
} }
IconPage.displayName = 'Page'; IconPage.displayName = 'Page';

View File

@ -1,10 +1,10 @@
import { IconBase, IconProps } from './icon-base'; import { SVGIcon, IconProps } from '@ali/lowcode-globals';
export function IconRemove(props: IconProps) { export function IconRemove(props: IconProps) {
return ( return (
<IconBase viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M224 256v639.84A64 64 0 0 0 287.84 960h448.32A64 64 0 0 0 800 895.84V256h64a32 32 0 1 0 0-64H160a32 32 0 1 0 0 64h64zM384 96c0-17.664 14.496-32 31.904-32h192.192C625.696 64 640 78.208 640 96c0 17.664-14.496 32-31.904 32H415.904A31.872 31.872 0 0 1 384 96z m-96 191.744C288 270.208 302.4 256 320.224 256h383.552C721.6 256 736 270.56 736 287.744v576.512C736 881.792 721.6 896 703.776 896H320.224A32.224 32.224 0 0 1 288 864.256V287.744zM352 352c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z" /> <path d="M224 256v639.84A64 64 0 0 0 287.84 960h448.32A64 64 0 0 0 800 895.84V256h64a32 32 0 1 0 0-64H160a32 32 0 1 0 0 64h64zM384 96c0-17.664 14.496-32 31.904-32h192.192C625.696 64 640 78.208 640 96c0 17.664-14.496 32-31.904 32H415.904A31.872 31.872 0 0 1 384 96z m-96 191.744C288 270.208 302.4 256 320.224 256h383.552C721.6 256 736 270.56 736 287.744v576.512C736 881.792 721.6 896 703.776 896H320.224A32.224 32.224 0 0 1 288 864.256V287.744zM352 352c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z m128 0c0-17.696 14.208-32.032 32-32.032 17.664 0 32 14.24 32 32v448c0 17.664-14.208 32-32 32-17.664 0-32-14.24-32-32V352z" />
</IconBase> </SVGIcon>
); );
} }
IconRemove.displayName = 'Remove'; IconRemove.displayName = 'Remove';

View File

@ -1,11 +1,11 @@
import { IconBase, IconProps } from './icon-base'; import { SVGIcon, IconProps } from '@ali/lowcode-globals';
export function IconSetting(props: IconProps) { export function IconSetting(props: IconProps) {
return ( return (
<IconBase viewBox="0 0 1024 1024" {...props}> <SVGIcon viewBox="0 0 1024 1024" {...props}>
<path d="M965.824 405.952a180.48 180.48 0 0 1-117.12-85.376 174.464 174.464 0 0 1-16-142.08 22.208 22.208 0 0 0-7.04-23.552 480.576 480.576 0 0 0-153.6-89.216 23.104 23.104 0 0 0-24.32 5.76 182.208 182.208 0 0 1-135.68 57.92 182.208 182.208 0 0 1-133.12-56.64 23.104 23.104 0 0 0-26.88-7.04 478.656 478.656 0 0 0-153.6 89.856 22.208 22.208 0 0 0-7.04 23.552 174.464 174.464 0 0 1-16 141.44A180.48 180.48 0 0 1 58.24 405.952a22.4 22.4 0 0 0-17.28 17.792 455.08 455.08 0 0 0 0 176.512 22.4 22.4 0 0 0 17.28 17.792 180.48 180.48 0 0 1 117.12 84.736c25.408 42.944 31.232 94.592 16 142.08a22.208 22.208 0 0 0 7.04 23.552A480.576 480.576 0 0 0 352 957.632h7.68a23.04 23.04 0 0 0 16.64-7.04 184.128 184.128 0 0 1 266.944 0c6.592 8.96 18.752 11.968 28.8 7.04a479.36 479.36 0 0 0 156.16-88.576 22.208 22.208 0 0 0 7.04-23.552 174.464 174.464 0 0 1 13.44-142.72 180.48 180.48 0 0 1 117.12-84.736 22.4 22.4 0 0 0 17.28-17.792 452.613 452.613 0 0 0 0-176.512 23.04 23.04 0 0 0-17.28-17.792z m-42.88 169.408a218.752 218.752 0 0 0-128 98.112 211.904 211.904 0 0 0-21.76 156.736 415.936 415.936 0 0 1-112 63.68 217.472 217.472 0 0 0-149.12-63.68 221.312 221.312 0 0 0-149.12 63.68 414.592 414.592 0 0 1-112-63.68c12.8-53.12 4.288-109.12-23.68-156.096A218.752 218.752 0 0 0 101.12 575.36a386.176 386.176 0 0 1 0-127.36 218.752 218.752 0 0 0 128-98.112c27.2-47.552 34.944-103.68 21.76-156.8a415.296 415.296 0 0 1 112-63.68A221.44 221.44 0 0 0 512 187.392a218.24 218.24 0 0 0 149.12-57.984 413.952 413.952 0 0 1 112 63.744 211.904 211.904 0 0 0 23.04 156.096 218.752 218.752 0 0 0 128 98.112 386.65 386.65 0 0 1 0 127.36l-1.28 0.64z" /> <path d="M965.824 405.952a180.48 180.48 0 0 1-117.12-85.376 174.464 174.464 0 0 1-16-142.08 22.208 22.208 0 0 0-7.04-23.552 480.576 480.576 0 0 0-153.6-89.216 23.104 23.104 0 0 0-24.32 5.76 182.208 182.208 0 0 1-135.68 57.92 182.208 182.208 0 0 1-133.12-56.64 23.104 23.104 0 0 0-26.88-7.04 478.656 478.656 0 0 0-153.6 89.856 22.208 22.208 0 0 0-7.04 23.552 174.464 174.464 0 0 1-16 141.44A180.48 180.48 0 0 1 58.24 405.952a22.4 22.4 0 0 0-17.28 17.792 455.08 455.08 0 0 0 0 176.512 22.4 22.4 0 0 0 17.28 17.792 180.48 180.48 0 0 1 117.12 84.736c25.408 42.944 31.232 94.592 16 142.08a22.208 22.208 0 0 0 7.04 23.552A480.576 480.576 0 0 0 352 957.632h7.68a23.04 23.04 0 0 0 16.64-7.04 184.128 184.128 0 0 1 266.944 0c6.592 8.96 18.752 11.968 28.8 7.04a479.36 479.36 0 0 0 156.16-88.576 22.208 22.208 0 0 0 7.04-23.552 174.464 174.464 0 0 1 13.44-142.72 180.48 180.48 0 0 1 117.12-84.736 22.4 22.4 0 0 0 17.28-17.792 452.613 452.613 0 0 0 0-176.512 23.04 23.04 0 0 0-17.28-17.792z m-42.88 169.408a218.752 218.752 0 0 0-128 98.112 211.904 211.904 0 0 0-21.76 156.736 415.936 415.936 0 0 1-112 63.68 217.472 217.472 0 0 0-149.12-63.68 221.312 221.312 0 0 0-149.12 63.68 414.592 414.592 0 0 1-112-63.68c12.8-53.12 4.288-109.12-23.68-156.096A218.752 218.752 0 0 0 101.12 575.36a386.176 386.176 0 0 1 0-127.36 218.752 218.752 0 0 0 128-98.112c27.2-47.552 34.944-103.68 21.76-156.8a415.296 415.296 0 0 1 112-63.68A221.44 221.44 0 0 0 512 187.392a218.24 218.24 0 0 0 149.12-57.984 413.952 413.952 0 0 1 112 63.744 211.904 211.904 0 0 0 23.04 156.096 218.752 218.752 0 0 0 128 98.112 386.65 386.65 0 0 1 0 127.36l-1.28 0.64z" />
<path d="M512 320.576c-105.984 0-192 85.568-192 191.104a191.552 191.552 0 0 0 192 191.104c106.112 0 192.064-85.568 192.064-191.104a190.72 190.72 0 0 0-56.256-135.168 192.448 192.448 0 0 0-135.744-55.936z m0 318.528c-70.656 0-128-57.088-128-127.424 0-70.4 57.344-127.36 128-127.36 70.72 0 128 56.96 128 127.36 0 33.792-13.44 66.176-37.44 90.112a128.32 128.32 0 0 1-90.496 37.312z" /> <path d="M512 320.576c-105.984 0-192 85.568-192 191.104a191.552 191.552 0 0 0 192 191.104c106.112 0 192.064-85.568 192.064-191.104a190.72 190.72 0 0 0-56.256-135.168 192.448 192.448 0 0 0-135.744-55.936z m0 318.528c-70.656 0-128-57.088-128-127.424 0-70.4 57.344-127.36 128-127.36 70.72 0 128 56.96 128 127.36 0 33.792-13.44 66.176-37.44 90.112a128.32 128.32 0 0 1-90.496 37.312z" />
</IconBase> </SVGIcon>
); );
} }

View File

@ -1,5 +1,6 @@
{ {
"copy": "Copy", "copy": "Copy",
"remove": "Remove", "remove": "Remove",
"Condition Group": "Condition Group" "Condition Group": "Condition Group",
"No opened document": "No opened document, open some document to editing"
} }

View File

@ -1,5 +1,6 @@
{ {
"copy": "复制", "copy": "复制",
"remove": "删除", "remove": "删除",
"Condition Group": "条件组" "Condition Group": "条件组",
"No opened document": "没有打开的页面,请选择页面打开编辑"
} }

View File

@ -2,6 +2,7 @@ import { Component } from 'react';
import { observer } from '@ali/lowcode-globals'; import { observer } from '@ali/lowcode-globals';
import { Designer } from '../designer'; import { Designer } from '../designer';
import { DocumentView } from '../document'; import { DocumentView } from '../document';
import { intl } from '../locale';
import './project.less'; import './project.less';
@observer @observer
@ -9,14 +10,14 @@ export class ProjectView extends Component<{ designer: Designer }> {
render() { render() {
const { designer } = this.props; const { designer } = this.props;
// TODO: support splitview // TODO: support splitview
const opens = designer.project.documents.filter((doc) => doc.opened);
return ( return (
<div className="lc-project"> <div className="lc-project">
{designer.project.documents.map(doc => { {opens.length > 0 ? (
if (!doc.opened) { opens.map((doc) => <DocumentView key={doc.id} document={doc} />)
return null; ) : (
} <div className="lc-project-empty">{intl('No opened document')}</div>
return <DocumentView key={doc.id} document={doc} />; )}
})}
</div> </div>
); );
} }

View File

@ -4,6 +4,14 @@
right: 0; right: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
.lc-project-empty {
width: 100%;
height: 100%;
font-size: 16px;
text-align: center;
background: transparent url(//img.alicdn.com/tfs/TB1xLKQAbj1gK0jSZFuXXcrHpXa-90-90.png) center 30% no-repeat;
padding-top: 50%;
}
.lc-document { .lc-document {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@ -14,11 +14,11 @@ export class Project {
// TODO: 考虑项目级别 History // TODO: 考虑项目级别 History
constructor(readonly designer: Designer, schema?: ProjectSchema) { constructor(readonly designer: Designer, schema?: ProjectSchema) {
this.setSchema(schema); this.load(schema);
} }
@computed get currentDocument() { @computed get currentDocument() {
return this.documents.find(doc => doc.actived); return this.documents.find((doc) => doc.actived);
} }
/** /**
@ -27,30 +27,45 @@ export class Project {
getSchema(): ProjectSchema { getSchema(): ProjectSchema {
return { return {
...this.data, ...this.data,
componentsTree: this.documents.map(doc => doc.schema), // todo: future change this filter
componentsTree: this.documents.filter((doc) => !doc.isBlank()).map((doc) => doc.schema),
}; };
} }
/** /**
* schema * schema
*
* @param autoOpen true string
*/ */
setSchema(schema?: ProjectSchema) { load(schema?: ProjectSchema, autoOpen?: boolean | string) {
this.unload();
// load new document
this.data = { this.data = {
version: '1.0.0', version: '1.0.0',
componentsMap: [], componentsMap: [],
componentsTree: [], componentsTree: [],
...schema, ...schema,
}; };
if (this.documents.length > 0) {
this.documents.forEach(doc => doc.purge()); if (autoOpen) {
this.documents.length = 0; if (autoOpen === true) {
// auto open first document or open a blank page
this.open(this.data.componentsTree[0]);
} else {
// auto open should be string of fileName
this.open(autoOpen);
} }
this.open( }
this.data.componentsTree[0] || { }
componentName: 'Page',
fileName: '', /**
}, *
); */
unload() {
if (this.documents.length < 1) {
return;
}
this.documents.forEach((doc) => doc.remove());
} }
/** /**
@ -86,14 +101,23 @@ export class Project {
| string, | string,
): any {} ): any {}
open(doc: string | DocumentModel | RootSchema): void { open(doc?: string | DocumentModel | RootSchema): void {
if (!doc) {
const got = this.documents.find((item) => item.isBlank());
if (got) {
return got.open();
}
doc = new DocumentModel(this);
this.documents.push(doc);
return doc.open();
}
if (typeof doc === 'string') { if (typeof doc === 'string') {
const got = this.documents.find(item => item.fileName === doc); const got = this.documents.find((item) => item.fileName === doc);
if (got) { if (got) {
return got.open(); return got.open();
} }
const data = this.data.componentsTree.find(data => data.fileName === doc); const data = this.data.componentsTree.find((data) => data.fileName === doc);
if (data) { if (data) {
doc = new DocumentModel(this, data); doc = new DocumentModel(this, data);
this.documents.push(doc); this.documents.push(doc);
@ -113,7 +137,7 @@ export class Project {
} }
checkExclusive(actived: DocumentModel) { checkExclusive(actived: DocumentModel) {
this.documents.forEach(doc => { this.documents.forEach((doc) => {
if (doc !== actived) { if (doc !== actived) {
doc.suspense(); doc.suspense();
} }
@ -122,7 +146,7 @@ export class Project {
} }
closeOthers(opened: DocumentModel) { closeOthers(opened: DocumentModel) {
this.documents.forEach(doc => { this.documents.forEach((doc) => {
if (doc !== opened) { if (doc !== opened) {
doc.close(); doc.close();
} }

View 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

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-editor-core", "name": "@ali/lowcode-editor-core",
"version": "0.8.0", "version": "0.8.4",
"description": "alibaba lowcode editor core", "description": "alibaba lowcode editor core",
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
@ -20,15 +20,15 @@
], ],
"author": "xiayang.xy", "author": "xiayang.xy",
"dependencies": { "dependencies": {
"@alifd/next": "1.x",
"debug": "^4.1.1", "debug": "^4.1.1",
"events": "^3.1.0", "events": "^3.1.0",
"intl-messageformat": "^8.3.1", "intl-messageformat": "^8.3.1",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"prop-types": "^15.5.8", "prop-types": "^15.5.8",
"store": "^2.0.12",
"whatwg-fetch": "^3.0.0",
"react": "^16.8.0", "react": "^16.8.0",
"@alifd/next": "1.x" "store": "^2.0.12",
"whatwg-fetch": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@alib/build-scripts": "^0.1.3", "@alib/build-scripts": "^0.1.3",

View File

@ -11,6 +11,8 @@ import {
PluginSet, PluginSet,
} from './definitions'; } from './definitions';
import pluginFactory from './pluginFactory';
import * as editorUtils from './utils'; import * as editorUtils from './utils';
const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils; const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
@ -92,7 +94,10 @@ export default class Editor extends EventEmitter {
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) { constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
super(); super();
this.config = config; this.config = config;
this.components = components; this.components = {};
Object.entries(components).forEach(([key, value]): void => {
this.components[key] = pluginFactory(value);
});
this.utils = { ...editorUtils, ...utils }; this.utils = { ...editorUtils, ...utils };
instance = this; instance = this;
} }

View File

@ -1,9 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "lib", "outDir": "lib"
"target": "es6",
"jsx": "react"
}, },
"include": [ "include": [
"./src/" "./src/"

View 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

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-editor-skeleton", "name": "@ali/lowcode-editor-skeleton",
"version": "0.8.0", "version": "0.8.5",
"description": "alibaba lowcode editor skeleton", "description": "alibaba lowcode editor skeleton",
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
@ -20,7 +20,7 @@
], ],
"author": "xiayang.xy", "author": "xiayang.xy",
"dependencies": { "dependencies": {
"@ali/lowcode-editor-core": "^0.8.0", "@ali/lowcode-editor-core": "^0.8.4",
"@alifd/next": "^1.x", "@alifd/next": "^1.x",
"prop-types": "^15.5.8", "prop-types": "^15.5.8",
"react": "^16.8.1", "react": "^16.8.1",

View File

@ -1,9 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "lib", "outDir": "lib"
"target": "es6",
"jsx": "react"
}, },
"include": [ "include": [
"./src/" "./src/"

View 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

View File

@ -1,7 +1,8 @@
{ {
"name": "@ali/lowcode-globals", "name": "@ali/lowcode-globals",
"version": "0.8.0", "version": "0.9.1",
"description": "Globals api for Ali lowCode engine", "description": "Globals api for Ali lowCode engine",
"license": "MIT",
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
"files": [ "files": [
@ -14,6 +15,16 @@
"test": "ava", "test": "ava",
"test:snapshot": "ava --update-snapshots" "test:snapshot": "ava --update-snapshots"
}, },
"ava": {
"compileEnhancements": false,
"extensions": [
"ts"
],
"require": [
"ts-node/register"
],
"snapshotDir": "test/fixtures/__snapshots__"
},
"dependencies": { "dependencies": {
"@alifd/next": "^1.19.16", "@alifd/next": "^1.19.16",
"@recore/obx": "^1.0.8", "@recore/obx": "^1.0.8",
@ -23,26 +34,15 @@
"react-dom": "^16.7.0" "react-dom": "^16.7.0"
}, },
"devDependencies": { "devDependencies": {
"@alib/build-scripts": "^0.1.18",
"@types/classnames": "^2.2.7", "@types/classnames": "^2.2.7",
"@types/node": "^13.7.1", "@types/node": "^13.7.1",
"@types/react": "^16", "@types/react": "^16",
"@types/react-dom": "^16", "@types/react-dom": "^16",
"@alib/build-scripts": "^0.1.18",
"build-plugin-component": "^0.2.11", "build-plugin-component": "^0.2.11",
"build-plugin-fusion": "^0.1.0", "build-plugin-fusion": "^0.1.0",
"build-plugin-moment-locales": "^0.1.0" "build-plugin-moment-locales": "^0.1.0"
}, },
"ava": {
"compileEnhancements": false,
"snapshotDir": "test/fixtures/__snapshots__",
"extensions": [
"ts"
],
"require": [
"ts-node/register"
]
},
"license": "MIT",
"publishConfig": { "publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com" "registry": "https://registry.npm.alibaba-inc.com"
} }

View File

@ -1,2 +1,3 @@
export * from './tip'; export * from './tip';
export * from './title'; export * from './title';
export * from './svg-icon';

View File

@ -16,7 +16,7 @@ export interface IconProps {
style?: object; style?: object;
} }
export function IconBase({ export function SVGIcon({
fill, fill,
size = 'medium', size = 'medium',
viewBox, viewBox,

View File

@ -16,7 +16,7 @@ function findTip(target: HTMLElement | null): TipOptions | null {
if (target.dataset && target.dataset.tip) { if (target.dataset && target.dataset.tip) {
return { return {
children: target.dataset.tip, children: target.dataset.tip,
direction: target.dataset.direction || target.dataset.dir, direction: (target.dataset.direction || target.dataset.dir) as any,
theme: target.dataset.theme, theme: target.dataset.theme,
target, target,
}; };

View File

@ -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';

View File

@ -1,7 +1,6 @@
export * from './intl'; export * from './intl';
export * from './components'; export * from './components';
export * from './utils'; export * from './utils';
export * from './icons';
export * from './types'; export * from './types';
export * from './di'; export * from './di';
export * from './obx'; export * from './obx';

View File

@ -5,7 +5,7 @@ export interface TipConfig {
className?: string; className?: string;
children?: I18nData | ReactNode; children?: I18nData | ReactNode;
theme?: string; theme?: string;
direction?: string; // 'n|s|w|e|top|bottom|left|right'; direction?: 'top' | 'bottom' | 'left' | 'right';
} }
export type TipContent = string | I18nData | ReactElement | TipConfig; export type TipContent = string | I18nData | ReactElement | TipConfig;

View 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);
}
}
}

View File

@ -19,3 +19,4 @@ export * from './shallow-equal';
export * from './unique-id'; export * from './unique-id';
export * from './get-public-path'; export * from './get-public-path';
export * from './is-form-event'; export * from './is-form-event';
export * from './hotkey';

View 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

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-material-parser", "name": "@ali/lowcode-material-parser",
"version": "0.8.0", "version": "0.9.0",
"description": "material parser for Ali lowCode engine", "description": "material parser for Ali lowCode engine",
"main": "lib/index.js", "main": "lib/index.js",
"files": [ "files": [
@ -20,6 +20,7 @@
"jest-watch-typeahead": "^0.3.1", "jest-watch-typeahead": "^0.3.1",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"json-schema-to-typescript": "^8.2.0", "json-schema-to-typescript": "^8.2.0",
"tslib": "^1.11.1",
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"scripts": { "scripts": {
@ -47,6 +48,7 @@
"@babel/parser": "^7.8.4", "@babel/parser": "^7.8.4",
"@babel/traverse": "^7.8.4", "@babel/traverse": "^7.8.4",
"@babel/types": "^7.8.3", "@babel/types": "^7.8.3",
"ast-types": "^0.13.3",
"cross-spawn-promise": "^0.10.2", "cross-spawn-promise": "^0.10.2",
"debug": "^4.1.1", "debug": "^4.1.1",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
@ -54,5 +56,8 @@
"react-docgen": "^5.3.0", "react-docgen": "^5.3.0",
"semver": "^7.1.3", "semver": "^7.1.3",
"short-uuid": "^3.1.1" "short-uuid": "^3.1.1"
},
"publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com"
} }
} }

View File

@ -17,7 +17,7 @@ const tsPath = path.resolve(__dirname, '../src/otter-core/schema/types.ts');
ajv.compile(schema); ajv.compile(schema);
fs.writeFileSync(JsonPath, JSON.stringify(schema, null, 2), 'utf-8'); fs.writeFileSync(JsonPath, JSON.stringify(schema, null, 2), 'utf-8');
console.log('yaml file is successfully transformed into json'); console.log('yaml file is successfully transformed into json');
const ts = await compile(schema, 'IComponentMaterial'); const ts = await compile(schema, 'ComponentMeta');
fs.writeFileSync(tsPath, ts); fs.writeFileSync(tsPath, ts);
console.log('schema.d.ts is successfully generated'); console.log('schema.d.ts is successfully generated');
} catch (e) { } catch (e) {

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