chore: 🤖 update demo

This commit is contained in:
kangwei 2020-03-28 21:00:08 +08:00
parent 2587b9719c
commit 8174b42fa3
54 changed files with 364 additions and 16918 deletions

View File

@ -1,14 +1,13 @@
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"clean": "lerna clean -y", "clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
"setup": "./scripts/reinstall.sh", "setup": "./scripts/setup.sh",
"pub": "npm run test && lerna publish --registry http://registry.npm.alibaba-inc.com", "start": "./scripts/start.sh",
"lint": "eslint -p tsconfig.json", "build": "lerna exec -- npm run build",
"lint:fix": "eslint --fix -p tsconfig.json",
"build": "lerna run build",
"test": "lerna run test", "test": "lerna run test",
"test:snapshot": "lerna run test:snapshot", "test:snapshot": "lerna run test:snapshot",
"pub": "npm run test && lerna publish",
"commit": "git-cz" "commit": "git-cz"
}, },
"devDependencies": { "devDependencies": {
@ -36,15 +35,17 @@
"**/@alife/theme-lowcode-*" "**/@alife/theme-lowcode-*"
] ]
}, },
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": { "lint-staged": {
"*.{tsx,ts}": [ "*.{tsx,ts}": [
"eslint --fix", "eslint --quiet",
"git add" "git add"
] ]
}, },
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"config": { "config": {
"commitizen": { "commitizen": {
"path": "node_modules/cz-conventional-changelog" "path": "node_modules/cz-conventional-changelog"

View File

@ -4,6 +4,9 @@
"react-simulator-renderer": "../react-simulator-renderer/src/index.js" "react-simulator-renderer": "../react-simulator-renderer/src/index.js"
}, },
"vendor": false, "vendor": false,
"devServer": {
"hot": false
},
"publicPath": "/", "publicPath": "/",
"externals": { "externals": {
"react": "var window.React", "react": "var window.React",

View File

@ -7,6 +7,7 @@ module.exports = ({ onGetWebpackConfig }) => {
.use(TsconfigPathsPlugin, [{ .use(TsconfigPathsPlugin, [{
configFile: "./tsconfig.json" configFile: "./tsconfig.json"
}]); }]);
config.plugins.delete('hot');
config.devServer.hot(false); config.devServer.hot(false);
}); });
}; };

View File

@ -3,8 +3,7 @@
"version": "0.8.0", "version": "0.8.0",
"description": "低代码引擎 DEMO", "description": "低代码引擎 DEMO",
"scripts": { "scripts": {
"start": "build-scripts start", "start": "build-scripts start"
"build": "build-scripts build"
}, },
"dependencies": { "dependencies": {
"@ali/lowcode-editor-core": "^0.8", "@ali/lowcode-editor-core": "^0.8",

View File

@ -1,6 +1,11 @@
{ {
"version": "1.0.0", "version": "1.0.0",
"packages": { "packages": {
"moment": {
"package": "moment",
"urls": ["https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"],
"library": "moment"
},
"@alifd/next": { "@alifd/next": {
"title": "fusion组件库", "title": "fusion组件库",
"package": "@alifd/next", "package": "@alifd/next",

View File

@ -15,7 +15,7 @@
<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>
</head> </head>
<body class="dark"> <body>
<div id="lce-container"></div> <div id="lce-container"></div>
</body> </body>
</html> </html>

View File

@ -1,6 +1,6 @@
import undoRedo from '@ali/lowcode-plugin-undo-redo'; import undoRedo from '@ali/lowcode-plugin-undo-redo';
import logo from '@ali/lowcode-plugin-logo'; import logo from '@ali/lowcode-plugin-sample-logo';
import save from '@ali/lowcode-plugin-save'; import SamplePreview from '@ali/lowcode-plugin-sample-preview';
import Designer from '@ali/lowcode-plugin-designer'; import Designer from '@ali/lowcode-plugin-designer';
import SettingsPane from '@ali/lowcode-plugin-settings-pane'; import SettingsPane from '@ali/lowcode-plugin-settings-pane';
import componentsPane from '@ali/lowcode-plugin-components-pane'; import componentsPane from '@ali/lowcode-plugin-components-pane';
@ -9,10 +9,10 @@ import { PluginFactory } from '@ali/lowcode-editor-core';
export default { export default {
logo: PluginFactory(logo), logo: PluginFactory(logo),
save: PluginFactory(save), samplePreview: PluginFactory(SamplePreview),
undoRedo: PluginFactory(undoRedo), undoRedo: PluginFactory(undoRedo),
designer: PluginFactory(Designer), designer: PluginFactory(Designer),
componentsPane: PluginFactory(componentsPane), componentsPane: PluginFactory(componentsPane),
settingsPane: PluginFactory(SettingsPane), settingsPane: PluginFactory(SettingsPane),
OutlinePane: PluginFactory(OutlinePane), outlinePane: PluginFactory(OutlinePane),
}; };

View File

@ -21,7 +21,7 @@ export default {
width: 100 width: 100
}, },
config: { config: {
package: '@ali/lowcode-plugin-logo', package: '@ali/lowcode-plugin-sample-logo',
version: '1.0.0' version: '1.0.0'
}, },
pluginProps: { pluginProps: {
@ -49,14 +49,14 @@ export default {
} }
}, },
{ {
pluginKey: 'save', pluginKey: 'samplePreview',
type: 'Custom', type: 'Custom',
props: { props: {
align: 'right', align: 'right',
width: 64 width: 64
}, },
config: { config: {
package: '@ali/lowcode-plugin-save', package: '@ali/lowcode-plugin-sample-preview',
version: '1.0.0' version: '1.0.0'
} }
} }
@ -120,15 +120,12 @@ export default {
lifeCycles: { lifeCycles: {
init: async function init(editor) { init: async function init(editor) {
const assets = await editor.utils.get('/assets.json'); const assets = await editor.utils.get('/assets.json');
editor.set({ editor.set('assets', assets);
assets, editor.emit('assets.loaded', assets);
componentsMap: assets.components
});
editor.utils.get('/schema.json').then(res => { const schema = await editor.utils.get('/schema.json');
editor.set('schema', res); editor.set('schema', schema);
editor.emit('schema.reset', res); editor.emit('schema.loaded', schema);
});
} }
} }
}; };

View File

View File

@ -18,7 +18,7 @@ export class DesignerView extends Component<DesignerProps> {
const props = this.props; const props = this.props;
if ( if (
nextProps.className !== props.className || nextProps.className !== props.className ||
nextProps.style != props.style || nextProps.style !== props.style ||
nextProps.dragGhostComponent !== props.dragGhostComponent nextProps.dragGhostComponent !== props.dragGhostComponent
) { ) {
return true; return true;
@ -31,6 +31,7 @@ export class DesignerView extends Component<DesignerProps> {
if (onMount) { if (onMount) {
onMount(this.designer); onMount(this.designer);
} }
this.designer.postEvent('mount', this.designer);
} }
componentWillMount() { componentWillMount() {

View File

@ -153,10 +153,9 @@ export class Designer {
setupSelection(); setupSelection();
setupHistory(); setupHistory();
}); });
this.postEvent('designer.init', this);
setupSelection(); setupSelection();
setupHistory(); setupHistory();
this.postEvent('designer.ready', this);
} }
postEvent(event: string, ...args: any[]) { postEvent(event: string, ...args: any[]) {
@ -223,7 +222,8 @@ export class Designer {
} }
private props?: DesignerProps; private props?: DesignerProps;
setProps(props: DesignerProps) { setProps(nextProps: DesignerProps) {
const props = this.props ? { ...this.props, ...nextProps } : nextProps;
if (this.props) { if (this.props) {
// check hotkeys // check hotkeys
// TODO: // TODO:

View File

@ -159,23 +159,24 @@ function makeEventsHandler(
): (fn: (sdoc: Document) => void) => void { ): (fn: (sdoc: Document) => void) => void {
const topDoc = window.top.document; const topDoc = window.top.document;
const sourceDoc = boostEvent.view?.document || topDoc; const sourceDoc = boostEvent.view?.document || topDoc;
const boostPrevented = boostEvent.defaultPrevented; // TODO: optimize this logic, reduce listener
// const boostPrevented = boostEvent.defaultPrevented;
const docs = new Set<Document>(); const docs = new Set<Document>();
if (boostPrevented || isDragEvent(boostEvent)) { // if (boostPrevented || isDragEvent(boostEvent)) {
docs.add(topDoc); docs.add(topDoc);
} // }
docs.add(sourceDoc); docs.add(sourceDoc);
if (sourceDoc !== topDoc || isDragEvent(boostEvent)) { // if (sourceDoc !== topDoc || isDragEvent(boostEvent)) {
sensors.forEach(sim => { sensors.forEach((sim) => {
const sdoc = sim.contentDocument; const sdoc = sim.contentDocument;
if (sdoc) { if (sdoc) {
docs.add(sdoc); docs.add(sdoc);
} }
}); });
} // }
return (handle: (sdoc: Document) => void) => { return (handle: (sdoc: Document) => void) => {
docs.forEach(doc => handle(doc)); docs.forEach((doc) => handle(doc));
}; };
} }
@ -232,7 +233,7 @@ export class Dragon {
const masterSensors = this.getMasterSensors(); const masterSensors = this.getMasterSensors();
const handleEvents = makeEventsHandler(boostEvent, masterSensors); const handleEvents = makeEventsHandler(boostEvent, masterSensors);
const newBie = !isDragNodeObject(dragObject); const newBie = !isDragNodeObject(dragObject);
const forceCopyState = isDragNodeObject(dragObject) && dragObject.nodes.some(node => node.isSlotRoot); const forceCopyState = isDragNodeObject(dragObject) && dragObject.nodes.some((node) => node.isSlotRoot);
const isBoostFromDragAPI = boostEvent.type.substr(0, 4) === 'drag'; const isBoostFromDragAPI = boostEvent.type.substr(0, 4) === 'drag';
let lastSensor: ISensor | undefined; let lastSensor: ISensor | undefined;
@ -310,7 +311,7 @@ export class Dragon {
this.setDraggingState(true); this.setDraggingState(true);
// ESC cancel drag // ESC cancel drag
if (!isBoostFromDragAPI) { if (!isBoostFromDragAPI) {
handleEvents(doc => { handleEvents((doc) => {
doc.addEventListener('keydown', checkesc, false); doc.addEventListener('keydown', checkesc, false);
}); });
} }
@ -366,7 +367,7 @@ export class Dragon {
} }
} }
handleEvents(doc => { handleEvents((doc) => {
if (isBoostFromDragAPI) { if (isBoostFromDragAPI) {
doc.removeEventListener('dragover', move, true); doc.removeEventListener('dragover', move, true);
doc.removeEventListener('dragend', over, true); doc.removeEventListener('dragend', over, true);
@ -404,7 +405,7 @@ export class Dragon {
if (lastSim && lastSim.contentDocument === sourceDocument) { if (lastSim && lastSim.contentDocument === sourceDocument) {
srcSim = lastSim; srcSim = lastSim;
} else { } else {
srcSim = masterSensors.find(sim => sim.contentDocument === sourceDocument); srcSim = masterSensors.find((sim) => sim.contentDocument === sourceDocument);
if (!srcSim && lastSim) { if (!srcSim && lastSim) {
srcSim = lastSim; srcSim = lastSim;
} }
@ -428,7 +429,7 @@ export class Dragon {
const sourceSensor = getSourceSensor(dragObject); const sourceSensor = getSourceSensor(dragObject);
const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors); const sensors: ISensor[] = (masterSensors as ISensor[]).concat(this.sensors);
const chooseSensor = (e: LocateEvent) => { const chooseSensor = (e: LocateEvent) => {
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
if (lastSensor) { if (lastSensor) {
@ -473,7 +474,7 @@ export class Dragon {
this.setNativeSelection(false); this.setNativeSelection(false);
} }
handleEvents(doc => { handleEvents((doc) => {
if (isBoostFromDragAPI) { if (isBoostFromDragAPI) {
doc.addEventListener('dragover', move, true); doc.addEventListener('dragover', move, true);
// dragexit // dragexit
@ -490,7 +491,7 @@ export class Dragon {
// future think: drag things from browser-out or a iframe-pane // future think: drag things from browser-out or a iframe-pane
if (!newBie && !isBoostFromDragAPI) { if (!newBie && !isBoostFromDragAPI) {
handleEvents(doc => { handleEvents((doc) => {
doc.addEventListener('keydown', checkcopy, false); doc.addEventListener('keydown', checkcopy, false);
doc.addEventListener('keyup', checkcopy, false); doc.addEventListener('keyup', checkcopy, false);
}); });
@ -499,7 +500,7 @@ export class Dragon {
private getMasterSensors(): ISimulatorHost[] { private getMasterSensors(): ISimulatorHost[] {
return this.designer.project.documents return this.designer.project.documents
.map(doc => { .map((doc) => {
// TODO: not use actived, // TODO: not use actived,
if (doc.actived && doc.simulator?.sensorAvailable) { if (doc.actived && doc.simulator?.sensorAvailable) {
return doc.simulator; return doc.simulator;
@ -512,7 +513,7 @@ export class Dragon {
// #region ======== drag and drop helpers ============ // #region ======== drag and drop helpers ============
private setNativeSelection(enableFlag: boolean) { private setNativeSelection(enableFlag: boolean) {
setNativeSelection(enableFlag); setNativeSelection(enableFlag);
this.designer.project.documents.forEach(doc => { this.designer.project.documents.forEach((doc) => {
doc.simulator?.setNativeSelection(enableFlag); doc.simulator?.setNativeSelection(enableFlag);
}); });
} }
@ -522,7 +523,7 @@ export class Dragon {
*/ */
private setDraggingState(state: boolean) { private setDraggingState(state: boolean) {
cursor.setDragging(state); cursor.setDragging(state);
this.designer.project.documents.forEach(doc => { this.designer.project.documents.forEach((doc) => {
doc.simulator?.setDraggingState(state); doc.simulator?.setDraggingState(state);
}); });
} }
@ -532,7 +533,7 @@ export class Dragon {
*/ */
private setCopyState(state: boolean) { private setCopyState(state: boolean) {
cursor.setCopy(state); cursor.setCopy(state);
this.designer.project.documents.forEach(doc => { this.designer.project.documents.forEach((doc) => {
doc.simulator?.setCopyState(state); doc.simulator?.setCopyState(state);
}); });
} }
@ -542,7 +543,7 @@ export class Dragon {
*/ */
private clearState() { private clearState() {
cursor.release(); cursor.release();
this.designer.project.documents.forEach(doc => { this.designer.project.documents.forEach((doc) => {
doc.simulator?.clearState(); doc.simulator?.clearState();
}); });
} }

View File

@ -8,6 +8,7 @@ import {
obx, obx,
autorun, autorun,
isNodeSchema, isNodeSchema,
uniqueId,
} from '@ali/lowcode-globals'; } from '@ali/lowcode-globals';
import { Project } from '../project'; import { Project } from '../project';
import { ISimulatorHost } from '../simulator'; import { ISimulatorHost } from '../simulator';
@ -27,7 +28,7 @@ export class DocumentModel {
/** /**
* *
*/ */
readonly id: string; readonly id: string = uniqueId('doc');
/** /**
* *
*/ */
@ -68,17 +69,16 @@ export class DocumentModel {
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) {
item.purge(); item.purge();
} }
}); });
}, true); }, true);
this.rootNode = this.createRootNode(schema); this.rootNode = this.createRootNode(schema);
this.id = this.rootNode.id;
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),
); );
this.setupListenActiveNodes(); this.setupListenActiveNodes();
} }
@ -389,7 +389,9 @@ export class DocumentModel {
// todo: // todo:
} }
purge() {} purge() {
// todo:
}
checkNesting(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean { checkNesting(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean {
let items: Array<Node | NodeSchema>; let items: Array<Node | NodeSchema>;
@ -398,7 +400,7 @@ export class DocumentModel {
} else { } else {
items = dragObject.nodes; items = dragObject.nodes;
} }
return items.every(item => this.checkNestingDown(dropTarget, item)); return items.every((item) => this.checkNestingDown(dropTarget, item));
} }
checkDropTarget(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean { checkDropTarget(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean {
@ -408,7 +410,7 @@ export class DocumentModel {
} else { } else {
items = dragObject.nodes; items = dragObject.nodes;
} }
return items.every(item => this.checkNestingUp(dropTarget, item)); return items.every((item) => this.checkNestingUp(dropTarget, item));
} }
/** /**

View File

@ -22,27 +22,20 @@
"dependencies": { "dependencies": {
"debug": "^4.1.1", "debug": "^4.1.1",
"events": "^3.1.0", "events": "^3.1.0",
"intl-messageformat": "^7.8.4", "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", "store": "^2.0.12",
"whatwg-fetch": "^3.0.0" "whatwg-fetch": "^3.0.0",
"react": "^16.8.0",
"@alifd/next": "1.x"
}, },
"devDependencies": { "devDependencies": {
"@alib/build-scripts": "^0.1.3", "@alib/build-scripts": "^0.1.3",
"@ice/spec": "^0.1.1",
"@types/lodash": "^4.14.149", "@types/lodash": "^4.14.149",
"@types/react": "^16.9.13", "@types/react": "^16.9.13",
"@types/react-dom": "^16.9.4", "@types/react-dom": "^16.9.4",
"build-plugin-component": "^0.2.7-1", "build-plugin-component": "^0.2.10"
"eslint": "^6.0.1",
"prettier": "^1.19.1",
"react": "^16.8.0",
"react-dom": "^16.8.0"
},
"peerDependencies": {
"react": "^16.8.0",
"@alifd/next": "1.x"
}, },
"license": "MIT", "license": "MIT",
"homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-editor-core@0.0.1/build/index.html" "homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-editor-core@0.0.1/build/index.html"

View File

@ -18,3 +18,4 @@ export * from './set-prototype-of';
export * from './shallow-equal'; 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';

View File

@ -0,0 +1,14 @@
export function isFormEvent(e: KeyboardEvent | MouseEvent) {
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;
}

View File

@ -147,70 +147,84 @@ const SCHEMA = {
], ],
}; };
const BaseLibrary = ["https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"]; interface DesignerPluginState {
componentMetadatas?: any[] | null;
library?: any[] | null;
}
export default class DesignerPlugin extends PureComponent<PluginProps> { export default class DesignerPlugin extends PureComponent<PluginProps, DesignerPluginState> {
static displayName: 'LowcodePluginDesigner'; static displayName: 'LowcodePluginDesigner';
componentDidMount(): void { state: DesignerPluginState = {
const { editor } = this.props; componentMetadatas: null,
editor.on('schema.reset', this.handleSchemaReset);
}
componentWillUmount(): void {
const { editor } = this.props;
editor.off('schema.reset', this.handleSchemaReset);
}
private designer?: Designer;
state = {
componentMetadatas: [],
library: null, library: null,
}; };
handleSchemaReset = (schema: any): void => {
const { editor } = this.props;
const { components, packages } = editor.get('assets') || {};
this.setState({ private _lifeState = 0;
constructor(props: any) {
super(props);
const { editor } = this.props;
const assets = editor.get('assets');
if (assets) {
this.setupAssets(assets);
} else {
editor.once('assets.loaded', this.setupAssets);
}
this._lifeState = 1;
}
setupAssets = (assets: any) => {
if (this._lifeState < 0) {
return;
}
const { components, packages } = assets;
const state = {
componentMetadatas: components ? Object.values(components) : [], componentMetadatas: components ? Object.values(components) : [],
library: packages ? Object.values(packages) : [], library: packages ? Object.values(packages) : [],
});
/*
if (this.designer) {
this.designer.setSchema(schema);
} else {
editor.once('designer.ready', (designer: Designer): void => {
designer.setSchema(schema);
});
}
*/
}; };
if (this._lifeState === 0) {
this.state = state;
} else {
this.setState(state);
}
};
componentWillUnmount() {
this._lifeState = -1;
}
handleDesignerMount = (designer: Designer): void => { handleDesignerMount = (designer: Designer): void => {
const { editor } = this.props; const { editor } = this.props;
this.designer = designer;
editor.set('designer', designer); editor.set('designer', designer);
// editor.emit('designer.ready', designer); editor.emit('designer.ready', designer);
const schema = editor.get('schema');
if (schema) {
designer.project.open(schema);
}
editor.on('schema.loaded', (schema) => {
designer.project.open(schema);
});
}; };
render(): React.ReactNode { render(): React.ReactNode {
const { editor } = this.props; const { editor } = this.props;
const { componentMetadatas, library } = this.state; const { componentMetadatas, library } = this.state;
if (!library) { if (!library || !componentMetadatas) {
return 'loading'; // TODO: use a Loading
return 'assets loading';
} }
return ( return (
<DesignerView <DesignerView
onMount={this.handleDesignerMount} onMount={this.handleDesignerMount}
className="lowcode-plugin-designer" className="lowcode-plugin-designer"
defaultSchema={SCHEMA as any}
eventPipe={editor} eventPipe={editor}
componentMetadatas={componentMetadatas} componentMetadatas={componentMetadatas}
simulatorProps={{ simulatorProps={{
library: BaseLibrary.concat(library || []), library,
}} }}
/> />
); );

View File

@ -1 +0,0 @@
## todo

View File

@ -17,10 +17,7 @@ export default class DwellTimer {
} }
this.reset(); this.reset();
this.previous = node; this.previous = node;
const x = Date.now();
console.info('set', x);
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
console.info('done', x, Date.now() - x);
this.previous && this.decide(this.previous, this.event!); this.previous && this.decide(this.previous, this.event!);
this.reset(); this.reset();
}, this.timeout) as any; }, this.timeout) as any;
@ -39,7 +36,6 @@ export default class DwellTimer {
} }
reset() { reset() {
console.info('reset');
if (this.timer) { if (this.timer) {
clearTimeout(this.timer); clearTimeout(this.timer);
this.timer = undefined; this.timer = undefined;

View File

@ -1,6 +1,5 @@
{ {
"Designer not found": "Designer not found", "Initializing": "Initializing",
"No opened document": "No opened document",
"Hide": "Hide", "Hide": "Hide",
"Show": "Show", "Show": "Show",
"Lock": "Lock", "Lock": "Lock",

View File

@ -1,6 +1,5 @@
{ {
"Designer not found": "未发现设计器模块", "Initializing": "正在初始化",
"No opened document": "没有打开的文档",
"Hide": "隐藏", "Hide": "隐藏",
"Show": "显示", "Show": "显示",
"Lock": "锁定", "Lock": "锁定",

View File

@ -68,6 +68,7 @@ class TreeMaster {
const doc = this.designer?.currentDocument; const doc = this.designer?.currentDocument;
if (doc) { if (doc) {
const id = doc.id; const id = doc.id;
console.info(id);
if (this.treeMap.has(id)) { if (this.treeMap.has(id)) {
return this.treeMap.get(id)!; return this.treeMap.get(id)!;
} }
@ -96,13 +97,16 @@ export class OutlineMain implements ISensor, IScrollBoard, IScrollable {
get master() { get master() {
return this._master; return this._master;
} }
readonly id = uniqueId('tree'); @computed get currentTree() {
return this._master?.currentTree;
}
readonly id = uniqueId('outline');
constructor(readonly editor: any) { constructor(readonly editor: any) {
if (editor.designer) { if (editor.designer) {
this.setupDesigner(editor.designer); this.setupDesigner(editor.designer);
} else { } else {
editor.once('designer.ready', (designer: Designer) => { editor.once('designer.mount', (designer: Designer) => {
this.setupDesigner(designer); this.setupDesigner(designer);
}); });
} }
@ -404,7 +408,7 @@ export class OutlineMain implements ISensor, IScrollBoard, IScrollable {
let items: TreeNode[] | null = null; let items: TreeNode[] | null = null;
let slotsRect: DOMRect | undefined; let slotsRect: DOMRect | undefined;
let focusSlots: boolean = false; let focusSlots = false;
// isSlotContainer // isSlotContainer
if (isSlotContainer) { if (isSlotContainer) {
slotsRect = this.getTreeSlotsRect(treeNode); slotsRect = this.getTreeSlotsRect(treeNode);
@ -491,7 +495,7 @@ export class OutlineMain implements ISensor, IScrollBoard, IScrollable {
/** /**
* @see IScrollBoard * @see IScrollBoard
*/ */
scrollToNode(treeNode: TreeNode, detail?: any, tryTimes: number = 0) { scrollToNode(treeNode: TreeNode, detail?: any, tryTimes = 0) {
if (tryTimes < 1 && this.tryScrollAgain) { if (tryTimes < 1 && this.tryScrollAgain) {
(window as any).cancelIdleCallback(this.tryScrollAgain); (window as any).cancelIdleCallback(this.tryScrollAgain);
this.tryScrollAgain = null; this.tryScrollAgain = null;
@ -576,7 +580,7 @@ export class OutlineMain implements ISensor, IScrollBoard, IScrollable {
// todo purge treeMaster if needed // todo purge treeMaster if needed
} }
private _sensorAvailable: boolean = false; private _sensorAvailable = false;
/** /**
* @see ISensor * @see ISensor
*/ */
@ -644,13 +648,7 @@ function checkRecursion(parent: Node | undefined | null, dragObject: DragObject)
function getPosFromEvent( function getPosFromEvent(
{ target }: LocateEvent, { target }: LocateEvent,
stop: Element, stop: Element,
): ): null | 'unchanged' | { nodeId: string; focusSlots: boolean } {
| null
| 'unchanged'
| {
nodeId: string;
focusSlots: boolean;
} {
if (!target || !stop.contains(target)) { if (!target || !stop.contains(target)) {
return null; return null;
} }

View File

@ -18,27 +18,21 @@ export default class OutlinePane extends Component<{ editor: any }> {
} }
render() { render() {
if (!this.main.master) { const tree = this.main.currentTree;
return (
<div className="lc-outline-pane">
<p className="lc-outline-notice">{intl('Designer not found')}</p>
</div>
);
}
const tree = this.main.master.currentTree; console.info('tree', tree);
if (!tree) { if (!tree) {
return ( return (
<div className="lc-outline-pane"> <div className="lc-outline-pane">
<p className="lc-outline-notice">{intl('No opened document')}</p> <p className="lc-outline-notice">{intl('Initializing')}</p>
</div> </div>
); );
} }
return ( return (
<div className="lc-outline-pane"> <div className="lc-outline-pane">
<div ref={shell => this.main.mount(shell)} className="lc-outline-tree-container"> <div ref={(shell) => this.main.mount(shell)} className="lc-outline-tree-container">
<TreeView key={tree.id} tree={tree} /> <TreeView key={tree.id} tree={tree} />
</div> </div>
</div> </div>

View File

@ -16,7 +16,9 @@ import { IconSlot } from '../icons/slot';
export default class TreeTitle extends Component<{ export default class TreeTitle extends Component<{
treeNode: TreeNode; treeNode: TreeNode;
}> { }> {
state = { state: {
editing: boolean;
} = {
editing: false, editing: false,
}; };
@ -30,6 +32,7 @@ export default class TreeTitle extends Component<{
this.setState({ this.setState({
editing: false, editing: false,
}); });
this.lastInput = undefined;
} }
private saveEdit = (e: FocusEvent<HTMLInputElement> | KeyboardEvent<HTMLInputElement>) => { private saveEdit = (e: FocusEvent<HTMLInputElement> | KeyboardEvent<HTMLInputElement>) => {
@ -47,15 +50,15 @@ export default class TreeTitle extends Component<{
} }
}; };
componentDidUpdate() { private lastInput?: HTMLInputElement;
// TODO: private setCaret = (input: HTMLInputElement | null) => {
/* if (!input || this.lastInput === input) {
const { current } = this.inputRef; return;
if (current) {
current.select();
}
*/
} }
input.focus();
input.select();
input.selectionStart = input.selectionEnd;
};
render() { render() {
const { treeNode } = this.props; const { treeNode } = this.props;
@ -90,16 +93,19 @@ export default class TreeTitle extends Component<{
className="tree-node-title-input" className="tree-node-title-input"
defaultValue={treeNode.titleLabel} defaultValue={treeNode.titleLabel}
onBlur={this.saveEdit} onBlur={this.saveEdit}
ref={this.setCaret}
onKeyUp={this.handleKeyUp} onKeyUp={this.handleKeyUp}
/> />
) : ( ) : (
<Fragment> <Fragment>
<Title title={treeNode.title} /> <Title title={treeNode.title} />
{node.slotFor && (<a className="tree-node-tag slot"> {node.slotFor && (
<a className="tree-node-tag slot">
{/* todo: click redirect to prop */} {/* todo: click redirect to prop */}
<IconSlot /> <IconSlot />
<EmbedTip>{intl('Slot for {prop}', { prop: node.slotFor.key })}</EmbedTip> <EmbedTip>{intl('Slot for {prop}', { prop: node.slotFor.key })}</EmbedTip>
</a>)} </a>
)}
{node.hasLoop() && ( {node.hasLoop() && (
<a className="tree-node-tag loop"> <a className="tree-node-tag loop">
{/* todo: click todo something */} {/* todo: click todo something */}
@ -125,9 +131,7 @@ export default class TreeTitle extends Component<{
} }
@observer @observer
class LockBtn extends Component<{ class LockBtn extends Component<{ treeNode: TreeNode }> {
treeNode: TreeNode;
}> {
shouldComponentUpdate() { shouldComponentUpdate() {
return false; return false;
} }
@ -136,7 +140,7 @@ class LockBtn extends Component<{
return ( return (
<div <div
className="tree-node-lock-btn" className="tree-node-lock-btn"
onClick={e => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
treeNode.setLocked(!treeNode.locked); treeNode.setLocked(!treeNode.locked);
}} }}
@ -149,9 +153,7 @@ class LockBtn extends Component<{
} }
@observer @observer
class HideBtn extends Component<{ class HideBtn extends Component<{ treeNode: TreeNode }> {
treeNode: TreeNode;
}> {
shouldComponentUpdate() { shouldComponentUpdate() {
return false; return false;
} }
@ -160,7 +162,7 @@ class HideBtn extends Component<{
return ( return (
<div <div
className="tree-node-hide-btn" className="tree-node-hide-btn"
onClick={e => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
treeNode.setHidden(!treeNode.hidden); treeNode.setHidden(!treeNode.hidden);
}} }}
@ -173,9 +175,7 @@ class HideBtn extends Component<{
} }
@observer @observer
class ExpandBtn extends Component<{ class ExpandBtn extends Component<{ treeNode: TreeNode }> {
treeNode: TreeNode;
}> {
shouldComponentUpdate() { shouldComponentUpdate() {
return false; return false;
} }
@ -187,7 +187,7 @@ class ExpandBtn extends Component<{
return ( return (
<div <div
className="tree-node-expand-btn" className="tree-node-expand-btn"
onClick={e => { onClick={(e) => {
if (treeNode.expanded) { if (treeNode.expanded) {
e.stopPropagation(); e.stopPropagation();
} }
@ -200,3 +200,52 @@ class ExpandBtn extends Component<{
); );
} }
} }
/*
interface Point {
clientX: number;
clientY: number;
}
function setCaret(point: Point) {
debugger;
const range = getRangeFromPoint(point);
if (range) {
selectRange(range);
setTimeout(() => selectRange(range), 1);
}
}
function getRangeFromPoint(point: Point): Range | undefined {
const x = point.clientX;
const y = point.clientY;
let range;
let pos: CaretPosition | null = null;
if (document.caretRangeFromPoint) {
range = document.caretRangeFromPoint(x, y);
} else if ((pos = document.caretPositionFromPoint(x, y))) {
range = document.createRange();
range.setStart(pos.offsetNode, pos.offset);
range.collapse(true);
}
return range;
}
function selectRange(range: Range) {
const selection = document.getSelection();
if (selection) {
selection.removeAllRanges();
selection.addRange(range);
}
}
function setCaretAfter(elem) {
const range = document.createRange();
const node = elem.lastChild;
if (!node) return;
range.setStartAfter(node);
range.setEndAfter(node);
selectRange(range);
}
*/

View File

@ -1,5 +1,5 @@
import { Component, MouseEvent as ReactMouseEvent } from 'react'; import { Component, MouseEvent as ReactMouseEvent } from 'react';
import { observer } from '@ali/lowcode-globals'; import { observer, isFormEvent } from '@ali/lowcode-globals';
import { Tree } from '../tree'; import { Tree } from '../tree';
import TreeNodeView from './tree-node'; import TreeNodeView from './tree-node';
import { isRootNode, Node, DragObjectType, isShaken } from '@ali/lowcode-designer'; import { isRootNode, Node, DragObjectType, isShaken } from '@ali/lowcode-designer';
@ -54,7 +54,9 @@ export default class TreeView extends Component<{ tree: Tree }> {
const isMulti = e.metaKey || e.ctrlKey; const isMulti = e.metaKey || e.ctrlKey;
designer.activeTracker.track(node); designer.activeTracker.track(node);
if (isMulti && !isRootNode(node) && selection.has(id)) { if (isMulti && !isRootNode(node) && selection.has(id)) {
if (!isFormEvent(e.nativeEvent)) {
selection.remove(id); selection.remove(id);
}
} else { } else {
selection.select(id); selection.select(id);
} }
@ -80,6 +82,9 @@ export default class TreeView extends Component<{ tree: Tree }> {
private ignoreUpSelected = false; private ignoreUpSelected = false;
private boostEvent?: MouseEvent; private boostEvent?: MouseEvent;
private onMouseDown = (e: ReactMouseEvent) => { private onMouseDown = (e: ReactMouseEvent) => {
if (isFormEvent(e.nativeEvent)) {
return;
}
const treeNode = this.getTreeNodeFromEvent(e); const treeNode = this.getTreeNodeFromEvent(e);
if (!treeNode) { if (!treeNode) {
return; return;
@ -132,8 +137,8 @@ export default class TreeView extends Component<{ tree: Tree }> {
return ( return (
<div <div
className="lc-outline-tree" className="lc-outline-tree"
ref={shell => (this.shell = shell)} ref={(shell) => (this.shell = shell)}
onMouseDown={this.onMouseDown} onMouseDownCapture={this.onMouseDown}
onMouseOver={this.onMouseOver} onMouseOver={this.onMouseOver}
onClick={this.onClick} onClick={this.onClick}
onMouseLeave={this.onMouseLeave} onMouseLeave={this.onMouseLeave}

View File

@ -0,0 +1,3 @@
## todo
Sample logo plugin

View File

@ -1,5 +1,5 @@
{ {
"name": "@ali/lowcode-plugin-logo", "name": "@ali/lowcode-plugin-sample-logo",
"version": "0.8.0", "version": "0.8.0",
"description": "alibaba lowcode editor logo plugin", "description": "alibaba lowcode editor logo plugin",
"files": [ "files": [

View File

@ -0,0 +1,3 @@
## todo
Sample preview plugin

View File

@ -0,0 +1,34 @@
{
"name": "@ali/lowcode-plugin-sample-preview",
"version": "0.8.0",
"description": "alibaba lowcode editor sample preview plugin",
"files": [
"es",
"lib"
],
"main": "lib/index.js",
"module": "es/index.js",
"scripts": {
"build": "build-scripts build --skip-demo",
"test": "ava",
"test:snapshot": "ava --update-snapshots"
},
"keywords": [
"lowcode",
"editor"
],
"dependencies": {
"@alifd/next": "^1.x",
"react": "^16.8.1",
"@ali/lowcode-editor-core": "^0.8.0",
"@ali/lowcode-designer": "^0.8.0"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.3",
"@types/react": "^16.9.13",
"@types/react-dom": "^16.9.4",
"build-plugin-component": "^0.2.11",
"build-plugin-fusion": "^0.1.0",
"build-plugin-moment-locales": "^0.1.0"
}
}

View File

@ -0,0 +1,3 @@
.lowcode-plugin-sample-preview {
padding: 10px 4px;
}

View File

@ -0,0 +1,24 @@
import React from 'react';
import { Button } from '@alifd/next';
import { PluginProps } from '@ali/lowcode-editor-core';
import { Designer } from '@ali/lowcode-designer';
import './index.scss';
const SamplePreview = ({ editor }: PluginProps) => {
const handleClick = () => {
const designer = editor.get('designer') as Designer;
console.info('save schema:', designer.schema);
localStorage.setItem('lce-dev-store', JSON.stringify(designer.schema));
window.open('./preview.html', 'preview');
};
return (
<div className="lowcode-plugin-sample-preview">
<Button type="primary" onClick={handleClick}>
</Button>
</div>
);
};
export default SamplePreview;

View File

@ -0,0 +1,3 @@
## todo
Sample save plugin

View File

@ -0,0 +1,9 @@
{
"plugins": [
"build-plugin-component",
"build-plugin-fusion",
["build-plugin-moment-locales", {
"locales": ["zh-cn"]
}]
]
}

View File

@ -1,7 +1,7 @@
{ {
"name": "@ali/lowcode-plugin-save", "name": "@ali/lowcode-plugin-sample-save",
"version": "0.8.0", "version": "0.8.0",
"description": "alibaba lowcode editor save plugin", "description": "alibaba lowcode editor sample save plugin",
"files": [ "files": [
"es", "es",
"lib" "lib"

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { Button } from '@alifd/next'; import { Button } from '@alifd/next';
import { PluginProps } from '@ali/lowcode-editor-core';
import './index.scss'; import './index.scss';
import { PluginProps } from '@ali/lowcode-editor-core/lib/definitions';
const Save: React.FC<PluginProps> = (props): React.ReactElement => { const Save: React.FC<PluginProps> = (props): React.ReactElement => {
const handleClick = (): void => { const handleClick = (): void => {

View File

@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.json",
"include": ["src/*.ts", "src/*.tsx"],
"exclude": ["node_modules", "build", "public"]
}

View File

@ -1 +0,0 @@
## todo

View File

@ -104,6 +104,7 @@
.next-tabs-tab.lc-settings-tab-item { .next-tabs-tab.lc-settings-tab-item {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
outline: none;
.next-tabs-tab-inner { .next-tabs-tab-inner {
text-align: center; text-align: center;
padding: 12px 0; padding: 12px 0;

View File

@ -25,7 +25,7 @@
"dependencies": { "dependencies": {
"@ali/b3-one": "^0.0.17", "@ali/b3-one": "^0.0.17",
"@ali/bzb-request": "^2.6.0-beta.13", "@ali/bzb-request": "^2.6.0-beta.13",
"@ali/iceluna-comp-div": "^0.0.5", "@ali/iceluna-comp-div": "^1.0.0",
"@ali/iceluna-rax": "0.0.5", "@ali/iceluna-rax": "0.0.5",
"@ali/lib-mtop": "^2.5.1", "@ali/lib-mtop": "^2.5.1",
"@alifd/next": "^1.18.17", "@alifd/next": "^1.18.17",
@ -33,7 +33,7 @@
"driver-universal": "^3.1.2", "driver-universal": "^3.1.2",
"events": "^3.0.0", "events": "^3.0.0",
"fetch-jsonp": "^1.1.3", "fetch-jsonp": "^1.1.3",
"intl-messageformat": "^7.7.2", "intl-messageformat": "^8.3.1",
"jsonuri": "^2.1.2", "jsonuri": "^2.1.2",
"keymaster": "^1.6.2", "keymaster": "^1.6.2",
"localforage": "^1.7.3", "localforage": "^1.7.3",

View File

@ -8,6 +8,7 @@
"libraryExport": "default", "libraryExport": "default",
"libraryTarget": "umd" "libraryTarget": "umd"
} }
] ],
"./build.plugin.js"
] ]
} }

View File

@ -0,0 +1,5 @@
module.exports = ({ onGetWebpackConfig }) => {
onGetWebpackConfig((config) => {
config.performance.hints(false);
});
};

View File

@ -0,0 +1,9 @@
{
"plugins": [
"build-plugin-component",
"build-plugin-fusion",
["build-plugin-moment-locales", {
"locales": ["zh-cn"]
}]
]
}

View File

@ -1,6 +1,6 @@
{ {
"name": "@ali/lowcode-runtime", "name": "@ali/lowcode-runtime",
"version": "0.0.1", "version": "0.8.0",
"description": "Runtime for Ali lowCode engine", "description": "Runtime for Ali lowCode engine",
"files": [ "files": [
"es", "es",
@ -27,6 +27,13 @@
"dependencies": { "dependencies": {
"@ali/recore": "^1.6.9" "@ali/recore": "^1.6.9"
}, },
"devDependencies": {
"@types/react-dom": "^16",
"@alib/build-scripts": "^0.1.18",
"build-plugin-component": "^0.2.11",
"@types/node": "^13.7.1",
"@types/react": "^16"
},
"publishConfig": { "publishConfig": {
"registry": "https://registry.npm.alibaba-inc.com" "registry": "https://registry.npm.alibaba-inc.com"
} }

View File

@ -1,5 +0,0 @@
import test from 'ava';
test('foobar', t => {
t.pass();
});

View File

@ -4,5 +4,5 @@ rm -rf node_modules package-lock.json
lerna clean -y lerna clean -y
find ./packages -type f -name "package-lock.json" -exec rm -f {} \; find ./packages -type f -name "package-lock.json" -exec rm -f {} \;
yarn install yarn install --registry=http://registry.npm.alibaba-inc.com
npm run bootstrap lerna bootstrap

5
scripts/start.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
# FIXME! do not run build
lerna exec --scope @ali/lowcode-react-renderer -- npm run build
lerna exec --scope @ali/lowcode-demo -- npm start

16731
yarn.lock

File diff suppressed because it is too large Load Diff