import { ComponentType, forwardRef, createElement } from 'react'; import { NpmInfo } from '@ali/lowcode-types'; import { isReactComponent } from './is-react'; import { isESModule } from './is-es-module'; interface LibraryMap { [key: string]: string; } function accessLibrary(library: string | Record) { if (typeof library !== 'string') { return library; } return (window as any)[library] || generateHtmlComp(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[]) { 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); } // libraryName the key access to global // export { exportName } from xxx exportName === global.libraryName.exportName // export exportName from xxx exportName === global.libraryName.default || global.libraryName // export { exportName as componentName } from package // if exportName == null exportName === componentName; // const componentName = exportName.subName, if exportName empty subName donot use 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); } export 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; }