# Description of Changes Add linting to ensure correct imports style is used. I've disabled the linting for two imports which use relative paths because the files they're importing are siblings to core and proprietary. They could probs be imported by `@app/../assets/xxx` but it seems silly. The other thing we could do is add an explicit `@assets` path alias or something, but it seemed more complex than just disabling the lint for those two imports at this stage. We could always do it in the future if we want to import stuff up there a lot in the future.
65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
import React from 'react';
|
||
import { addCollection, Icon } from '@iconify/react';
|
||
import iconSet from '../../../assets/material-symbols-icons.json'; // eslint-disable-line no-restricted-imports -- Outside app paths
|
||
|
||
// Load icons synchronously at import time - guaranteed to be ready on first render
|
||
let iconsLoaded = false;
|
||
let localIconCount = 0;
|
||
|
||
try {
|
||
if (iconSet) {
|
||
addCollection(iconSet);
|
||
iconsLoaded = true;
|
||
localIconCount = Object.keys(iconSet.icons || {}).length;
|
||
console.info(`✅ Local icons loaded: ${localIconCount} icons (${Math.round(JSON.stringify(iconSet).length / 1024)}KB)`);
|
||
}
|
||
} catch {
|
||
console.info('ℹ️ Local icons not available - using CDN fallback');
|
||
}
|
||
|
||
interface LocalIconProps {
|
||
icon: string;
|
||
width?: string | number;
|
||
height?: string | number;
|
||
style?: React.CSSProperties;
|
||
className?: string;
|
||
}
|
||
|
||
/**
|
||
* LocalIcon component that uses our locally bundled Material Symbols icons
|
||
* instead of loading from CDN
|
||
*/
|
||
export const LocalIcon: React.FC<LocalIconProps> = ({ icon, width, height, style, ...props }) => {
|
||
// Convert our icon naming convention to the local collection format
|
||
const iconName = icon.startsWith('material-symbols:')
|
||
? icon
|
||
: `material-symbols:${icon}`;
|
||
|
||
// Development logging (only in dev mode)
|
||
if (process.env.NODE_ENV === 'development') {
|
||
const logKey = `icon-${iconName}`;
|
||
if (!sessionStorage.getItem(logKey)) {
|
||
const source = iconsLoaded ? 'local' : 'CDN';
|
||
console.debug(`🎯 Icon: ${iconName} (${source})`);
|
||
sessionStorage.setItem(logKey, 'logged');
|
||
}
|
||
}
|
||
|
||
const iconStyle: React.CSSProperties = { ...style };
|
||
|
||
// Use width if provided, otherwise fall back to height
|
||
const size = width || height;
|
||
if (size && typeof size === 'string') {
|
||
// If it's a CSS unit string (like '1.5rem'), use it as fontSize
|
||
iconStyle.fontSize = size;
|
||
} else if (typeof size === 'number') {
|
||
// If it's a number, treat it as pixels
|
||
iconStyle.fontSize = `${size}px`;
|
||
}
|
||
|
||
// Always render the icon - Iconify will use local if available, CDN if not
|
||
return <Icon icon={iconName} style={iconStyle} {...props} />;
|
||
};
|
||
|
||
export default LocalIcon;
|