diff --git a/packages/demo/build.plugin.js b/packages/demo/build.plugin.js index 50ac34ddd..6c89f05c1 100644 --- a/packages/demo/build.plugin.js +++ b/packages/demo/build.plugin.js @@ -16,7 +16,7 @@ module.exports = ({ onGetWebpackConfig }) => { .plugin('MonacoWebpackPlugin') // 第一项为具体插件,第二项为插件参数 .use(new MonacoWebpackPlugin({ - languages:["javascript","css","json"] + languages:["typescript","css","json"] }), []); config.plugins.delete('hot'); diff --git a/packages/demo/src/vision/index.ts b/packages/demo/src/vision/index.ts index e01b724c6..3ab9ef186 100644 --- a/packages/demo/src/vision/index.ts +++ b/packages/demo/src/vision/index.ts @@ -11,6 +11,7 @@ import PageHistoryPane from '@ali/ve-page-history-pane'; // import I18nPane from '@ali/ve-i18n-pane'; import I18nManagePane from '@ali/ve-i18n-manage-pane'; import ActionPane from '@ali/ve-action-pane'; +import SourceEditor from '@ali/lowcode-plugin-source-editor'; import fetchContext from '@ali/vu-legao-design-fetch-context'; import EventBindDialog from '@ali/lowcode-plugin-event-bind-dialog'; import loadUrls from './loader'; @@ -95,16 +96,43 @@ function initDemoPanes() { type: 'Widget', content: EventBindDialog, }); - skeleton.add({ - area: 'leftArea', - name: 'icon1', - type: 'Dock', - props: { - align: 'bottom', - icon: 'set', - description: '设置' - }, - }); + + // skeleton.add({ + // area: 'left', + // name: 'sourceEditor', + // type: "PanelDock", + // content: SourceEditor, + // props: { + // align: undefined, + // description: "动作面板", + // onDestroy: undefined, + // icon: 'set', + // onInit: undefined + // }, + // panelProps:{ + // height: 300, + // help: undefined, + // hideTitleBar: true, + // maxHeight: 800, + // maxWidth: 1200, + // title: "动作面板", + // width: 600 + // } + + // }); + + // skeleton.add({ + // area: 'leftArea', + // name: 'icon1', + // type: 'PanelDock', + // props: { + // align: 'bottom', + // icon: 'set', + // description: '设置' + // }, + // }); + + skeleton.add({ area: 'leftArea', name: 'icon2', @@ -129,6 +157,8 @@ function initDemoPanes() { children: '发布', }), }); + + skeleton.add({ area: 'topArea', type: 'Dock', @@ -322,6 +352,7 @@ function initActionPane() { enableHeaderTip: true, }; + Panes.add(ActionPane, { props, }); diff --git a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx index 209fce326..33303c2fc 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx +++ b/packages/designer/src/builtin-simulator/bem-tools/border-selecting.tsx @@ -15,6 +15,7 @@ import { ActionContentObject, isActionContentObject } from '@ali/lowcode-types'; import { BuiltinSimulatorHost } from '../host'; import { OffsetObserver } from '../../designer'; import { Node } from '../../document'; +import NodeSelector from '../node-selector'; @observer export class BorderSelectingInstance extends Component<{ @@ -68,7 +69,6 @@ class Toolbar extends Component<{ observed: OffsetObserver }> { let style: any; if (observed.top > SPACE_HEIGHT) { style = { - right: Math.max(-BORDER, observed.right - width - BORDER), top: -SPACE_HEIGHT, height: BAR_HEIGHT, }; @@ -76,15 +76,18 @@ class Toolbar extends Component<{ observed: OffsetObserver }> { style = { bottom: -SPACE_HEIGHT, height: BAR_HEIGHT, - right: Math.max(-BORDER, observed.right - width - BORDER), }; } else { style = { height: BAR_HEIGHT, top: Math.max(MARGIN, MARGIN - observed.top), - right: Math.max(MARGIN, MARGIN + observed.right - width), }; } + if (observed.width < 140) { + style.left = Math.max(-BORDER, observed.left - width - BORDER); + } else { + style.right = Math.max(-BORDER, observed.right - width - BORDER); + } const { node } = observed; const actions: ReactNodeArray = []; node.componentMeta.availableActions.forEach((action) => { @@ -100,6 +103,7 @@ class Toolbar extends Component<{ observed: OffsetObserver }> { return (
{actions} +
); } diff --git a/packages/designer/src/builtin-simulator/bem-tools/borders.less b/packages/designer/src/builtin-simulator/bem-tools/borders.less index 7effde36a..a2469519c 100644 --- a/packages/designer/src/builtin-simulator/bem-tools/borders.less +++ b/packages/designer/src/builtin-simulator/bem-tools/borders.less @@ -30,7 +30,8 @@ } } - &-action { + &-action, + .ve-icon-button.ve-action-save { box-sizing: border-box; cursor: pointer; height: 20px; diff --git a/packages/designer/src/builtin-simulator/host.less b/packages/designer/src/builtin-simulator/host.less index ea009f455..d183408f2 100644 --- a/packages/designer/src/builtin-simulator/host.less +++ b/packages/designer/src/builtin-simulator/host.less @@ -31,12 +31,13 @@ &-device-iphone6 { left: 50%; - width: 368px; + width: 378px; transform: translateX(-50%); background: url(https://img.alicdn.com/tps/TB12GetLpXXXXXhXFXXXXXXXXXX-756-1544.png) no-repeat top; background-size: 378px 772px; top: 8px; .@{scope}-canvas-viewport { + width: auto; top: 114px; left: 25px; right: 25px; diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index 6f9a2d9da..04aad80ad 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -77,7 +77,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost item.condition(prop))?.onSaveContent || defaultSaveContent; setterPropElement.setAttribute('contenteditable', matched?.mode && matched.mode !== 'plaintext' ? 'true' : 'plaintext-only'); + setterPropElement.removeAttribute('for'); setterPropElement.classList.add('engine-live-editing'); // be sure setterPropElement.focus(); @@ -107,14 +108,24 @@ export class LiveEditing { onSaveContent(setterPropElement!.innerText, prop); }; - this._dispose = () => { - setterPropElement!.removeAttribute('contenteditable'); - setterPropElement!.classList.remove('engine-live-editing'); + const keydown = (e: KeyboardEvent) => { + console.info(e.code); + // esc + // enter + // tab }; - - setterPropElement.addEventListener('focusout', (e) => { + const focusout = (e: FocusEvent) => { this.saveAndDispose(); - }); + }; + setterPropElement.addEventListener('focusout', focusout); + setterPropElement.addEventListener('keydown', keydown, true); + + this._dispose = () => { + setterPropElement!.classList.remove('engine-live-editing'); + setterPropElement!.removeAttribute('contenteditable'); + setterPropElement!.removeEventListener('focusout', focusout); + setterPropElement!.removeEventListener('keydown', keydown, true); + }; this._editing = prop; } diff --git a/packages/designer/src/builtin-simulator/node-selector/index.less b/packages/designer/src/builtin-simulator/node-selector/index.less new file mode 100644 index 000000000..c630e0914 --- /dev/null +++ b/packages/designer/src/builtin-simulator/node-selector/index.less @@ -0,0 +1,82 @@ +@import '~@ali/ve-less-variables/index.less'; + +// 样式直接沿用之前的样式,优化了下命名 +.instance-node-selector { + position: relative; + margin-right: 2px; + color: var(--color-icon-white, @title-bgcolor); + border-radius: @global-border-radius; + margin-right: 2px; + pointer-events: auto; + flex-grow: 0; + flex-shrink: 0; + + svg { + width: 16px; + height: 16px; + margin-right: 5px; + flex-grow: 0; + flex-shrink: 0; + max-width: inherit; + path { + fill: var(--color-icon-white, @title-bgcolor); + } + } + &-current { + background: var(--color-brand, @brand-color-1); + padding: 0 6px; + display: flex; + align-items: center; + height: 20px; + cursor: pointer; + color: var(--color-icon-white, @title-bgcolor); + border-radius: 3px; + + &-title { + padding-right: 6px; + color: var(--color-icon-white, @title-bgcolor); + } + } + &-list { + position: absolute; + left: 0; + right: 0; + opacity: 0; + visibility: hidden; + } + &-node { + margin: 2px 0; + &-content { + padding-left: 6px; + background: #78869a; + display: inline-flex; + border-radius: 3px; + align-items: center; + height: 20px; + color: var(--color-icon-white, @title-bgcolor); + cursor: pointer; + overflow: visible; + } + &-title { + padding-right: 6px; + // margin-left: 5px; + color: var(--color-icon-white, @title-bgcolor); + cursor: pointer; + overflow: visible; + } + &:hover { + opacity: 0.8; + } + } +} + +&:hover { + .instance-node-selector-current { + color: ar(--color-text-reverse, @white-alpha-2); + } + .instance-node-selector-popup { + visibility: visible; + opacity: 1; + transition: 0.2s all ease-in; + } +} diff --git a/packages/designer/src/builtin-simulator/node-selector/index.tsx b/packages/designer/src/builtin-simulator/node-selector/index.tsx new file mode 100644 index 000000000..5d1118294 --- /dev/null +++ b/packages/designer/src/builtin-simulator/node-selector/index.tsx @@ -0,0 +1,111 @@ +import { Overlay } from '@alifd/next'; +import React from 'react'; +import './index.less'; +import { Title } from '@ali/lowcode-editor-core'; + +import { Node, ParentalNode } from '@ali/lowcode-designer'; + +const { Popup } = Overlay; + +export interface IProps { + node: Node; +} + +export interface IState { + parentNodes: Node[]; +} + +type UnionNode = Node | ParentalNode | null; + +export default class InstanceNodeSelector extends React.Component { + state: IState = { + parentNodes: [], + }; + + componentDidMount() { + const parentNodes = this.getParentNodes(this.props.node); + this.setState({ + parentNodes, + }); + } + + // 获取节点的父级节点(最多获取5层) + getParentNodes = (node: Node) => { + const parentNodes = []; + let currentNode: UnionNode = node; + + while (currentNode && parentNodes.length < 5) { + currentNode = currentNode.getParent(); + if (currentNode) { + parentNodes.push(currentNode); + } + } + return parentNodes; + }; + + onSelect = (node: Node) => () => { + if (node && typeof node.select === 'function') { + node.select(); + } + }; + onMouseOver = (node: Node) => (_: any, flag = true) => { + if (node && typeof node.hover === 'function') { + node.hover(flag); + } + }; + onMouseOut = (node: Node) => (_: any, flag = false) => { + if (node && typeof node.hover === 'function') { + node.hover(flag); + } + }; + renderNodes = (node: Node) => { + const nodes = this.state.parentNodes || []; + const children = nodes.map((node, key) => { + return ( +
+
+ + </div> + </div> + ); + }); + return children; + }; + + render() { + const { node } = this.props; + return ( + <div className="instance-node-selector"> + <Popup + trigger={ + <div className="instance-node-selector-current"> + <Title + className="instance-node-selector-node-title" + title={{ + label: node.title, + icon: node.icon, + }} + /> + </div> + } + triggerType="hover" + offset={[0, 2]} + > + <div className="instance-node-selector">{this.renderNodes(node)}</div> + </Popup> + </div> + ); + } +} diff --git a/packages/designer/src/designer/setting/utils.js b/packages/designer/src/designer/setting/utils.js index 64f063da3..ab09545e6 100644 --- a/packages/designer/src/designer/setting/utils.js +++ b/packages/designer/src/designer/setting/utils.js @@ -47,6 +47,9 @@ export class Transducer { } if (typeof setter === 'string') { setter = getSetter(setter)?.component; + if (!setter) { + debugger; + } } this.setterTransducer = combineTransducer( diff --git a/packages/designer/src/simulator.ts b/packages/designer/src/simulator.ts index fd3e7dcaf..0979ce40e 100644 --- a/packages/designer/src/simulator.ts +++ b/packages/designer/src/simulator.ts @@ -81,7 +81,10 @@ export interface ISimulatorHost<P = object> extends ISensor { // later: // layout: ComponentName // 获取区块代码, 通过 components 传递,可异步获取 + // 设置 simulator Props setProps(props: P): void; + // 设置单个 Prop + set(key: string, value: any): void; setSuspense(suspensed: boolean): void; diff --git a/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx b/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx index 77c9eda0f..182a521b7 100644 --- a/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx +++ b/packages/editor-skeleton/src/components/settings/settings-primary-pane.tsx @@ -96,6 +96,7 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor }> { return ( <div className="lc-settings-main"> <Tab + key={settings.id} navClassName="lc-settings-tabs" animation={false} excessMode="dropdown" diff --git a/packages/editor-skeleton/src/layouts/workbench.less b/packages/editor-skeleton/src/layouts/workbench.less index 019835cb7..deec754a1 100644 --- a/packages/editor-skeleton/src/layouts/workbench.less +++ b/packages/editor-skeleton/src/layouts/workbench.less @@ -156,6 +156,9 @@ body { margin-left: 4px; margin-right: 4px; } + .ve-quick-search-trigger{ + display: flex; + } } } .lc-workbench-body { @@ -229,6 +232,7 @@ body { flex-shrink: 0; flex-direction: column; justify-content: space-between; + overflow: hidden; &.lc-area-visible { display: flex; } diff --git a/packages/plugin-source-editor/src/index.scss b/packages/plugin-source-editor/src/index.scss index 02b902227..bd570e930 100644 --- a/packages/plugin-source-editor/src/index.scss +++ b/packages/plugin-source-editor/src/index.scss @@ -19,5 +19,16 @@ height: 100%; } + .full-screen-container{ + position: absolute; + top: 40px; + right: 20px; + cursor: pointer; + img{ + width: 20px; + height: 20px; + } + } + } diff --git a/packages/plugin-source-editor/src/index.tsx b/packages/plugin-source-editor/src/index.tsx index fb957dbb6..0a4aaefdb 100644 --- a/packages/plugin-source-editor/src/index.tsx +++ b/packages/plugin-source-editor/src/index.tsx @@ -1,11 +1,8 @@ import { Component, isValidElement, ReactElement, ReactNode } from 'react'; import { Tab, Search, Input, Button } from '@alifd/next'; -import { Editor } from '@ali/lowcode-editor-core'; +import {Editor} from '@ali/lowcode-editor-core'; import { js_beautify, css_beautify } from 'js-beautify'; import MonacoEditor from 'react-monaco-editor'; - -// import lolizer from './sorceEditorPlugin', - import { Designer } from '@ali/lowcode-designer'; const TAB_KEY = { JS_TAB: 'js_tab', @@ -46,23 +43,33 @@ interface FunctionEventParam { export default class SourceEditor extends Component<{ editor: Editor; - panel?: any }> { - private monocoEditer: any; - private editorCmd: any; + private monocoEditor: Object; + private editorCmd: Object; + private editorRef = React.createRef(); + private editorNode: Object; + private editorParentNode: Object; - state: any = { + state = { isShow: false, tabKey: TAB_KEY.JS_TAB, }; - async componentWillMount() { + componentWillMount() { const { editor } = this.props; editor.on('leftPanel.show', (key: String) => { - if (key === 'sourceEditor' && !this.monocoEditer) { + debugger; + if (key === 'sourceEditor' && !this.monocoEditor) { this.setState({ isShow: true, }); + + + setTimeout(()=>{ + this.editorNode = this.editorRef.current; //记录当前dom节点; + this.editorParentNode = this.editorNode.parentNode; //记录父节点; + console.log(this.editorNode); + },0) } }); @@ -73,57 +80,68 @@ export default class SourceEditor extends Component<{ }); // 定位函数 - editor.on('sourceEditor.focusByFunction',(params:FunctionEventParam)=>{ + editor.on('sourceEditor.focusByFunction', (params: FunctionEventParam) => { this.callEditorEvent('sourceEditor.focusByFunction', params); this.openPluginPannel(); - }) + }); - const designer = await editor.onceGot(Designer); - // let schema = designer.project.getSchema(); - // mock data - let schema = { - componentTree: [ - { - state: { - // 初始state: 选填 对象类型/变量表达式 - btnText: 'submit', // 默认数据值: 选填 变量表达式 - }, - css: 'body {font-size: 12px;} .botton{widht:100px;color:#ff00ff}', //css样式描述: 选填 - lifeCycles: { - //生命周期: 选填 对象类型 - didMount: { - type: 'JSExpression', - value: "function() {\n \t\tconsole.log('did mount');\n\t}", + //editor.once('designer.mount', (designer: Designer) => { + // let schema = designer.project.getSchema(); + // mock data + let schema = { + componentTree: [ + { + state: { + // 初始state: 选填 对象类型/变量表达式 + btnText: 'submit', // 默认数据值: 选填 变量表达式 }, - willUnmount: { - type: 'JSExpression', - value: "function() {\n \t\tconsole.log('will umount');\n\t}", + css: 'body {font-size: 12px;} .botton{widht:100px;color:#ff00ff}', //css样式描述: 选填 + lifeCycles: { + //生命周期: 选填 对象类型 + didMount: { + type: 'JSExpression', + value: "function() {\n \t\tconsole.log('did mount');\n\t}", + }, + willUnmount: { + type: 'JSExpression', + value: "function() {\n \t\tconsole.log('will umount');\n\t}", + }, + }, + methods: { + //自定义方法对象: 选填 对象类型 + getData: { + //自定义方法: 选填 函数类型 + type: 'JSExpression', + value: "function() {\n \t\tconsole.log('testFunc');\n \t}", + }, }, }, - methods: { - //自定义方法对象: 选填 对象类型 - getData: { - //自定义方法: 选填 函数类型 - type: 'JSExpression', - value: "function() {\n \t\tconsole.log('testFunc');\n \t}", - }, - }, - }, - ], - }; + ], + }; + + this.initCode(schema); + //}); + } + + componentDidMount(){ + - this.initCode(schema); } openPluginPannel = () => { - const { panel } = this.props; - if (panel) { - panel.show(); + const { editor } = this.props; + // 判断面板是否处于激活状态 + if (!editor.leftNav || editor.leftNav != 'sourceEditor') { + // 打开面板 + editor.emit('leftNav.change', 'sourceEditor'); } - } + }; - callEditorEvent = (eventName: any, params: any) => { - if (!this.monocoEditer) { + /** + * 执行编辑器事件 + */ + callEditorEvent = (eventName, params) => { + if (!this.monocoEditor) { this.editorCmd = { eventName, params, @@ -131,16 +149,24 @@ export default class SourceEditor extends Component<{ return; } - if (eventName === 'sourceEditor.addFunction') { - this.addFunction(params); - }else if (eventName === 'sourceEditor.focusByFunction'){ - this.focusByFunctionName(params); + if (this.state.selectTab == TAB_KEY.CSS_TAB) { + this.setState({ + selectTab: TAB_KEY.JS_TAB, + }); } - + if (eventName === 'sourceEditor.addFunction') { + setTimeout(() => { + this.addFunction(params); + }, 100); + } else if (eventName === 'sourceEditor.focusByFunction') { + setTimeout(() => { + this.focusByFunctionName(params); + }, 100); + } }; - initCode = (schema: any) => { + initCode = (schema) => { let jsCode = js_beautify(transfrom.schema2Code(schema), { indent_size: 2, indent_empty_lines: true }); let css; @@ -160,19 +186,19 @@ export default class SourceEditor extends Component<{ * @param params */ addFunction(params: FunctionEventParam) { - const count = this.monocoEditer.getModel().getLineCount() || 0; - const range = new (window as any).monaco.Range(count, 1, count, 1); + const count = this.monocoEditor.getModel().getLineCount() || 0; + const range = new monaco.Range(count, 1, count, 1); const functionCode = transfrom.getNewFunctionCode(params.functionName); - this.monocoEditer.executeEdits('log-source', [ + this.monocoEditor.executeEdits('log-source', [ { identifier: 'event_id', range: range, text: functionCode, forceMoveMarkers: true }, ]); setTimeout(() => { - let newPosition = new (window as any).monaco.Position(count + 1, 2); - this.monocoEditer.setPosition(newPosition); - this.monocoEditer.focus(); + let newPosition = new monaco.Position(count + 1, 2); + this.monocoEditor.setPosition(newPosition); + this.monocoEditor.focus(); }, 100); - this.updateCode(this.monocoEditer.getModel().getValue()); + this.updateCode(this.monocoEditor.getModel().getValue()); } /** @@ -181,30 +207,24 @@ export default class SourceEditor extends Component<{ */ focusByFunctionName(params: FunctionEventParam) { const functionName = params.functionName; - const matchedResult = this.monocoEditer + const matchedResult = this.monocoEditor .getModel() .findMatches(`${functionName}\\s*\\([\\s\\S]*\\)[\\s\\S]*\\{`, false, true)[0]; if (matchedResult) { - - setTimeout(()=>{ - this.monocoEditer.revealLineInCenter(matchedResult.range.startLineNumber); - this.monocoEditer.setPosition({ + let monocoEditor = this.monocoEditor; + setTimeout(() => { + monocoEditor.revealLineInCenter(matchedResult.range.startLineNumber); + monocoEditor.setPosition({ column: matchedResult.range.endColumn, lineNumber: matchedResult.range.endLineNumber, }); - - this.monocoEditer.focus(); - },100) + monocoEditor.focus(); + }, 100); } } - editorDidMount = (editor: any, monaco: any) => { + editorDidMount = (editor, monaco) => { console.log('editorDidMount', editor); - this.monocoEditer = editor; - - if (this.editorCmd) { - this.callEditorEvent(this.editorCmd.eventName, this.editorCmd.params); - } // var commandId = editor.addCommand( // 0, @@ -215,39 +235,22 @@ export default class SourceEditor extends Component<{ // '', // ); - // monaco.languages.registerCodeLensProvider('javascript', { - // provideCodeLenses: function(model, token) { - // return { - // lenses: [ - // { - // range: { - // startLineNumber: 1, - // startColumn: 1, - // endLineNumber: 1, - // endColumn: 1, - // }, - // id: 'First Line', - // command: { - // id: commandId, - // title: 'First Line', - // }, - // }, - // ], - // }; - // }, - // resolveCodeLens: function(model, codeLens, token) { - // return codeLens; - // }, - // }); + if (this.state.selectTab == TAB_KEY.JS_TAB) { + this.monocoEditor = editor; + } + + if (this.editorCmd) { + this.callEditorEvent(this.editorCmd.eventName, this.editorCmd.params); + } }; - onTabChange = (key: any) => { + onTabChange = (key) => { this.setState({ selectTab: key, }); }; - updateCode = (newCode: any) => { + updateCode = (newCode) => { const { selectTab } = this.state; if (selectTab === TAB_KEY.JS_TAB) { this.setState({ @@ -270,22 +273,28 @@ export default class SourceEditor extends Component<{ ]; return ( - <div className="source-editor-container"> - <Tab size="small" shape="wrapped" onChange={this.onTabChange}> + <div className="source-editor-container" > + <Tab size="small" shape="wrapped" onChange={this.onTabChange} activeKey={selectTab}> {tabs.map((item) => ( <Tab.Item key={item.key} title={item.tab}> {isShow && ( - <MonacoEditor - value={selectTab == TAB_KEY.JS_TAB ? jsCode : css} - {...defaultEditorOption as any} - {...{ language: selectTab == TAB_KEY.JS_TAB ? 'javascript' : 'css' }} - onChange={(newCode) => this.updateCode(newCode)} - editorDidMount={this.editorDidMount} - /> + <div style={{ height: '100%' }} ref={this.editorRef}> + <MonacoEditor + value={selectTab == TAB_KEY.JS_TAB ? jsCode : css} + {...defaultEditorOption} + {...{ language: selectTab == TAB_KEY.JS_TAB ? 'typescript' : 'css' }} + onChange={(newCode) => this.updateCode(newCode)} + editorDidMount={(editor, monaco) => this.editorDidMount.call(this, editor, monaco)} + /> + </div> )} </Tab.Item> ))} </Tab> + + <div className="full-screen-container" onClick={this.fullScreen}> + <img src="https://gw.alicdn.com/tfs/TB1d7XqE1T2gK0jSZFvXXXnFXXa-200-200.png"></img> + </div> </div> ); } diff --git a/packages/react-renderer/src/engine/index.jsx b/packages/react-renderer/src/engine/index.jsx index 6ddcf8907..0853a39e0 100644 --- a/packages/react-renderer/src/engine/index.jsx +++ b/packages/react-renderer/src/engine/index.jsx @@ -162,7 +162,7 @@ export default class Engine extends PureComponent { debug('entry.render'); const { componentName } = schema; const allComponents = { ...ENGINE_COMPS, ...components }; - let Comp = allComponents[componentName]; + let Comp = allComponents[componentName] || ENGINE_COMPS[`${componentName}Engine`]; if (Comp && Comp.prototype) { const proto = Comp.prototype; if (!(Comp.prototype instanceof BaseEngine)) { diff --git a/packages/react-simulator-renderer/src/renderer-view.tsx b/packages/react-simulator-renderer/src/renderer-view.tsx index 5ae9ce0fe..c2f2e03ab 100644 --- a/packages/react-simulator-renderer/src/renderer-view.tsx +++ b/packages/react-simulator-renderer/src/renderer-view.tsx @@ -47,6 +47,26 @@ export default class SimulatorRendererView extends Component<{ renderer: Simulat } } +function ucfirst(s: string) { + return s.charAt(0).toUpperCase() + s.substring(1); +} +function getDeviceView(view: any, device: string, mode: string) { + if (!view || typeof view === 'string') { + return view; + } + + // compatible vision Mobile | Preview + device = ucfirst(device); + if (device === 'Mobile' && view.hasOwnProperty(device)) { + view = view[device]; + } + mode = ucfirst(mode); + if (mode === 'Preview' && view.hasOwnProperty(mode)) { + view = view[mode]; + } + return view; +} + @observer class Layout extends Component<{ renderer: SimulatorRenderer }> { shouldComponentUpdate() { @@ -72,13 +92,14 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> { } render() { const { renderer } = this.props; + const { device, designMode } = renderer; return ( <LowCodeRenderer schema={renderer.schema} components={renderer.components} appHelper={renderer.context} // context={renderer.context} - designMode={renderer.designMode} + designMode={designMode} suspended={renderer.suspended} self={renderer.scope} customCreateElement={(Component: any, props: any, children: any) => { @@ -87,7 +108,7 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> { viewProps._leaf = host.document.getNode(__id); return createElement( - Component, + getDeviceView(Component, device, designMode), viewProps, children == null ? [] : Array.isArray(children) ? children : [children], ); diff --git a/packages/react-simulator-renderer/src/renderer.ts b/packages/react-simulator-renderer/src/renderer.ts index 1aa4ba534..a5bee9da7 100644 --- a/packages/react-simulator-renderer/src/renderer.ts +++ b/packages/react-simulator-renderer/src/renderer.ts @@ -35,12 +35,14 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer { } // sync designMode + this._designMode = host.designMode; // sync suspended // sync scope // sync device + this._device = host.device; }); host.componentsConsumer.consume(async (componentsAsset) => { if (componentsAsset) { @@ -83,9 +85,13 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer { @computed get context(): any { return this._appContext; } - + @obx.ref private _designMode: string = 'design'; @computed get designMode(): any { - return 'preview'; + return this._designMode; + } + @obx.ref private _device: string = 'default'; + @computed get device() { + return this._device; } @obx.ref private _componentsMap = {}; @computed get componentsMap(): any { diff --git a/packages/vision-preset/src/editor.ts b/packages/vision-preset/src/editor.ts index 805537782..954235f6c 100644 --- a/packages/vision-preset/src/editor.ts +++ b/packages/vision-preset/src/editor.ts @@ -180,9 +180,9 @@ skeleton.add({ LiveEditing.addLiveEditingSpecificRule(liveEditingRule); // 实例节点选择器,线框高亮 -addBuiltinComponentAction({ - name: 'instance-node-selector', - content: InstanceNodeSelector, - important: true, - condition: 'always', -}); +// addBuiltinComponentAction({ +// name: 'instance-node-selector', +// content: InstanceNodeSelector, +// important: true, +// condition: 'always' +// }); diff --git a/packages/vision-preset/src/pages.ts b/packages/vision-preset/src/pages.ts index c269f2471..ada3dfc97 100644 --- a/packages/vision-preset/src/pages.ts +++ b/packages/vision-preset/src/pages.ts @@ -57,6 +57,9 @@ const pages = Object.assign(project, { }, onCurrentPageChange(fn: (page: DocumentModel) => void) { return project.onCurrentDocumentChange(fn); + }, + toData() { + return project.documents.map(doc => doc.toData()); } }); diff --git a/packages/vision-preset/src/viewport.ts b/packages/vision-preset/src/viewport.ts index 0b5ec7cb7..536010ae6 100644 --- a/packages/vision-preset/src/viewport.ts +++ b/packages/vision-preset/src/viewport.ts @@ -2,6 +2,7 @@ import { EventEmitter } from 'events'; const domReady = require('domready'); import Flags from './flags'; +import { designer } from './editor'; function enterFullscreen() { const elem = document.documentElement; @@ -185,8 +186,9 @@ export class Viewport { setDevice(device = 'pc') { if (this.getDevice() !== device) { this.device = device; - Flags.setSimulator(device); - this.applyMediaCSS(); + designer.currentDocument?.simulator?.set('device', device === 'mobile' ? 'mobile' : 'default'); + // Flags.setSimulator(device); + // this.applyMediaCSS(); this.emitter.emit('devicechange', device); this.changeViewport(); } @@ -229,7 +231,7 @@ export class Viewport { } setWithShell(shell: string) { - Flags.setWithShell(shell); + // Flags.setWithShell(shell); } onFullscreenChange(func: () => any) {