- iconManager MaterialIconManager.js zijn nu 'unified' in 1 component, en samen met translation utilities omgezet naar een meer moderne Vue composable
- De sidebar is nu eveneens omgezet naar een Vue component.
This commit is contained in:
192
eveai_chat_client/static/assets/js/composables/useIconManager.js
Normal file
192
eveai_chat_client/static/assets/js/composables/useIconManager.js
Normal file
@@ -0,0 +1,192 @@
|
||||
// eveai_chat_client/static/assets/js/composables/useIconManager.js
|
||||
|
||||
import { onMounted, watch, ref } from 'vue';
|
||||
|
||||
/**
|
||||
* Vue 3 Composable for Material Symbols Outlined icon management
|
||||
* Self-contained modern icon management without legacy dependencies
|
||||
*/
|
||||
export function useIconManager() {
|
||||
const isIconManagerReady = ref(true); // Always ready since we're self-contained
|
||||
const loadedIcons = ref([]);
|
||||
|
||||
/**
|
||||
* Load a single Material Symbols Outlined icon
|
||||
* @param {string} iconName - Name of the icon to load
|
||||
* @param {Object} options - Icon options (opsz, wght, FILL, GRAD)
|
||||
*/
|
||||
const loadIcon = (iconName, options = {}) => {
|
||||
if (!iconName) {
|
||||
console.warn('No icon name provided');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if icon is already loaded
|
||||
if (loadedIcons.value.includes(iconName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Default options for Material Symbols Outlined
|
||||
const defaultOptions = {
|
||||
opsz: 24,
|
||||
wght: 400,
|
||||
FILL: 0,
|
||||
GRAD: 0
|
||||
};
|
||||
|
||||
const iconOptions = { ...defaultOptions, ...options };
|
||||
|
||||
// Create CSS for the icon with specific options
|
||||
const cssRule = `
|
||||
.material-symbols-outlined.icon-${iconName} {
|
||||
font-variation-settings:
|
||||
'FILL' ${iconOptions.FILL},
|
||||
'wght' ${iconOptions.wght},
|
||||
'GRAD' ${iconOptions.GRAD},
|
||||
'opsz' ${iconOptions.opsz};
|
||||
}
|
||||
`;
|
||||
|
||||
// Add CSS rule to document
|
||||
const style = document.createElement('style');
|
||||
style.textContent = cssRule;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Mark icon as loaded
|
||||
loadedIcons.value.push(iconName);
|
||||
|
||||
console.log(`Icon loaded: ${iconName}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Load multiple icons
|
||||
* @param {Array} iconNames - Array of icon names to load
|
||||
* @param {Object} options - Icon options (opsz, wght, FILL, GRAD)
|
||||
*/
|
||||
const loadIcons = (iconNames, options = {}) => {
|
||||
if (!Array.isArray(iconNames)) {
|
||||
console.warn('iconNames must be an array');
|
||||
return;
|
||||
}
|
||||
|
||||
iconNames.forEach(iconName => {
|
||||
loadIcon(iconName, options);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure icons are loaded (alias for loadIcons for backward compatibility)
|
||||
* @param {Object} options - Icon options (opsz, wght, FILL, GRAD)
|
||||
* @param {Array} iconNames - Array of icon names to load
|
||||
*/
|
||||
const ensureIconsLoaded = (options = {}, iconNames = []) => {
|
||||
if (iconNames && iconNames.length > 0) {
|
||||
loadIcons(iconNames, options);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Watch a reactive property for icon changes and automatically load icons
|
||||
* @param {Ref|Function} iconSource - Reactive source that contains icon name(s)
|
||||
* @param {Object} options - Icon options
|
||||
*/
|
||||
const watchIcon = (iconSource, options = {}) => {
|
||||
watch(
|
||||
iconSource,
|
||||
(newIcon) => {
|
||||
if (newIcon) {
|
||||
if (Array.isArray(newIcon)) {
|
||||
loadIcons(newIcon, options);
|
||||
} else {
|
||||
loadIcon(newIcon, options);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Watch formData for icon changes (common pattern in Vue components)
|
||||
* @param {Ref} formData - Reactive formData object
|
||||
* @param {Object} options - Icon options
|
||||
*/
|
||||
const watchFormDataIcon = (formData, options = {}) => {
|
||||
watch(
|
||||
() => formData.value?.icon,
|
||||
(newIcon) => {
|
||||
if (newIcon) {
|
||||
loadIcon(newIcon, options);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Preload common icons used throughout the application
|
||||
* @param {Array} commonIcons - Array of commonly used icon names
|
||||
* @param {Object} options - Icon options
|
||||
*/
|
||||
const preloadCommonIcons = (commonIcons = [], options = {}) => {
|
||||
const defaultCommonIcons = [
|
||||
'send', 'attach_file', 'mic', 'more_vert', 'close', 'check',
|
||||
'error', 'warning', 'info', 'expand_more', 'expand_less'
|
||||
];
|
||||
|
||||
const iconsToLoad = commonIcons.length > 0 ? commonIcons : defaultCommonIcons;
|
||||
loadIcons(iconsToLoad, options);
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
isIconManagerReady,
|
||||
|
||||
// Methods
|
||||
loadIcon,
|
||||
loadIcons,
|
||||
ensureIconsLoaded,
|
||||
|
||||
// Watchers
|
||||
watchIcon,
|
||||
watchFormDataIcon,
|
||||
|
||||
// Utilities
|
||||
preloadCommonIcons
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified composable for basic icon loading
|
||||
* Use this when you only need basic icon loading functionality
|
||||
*/
|
||||
export function useIcon(iconName, options = {}) {
|
||||
const { loadIcon, isIconManagerReady } = useIconManager();
|
||||
|
||||
onMounted(() => {
|
||||
if (iconName) {
|
||||
loadIcon(iconName, options);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
loadIcon,
|
||||
isIconManagerReady
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable for form-related icon management
|
||||
* Automatically handles formData.icon watching
|
||||
*/
|
||||
export function useFormIcon(formData, options = {}) {
|
||||
const { watchFormDataIcon, loadIcon, isIconManagerReady } = useIconManager();
|
||||
|
||||
// Automatically watch formData for icon changes
|
||||
watchFormDataIcon(formData, options);
|
||||
|
||||
return {
|
||||
loadIcon,
|
||||
isIconManagerReady
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user