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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,11 @@
{
"version": "1.0.0",
"packages": {
"moment": {
"package": "moment",
"urls": ["https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"],
"library": "moment"
},
"@alifd/next": {
"title": "fusion组件库",
"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>
</head>
<body class="dark">
<body>
<div id="lce-container"></div>
</body>
</html>

View File

@ -1,6 +1,6 @@
import undoRedo from '@ali/lowcode-plugin-undo-redo';
import logo from '@ali/lowcode-plugin-logo';
import save from '@ali/lowcode-plugin-save';
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';
@ -9,10 +9,10 @@ import { PluginFactory } from '@ali/lowcode-editor-core';
export default {
logo: PluginFactory(logo),
save: PluginFactory(save),
samplePreview: PluginFactory(SamplePreview),
undoRedo: PluginFactory(undoRedo),
designer: PluginFactory(Designer),
componentsPane: PluginFactory(componentsPane),
settingsPane: PluginFactory(SettingsPane),
OutlinePane: PluginFactory(OutlinePane),
outlinePane: PluginFactory(OutlinePane),
};

View File

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

View File

View File

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

View File

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

View File

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

View File

@ -8,6 +8,7 @@ import {
obx,
autorun,
isNodeSchema,
uniqueId,
} from '@ali/lowcode-globals';
import { Project } from '../project';
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) {
autorun(() => {
this.nodes.forEach(item => {
this.nodes.forEach((item) => {
if (item.parent == null && item !== this.rootNode) {
item.purge();
}
});
}, true);
this.rootNode = this.createRootNode(schema);
this.id = this.rootNode.id;
this.history = new History(
() => this.schema,
schema => this.import(schema as RootSchema, true),
(schema) => this.import(schema as RootSchema, true),
);
this.setupListenActiveNodes();
}
@ -389,7 +389,9 @@ export class DocumentModel {
// todo:
}
purge() {}
purge() {
// todo:
}
checkNesting(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean {
let items: Array<Node | NodeSchema>;
@ -398,7 +400,7 @@ export class DocumentModel {
} else {
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 {
@ -408,7 +410,7 @@ export class DocumentModel {
} else {
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": {
"debug": "^4.1.1",
"events": "^3.1.0",
"intl-messageformat": "^7.8.4",
"intl-messageformat": "^8.3.1",
"lodash": "^4.17.15",
"prop-types": "^15.5.8",
"store": "^2.0.12",
"whatwg-fetch": "^3.0.0"
"whatwg-fetch": "^3.0.0",
"react": "^16.8.0",
"@alifd/next": "1.x"
},
"devDependencies": {
"@alib/build-scripts": "^0.1.3",
"@ice/spec": "^0.1.1",
"@types/lodash": "^4.14.149",
"@types/react": "^16.9.13",
"@types/react-dom": "^16.9.4",
"build-plugin-component": "^0.2.7-1",
"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"
"build-plugin-component": "^0.2.10"
},
"license": "MIT",
"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 './unique-id';
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';
componentDidMount(): void {
const { editor } = this.props;
editor.on('schema.reset', this.handleSchemaReset);
}
componentWillUmount(): void {
const { editor } = this.props;
editor.off('schema.reset', this.handleSchemaReset);
}
private designer?: Designer;
state = {
componentMetadatas: [],
state: DesignerPluginState = {
componentMetadatas: 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) : [],
library: packages ? Object.values(packages) : [],
});
/*
if (this.designer) {
this.designer.setSchema(schema);
};
if (this._lifeState === 0) {
this.state = state;
} else {
editor.once('designer.ready', (designer: Designer): void => {
designer.setSchema(schema);
});
this.setState(state);
}
*/
};
componentWillUnmount() {
this._lifeState = -1;
}
handleDesignerMount = (designer: Designer): void => {
const { editor } = this.props;
this.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 {
const { editor } = this.props;
const { componentMetadatas, library } = this.state;
if (!library) {
return 'loading';
if (!library || !componentMetadatas) {
// TODO: use a Loading
return 'assets loading';
}
return (
<DesignerView
onMount={this.handleDesignerMount}
className="lowcode-plugin-designer"
defaultSchema={SCHEMA as any}
eventPipe={editor}
componentMetadatas={componentMetadatas}
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.previous = node;
const x = Date.now();
console.info('set', x);
this.timer = setTimeout(() => {
console.info('done', x, Date.now() - x);
this.previous && this.decide(this.previous, this.event!);
this.reset();
}, this.timeout) as any;
@ -39,7 +36,6 @@ export default class DwellTimer {
}
reset() {
console.info('reset');
if (this.timer) {
clearTimeout(this.timer);
this.timer = undefined;

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,9 @@ import { IconSlot } from '../icons/slot';
export default class TreeTitle extends Component<{
treeNode: TreeNode;
}> {
state = {
state: {
editing: boolean;
} = {
editing: false,
};
@ -30,6 +32,7 @@ export default class TreeTitle extends Component<{
this.setState({
editing: false,
});
this.lastInput = undefined;
}
private saveEdit = (e: FocusEvent<HTMLInputElement> | KeyboardEvent<HTMLInputElement>) => {
@ -47,15 +50,15 @@ export default class TreeTitle extends Component<{
}
};
componentDidUpdate() {
// TODO:
/*
const { current } = this.inputRef;
if (current) {
current.select();
private lastInput?: HTMLInputElement;
private setCaret = (input: HTMLInputElement | null) => {
if (!input || this.lastInput === input) {
return;
}
*/
}
input.focus();
input.select();
input.selectionStart = input.selectionEnd;
};
render() {
const { treeNode } = this.props;
@ -90,16 +93,19 @@ export default class TreeTitle extends Component<{
className="tree-node-title-input"
defaultValue={treeNode.titleLabel}
onBlur={this.saveEdit}
ref={this.setCaret}
onKeyUp={this.handleKeyUp}
/>
) : (
<Fragment>
<Title title={treeNode.title} />
{node.slotFor && (<a className="tree-node-tag slot">
{/* todo: click redirect to prop */}
<IconSlot />
<EmbedTip>{intl('Slot for {prop}', { prop: node.slotFor.key })}</EmbedTip>
</a>)}
{node.slotFor && (
<a className="tree-node-tag slot">
{/* todo: click redirect to prop */}
<IconSlot />
<EmbedTip>{intl('Slot for {prop}', { prop: node.slotFor.key })}</EmbedTip>
</a>
)}
{node.hasLoop() && (
<a className="tree-node-tag loop">
{/* todo: click todo something */}
@ -125,9 +131,7 @@ export default class TreeTitle extends Component<{
}
@observer
class LockBtn extends Component<{
treeNode: TreeNode;
}> {
class LockBtn extends Component<{ treeNode: TreeNode }> {
shouldComponentUpdate() {
return false;
}
@ -136,7 +140,7 @@ class LockBtn extends Component<{
return (
<div
className="tree-node-lock-btn"
onClick={e => {
onClick={(e) => {
e.stopPropagation();
treeNode.setLocked(!treeNode.locked);
}}
@ -149,9 +153,7 @@ class LockBtn extends Component<{
}
@observer
class HideBtn extends Component<{
treeNode: TreeNode;
}> {
class HideBtn extends Component<{ treeNode: TreeNode }> {
shouldComponentUpdate() {
return false;
}
@ -160,7 +162,7 @@ class HideBtn extends Component<{
return (
<div
className="tree-node-hide-btn"
onClick={e => {
onClick={(e) => {
e.stopPropagation();
treeNode.setHidden(!treeNode.hidden);
}}
@ -173,9 +175,7 @@ class HideBtn extends Component<{
}
@observer
class ExpandBtn extends Component<{
treeNode: TreeNode;
}> {
class ExpandBtn extends Component<{ treeNode: TreeNode }> {
shouldComponentUpdate() {
return false;
}
@ -187,7 +187,7 @@ class ExpandBtn extends Component<{
return (
<div
className="tree-node-expand-btn"
onClick={e => {
onClick={(e) => {
if (treeNode.expanded) {
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 { observer } from '@ali/lowcode-globals';
import { observer, isFormEvent } from '@ali/lowcode-globals';
import { Tree } from '../tree';
import TreeNodeView from './tree-node';
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;
designer.activeTracker.track(node);
if (isMulti && !isRootNode(node) && selection.has(id)) {
selection.remove(id);
if (!isFormEvent(e.nativeEvent)) {
selection.remove(id);
}
} else {
selection.select(id);
}
@ -80,6 +82,9 @@ export default class TreeView extends Component<{ tree: Tree }> {
private ignoreUpSelected = false;
private boostEvent?: MouseEvent;
private onMouseDown = (e: ReactMouseEvent) => {
if (isFormEvent(e.nativeEvent)) {
return;
}
const treeNode = this.getTreeNodeFromEvent(e);
if (!treeNode) {
return;
@ -132,8 +137,8 @@ export default class TreeView extends Component<{ tree: Tree }> {
return (
<div
className="lc-outline-tree"
ref={shell => (this.shell = shell)}
onMouseDown={this.onMouseDown}
ref={(shell) => (this.shell = shell)}
onMouseDownCapture={this.onMouseDown}
onMouseOver={this.onMouseOver}
onClick={this.onClick}
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",
"description": "alibaba lowcode editor logo plugin",
"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",
"description": "alibaba lowcode editor save plugin",
"description": "alibaba lowcode editor sample save plugin",
"files": [
"es",
"lib"

View File

@ -1,7 +1,7 @@
import React from 'react';
import { Button } from '@alifd/next';
import { PluginProps } from '@ali/lowcode-editor-core';
import './index.scss';
import { PluginProps } from '@ali/lowcode-editor-core/lib/definitions';
const Save: React.FC<PluginProps> = (props): React.ReactElement => {
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 {
flex: 1;
min-width: 0;
outline: none;
.next-tabs-tab-inner {
text-align: center;
padding: 12px 0;

View File

@ -25,7 +25,7 @@
"dependencies": {
"@ali/b3-one": "^0.0.17",
"@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/lib-mtop": "^2.5.1",
"@alifd/next": "^1.18.17",
@ -33,7 +33,7 @@
"driver-universal": "^3.1.2",
"events": "^3.0.0",
"fetch-jsonp": "^1.1.3",
"intl-messageformat": "^7.7.2",
"intl-messageformat": "^8.3.1",
"jsonuri": "^2.1.2",
"keymaster": "^1.6.2",
"localforage": "^1.7.3",

View File

@ -8,6 +8,7 @@
"libraryExport": "default",
"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",
"version": "0.0.1",
"version": "0.8.0",
"description": "Runtime for Ali lowCode engine",
"files": [
"es",
@ -27,6 +27,13 @@
"dependencies": {
"@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": {
"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
find ./packages -type f -name "package-lock.json" -exec rm -f {} \;
yarn install
npm run bootstrap
yarn install --registry=http://registry.npm.alibaba-inc.com
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