1+ // Define the base settings
2+ const inkeepSettings = {
3+ isOpen : true ,
4+ baseSettings : {
5+ apiKey : "a58574ddc0e41c75990d1c0e890ad3c8725dc9e7c8ee3d3e" ,
6+ integrationId : "clthv1rgg000sdjil26l2vg03" ,
7+ organizationId : "org_SGvQFUfKzrYkf8z8" ,
8+ primaryBrandColor : "#5DFECA"
9+ } ,
10+ aiChatSettings : {
11+ chatSubjectName : "Vapi" ,
12+ botAvatarSrcUrl : "https://storage.googleapis.com/organization-image-assets/vapi-botAvatarSrcUrl-1709929183314.png" ,
13+ botAvatarDarkSrcUrl : "https://storage.googleapis.com/organization-image-assets/vapi-botAvatarDarkSrcUrl-1709929110474.png" ,
14+ getHelpCallToActions : [
15+ {
16+ name : "Contact Us" ,
17+ 18+ icon : {
19+ builtIn : "IoMail"
20+ }
21+ }
22+ ] ,
23+ quickQuestions : [
24+ "What voices are supported?" ,
25+ "What languages are supported?" ,
26+ "How do I connect a custom LLM?" ,
27+ "How do I fetch the prompt dynamically?"
28+ ]
29+ }
30+ } ;
31+
32+ // Function to initialize search containers
33+ function initializeSearchContainers ( ) {
34+ const searchButtonContainerIds = [
35+ "search-bar-entry" ,
36+ "search-bar-entry-mobile" ,
37+ ] ;
38+
39+ // Clone and replace search buttons to remove existing listeners
40+ // Only process elements that exist
41+ const clonedSearchButtonContainers = searchButtonContainerIds
42+ . map ( ( id ) => {
43+ const originalElement = document . getElementById ( id ) ;
44+ if ( ! originalElement ) {
45+ console . log ( `Search container ${ id } not found, skipping...` ) ;
46+ return null ;
47+ }
48+ const clonedElement = originalElement . cloneNode ( true ) ;
49+ originalElement . parentNode . replaceChild ( clonedElement , originalElement ) ;
50+ return clonedElement ;
51+ } )
52+ . filter ( Boolean ) ; // Remove null entries
53+
54+ return clonedSearchButtonContainers ;
55+ }
56+
57+ // Function to initialize Inkeep
58+ function initializeInkeep ( ) {
59+ // Color mode sync settings
60+ const colorModeSettings = {
61+ observedElement : document . documentElement ,
62+ isDarkModeCallback : ( el ) => {
63+ return el . classList . contains ( "dark" ) ;
64+ } ,
65+ colorModeAttribute : "class" ,
66+ } ;
67+
68+ // Initialize the chat button
69+ Inkeep ( ) . embed ( {
70+ componentType : "ChatButton" ,
71+ colorModeSync : colorModeSettings ,
72+ properties : inkeepSettings ,
73+ } ) ;
74+
75+ // Initialize the search modal
76+ const inkeepSearchModal = Inkeep ( {
77+ ...inkeepSettings . baseSettings ,
78+ } ) . embed ( {
79+ componentType : "CustomTrigger" ,
80+ colorModeSync : colorModeSettings ,
81+ properties : {
82+ ...inkeepSettings ,
83+ isOpen : false ,
84+ onClose : ( ) => {
85+ inkeepSearchModal . render ( {
86+ isOpen : false ,
87+ } ) ;
88+ } ,
89+ } ,
90+ } ) ;
91+
92+ // Get search containers after DOM is ready
93+ const clonedSearchButtonContainers = initializeSearchContainers ( ) ;
94+
95+ // Add click listeners to search buttons
96+ clonedSearchButtonContainers . forEach ( ( trigger ) => {
97+ trigger . addEventListener ( "click" , function ( ) {
98+ inkeepSearchModal . render ( {
99+ isOpen : true ,
100+ } ) ;
101+ } ) ;
102+ } ) ;
103+
104+ // Add keyboard shortcut listener
105+ window . addEventListener (
106+ "keydown" ,
107+ ( event ) => {
108+ if (
109+ ( event . metaKey || event . ctrlKey ) &&
110+ ( event . key === "k" || event . key === "K" )
111+ ) {
112+ event . stopPropagation ( ) ;
113+ inkeepSearchModal . render ( { isOpen : true } ) ;
114+ return false ;
115+ }
116+ } ,
117+ true
118+ ) ;
119+ }
120+
121+ // Create and inject the Inkeep script
122+ const inkeepScript = document . createElement ( "script" ) ;
123+ inkeepScript . type = "module" ;
124+ inkeepScript . src = "https://unpkg.com/@inkeep/widgets-embed@latest/dist/embed.js" ;
125+
126+ // Wait for both DOM content and Inkeep script to load
127+ let domReady = false ;
128+ let scriptLoaded = false ;
129+
130+ function tryInitialize ( ) {
131+ if ( domReady && scriptLoaded ) {
132+ initializeInkeep ( ) ;
133+ }
134+ }
135+
136+ // Handle DOM content loaded
137+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
138+ domReady = true ;
139+ tryInitialize ( ) ;
140+ } ) ;
141+
142+ // Handle script load
143+ inkeepScript . addEventListener ( "load" , ( ) => {
144+ scriptLoaded = true ;
145+ tryInitialize ( ) ;
146+ } ) ;
147+
148+ // Handle case where DOMContentLoaded has already fired
149+ if ( document . readyState === 'complete' || document . readyState === 'interactive' ) {
150+ domReady = true ;
151+ tryInitialize ( ) ;
152+ }
153+
154+ // Inject the script
155+ document . body . appendChild ( inkeepScript ) ;
0 commit comments