Merge branch 'release/1.0.0' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into release/1.0.0

This commit is contained in:
荣彬 2020-08-16 21:41:06 +08:00
commit 4083945c5d
15 changed files with 1909 additions and 395 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -67,7 +67,7 @@
.event-menu {
max-height: 300px;
width: 230px;
width: 256px;
overflow-x: hidden;
position: absolute;
top: 67px;

View File

@ -29,30 +29,31 @@ export default class EventsSetter extends Component<{
selectType: null,
nativeEventList: [],
lifeCycleEventList: [],
eventDataList: this.props.value || [],
eventDataList: (this.props?.value?.eventDataList ? this.props.value.eventDataList : this.props?.value) || [],
relatedEventName: '',
};
// constructor (){
// super();
// debugger;
// if (!this.props || !this.props.value){
// this.setState({
// eventDataList:[]
// })
// }
// // if (!this.props || !this.props.value){
// // this.setState({
// // eventDataList:[]
// // })
// // }
// }
static getDerivedStateFromProps(nextProps, prevState) {
// const { value } = nextProps;
// debugger;
// if (value !== prevState.eventDataList) {
// return {
// value,
// };
// }
return null;
}
// static getDerivedStateFromProps(nextProps, prevState) {
// debugger;
// // const { value } = nextProps;
// // debugger;
// // if (value !== prevState.eventDataList) {
// // return {
// // value,
// // };
// // }
// return null;
// }
private bindEventName:String;
@ -310,7 +311,7 @@ export default class EventsSetter extends Component<{
};
deleteEvent = (eventName: String) => {
const { eventDataList } = this.state;
const { eventDataList,eventList} = this.state;
eventDataList.map((item, index) => {
if (item.name === eventName) {
eventDataList.splice(index, 1);
@ -320,7 +321,7 @@ export default class EventsSetter extends Component<{
this.setState({
eventDataList,
});
this.props.onChange({eventDataList,eventList});
this.updateEventListStatus(eventName, true);
};
@ -332,7 +333,7 @@ export default class EventsSetter extends Component<{
bindEvent = (relatedEventName: String) => {
const {eventDataList} = this.state;
const {eventDataList,eventList} = this.state;
eventDataList.map(item => {
if (item.name === this.bindEventName) {
item.relatedEventName = relatedEventName;
@ -344,7 +345,7 @@ export default class EventsSetter extends Component<{
})
this.props.onChange(eventDataList);
this.props.onChange({eventDataList,eventList});
//this.closeDialog();
};

View File

@ -206,7 +206,12 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
return val;
},
setValue(field: SettingTarget, eventDataList: any[]) {
setValue(field: SettingTarget, eventData) {
const {eventDataList,eventList} = eventData;
eventList.map((item)=>{
field.parent.clearPropValue(item.name);
return item;
})
eventDataList.map((item) => {
field.parent.setPropValue(item.name, {
type: 'JSFunction',

View File

@ -188,7 +188,7 @@ function propTypeToSetter(propType: PropType): SetterType {
};
}
const EVENT_RE = /^on[A-Z][\w]*$/;
const EVENT_RE = /^on|after[A-Z][\w]*$/;
export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata {
const { configure = {} } = metadata;

View File

@ -2,7 +2,7 @@ import React, { useState, ComponentType } from 'react';
import { Button, Dialog } from '@alifd/next';
import { PluginProps, NpmInfo } from '@ali/lowcode-types';
import { Designer } from '@ali/lowcode-designer';
import { buildComponents } from '@ali/lowcode-utils';
import { buildComponents, assetBundle, AssetList, AssetLevel, AssetLoader } from '@ali/lowcode-utils';
import ReactRenderer from '@ali/lowcode-react-renderer';
import './index.scss';
@ -16,15 +16,34 @@ const SamplePreview = ({ editor }: PluginProps) => {
const designer = editor.get(Designer);
if (designer) {
const assets = await editor.get('assets');
const { packages } = assets;
const { componentsMap, schema } = designer;
console.info('save schema:', designer, assets);
const libraryMap = {};
assets.packages.forEach(({ package, library }) => {
const libraryAsset: AssetList = [];
packages.forEach(({ package, library, urls }) => {
libraryMap[package] = library;
if (urls) {
libraryAsset.push(urls);
}
});
const vendors = [
assetBundle(libraryAsset, AssetLevel.Library),
];
console.log('libraryMap&vendors', libraryMap, vendors);
// TODO asset may cause pollution
const assetLoader = new AssetLoader();
await assetLoader.load(libraryAsset);
const components = buildComponents(libraryMap, componentsMap);
console.log('components', components);
setData({
schema: designer.schema.componentsTree[0],
components: buildComponents(libraryMap, designer.componentsMap),
schema: schema.componentsTree[0],
components,
});
setVisible(true);
}

View File

@ -275,9 +275,9 @@ export default class SourceEditor extends Component<{
</div>
<div className="full-screen-container" onClick={this.fullScreen}>
{/* <div className="full-screen-container" onClick={this.fullScreen}>
<img src="https://gw.alicdn.com/tfs/TB1d7XqE1T2gK0jSZFvXXXnFXXa-200-200.png"></img>
</div>
</div> */}
</div>
);
}

View File

@ -5,15 +5,16 @@ import SimulatorRendererView from './renderer-view';
import { computed, obx } from '@recore/obx';
import { Asset } from '@ali/lowcode-utils';
import { getClientRects } from './utils/get-client-rects';
import loader from './utils/loader';
import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes';
import { isElement, cursor, setNativeSelection, buildComponents, getSubComponent } from '@ali/lowcode-utils';
import { isElement, cursor, setNativeSelection, buildComponents, getSubComponent, AssetLoader } from '@ali/lowcode-utils';
import { RootSchema, ComponentSchema, TransformStage } from '@ali/lowcode-types';
// just use types
import { BuiltinSimulatorRenderer, NodeInstance, Component } from '@ali/lowcode-designer';
import Slot from './builtin-components/slot';
import Leaf from './builtin-components/leaf';
const loader = new AssetLoader();
export class SimulatorRenderer implements BuiltinSimulatorRenderer {
readonly isSimulatorRenderer = true;
private dispose?: () => void;

View File

@ -1,113 +0,0 @@
import { load, evaluate } from './script';
import StylePoint from './style';
import {
Asset,
AssetLevel,
AssetLevels,
AssetType,
AssetList,
isAssetBundle,
isAssetItem,
assetItem,
AssetItem,
isCSSUrl,
} from '@ali/lowcode-utils';
function parseAssetList(scripts: any, styles: any, assets: AssetList, level?: AssetLevel) {
for (const asset of assets) {
parseAsset(scripts, styles, asset, level);
}
}
function parseAsset(scripts: any, styles: any, asset: Asset | undefined | null, level?: AssetLevel) {
if (!asset) {
return;
}
if (Array.isArray(asset)) {
return parseAssetList(scripts, styles, asset, level);
}
if (isAssetBundle(asset)) {
if (asset.assets) {
if (Array.isArray(asset.assets)) {
parseAssetList(scripts, styles, asset.assets, asset.level || level);
} else {
parseAsset(scripts, styles, asset.assets, asset.level || level);
}
return;
}
return;
}
if (!isAssetItem(asset)) {
asset = assetItem(isCSSUrl(asset) ? AssetType.CSSUrl : AssetType.JSUrl, asset, level)!;
}
let lv = asset.level || level;
if (!lv || AssetLevel[lv] == null) {
lv = AssetLevel.App;
}
asset.level = lv;
if (asset.type === AssetType.CSSUrl || asset.type == AssetType.CSSText) {
styles[lv].push(asset);
} else {
scripts[lv].push(asset);
}
}
export class AssetLoader {
async load(asset: Asset) {
const styles: any = {};
const scripts: any = {};
AssetLevels.forEach(lv => {
styles[lv] = [];
scripts[lv] = [];
});
parseAsset(scripts, styles, asset);
const styleQueue: AssetItem[] = styles[AssetLevel.Environment].concat(
styles[AssetLevel.Library],
styles[AssetLevel.Theme],
styles[AssetLevel.Runtime],
styles[AssetLevel.App],
);
const scriptQueue: AssetItem[] = scripts[AssetLevel.Environment].concat(
scripts[AssetLevel.Library],
scripts[AssetLevel.Theme],
scripts[AssetLevel.Runtime],
scripts[AssetLevel.App],
);
await Promise.all(
styleQueue.map(({ content, level, type, id }) => this.loadStyle(content, level!, type === AssetType.CSSUrl, id)),
);
await Promise.all(scriptQueue.map(({ content, type }) => this.loadScript(content, type === AssetType.JSUrl)));
}
private stylePoints = new Map<string, StylePoint>();
private loadStyle(content: string | undefined | null, level: AssetLevel, isUrl?: boolean, id?: string) {
if (!content) {
return;
}
let point: StylePoint | undefined;
if (id) {
point = this.stylePoints.get(id);
if (!point) {
point = new StylePoint(level, id);
this.stylePoints.set(id, point);
}
} else {
point = new StylePoint(level);
}
return isUrl ? point.applyUrl(content) : point.applyText(content);
}
private loadScript(content: string | undefined | null, isUrl?: boolean) {
if (!content) {
return;
}
return isUrl ? load(content) : evaluate(content);
}
}
export default new AssetLoader();

View File

@ -1,73 +0,0 @@
import { createDefer } from './create-defer';
export default class StylePoint {
private lastContent: string | undefined;
private lastUrl: string | undefined;
private placeholder: Element | Text;
constructor(readonly level: number, readonly id?: string) {
let placeholder: any;
if (id) {
placeholder = document.head.querySelector(`style[data-id="${id}"]`);
}
if (!placeholder) {
placeholder = document.createTextNode('');
const meta = document.head.querySelector(`meta[level="${level}"]`);
if (meta) {
document.head.insertBefore(placeholder, meta);
} else {
document.head.appendChild(placeholder);
}
}
this.placeholder = placeholder;
}
applyText(content: string) {
if (this.lastContent === content) {
return;
}
this.lastContent = content;
this.lastUrl = undefined;
const element = document.createElement('style');
element.setAttribute('type', 'text/css');
if (this.id) {
element.setAttribute('data-id', this.id);
}
element.appendChild(document.createTextNode(content));
document.head.insertBefore(element, this.placeholder.parentNode === document.head ? this.placeholder.nextSibling : null);
document.head.removeChild(this.placeholder);
this.placeholder = element;
}
applyUrl(url: string) {
if (this.lastUrl === url) {
return;
}
this.lastContent = undefined;
this.lastUrl = url;
const element = document.createElement('link');
element.onload = onload;
element.onerror = onload;
const i = createDefer();
function onload(e: any) {
element.onload = null;
element.onerror = null;
if (e.type === 'load') {
i.resolve();
} else {
i.reject();
}
}
element.href = url;
element.rel = 'stylesheet';
if (this.id) {
element.setAttribute('data-id', this.id);
}
document.head.insertBefore(element, this.placeholder.parentNode === document.head ? this.placeholder.nextSibling : null);
document.head.removeChild(this.placeholder);
this.placeholder = element;
return i.promise();
}
}

View File

@ -1,3 +1,7 @@
import { isCSSUrl } from './is-css-url';
import { createDefer } from './create-defer';
import { load, evaluate } from './script';
export interface AssetItem {
type: AssetType;
content?: string | null;
@ -88,3 +92,172 @@ export function assetItem(type: AssetType, content?: string | null, level?: Asse
id,
};
}
export class StylePoint {
private lastContent: string | undefined;
private lastUrl: string | undefined;
private placeholder: Element | Text;
constructor(readonly level: number, readonly id?: string) {
let placeholder: any;
if (id) {
placeholder = document.head.querySelector(`style[data-id="${id}"]`);
}
if (!placeholder) {
placeholder = document.createTextNode('');
const meta = document.head.querySelector(`meta[level="${level}"]`);
if (meta) {
document.head.insertBefore(placeholder, meta);
} else {
document.head.appendChild(placeholder);
}
}
this.placeholder = placeholder;
}
applyText(content: string) {
if (this.lastContent === content) {
return;
}
this.lastContent = content;
this.lastUrl = undefined;
const element = document.createElement('style');
element.setAttribute('type', 'text/css');
if (this.id) {
element.setAttribute('data-id', this.id);
}
element.appendChild(document.createTextNode(content));
document.head.insertBefore(element, this.placeholder.parentNode === document.head ? this.placeholder.nextSibling : null);
document.head.removeChild(this.placeholder);
this.placeholder = element;
}
applyUrl(url: string) {
if (this.lastUrl === url) {
return;
}
this.lastContent = undefined;
this.lastUrl = url;
const element = document.createElement('link');
element.onload = onload;
element.onerror = onload;
const i = createDefer();
function onload(e: any) {
element.onload = null;
element.onerror = null;
if (e.type === 'load') {
i.resolve();
} else {
i.reject();
}
}
element.href = url;
element.rel = 'stylesheet';
if (this.id) {
element.setAttribute('data-id', this.id);
}
document.head.insertBefore(element, this.placeholder.parentNode === document.head ? this.placeholder.nextSibling : null);
document.head.removeChild(this.placeholder);
this.placeholder = element;
return i.promise();
}
}
function parseAssetList(scripts: any, styles: any, assets: AssetList, level?: AssetLevel) {
for (const asset of assets) {
parseAsset(scripts, styles, asset, level);
}
}
function parseAsset(scripts: any, styles: any, asset: Asset | undefined | null, level?: AssetLevel) {
if (!asset) {
return;
}
if (Array.isArray(asset)) {
return parseAssetList(scripts, styles, asset, level);
}
if (isAssetBundle(asset)) {
if (asset.assets) {
if (Array.isArray(asset.assets)) {
parseAssetList(scripts, styles, asset.assets, asset.level || level);
} else {
parseAsset(scripts, styles, asset.assets, asset.level || level);
}
return;
}
return;
}
if (!isAssetItem(asset)) {
asset = assetItem(isCSSUrl(asset) ? AssetType.CSSUrl : AssetType.JSUrl, asset, level)!;
}
let lv = asset.level || level;
if (!lv || AssetLevel[lv] == null) {
lv = AssetLevel.App;
}
asset.level = lv;
if (asset.type === AssetType.CSSUrl || asset.type == AssetType.CSSText) {
styles[lv].push(asset);
} else {
scripts[lv].push(asset);
}
}
export class AssetLoader {
async load(asset: Asset) {
const styles: any = {};
const scripts: any = {};
AssetLevels.forEach(lv => {
styles[lv] = [];
scripts[lv] = [];
});
parseAsset(scripts, styles, asset);
const styleQueue: AssetItem[] = styles[AssetLevel.Environment].concat(
styles[AssetLevel.Library],
styles[AssetLevel.Theme],
styles[AssetLevel.Runtime],
styles[AssetLevel.App],
);
const scriptQueue: AssetItem[] = scripts[AssetLevel.Environment].concat(
scripts[AssetLevel.Library],
scripts[AssetLevel.Theme],
scripts[AssetLevel.Runtime],
scripts[AssetLevel.App],
);
await Promise.all(
styleQueue.map(({ content, level, type, id }) => this.loadStyle(content, level!, type === AssetType.CSSUrl, id)),
);
await Promise.all(scriptQueue.map(({ content, type }) => this.loadScript(content, type === AssetType.JSUrl)));
}
private stylePoints = new Map<string, StylePoint>();
private loadStyle(content: string | undefined | null, level: AssetLevel, isUrl?: boolean, id?: string) {
if (!content) {
return;
}
let point: StylePoint | undefined;
if (id) {
point = this.stylePoints.get(id);
if (!point) {
point = new StylePoint(level, id);
this.stylePoints.set(id, point);
}
} else {
point = new StylePoint(level);
}
return isUrl ? point.applyUrl(content) : point.applyText(content);
}
private loadScript(content: string | undefined | null, isUrl?: boolean) {
if (!content) {
return;
}
return isUrl ? load(content) : evaluate(content);
}
}

View File

@ -1,5 +1,5 @@
import { ComponentType } from 'react';
import { NpmInfo} from '@ali/lowcode-types';
import { ComponentType, forwardRef, createElement } from 'react';
import { NpmInfo } from '@ali/lowcode-types';
import { isReactComponent } from './is-react';
import { isESModule } from './is-es-module';
@ -11,8 +11,16 @@ function accessLibrary(library: string | object) {
if (typeof library !== 'string') {
return library;
}
return (window as any)[library] || generateHtmlComp(library);
}
return (window as any)[library] || library;
export function generateHtmlComp(library: string) {
if (['a', 'img', 'div', 'span', 'svg'].includes(library)) {
return forwardRef((props, ref) => {
return createElement(library, { ref, ...props }, props.children);
});
}
}
export function getSubComponent(library: any, paths: string[]) {