feat: merge live mode

This commit is contained in:
wanying.jwy 2020-08-16 15:28:25 +08:00
parent dc950336b5
commit 92c303967a
12 changed files with 124 additions and 34 deletions

View File

@ -15,8 +15,14 @@ export class BemTools extends Component<{ host: BuiltinSimulatorHost }> {
}
render() {
const host = this.props.host;
// yiyi
// live 模式选中,画布会不会有相关交互
const { host } = this.props;
const { designMode } = host;
const { scrollX, scrollY, scale } = host.viewport;
if (designMode === 'live') {
return null;
}
return (
<div className="lc-bem-tools" style={{ transform: `translate(${-scrollX * scale}px,${-scrollY * scale}px)` }}>
<BorderDetecting key="hovering" host={host} />

View File

@ -288,7 +288,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
}
setupDragAndClick() {
const designer = this.designer;
const documentModel = this.project.currentDocument;
if (!documentModel) return;
const selection = documentModel.selection;
const designer = documentModel.designer;
const doc = this.contentDocument!;
// TODO: think of lock when edit a node
@ -299,10 +302,17 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
// fix for popups close logic
document.dispatchEvent(new Event('mousedown'));
const documentModel = this.project.currentDocument;
if (this.liveEditing.editing || !documentModel) {
let isMulti = false;
if (this.designMode === 'design') {
isMulti = downEvent.metaKey || downEvent.ctrlKey;
} else if (!downEvent.metaKey) {
return;
}
const selection = documentModel.selection;
if (this.liveEditing.editing) {
return;
}
const selection = documentModel?.selection;
// stop response document focus event
downEvent.stopPropagation();
downEvent.preventDefault();
@ -312,23 +322,29 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element);
const node = nodeInst?.node || documentModel.rootNode;
const node = nodeInst?.node || documentModel?.rootNode;
if (!node?.isValidComponent()) {
// 对于未注册组件直接返回
return;
}
const isMulti = downEvent.metaKey || downEvent.ctrlKey;
const isLeftButton = downEvent.which === 1 || downEvent.button === 0;
const checkSelect = (e: MouseEvent) => {
doc.removeEventListener('mouseup', checkSelect, true);
// 鼠标是否移动
if (!isShaken(downEvent, e)) {
const id = node.id;
let id = node.id;
designer.activeTracker.track({ node, instance: nodeInst?.instance });
if (isMulti && !isRootNode(node) && selection.has(id)) {
if (isMulti && !isRootNode(node) && selection?.has(id)) {
selection.remove(id);
} else {
selection.select(id);
if (node.isPage() && node.getChildren()?.notEmpty()) {
const firstChildId = node
.getChildren()
?.get(0)
?.getId();
if (firstChildId) id = firstChildId;
}
selection?.select(id);
// dirty code should refector
const editor = this.designer?.editor;
@ -349,15 +365,15 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
let ignoreUpSelected = false;
if (isMulti) {
// multi select mode, directily add
if (!selection.has(node.id)) {
if (!selection?.has(node.id)) {
designer.activeTracker.track({ node, instance: nodeInst?.instance });
selection.add(node.id);
selection?.add(node.id);
ignoreUpSelected = true;
}
selection.remove(documentModel.rootNode.id);
selection?.remove(documentModel.rootNode.id);
// 获得顶层 nodes
nodes = selection.getTopNodes();
} else if (selection.containsNode(node, true)) {
nodes = selection?.getTopNodes();
} else if (selection?.containsNode(node, true)) {
nodes = selection.getTopNodes();
} else {
// will clear current selection & select dragment in dragstart
@ -412,7 +428,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
const doc = this.contentDocument!;
const detecting = this.designer.detecting;
const hover = (e: MouseEvent) => {
if (!detecting.enable) {
if (!detecting.enable || this.designMode !== 'design') {
return;
}
const nodeInst = this.getNodeInstanceFromElement(e.target as Element);

View File

@ -40,7 +40,7 @@ export class DesignerView extends Component<DesignerProps & {
if (onMount) {
onMount(this.designer);
}
clipboard.injectCopyPaster(document)
clipboard.injectCopyPaster(document);
this.designer.postEvent('mount', this.designer);
}

View File

@ -30,6 +30,15 @@ export class Project {
return this.documents.find((doc) => doc.actived);
}
@obx private _config: any = {};
@computed get config(): any {
// TODO: parse layout Component
return this._config;
}
set config(value: any) {
this._config = value;
}
/**
* schema
*/
@ -55,6 +64,7 @@ export class Project {
componentsTree: [],
...schema,
};
this.config = schema?.config;
if (autoOpen) {
if (autoOpen === true) {
@ -91,9 +101,14 @@ export class Project {
| 'i18n'
| 'css'
| 'dataSource'
| 'config'
| string,
value: any,
): void {}
): void {
if (key === 'config') {
this.config = value;
}
}
/**
*
@ -108,8 +123,13 @@ export class Project {
| 'i18n'
| 'css'
| 'dataSource'
| 'config'
| string,
): any {}
): any {
if (key === 'config') {
return this.config;
}
}
private documentsMap = new Map<string, DocumentModel>();

View File

@ -20,6 +20,7 @@ globalContext.register(editor, Editor);
export const skeleton = new Skeleton(editor);
editor.set(Skeleton, skeleton);
editor.set('skeleton', skeleton);
editor.set('designMode', 'live');
export const designer = new Designer({ editor: editor });
editor.set(Designer, designer);
@ -279,6 +280,9 @@ skeleton.add({
name: 'settingsPane',
type: 'Panel',
content: SettingsPrimaryPane,
props: {
ignoreRoot: true,
},
});
skeleton.add({
area: 'leftArea',

View File

@ -52,6 +52,15 @@ const pages = Object.assign(project, {
version: '1.0.0',
componentsMap: [],
componentsTree,
config: {
layout: {
componentName: 'MiniappTabNav',
props: {
logo: '',
name: '测试网站',
},
},
},
}, true);
},
addPage(data: OldPageData | RootSchema) {

View File

@ -1,17 +1,15 @@
export class Project {
private schema: any;
import { designer } from './editor';
constructor() {
this.schema = {};
}
const { project } = designer;
getSchema() {
return this.schema;
}
Object.assign(project, {
getSchema(): any {
return this.schema || {};
},
setSchema(schema: any) {
this.schema = schema;
}
}
},
});
export default new Project();
export default project;

View File

@ -7,7 +7,7 @@ import { SettingsPane } from './settings-pane';
import { createIcon } from '@ali/lowcode-utils';
@observer
export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
export class SettingsPrimaryPane extends Component<{ editor: Editor; config: any }> {
private main = new SettingsMain(this.props.editor);
@obx.ref private _activeKey?: any;
@ -22,6 +22,8 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
renderBreadcrumb() {
const { settings } = this.main;
const { config } = this.props;
const shouldIgnoreRoot = config.props?.ignoreRoot;
if (!settings) {
return null;
}
@ -43,6 +45,10 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> {
let l = 3;
while (l-- > 0 && node) {
const _node = node;
if (shouldIgnoreRoot && node.isRoot()) {
node = null;
continue;
}
const props =
l === 2
? {}

View File

@ -13,6 +13,7 @@ interface DesignerPluginState {
extraEnvironment?: any[] | null;
renderEnv?: string;
device?: string;
designMode?: string;
}
export default class DesignerPlugin extends PureComponent<PluginProps, DesignerPluginState> {
@ -24,6 +25,7 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
extraEnvironment: null,
renderEnv: 'default',
device: 'default',
designMode: 'live',
};
private _mounted = true;
@ -39,6 +41,7 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
const assets = await editor.onceGot('assets');
const renderEnv = await editor.get('renderEnv');
const device = await editor.get('device');
const designMode = await editor.get('designMode');
if (!this._mounted) {
return;
}
@ -49,6 +52,7 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
extraEnvironment,
renderEnv,
device,
designMode,
};
this.setState(state);
} catch (e) {
@ -71,7 +75,7 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
render(): React.ReactNode {
const { editor } = this.props;
const { componentMetadatas, library, extraEnvironment, renderEnv, device } = this.state;
const { componentMetadatas, library, extraEnvironment, renderEnv, device, designMode } = this.state;
if (!library || !componentMetadatas) {
// TODO: use a Loading
@ -90,6 +94,7 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
extraEnvironment,
renderEnv,
device,
designMode,
}}
/>
);

View File

@ -90,8 +90,13 @@ class Layout extends Component<{ rendererContainer: SimulatorRendererContainer }
const layout = rendererContainer.layout;
if (layout) {
const { Component, props } = layout;
return <Component props={props}>{children}</Component>;
const { Component, props, componentName } = layout;
if (Component) {
return <Component props={props}>{children}</Component>;
}
if (componentName) {
return createElement(rendererContainer.getComponent(componentName), {}, [children]);
}
}
return <Fragment>{children}</Fragment>;

View File

@ -0,0 +1,19 @@
export interface AppConfig {
sdkVersion?: string;
historyMode?: string;
targetRootID?: string;
layout?: Layout;
theme?: Theme;
[key: string]: any;
}
interface Theme {
package: string;
version: string;
primary: string;
}
interface Layout {
componentName?: string;
props?: Record<string, any>;
}

View File

@ -3,6 +3,7 @@ import { CompositeValue, JSExpression, CompositeObject, JSONObject } from './val
import { DataSource } from './data-source';
import { I18nMap } from './i18n';
import { UtilsMap } from './utils';
import { AppConfig } from './app-config';
export interface NodeSchema {
id?: string;
@ -83,6 +84,7 @@ export interface ProjectSchema {
constants?: JSONObject;
css?: string;
dataSource?: DataSource;
config?: AppConfig;
}
export function isNodeSchema(data: any): data is NodeSchema {