/** * component-registry.js * MVP1: Lazy-loading registry for panel components * Components are loaded on-demand to improve performance */ /** * Component registry maps tag names to dynamic import paths * Format: { 'tag-name': () => import('path/to/component.js') } */ export const COMPONENT_REGISTRY = { // Tools components 'ds-metrics-panel': () => import('../components/tools/ds-metrics-panel.js'), 'ds-console-viewer': () => import('../components/tools/ds-console-viewer.js'), 'ds-token-inspector': () => import('../components/tools/ds-token-inspector.js'), 'ds-figma-status': () => import('../components/tools/ds-figma-status.js'), 'ds-activity-log': () => import('../components/tools/ds-activity-log.js'), 'ds-visual-diff': () => import('../components/tools/ds-visual-diff.js'), 'ds-accessibility-report': () => import('../components/tools/ds-accessibility-report.js'), 'ds-screenshot-gallery': () => import('../components/tools/ds-screenshot-gallery.js'), 'ds-network-monitor': () => import('../components/tools/ds-network-monitor.js'), 'ds-test-results': () => import('../components/tools/ds-test-results.js'), 'ds-system-log': () => import('../components/tools/ds-system-log.js'), // Phase 6 Special Tools (MVP2) 'ds-figma-extract-quick': () => import('../components/tools/ds-figma-extract-quick.js'), 'ds-quick-wins-script': () => import('../components/tools/ds-quick-wins-script.js'), 'ds-regression-testing': () => import('../components/tools/ds-regression-testing.js'), // Other team-specific tools // UI Team Tools 'ds-storybook-figma-compare': () => import('../components/tools/ds-storybook-figma-compare.js'), 'ds-storybook-live-compare': () => import('../components/tools/ds-storybook-live-compare.js'), 'ds-figma-extraction': () => import('../components/tools/ds-figma-extraction.js'), 'ds-project-analysis': () => import('../components/tools/ds-project-analysis.js'), // UX Team Tools 'ds-figma-plugin': () => import('../components/tools/ds-figma-plugin.js'), 'ds-token-list': () => import('../components/tools/ds-token-list.js'), 'ds-asset-list': () => import('../components/tools/ds-asset-list.js'), 'ds-component-list': () => import('../components/tools/ds-component-list.js'), 'ds-navigation-demos': () => import('../components/tools/ds-navigation-demos.js'), // QA Team Tools 'ds-figma-live-compare': () => import('../components/tools/ds-figma-live-compare.js'), 'ds-esre-editor': () => import('../components/tools/ds-esre-editor.js'), // Chat components 'ds-chat-panel': () => import('../components/tools/ds-chat-panel.js'), // Metrics components 'ds-frontpage': () => import('../components/metrics/ds-frontpage.js'), // Admin components 'ds-user-settings': () => import('../components/admin/ds-user-settings.js'), // Additional UI & Layout Components 'ds-action-bar': () => import('../components/ds-action-bar.js'), 'ds-activity-bar': () => import('../components/layout/ds-activity-bar.js'), 'ds-admin-settings': () => import('../components/admin/ds-admin-settings.js'), 'ds-ai-chat-sidebar': () => import('../components/layout/ds-ai-chat-sidebar.js'), 'ds-badge': () => import('../components/ds-badge.js'), 'ds-base-tool': () => import('../components/base/ds-base-tool.js'), 'ds-button': () => import('../components/ds-button.js'), 'ds-card': () => import('../components/ds-card.js'), 'ds-component-base': () => import('../components/ds-component-base.js'), 'ds-input': () => import('../components/ds-input.js'), 'ds-metric-card': () => import('../components/metrics/ds-metric-card.js'), 'ds-metrics-dashboard': () => import('../components/metrics/ds-metrics-dashboard.js'), 'ds-notification-center': () => import('../components/ds-notification-center.js'), 'ds-panel': () => import('../components/layout/ds-panel.js'), 'ds-project-list': () => import('../components/admin/ds-project-list.js'), 'ds-project-selector': () => import('../components/layout/ds-project-selector.js'), 'ds-quick-wins': () => import('../components/tools/ds-quick-wins.js'), 'ds-shell': () => import('../components/layout/ds-shell.js'), 'ds-toast': () => import('../components/ds-toast.js'), 'ds-toast-provider': () => import('../components/ds-toast-provider.js'), 'ds-workflow': () => import('../components/ds-workflow.js'), // Listing Components 'ds-icon-list': () => import('../components/listings/ds-icon-list.js'), 'ds-jira-issues': () => import('../components/listings/ds-jira-issues.js'), }; // Track loaded components const loadedComponents = new Set(); /** * MVP1: Lazy-load and hydrate a component * @param {string} tagName - Component tag name (e.g., 'ds-metrics-panel') * @param {HTMLElement} container - Container to append component to * @returns {Promise} The created component element */ export async function hydrateComponent(tagName, container) { if (!COMPONENT_REGISTRY[tagName]) { console.warn(`[ComponentRegistry] Unknown component: ${tagName}`); throw new Error(`Component not found in registry: ${tagName}`); } try { // Load component if not already loaded if (!loadedComponents.has(tagName)) { console.log(`[ComponentRegistry] Loading component: ${tagName}`); await COMPONENT_REGISTRY[tagName](); loadedComponents.add(tagName); } // Verify component was registered as custom element if (!customElements.get(tagName)) { throw new Error(`Component ${tagName} loaded but not defined as custom element`); } // Create and append element const element = document.createElement(tagName); if (container) { container.appendChild(element); } return element; } catch (error) { console.error(`[ComponentRegistry] Failed to hydrate ${tagName}:`, error); throw error; } } /** * Check if component exists in registry * @param {string} tagName - Component tag name * @returns {boolean} */ export function isComponentRegistered(tagName) { return tagName in COMPONENT_REGISTRY; } /** * Check if component is already loaded * @param {string} tagName - Component tag name * @returns {boolean} */ export function isComponentLoaded(tagName) { return loadedComponents.has(tagName); } /** * Get all registered component tags * @returns {Array} Array of component tag names */ export function getRegisteredComponents() { return Object.keys(COMPONENT_REGISTRY); } /** * Preload a component without instantiating it * @param {string} tagName - Component tag name * @returns {Promise} */ export async function preloadComponent(tagName) { if (!COMPONENT_REGISTRY[tagName]) { throw new Error(`Component not found in registry: ${tagName}`); } if (!loadedComponents.has(tagName)) { await COMPONENT_REGISTRY[tagName](); loadedComponents.add(tagName); } } /** * Preload multiple components in parallel * @param {Array} tagNames - Array of component tag names * @returns {Promise} */ export async function preloadComponents(tagNames) { await Promise.all( tagNames.map(tag => preloadComponent(tag).catch(err => { console.warn(`Failed to preload ${tag}:`, err); })) ); } /** * Get registry statistics * @returns {object} Stats about loaded/unloaded components */ export function getRegistryStats() { const total = Object.keys(COMPONENT_REGISTRY).length; const loaded = loadedComponents.size; return { total, loaded, unloaded: total - loaded, loadedComponents: Array.from(loadedComponents), availableComponents: Object.keys(COMPONENT_REGISTRY) }; }