diff --git a/packages/demo/build.json b/packages/demo/build.json index 376c27c63..e68509f5b 100644 --- a/packages/demo/build.json +++ b/packages/demo/build.json @@ -1,6 +1,6 @@ { "entry": { - "index": "src/vision/index.ts", + "index": "src/index.ts", "vision-preset": "../vision-preset/src/index.ts", "react-simulator-renderer": "../react-simulator-renderer/src/index.ts" }, diff --git a/packages/demo/build.plugin.js b/packages/demo/build.plugin.js index 50ac34ddd..c9fe6c380 100644 --- a/packages/demo/build.plugin.js +++ b/packages/demo/build.plugin.js @@ -1,23 +1,24 @@ const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); - module.exports = ({ onGetWebpackConfig }) => { onGetWebpackConfig((config) => { - config.resolve - .plugin('tsconfigpaths') - .use(TsconfigPathsPlugin, [{ - configFile: "./tsconfig.json" - }]); - + config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [ + { + configFile: './tsconfig.json', + }, + ]); config - // 定义插件名称 - .plugin('MonacoWebpackPlugin') - // 第一项为具体插件,第二项为插件参数 - .use(new MonacoWebpackPlugin({ - languages:["javascript","css","json"] - }), []); + // 定义插件名称 + .plugin('MonacoWebpackPlugin') + // 第一项为具体插件,第二项为插件参数 + .use( + new MonacoWebpackPlugin({ + languages: ['javascript', 'css', 'json'], + }), + [], + ); config.plugins.delete('hot'); config.devServer.hot(false); diff --git a/packages/demo/src/editor/components/index.less b/packages/demo/src/editor/components/index.less new file mode 100644 index 000000000..c630e0914 --- /dev/null +++ b/packages/demo/src/editor/components/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/demo/src/editor/components/index.tsx b/packages/demo/src/editor/components/index.tsx new file mode 100644 index 000000000..f32681dd0 --- /dev/null +++ b/packages/demo/src/editor/components/index.tsx @@ -0,0 +1,110 @@ +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 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" + > + <div className="instance-node-selector">{this.renderNodes(node)}</div> + </Popup> + </div> + ); + } +} diff --git a/packages/demo/src/editor/config/components.js b/packages/demo/src/editor/config/components.js index 95831f033..1d23d49b2 100644 --- a/packages/demo/src/editor/config/components.js +++ b/packages/demo/src/editor/config/components.js @@ -1,6 +1,6 @@ -import LowcodeSkeleton from '@ali/lowcode-editor-skeleton'; +import { Workbench as LowcodeSkeleton } from '@ali/lowcode-editor-skeleton'; import logo from '@ali/lowcode-plugin-sample-logo'; -import undoRedo from '@ali/lowcode-plugin-undo-redo'; +// import undoRedo from '@ali/lowcode-plugin-undo-redo'; import samplePreview from '@ali/lowcode-plugin-sample-preview'; import componentsPane from '@ali/lowcode-plugin-components-pane'; import outlinePane from '@ali/lowcode-plugin-outline-pane'; @@ -13,7 +13,7 @@ import variableBindDialog from '@ali/lowcode-plugin-variable-bind-dialog'; export default { LowcodeSkeleton, logo, - undoRedo, + // undoRedo, samplePreview, componentsPane, outlinePane, diff --git a/packages/demo/src/editor/editor.ts b/packages/demo/src/editor/editor.ts new file mode 100644 index 000000000..2a03ebaee --- /dev/null +++ b/packages/demo/src/editor/editor.ts @@ -0,0 +1,47 @@ +import { globalContext, Editor } from '@ali/lowcode-editor-core'; +import { Designer, addBuiltinComponentAction } from '@ali/lowcode-designer'; +import Outline from '@ali/lowcode-plugin-outline-pane'; + +import DesignerPlugin from '@ali/lowcode-plugin-designer'; +import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton'; + +import { InstanceNodeSelector } from './components'; + +export const editor = new Editor(); +globalContext.register(editor, Editor); + +export const skeleton = new Skeleton(editor); +editor.set(Skeleton, skeleton); + +export const designer = new Designer({ editor: editor }); +editor.set(Designer, designer); + +skeleton.add({ + area: 'mainArea', + name: 'designer', + type: 'Widget', + content: DesignerPlugin, +}); +skeleton.add({ + area: 'rightArea', + name: 'settingsPane', + type: 'Panel', + content: SettingsPrimaryPane, +}); +skeleton.add({ + area: 'leftArea', + name: 'outlinePane', + type: 'PanelDock', + content: Outline, + panelProps: { + area: 'leftFixedArea', + }, +}); + +// 实例节点选择器,线框高亮 +addBuiltinComponentAction({ + name: 'instance-node-selector', + content: InstanceNodeSelector, + important: true, + condition: 'always', +}); diff --git a/packages/demo/src/editor/index.tsx b/packages/demo/src/editor/index.tsx index 48c99732c..abe464ee5 100644 --- a/packages/demo/src/editor/index.tsx +++ b/packages/demo/src/editor/index.tsx @@ -1,20 +1,76 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -// import { registerSetters } from '@ali/lowcode-setters'; -import config from './config/skeleton'; -import components from './config/components'; -import utils from './config/utils'; +/* eslint-disable */ +import { createElement } from 'react'; +import EventBindDialog from '@ali/lowcode-plugin-event-bind-dialog'; +import ComponentPane from '../../../plugin-components-pane/src/index'; +import { render } from 'react-dom'; +import { Workbench } from '@ali/lowcode-editor-skeleton'; -import './global.scss'; -import './config/theme.scss'; +import { skeleton, editor } from './editor'; -// registerSetters(); -const Skeleton = components.LowcodeSkeleton; -const LCE_CONTAINER = document.getElementById('lce-container'); - -if (!LCE_CONTAINER) { - throw new Error('当前页面不存在 <div id="lce-container"></div> 节点.'); +async function loadAssets() { + const _assets = await editor.utils.get('./assets.json'); + _assets.components = Object.values(_assets.components); + _assets.packages = Object.values(_assets.packages); + editor.set('assets', _assets); } -// @ts-ignore -ReactDOM.render(<Skeleton config={config} utils={utils} components={components} />, LCE_CONTAINER); +async function loadSchema() { + const schema = await editor.utils.get('./schema.json'); + editor.set('schema', schema); +} + +// demo +function initDemoPanes() { + skeleton.add({ + "name": "ali-lowcode-components-panel", + "content": createElement(ComponentPane, { + editor + }), + "props": { + icon: "add", + "description": "组件库" + }, + "type": "PanelDock", + "area": "left", + "panelProps": { + "width": 300 + } + }); + skeleton.add({ + name: 'eventBindDialog', + type: 'Widget', + content: EventBindDialog, + }); + skeleton.add({ + area: 'leftArea', + name: 'icon1', + type: 'Dock', + props: { + align: 'bottom', + icon: 'set', + description: '设置' + }, + }); +} + +async function init(container?: Element) { + await loadAssets(); + await loadSchema(); + initDemoPanes(); + + if (!container) { + container = document.createElement('div'); + document.body.appendChild(container); + } + container.id = 'engine'; + + render( + createElement(Workbench, { + skeleton, + className: 'engine-main', + topAreaItemClassName: 'engine-actionitem', + }), + container, + ); +} +init();