# LiveComponents Events Reference

Complete reference for all client-side events and lifecycle hooks with examples and best practices.

## Table of Contents

- [Lifecycle Events](#lifecycle-events)
  - [livecomponent:init](#livecomponentinit)
  - [livecomponent:mounted](#livecomponentmounted)
  - [livecomponent:updated](#livecomponentupdated)
  - [livecomponent:unmounted](#livecomponentunmounted)
- [Action Events](#action-events)
  - [livecomponent:action-start](#livecomponentaction-start)
  - [livecomponent:action-executed](#livecomponentaction-executed)
  - [livecomponent:action-failed](#livecomponentaction-failed)
- [State Events](#state-events)
  - [livecomponent:state-changed](#livecomponentstate-changed)
  - [livecomponent:prop-updated](#livecomponentprop-updated)
- [Network Events](#network-events)
  - [livecomponent:request-start](#livecomponentrequest-start)
  - [livecomponent:request-complete](#livecomponentrequest-complete)
  - [livecomponent:request-failed](#livecomponentrequest-failed)
  - [livecomponent:batch-dispatched](#livecomponentbatch-dispatched)
- [Rendering Events](#rendering-events)
  - [livecomponent:render-start](#livecomponentrender-start)
  - [livecomponent:render-complete](#livecomponentrender-complete)
  - [livecomponent:fragment-updated](#livecomponentfragment-updated)
- [SSE Events](#sse-events)
  - [livecomponent:sse-connected](#livecomponentsse-connected)
  - [livecomponent:sse-disconnected](#livecomponentsse-disconnected)
  - [livecomponent:sse-message](#livecomponentsse-message)
  - [livecomponent:sse-error](#livecomponentsse-error)
- [Upload Events](#upload-events)
  - [livecomponent:upload-start](#livecomponentupload-start)
  - [livecomponent:upload-progress](#livecomponentupload-progress)
  - [livecomponent:upload-complete](#livecomponentupload-complete)
  - [livecomponent:upload-failed](#livecomponentupload-failed)
- [Error Events](#error-events)
  - [livecomponent:error](#livecomponenterror)
  - [livecomponent:validation-error](#livecomponentvalidation-error)
  - [livecomponent:rate-limit-exceeded](#livecomponentrate-limit-exceeded)

---

## Lifecycle Events

### livecomponent:init

**Fired**: When a LiveComponent is discovered in the DOM but before initialization.

**Use Case**: Prepare component before mounting, modify initial state.

**Event Detail**:
```typescript
{
    componentId: string;      // Unique component ID
    element: HTMLElement;     // Component root element
    props: object;           // Initial component props
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:init', (event) => {
    const { componentId, element, props } = event.detail;

    console.log('Initializing component:', componentId);

    // Modify initial props
    if (props.theme === undefined) {
        props.theme = localStorage.getItem('theme') || 'light';
    }

    // Add custom data attributes
    element.dataset.initialized = Date.now();
});
```

**Common Use Cases**:
- Restore state from localStorage
- Set default props from user preferences
- Initialize third-party libraries
- Track component initialization analytics

---

### livecomponent:mounted

**Fired**: After a LiveComponent is fully mounted and ready for interaction.

**Use Case**: Initialize JavaScript behaviors, start timers, load external data.

**Event Detail**:
```typescript
{
    componentId: string;      // Unique component ID
    element: HTMLElement;     // Component root element
    component: Component;     // Component instance
    props: object;           // Current component props
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:mounted', (event) => {
    const { componentId, element, component } = event.detail;

    // Initialize tooltips
    const tooltips = element.querySelectorAll('[data-tooltip]');
    tooltips.forEach(el => new Tooltip(el));

    // Start auto-refresh timer
    if (component.config.autoRefresh) {
        setInterval(() => {
            component.executeAction('refresh');
        }, component.config.refreshInterval || 30000);
    }

    // Track mount analytics
    analytics.track('component_mounted', {
        component_type: componentId,
        mount_time: Date.now()
    });
});
```

**Common Use Cases**:
- Initialize third-party plugins (charts, maps, editors)
- Start polling/auto-refresh timers
- Bind custom event listeners
- Load deferred content
- Track analytics

---

### livecomponent:updated

**Fired**: After a LiveComponent has been updated (re-rendered).

**Use Case**: React to state changes, update third-party integrations, track updates.

**Event Detail**:
```typescript
{
    componentId: string;      // Unique component ID
    element: HTMLElement;     // Component root element
    component: Component;     // Component instance
    previousProps: object;    // Props before update
    currentProps: object;     // Props after update
    changedProps: string[];   // Names of changed props
    fragments: string[];      // Updated fragments (if partial render)
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:updated', (event) => {
    const { componentId, previousProps, currentProps, changedProps, fragments } = event.detail;

    // Re-initialize elements in updated fragments
    if (fragments.includes('chart-container')) {
        const chartEl = document.querySelector('[data-lc-fragment="chart-container"]');
        initializeChart(chartEl, currentProps.chartData);
    }

    // Track specific prop changes
    if (changedProps.includes('status')) {
        console.log('Status changed:', previousProps.status, '→', currentProps.status);

        if (currentProps.status === 'completed') {
            showSuccessNotification();
        }
    }

    // Update document title
    if (changedProps.includes('unreadCount')) {
        document.title = currentProps.unreadCount > 0
            ? `(${currentProps.unreadCount}) Messages`
            : 'Messages';
    }
});
```

**Common Use Cases**:
- Re-initialize third-party components in updated fragments
- Trigger animations on state changes
- Update browser title/favicon based on state
- Track state change analytics
- Sync with external systems

---

### livecomponent:unmounted

**Fired**: Before a LiveComponent is removed from the DOM.

**Use Case**: Cleanup timers, remove event listeners, save state.

**Event Detail**:
```typescript
{
    componentId: string;      // Unique component ID
    element: HTMLElement;     // Component root element (about to be removed)
    component: Component;     // Component instance
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:unmounted', (event) => {
    const { componentId, element, component } = event.detail;

    // Save state to localStorage
    localStorage.setItem(`component-${componentId}`, JSON.stringify(component.props));

    // Clear timers
    if (window.componentTimers[componentId]) {
        clearInterval(window.componentTimers[componentId]);
        delete window.componentTimers[componentId];
    }

    // Destroy third-party instances
    if (window.chartInstances[componentId]) {
        window.chartInstances[componentId].destroy();
        delete window.chartInstances[componentId];
    }

    // Track unmount analytics
    analytics.track('component_unmounted', {
        component_type: componentId,
        lifetime_ms: Date.now() - parseInt(element.dataset.initialized)
    });
});
```

**Common Use Cases**:
- Save component state before removal
- Clear timers and intervals
- Remove global event listeners
- Destroy third-party plugin instances
- Cancel pending network requests
- Track component lifetime analytics

---

## Action Events

### livecomponent:action-start

**Fired**: When a LiveAction is triggered (before server request).

**Use Case**: Show loading states, disable buttons, track action starts.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    action: string;          // Action name
    params: object;          // Action parameters
    element: HTMLElement;    // Element that triggered action
    timestamp: number;       // Start timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:action-start', (event) => {
    const { componentId, action, params, element } = event.detail;

    // Show loading state
    element.classList.add('loading');
    element.disabled = true;

    // Show loading spinner for long-running actions
    if (['generateReport', 'processPayment'].includes(action)) {
        showLoadingSpinner(`Processing ${action}...`);
    }

    // Track action starts
    analytics.track('action_started', {
        component: componentId,
        action: action,
        params: params
    });
});
```

**Common Use Cases**:
- Show loading indicators
- Disable form buttons to prevent double-submission
- Show progress overlays
- Track action analytics
- Optimistic UI updates

---

### livecomponent:action-executed

**Fired**: After a LiveAction completes successfully.

**Use Case**: Hide loading states, show success messages, track performance.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    action: string;          // Action name
    params: object;          // Action parameters
    result: any;             // Action result
    duration: number;        // Execution time (ms)
    timestamp: number;       // Completion timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:action-executed', (event) => {
    const { componentId, action, result, duration } = event.detail;

    // Hide loading states
    hideLoadingSpinner();

    // Show success message for specific actions
    if (action === 'saveForm') {
        showToast('Changes saved successfully!', 'success');
    }

    // Track slow actions
    if (duration > 1000) {
        console.warn(`Slow action: ${action} took ${duration}ms`);
        analytics.track('slow_action', {
            component: componentId,
            action: action,
            duration: duration
        });
    }

    // Update badge counts
    if (action === 'markAsRead') {
        const badge = document.querySelector('.unread-badge');
        const count = parseInt(badge.textContent) - 1;
        badge.textContent = count > 0 ? count : '';
    }
});
```

**Common Use Cases**:
- Hide loading indicators
- Show success notifications
- Update UI elements outside component
- Track action performance
- Trigger follow-up actions

---

### livecomponent:action-failed

**Fired**: When a LiveAction fails (validation, authorization, or server error).

**Use Case**: Show error messages, re-enable forms, track failures.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    action: string;          // Action name
    params: object;          // Action parameters
    error: {
        message: string;      // Error message
        code: string;        // Error code
        details: object;     // Additional error details
    };
    duration: number;        // Time before failure (ms)
    timestamp: number;       // Failure timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:action-failed', (event) => {
    const { componentId, action, error, element } = event.detail;

    // Re-enable form elements
    if (element) {
        element.classList.remove('loading');
        element.disabled = false;
    }

    // Show error message
    if (error.code === 'VALIDATION_ERROR') {
        showValidationErrors(error.details);
    } else if (error.code === 'RATE_LIMIT_EXCEEDED') {
        showToast(`Too many requests. Please wait ${error.details.retryAfter} seconds.`, 'warning');
    } else {
        showToast(error.message || 'An error occurred', 'error');
    }

    // Track failures
    analytics.track('action_failed', {
        component: componentId,
        action: action,
        error_code: error.code,
        error_message: error.message
    });
});
```

**Common Use Cases**:
- Display error messages
- Re-enable disabled form elements
- Show validation errors
- Track error rates
- Trigger error recovery flows

---

## State Events

### livecomponent:state-changed

**Fired**: When component state changes (any LiveProp update).

**Use Case**: React to any state change, sync with external systems.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    previousState: object;    // State before change
    currentState: object;     // State after change
    changedProps: string[];   // Names of changed props
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:state-changed', (event) => {
    const { componentId, previousState, currentState, changedProps } = event.detail;

    // Sync with localStorage
    localStorage.setItem(`state-${componentId}`, JSON.stringify(currentState));

    // Track state changes
    changedProps.forEach(prop => {
        console.log(`${prop} changed:`, previousState[prop], '→', currentState[prop]);
    });

    // Trigger side effects
    if (changedProps.includes('selectedItems')) {
        updateBulkActionBar(currentState.selectedItems);
    }
});
```

**Common Use Cases**:
- Persist state to localStorage
- Sync with external state management
- Update derived UI elements
- Track state change analytics
- Debug state changes

---

### livecomponent:prop-updated

**Fired**: When a specific LiveProp is updated.

**Use Case**: React to specific property changes, trigger dependent updates.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    propName: string;        // Updated property name
    previousValue: any;      // Value before update
    currentValue: any;       // Value after update
    source: 'server' | 'client' | 'optimistic';  // Update source
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:prop-updated', (event) => {
    const { componentId, propName, previousValue, currentValue, source } = event.detail;

    // React to specific prop changes
    if (propName === 'theme') {
        document.body.classList.remove(`theme-${previousValue}`);
        document.body.classList.add(`theme-${currentValue}`);
        localStorage.setItem('theme', currentValue);
    }

    if (propName === 'count' && source === 'optimistic') {
        // Animate optimistic updates
        animateNumberChange(previousValue, currentValue);
    }

    if (propName === 'sortOrder') {
        // Re-sort table when sort order changes
        sortTable(currentValue);
    }
});
```

**Common Use Cases**:
- Trigger animations on specific prop changes
- Update global UI state (theme, locale)
- Sync specific props with localStorage
- Track important prop changes
- Trigger dependent updates

---

## Network Events

### livecomponent:request-start

**Fired**: When a network request starts (action or state sync).

**Use Case**: Show global loading indicators, track request starts.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    requestId: string;       // Unique request ID
    type: 'action' | 'sync'; // Request type
    payload: object;         // Request payload
    timestamp: number;       // Start timestamp
}
```

**Example**:
```javascript
let activeRequests = 0;

window.addEventListener('livecomponent:request-start', (event) => {
    const { componentId, requestId, type } = event.detail;

    activeRequests++;

    // Show global loading indicator
    if (activeRequests === 1) {
        document.body.classList.add('loading');
    }

    // Track request
    console.log(`Request ${requestId} started for ${componentId} (type: ${type})`);
});
```

---

### livecomponent:request-complete

**Fired**: When a network request completes successfully.

**Use Case**: Hide loading indicators, track request performance.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    requestId: string;       // Unique request ID
    type: 'action' | 'sync'; // Request type
    response: object;        // Server response
    duration: number;        // Request duration (ms)
    timestamp: number;       // Completion timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:request-complete', (event) => {
    const { componentId, requestId, duration } = event.detail;

    activeRequests--;

    // Hide global loading indicator
    if (activeRequests === 0) {
        document.body.classList.remove('loading');
    }

    // Track slow requests
    if (duration > 1000) {
        console.warn(`Slow request: ${requestId} took ${duration}ms`);
    }
});
```

---

### livecomponent:request-failed

**Fired**: When a network request fails.

**Use Case**: Handle network errors, retry logic, track failures.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    requestId: string;       // Unique request ID
    type: 'action' | 'sync'; // Request type
    error: {
        message: string;      // Error message
        code: string;        // Error code
        status: number;      // HTTP status code
    };
    duration: number;        // Time before failure (ms)
    timestamp: number;       // Failure timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:request-failed', (event) => {
    const { componentId, requestId, error, duration } = event.detail;

    activeRequests--;

    // Hide global loading indicator
    if (activeRequests === 0) {
        document.body.classList.remove('loading');
    }

    // Handle network errors
    if (error.status === 0) {
        showToast('Network error. Please check your connection.', 'error');
    } else if (error.status === 429) {
        showToast('Too many requests. Please slow down.', 'warning');
    } else if (error.status >= 500) {
        showToast('Server error. Please try again later.', 'error');
    }

    // Track failures
    analytics.track('request_failed', {
        component: componentId,
        request_id: requestId,
        error_code: error.code,
        status: error.status
    });
});
```

---

### livecomponent:batch-dispatched

**Fired**: When batched requests are sent to server.

**Use Case**: Track batching efficiency, debug batch behavior.

**Event Detail**:
```typescript
{
    batchId: string;         // Unique batch ID
    actions: Array<{         // Batched actions
        componentId: string;
        action: string;
        params: object;
    }>;
    batchSize: number;       // Number of actions in batch
    timestamp: number;       // Dispatch timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:batch-dispatched', (event) => {
    const { batchId, actions, batchSize } = event.detail;

    console.log(`Batch ${batchId} dispatched with ${batchSize} actions:`, actions);

    // Track batching efficiency
    analytics.track('batch_dispatched', {
        batch_id: batchId,
        batch_size: batchSize,
        components: [...new Set(actions.map(a => a.componentId))]
    });
});
```

---

## Rendering Events

### livecomponent:render-start

**Fired**: Before component re-rendering begins.

**Use Case**: Save scroll position, prepare for render.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    fragments: string[];      // Fragments to be rendered
    timestamp: number;       // Render start timestamp
}
```

**Example**:
```javascript
const scrollPositions = new Map();

window.addEventListener('livecomponent:render-start', (event) => {
    const { componentId, fragments } = event.detail;

    // Save scroll positions of fragments
    fragments.forEach(fragmentName => {
        const fragment = document.querySelector(`[data-lc-fragment="${fragmentName}"]`);
        if (fragment) {
            scrollPositions.set(fragmentName, {
                scrollTop: fragment.scrollTop,
                scrollLeft: fragment.scrollLeft
            });
        }
    });
});
```

---

### livecomponent:render-complete

**Fired**: After component re-rendering completes.

**Use Case**: Restore scroll position, re-initialize JavaScript.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    fragments: string[];      // Rendered fragments
    duration: number;        // Render duration (ms)
    timestamp: number;       // Render complete timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:render-complete', (event) => {
    const { componentId, fragments, duration } = event.detail;

    // Restore scroll positions
    fragments.forEach(fragmentName => {
        const fragment = document.querySelector(`[data-lc-fragment="${fragmentName}"]`);
        const savedPosition = scrollPositions.get(fragmentName);

        if (fragment && savedPosition) {
            fragment.scrollTop = savedPosition.scrollTop;
            fragment.scrollLeft = savedPosition.scrollLeft;
        }
    });

    // Re-initialize JavaScript in rendered fragments
    fragments.forEach(fragmentName => {
        const fragment = document.querySelector(`[data-lc-fragment="${fragmentName}"]`);
        initializeFragment(fragment);
    });

    // Track slow renders
    if (duration > 100) {
        console.warn(`Slow render: ${componentId} took ${duration}ms`);
    }
});
```

---

### livecomponent:fragment-updated

**Fired**: When a specific fragment is updated.

**Use Case**: Re-initialize fragment-specific JavaScript, track updates.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    fragmentName: string;    // Updated fragment name
    element: HTMLElement;    // Fragment element
    timestamp: number;       // Update timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:fragment-updated', (event) => {
    const { componentId, fragmentName, element } = event.detail;

    // Re-initialize specific fragment behaviors
    if (fragmentName === 'chart-container') {
        const chartEl = element.querySelector('.chart');
        if (chartEl) {
            initializeChart(chartEl);
        }
    }

    if (fragmentName === 'image-gallery') {
        const images = element.querySelectorAll('img[data-lazy]');
        lazyLoadImages(images);
    }

    // Track fragment updates
    analytics.track('fragment_updated', {
        component: componentId,
        fragment: fragmentName
    });
});
```

---

## SSE Events

### livecomponent:sse-connected

**Fired**: When SSE connection is established.

**Use Case**: Show online status, enable real-time features.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    url: string;             // SSE endpoint URL
    timestamp: number;       // Connection timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:sse-connected', (event) => {
    const { componentId, url } = event.detail;

    console.log(`SSE connected for ${componentId} at ${url}`);

    // Show online indicator
    const indicator = document.querySelector('.connection-status');
    indicator.classList.remove('offline');
    indicator.classList.add('online');
    indicator.textContent = 'Connected';
});
```

---

### livecomponent:sse-disconnected

**Fired**: When SSE connection is lost.

**Use Case**: Show offline status, disable real-time features.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    reason: string;          // Disconnection reason
    willReconnect: boolean;  // Auto-reconnect enabled
    timestamp: number;       // Disconnection timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:sse-disconnected', (event) => {
    const { componentId, reason, willReconnect } = event.detail;

    console.warn(`SSE disconnected for ${componentId}: ${reason}`);

    // Show offline indicator
    const indicator = document.querySelector('.connection-status');
    indicator.classList.remove('online');
    indicator.classList.add('offline');
    indicator.textContent = willReconnect ? 'Reconnecting...' : 'Offline';
});
```

---

### livecomponent:sse-message

**Fired**: When an SSE message is received.

**Use Case**: Handle real-time updates, show notifications.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    event: string;           // SSE event type
    data: any;               // Message data
    timestamp: number;       // Message timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:sse-message', (event) => {
    const { componentId, event: eventType, data } = event.detail;

    if (eventType === 'notification') {
        showNotification(data.title, data.body);
    }

    if (eventType === 'user-joined') {
        updateOnlineUsers(data.userId, data.userName);
    }

    if (eventType === 'price-update') {
        animatePriceChange(data.symbol, data.price);
    }
});
```

---

### livecomponent:sse-error

**Fired**: When an SSE error occurs.

**Use Case**: Handle SSE errors, implement fallback.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    error: {
        message: string;      // Error message
        code: string;        // Error code
    };
    timestamp: number;       // Error timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:sse-error', (event) => {
    const { componentId, error } = event.detail;

    console.error(`SSE error for ${componentId}:`, error.message);

    // Fallback to polling
    if (!window.pollingTimers[componentId]) {
        window.pollingTimers[componentId] = setInterval(() => {
            LiveComponent.getComponent(componentId).executeAction('refresh');
        }, 5000);
    }
});
```

---

## Upload Events

### livecomponent:upload-start

**Fired**: When file upload starts.

**Use Case**: Show upload progress UI.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    uploadId: string;        // Unique upload ID
    file: {
        name: string;
        size: number;
        type: string;
    };
    chunks: number;          // Total number of chunks
    timestamp: number;       // Upload start timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:upload-start', (event) => {
    const { uploadId, file, chunks } = event.detail;

    // Create progress UI
    const progressEl = document.createElement('div');
    progressEl.id = `upload-${uploadId}`;
    progressEl.innerHTML = `
        <div class="upload-item">
            <span class="filename">${file.name}</span>
            <div class="progress-bar">
                <div class="progress" style="width: 0%"></div>
            </div>
            <span class="status">Uploading (0/${chunks} chunks)...</span>
        </div>
    `;
    document.querySelector('.upload-queue').appendChild(progressEl);
});
```

---

### livecomponent:upload-progress

**Fired**: During file upload (per chunk).

**Use Case**: Update progress bar, show upload speed.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    uploadId: string;        // Upload ID
    progress: {
        loaded: number;       // Bytes uploaded
        total: number;        // Total bytes
        percentage: number;   // Progress percentage
        chunk: number;        // Current chunk
        totalChunks: number;  // Total chunks
    };
    timestamp: number;       // Progress update timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:upload-progress', (event) => {
    const { uploadId, progress } = event.detail;

    // Update progress bar
    const progressEl = document.querySelector(`#upload-${uploadId}`);
    const progressBar = progressEl.querySelector('.progress');
    const statusEl = progressEl.querySelector('.status');

    progressBar.style.width = `${progress.percentage}%`;
    statusEl.textContent = `Uploading (${progress.chunk}/${progress.totalChunks} chunks) - ${progress.percentage}%`;
});
```

---

### livecomponent:upload-complete

**Fired**: When file upload completes successfully.

**Use Case**: Show success message, clean up progress UI.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    uploadId: string;        // Upload ID
    file: {
        name: string;
        size: number;
        url: string;          // Uploaded file URL
    };
    duration: number;        // Upload duration (ms)
    timestamp: number;       // Completion timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:upload-complete', (event) => {
    const { uploadId, file, duration } = event.detail;

    // Update progress UI
    const progressEl = document.querySelector(`#upload-${uploadId}`);
    const statusEl = progressEl.querySelector('.status');

    statusEl.textContent = `✓ Complete (${(duration / 1000).toFixed(1)}s)`;
    statusEl.classList.add('success');

    // Remove after 3 seconds
    setTimeout(() => progressEl.remove(), 3000);

    // Show success toast
    showToast(`${file.name} uploaded successfully!`, 'success');
});
```

---

### livecomponent:upload-failed

**Fired**: When file upload fails.

**Use Case**: Show error message, allow retry.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    uploadId: string;        // Upload ID
    file: {
        name: string;
        size: number;
    };
    error: {
        message: string;      // Error message
        code: string;        // Error code
        chunk: number;       // Failed chunk (if applicable)
    };
    timestamp: number;       // Failure timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:upload-failed', (event) => {
    const { uploadId, file, error } = event.detail;

    // Update progress UI
    const progressEl = document.querySelector(`#upload-${uploadId}`);
    const statusEl = progressEl.querySelector('.status');

    statusEl.textContent = `✗ Failed: ${error.message}`;
    statusEl.classList.add('error');

    // Add retry button
    const retryBtn = document.createElement('button');
    retryBtn.textContent = 'Retry';
    retryBtn.onclick = () => retryUpload(uploadId);
    progressEl.appendChild(retryBtn);

    // Show error toast
    showToast(`Failed to upload ${file.name}: ${error.message}`, 'error');
});
```

---

## Error Events

### livecomponent:error

**Fired**: When a general LiveComponent error occurs.

**Use Case**: Global error handling, error tracking.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    error: {
        message: string;      // Error message
        code: string;        // Error code
        stack: string;       // Stack trace
    };
    context: string;         // Error context ('render', 'action', 'network', etc.)
    timestamp: number;       // Error timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:error', (event) => {
    const { componentId, error, context } = event.detail;

    console.error(`LiveComponent error in ${componentId} (${context}):`, error);

    // Send to error tracking service
    if (window.errorTracker) {
        window.errorTracker.captureException(error, {
            component: componentId,
            context: context
        });
    }

    // Show generic error message to user
    showToast('An unexpected error occurred. Please refresh the page.', 'error');
});
```

---

### livecomponent:validation-error

**Fired**: When server-side validation fails.

**Use Case**: Display validation errors, focus first error.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    action: string;          // Action that failed validation
    errors: Record<string, string[]>;  // Validation errors by field
    timestamp: number;       // Error timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:validation-error', (event) => {
    const { componentId, action, errors } = event.detail;

    // Display errors next to fields
    Object.entries(errors).forEach(([field, messages]) => {
        const input = document.querySelector(`[name="${field}"]`);
        const errorEl = input.parentElement.querySelector('.error-message');

        if (errorEl) {
            errorEl.textContent = messages[0];
            errorEl.style.display = 'block';
        }

        input.classList.add('invalid');
    });

    // Focus first invalid field
    const firstInvalid = document.querySelector('.invalid');
    if (firstInvalid) {
        firstInvalid.focus();
    }
});
```

---

### livecomponent:rate-limit-exceeded

**Fired**: When rate limit is exceeded for an action.

**Use Case**: Show rate limit message, display countdown.

**Event Detail**:
```typescript
{
    componentId: string;      // Component ID
    action: string;          // Rate-limited action
    retryAfter: number;      // Seconds until retry allowed
    timestamp: number;       // Rate limit timestamp
}
```

**Example**:
```javascript
window.addEventListener('livecomponent:rate-limit-exceeded', (event) => {
    const { componentId, action, retryAfter } = event.detail;

    // Show countdown toast
    let remaining = retryAfter;
    const toastId = showToast(
        `Rate limit exceeded. Please wait ${remaining} seconds.`,
        'warning',
        { duration: retryAfter * 1000 }
    );

    const countdown = setInterval(() => {
        remaining--;
        if (remaining > 0) {
            updateToast(toastId, `Rate limit exceeded. Please wait ${remaining} seconds.`);
        } else {
            clearInterval(countdown);
            updateToast(toastId, 'You can try again now!');
        }
    }, 1000);
});
```

---

## Event Patterns

### Event Delegation

```javascript
// Instead of listening on each component
document.addEventListener('livecomponent:action-executed', (event) => {
    if (event.detail.componentId.startsWith('notification-')) {
        updateNotificationBadge();
    }
});
```

### Debounced Event Handlers

```javascript
import { debounce } from './utils';

window.addEventListener('livecomponent:prop-updated',
    debounce((event) => {
        if (event.detail.propName === 'searchQuery') {
            updateSearchResults(event.detail.currentValue);
        }
    }, 300)
);
```

### Global Loading Indicator

```javascript
let activeRequests = 0;

window.addEventListener('livecomponent:request-start', () => {
    activeRequests++;
    if (activeRequests === 1) {
        document.body.classList.add('loading');
    }
});

window.addEventListener('livecomponent:request-complete', () => {
    activeRequests--;
    if (activeRequests === 0) {
        document.body.classList.remove('loading');
    }
});

window.addEventListener('livecomponent:request-failed', () => {
    activeRequests--;
    if (activeRequests === 0) {
        document.body.classList.remove('loading');
    }
});
```

### Performance Monitoring

```javascript
window.addEventListener('livecomponent:action-executed', (event) => {
    const { action, duration } = event.detail;

    if (duration > 1000) {
        console.warn(`Slow action: ${action} (${duration}ms)`);
    }

    // Track to analytics
    analytics.track('action_performance', {
        action: action,
        duration: duration
    });
});
```

---

## Best Practices

1. **Use Event Delegation**: Listen on `window` instead of individual elements
2. **Cleanup Listeners**: Remove listeners in `unmounted` event
3. **Debounce/Throttle**: Use debouncing for high-frequency events
4. **Error Handling**: Always handle errors gracefully
5. **Performance**: Minimize work in event handlers
6. **Analytics**: Track important events for monitoring
7. **User Feedback**: Provide visual feedback for all events
8. **Accessibility**: Announce important events to screen readers

---

For more examples and patterns, see:
- [Advanced Features Guide](advanced-features.md)
- [Troubleshooting Guide](troubleshooting.md)
- [API Reference](api-reference.md)
