import { addCollection } from '@iconify/vue/offline'
|
import { LOCAL_ICON_COLLECTIONS } from '../../plugins/iconify.collections.js'
|
|
const FULL_ICON_COLLECTION_LOADERS = Object.freeze({
|
fluent: () => import('@iconify-json/fluent').then((module) => module.icons),
|
'icon-park-outline': () =>
|
import('@iconify-json/icon-park-outline').then((module) => module.icons),
|
iconamoon: () => import('@iconify-json/iconamoon').then((module) => module.icons),
|
ix: () => import('@iconify-json/ix').then((module) => module.icons),
|
'line-md': () => import('@iconify-json/line-md').then((module) => module.icons),
|
ri: () => import('@iconify-json/ri').then((module) => module.icons),
|
solar: () => import('@iconify-json/solar').then((module) => module.icons),
|
'svg-spinners': () => import('@iconify-json/svg-spinners').then((module) => module.icons),
|
'system-uicons': () => import('@iconify-json/system-uicons').then((module) => module.icons),
|
vaadin: () => import('@iconify-json/vaadin').then((module) => module.icons)
|
})
|
|
const fullyRegisteredPrefixes = new Set()
|
const pendingPrefixLoads = new Map()
|
|
function parseIconName(icon) {
|
if (typeof icon !== 'string') {
|
return null
|
}
|
|
const normalizedIcon = icon.trim()
|
if (!normalizedIcon) {
|
return null
|
}
|
|
const separatorIndex = normalizedIcon.indexOf(':')
|
if (separatorIndex <= 0 || separatorIndex >= normalizedIcon.length - 1) {
|
return null
|
}
|
|
return {
|
prefix: normalizedIcon.slice(0, separatorIndex),
|
name: normalizedIcon.slice(separatorIndex + 1)
|
}
|
}
|
|
function hasBundledIcon(icon) {
|
const parsedIcon = parseIconName(icon)
|
if (!parsedIcon) {
|
return false
|
}
|
|
const collection = LOCAL_ICON_COLLECTIONS[parsedIcon.prefix]
|
if (!collection) {
|
return false
|
}
|
|
return Boolean(collection.icons?.[parsedIcon.name] || collection.aliases?.[parsedIcon.name])
|
}
|
|
function loadFullIconCollection(prefix) {
|
if (fullyRegisteredPrefixes.has(prefix)) {
|
return Promise.resolve(true)
|
}
|
|
const currentTask = pendingPrefixLoads.get(prefix)
|
if (currentTask) {
|
return currentTask
|
}
|
|
const loader = FULL_ICON_COLLECTION_LOADERS[prefix]
|
if (!loader) {
|
return Promise.resolve(false)
|
}
|
|
const loadTask = loader()
|
.then((collection) => {
|
addCollection(collection)
|
fullyRegisteredPrefixes.add(prefix)
|
pendingPrefixLoads.delete(prefix)
|
return true
|
})
|
.catch((error) => {
|
pendingPrefixLoads.delete(prefix)
|
throw error
|
})
|
|
pendingPrefixLoads.set(prefix, loadTask)
|
return loadTask
|
}
|
|
function collectRuntimeIcons(source, iconNames = new Set()) {
|
if (!Array.isArray(source)) {
|
return iconNames
|
}
|
|
source.forEach((item) => {
|
if (!item || typeof item !== 'object') {
|
return
|
}
|
|
const icon = item.meta?.icon || item.icon
|
if (typeof icon === 'string' && icon.includes(':') && !hasBundledIcon(icon)) {
|
iconNames.add(icon)
|
}
|
|
if (Array.isArray(item.children) && item.children.length > 0) {
|
collectRuntimeIcons(item.children, iconNames)
|
}
|
})
|
|
return iconNames
|
}
|
|
function scheduleIdleTask(task, delay = 0) {
|
const invoke = () => {
|
if (globalThis.requestIdleCallback) {
|
globalThis.requestIdleCallback(task, { timeout: 1000 })
|
return
|
}
|
setTimeout(task, 0)
|
}
|
|
if (delay > 0) {
|
setTimeout(invoke, delay)
|
return
|
}
|
|
invoke()
|
}
|
|
async function ensureIconRegistered(icon) {
|
const parsedIcon = parseIconName(icon)
|
if (!parsedIcon) {
|
return false
|
}
|
|
if (hasBundledIcon(icon) || fullyRegisteredPrefixes.has(parsedIcon.prefix)) {
|
return true
|
}
|
|
return loadFullIconCollection(parsedIcon.prefix)
|
}
|
|
function warmRuntimeIcons(iconNames, delay = 120) {
|
const icons = [...new Set(Array.isArray(iconNames) ? iconNames : [])].filter(Boolean)
|
if (icons.length === 0) {
|
return
|
}
|
|
scheduleIdleTask(() => {
|
icons.forEach((icon) => {
|
void ensureIconRegistered(icon)
|
})
|
}, delay)
|
}
|
|
function warmMenuIcons(menuList, delay = 120) {
|
warmRuntimeIcons([...collectRuntimeIcons(menuList)], delay)
|
}
|
|
export {
|
collectRuntimeIcons,
|
ensureIconRegistered,
|
hasBundledIcon,
|
warmMenuIcons,
|
warmRuntimeIcons
|
}
|