diff --git a/packages/plugin-sample-preview/package.json b/packages/plugin-sample-preview/package.json index e02b421b7..6f6324216 100644 --- a/packages/plugin-sample-preview/package.json +++ b/packages/plugin-sample-preview/package.json @@ -21,6 +21,9 @@ "dependencies": { "@ali/lowcode-designer": "^0.9.27", "@ali/lowcode-editor-core": "^0.8.21", + "@ali/lowcode-types": "^0.8.11", + "@ali/lowcode-utils": "^0.8.12", + "@ali/lowcode-react-renderer": "^0.8.0", "@alifd/next": "^1.x", "react": "^16.8.1" }, @@ -30,8 +33,7 @@ "@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", - "@ali/lowcode-react-renderer": "^0.8.0" + "build-plugin-moment-locales": "^0.1.0" }, "publishConfig": { "registry": "https://registry.npm.alibaba-inc.com" diff --git a/packages/plugin-sample-preview/src/index.tsx b/packages/plugin-sample-preview/src/index.tsx index c6c6c38c5..7435f5ed2 100644 --- a/packages/plugin-sample-preview/src/index.tsx +++ b/packages/plugin-sample-preview/src/index.tsx @@ -1,10 +1,86 @@ -import React, { useState } from 'react'; +import React, { useState, ComponentType } from 'react'; import { Button, Dialog } from '@alifd/next'; -import { PluginProps } from '@ali/lowcode-types'; +import { PluginProps, NpmInfo } from '@ali/lowcode-types'; import { Designer } from '@ali/lowcode-designer'; +import { isReactComponent, isESModule } from '@ali/lowcode-utils'; import ReactRenderer from '@ali/lowcode-react-renderer'; import './index.scss'; +interface LibraryMap { + [key: string]: string; +} + +function accessLibrary(library: string | object) { + if (typeof library !== 'string') { + return library; + } + + return (window as any)[library]; +} + +function getSubComponent(library: any, paths: string[]) { + const l = paths.length; + if (l < 1 || !library) { + return library; + } + let i = 0; + let component: any; + while (i < l) { + const key = paths[i]!; + let ex: any; + try { + component = library[key]; + } catch (e) { + ex = e; + component = null; + } + if (i === 0 && component == null && key === 'default') { + if (ex) { + return l === 1 ? library : null; + } + component = library; + } else if (component == null) { + return null; + } + library = component; + i++; + } + return component; +} + +function findComponent(libraryMap: LibraryMap, componentName: string, npm?: NpmInfo) { + if (!npm) { + return accessLibrary(componentName); + } + const exportName = npm.exportName || npm.componentName || componentName; + const libraryName = libraryMap[npm.package] || exportName; + const library = accessLibrary(libraryName); + const paths = npm.exportName && npm.subName ? npm.subName.split('.') : []; + if (npm.destructuring) { + paths.unshift(exportName); + } else if (isESModule(library)) { + paths.unshift('default'); + } + return getSubComponent(library, paths); +} + +function buildComponents(libraryMap: LibraryMap, componentsMap: { [componentName: string]: NpmInfo | ComponentType }) { + const components: any = { + }; + Object.keys(componentsMap).forEach((componentName) => { + let component = componentsMap[componentName]; + if (isReactComponent(component)) { + components[componentName] = component; + } else { + component = findComponent(libraryMap, componentName, component); + if (component) { + components[componentName] = component; + } + } + }); + return components; +} + const SamplePreview = ({ editor }: PluginProps) => { const [data, setData] = useState({}); const [visible, setVisible] = useState(false); @@ -14,12 +90,16 @@ const SamplePreview = ({ editor }: PluginProps) => { } const designer = editor.get(Designer); if (designer) { - console.info('save schema:', designer.schema); + const assets = await editor.get('assets'); + console.info('save schema:', designer, assets); - const { components } = await editor.get('assets'); + const libraryMap: LibraryMap = {}; + assets.packages.forEach(({ package, library }) => { + libraryMap[package] = library; + }); setData({ - schema: designer.schema, - components, + schema: designer.schema.componentsTree[0], + components: buildComponents(libraryMap, designer.componentsMap), }); setVisible(true); } @@ -41,7 +121,7 @@ const SamplePreview = ({ editor }: PluginProps) => { onClose={handleClose} > {visible && }