refactor: Convert icon manager into class

This commit is contained in:
Sidharth Vinod
2025-10-29 01:38:42 +09:00
parent 13baf51b35
commit a23c2baed8

View File

@@ -23,10 +23,11 @@ export const unknownIcon: IconifyIcon = {
width: 80,
};
const iconsStore = new Map<string, IconifyJSON>();
const loaderStore = new Map<string, AsyncIconLoader['loader']>();
class IconManager {
private iconsStore = new Map<string, IconifyJSON>();
private loaderStore = new Map<string, AsyncIconLoader['loader']>();
export const registerIconPacks = (iconLoaders: IconLoader[]) => {
registerIconPacks(iconLoaders: IconLoader[]): void {
for (const iconLoader of iconLoaders) {
if (!iconLoader.name) {
throw new Error(
@@ -35,17 +36,20 @@ export const registerIconPacks = (iconLoaders: IconLoader[]) => {
}
log.debug('Registering icon pack:', iconLoader.name);
if ('loader' in iconLoader) {
loaderStore.set(iconLoader.name, iconLoader.loader);
this.loaderStore.set(iconLoader.name, iconLoader.loader);
} else if ('icons' in iconLoader) {
iconsStore.set(iconLoader.name, iconLoader.icons);
this.iconsStore.set(iconLoader.name, iconLoader.icons);
} else {
log.error('Invalid icon loader:', iconLoader);
throw new Error('Invalid icon loader. Must have either "icons" or "loader" property.');
}
}
};
}
const getRegisteredIconData = async (iconName: string, fallbackPrefix?: string) => {
private async getRegisteredIconData(
iconName: string,
fallbackPrefix?: string
): Promise<ExtendedIconifyIcon> {
const data = stringToIcon(iconName, true, fallbackPrefix !== undefined);
if (!data) {
throw new Error(`Invalid icon name: ${iconName}`);
@@ -54,16 +58,16 @@ const getRegisteredIconData = async (iconName: string, fallbackPrefix?: string)
if (!prefix) {
throw new Error(`Icon name must contain a prefix: ${iconName}`);
}
let icons = iconsStore.get(prefix);
let icons = this.iconsStore.get(prefix);
if (!icons) {
const loader = loaderStore.get(prefix);
const loader = this.loaderStore.get(prefix);
if (!loader) {
throw new Error(`Icon set not found: ${data.prefix}`);
}
try {
const loaded = await loader();
icons = { ...loaded, prefix };
iconsStore.set(prefix, icons);
this.iconsStore.set(prefix, icons);
} catch (e) {
log.error(e);
throw new Error(`Failed to load icon set: ${data.prefix}`);
@@ -74,25 +78,25 @@ const getRegisteredIconData = async (iconName: string, fallbackPrefix?: string)
throw new Error(`Icon not found: ${iconName}`);
}
return iconData;
};
}
export const isIconAvailable = async (iconName: string) => {
async isIconAvailable(iconName: string): Promise<boolean> {
try {
await getRegisteredIconData(iconName);
await this.getRegisteredIconData(iconName);
return true;
} catch {
return false;
}
};
}
export const getIconSVG = async (
async getIconSVG(
iconName: string,
customisations?: IconifyIconCustomisations & { fallbackPrefix?: string },
extraAttributes?: Record<string, string>
) => {
): Promise<string> {
let iconData: ExtendedIconifyIcon;
try {
iconData = await getRegisteredIconData(iconName, customisations?.fallbackPrefix);
iconData = await this.getRegisteredIconData(iconName, customisations?.fallbackPrefix);
} catch (e) {
log.error(e);
iconData = unknownIcon;
@@ -103,4 +107,22 @@ export const getIconSVG = async (
...extraAttributes,
});
return sanitizeText(svg, getConfig());
}
}
const globalIconManager = new IconManager();
// Export the singleton instance methods for backward compatibility
export const registerIconPacks = (iconLoaders: IconLoader[]) =>
globalIconManager.registerIconPacks(iconLoaders);
export const isIconAvailable = async (iconName: string) => {
return await globalIconManager.isIconAvailable(iconName);
};
export const getIconSVG = async (
iconName: string,
customisations?: IconifyIconCustomisations & { fallbackPrefix?: string },
extraAttributes?: Record<string, string>
) => {
return await globalIconManager.getIconSVG(iconName, customisations, extraAttributes);
};