Skip to content

KimuComponentElement โ€‹

Abstract base class for all KIMU framework components and extensions.

Description โ€‹

KimuComponentElement is the fundamental class from which all KIMU components derive. It extends HTMLElement and provides essential functionality for lifecycle, rendering, and resource management.

Key Features:

  • Automatic Shadow DOM for CSS/DOM isolation
  • Lifecycle hooks for component lifecycle management
  • Template-based rendering system
  • Automatic asset and dependency management
  • Utilities for DOM queries and resource loading

Basic Usage โ€‹

Creating a Component โ€‹

typescript
import { KimuComponentElement } from './core/kimu-component-element';
import { KimuComponent } from './core/kimu-component';

@KimuComponent({
    tag: 'my-component',
    name: 'My Component',
    version: '1.0.0',
    path: 'my-component'
})
export class MyComponent extends KimuComponentElement {
    
    // Provides data for rendering
    getData(): Record<string, any> {
        return {
            title: 'Hello KIMU!',
            timestamp: Date.now()
        };
    }
    
    // Initialization hook
    onInit(): void {
        console.log('Component initialized');
    }
    
    // Hook after each render
    onRender(): void {
        console.log('Component rendered');
        
        // Access template elements
        const button = this.$('button');
        if (button) {
            button.addEventListener('click', () => {
                this.refresh(); // Re-render
            });
        }
    }
    
    // Destruction hook
    onDestroy(): void {
        console.log('Component destroyed');
    }
}

HTML Template (view.html) โ€‹

html
<div class="container">
    <h1>${title}</h1>
    <p>Timestamp: ${timestamp}</p>
    <button>Update</button>
</div>

CSS Styles (style.css) โ€‹

css
:host {
    display: block;
    padding: 20px;
}

.container {
    background: #f0f0f0;
    border-radius: 8px;
    padding: 16px;
}

button {
    background: #007acc;
    color: white;
    border: none;
    padding: 8px 16px;
    border-radius: 4px;
    cursor: pointer;
}

API โ€‹

Abstract Methods โ€‹

getData(): Record<string, any> โ€‹

Required: Provides data for template rendering.

Returns: Record<string, any> - Object with component data

Example:

typescript
getData(): Record<string, any> {
    return {
        username: this.getAttribute('username') || 'Guest',
        isLoggedIn: this.hasAttribute('logged-in'),
        items: this.items || []
    };
}

Lifecycle Hooks โ€‹

onInit(): void โ€‹

Hook called once after the component has been connected to the DOM and initialized.

Typical usage:

  • Event setup
  • State initialization
  • Initial configuration
typescript
onInit(): void {
    // Setup global events
    window.addEventListener('resize', this.handleResize.bind(this));
    
    // State initialization
    this.state = { count: 0 };
}

onRender(): void โ€‹

Hook called after each template rendering.

Typical usage:

  • DOM event binding
  • Dynamic element updates
  • Animations
typescript
onRender(): void {
    // Event binding
    this.$('.btn-increment')?.addEventListener('click', () => {
        this.state.count++;
        this.refresh();
    });
    
    // Element updates
    const counter = this.$('.counter');
    if (counter) {
        counter.textContent = this.state.count.toString();
    }
}

onDestroy(): void โ€‹

Hook called when the component is removed from the DOM.

Typical usage:

  • Event cleanup
  • Timer cancellation
  • Resource release
typescript
onDestroy(): void {
    // Event cleanup
    window.removeEventListener('resize', this.handleResize);
    
    // Timer cancellation
    if (this.timer) {
        clearInterval(this.timer);
    }
}

Utility Methods โ€‹

$(selector: string): HTMLElement | null โ€‹

Shortcut for DOM query within the Shadow DOM.

Parameters:

  • selector: string - CSS selector

Returns: HTMLElement | null

Example:

typescript
onRender(): void {
    const button = this.$('button.primary');
    const inputs = this.shadowRoot?.querySelectorAll('input');
}

refresh(): Promise<void> โ€‹

Forces a re-render of the component with current data.

Usage:

typescript
// Update state and re-render
this.updateState();
await this.refresh();

getMeta(): KimuExtensionMeta โ€‹

Gets the metadata associated with the component (defined in the decorator).

Returns: KimuExtensionMeta

Example:

typescript
onInit(): void {
    const meta = this.getMeta();
    console.log(`Component: ${meta.name} v${meta.version}`);
}

Resource Methods โ€‹

loadResource(file: string): Promise<any> โ€‹

Loads a JSON resource from the extension's resources/ folder.

Parameters:

  • file: string - Resource file name

Returns: Promise<any> - JSON content of the resource

Example:

typescript
async onInit(): Promise<void> {
    try {
        const config = await this.loadResource('config.json');
        const translations = await this.loadResource('i18n/en.json');
        
        this.setupWithConfig(config);
    } catch (error) {
        console.error('Resource loading error:', error);
    }
}

loadAssetUrl(file: string): string โ€‹

Generates the URL for an asset in the extension's assets/ folder.

Parameters:

  • file: string - Asset file name

Returns: string - Complete asset URL

Example:

typescript
getData(): Record<string, any> {
    return {
        logoUrl: this.loadAssetUrl('logo.png'),
        iconUrl: this.loadAssetUrl('icons/user.svg')
    };
}

Complete Lifecycle โ€‹

typescript
@KimuComponent({
    tag: 'advanced-component',
    name: 'Advanced Component',
    path: 'advanced-component',
    dependencies: ['base-utils'] // Load dependencies first
})
export class AdvancedComponent extends KimuComponentElement {
    private state: any = {};
    private timer?: number;
    
    // 1. Data for template
    getData(): Record<string, any> {
        return {
            ...this.state,
            timestamp: new Date().toLocaleString()
        };
    }
    
    // 2. Initialization (once)
    async onInit(): Promise<void> {
        // Load configuration
        const config = await this.loadResource('config.json');
        this.state = { ...config.defaultState };
        
        // Setup timer
        this.timer = window.setInterval(() => {
            this.refresh();
        }, 1000);
        
        console.log('โœ… Component initialized');
    }
    
    // 3. After each render
    onRender(): void {
        // Event binding
        this.$('.update-btn')?.addEventListener('click', () => {
            this.handleUpdate();
        });
        
        console.log('๐ŸŽจ Component rendered');
    }
    
    // 4. Cleanup (when removed)
    onDestroy(): void {
        if (this.timer) {
            clearInterval(this.timer);
        }
        
        console.log('๐Ÿ—‘๏ธ Component destroyed');
    }
    
    private handleUpdate(): void {
        this.state.counter = (this.state.counter || 0) + 1;
        this.refresh();
    }
}

Best Practices โ€‹

State Management โ€‹

typescript
// โœ… Local state in component
private state = {
    count: 0,
    isLoading: false
};

// โœ… State update with refresh
updateCount(newCount: number): void {
    this.state.count = newCount;
    this.refresh(); // Re-render with new data
}

Event Management โ€‹

typescript
// โœ… Event binding in onRender
onRender(): void {
    // Remove old listeners if necessary
    this.$('.btn')?.removeEventListener('click', this.handleClick);
    
    // Add new listeners
    this.$('.btn')?.addEventListener('click', this.handleClick.bind(this));
}

// โœ… Cleanup in onDestroy
onDestroy(): void {
    this.$('.btn')?.removeEventListener('click', this.handleClick);
}

Async Loading โ€‹

typescript
async onInit(): Promise<void> {
    try {
        // โœ… Parallel resource loading
        const [config, translations, userData] = await Promise.all([
            this.loadResource('config.json'),
            this.loadResource('i18n/en.json'),
            this.fetchUserData()
        ]);
        
        this.setupComponent(config, translations, userData);
        
    } catch (error) {
        this.handleError(error);
    }
}

Optimizations and Performance โ€‹

Optimization Configuration โ€‹

KIMU-Core includes safe optimizations to improve performance and reliability without adding complexity.

configureOptimizations(settings): void (Static) โ€‹

Configure global optimizations for all components.

Parameters:

  • settings: object - Optimization settings

Available options:

typescript
KimuComponentElement.configureOptimizations({
    enableTemplateCache: true,      // Cache compiled templates (default: true)
    enableFileCache: true,          // Cache loaded files (default: true)
    enableRenderDebouncing: true,   // Render debouncing (default: true)
    enableErrorBoundaries: true,    // Error isolation (default: true)
    cacheMaxSize: 50,              // Template cache limit (default: 50)
    enableAssetPreloading: false   // Asset preloading (default: false)
});

Error Boundaries โ€‹

Components have automatic error isolation to prevent cascading crashes.

onError(error: Error): void (Optional) โ€‹

Hook for custom error handling in rendering.

typescript
export class MyComponent extends KimuComponentElement {
    // Custom error handling
    onError(error: Error): void {
        console.error(`Error in ${this.tagName}:`, error);
        
        // Report error to analytics service
        this.reportError(error);
        
        // Notify user (fallback UI is shown automatically)
        this.showUserNotification('Component temporarily unavailable');
    }
    
    private reportError(error: Error) {
        // Send error to logging service
        fetch('/api/errors', {
            method: 'POST',
            body: JSON.stringify({
                component: this.tagName,
                error: error.message,
                stack: error.stack
            })
        });
    }
}

Asset Preloading โ€‹

Improve performance by preloading critical assets.

preloadAssets(paths: string[]): Promise<void> (Static) โ€‹

Preload assets to improve perceived performance.

typescript
// During app initialization
await KimuComponentElement.preloadAssets([
    'extensions/dashboard/view.html',
    'extensions/dashboard/style.css',
    'extensions/sidebar/view.html',
    'assets/theme.css'
]);

Debug and Monitoring โ€‹

getOptimizationSettings(): object (Static) โ€‹

Returns current optimization settings for debugging.

typescript
// Check configuration
console.log('Active optimizations:', 
    KimuComponentElement.getOptimizationSettings());

forceRefresh(): Promise<void> โ€‹

Force immediate refresh bypassing optimizations (useful for debugging).

typescript
// Debug: forced refresh
await this.forceRefresh();

See Also โ€‹

Released under Creative Commons Attribution 4.0 International (CC BY 4.0)