omnibox.ts RawHistoryFolder
1/**
2 * Omnibox Module Initialization
3 *
4 * Initializes the Svelte 5 omnibox component system
5 */
6
7import { mount } from 'svelte';
8import { Omnibox } from '../../components/omnibox';
9import { ensureShadowMount } from './shadowHost';
10import type { OmniboxConfig } from '../../components/omnibox/types';
11
12let omniboxComponent: ReturnType<typeof mount> | null = null;
13let isInitialized = false;
14
15export interface OmniboxInitConfig extends OmniboxConfig {
16 // Additional initialization options if needed
17 containerId?: string;
18}
19
20/**
21 * Initialize the omnibox component system
22 */
23export async function initializeOmnibox(_config: OmniboxInitConfig = {}): Promise<void> {
24 if (isInitialized) {
25 console.warn('Omnibox already initialized');
26 return;
27 }
28
29 try {
30 // Ensure we're in the main frame (not an iframe)
31 if (window.self !== window.top) {
32 console.log('🚫 Omnibox skipped in iframe');
33 return;
34 }
35
36 // Check if DOM is ready
37 if (!document.body) {
38 console.warn('DOM body not ready for omnibox initialization');
39 return;
40 }
41
42 // Mount omnibox into the shared global Shadow DOM host
43 const mountEl = ensureShadowMount('dumber-omnibox');
44 omniboxComponent = mount(Omnibox, {
45 target: mountEl as unknown as Element
46 });
47
48 // Wait for the component to mount and set up the global API
49 await new Promise<void>((resolve) => {
50 const checkAPI = () => {
51 if (window.__dumber_omnibox && typeof window.__dumber_omnibox === 'object') {
52 console.log('✅ Omnibox component system initialized');
53 console.log('🔧 Global API is available:', Object.keys(window.__dumber_omnibox));
54 isInitialized = true;
55 // Notify isolated bundle listeners that omnibox is ready
56 try {
57 document.dispatchEvent(new CustomEvent('dumber:omnibox-ready'));
58 } catch (e) {
59 console.warn('Failed to dispatch omnibox-ready event', e);
60 }
61 resolve();
62 } else {
63 setTimeout(checkAPI, 10); // Check again in 10ms
64 }
65 };
66 checkAPI();
67 });
68
69 // Bridge: listen for page-world events carrying suggestions and forward to API
70 const handleSuggestionsEvent = (e: Event) => {
71 try {
72 const detail = (e as CustomEvent).detail;
73 const suggestions = detail?.suggestions ?? detail;
74 if (Array.isArray(suggestions) && window.__dumber_omnibox?.setSuggestions) {
75 console.log('🔗 [Bridge] Received page-world suggestions event:', suggestions.length);
76 window.__dumber_omnibox.setSuggestions(suggestions);
77 } else {
78 console.warn('🔗 [Bridge] Suggestions event received but API not ready or invalid payload');
79 }
80 } catch (err) {
81 console.warn('🔗 [Bridge] Failed handling suggestions event:', err);
82 }
83 };
84
85 document.addEventListener(
86 'dumber:omnibox-suggestions',
87 handleSuggestionsEvent,
88 false
89 );
90 // Unified event name
91 document.addEventListener('dumber:omnibox:suggestions', handleSuggestionsEvent, false);
92
93 } catch (error) {
94 console.error('❌ Failed to initialize omnibox component:', error);
95 throw error;
96 }
97}
98
99/**
100 * Get the current initialization status
101 */
102export function isOmniboxInitialized(): boolean {
103 return isInitialized;
104}
105
106/**
107 * Cleanup omnibox component (useful for hot reload during development)
108 */
109export function cleanupOmnibox(): void {
110 if (omniboxComponent) {
111 try {
112 omniboxComponent.$destroy?.();
113 } catch (error) {
114 console.warn('Error destroying omnibox component:', error);
115 }
116 omniboxComponent = null;
117 }
118
119 // The shared shadow host remains persistent; just log cleanup
120
121 isInitialized = false;
122 console.log('🧹 Omnibox component cleaned up');
123}