@guidelytech/guide-runtime 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-SGFC66YD.js +322 -0
- package/dist/chunk-SGFC66YD.js.map +1 -0
- package/dist/index.cjs +59 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/messenger.cjs +47 -15
- package/dist/messenger.cjs.map +1 -1
- package/dist/messenger.d.cts +2 -0
- package/dist/messenger.d.ts +2 -0
- package/dist/messenger.js +2 -1
- package/dist/messenger.js.map +1 -1
- package/package.json +2 -2
package/dist/messenger.cjs
CHANGED
|
@@ -25,9 +25,13 @@ __export(messenger_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(messenger_exports);
|
|
27
27
|
|
|
28
|
+
// src/help-view.ts
|
|
29
|
+
var import_runtime2 = require("@guidelytech/shared/runtime");
|
|
30
|
+
|
|
28
31
|
// src/sanitize.ts
|
|
32
|
+
var import_runtime = require("@guidelytech/shared/runtime");
|
|
29
33
|
var ALLOWED_TAGS = /* @__PURE__ */ new Set(["p", "br", "strong", "b", "em", "i", "u", "a", "ul", "ol", "li", "img", "h1", "h2", "h3", "h4", "code", "pre", "blockquote", "span", "div", "hr", "button"]);
|
|
30
|
-
var DROP_TAGS = /* @__PURE__ */ new Set(["script", "style", "
|
|
34
|
+
var DROP_TAGS = /* @__PURE__ */ new Set(["script", "style", "object", "embed", "form", "input", "textarea", "select", "link", "meta", "base", "template", "svg", "math", "frame", "frameset", "noscript"]);
|
|
31
35
|
var ALLOWED_ATTRS = /* @__PURE__ */ new Set(["href", "src", "alt", "title", "target", "rel", "class", "data-g-action", "data-g-value"]);
|
|
32
36
|
function isSafeUrl(value, attr, tag) {
|
|
33
37
|
const v = value.trim().replace(/[\u0000-\u001f\s]/g, "").toLowerCase();
|
|
@@ -59,6 +63,27 @@ function sanitizeElement(el2) {
|
|
|
59
63
|
if (!el2.getAttribute("alt")) el2.setAttribute("alt", "");
|
|
60
64
|
}
|
|
61
65
|
}
|
|
66
|
+
function rebuildMedia(el2) {
|
|
67
|
+
const doc = el2.ownerDocument;
|
|
68
|
+
const tag = el2.tagName.toLowerCase();
|
|
69
|
+
const src = el2.getAttribute("src");
|
|
70
|
+
let out;
|
|
71
|
+
if (tag === "iframe") {
|
|
72
|
+
if (!(0, import_runtime.isAllowedEmbedSrc)(src)) return null;
|
|
73
|
+
out = doc.createElement("iframe");
|
|
74
|
+
out.setAttribute("src", src);
|
|
75
|
+
out.setAttribute("title", el2.getAttribute("title") || "Embedded video");
|
|
76
|
+
for (const [k, v] of Object.entries(import_runtime.EMBED_IFRAME_ATTRS)) out.setAttribute(k, v);
|
|
77
|
+
} else {
|
|
78
|
+
if (!(0, import_runtime.isSafeMediaUrl)(src)) return null;
|
|
79
|
+
out = doc.createElement("video");
|
|
80
|
+
out.setAttribute("src", src);
|
|
81
|
+
const poster = el2.getAttribute("poster");
|
|
82
|
+
if ((0, import_runtime.isSafeMediaUrl)(poster)) out.setAttribute("poster", poster);
|
|
83
|
+
for (const [k, v] of Object.entries(import_runtime.VIDEO_ATTRS)) out.setAttribute(k, v);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
62
87
|
function walk(node) {
|
|
63
88
|
const children = Array.from(node.childNodes);
|
|
64
89
|
for (const child of children) {
|
|
@@ -73,6 +98,12 @@ function walk(node) {
|
|
|
73
98
|
node.removeChild(el2);
|
|
74
99
|
continue;
|
|
75
100
|
}
|
|
101
|
+
if (tag === "iframe" || tag === "video") {
|
|
102
|
+
const media = rebuildMedia(el2);
|
|
103
|
+
if (media) node.replaceChild(media, el2);
|
|
104
|
+
else node.removeChild(el2);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
76
107
|
if (!ALLOWED_TAGS.has(tag)) {
|
|
77
108
|
while (el2.firstChild) node.insertBefore(el2.firstChild, el2);
|
|
78
109
|
node.removeChild(el2);
|
|
@@ -172,7 +203,11 @@ function createHelpView(options) {
|
|
|
172
203
|
body.appendChild(wrap);
|
|
173
204
|
back.focus?.({ preventScroll: true });
|
|
174
205
|
};
|
|
175
|
-
const section = (label
|
|
206
|
+
const section = (label, depth = 0) => {
|
|
207
|
+
const s = body.appendChild(el(doc, "div", "g-rc-section", label));
|
|
208
|
+
if (depth) s.dataset.depth = String(depth);
|
|
209
|
+
return s;
|
|
210
|
+
};
|
|
176
211
|
const articleButton = (a) => {
|
|
177
212
|
const b = listItem(doc, "\u{1F4C4}", a.title, a.summary);
|
|
178
213
|
b.addEventListener("click", () => openArticle(a));
|
|
@@ -182,11 +217,15 @@ function createHelpView(options) {
|
|
|
182
217
|
body.textContent = "";
|
|
183
218
|
if (active) return renderArticle(active);
|
|
184
219
|
const data = options.data();
|
|
220
|
+
const member = options.audienceIds?.() ?? [];
|
|
221
|
+
const sections = (0, import_runtime2.resourceCenterSections)(data.collections, data.articles, member);
|
|
185
222
|
const q = query.trim().toLowerCase();
|
|
186
223
|
if (q) {
|
|
187
|
-
const
|
|
224
|
+
const visible = sections.flatMap((s) => s.articles);
|
|
225
|
+
const local = visible.filter((a) => a.title.toLowerCase().includes(q) || a.summary.toLowerCase().includes(q));
|
|
188
226
|
const seen = new Set(local.map((a) => a.id));
|
|
189
|
-
const
|
|
227
|
+
const hidden = new Set(data.articles.map((a) => a.id).filter((id) => !visible.some((v) => v.id === id)));
|
|
228
|
+
const merged = [...local, ...serverResults.filter((a) => !seen.has(a.id) && !hidden.has(a.id) && (0, import_runtime2.isArticleListed)(data.collections, a, member))];
|
|
190
229
|
section(`Results (${merged.length})`);
|
|
191
230
|
if (!merged.length) body.appendChild(el(doc, "div", "g-rc-empty", "No articles match your search."));
|
|
192
231
|
merged.forEach(articleButton);
|
|
@@ -208,17 +247,9 @@ function createHelpView(options) {
|
|
|
208
247
|
body.appendChild(b);
|
|
209
248
|
});
|
|
210
249
|
}
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const articles = data.articles.filter((a) => a.collectionId === c.id);
|
|
215
|
-
if (!articles.length) return;
|
|
216
|
-
section(c.name);
|
|
217
|
-
articles.forEach(articleButton);
|
|
218
|
-
});
|
|
219
|
-
if (uncollected.length) {
|
|
220
|
-
section("Articles");
|
|
221
|
-
uncollected.forEach(articleButton);
|
|
250
|
+
for (const s of sections) {
|
|
251
|
+
section(s.collection ? s.path.join(" \u203A ") : "Articles", s.depth);
|
|
252
|
+
s.articles.forEach(articleButton);
|
|
222
253
|
}
|
|
223
254
|
if (data.faqs?.length) {
|
|
224
255
|
section("FAQ");
|
|
@@ -532,6 +563,7 @@ function renderMessenger(options) {
|
|
|
532
563
|
links: options.resourceCenter?.links
|
|
533
564
|
}),
|
|
534
565
|
search: (q) => api.searchArticles(q),
|
|
566
|
+
audienceIds: options.audienceIds,
|
|
535
567
|
loadArticle: (id) => api.getArticle(id),
|
|
536
568
|
onStartGuide: (id) => {
|
|
537
569
|
setOpen(false);
|
package/dist/messenger.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/messenger.ts","../src/sanitize.ts","../src/help-view.ts","../src/messenger-styles.ts","../src/render-safe.ts"],"sourcesContent":["import type {\n ConversationMessagesResponse,\n MessengerConfig,\n MessengerConversation,\n MessengerMessage,\n ResourceCenterArticle,\n ResourceCenterConfig,\n SdkArticlesResponse,\n} from \"@guidelytech/shared\";\nimport { createHelpView, el, type HelpData, type HelpGuideRef } from \"./help-view\";\nimport { MESSENGER_STYLES } from \"./messenger-styles\";\nimport { renderSafeText } from \"./render-safe\";\n\n/** Callbacks the transport invokes while a message is sent and Scout replies. */\nexport interface MessengerStreamHandlers {\n /** A new conversation was created (first message only). */\n onConversation?(conversation: MessengerConversation): void;\n onMessage(message: MessengerMessage): void;\n onDelta(messageId: string, text: string): void;\n onDone(message: MessengerMessage | null, conversation: MessengerConversation): void;\n onError(message: string): void;\n}\n\n/** Server access for the messenger; implemented by sdk-core over the public SDK API. */\nexport interface MessengerApi {\n listConversations(): Promise<MessengerConversation[]>;\n loadMessages(conversationId: string, since?: string | null): Promise<ConversationMessagesResponse>;\n start(text: string, handlers: MessengerStreamHandlers): Promise<void>;\n send(conversationId: string, text: string, handlers: MessengerStreamHandlers): Promise<void>;\n handoff(conversationId: string): Promise<ConversationMessagesResponse>;\n rate(conversationId: string, rating: number): Promise<void>;\n listArticles(): Promise<SdkArticlesResponse>;\n getArticle(id: string): Promise<ResourceCenterArticle | null>;\n searchArticles(q: string): Promise<ResourceCenterArticle[]>;\n}\n\nexport type MessengerTab = \"home\" | \"messages\" | \"help\";\n\nexport interface MessengerOptions {\n scope: HTMLElement;\n config: MessengerConfig;\n api: MessengerApi;\n /** Resource center extras (recommended guides, checklists, FAQs, links) shown in the Help tab. */\n resourceCenter?: ResourceCenterConfig | null;\n guides?: HelpGuideRef[];\n onStartGuide?: (guideKeyOrId: string) => void;\n onOpenChecklist?: (guideId: string) => void;\n onArticleView?: (article: ResourceCenterArticle) => void;\n onOpen?: () => void;\n onClose?: () => void;\n onMessage?: (message: MessengerMessage, conversation: MessengerConversation) => void;\n hideLauncher?: boolean;\n /** Poll intervals (ms): open thread, and unread badge while closed. */\n pollMs?: { thread: number; background: number };\n}\n\nexport interface MessengerWidget {\n el: HTMLElement;\n open(tab?: MessengerTab): void;\n close(): void;\n toggle(): void;\n isOpen(): boolean;\n /** Opens a new conversation, optionally pre-filling the composer. */\n showNewMessage(text?: string): void;\n openArticle(id: string): void;\n destroy(): void;\n}\n\ntype View = { kind: \"tab\"; tab: MessengerTab } | { kind: \"thread\"; conversationId: string | null };\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\nfunction chatIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS(SVG_NS, \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = doc.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", \"M12 3C6.5 3 2 6.8 2 11.5c0 2.4 1.2 4.6 3.1 6.1L4.5 21l3.9-2c1.1.3 2.3.5 3.6.5 5.5 0 10-3.8 10-8.5S17.5 3 12 3z\");\n svg.appendChild(path);\n return svg;\n}\n\nexport function relativeTime(iso: string, now = Date.now()): string {\n const s = Math.max(0, Math.round((now - Date.parse(iso)) / 1000));\n if (!Number.isFinite(s) || s < 60) return \"now\";\n if (s < 3600) return `${Math.floor(s / 60)}m`;\n if (s < 86400) return `${Math.floor(s / 3600)}h`;\n return `${Math.floor(s / 86400)}d`;\n}\n\nfunction ensureStyles(scope: HTMLElement) {\n const root = scope.getRootNode() as ShadowRoot | Document;\n const container = \"host\" in root ? root : scope.ownerDocument.head;\n if (container.querySelector?.(\"style[data-g-messenger]\")) return;\n const style = scope.ownerDocument.createElement(\"style\");\n style.setAttribute(\"data-g-messenger\", \"\");\n style.textContent = MESSENGER_STYLES;\n container.appendChild(style);\n}\n\n/** Intercom-style messenger: launcher + panel with Home, Messages (chat with Scout / the team) and Help tabs. */\nexport function renderMessenger(options: MessengerOptions): MessengerWidget {\n const { scope, config, api } = options;\n const doc = scope.ownerDocument;\n const poll = options.pollMs ?? { thread: 5000, background: 60000 };\n ensureStyles(scope);\n\n let open = false;\n let destroyed = false;\n let view: View = { kind: \"tab\", tab: \"home\" };\n let conversations: MessengerConversation[] = [];\n let messages: MessengerMessage[] = [];\n let current: MessengerConversation | null = null;\n const streaming = new Map<string, string>();\n let sending = false;\n let draft = \"\";\n let articles: SdkArticlesResponse | null = null;\n let articlesLoading = false;\n let threadTimer: ReturnType<typeof setTimeout> | null = null;\n let backgroundTimer: ReturnType<typeof setInterval> | null = null;\n let threadSeq = 0;\n\n const pos = `g-pos-${config.launcher.position}`;\n // Other launchers (checklists, resource center) in the same corner move aside for the chat bubble.\n const rootNode = scope.getRootNode();\n const shadowHost = \"host\" in rootNode ? (rootNode.host as HTMLElement) : null;\n shadowHost?.setAttribute(\"data-g-messenger\", config.launcher.position);\n const root = el(doc, \"div\", \"g-messenger-root\");\n const launcher = el(doc, \"button\", `g-m-launcher ${pos}`);\n launcher.type = \"button\";\n launcher.setAttribute(\"aria-label\", `Open ${config.name}`);\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.appendChild(chatIcon(doc));\n const badge = el(doc, \"span\", \"g-m-badge\");\n badge.hidden = true;\n launcher.appendChild(badge);\n if (options.hideLauncher) launcher.hidden = true;\n\n const panel = el(doc, \"div\", `g-panel g-messenger ${pos}`);\n panel.setAttribute(\"role\", \"dialog\");\n panel.setAttribute(\"aria-label\", config.name);\n panel.hidden = true;\n const head = el(doc, \"div\", \"g-m-head\");\n const main = el(doc, \"div\", \"g-m-main\");\n const tabs = el(doc, \"div\", \"g-m-tabs\");\n tabs.setAttribute(\"role\", \"tablist\");\n panel.append(head, main, tabs);\n root.append(launcher, panel);\n scope.appendChild(root);\n\n const rcExtras = (ids: string[] = []) => ids.map((id) => options.guides?.find((g) => g.id === id || g.key === id)).filter((g): g is HelpGuideRef => !!g);\n const help = createHelpView({\n doc,\n data: (): HelpData => ({\n collections: articles?.collections ?? options.resourceCenter?.collections ?? [],\n articles: articles?.articles ?? options.resourceCenter?.articles ?? [],\n recommended: rcExtras(options.resourceCenter?.recommendedGuideIds),\n checklists: rcExtras(options.resourceCenter?.checklistGuideIds),\n faqs: options.resourceCenter?.faqs,\n links: options.resourceCenter?.links,\n }),\n search: (q) => api.searchArticles(q),\n loadArticle: (id) => api.getArticle(id),\n onStartGuide: (id) => {\n setOpen(false);\n options.onStartGuide?.(id);\n },\n onOpenChecklist: (id) => {\n setOpen(false);\n options.onOpenChecklist?.(id);\n },\n onArticleView: options.onArticleView,\n });\n\n const unreadTotal = () => conversations.reduce((n, c) => n + (c.unread > 0 ? 1 : 0), 0);\n const updateBadge = () => {\n const n = unreadTotal();\n badge.hidden = n === 0 || open;\n badge.textContent = n > 9 ? \"9+\" : String(n);\n launcher.setAttribute(\"aria-label\", n ? `Open ${config.name}, ${n} unread` : `Open ${config.name}`);\n };\n\n const upsertConversation = (c: MessengerConversation) => {\n conversations = [c, ...conversations.filter((x) => x.id !== c.id)].sort((a, b) => b.lastMessageAt.localeCompare(a.lastMessageAt));\n if (current?.id === c.id) current = c;\n updateBadge();\n };\n const upsertMessage = (m: MessengerMessage) => {\n const i = messages.findIndex((x) => x.id === m.id);\n if (i >= 0) messages[i] = m;\n else messages.push(m);\n messages.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n if (m.status !== \"pending\") streaming.delete(m.id);\n };\n\n const loadArticles = () => {\n if (articles || articlesLoading) return;\n articlesLoading = true;\n api\n .listArticles()\n .then((res) => {\n articles = res;\n if (view.kind === \"tab\" && view.tab === \"help\") help.render();\n })\n .catch(() => {})\n .finally(() => (articlesLoading = false));\n };\n\n const refreshConversations = () =>\n api\n .listConversations()\n .then((list) => {\n conversations = [...list].sort((a, b) => b.lastMessageAt.localeCompare(a.lastMessageAt));\n updateBadge();\n if (open && view.kind === \"tab\" && view.tab !== \"help\") render();\n })\n .catch(() => {});\n\n // ---------------------------------------------------------------------------\n // Rendering\n // ---------------------------------------------------------------------------\n\n function renderHead(title: string, back?: () => void) {\n head.textContent = \"\";\n if (back) {\n const b = el(doc, \"button\", \"g-m-back\", \"←\");\n b.type = \"button\";\n b.setAttribute(\"aria-label\", \"Back\");\n b.addEventListener(\"click\", back);\n head.appendChild(b);\n }\n head.appendChild(el(doc, \"h2\", \"\", title));\n const close = el(doc, \"button\", \"g-close\", \"×\");\n close.type = \"button\";\n close.setAttribute(\"aria-label\", \"Close\");\n close.addEventListener(\"click\", () => setOpen(false));\n head.appendChild(close);\n }\n\n function renderTabs() {\n tabs.textContent = \"\";\n tabs.hidden = view.kind === \"thread\";\n const items: Array<[MessengerTab, string, string]> = [\n [\"home\", \"⌂\", \"Home\"],\n [\"messages\", \"💬\", \"Messages\"],\n [\"help\", \"?\", \"Help\"],\n ];\n for (const [tab, icon, label] of items) {\n const b = el(doc, \"button\", \"g-m-tab\");\n b.type = \"button\";\n b.setAttribute(\"role\", \"tab\");\n b.setAttribute(\"aria-selected\", String(view.kind === \"tab\" && view.tab === tab));\n const i = el(doc, \"span\", \"g-m-tab-icon\", icon);\n i.setAttribute(\"aria-hidden\", \"true\");\n b.append(i, el(doc, \"span\", \"\", label));\n b.addEventListener(\"click\", () => go({ kind: \"tab\", tab }));\n tabs.appendChild(b);\n }\n }\n\n function conversationCard(c: MessengerConversation): HTMLButtonElement {\n const card = el(doc, \"button\", \"g-m-card\");\n card.type = \"button\";\n const row = el(doc, \"div\", \"g-m-row\");\n if (c.unread > 0) row.appendChild(el(doc, \"span\", \"g-m-dot\"));\n const text = el(doc, \"div\", \"g-m-grow\");\n text.append(el(doc, \"div\", \"g-m-card-title g-m-ellipsis\", c.subject || \"Conversation\"), el(doc, \"div\", \"g-m-card-sub g-m-ellipsis\", c.lastMessagePreview));\n row.append(text, el(doc, \"span\", \"g-m-time\", relativeTime(c.lastMessageAt)));\n card.appendChild(row);\n card.setAttribute(\"aria-label\", `${c.subject || \"Conversation\"}${c.unread ? \", unread\" : \"\"}`);\n card.addEventListener(\"click\", () => go({ kind: \"thread\", conversationId: c.id }));\n return card;\n }\n\n function renderHome() {\n renderHead(config.name);\n const scroll = el(doc, \"div\", \"g-m-scroll\");\n scroll.append(el(doc, \"div\", \"g-m-hero\", \"Hi there 👋\"), el(doc, \"p\", \"g-m-greet\", config.greeting));\n const ask = el(doc, \"button\", \"g-m-card\");\n ask.type = \"button\";\n ask.append(el(doc, \"div\", \"g-m-card-title\", \"Ask a question\"), el(doc, \"div\", \"g-m-card-sub\", config.aiAvailable ? `${config.name} answers right away, and the team can help too` : \"The team will reply here\"));\n ask.addEventListener(\"click\", () => go({ kind: \"thread\", conversationId: null }));\n scroll.appendChild(ask);\n const recent = conversations[0];\n if (recent) {\n scroll.appendChild(el(doc, \"div\", \"g-rc-section\", \"Recent conversation\"));\n scroll.appendChild(conversationCard(recent));\n }\n const search = el(doc, \"button\", \"g-m-card\");\n search.type = \"button\";\n search.append(el(doc, \"div\", \"g-m-card-title\", \"Search for help\"), el(doc, \"div\", \"g-m-card-sub\", \"Browse articles and guides\"));\n search.addEventListener(\"click\", () => go({ kind: \"tab\", tab: \"help\" }));\n scroll.appendChild(search);\n main.appendChild(scroll);\n }\n\n function renderMessagesTab() {\n renderHead(\"Messages\");\n const scroll = el(doc, \"div\", \"g-m-scroll\");\n if (!conversations.length) scroll.appendChild(el(doc, \"div\", \"g-m-empty\", \"No conversations yet.\"));\n conversations.forEach((c) => scroll.appendChild(conversationCard(c)));\n const start = el(doc, \"button\", \"g-btn g-btn-primary\", \"Send us a message\");\n start.type = \"button\";\n start.style.width = \"100%\";\n start.addEventListener(\"click\", () => go({ kind: \"thread\", conversationId: null }));\n scroll.appendChild(start);\n main.appendChild(scroll);\n }\n\n function renderHelpTab() {\n renderHead(\"Help\");\n loadArticles();\n help.render();\n main.appendChild(help.el);\n }\n\n let log: HTMLElement | null = null;\n let foot: HTMLElement | null = null;\n let textarea: HTMLTextAreaElement | null = null;\n let sendButton: HTMLButtonElement | null = null;\n\n function messageNode(m: MessengerMessage): HTMLElement {\n const wrap = el(doc, \"div\", `g-m-msg g-from-${m.author}${m.status === \"failed\" ? \" g-m-failed\" : \"\"}`);\n if (m.author === \"system\") {\n wrap.textContent = m.body;\n return wrap;\n }\n if (m.author !== \"user\") {\n const author = el(doc, \"div\", \"g-m-author\", m.author === \"scout\" ? config.name : m.authorName || \"Support team\");\n if (m.author === \"scout\") author.appendChild(el(doc, \"span\", \"g-m-ai\", \"AI\"));\n wrap.appendChild(author);\n }\n const bubble = el(doc, \"div\", \"g-m-bubble\");\n const live = streaming.get(m.id);\n if (m.status === \"pending\" && !live) {\n const dots = el(doc, \"span\", \"g-m-typing\");\n dots.setAttribute(\"aria-label\", `${config.name} is typing`);\n dots.append(el(doc, \"span\"), el(doc, \"span\"), el(doc, \"span\"));\n bubble.appendChild(dots);\n } else if (m.status === \"failed\") {\n bubble.textContent = \"This reply couldn't be completed.\";\n } else {\n bubble.appendChild(renderSafeText(doc, live ?? m.body));\n }\n if (m.status === \"pending\") bubble.setAttribute(\"aria-busy\", \"true\");\n bubble.dataset.messageId = m.id;\n wrap.appendChild(bubble);\n if (m.citations.length || m.suggestedGuides.length) {\n const chips = el(doc, \"div\", \"g-m-chips\");\n for (const g of m.suggestedGuides) {\n const b = el(doc, \"button\", \"g-m-chip g-m-guide\", `▶ Show me: ${g.name}`);\n b.type = \"button\";\n b.addEventListener(\"click\", () => {\n setOpen(false);\n options.onStartGuide?.(g.key);\n });\n chips.appendChild(b);\n }\n for (const c of m.citations) {\n const b = el(doc, \"button\", \"g-m-chip\", `📄 ${c.title}`);\n b.type = \"button\";\n b.addEventListener(\"click\", () => openArticle(c.articleId));\n chips.appendChild(b);\n }\n wrap.appendChild(chips);\n }\n return wrap;\n }\n\n function renderLog() {\n if (!log) return;\n const atBottom = log.scrollHeight - log.scrollTop - log.clientHeight < 40;\n log.textContent = \"\";\n if (!messages.length) {\n const intro: MessengerMessage = { id: \"intro\", author: config.aiAvailable ? \"scout\" : \"agent\", authorName: \"Support team\", body: config.greeting, citations: [], suggestedGuides: [], status: \"complete\", createdAt: new Date().toISOString() };\n log.appendChild(messageNode(intro));\n }\n messages.forEach((m) => log!.appendChild(messageNode(m)));\n if (atBottom || sending) log.scrollTop = log.scrollHeight;\n renderFoot();\n }\n\n function renderFoot() {\n if (!foot || !textarea || !sendButton) return;\n sendButton.disabled = sending || !textarea.value.trim();\n textarea.disabled = sending;\n for (const extra of Array.from(foot.querySelectorAll(\".g-m-human,.g-m-rate,.g-m-note\"))) extra.remove();\n if (current?.status === \"closed\" && current.rating == null) {\n const rate = el(doc, \"div\", \"g-m-rate\", \"How was this conversation? \");\n for (const [score, face, label] of [\n [1, \"😞\", \"Bad\"],\n [3, \"😐\", \"OK\"],\n [5, \"😀\", \"Great\"],\n ] as const) {\n const b = el(doc, \"button\", \"\", face);\n b.type = \"button\";\n b.setAttribute(\"aria-label\", label);\n b.addEventListener(\"click\", () => {\n if (!current) return;\n const id = current.id;\n current = { ...current, rating: score };\n upsertConversation(current);\n renderFoot();\n api.rate(id, score).catch(() => {});\n });\n rate.appendChild(b);\n }\n foot.prepend(rate);\n } else if (current && current.rating != null && current.status === \"closed\") {\n foot.prepend(el(doc, \"div\", \"g-m-note\", \"Thanks for the feedback!\"));\n }\n if (config.handoffEnabled && config.aiAvailable && current?.status === \"bot\" && !sending) {\n const human = el(doc, \"button\", \"g-m-human\", \"Talk to a person\");\n human.type = \"button\";\n human.addEventListener(\"click\", () => {\n if (!current) return;\n const id = current.id;\n human.disabled = true;\n api\n .handoff(id)\n .then((res) => {\n if (current?.id !== id) return;\n upsertConversation(res.conversation);\n res.messages.forEach(upsertMessage);\n renderLog();\n })\n .catch(() => (human.disabled = false));\n });\n foot.appendChild(human);\n }\n }\n\n function renderThread(conversationId: string | null) {\n renderHead(current?.subject || (conversationId ? \"Conversation\" : \"New conversation\"), () => go({ kind: \"tab\", tab: \"messages\" }));\n log = el(doc, \"div\", \"g-m-log\");\n log.setAttribute(\"role\", \"log\");\n log.setAttribute(\"aria-live\", \"polite\");\n foot = el(doc, \"div\", \"g-m-foot\");\n const compose = el(doc, \"form\", \"g-m-compose\");\n textarea = el(doc, \"textarea\");\n textarea.rows = 1;\n textarea.maxLength = 4000;\n textarea.placeholder = current?.status === \"open\" ? \"Reply to the team…\" : \"Ask a question…\";\n textarea.setAttribute(\"aria-label\", \"Message\");\n textarea.value = draft;\n sendButton = el(doc, \"button\", \"g-m-send\", \"↑\");\n sendButton.type = \"submit\";\n sendButton.setAttribute(\"aria-label\", \"Send\");\n compose.append(textarea, sendButton);\n foot.appendChild(compose);\n textarea.addEventListener(\"input\", () => {\n draft = textarea!.value;\n if (sendButton) sendButton.disabled = sending || !draft.trim();\n });\n textarea.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey && !e.isComposing) {\n e.preventDefault();\n submit();\n }\n });\n compose.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n submit();\n });\n main.append(log, foot);\n renderLog();\n textarea.focus?.({ preventScroll: true });\n }\n\n function render() {\n if (destroyed) return;\n main.textContent = \"\";\n log = foot = null;\n textarea = null;\n sendButton = null;\n if (view.kind === \"thread\") renderThread(view.conversationId);\n else if (view.tab === \"home\") renderHome();\n else if (view.tab === \"messages\") renderMessagesTab();\n else renderHelpTab();\n renderTabs();\n }\n\n // ---------------------------------------------------------------------------\n // Behaviour\n // ---------------------------------------------------------------------------\n\n const handlers = (seq: number): MessengerStreamHandlers => ({\n onConversation(c) {\n if (seq !== threadSeq) return;\n current = c;\n view = { kind: \"thread\", conversationId: c.id };\n upsertConversation(c);\n },\n onMessage(m) {\n if (seq !== threadSeq) return;\n upsertMessage(m);\n renderLog();\n },\n onDelta(id, text) {\n if (seq !== threadSeq) return;\n streaming.set(id, (streaming.get(id) ?? \"\") + text);\n const bubble = log?.querySelector<HTMLElement>(`[data-message-id=\"${id}\"]`);\n if (!bubble) return renderLog();\n bubble.textContent = \"\";\n bubble.appendChild(renderSafeText(doc, streaming.get(id)!));\n if (log) log.scrollTop = log.scrollHeight;\n },\n onDone(m, c) {\n if (seq !== threadSeq) return;\n if (m) {\n upsertMessage(m);\n options.onMessage?.(m, c);\n }\n upsertConversation({ ...c, unread: 0 });\n current = { ...c, unread: 0 };\n },\n onError() {\n /* the server also stores a system message explaining what happened */\n },\n });\n\n function submit() {\n if (!textarea || sending) return;\n const text = textarea.value.trim();\n if (!text) return;\n sending = true;\n draft = \"\";\n textarea.value = \"\";\n renderFoot();\n const seq = threadSeq;\n const h = handlers(seq);\n const done = current ? api.send(current.id, text, h) : api.start(text, h);\n done\n .catch(() => {\n if (seq !== threadSeq) return;\n draft = text;\n if (textarea) textarea.value = text;\n const note: MessengerMessage = { id: `local_${Date.now()}`, author: \"system\", body: \"Your message couldn't be sent. Please try again.\", citations: [], suggestedGuides: [], status: \"complete\", createdAt: new Date().toISOString() };\n upsertMessage(note);\n })\n .finally(() => {\n if (seq !== threadSeq) return;\n sending = false;\n streaming.clear();\n if (view.kind === \"thread\") {\n if (current) renderHead(current.subject || \"Conversation\", () => go({ kind: \"tab\", tab: \"messages\" }));\n renderLog();\n }\n scheduleThreadPoll();\n });\n }\n\n function scheduleThreadPoll() {\n if (threadTimer) clearTimeout(threadTimer);\n threadTimer = null;\n if (!open || view.kind !== \"thread\" || !current || destroyed) return;\n threadTimer = setTimeout(pollThread, poll.thread);\n }\n\n function pollThread() {\n if (!current || sending) return scheduleThreadPoll();\n const seq = threadSeq;\n const pending = messages.find((m) => m.status === \"pending\");\n const last = messages.filter((m) => !m.id.startsWith(\"local_\")).at(-1);\n // Re-fetch from a pending reply (its body changes in place); otherwise only newer messages.\n const since = pending ? new Date(Date.parse(pending.createdAt) - 1).toISOString() : (last?.createdAt ?? null);\n api\n .loadMessages(current.id, since)\n .then((res) => {\n if (seq !== threadSeq) return;\n const before = messages.length;\n const changed = res.messages.some((m) => {\n const prev = messages.find((x) => x.id === m.id);\n return !prev || prev.status !== m.status || prev.body !== m.body;\n });\n res.messages.forEach(upsertMessage);\n upsertConversation({ ...res.conversation, unread: 0 });\n current = { ...res.conversation, unread: 0 };\n if (changed || messages.length !== before) {\n renderLog();\n res.messages.filter((m) => m.author !== \"user\").forEach((m) => options.onMessage?.(m, res.conversation));\n } else renderFoot();\n })\n .catch(() => {})\n .finally(scheduleThreadPoll);\n }\n\n function go(next: View) {\n threadSeq++;\n if (threadTimer) clearTimeout(threadTimer);\n threadTimer = null;\n if (view.kind === \"tab\" && view.tab === \"help\" && !(next.kind === \"tab\" && next.tab === \"help\")) help.reset();\n view = next;\n if (next.kind === \"thread\") {\n messages = [];\n streaming.clear();\n sending = false;\n current = next.conversationId ? (conversations.find((c) => c.id === next.conversationId) ?? null) : null;\n render();\n if (next.conversationId) {\n const seq = threadSeq;\n api\n .loadMessages(next.conversationId)\n .then((res) => {\n if (seq !== threadSeq) return;\n res.messages.forEach(upsertMessage);\n current = { ...res.conversation, unread: 0 };\n upsertConversation(current);\n renderHead(current.subject || \"Conversation\", () => go({ kind: \"tab\", tab: \"messages\" }));\n renderLog();\n })\n .catch(() => {})\n .finally(scheduleThreadPoll);\n }\n } else {\n draft = \"\";\n render();\n }\n }\n\n function openArticle(id: string) {\n go({ kind: \"tab\", tab: \"help\" });\n help.openArticle(id);\n }\n\n function startBackgroundPoll() {\n if (backgroundTimer) clearInterval(backgroundTimer);\n backgroundTimer = setInterval(() => {\n if (!open && conversations.length && !destroyed) void refreshConversations();\n }, poll.background);\n }\n\n const setOpen = (v: boolean) => {\n if (open === v || destroyed) return;\n open = v;\n panel.hidden = !v;\n launcher.setAttribute(\"aria-expanded\", String(v));\n launcher.setAttribute(\"aria-label\", v ? `Close ${config.name}` : `Open ${config.name}`);\n updateBadge();\n if (v) {\n render();\n void refreshConversations();\n if (view.kind === \"thread\") scheduleThreadPoll();\n options.onOpen?.();\n } else {\n if (threadTimer) clearTimeout(threadTimer);\n threadTimer = null;\n options.onClose?.();\n }\n };\n launcher.addEventListener(\"click\", () => setOpen(!open));\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n setOpen(false);\n launcher.focus();\n }\n };\n panel.addEventListener(\"keydown\", onKey);\n\n void refreshConversations();\n startBackgroundPoll();\n\n return {\n el: root,\n open(tab?: MessengerTab) {\n if (tab) view = { kind: \"tab\", tab };\n if (open && tab) render();\n setOpen(true);\n },\n close: () => setOpen(false),\n toggle: () => setOpen(!open),\n isOpen: () => open,\n showNewMessage(text?: string) {\n setOpen(true);\n go({ kind: \"thread\", conversationId: null });\n if (text && textarea) {\n textarea.value = text.slice(0, 4000);\n draft = textarea.value;\n renderFoot();\n }\n },\n openArticle(id: string) {\n setOpen(true);\n openArticle(id);\n },\n destroy() {\n destroyed = true;\n if (threadTimer) clearTimeout(threadTimer);\n if (backgroundTimer) clearInterval(backgroundTimer);\n panel.removeEventListener(\"keydown\", onKey);\n help.destroy();\n shadowHost?.removeAttribute(\"data-g-messenger\");\n root.remove();\n },\n };\n}\n","const ALLOWED_TAGS = new Set([\"p\", \"br\", \"strong\", \"b\", \"em\", \"i\", \"u\", \"a\", \"ul\", \"ol\", \"li\", \"img\", \"h1\", \"h2\", \"h3\", \"h4\", \"code\", \"pre\", \"blockquote\", \"span\", \"div\", \"hr\", \"button\"]);\nconst DROP_TAGS = new Set([\"script\", \"style\", \"iframe\", \"object\", \"embed\", \"form\", \"input\", \"textarea\", \"select\", \"link\", \"meta\", \"base\", \"template\", \"svg\", \"math\", \"frame\", \"frameset\", \"noscript\"]);\nconst ALLOWED_ATTRS = new Set([\"href\", \"src\", \"alt\", \"title\", \"target\", \"rel\", \"class\", \"data-g-action\", \"data-g-value\"]);\nfunction isSafeUrl(value: string, attr: string, tag: string): boolean {\n // eslint-disable-next-line no-control-regex\n const v = value.trim().replace(/[\\u0000-\\u001f\\s]/g, \"\").toLowerCase();\n if (!v) return false;\n const m = /^([a-z][a-z0-9+.-]*):/.exec(v);\n if (!m) return true; // relative URL\n const scheme = m[1];\n if (scheme === \"data\") return tag === \"img\" && attr === \"src\" && v.startsWith(\"data:image/\");\n return scheme === \"http\" || scheme === \"https\" || scheme === \"mailto\" || scheme === \"tel\";\n}\n\nfunction sanitizeElement(el: Element): void {\n const tag = el.tagName.toLowerCase();\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase();\n if (name.startsWith(\"on\") || !ALLOWED_ATTRS.has(name)) {\n el.removeAttribute(attr.name);\n continue;\n }\n if ((name === \"href\" || name === \"src\") && !isSafeUrl(attr.value, name, tag)) el.removeAttribute(attr.name);\n }\n if (tag === \"a\") {\n const target = el.getAttribute(\"target\");\n if (target && target !== \"_blank\" && target !== \"_self\") el.removeAttribute(\"target\");\n if (el.getAttribute(\"target\") === \"_blank\") el.setAttribute(\"rel\", \"noopener noreferrer\");\n }\n if (tag === \"button\") el.setAttribute(\"type\", \"button\");\n if (tag === \"img\") {\n el.setAttribute(\"loading\", \"lazy\");\n if (!el.getAttribute(\"alt\")) el.setAttribute(\"alt\", \"\");\n }\n}\n\nfunction walk(node: Node): void {\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType === 8 /* comment */) {\n node.removeChild(child);\n continue;\n }\n if (child.nodeType !== 1) continue;\n const el = child as Element;\n const tag = el.tagName.toLowerCase();\n if (DROP_TAGS.has(tag)) {\n node.removeChild(el);\n continue;\n }\n if (!ALLOWED_TAGS.has(tag)) {\n // Unwrap: keep text/children, drop the element itself.\n while (el.firstChild) node.insertBefore(el.firstChild, el);\n node.removeChild(el);\n // Re-walk the parent since children moved up.\n walk(node);\n return;\n }\n sanitizeElement(el);\n walk(el);\n }\n}\n\n/**\n * Parses HTML into a sanitized DocumentFragment using a strict allowlist. No external\n * dependency: a `<template>` element parses inertly and the tree is walked element by element.\n */\nexport function sanitizeToFragment(html: string, doc: Document = document): DocumentFragment {\n const tpl = doc.createElement(\"template\");\n tpl.innerHTML = html || \"\";\n walk(tpl.content);\n return tpl.content;\n}\n\n/** Returns sanitized HTML as a string. */\nexport function sanitizeHtml(html: string, doc: Document = document): string {\n const frag = sanitizeToFragment(html, doc);\n const div = doc.createElement(\"div\");\n div.appendChild(frag);\n return div.innerHTML;\n}\n\n/** Replaces the content of `el` with the sanitized HTML. */\nexport function setSanitizedHtml(el: Element, html: string): void {\n el.textContent = \"\";\n el.appendChild(sanitizeToFragment(html, el.ownerDocument));\n}\n","import type { ResourceCenterArticle, ResourceCenterConfig } from \"@guidelytech/shared\";\nimport { setSanitizedHtml } from \"./sanitize\";\n\nexport interface HelpGuideRef {\n id: string;\n key: string;\n name: string;\n kind: string;\n}\n\n/** What the help view lists. Article bodies may be missing (`bodyOmitted` or summaries only): they load on open. */\nexport interface HelpData {\n collections: ResourceCenterConfig[\"collections\"];\n articles: Array<Omit<ResourceCenterArticle, \"body\"> & { body?: string }>;\n recommended?: HelpGuideRef[];\n checklists?: HelpGuideRef[];\n faqs?: ResourceCenterConfig[\"faqs\"];\n links?: ResourceCenterConfig[\"links\"];\n}\n\nexport interface HelpViewOptions {\n doc: Document;\n data: () => HelpData;\n /** Server search. Results are merged with the client-side title/summary filter. */\n search?: (q: string) => Promise<ResourceCenterArticle[]>;\n /** Loads an article body that isn't in `data()`. */\n loadArticle?: (id: string) => Promise<ResourceCenterArticle | null>;\n onStartGuide?: (guideId: string) => void;\n onOpenChecklist?: (guideId: string) => void;\n onArticleView?: (article: ResourceCenterArticle) => void;\n}\n\nexport interface HelpView {\n /** Search box + scrollable body. */\n el: HTMLElement;\n render(): void;\n /** Back to the article list and clear the search. */\n reset(): void;\n openArticle(id: string): void;\n focusSearch(): void;\n setQuery(q: string): void;\n destroy(): void;\n}\n\nexport function el<K extends keyof HTMLElementTagNameMap>(doc: Document, tag: K, cls?: string, text?: string): HTMLElementTagNameMap[K] {\n const e = doc.createElement(tag);\n if (cls) e.className = cls;\n if (text != null) e.textContent = text;\n return e;\n}\n\nexport function listItem(doc: Document, icon: string, title: string, summary?: string): HTMLButtonElement {\n const b = el(doc, \"button\", \"g-rc-item\");\n b.type = \"button\";\n const i = el(doc, \"span\", \"g-rc-icon\", icon);\n i.setAttribute(\"aria-hidden\", \"true\");\n const text = el(doc, \"span\");\n text.appendChild(el(doc, \"div\", \"g-rc-title\", title));\n if (summary) text.appendChild(el(doc, \"div\", \"g-rc-sum\", summary));\n b.append(i, text);\n return b;\n}\n\ntype ListedArticle = HelpData[\"articles\"][number];\n\n/** Article browser shared by the resource center and the messenger Help tab. */\nexport function createHelpView(options: HelpViewOptions): HelpView {\n const { doc } = options;\n let query = \"\";\n let serverResults: ResourceCenterArticle[] = [];\n let searchSeq = 0;\n let openSeq = 0;\n let active: { article: ListedArticle; loading: boolean } | null = null;\n\n const root = el(doc, \"div\", \"g-help\");\n const searchWrap = el(doc, \"div\", \"g-rc-search\");\n const input = el(doc, \"input\", \"g-input\");\n input.type = \"search\";\n input.placeholder = \"Search help articles…\";\n input.setAttribute(\"aria-label\", \"Search help articles\");\n searchWrap.appendChild(input);\n const body = el(doc, \"div\", \"g-panel-body\");\n root.append(searchWrap, body);\n\n const hasBody = (a: ListedArticle): a is ResourceCenterArticle => typeof a.body === \"string\" && !a.bodyOmitted;\n\n const openArticle = (article: ListedArticle) => {\n if (article.externalUrl) {\n window.open(article.externalUrl, \"_blank\", \"noopener,noreferrer\");\n if (hasBody(article)) options.onArticleView?.(article);\n return;\n }\n const seq = ++openSeq;\n if (hasBody(article) || !options.loadArticle) {\n active = { article, loading: false };\n if (hasBody(article)) options.onArticleView?.(article);\n return render();\n }\n active = { article, loading: true };\n render();\n options\n .loadArticle(article.id)\n .then((full) => {\n if (seq !== openSeq || !active) return;\n active = { article: full ?? { ...article, body: \"\" }, loading: false };\n if (full) options.onArticleView?.(full);\n render();\n })\n .catch(() => {\n if (seq !== openSeq || !active) return;\n active = { article: { ...article, body: \"\" }, loading: false };\n render();\n });\n };\n\n const renderArticle = ({ article, loading }: NonNullable<typeof active>) => {\n const wrap = el(doc, \"div\", \"g-rc-article\");\n const back = el(doc, \"button\", \"g-btn g-btn-link g-rc-back\", \"← Back\");\n back.type = \"button\";\n back.addEventListener(\"click\", () => {\n openSeq++;\n active = null;\n render();\n });\n const title = el(doc, \"h3\", \"g-title\", article.title);\n const content = el(doc, \"div\", \"g-body\");\n if (loading) content.appendChild(el(doc, \"div\", \"g-rc-empty\", \"Loading…\"));\n else if (article.body) setSanitizedHtml(content, article.body);\n else content.appendChild(el(doc, \"div\", \"g-rc-empty\", \"This article couldn't be loaded.\"));\n wrap.append(back, title, content);\n body.appendChild(wrap);\n back.focus?.({ preventScroll: true });\n };\n\n const section = (label: string) => body.appendChild(el(doc, \"div\", \"g-rc-section\", label));\n const articleButton = (a: ListedArticle) => {\n const b = listItem(doc, \"📄\", a.title, a.summary);\n b.addEventListener(\"click\", () => openArticle(a));\n body.appendChild(b);\n };\n\n function render() {\n body.textContent = \"\";\n if (active) return renderArticle(active);\n const data = options.data();\n const q = query.trim().toLowerCase();\n if (q) {\n const local = data.articles.filter((a) => a.title.toLowerCase().includes(q) || a.summary.toLowerCase().includes(q));\n const seen = new Set(local.map((a) => a.id));\n const merged: ListedArticle[] = [...local, ...serverResults.filter((a) => !seen.has(a.id))];\n section(`Results (${merged.length})`);\n if (!merged.length) body.appendChild(el(doc, \"div\", \"g-rc-empty\", \"No articles match your search.\"));\n merged.forEach(articleButton);\n return;\n }\n if (data.recommended?.length) {\n section(\"Recommended\");\n data.recommended.forEach((g) => {\n const b = listItem(doc, \"▶\", g.name, \"Start guide\");\n b.addEventListener(\"click\", () => options.onStartGuide?.(g.id));\n body.appendChild(b);\n });\n }\n if (data.checklists?.length) {\n section(\"Checklists\");\n data.checklists.forEach((g) => {\n const b = listItem(doc, \"☑\", g.name, \"Open checklist\");\n b.addEventListener(\"click\", () => options.onOpenChecklist?.(g.id));\n body.appendChild(b);\n });\n }\n const collections = [...data.collections].sort((a, b) => a.order - b.order);\n const uncollected = data.articles.filter((a) => !a.collectionId || !collections.some((c) => c.id === a.collectionId));\n collections.forEach((c) => {\n const articles = data.articles.filter((a) => a.collectionId === c.id);\n if (!articles.length) return;\n section(c.name);\n articles.forEach(articleButton);\n });\n if (uncollected.length) {\n section(\"Articles\");\n uncollected.forEach(articleButton);\n }\n if (data.faqs?.length) {\n section(\"FAQ\");\n data.faqs.forEach((f) => {\n const b = listItem(doc, \"?\", f.question);\n b.setAttribute(\"aria-expanded\", \"false\");\n const a = el(doc, \"div\", \"g-faq-a\");\n setSanitizedHtml(a, f.answer);\n a.hidden = true;\n b.addEventListener(\"click\", () => {\n a.hidden = !a.hidden;\n b.setAttribute(\"aria-expanded\", String(!a.hidden));\n });\n body.append(b, a);\n });\n }\n if (data.links?.length) {\n section(\"Links\");\n data.links.forEach((l) => {\n const a = el(doc, \"a\", \"g-rc-item\");\n a.href = l.url;\n a.target = \"_blank\";\n a.rel = \"noopener noreferrer\";\n const i = el(doc, \"span\", \"g-rc-icon\", \"↗\");\n i.setAttribute(\"aria-hidden\", \"true\");\n a.append(i, el(doc, \"span\", \"g-rc-title\", l.label));\n body.appendChild(a);\n });\n }\n if (!body.childNodes.length) body.appendChild(el(doc, \"div\", \"g-rc-empty\", \"Nothing here yet.\"));\n }\n\n let debounce: ReturnType<typeof setTimeout> | null = null;\n const onInput = () => {\n query = input.value;\n openSeq++;\n active = null;\n render();\n if (debounce) clearTimeout(debounce);\n if (!options.search || !query.trim()) {\n serverResults = [];\n return;\n }\n const seq = ++searchSeq;\n debounce = setTimeout(() => {\n options\n .search?.(query.trim())\n .then((results) => {\n if (seq !== searchSeq) return;\n serverResults = Array.isArray(results) ? results : [];\n render();\n })\n .catch(() => {});\n }, 250);\n };\n input.addEventListener(\"input\", onInput);\n\n return {\n el: root,\n render,\n reset() {\n openSeq++;\n active = null;\n query = \"\";\n input.value = \"\";\n serverResults = [];\n },\n openArticle(id: string) {\n const listed = options.data().articles.find((a) => a.id === id) ?? { id, slug: id, title: \"Article\", summary: \"\", updatedAt: \"\", bodyOmitted: true };\n openArticle(listed);\n },\n focusSearch: () => input.focus?.({ preventScroll: true }),\n setQuery(q: string) {\n input.value = q;\n onInput();\n },\n destroy() {\n if (debounce) clearTimeout(debounce);\n input.removeEventListener(\"input\", onInput);\n root.remove();\n },\n };\n}\n","/** Messenger styles, injected into the Guidely shadow root the first time the messenger renders. */\nexport const MESSENGER_STYLES = `\n:host([data-g-messenger=\"bottom-right\"]) .g-launcher.g-pos-bottom-right{right:72px}\n:host([data-g-messenger=\"bottom-left\"]) .g-launcher.g-pos-bottom-left{left:72px}\n.g-m-launcher{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;width:56px;height:56px;margin:16px;border-radius:999px;border:0;background:var(--g-primary);color:var(--g-primary-text);cursor:pointer;box-shadow:var(--g-shadow);display:inline-flex;align-items:center;justify-content:center;padding:0;transition:transform .15s}\n.g-m-launcher:hover{transform:scale(1.05)}\n.g-m-launcher:focus-visible{outline:2px solid var(--g-primary);outline-offset:3px}\n.g-m-launcher svg{width:26px;height:26px;fill:currentColor}\n.g-m-badge{position:absolute;top:-2px;right:-2px;min-width:20px;height:20px;padding:0 5px;border-radius:999px;background:#e11d48;color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--g-bg)}\n.g-messenger{bottom:76px;height:min(640px,calc(100vh - 110px))}\n.g-m-head{padding:16px 48px 14px 20px;background:var(--g-primary);color:var(--g-primary-text);position:relative;display:flex;align-items:center;gap:8px;min-height:56px}\n.g-m-head .g-close{color:inherit;top:50%;transform:translateY(-50%)}\n.g-m-head .g-close:hover,.g-m-head .g-close:focus-visible{background:rgba(255,255,255,.18);color:inherit}\n.g-m-head h2{margin:0;font-size:16px;font-weight:600;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.g-m-back{border:0;background:transparent;color:inherit;font:inherit;font-size:18px;cursor:pointer;width:32px;height:32px;border-radius:999px;margin-left:-8px}\n.g-m-back:hover,.g-m-back:focus-visible{background:rgba(255,255,255,.18);outline:none}\n.g-m-main{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}\n.g-m-scroll{flex:1;overflow:auto;padding:16px}\n.g-m-hero{font-size:22px;font-weight:700;margin:4px 0 4px}\n.g-m-greet{color:var(--g-muted);margin:0 0 16px}\n.g-m-card{display:block;width:100%;text-align:left;border:1px solid var(--g-border);background:var(--g-bg);color:var(--g-text);border-radius:calc(var(--g-radius) * .8);padding:14px 16px;margin:0 0 12px;font:inherit;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.04)}\n.g-m-card:hover{background:var(--g-subtle)}\n.g-m-card:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-m-card-title{font-weight:600}\n.g-m-card-sub{color:var(--g-muted);font-size:13px;margin-top:2px}\n.g-m-row{display:flex;align-items:flex-start;gap:10px}\n.g-m-row .g-m-grow{flex:1;min-width:0}\n.g-m-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.g-m-time{color:var(--g-muted);font-size:12px;flex:none}\n.g-m-dot{width:8px;height:8px;border-radius:999px;background:var(--g-primary);flex:none;margin-top:6px}\n.g-m-tabs{display:flex;border-top:1px solid var(--g-border);background:var(--g-bg)}\n.g-m-tab{flex:1;border:0;background:transparent;color:var(--g-muted);font:inherit;font-size:12px;font-weight:600;padding:10px 4px 12px;cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:2px}\n.g-m-tab[aria-selected=\"true\"]{color:var(--g-primary)}\n.g-m-tab:focus-visible{outline:2px solid var(--g-primary);outline-offset:-2px}\n.g-m-tab-icon{font-size:18px;line-height:1}\n.g-m-log{flex:1;overflow:auto;padding:16px;display:flex;flex-direction:column;gap:10px}\n.g-m-msg{max-width:85%;display:flex;flex-direction:column;gap:4px}\n.g-m-msg.g-from-user{align-self:flex-end;align-items:flex-end}\n.g-m-msg.g-from-system{align-self:center;max-width:95%;text-align:center;color:var(--g-muted);font-size:12px}\n.g-m-author{font-size:12px;color:var(--g-muted);display:flex;align-items:center;gap:6px}\n.g-m-ai{font-size:10px;font-weight:700;letter-spacing:.04em;padding:1px 5px;border-radius:4px;background:var(--g-subtle);color:var(--g-muted)}\n.g-m-bubble{padding:10px 12px;border-radius:14px;background:var(--g-subtle);color:var(--g-text);overflow-wrap:anywhere}\n.g-from-user .g-m-bubble{background:var(--g-primary);color:var(--g-primary-text)}\n.g-from-user .g-m-bubble a{color:inherit}\n.g-m-bubble p{margin:0 0 8px}.g-m-bubble p:last-child{margin:0}\n.g-m-bubble ul,.g-m-bubble ol{margin:4px 0 8px;padding-left:20px}\n.g-m-bubble code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;background:color-mix(in srgb,var(--g-text) 8%,transparent);padding:1px 4px;border-radius:4px}\n.g-m-bubble a{color:var(--g-primary)}\n.g-m-failed .g-m-bubble{opacity:.7;font-style:italic}\n.g-m-typing{display:inline-flex;gap:4px;padding:4px 0}\n.g-m-typing span{width:6px;height:6px;border-radius:999px;background:var(--g-muted);animation:g-m-bounce 1s infinite}\n.g-m-typing span:nth-child(2){animation-delay:.15s}.g-m-typing span:nth-child(3){animation-delay:.3s}\n@keyframes g-m-bounce{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}\n@media (prefers-reduced-motion: reduce){.g-m-typing span{animation:none}.g-m-launcher{transition:none}}\n.g-m-chips{display:flex;flex-direction:column;gap:6px;margin-top:2px}\n.g-m-chip{display:flex;align-items:center;gap:8px;text-align:left;border:1px solid var(--g-border);background:var(--g-bg);color:var(--g-text);border-radius:10px;padding:8px 10px;font:inherit;font-size:13px;cursor:pointer}\n.g-m-chip:hover{background:var(--g-subtle)}\n.g-m-chip:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-m-chip.g-m-guide{border-color:var(--g-primary);color:var(--g-primary);font-weight:600}\n.g-m-foot{border-top:1px solid var(--g-border);padding:10px 12px 12px;background:var(--g-bg)}\n.g-m-compose{display:flex;align-items:flex-end;gap:8px}\n.g-m-compose textarea{flex:1;resize:none;min-height:40px;max-height:120px;border:1px solid var(--g-border);border-radius:10px;padding:9px 10px;font:inherit;font-size:14px;color:var(--g-text);background:var(--g-bg)}\n.g-m-compose textarea:focus-visible{outline:2px solid var(--g-primary);outline-offset:1px}\n.g-m-send{width:40px;height:40px;border-radius:999px;border:0;background:var(--g-primary);color:var(--g-primary-text);cursor:pointer;font-size:18px;flex:none}\n.g-m-send:disabled{opacity:.45;cursor:not-allowed}\n.g-m-send:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-m-human{border:0;background:transparent;color:var(--g-muted);font:inherit;font-size:12px;cursor:pointer;padding:6px 2px 0;text-decoration:underline}\n.g-m-human:hover{color:var(--g-text)}\n.g-m-rate{text-align:center;padding:4px 0 2px;font-size:13px;color:var(--g-muted)}\n.g-m-rate button{border:0;background:transparent;font-size:22px;cursor:pointer;padding:4px 8px;border-radius:8px}\n.g-m-rate button:hover,.g-m-rate button:focus-visible{background:var(--g-subtle);outline:none}\n.g-m-note{color:var(--g-muted);font-size:12px;margin-top:6px}\n.g-m-empty{color:var(--g-muted);text-align:center;padding:24px 8px}\n`;\n","/**\n * Renders untrusted chat text (Scout replies, user and teammate messages) with createElement and\n * textContent only. Supports paragraphs, line breaks, `- ` / `1. ` lists, **bold**, `code` and\n * http(s) links. Never creates images, raw HTML or non-http links, so a prompt-injected reply can't\n * load remote resources or run script.\n */\n\nconst CITATION = /\\s*\\[\\[article:[^\\]]*\\]\\]/g;\n// Inline tokens: **bold**, `code`, [label](url), bare https?:// URLs.\nconst INLINE = /\\*\\*([^*\\n]+)\\*\\*|`([^`\\n]+)`|(!?)\\[([^\\]\\n]{1,200})\\]\\((https?:\\/\\/[^\\s)]+)\\)|(https?:\\/\\/[^\\s<>()\"']+[^\\s<>().,;:!?'\"])/g;\n\n/** Removes `[[article:ID]]` markers (citations are rendered from structured data instead). */\nexport function stripCitationMarkers(text: string): string {\n return text.replace(CITATION, \"\");\n}\n\nexport function safeHttpUrl(raw: string): string | null {\n try {\n const u = new URL(raw);\n return u.protocol === \"http:\" || u.protocol === \"https:\" ? u.href : null;\n } catch {\n return null;\n }\n}\n\nfunction link(doc: Document, label: string, href: string): Node {\n const url = safeHttpUrl(href);\n if (!url) return doc.createTextNode(label);\n const a = doc.createElement(\"a\");\n a.href = url;\n a.target = \"_blank\";\n a.rel = \"noopener noreferrer nofollow\";\n a.textContent = label;\n return a;\n}\n\nfunction appendInline(doc: Document, parent: Node, text: string) {\n let last = 0;\n for (const m of text.matchAll(INLINE)) {\n const start = m.index ?? 0;\n if (start > last) parent.appendChild(doc.createTextNode(text.slice(last, start)));\n if (m[1] !== undefined) {\n const b = doc.createElement(\"strong\");\n b.textContent = m[1];\n parent.appendChild(b);\n } else if (m[2] !== undefined) {\n const c = doc.createElement(\"code\");\n c.textContent = m[2];\n parent.appendChild(c);\n } else if (m[4] !== undefined && m[5] !== undefined) {\n // Markdown images () are never loaded or linked: keep the alt text only.\n parent.appendChild(m[3] ? doc.createTextNode(m[4]) : link(doc, m[4], m[5]));\n } else if (m[6] !== undefined) {\n parent.appendChild(link(doc, m[6], m[6]));\n }\n last = start + m[0].length;\n }\n if (last < text.length) parent.appendChild(doc.createTextNode(text.slice(last)));\n}\n\nconst BULLET = /^\\s*[-*•]\\s+/;\nconst NUMBERED = /^\\s*\\d{1,3}[.)]\\s+/;\n\n/** Builds a fragment for `text`. Safe for any input. */\nexport function renderSafeText(doc: Document, text: string): DocumentFragment {\n const frag = doc.createDocumentFragment();\n const blocks = stripCitationMarkers(text).replace(/\\r\\n?/g, \"\\n\").trim().split(/\\n{2,}/);\n for (const block of blocks) {\n if (!block.trim()) continue;\n const lines = block.split(\"\\n\");\n if (lines.every((l) => BULLET.test(l)) || lines.every((l) => NUMBERED.test(l))) {\n const ordered = NUMBERED.test(lines[0]!);\n const list = doc.createElement(ordered ? \"ol\" : \"ul\");\n for (const line of lines) {\n const li = doc.createElement(\"li\");\n appendInline(doc, li, line.replace(ordered ? NUMBERED : BULLET, \"\"));\n list.appendChild(li);\n }\n frag.appendChild(list);\n continue;\n }\n const p = doc.createElement(\"p\");\n lines.forEach((line, i) => {\n if (i) p.appendChild(doc.createElement(\"br\"));\n appendInline(doc, p, line);\n });\n frag.appendChild(p);\n }\n return frag;\n}\n"],"mappings":"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","names":["el","el"]}
|
|
1
|
+
{"version":3,"sources":["../src/messenger.ts","../src/help-view.ts","../src/sanitize.ts","../src/messenger-styles.ts","../src/render-safe.ts"],"sourcesContent":["import type {\n ConversationMessagesResponse,\n MessengerConfig,\n MessengerConversation,\n MessengerMessage,\n ResourceCenterArticle,\n ResourceCenterConfig,\n SdkArticlesResponse,\n} from \"@guidelytech/shared\";\nimport { createHelpView, el, type HelpData, type HelpGuideRef } from \"./help-view\";\nimport { MESSENGER_STYLES } from \"./messenger-styles\";\nimport { renderSafeText } from \"./render-safe\";\n\n/** Callbacks the transport invokes while a message is sent and Scout replies. */\nexport interface MessengerStreamHandlers {\n /** A new conversation was created (first message only). */\n onConversation?(conversation: MessengerConversation): void;\n onMessage(message: MessengerMessage): void;\n onDelta(messageId: string, text: string): void;\n onDone(message: MessengerMessage | null, conversation: MessengerConversation): void;\n onError(message: string): void;\n}\n\n/** Server access for the messenger; implemented by sdk-core over the public SDK API. */\nexport interface MessengerApi {\n listConversations(): Promise<MessengerConversation[]>;\n loadMessages(conversationId: string, since?: string | null): Promise<ConversationMessagesResponse>;\n start(text: string, handlers: MessengerStreamHandlers): Promise<void>;\n send(conversationId: string, text: string, handlers: MessengerStreamHandlers): Promise<void>;\n handoff(conversationId: string): Promise<ConversationMessagesResponse>;\n rate(conversationId: string, rating: number): Promise<void>;\n listArticles(): Promise<SdkArticlesResponse>;\n getArticle(id: string): Promise<ResourceCenterArticle | null>;\n searchArticles(q: string): Promise<ResourceCenterArticle[]>;\n}\n\nexport type MessengerTab = \"home\" | \"messages\" | \"help\";\n\nexport interface MessengerOptions {\n scope: HTMLElement;\n config: MessengerConfig;\n api: MessengerApi;\n /** Resource center extras (recommended guides, checklists, FAQs, links) shown in the Help tab. */\n resourceCenter?: ResourceCenterConfig | null;\n /** The visitor's audiences (for audience-targeted articles and collections in the Help tab). */\n audienceIds?: () => ReadonlySet<string> | readonly string[];\n guides?: HelpGuideRef[];\n onStartGuide?: (guideKeyOrId: string) => void;\n onOpenChecklist?: (guideId: string) => void;\n onArticleView?: (article: ResourceCenterArticle) => void;\n onOpen?: () => void;\n onClose?: () => void;\n onMessage?: (message: MessengerMessage, conversation: MessengerConversation) => void;\n hideLauncher?: boolean;\n /** Poll intervals (ms): open thread, and unread badge while closed. */\n pollMs?: { thread: number; background: number };\n}\n\nexport interface MessengerWidget {\n el: HTMLElement;\n open(tab?: MessengerTab): void;\n close(): void;\n toggle(): void;\n isOpen(): boolean;\n /** Opens a new conversation, optionally pre-filling the composer. */\n showNewMessage(text?: string): void;\n openArticle(id: string): void;\n destroy(): void;\n}\n\ntype View = { kind: \"tab\"; tab: MessengerTab } | { kind: \"thread\"; conversationId: string | null };\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\nfunction chatIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS(SVG_NS, \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = doc.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", \"M12 3C6.5 3 2 6.8 2 11.5c0 2.4 1.2 4.6 3.1 6.1L4.5 21l3.9-2c1.1.3 2.3.5 3.6.5 5.5 0 10-3.8 10-8.5S17.5 3 12 3z\");\n svg.appendChild(path);\n return svg;\n}\n\nexport function relativeTime(iso: string, now = Date.now()): string {\n const s = Math.max(0, Math.round((now - Date.parse(iso)) / 1000));\n if (!Number.isFinite(s) || s < 60) return \"now\";\n if (s < 3600) return `${Math.floor(s / 60)}m`;\n if (s < 86400) return `${Math.floor(s / 3600)}h`;\n return `${Math.floor(s / 86400)}d`;\n}\n\nfunction ensureStyles(scope: HTMLElement) {\n const root = scope.getRootNode() as ShadowRoot | Document;\n const container = \"host\" in root ? root : scope.ownerDocument.head;\n if (container.querySelector?.(\"style[data-g-messenger]\")) return;\n const style = scope.ownerDocument.createElement(\"style\");\n style.setAttribute(\"data-g-messenger\", \"\");\n style.textContent = MESSENGER_STYLES;\n container.appendChild(style);\n}\n\n/** Intercom-style messenger: launcher + panel with Home, Messages (chat with Scout / the team) and Help tabs. */\nexport function renderMessenger(options: MessengerOptions): MessengerWidget {\n const { scope, config, api } = options;\n const doc = scope.ownerDocument;\n const poll = options.pollMs ?? { thread: 5000, background: 60000 };\n ensureStyles(scope);\n\n let open = false;\n let destroyed = false;\n let view: View = { kind: \"tab\", tab: \"home\" };\n let conversations: MessengerConversation[] = [];\n let messages: MessengerMessage[] = [];\n let current: MessengerConversation | null = null;\n const streaming = new Map<string, string>();\n let sending = false;\n let draft = \"\";\n let articles: SdkArticlesResponse | null = null;\n let articlesLoading = false;\n let threadTimer: ReturnType<typeof setTimeout> | null = null;\n let backgroundTimer: ReturnType<typeof setInterval> | null = null;\n let threadSeq = 0;\n\n const pos = `g-pos-${config.launcher.position}`;\n // Other launchers (checklists, resource center) in the same corner move aside for the chat bubble.\n const rootNode = scope.getRootNode();\n const shadowHost = \"host\" in rootNode ? (rootNode.host as HTMLElement) : null;\n shadowHost?.setAttribute(\"data-g-messenger\", config.launcher.position);\n const root = el(doc, \"div\", \"g-messenger-root\");\n const launcher = el(doc, \"button\", `g-m-launcher ${pos}`);\n launcher.type = \"button\";\n launcher.setAttribute(\"aria-label\", `Open ${config.name}`);\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.appendChild(chatIcon(doc));\n const badge = el(doc, \"span\", \"g-m-badge\");\n badge.hidden = true;\n launcher.appendChild(badge);\n if (options.hideLauncher) launcher.hidden = true;\n\n const panel = el(doc, \"div\", `g-panel g-messenger ${pos}`);\n panel.setAttribute(\"role\", \"dialog\");\n panel.setAttribute(\"aria-label\", config.name);\n panel.hidden = true;\n const head = el(doc, \"div\", \"g-m-head\");\n const main = el(doc, \"div\", \"g-m-main\");\n const tabs = el(doc, \"div\", \"g-m-tabs\");\n tabs.setAttribute(\"role\", \"tablist\");\n panel.append(head, main, tabs);\n root.append(launcher, panel);\n scope.appendChild(root);\n\n const rcExtras = (ids: string[] = []) => ids.map((id) => options.guides?.find((g) => g.id === id || g.key === id)).filter((g): g is HelpGuideRef => !!g);\n const help = createHelpView({\n doc,\n data: (): HelpData => ({\n collections: articles?.collections ?? options.resourceCenter?.collections ?? [],\n articles: articles?.articles ?? options.resourceCenter?.articles ?? [],\n recommended: rcExtras(options.resourceCenter?.recommendedGuideIds),\n checklists: rcExtras(options.resourceCenter?.checklistGuideIds),\n faqs: options.resourceCenter?.faqs,\n links: options.resourceCenter?.links,\n }),\n search: (q) => api.searchArticles(q),\n audienceIds: options.audienceIds,\n loadArticle: (id) => api.getArticle(id),\n onStartGuide: (id) => {\n setOpen(false);\n options.onStartGuide?.(id);\n },\n onOpenChecklist: (id) => {\n setOpen(false);\n options.onOpenChecklist?.(id);\n },\n onArticleView: options.onArticleView,\n });\n\n const unreadTotal = () => conversations.reduce((n, c) => n + (c.unread > 0 ? 1 : 0), 0);\n const updateBadge = () => {\n const n = unreadTotal();\n badge.hidden = n === 0 || open;\n badge.textContent = n > 9 ? \"9+\" : String(n);\n launcher.setAttribute(\"aria-label\", n ? `Open ${config.name}, ${n} unread` : `Open ${config.name}`);\n };\n\n const upsertConversation = (c: MessengerConversation) => {\n conversations = [c, ...conversations.filter((x) => x.id !== c.id)].sort((a, b) => b.lastMessageAt.localeCompare(a.lastMessageAt));\n if (current?.id === c.id) current = c;\n updateBadge();\n };\n const upsertMessage = (m: MessengerMessage) => {\n const i = messages.findIndex((x) => x.id === m.id);\n if (i >= 0) messages[i] = m;\n else messages.push(m);\n messages.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n if (m.status !== \"pending\") streaming.delete(m.id);\n };\n\n const loadArticles = () => {\n if (articles || articlesLoading) return;\n articlesLoading = true;\n api\n .listArticles()\n .then((res) => {\n articles = res;\n if (view.kind === \"tab\" && view.tab === \"help\") help.render();\n })\n .catch(() => {})\n .finally(() => (articlesLoading = false));\n };\n\n const refreshConversations = () =>\n api\n .listConversations()\n .then((list) => {\n conversations = [...list].sort((a, b) => b.lastMessageAt.localeCompare(a.lastMessageAt));\n updateBadge();\n if (open && view.kind === \"tab\" && view.tab !== \"help\") render();\n })\n .catch(() => {});\n\n // ---------------------------------------------------------------------------\n // Rendering\n // ---------------------------------------------------------------------------\n\n function renderHead(title: string, back?: () => void) {\n head.textContent = \"\";\n if (back) {\n const b = el(doc, \"button\", \"g-m-back\", \"←\");\n b.type = \"button\";\n b.setAttribute(\"aria-label\", \"Back\");\n b.addEventListener(\"click\", back);\n head.appendChild(b);\n }\n head.appendChild(el(doc, \"h2\", \"\", title));\n const close = el(doc, \"button\", \"g-close\", \"×\");\n close.type = \"button\";\n close.setAttribute(\"aria-label\", \"Close\");\n close.addEventListener(\"click\", () => setOpen(false));\n head.appendChild(close);\n }\n\n function renderTabs() {\n tabs.textContent = \"\";\n tabs.hidden = view.kind === \"thread\";\n const items: Array<[MessengerTab, string, string]> = [\n [\"home\", \"⌂\", \"Home\"],\n [\"messages\", \"💬\", \"Messages\"],\n [\"help\", \"?\", \"Help\"],\n ];\n for (const [tab, icon, label] of items) {\n const b = el(doc, \"button\", \"g-m-tab\");\n b.type = \"button\";\n b.setAttribute(\"role\", \"tab\");\n b.setAttribute(\"aria-selected\", String(view.kind === \"tab\" && view.tab === tab));\n const i = el(doc, \"span\", \"g-m-tab-icon\", icon);\n i.setAttribute(\"aria-hidden\", \"true\");\n b.append(i, el(doc, \"span\", \"\", label));\n b.addEventListener(\"click\", () => go({ kind: \"tab\", tab }));\n tabs.appendChild(b);\n }\n }\n\n function conversationCard(c: MessengerConversation): HTMLButtonElement {\n const card = el(doc, \"button\", \"g-m-card\");\n card.type = \"button\";\n const row = el(doc, \"div\", \"g-m-row\");\n if (c.unread > 0) row.appendChild(el(doc, \"span\", \"g-m-dot\"));\n const text = el(doc, \"div\", \"g-m-grow\");\n text.append(el(doc, \"div\", \"g-m-card-title g-m-ellipsis\", c.subject || \"Conversation\"), el(doc, \"div\", \"g-m-card-sub g-m-ellipsis\", c.lastMessagePreview));\n row.append(text, el(doc, \"span\", \"g-m-time\", relativeTime(c.lastMessageAt)));\n card.appendChild(row);\n card.setAttribute(\"aria-label\", `${c.subject || \"Conversation\"}${c.unread ? \", unread\" : \"\"}`);\n card.addEventListener(\"click\", () => go({ kind: \"thread\", conversationId: c.id }));\n return card;\n }\n\n function renderHome() {\n renderHead(config.name);\n const scroll = el(doc, \"div\", \"g-m-scroll\");\n scroll.append(el(doc, \"div\", \"g-m-hero\", \"Hi there 👋\"), el(doc, \"p\", \"g-m-greet\", config.greeting));\n const ask = el(doc, \"button\", \"g-m-card\");\n ask.type = \"button\";\n ask.append(el(doc, \"div\", \"g-m-card-title\", \"Ask a question\"), el(doc, \"div\", \"g-m-card-sub\", config.aiAvailable ? `${config.name} answers right away, and the team can help too` : \"The team will reply here\"));\n ask.addEventListener(\"click\", () => go({ kind: \"thread\", conversationId: null }));\n scroll.appendChild(ask);\n const recent = conversations[0];\n if (recent) {\n scroll.appendChild(el(doc, \"div\", \"g-rc-section\", \"Recent conversation\"));\n scroll.appendChild(conversationCard(recent));\n }\n const search = el(doc, \"button\", \"g-m-card\");\n search.type = \"button\";\n search.append(el(doc, \"div\", \"g-m-card-title\", \"Search for help\"), el(doc, \"div\", \"g-m-card-sub\", \"Browse articles and guides\"));\n search.addEventListener(\"click\", () => go({ kind: \"tab\", tab: \"help\" }));\n scroll.appendChild(search);\n main.appendChild(scroll);\n }\n\n function renderMessagesTab() {\n renderHead(\"Messages\");\n const scroll = el(doc, \"div\", \"g-m-scroll\");\n if (!conversations.length) scroll.appendChild(el(doc, \"div\", \"g-m-empty\", \"No conversations yet.\"));\n conversations.forEach((c) => scroll.appendChild(conversationCard(c)));\n const start = el(doc, \"button\", \"g-btn g-btn-primary\", \"Send us a message\");\n start.type = \"button\";\n start.style.width = \"100%\";\n start.addEventListener(\"click\", () => go({ kind: \"thread\", conversationId: null }));\n scroll.appendChild(start);\n main.appendChild(scroll);\n }\n\n function renderHelpTab() {\n renderHead(\"Help\");\n loadArticles();\n help.render();\n main.appendChild(help.el);\n }\n\n let log: HTMLElement | null = null;\n let foot: HTMLElement | null = null;\n let textarea: HTMLTextAreaElement | null = null;\n let sendButton: HTMLButtonElement | null = null;\n\n function messageNode(m: MessengerMessage): HTMLElement {\n const wrap = el(doc, \"div\", `g-m-msg g-from-${m.author}${m.status === \"failed\" ? \" g-m-failed\" : \"\"}`);\n if (m.author === \"system\") {\n wrap.textContent = m.body;\n return wrap;\n }\n if (m.author !== \"user\") {\n const author = el(doc, \"div\", \"g-m-author\", m.author === \"scout\" ? config.name : m.authorName || \"Support team\");\n if (m.author === \"scout\") author.appendChild(el(doc, \"span\", \"g-m-ai\", \"AI\"));\n wrap.appendChild(author);\n }\n const bubble = el(doc, \"div\", \"g-m-bubble\");\n const live = streaming.get(m.id);\n if (m.status === \"pending\" && !live) {\n const dots = el(doc, \"span\", \"g-m-typing\");\n dots.setAttribute(\"aria-label\", `${config.name} is typing`);\n dots.append(el(doc, \"span\"), el(doc, \"span\"), el(doc, \"span\"));\n bubble.appendChild(dots);\n } else if (m.status === \"failed\") {\n bubble.textContent = \"This reply couldn't be completed.\";\n } else {\n bubble.appendChild(renderSafeText(doc, live ?? m.body));\n }\n if (m.status === \"pending\") bubble.setAttribute(\"aria-busy\", \"true\");\n bubble.dataset.messageId = m.id;\n wrap.appendChild(bubble);\n if (m.citations.length || m.suggestedGuides.length) {\n const chips = el(doc, \"div\", \"g-m-chips\");\n for (const g of m.suggestedGuides) {\n const b = el(doc, \"button\", \"g-m-chip g-m-guide\", `▶ Show me: ${g.name}`);\n b.type = \"button\";\n b.addEventListener(\"click\", () => {\n setOpen(false);\n options.onStartGuide?.(g.key);\n });\n chips.appendChild(b);\n }\n for (const c of m.citations) {\n const b = el(doc, \"button\", \"g-m-chip\", `📄 ${c.title}`);\n b.type = \"button\";\n b.addEventListener(\"click\", () => openArticle(c.articleId));\n chips.appendChild(b);\n }\n wrap.appendChild(chips);\n }\n return wrap;\n }\n\n function renderLog() {\n if (!log) return;\n const atBottom = log.scrollHeight - log.scrollTop - log.clientHeight < 40;\n log.textContent = \"\";\n if (!messages.length) {\n const intro: MessengerMessage = { id: \"intro\", author: config.aiAvailable ? \"scout\" : \"agent\", authorName: \"Support team\", body: config.greeting, citations: [], suggestedGuides: [], status: \"complete\", createdAt: new Date().toISOString() };\n log.appendChild(messageNode(intro));\n }\n messages.forEach((m) => log!.appendChild(messageNode(m)));\n if (atBottom || sending) log.scrollTop = log.scrollHeight;\n renderFoot();\n }\n\n function renderFoot() {\n if (!foot || !textarea || !sendButton) return;\n sendButton.disabled = sending || !textarea.value.trim();\n textarea.disabled = sending;\n for (const extra of Array.from(foot.querySelectorAll(\".g-m-human,.g-m-rate,.g-m-note\"))) extra.remove();\n if (current?.status === \"closed\" && current.rating == null) {\n const rate = el(doc, \"div\", \"g-m-rate\", \"How was this conversation? \");\n for (const [score, face, label] of [\n [1, \"😞\", \"Bad\"],\n [3, \"😐\", \"OK\"],\n [5, \"😀\", \"Great\"],\n ] as const) {\n const b = el(doc, \"button\", \"\", face);\n b.type = \"button\";\n b.setAttribute(\"aria-label\", label);\n b.addEventListener(\"click\", () => {\n if (!current) return;\n const id = current.id;\n current = { ...current, rating: score };\n upsertConversation(current);\n renderFoot();\n api.rate(id, score).catch(() => {});\n });\n rate.appendChild(b);\n }\n foot.prepend(rate);\n } else if (current && current.rating != null && current.status === \"closed\") {\n foot.prepend(el(doc, \"div\", \"g-m-note\", \"Thanks for the feedback!\"));\n }\n if (config.handoffEnabled && config.aiAvailable && current?.status === \"bot\" && !sending) {\n const human = el(doc, \"button\", \"g-m-human\", \"Talk to a person\");\n human.type = \"button\";\n human.addEventListener(\"click\", () => {\n if (!current) return;\n const id = current.id;\n human.disabled = true;\n api\n .handoff(id)\n .then((res) => {\n if (current?.id !== id) return;\n upsertConversation(res.conversation);\n res.messages.forEach(upsertMessage);\n renderLog();\n })\n .catch(() => (human.disabled = false));\n });\n foot.appendChild(human);\n }\n }\n\n function renderThread(conversationId: string | null) {\n renderHead(current?.subject || (conversationId ? \"Conversation\" : \"New conversation\"), () => go({ kind: \"tab\", tab: \"messages\" }));\n log = el(doc, \"div\", \"g-m-log\");\n log.setAttribute(\"role\", \"log\");\n log.setAttribute(\"aria-live\", \"polite\");\n foot = el(doc, \"div\", \"g-m-foot\");\n const compose = el(doc, \"form\", \"g-m-compose\");\n textarea = el(doc, \"textarea\");\n textarea.rows = 1;\n textarea.maxLength = 4000;\n textarea.placeholder = current?.status === \"open\" ? \"Reply to the team…\" : \"Ask a question…\";\n textarea.setAttribute(\"aria-label\", \"Message\");\n textarea.value = draft;\n sendButton = el(doc, \"button\", \"g-m-send\", \"↑\");\n sendButton.type = \"submit\";\n sendButton.setAttribute(\"aria-label\", \"Send\");\n compose.append(textarea, sendButton);\n foot.appendChild(compose);\n textarea.addEventListener(\"input\", () => {\n draft = textarea!.value;\n if (sendButton) sendButton.disabled = sending || !draft.trim();\n });\n textarea.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey && !e.isComposing) {\n e.preventDefault();\n submit();\n }\n });\n compose.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n submit();\n });\n main.append(log, foot);\n renderLog();\n textarea.focus?.({ preventScroll: true });\n }\n\n function render() {\n if (destroyed) return;\n main.textContent = \"\";\n log = foot = null;\n textarea = null;\n sendButton = null;\n if (view.kind === \"thread\") renderThread(view.conversationId);\n else if (view.tab === \"home\") renderHome();\n else if (view.tab === \"messages\") renderMessagesTab();\n else renderHelpTab();\n renderTabs();\n }\n\n // ---------------------------------------------------------------------------\n // Behaviour\n // ---------------------------------------------------------------------------\n\n const handlers = (seq: number): MessengerStreamHandlers => ({\n onConversation(c) {\n if (seq !== threadSeq) return;\n current = c;\n view = { kind: \"thread\", conversationId: c.id };\n upsertConversation(c);\n },\n onMessage(m) {\n if (seq !== threadSeq) return;\n upsertMessage(m);\n renderLog();\n },\n onDelta(id, text) {\n if (seq !== threadSeq) return;\n streaming.set(id, (streaming.get(id) ?? \"\") + text);\n const bubble = log?.querySelector<HTMLElement>(`[data-message-id=\"${id}\"]`);\n if (!bubble) return renderLog();\n bubble.textContent = \"\";\n bubble.appendChild(renderSafeText(doc, streaming.get(id)!));\n if (log) log.scrollTop = log.scrollHeight;\n },\n onDone(m, c) {\n if (seq !== threadSeq) return;\n if (m) {\n upsertMessage(m);\n options.onMessage?.(m, c);\n }\n upsertConversation({ ...c, unread: 0 });\n current = { ...c, unread: 0 };\n },\n onError() {\n /* the server also stores a system message explaining what happened */\n },\n });\n\n function submit() {\n if (!textarea || sending) return;\n const text = textarea.value.trim();\n if (!text) return;\n sending = true;\n draft = \"\";\n textarea.value = \"\";\n renderFoot();\n const seq = threadSeq;\n const h = handlers(seq);\n const done = current ? api.send(current.id, text, h) : api.start(text, h);\n done\n .catch(() => {\n if (seq !== threadSeq) return;\n draft = text;\n if (textarea) textarea.value = text;\n const note: MessengerMessage = { id: `local_${Date.now()}`, author: \"system\", body: \"Your message couldn't be sent. Please try again.\", citations: [], suggestedGuides: [], status: \"complete\", createdAt: new Date().toISOString() };\n upsertMessage(note);\n })\n .finally(() => {\n if (seq !== threadSeq) return;\n sending = false;\n streaming.clear();\n if (view.kind === \"thread\") {\n if (current) renderHead(current.subject || \"Conversation\", () => go({ kind: \"tab\", tab: \"messages\" }));\n renderLog();\n }\n scheduleThreadPoll();\n });\n }\n\n function scheduleThreadPoll() {\n if (threadTimer) clearTimeout(threadTimer);\n threadTimer = null;\n if (!open || view.kind !== \"thread\" || !current || destroyed) return;\n threadTimer = setTimeout(pollThread, poll.thread);\n }\n\n function pollThread() {\n if (!current || sending) return scheduleThreadPoll();\n const seq = threadSeq;\n const pending = messages.find((m) => m.status === \"pending\");\n const last = messages.filter((m) => !m.id.startsWith(\"local_\")).at(-1);\n // Re-fetch from a pending reply (its body changes in place); otherwise only newer messages.\n const since = pending ? new Date(Date.parse(pending.createdAt) - 1).toISOString() : (last?.createdAt ?? null);\n api\n .loadMessages(current.id, since)\n .then((res) => {\n if (seq !== threadSeq) return;\n const before = messages.length;\n const changed = res.messages.some((m) => {\n const prev = messages.find((x) => x.id === m.id);\n return !prev || prev.status !== m.status || prev.body !== m.body;\n });\n res.messages.forEach(upsertMessage);\n upsertConversation({ ...res.conversation, unread: 0 });\n current = { ...res.conversation, unread: 0 };\n if (changed || messages.length !== before) {\n renderLog();\n res.messages.filter((m) => m.author !== \"user\").forEach((m) => options.onMessage?.(m, res.conversation));\n } else renderFoot();\n })\n .catch(() => {})\n .finally(scheduleThreadPoll);\n }\n\n function go(next: View) {\n threadSeq++;\n if (threadTimer) clearTimeout(threadTimer);\n threadTimer = null;\n if (view.kind === \"tab\" && view.tab === \"help\" && !(next.kind === \"tab\" && next.tab === \"help\")) help.reset();\n view = next;\n if (next.kind === \"thread\") {\n messages = [];\n streaming.clear();\n sending = false;\n current = next.conversationId ? (conversations.find((c) => c.id === next.conversationId) ?? null) : null;\n render();\n if (next.conversationId) {\n const seq = threadSeq;\n api\n .loadMessages(next.conversationId)\n .then((res) => {\n if (seq !== threadSeq) return;\n res.messages.forEach(upsertMessage);\n current = { ...res.conversation, unread: 0 };\n upsertConversation(current);\n renderHead(current.subject || \"Conversation\", () => go({ kind: \"tab\", tab: \"messages\" }));\n renderLog();\n })\n .catch(() => {})\n .finally(scheduleThreadPoll);\n }\n } else {\n draft = \"\";\n render();\n }\n }\n\n function openArticle(id: string) {\n go({ kind: \"tab\", tab: \"help\" });\n help.openArticle(id);\n }\n\n function startBackgroundPoll() {\n if (backgroundTimer) clearInterval(backgroundTimer);\n backgroundTimer = setInterval(() => {\n if (!open && conversations.length && !destroyed) void refreshConversations();\n }, poll.background);\n }\n\n const setOpen = (v: boolean) => {\n if (open === v || destroyed) return;\n open = v;\n panel.hidden = !v;\n launcher.setAttribute(\"aria-expanded\", String(v));\n launcher.setAttribute(\"aria-label\", v ? `Close ${config.name}` : `Open ${config.name}`);\n updateBadge();\n if (v) {\n render();\n void refreshConversations();\n if (view.kind === \"thread\") scheduleThreadPoll();\n options.onOpen?.();\n } else {\n if (threadTimer) clearTimeout(threadTimer);\n threadTimer = null;\n options.onClose?.();\n }\n };\n launcher.addEventListener(\"click\", () => setOpen(!open));\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n setOpen(false);\n launcher.focus();\n }\n };\n panel.addEventListener(\"keydown\", onKey);\n\n void refreshConversations();\n startBackgroundPoll();\n\n return {\n el: root,\n open(tab?: MessengerTab) {\n if (tab) view = { kind: \"tab\", tab };\n if (open && tab) render();\n setOpen(true);\n },\n close: () => setOpen(false),\n toggle: () => setOpen(!open),\n isOpen: () => open,\n showNewMessage(text?: string) {\n setOpen(true);\n go({ kind: \"thread\", conversationId: null });\n if (text && textarea) {\n textarea.value = text.slice(0, 4000);\n draft = textarea.value;\n renderFoot();\n }\n },\n openArticle(id: string) {\n setOpen(true);\n openArticle(id);\n },\n destroy() {\n destroyed = true;\n if (threadTimer) clearTimeout(threadTimer);\n if (backgroundTimer) clearInterval(backgroundTimer);\n panel.removeEventListener(\"keydown\", onKey);\n help.destroy();\n shadowHost?.removeAttribute(\"data-g-messenger\");\n root.remove();\n },\n };\n}\n","import type { ResourceCenterArticle, ResourceCenterConfig } from \"@guidelytech/shared\";\nimport { isArticleListed, resourceCenterSections } from \"@guidelytech/shared/runtime\";\nimport { setSanitizedHtml } from \"./sanitize\";\n\nexport interface HelpGuideRef {\n id: string;\n key: string;\n name: string;\n kind: string;\n}\n\n/** What the help view lists. Article bodies may be missing (`bodyOmitted` or summaries only): they load on open. */\nexport interface HelpData {\n collections: ResourceCenterConfig[\"collections\"];\n articles: Array<Omit<ResourceCenterArticle, \"body\"> & { body?: string }>;\n recommended?: HelpGuideRef[];\n checklists?: HelpGuideRef[];\n faqs?: ResourceCenterConfig[\"faqs\"];\n links?: ResourceCenterConfig[\"links\"];\n}\n\nexport interface HelpViewOptions {\n doc: Document;\n data: () => HelpData;\n /** Server search. Results are merged with the client-side title/summary filter. */\n search?: (q: string) => Promise<ResourceCenterArticle[]>;\n /** The visitor's audiences; articles and collections targeted at others aren't listed. */\n audienceIds?: () => ReadonlySet<string> | readonly string[];\n /** Loads an article body that isn't in `data()`. */\n loadArticle?: (id: string) => Promise<ResourceCenterArticle | null>;\n onStartGuide?: (guideId: string) => void;\n onOpenChecklist?: (guideId: string) => void;\n onArticleView?: (article: ResourceCenterArticle) => void;\n}\n\nexport interface HelpView {\n /** Search box + scrollable body. */\n el: HTMLElement;\n render(): void;\n /** Back to the article list and clear the search. */\n reset(): void;\n openArticle(id: string): void;\n focusSearch(): void;\n setQuery(q: string): void;\n destroy(): void;\n}\n\nexport function el<K extends keyof HTMLElementTagNameMap>(doc: Document, tag: K, cls?: string, text?: string): HTMLElementTagNameMap[K] {\n const e = doc.createElement(tag);\n if (cls) e.className = cls;\n if (text != null) e.textContent = text;\n return e;\n}\n\nexport function listItem(doc: Document, icon: string, title: string, summary?: string): HTMLButtonElement {\n const b = el(doc, \"button\", \"g-rc-item\");\n b.type = \"button\";\n const i = el(doc, \"span\", \"g-rc-icon\", icon);\n i.setAttribute(\"aria-hidden\", \"true\");\n const text = el(doc, \"span\");\n text.appendChild(el(doc, \"div\", \"g-rc-title\", title));\n if (summary) text.appendChild(el(doc, \"div\", \"g-rc-sum\", summary));\n b.append(i, text);\n return b;\n}\n\ntype ListedArticle = HelpData[\"articles\"][number];\n\n/** Article browser shared by the resource center and the messenger Help tab. */\nexport function createHelpView(options: HelpViewOptions): HelpView {\n const { doc } = options;\n let query = \"\";\n let serverResults: ResourceCenterArticle[] = [];\n let searchSeq = 0;\n let openSeq = 0;\n let active: { article: ListedArticle; loading: boolean } | null = null;\n\n const root = el(doc, \"div\", \"g-help\");\n const searchWrap = el(doc, \"div\", \"g-rc-search\");\n const input = el(doc, \"input\", \"g-input\");\n input.type = \"search\";\n input.placeholder = \"Search help articles…\";\n input.setAttribute(\"aria-label\", \"Search help articles\");\n searchWrap.appendChild(input);\n const body = el(doc, \"div\", \"g-panel-body\");\n root.append(searchWrap, body);\n\n const hasBody = (a: ListedArticle): a is ResourceCenterArticle => typeof a.body === \"string\" && !a.bodyOmitted;\n\n const openArticle = (article: ListedArticle) => {\n if (article.externalUrl) {\n window.open(article.externalUrl, \"_blank\", \"noopener,noreferrer\");\n if (hasBody(article)) options.onArticleView?.(article);\n return;\n }\n const seq = ++openSeq;\n if (hasBody(article) || !options.loadArticle) {\n active = { article, loading: false };\n if (hasBody(article)) options.onArticleView?.(article);\n return render();\n }\n active = { article, loading: true };\n render();\n options\n .loadArticle(article.id)\n .then((full) => {\n if (seq !== openSeq || !active) return;\n active = { article: full ?? { ...article, body: \"\" }, loading: false };\n if (full) options.onArticleView?.(full);\n render();\n })\n .catch(() => {\n if (seq !== openSeq || !active) return;\n active = { article: { ...article, body: \"\" }, loading: false };\n render();\n });\n };\n\n const renderArticle = ({ article, loading }: NonNullable<typeof active>) => {\n const wrap = el(doc, \"div\", \"g-rc-article\");\n const back = el(doc, \"button\", \"g-btn g-btn-link g-rc-back\", \"← Back\");\n back.type = \"button\";\n back.addEventListener(\"click\", () => {\n openSeq++;\n active = null;\n render();\n });\n const title = el(doc, \"h3\", \"g-title\", article.title);\n const content = el(doc, \"div\", \"g-body\");\n if (loading) content.appendChild(el(doc, \"div\", \"g-rc-empty\", \"Loading…\"));\n else if (article.body) setSanitizedHtml(content, article.body);\n else content.appendChild(el(doc, \"div\", \"g-rc-empty\", \"This article couldn't be loaded.\"));\n wrap.append(back, title, content);\n body.appendChild(wrap);\n back.focus?.({ preventScroll: true });\n };\n\n const section = (label: string, depth = 0) => {\n const s = body.appendChild(el(doc, \"div\", \"g-rc-section\", label));\n if (depth) s.dataset.depth = String(depth);\n return s;\n };\n const articleButton = (a: ListedArticle) => {\n const b = listItem(doc, \"📄\", a.title, a.summary);\n b.addEventListener(\"click\", () => openArticle(a));\n body.appendChild(b);\n };\n\n function render() {\n body.textContent = \"\";\n if (active) return renderArticle(active);\n const data = options.data();\n const member = options.audienceIds?.() ?? [];\n const sections = resourceCenterSections(data.collections, data.articles, member);\n const q = query.trim().toLowerCase();\n if (q) {\n const visible = sections.flatMap((s) => s.articles);\n const local = visible.filter((a) => a.title.toLowerCase().includes(q) || a.summary.toLowerCase().includes(q));\n const seen = new Set(local.map((a) => a.id));\n // Server search covers every published article: keep only the ones listed for this visitor.\n const hidden = new Set(data.articles.map((a) => a.id).filter((id) => !visible.some((v) => v.id === id)));\n const merged: ListedArticle[] = [...local, ...serverResults.filter((a) => !seen.has(a.id) && !hidden.has(a.id) && isArticleListed(data.collections, a, member))];\n section(`Results (${merged.length})`);\n if (!merged.length) body.appendChild(el(doc, \"div\", \"g-rc-empty\", \"No articles match your search.\"));\n merged.forEach(articleButton);\n return;\n }\n if (data.recommended?.length) {\n section(\"Recommended\");\n data.recommended.forEach((g) => {\n const b = listItem(doc, \"▶\", g.name, \"Start guide\");\n b.addEventListener(\"click\", () => options.onStartGuide?.(g.id));\n body.appendChild(b);\n });\n }\n if (data.checklists?.length) {\n section(\"Checklists\");\n data.checklists.forEach((g) => {\n const b = listItem(doc, \"☑\", g.name, \"Open checklist\");\n b.addEventListener(\"click\", () => options.onOpenChecklist?.(g.id));\n body.appendChild(b);\n });\n }\n // Nested collections read as \"Billing › Invoices\", depth first.\n for (const s of sections) {\n section(s.collection ? s.path.join(\" › \") : \"Articles\", s.depth);\n s.articles.forEach(articleButton);\n }\n if (data.faqs?.length) {\n section(\"FAQ\");\n data.faqs.forEach((f) => {\n const b = listItem(doc, \"?\", f.question);\n b.setAttribute(\"aria-expanded\", \"false\");\n const a = el(doc, \"div\", \"g-faq-a\");\n setSanitizedHtml(a, f.answer);\n a.hidden = true;\n b.addEventListener(\"click\", () => {\n a.hidden = !a.hidden;\n b.setAttribute(\"aria-expanded\", String(!a.hidden));\n });\n body.append(b, a);\n });\n }\n if (data.links?.length) {\n section(\"Links\");\n data.links.forEach((l) => {\n const a = el(doc, \"a\", \"g-rc-item\");\n a.href = l.url;\n a.target = \"_blank\";\n a.rel = \"noopener noreferrer\";\n const i = el(doc, \"span\", \"g-rc-icon\", \"↗\");\n i.setAttribute(\"aria-hidden\", \"true\");\n a.append(i, el(doc, \"span\", \"g-rc-title\", l.label));\n body.appendChild(a);\n });\n }\n if (!body.childNodes.length) body.appendChild(el(doc, \"div\", \"g-rc-empty\", \"Nothing here yet.\"));\n }\n\n let debounce: ReturnType<typeof setTimeout> | null = null;\n const onInput = () => {\n query = input.value;\n openSeq++;\n active = null;\n render();\n if (debounce) clearTimeout(debounce);\n if (!options.search || !query.trim()) {\n serverResults = [];\n return;\n }\n const seq = ++searchSeq;\n debounce = setTimeout(() => {\n options\n .search?.(query.trim())\n .then((results) => {\n if (seq !== searchSeq) return;\n serverResults = Array.isArray(results) ? results : [];\n render();\n })\n .catch(() => {});\n }, 250);\n };\n input.addEventListener(\"input\", onInput);\n\n return {\n el: root,\n render,\n reset() {\n openSeq++;\n active = null;\n query = \"\";\n input.value = \"\";\n serverResults = [];\n },\n openArticle(id: string) {\n const listed = options.data().articles.find((a) => a.id === id) ?? { id, slug: id, title: \"Article\", summary: \"\", updatedAt: \"\", bodyOmitted: true };\n openArticle(listed);\n },\n focusSearch: () => input.focus?.({ preventScroll: true }),\n setQuery(q: string) {\n input.value = q;\n onInput();\n },\n destroy() {\n if (debounce) clearTimeout(debounce);\n input.removeEventListener(\"input\", onInput);\n root.remove();\n },\n };\n}\n","import { EMBED_IFRAME_ATTRS, VIDEO_ATTRS, isAllowedEmbedSrc, isSafeMediaUrl } from \"@guidelytech/shared/runtime\";\n\nconst ALLOWED_TAGS = new Set([\"p\", \"br\", \"strong\", \"b\", \"em\", \"i\", \"u\", \"a\", \"ul\", \"ol\", \"li\", \"img\", \"h1\", \"h2\", \"h3\", \"h4\", \"code\", \"pre\", \"blockquote\", \"span\", \"div\", \"hr\", \"button\"]);\nconst DROP_TAGS = new Set([\"script\", \"style\", \"object\", \"embed\", \"form\", \"input\", \"textarea\", \"select\", \"link\", \"meta\", \"base\", \"template\", \"svg\", \"math\", \"frame\", \"frameset\", \"noscript\"]);\nconst ALLOWED_ATTRS = new Set([\"href\", \"src\", \"alt\", \"title\", \"target\", \"rel\", \"class\", \"data-g-action\", \"data-g-value\"]);\nfunction isSafeUrl(value: string, attr: string, tag: string): boolean {\n // eslint-disable-next-line no-control-regex\n const v = value.trim().replace(/[\\u0000-\\u001f\\s]/g, \"\").toLowerCase();\n if (!v) return false;\n const m = /^([a-z][a-z0-9+.-]*):/.exec(v);\n if (!m) return true; // relative URL\n const scheme = m[1];\n if (scheme === \"data\") return tag === \"img\" && attr === \"src\" && v.startsWith(\"data:image/\");\n return scheme === \"http\" || scheme === \"https\" || scheme === \"mailto\" || scheme === \"tel\";\n}\n\nfunction sanitizeElement(el: Element): void {\n const tag = el.tagName.toLowerCase();\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase();\n if (name.startsWith(\"on\") || !ALLOWED_ATTRS.has(name)) {\n el.removeAttribute(attr.name);\n continue;\n }\n if ((name === \"href\" || name === \"src\") && !isSafeUrl(attr.value, name, tag)) el.removeAttribute(attr.name);\n }\n if (tag === \"a\") {\n const target = el.getAttribute(\"target\");\n if (target && target !== \"_blank\" && target !== \"_self\") el.removeAttribute(\"target\");\n if (el.getAttribute(\"target\") === \"_blank\") el.setAttribute(\"rel\", \"noopener noreferrer\");\n }\n if (tag === \"button\") el.setAttribute(\"type\", \"button\");\n if (tag === \"img\") {\n el.setAttribute(\"loading\", \"lazy\");\n if (!el.getAttribute(\"alt\")) el.setAttribute(\"alt\", \"\");\n }\n}\n\n/**\n * Media elements are rebuilt from scratch rather than filtered: an `<iframe>` only for a canonical\n * YouTube/Vimeo/Loom/Wistia embed, a `<video>` only for an absolute http(s) file, each with fixed\n * attributes. Returns null when the element must go.\n */\nfunction rebuildMedia(el: Element): Element | null {\n const doc = el.ownerDocument;\n const tag = el.tagName.toLowerCase();\n const src = el.getAttribute(\"src\");\n let out: Element;\n if (tag === \"iframe\") {\n if (!isAllowedEmbedSrc(src)) return null;\n out = doc.createElement(\"iframe\");\n out.setAttribute(\"src\", src!);\n out.setAttribute(\"title\", el.getAttribute(\"title\") || \"Embedded video\");\n for (const [k, v] of Object.entries(EMBED_IFRAME_ATTRS)) out.setAttribute(k, v);\n } else {\n if (!isSafeMediaUrl(src)) return null;\n out = doc.createElement(\"video\");\n out.setAttribute(\"src\", src!);\n const poster = el.getAttribute(\"poster\");\n if (isSafeMediaUrl(poster)) out.setAttribute(\"poster\", poster!);\n for (const [k, v] of Object.entries(VIDEO_ATTRS)) out.setAttribute(k, v);\n }\n return out;\n}\n\nfunction walk(node: Node): void {\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType === 8 /* comment */) {\n node.removeChild(child);\n continue;\n }\n if (child.nodeType !== 1) continue;\n const el = child as Element;\n const tag = el.tagName.toLowerCase();\n if (DROP_TAGS.has(tag)) {\n node.removeChild(el);\n continue;\n }\n if (tag === \"iframe\" || tag === \"video\") {\n const media = rebuildMedia(el);\n if (media) node.replaceChild(media, el);\n else node.removeChild(el);\n continue;\n }\n if (!ALLOWED_TAGS.has(tag)) {\n // Unwrap: keep text/children, drop the element itself.\n while (el.firstChild) node.insertBefore(el.firstChild, el);\n node.removeChild(el);\n // Re-walk the parent since children moved up.\n walk(node);\n return;\n }\n sanitizeElement(el);\n walk(el);\n }\n}\n\n/**\n * Parses HTML into a sanitized DocumentFragment using a strict allowlist. No external\n * dependency: a `<template>` element parses inertly and the tree is walked element by element.\n */\nexport function sanitizeToFragment(html: string, doc: Document = document): DocumentFragment {\n const tpl = doc.createElement(\"template\");\n tpl.innerHTML = html || \"\";\n walk(tpl.content);\n return tpl.content;\n}\n\n/** Returns sanitized HTML as a string. */\nexport function sanitizeHtml(html: string, doc: Document = document): string {\n const frag = sanitizeToFragment(html, doc);\n const div = doc.createElement(\"div\");\n div.appendChild(frag);\n return div.innerHTML;\n}\n\n/** Replaces the content of `el` with the sanitized HTML. */\nexport function setSanitizedHtml(el: Element, html: string): void {\n el.textContent = \"\";\n el.appendChild(sanitizeToFragment(html, el.ownerDocument));\n}\n","/** Messenger styles, injected into the Guidely shadow root the first time the messenger renders. */\nexport const MESSENGER_STYLES = `\n:host([data-g-messenger=\"bottom-right\"]) .g-launcher.g-pos-bottom-right{right:72px}\n:host([data-g-messenger=\"bottom-left\"]) .g-launcher.g-pos-bottom-left{left:72px}\n.g-m-launcher{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;width:56px;height:56px;margin:16px;border-radius:999px;border:0;background:var(--g-primary);color:var(--g-primary-text);cursor:pointer;box-shadow:var(--g-shadow);display:inline-flex;align-items:center;justify-content:center;padding:0;transition:transform .15s}\n.g-m-launcher:hover{transform:scale(1.05)}\n.g-m-launcher:focus-visible{outline:2px solid var(--g-primary);outline-offset:3px}\n.g-m-launcher svg{width:26px;height:26px;fill:currentColor}\n.g-m-badge{position:absolute;top:-2px;right:-2px;min-width:20px;height:20px;padding:0 5px;border-radius:999px;background:#e11d48;color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--g-bg)}\n.g-messenger{bottom:76px;height:min(640px,calc(100vh - 110px))}\n.g-m-head{padding:16px 48px 14px 20px;background:var(--g-primary);color:var(--g-primary-text);position:relative;display:flex;align-items:center;gap:8px;min-height:56px}\n.g-m-head .g-close{color:inherit;top:50%;transform:translateY(-50%)}\n.g-m-head .g-close:hover,.g-m-head .g-close:focus-visible{background:rgba(255,255,255,.18);color:inherit}\n.g-m-head h2{margin:0;font-size:16px;font-weight:600;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.g-m-back{border:0;background:transparent;color:inherit;font:inherit;font-size:18px;cursor:pointer;width:32px;height:32px;border-radius:999px;margin-left:-8px}\n.g-m-back:hover,.g-m-back:focus-visible{background:rgba(255,255,255,.18);outline:none}\n.g-m-main{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}\n.g-m-scroll{flex:1;overflow:auto;padding:16px}\n.g-m-hero{font-size:22px;font-weight:700;margin:4px 0 4px}\n.g-m-greet{color:var(--g-muted);margin:0 0 16px}\n.g-m-card{display:block;width:100%;text-align:left;border:1px solid var(--g-border);background:var(--g-bg);color:var(--g-text);border-radius:calc(var(--g-radius) * .8);padding:14px 16px;margin:0 0 12px;font:inherit;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.04)}\n.g-m-card:hover{background:var(--g-subtle)}\n.g-m-card:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-m-card-title{font-weight:600}\n.g-m-card-sub{color:var(--g-muted);font-size:13px;margin-top:2px}\n.g-m-row{display:flex;align-items:flex-start;gap:10px}\n.g-m-row .g-m-grow{flex:1;min-width:0}\n.g-m-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.g-m-time{color:var(--g-muted);font-size:12px;flex:none}\n.g-m-dot{width:8px;height:8px;border-radius:999px;background:var(--g-primary);flex:none;margin-top:6px}\n.g-m-tabs{display:flex;border-top:1px solid var(--g-border);background:var(--g-bg)}\n.g-m-tab{flex:1;border:0;background:transparent;color:var(--g-muted);font:inherit;font-size:12px;font-weight:600;padding:10px 4px 12px;cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:2px}\n.g-m-tab[aria-selected=\"true\"]{color:var(--g-primary)}\n.g-m-tab:focus-visible{outline:2px solid var(--g-primary);outline-offset:-2px}\n.g-m-tab-icon{font-size:18px;line-height:1}\n.g-m-log{flex:1;overflow:auto;padding:16px;display:flex;flex-direction:column;gap:10px}\n.g-m-msg{max-width:85%;display:flex;flex-direction:column;gap:4px}\n.g-m-msg.g-from-user{align-self:flex-end;align-items:flex-end}\n.g-m-msg.g-from-system{align-self:center;max-width:95%;text-align:center;color:var(--g-muted);font-size:12px}\n.g-m-author{font-size:12px;color:var(--g-muted);display:flex;align-items:center;gap:6px}\n.g-m-ai{font-size:10px;font-weight:700;letter-spacing:.04em;padding:1px 5px;border-radius:4px;background:var(--g-subtle);color:var(--g-muted)}\n.g-m-bubble{padding:10px 12px;border-radius:14px;background:var(--g-subtle);color:var(--g-text);overflow-wrap:anywhere}\n.g-from-user .g-m-bubble{background:var(--g-primary);color:var(--g-primary-text)}\n.g-from-user .g-m-bubble a{color:inherit}\n.g-m-bubble p{margin:0 0 8px}.g-m-bubble p:last-child{margin:0}\n.g-m-bubble ul,.g-m-bubble ol{margin:4px 0 8px;padding-left:20px}\n.g-m-bubble code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;background:color-mix(in srgb,var(--g-text) 8%,transparent);padding:1px 4px;border-radius:4px}\n.g-m-bubble a{color:var(--g-primary)}\n.g-m-failed .g-m-bubble{opacity:.7;font-style:italic}\n.g-m-typing{display:inline-flex;gap:4px;padding:4px 0}\n.g-m-typing span{width:6px;height:6px;border-radius:999px;background:var(--g-muted);animation:g-m-bounce 1s infinite}\n.g-m-typing span:nth-child(2){animation-delay:.15s}.g-m-typing span:nth-child(3){animation-delay:.3s}\n@keyframes g-m-bounce{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}\n@media (prefers-reduced-motion: reduce){.g-m-typing span{animation:none}.g-m-launcher{transition:none}}\n.g-m-chips{display:flex;flex-direction:column;gap:6px;margin-top:2px}\n.g-m-chip{display:flex;align-items:center;gap:8px;text-align:left;border:1px solid var(--g-border);background:var(--g-bg);color:var(--g-text);border-radius:10px;padding:8px 10px;font:inherit;font-size:13px;cursor:pointer}\n.g-m-chip:hover{background:var(--g-subtle)}\n.g-m-chip:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-m-chip.g-m-guide{border-color:var(--g-primary);color:var(--g-primary);font-weight:600}\n.g-m-foot{border-top:1px solid var(--g-border);padding:10px 12px 12px;background:var(--g-bg)}\n.g-m-compose{display:flex;align-items:flex-end;gap:8px}\n.g-m-compose textarea{flex:1;resize:none;min-height:40px;max-height:120px;border:1px solid var(--g-border);border-radius:10px;padding:9px 10px;font:inherit;font-size:14px;color:var(--g-text);background:var(--g-bg)}\n.g-m-compose textarea:focus-visible{outline:2px solid var(--g-primary);outline-offset:1px}\n.g-m-send{width:40px;height:40px;border-radius:999px;border:0;background:var(--g-primary);color:var(--g-primary-text);cursor:pointer;font-size:18px;flex:none}\n.g-m-send:disabled{opacity:.45;cursor:not-allowed}\n.g-m-send:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-m-human{border:0;background:transparent;color:var(--g-muted);font:inherit;font-size:12px;cursor:pointer;padding:6px 2px 0;text-decoration:underline}\n.g-m-human:hover{color:var(--g-text)}\n.g-m-rate{text-align:center;padding:4px 0 2px;font-size:13px;color:var(--g-muted)}\n.g-m-rate button{border:0;background:transparent;font-size:22px;cursor:pointer;padding:4px 8px;border-radius:8px}\n.g-m-rate button:hover,.g-m-rate button:focus-visible{background:var(--g-subtle);outline:none}\n.g-m-note{color:var(--g-muted);font-size:12px;margin-top:6px}\n.g-m-empty{color:var(--g-muted);text-align:center;padding:24px 8px}\n`;\n","/**\n * Renders untrusted chat text (Scout replies, user and teammate messages) with createElement and\n * textContent only. Supports paragraphs, line breaks, `- ` / `1. ` lists, **bold**, `code` and\n * http(s) links. Never creates images, raw HTML or non-http links, so a prompt-injected reply can't\n * load remote resources or run script.\n */\n\nconst CITATION = /\\s*\\[\\[article:[^\\]]*\\]\\]/g;\n// Inline tokens: **bold**, `code`, [label](url), bare https?:// URLs.\nconst INLINE = /\\*\\*([^*\\n]+)\\*\\*|`([^`\\n]+)`|(!?)\\[([^\\]\\n]{1,200})\\]\\((https?:\\/\\/[^\\s)]+)\\)|(https?:\\/\\/[^\\s<>()\"']+[^\\s<>().,;:!?'\"])/g;\n\n/** Removes `[[article:ID]]` markers (citations are rendered from structured data instead). */\nexport function stripCitationMarkers(text: string): string {\n return text.replace(CITATION, \"\");\n}\n\nexport function safeHttpUrl(raw: string): string | null {\n try {\n const u = new URL(raw);\n return u.protocol === \"http:\" || u.protocol === \"https:\" ? u.href : null;\n } catch {\n return null;\n }\n}\n\nfunction link(doc: Document, label: string, href: string): Node {\n const url = safeHttpUrl(href);\n if (!url) return doc.createTextNode(label);\n const a = doc.createElement(\"a\");\n a.href = url;\n a.target = \"_blank\";\n a.rel = \"noopener noreferrer nofollow\";\n a.textContent = label;\n return a;\n}\n\nfunction appendInline(doc: Document, parent: Node, text: string) {\n let last = 0;\n for (const m of text.matchAll(INLINE)) {\n const start = m.index ?? 0;\n if (start > last) parent.appendChild(doc.createTextNode(text.slice(last, start)));\n if (m[1] !== undefined) {\n const b = doc.createElement(\"strong\");\n b.textContent = m[1];\n parent.appendChild(b);\n } else if (m[2] !== undefined) {\n const c = doc.createElement(\"code\");\n c.textContent = m[2];\n parent.appendChild(c);\n } else if (m[4] !== undefined && m[5] !== undefined) {\n // Markdown images () are never loaded or linked: keep the alt text only.\n parent.appendChild(m[3] ? doc.createTextNode(m[4]) : link(doc, m[4], m[5]));\n } else if (m[6] !== undefined) {\n parent.appendChild(link(doc, m[6], m[6]));\n }\n last = start + m[0].length;\n }\n if (last < text.length) parent.appendChild(doc.createTextNode(text.slice(last)));\n}\n\nconst BULLET = /^\\s*[-*•]\\s+/;\nconst NUMBERED = /^\\s*\\d{1,3}[.)]\\s+/;\n\n/** Builds a fragment for `text`. Safe for any input. */\nexport function renderSafeText(doc: Document, text: string): DocumentFragment {\n const frag = doc.createDocumentFragment();\n const blocks = stripCitationMarkers(text).replace(/\\r\\n?/g, \"\\n\").trim().split(/\\n{2,}/);\n for (const block of blocks) {\n if (!block.trim()) continue;\n const lines = block.split(\"\\n\");\n if (lines.every((l) => BULLET.test(l)) || lines.every((l) => NUMBERED.test(l))) {\n const ordered = NUMBERED.test(lines[0]!);\n const list = doc.createElement(ordered ? \"ol\" : \"ul\");\n for (const line of lines) {\n const li = doc.createElement(\"li\");\n appendInline(doc, li, line.replace(ordered ? NUMBERED : BULLET, \"\"));\n list.appendChild(li);\n }\n frag.appendChild(list);\n continue;\n }\n const p = doc.createElement(\"p\");\n lines.forEach((line, i) => {\n if (i) p.appendChild(doc.createElement(\"br\"));\n appendInline(doc, p, line);\n });\n frag.appendChild(p);\n }\n return frag;\n}\n"],"mappings":"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","names":["import_runtime","el","el"]}
|
package/dist/messenger.d.cts
CHANGED
|
@@ -29,6 +29,8 @@ interface MessengerOptions {
|
|
|
29
29
|
api: MessengerApi;
|
|
30
30
|
/** Resource center extras (recommended guides, checklists, FAQs, links) shown in the Help tab. */
|
|
31
31
|
resourceCenter?: ResourceCenterConfig | null;
|
|
32
|
+
/** The visitor's audiences (for audience-targeted articles and collections in the Help tab). */
|
|
33
|
+
audienceIds?: () => ReadonlySet<string> | readonly string[];
|
|
32
34
|
guides?: HelpGuideRef[];
|
|
33
35
|
onStartGuide?: (guideKeyOrId: string) => void;
|
|
34
36
|
onOpenChecklist?: (guideId: string) => void;
|
package/dist/messenger.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ interface MessengerOptions {
|
|
|
29
29
|
api: MessengerApi;
|
|
30
30
|
/** Resource center extras (recommended guides, checklists, FAQs, links) shown in the Help tab. */
|
|
31
31
|
resourceCenter?: ResourceCenterConfig | null;
|
|
32
|
+
/** The visitor's audiences (for audience-targeted articles and collections in the Help tab). */
|
|
33
|
+
audienceIds?: () => ReadonlySet<string> | readonly string[];
|
|
32
34
|
guides?: HelpGuideRef[];
|
|
33
35
|
onStartGuide?: (guideKeyOrId: string) => void;
|
|
34
36
|
onOpenChecklist?: (guideId: string) => void;
|
package/dist/messenger.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createHelpView,
|
|
3
3
|
el
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SGFC66YD.js";
|
|
5
5
|
|
|
6
6
|
// src/messenger-styles.ts
|
|
7
7
|
var MESSENGER_STYLES = `
|
|
@@ -236,6 +236,7 @@ function renderMessenger(options) {
|
|
|
236
236
|
links: options.resourceCenter?.links
|
|
237
237
|
}),
|
|
238
238
|
search: (q) => api.searchArticles(q),
|
|
239
|
+
audienceIds: options.audienceIds,
|
|
239
240
|
loadArticle: (id) => api.getArticle(id),
|
|
240
241
|
onStartGuide: (id) => {
|
|
241
242
|
setOpen(false);
|