Skip to content

Commit 18aecb4

Browse files
committed
add inkeep
1 parent d9144fc commit 18aecb4

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

fern/assets/inkeep.js

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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+
url: "mailto:support@vapi.ai",
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);

fern/docs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ css: assets/styles.css
3939
js:
4040
- path: ./assets/close-playground.js
4141
strategy: lazyOnload
42+
- path: ./assets/inkeep.js
43+
strategy: lazyOnload
4244
navbar-links:
4345
- type: minimal
4446
text: Home

0 commit comments

Comments
 (0)