import { h, defineAsyncComponent } from 'vue'
import { isHTMLTag } from '@vue/shared'
import * as TinyVueIcon from '@opentiny/vue-icon'
import {
CanvasRow,
CanvasCol,
CanvasRowColContainer,
CanvasFlexBox,
CanvasSection,
CanvasNavigation,
FormModel,
TableModel,
PageModel
} from '@opentiny/tiny-engine-builtin-component'
import {
CanvasBox,
CanvasCollection,
CanvasIcon,
CanvasText,
CanvasSlot,
CanvasImg,
CanvasPlaceholder,
CanvasRouterView,
CanvasRouterLink
} from '../builtin'
import { getController } from '../canvas-function/controller'
import BlockLoadError from '../BlockLoadError.vue'
export const Mapper = {
Icon: CanvasIcon,
Text: CanvasText,
Collection: CanvasCollection,
div: CanvasBox,
Slot: CanvasSlot,
slot: CanvasSlot,
Template: CanvasBox,
Img: CanvasImg,
CanvasSection,
CanvasFlexBox,
CanvasRow,
CanvasCol,
CanvasRowColContainer,
CanvasPlaceholder,
FormModel,
TableModel,
PageModel,
RouterView: CanvasRouterView,
RouterLink: CanvasRouterLink,
CanvasNavigation
}
const getNative = (name) => {
return window.TinyLowcodeComponent?.[name]
}
const getBlock = (name) => {
return window.blocks?.[name]
}
const blockComponentsBlobUrlMap = new Map<string, string>()
const loadBlockComponent = async (name: string) => {
try {
if (blockComponentsBlobUrlMap.has(name)) {
return import( blockComponentsBlobUrlMap.get(name))
}
const blocksBlob = (await getController().getBlockByName(name)) as Array<{ blobURL: string; style: string }>
for (const [fileName, value] of Object.entries(blocksBlob)) {
blockComponentsBlobUrlMap.set(fileName, value.blobURL)
if (!value.style) {
continue
}
const stylesheet = document.querySelector(`#${fileName}`)
if (stylesheet) {
stylesheet.innerHTML = value.style
} else {
const newStylesheet = document.createElement('style')
newStylesheet.innerHTML = value.style
newStylesheet.setAttribute('id', fileName)
document.head.appendChild(newStylesheet)
}
}
return import( blockComponentsBlobUrlMap.get(name))
} catch (error) {
return h(BlockLoadError, { name })
}
}
window.loadBlockComponent = loadBlockComponent
const getBlockComponent = (name) => {
return defineAsyncComponent(() => loadBlockComponent(name))
}
export const removeBlockCompsCache = () => {
blockComponentsBlobUrlMap.forEach((_, fileName) => {
const stylesheet = document.querySelector(`#${fileName}`)
stylesheet?.remove?.()
})
blockComponentsBlobUrlMap.clear()
}
export const getIcon = (name) => TinyVueIcon?.[name]?.() || ''
export const getComponent = (name) => {
return Mapper[name] || getNative(name) || getBlock(name) || (isHTMLTag(name) ? name : getBlockComponent(name))
}