@mrrocket/sdk 0.12.0 → 0.14.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +60 -0
  3. package/dist/browser/mrrocket-flows.js +11 -2
  4. package/dist/browser/mrrocket-messenger.js +143 -65
  5. package/dist/browser/mrrocket.js +1 -1
  6. package/dist/browser.d.ts +1 -1
  7. package/dist/browser.js +2 -1
  8. package/dist/browser.js.map +1 -1
  9. package/dist/client.d.ts +12 -0
  10. package/dist/client.js +22 -0
  11. package/dist/client.js.map +1 -1
  12. package/dist/context.d.ts +3 -0
  13. package/dist/context.js.map +1 -1
  14. package/dist/core.d.ts +4 -1
  15. package/dist/core.js +1 -1
  16. package/dist/core.js.map +1 -1
  17. package/dist/flows-ui.d.ts +6 -4
  18. package/dist/flows-ui.js +99 -4
  19. package/dist/flows-ui.js.map +1 -1
  20. package/dist/index.d.ts +2 -1
  21. package/dist/index.js +4 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/messenger-ui.d.ts +22 -0
  24. package/dist/messenger-ui.js +313 -79
  25. package/dist/messenger-ui.js.map +1 -1
  26. package/dist/paywall.d.ts +123 -0
  27. package/dist/paywall.js +131 -0
  28. package/dist/paywall.js.map +1 -0
  29. package/dist/proxy.d.ts +1 -0
  30. package/dist/proxy.js +3 -0
  31. package/dist/proxy.js.map +1 -1
  32. package/dist/react-native/index.d.cts +134 -3
  33. package/dist/react-native/index.d.ts +134 -3
  34. package/dist/react-native/index.js +204 -4
  35. package/dist/react-native/index.js.map +1 -1
  36. package/dist/security.d.ts +71 -0
  37. package/dist/security.js +73 -0
  38. package/dist/security.js.map +1 -0
  39. package/dist/server.d.ts +1 -0
  40. package/dist/server.js +8 -1
  41. package/dist/server.js.map +1 -1
  42. package/dist/styles-css.d.ts +1 -1
  43. package/dist/styles-css.js +141 -63
  44. package/dist/styles-css.js.map +1 -1
  45. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/messenger-ui.ts"],"sourcesContent":["/**\n * The web messenger, after Featurebase's: a round launcher and a panel with three tabs, Home (greeting, the latest\n * chat, help search, top articles), Messages (the chat with the team, answered in MRRocket › Support by the owner or\n * the Customer experience agent) and Help (the product's published help articles, searchable, read in the panel).\n * While the panel is closed it checks for answers now and then; a new answer plays a short sound, shows a count on\n * the launcher and a preview card above it.\n *\n * Plain DOM, no React, so `<Messenger />` (Next.js) and the script tag share it; both load it only when it is used (a\n * dynamic import, and `sdk-messenger.js` for the script tag). Every text is set with textContent; articles arrive as\n * blocks, never HTML.\n */\nimport { type ArticleBlock, type ArticleSpan, type ArticleSummary, type ChatMessage, type ChatThread, type MessengerLook, createApi, inkOn, replyLine } from \"./api-client\";\nimport { injectStyles } from \"./styles-css\";\n\nexport interface MessengerUiOptions {\n host: string;\n apiKey: string;\n /** The visitor id now (it changes on identify and reset). */\n distinctId: () => string;\n /** The signed-in person's id, name and email, when the site called identify. */\n user: () => { id?: string; name?: string; email?: string } | undefined;\n /** Show the round launcher (default true). Without it the panel opens only through `open()`. */\n launcher?: boolean;\n position?: \"bottom-right\" | \"bottom-left\";\n /** The panel's title. */\n title?: string;\n /** The big line on Home and the first line of an empty chat. */\n greeting?: string;\n /** Ask anonymous visitors for an email (optional for them). Default true. */\n askEmail?: boolean;\n /** Text on the launcher; empty shows the icon only. */\n label?: string;\n /** How soon the team usually answers, said under \"Send us a message\" and in the chat's head. */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** The Help tab with the product's published help articles (default true; hidden while there are none). */\n help?: boolean;\n /** A short sound when an answer arrives (default true). */\n sound?: boolean;\n /** A preview of a new answer above the closed launcher (default true). */\n preview?: boolean;\n theme?: \"light\" | \"dark\" | \"auto\";\n accent?: string;\n}\n\nexport type MessengerView = \"home\" | \"messages\" | \"help\";\n\nexport interface MessengerHandle {\n /** Opens the panel, on Home or the given tab; `{ article }` opens a help article. */\n open(view?: MessengerView | { article: string }): void;\n close(): void;\n toggle(): void;\n /** Removes the launcher and the panel from the page. */\n destroy(): void;\n}\n\nconst POLL_OPEN_MS = 4000;\n/** While the panel is closed: soon after the visitor wrote, answers are looked for often, later now and then. */\nconst POLL_WAITING_MS = 8000;\nconst POLL_IDLE_MS = 30000;\nconst WAITING_FOR_MS = 10 * 60_000;\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/;\nconst SEEN_KEY = \"ckw_msgr_seen\";\nconst whoLabel: Record<ChatMessage[\"from\"], string> = { visitor: \"You\", team: \"Team\", ai: \"AI agent\", auto: \"Team\" };\n\nconst readSeen = () => {\n try {\n return window.localStorage.getItem(SEEN_KEY) ?? \"\";\n } catch {\n return \"\";\n }\n};\nconst writeSeen = (id: string) => {\n try {\n window.localStorage.setItem(SEEN_KEY, id);\n } catch {\n // Private mode: the count just shows again next time.\n }\n};\n\nconst timeAgo = (iso: string) => {\n const t = new Date(iso).getTime();\n if (Number.isNaN(t)) return \"\";\n const d = Math.max(0, Date.now() - t) / 1000;\n if (d < 60) return \"just now\";\n if (d < 3600) return `${Math.floor(d / 60)}m ago`;\n if (d < 86400) return `${Math.floor(d / 3600)}h ago`;\n if (d < 86400 * 30) return `${Math.floor(d / 86400)}d ago`;\n return new Date(iso).toLocaleDateString(undefined, { month: \"short\", day: \"numeric\", year: \"numeric\" });\n};\n\nconst el = <K extends keyof HTMLElementTagNameMap>(tag: K, attrs: Record<string, string> = {}, ...kids: (Node | string | null | false | undefined)[]) => {\n const e = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) e.setAttribute(k, v);\n for (const k of kids) if (k !== null && k !== false && k !== undefined) e.append(k);\n return e;\n};\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\nconst icon = (d: string, size = 16) => {\n const svg = document.createElementNS(SVG_NS, \"svg\");\n for (const [k, v] of Object.entries({ class: \"ckw-icon\", width: String(size), height: String(size), viewBox: \"0 0 16 16\", fill: \"none\", stroke: \"currentColor\", \"stroke-width\": \"1.7\", \"stroke-linecap\": \"round\", \"stroke-linejoin\": \"round\", \"aria-hidden\": \"true\" }))\n svg.setAttribute(k, v);\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", d);\n svg.appendChild(path);\n return svg;\n};\nconst I = {\n cross: \"m4 4 8 8M12 4l-8 8\",\n chat: \"M2.5 4.5a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v4.5a2 2 0 0 1-2 2H7l-3 2.5V11a2 2 0 0 1-1.5-2z\",\n send: \"M2.5 8h10M8.5 3.5 13 8l-4.5 4.5\",\n up: \"M8 13V3M3.5 7.5 8 3l4.5 4.5\",\n home: \"M2.5 7 8 2.5 13.5 7v6a1 1 0 0 1-1 1h-3v-4h-3v4h-3a1 1 0 0 1-1-1z\",\n help: \"M8 14.5A6.5 6.5 0 1 0 8 1.5a6.5 6.5 0 0 0 0 13zM6.2 6.2a1.9 1.9 0 1 1 2.6 1.8c-.5.2-.8.6-.8 1.1v.4M8 11.6v.1\",\n back: \"M10 3.5 5.5 8l4.5 4.5\",\n next: \"M6 3.5 10.5 8 6 12.5\",\n search: \"M7 11.5a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9zM10.5 10.5l3 3\",\n doc: \"M4 1.5h5.5l3 3V14a.5.5 0 0 1-.5.5H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5zM9.5 1.5v3h3M6 8.5h4M6 11h4\",\n};\n\n/** A soft two-note chime made with Web Audio (no file to load). Browsers allow it once the visitor has clicked. */\nconst chime = (() => {\n let ctx: AudioContext | null = null;\n const get = () => {\n const AC = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!AC) return null;\n ctx ??= new AC();\n return ctx;\n };\n return {\n /** Call from a click so later sounds may play. */\n unlock: () => {\n try {\n const c = get();\n if (c?.state === \"suspended\") void c.resume();\n } catch {\n // No audio: no sound.\n }\n },\n play: () => {\n try {\n const c = get();\n if (!c || c.state !== \"running\") return;\n const t = c.currentTime;\n [880, 1318.5].forEach((f, i) => {\n const o = c.createOscillator();\n const g = c.createGain();\n const at = t + i * 0.11;\n o.type = \"sine\";\n o.frequency.value = f;\n g.gain.setValueAtTime(0.0001, at);\n g.gain.exponentialRampToValueAtTime(0.12, at + 0.012);\n g.gain.exponentialRampToValueAtTime(0.0001, at + 0.32);\n o.connect(g);\n g.connect(c.destination);\n o.start(at);\n o.stop(at + 0.34);\n });\n } catch {\n // No audio: no sound.\n }\n },\n };\n})();\n\nconst spansOf = (spans: ArticleSpan[]) =>\n spans.map((s) => {\n let node: HTMLElement = s.href ? el(\"a\", { href: s.href, target: \"_blank\", rel: \"noopener noreferrer\" }, s.text) : el(\"span\", {}, s.text);\n if (s.code) node = el(\"code\", {}, node);\n if (s.italic) node = el(\"em\", {}, node);\n if (s.bold) node = el(\"strong\", {}, node);\n return node;\n });\n\nconst blockOf = (b: ArticleBlock): HTMLElement => {\n switch (b.type) {\n case \"h2\":\n case \"h3\":\n return el(b.type, {}, ...spansOf(b.spans));\n case \"quote\":\n return el(\"blockquote\", {}, ...spansOf(b.spans));\n case \"ul\":\n case \"ol\":\n return el(b.type, {}, ...b.items.map((it) => el(\"li\", {}, ...spansOf(it))));\n case \"code\":\n return el(\"pre\", {}, el(\"code\", {}, b.text));\n case \"hr\":\n return el(\"hr\");\n default:\n return el(\"p\", {}, ...spansOf(b.spans));\n }\n};\n\n/** How long the launcher waits for the look from MRRocket before it shows with the code's options and the defaults. */\nconst LOOK_WAIT_MS = 2500;\n\n/**\n * Mounts the messenger with its look from MRRocket (Support › Messenger) underneath what the code passes: an option the\n * code sets wins, one it leaves out comes from MRRocket, then the default. Calls made before the look arrived wait.\n */\nexport const mountMessenger = (o: MessengerUiOptions): MessengerHandle => {\n let real: MessengerHandle | null = null;\n let gone = false;\n const queued: ((h: MessengerHandle) => void)[] = [];\n const later = (fn: (h: MessengerHandle) => void) => (real ? fn(real) : queued.push(fn));\n const ctrl = new AbortController();\n const start = (look: Partial<MessengerLook> | null) => {\n if (real || gone) return;\n const defined = Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as MessengerUiOptions;\n real = build({ ...(look ?? {}), ...defined, accent: o.accent ?? look?.accent, theme: o.theme ?? look?.theme });\n for (const fn of queued.splice(0)) fn(real);\n };\n const timer = setTimeout(() => start(null), LOOK_WAIT_MS);\n createApi({ host: o.host, apiKey: o.apiKey, distinctId: o.distinctId(), user: o.user() })\n .messengerLook(ctrl.signal)\n .then((look) => start(look))\n .catch(() => start(null))\n .finally(() => clearTimeout(timer));\n return {\n open: (v) => later((h) => h.open(v)),\n close: () => real?.close(),\n toggle: () => later((h) => h.toggle()),\n destroy: () => {\n gone = true;\n ctrl.abort();\n clearTimeout(timer);\n real?.destroy();\n },\n };\n};\n\nconst build = (o: MessengerUiOptions): MessengerHandle => {\n injectStyles();\n const position = o.position ?? \"bottom-right\";\n const title = o.title || \"Chat with us\";\n const greeting = o.greeting || \"Hi! How can we help?\";\n const askEmail = o.askEmail ?? true;\n const label = o.label ?? \"\";\n const reply = replyLine(o.replyTime);\n /** The team's mark: the first letter of the title, on the accent. */\n const initial = (title.trim()[0] ?? \"?\").toUpperCase();\n const launcherOn = o.launcher ?? true;\n const helpOn = o.help ?? true;\n const soundOn = o.sound ?? true;\n const previewOn = o.preview ?? true;\n const api = () => createApi({ host: o.host, apiKey: o.apiKey, distinctId: o.distinctId(), user: o.user() });\n\n const root = el(\"div\", { class: \"ckw-root\", \"data-theme\": o.theme ?? \"auto\" });\n if (o.accent) {\n root.style.setProperty(\"--ckw-accent\", o.accent);\n root.style.setProperty(\"--ckw-accent-ink\", inkOn(o.accent));\n }\n document.body.appendChild(root);\n\n let open = false;\n let view: MessengerView | { article: string } = \"home\";\n let thread: ChatThread | null = null;\n let loaded = false;\n let error = \"\";\n let pending: ChatMessage | null = null;\n /** The newest team message seen in this page load: what counts as new after it. */\n let lastKnown: string | null = null;\n let unseen: ChatMessage[] = [];\n let previewGone = false;\n let poll: ReturnType<typeof setTimeout> | undefined;\n let ctrl: AbortController | null = null;\n let articles: ArticleSummary[] | null = null;\n let query = \"\";\n let rated = new Set<string>();\n /** Whether the product has any published article: the Help tab and Home's help card hide when it has none. */\n let hasArticles: boolean | null = null;\n\n const teamMsgs = (t: ChatThread | null) => (t?.messages ?? []).filter((m) => m.from !== \"visitor\");\n const lastTeamId = (t: ChatThread | null) => teamMsgs(t).at(-1)?.id ?? \"\";\n const watching = () => open && view === \"messages\" && document.visibilityState !== \"hidden\";\n\n /** Takes a thread from the server: new answers count, chime and show in the preview. */\n const take = (t: ChatThread) => {\n const team = teamMsgs(t);\n if (lastKnown === null) {\n // First read: answers the visitor never saw in an earlier visit count, without a sound.\n const seen = readSeen();\n const i = team.findIndex((m) => m.id === seen);\n unseen = t.messages.some((m) => m.from === \"visitor\") ? team.slice(i + 1).filter((m) => m.from !== \"auto\") : [];\n } else {\n const i = team.findIndex((m) => m.id === lastKnown);\n const fresh = team.slice(i + 1).filter((m) => m.from !== \"auto\");\n if (fresh.length) {\n if (soundOn) chime.play();\n if (!watching()) {\n unseen = [...unseen, ...fresh];\n previewGone = false;\n }\n }\n }\n lastKnown = lastTeamId(t);\n thread = t;\n if (watching()) markSeen();\n };\n const markSeen = () => {\n unseen = [];\n const id = lastTeamId(thread);\n if (id) writeSeen(id);\n };\n\n const avatar = (size?: \"sm\") => el(\"span\", { class: `ckw-msgr-av${size ? \" ckw-msgr-av-sm\" : \"\"}`, \"aria-hidden\": \"true\" }, initial);\n\n // ---------- Launcher and preview ----------\n const fab = el(\"button\", { type: \"button\", class: `ckw-fab ckw-msgr-fab${label ? \"\" : \" ckw-msgr-round\"}`, \"data-pos\": position, \"aria-haspopup\": \"dialog\" });\n const prev = el(\"div\", { class: \"ckw-msgr-preview\", \"data-pos\": position, role: \"status\" });\n /** The open state the launcher's icon last showed: the icon turns only when it changes, not on every read. */\n let fabShows: boolean | null = null;\n const drawFab = () => {\n const glyph = icon(open ? I.cross : I.chat, label ? 18 : 24);\n if (fabShows !== null && fabShows !== open) glyph.classList.add(\"ckw-turn\");\n fabShows = open;\n fab.replaceChildren(glyph);\n if (label) fab.append(el(\"span\", {}, label));\n if (unseen.length && !open) fab.append(el(\"span\", { class: \"ckw-msgr-count\", \"aria-hidden\": \"true\" }, String(Math.min(unseen.length, 9))));\n fab.setAttribute(\"aria-expanded\", String(open));\n fab.setAttribute(\"aria-label\", open ? \"Close chat\" : unseen.length ? `Open chat, ${unseen.length} new ${unseen.length === 1 ? \"reply\" : \"replies\"}` : \"Open chat\");\n drawPreview();\n };\n const drawPreview = () => {\n const m = unseen.at(-1);\n if (!previewOn || open || previewGone || !m || !launcherOn) return prev.remove();\n const x = el(\"button\", { type: \"button\", class: \"ckw-msgr-preview-x\", \"aria-label\": \"Dismiss\" }, icon(I.cross, 12));\n x.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n previewGone = true;\n drawPreview();\n });\n const card = el(\n \"button\",\n { type: \"button\", class: \"ckw-msgr-preview-card\" },\n avatar(),\n el(\n \"span\",\n { class: \"ckw-msgr-preview-main\" },\n el(\"span\", { class: \"ckw-msgr-preview-who\" }, `${whoLabel[m.from]}${unseen.length > 1 ? ` · ${unseen.length} new` : \"\"}`),\n el(\"span\", { class: \"ckw-msgr-preview-text\" }, m.body),\n ),\n );\n card.addEventListener(\"click\", () => show(\"messages\"));\n prev.replaceChildren(card, x);\n if (!prev.isConnected) root.appendChild(prev);\n };\n fab.addEventListener(\"click\", () => {\n chime.unlock();\n if (open) close();\n else show(unseen.length ? \"messages\" : \"home\");\n });\n if (launcherOn) root.appendChild(fab);\n\n // ---------- Panel ----------\n const pop = el(\"div\", { class: \"ckw-pop ckw-msgr\", \"data-pos\": position, role: \"dialog\", \"aria-label\": title });\n const head = el(\"div\", { class: \"ckw-pop-head ckw-msgr-head\" });\n const body = el(\"div\", { class: \"ckw-pop-body ckw-msgr-body\" });\n const tabs = el(\"nav\", { class: \"ckw-msgr-tabs\", \"aria-label\": \"Messenger\" });\n pop.addEventListener(\"click\", () => chime.unlock());\n\n // The chat's compose form keeps its elements between draws, so the field never loses the focus.\n const form = el(\"form\", { class: \"ckw-msgr-compose\" });\n const err = el(\"p\", { class: \"ckw-msgr-error\", role: \"alert\" });\n const email = el(\"input\", { class: \"ckw-input\", type: \"email\", inputmode: \"email\", autocomplete: \"email\", placeholder: \"Your email (optional), so we can follow up\", \"aria-label\": \"Your email (optional)\", maxlength: \"200\" });\n const row = el(\"div\", { class: \"ckw-msgr-row\" });\n const text = el(\"textarea\", { class: \"ckw-textarea ckw-msgr-input\", rows: \"1\", placeholder: \"Write a message…\", \"aria-label\": \"Message\", maxlength: \"4000\" });\n const send = el(\"button\", { type: \"submit\", class: \"ckw-msgr-send\", \"aria-label\": \"Send\" }, icon(I.up));\n row.append(text, send);\n form.append(row);\n\n const list = el(\"ol\", { class: \"ckw-msgs\", \"aria-live\": \"polite\", \"aria-label\": \"Messages\" });\n const needEmail = () => askEmail && !o.user()?.email && !thread?.hasEmail;\n const emailOk = () => !email.value.trim() || EMAIL.test(email.value.trim());\n const canSend = () => !!text.value.trim() && !pending && emailOk();\n\n const closeBtn = () => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-btn ckw-btn-ghost ckw-msgr-x\", \"aria-label\": \"Close messenger\" }, icon(I.cross));\n b.addEventListener(\"click\", () => close());\n return b;\n };\n const go = (v: MessengerView | { article: string }) => {\n view = v;\n drawn = -1;\n draw();\n if (v === \"messages\") {\n markSeen();\n drawFab();\n text.focus();\n } else if (v === \"help\") helpInput.focus();\n schedule(0);\n };\n\n const bubble = (m: ChatMessage, isPending = false) => {\n const li = el(\"li\", { class: \"ckw-msg\", \"data-from\": m.from === \"visitor\" ? \"me\" : \"them\" }, el(\"div\", { class: \"ckw-bubble\" }, m.body));\n if (isPending) li.setAttribute(\"aria-busy\", \"true\");\n for (const a of m.articles ?? []) {\n const chip = el(\"button\", { type: \"button\", class: \"ckw-msgr-cite\" }, icon(I.doc, 14), el(\"span\", {}, a.title));\n chip.addEventListener(\"click\", () => go({ article: a.id }));\n li.append(chip);\n }\n li.append(el(\"span\", { class: \"ckw-msg-meta\" }, `${m.from !== \"visitor\" ? `${whoLabel[m.from]} · ` : \"\"}${isPending ? \"Sending…\" : timeAgo(m.at)}`));\n return li;\n };\n\n const articleRow = (a: ArticleSummary) => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-msgr-art\" }, el(\"span\", { class: \"ckw-msgr-art-t\" }, a.title), icon(I.next, 14));\n b.addEventListener(\"click\", () => go({ article: a.id }));\n return b;\n };\n\n const searchBox = () => {\n const wrap = el(\"label\", { class: \"ckw-msgr-search\" });\n const input = el(\"input\", { class: \"ckw-msgr-search-in\", type: \"search\", placeholder: \"Search for help\", \"aria-label\": \"Search for help\", maxlength: \"200\" });\n input.value = query;\n let t: ReturnType<typeof setTimeout> | undefined;\n input.addEventListener(\"input\", () => {\n query = input.value;\n clearTimeout(t);\n t = setTimeout(() => {\n if (view !== \"help\") return go(\"help\");\n void loadArticles(true);\n }, 250);\n });\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n if (view !== \"help\") go(\"help\");\n }\n });\n wrap.append(input, icon(I.search, 16));\n return wrap;\n };\n // Help's own field stays the same element between draws, so typing never loses the cursor.\n const helpSearch = searchBox();\n const helpInput = helpSearch.querySelector(\"input\")!;\n\n let loadingArticles = false;\n const loadArticles = async (force = false) => {\n if (!helpOn || (loadingArticles && !force)) return;\n loadingArticles = true;\n const q = query.trim();\n try {\n const r = await api().articles(q || undefined);\n if (q !== query.trim()) return;\n articles = r.articles;\n if (!q) hasArticles = r.articles.length > 0;\n } catch {\n articles = articles ?? [];\n } finally {\n loadingArticles = false;\n }\n draw();\n };\n const drawHome = () => {\n head.replaceChildren(el(\"span\", { class: \"ckw-msgr-brand\" }, avatar(\"sm\"), el(\"span\", {}, title)), closeBtn());\n const hero = el(\"div\", { class: \"ckw-msgr-hero\" }, el(\"p\", { class: \"ckw-msgr-hello\" }, greeting));\n const last = (thread?.messages ?? []).at(-1);\n const parts: HTMLElement[] = [hero];\n if (last) {\n const recent = el(\n \"button\",\n { type: \"button\", class: \"ckw-msgr-card ckw-msgr-recent\" },\n el(\"span\", { class: \"ckw-msgr-card-label\" }, \"Recent message\"),\n el(\n \"span\",\n { class: \"ckw-msgr-recent-row\" },\n avatar(),\n el(\n \"span\",\n { class: \"ckw-msgr-card-main\" },\n el(\"span\", { class: \"ckw-msgr-card-sub ckw-msgr-recent-text\" }, last.body),\n el(\"span\", { class: \"ckw-msgr-card-meta\" }, `${last.from === \"visitor\" ? \"You\" : whoLabel[last.from]} · ${timeAgo(last.at)}`),\n ),\n unseen.length ? el(\"span\", { class: \"ckw-msgr-badge\" }, String(unseen.length)) : icon(I.next, 14),\n ),\n );\n recent.addEventListener(\"click\", () => go(\"messages\"));\n parts.push(recent);\n }\n const msgCard = el(\n \"button\",\n { type: \"button\", class: \"ckw-msgr-card\" },\n el(\"span\", { class: \"ckw-msgr-card-main\" }, el(\"b\", {}, \"Send us a message\"), el(\"span\", { class: \"ckw-msgr-card-sub\" }, reply)),\n el(\"span\", { class: \"ckw-msgr-go\" }, icon(I.send)),\n );\n msgCard.addEventListener(\"click\", () => go(\"messages\"));\n parts.push(msgCard);\n if (helpOn && hasArticles !== false) {\n const helpCard = el(\"div\", { class: \"ckw-msgr-card ckw-msgr-card-col\" }, searchBox());\n const top = (articles ?? []).slice(0, 4);\n if (top.length) helpCard.append(...top.map(articleRow));\n else if (articles === null) helpCard.append(el(\"div\", { class: \"ckw-skel ckw-msgr-skel\" }));\n parts.push(helpCard);\n }\n body.replaceChildren(...parts);\n };\n\n const drawHelp = () => {\n head.replaceChildren(el(\"span\", {}, \"Help\"), closeBtn());\n if (helpInput.value !== query) helpInput.value = query;\n const parts: HTMLElement[] = [helpSearch];\n if (articles === null) parts.push(el(\"div\", { class: \"ckw-skel\" }));\n else if (!articles.length) {\n const ask = el(\"button\", { type: \"button\", class: \"ckw-btn ckw-btn-primary\" }, \"Send us a message\");\n ask.addEventListener(\"click\", () => go(\"messages\"));\n parts.push(el(\"div\", { class: \"ckw-msgr-empty\" }, el(\"p\", {}, query.trim() ? `Nothing found for “${query.trim()}”.` : \"No help articles yet.\"), ask));\n } else if (query.trim()) parts.push(el(\"div\", { class: \"ckw-msgr-card ckw-msgr-card-col\" }, ...articles.map(articleRow)));\n else {\n const groups = new Map<string, ArticleSummary[]>();\n for (const a of articles) groups.set(a.collection, [...(groups.get(a.collection) ?? []), a]);\n for (const [name, items] of groups)\n parts.push(el(\"section\", { class: \"ckw-msgr-group\" }, el(\"h3\", { class: \"ckw-msgr-group-h\" }, `${name} · ${items.length}`), el(\"div\", { class: \"ckw-msgr-card ckw-msgr-card-col\" }, ...items.map(articleRow))));\n }\n // The field stays in place (moving it would take its focus); only what is under it changes.\n if (body.firstChild !== helpSearch) body.replaceChildren(helpSearch);\n while (body.childNodes.length > 1) body.lastChild!.remove();\n body.append(...parts.slice(1));\n };\n\n let articleShown: { id: string; node: HTMLElement } | null = null;\n const drawArticle = (id: string) => {\n const back = el(\"button\", { type: \"button\", class: \"ckw-btn ckw-btn-ghost ckw-msgr-x\", \"aria-label\": \"Back to help\" }, icon(I.back));\n back.addEventListener(\"click\", () => go(\"help\"));\n head.replaceChildren(back, el(\"span\", { class: \"ckw-msgr-head-t\" }, \"Help\"), closeBtn());\n if (articleShown?.id === id) return body.replaceChildren(articleShown.node);\n const node = el(\"article\", { class: \"ckw-msgr-doc\" }, el(\"div\", { class: \"ckw-skel\" }));\n articleShown = { id, node };\n body.replaceChildren(node);\n api()\n .article(id)\n .then((a) => {\n const foot = el(\"div\", { class: \"ckw-msgr-rate\" });\n const drawRate = () => {\n if (rated.has(id)) return foot.replaceChildren(el(\"span\", {}, \"Thanks for letting us know.\"));\n const yes = el(\"button\", { type: \"button\", class: \"ckw-btn\" }, \"Yes\");\n const no = el(\"button\", { type: \"button\", class: \"ckw-btn\" }, \"No\");\n const rate = (helpful: boolean) => {\n rated = new Set(rated).add(id);\n drawRate();\n api()\n .rateArticle(id, helpful)\n .catch(() => undefined);\n if (!helpful) go(\"messages\");\n };\n yes.addEventListener(\"click\", () => rate(true));\n no.addEventListener(\"click\", () => rate(false));\n foot.replaceChildren(el(\"span\", {}, \"Did this answer your question?\"), el(\"span\", { class: \"ckw-msgr-rate-b\" }, yes, no));\n };\n drawRate();\n const ask = el(\"button\", { type: \"button\", class: \"ckw-btn ckw-msgr-ask\" }, icon(I.chat), \"Still need help? Send us a message\");\n ask.addEventListener(\"click\", () => go(\"messages\"));\n node.replaceChildren(\n el(\"p\", { class: \"ckw-msgr-doc-c\" }, a.collection),\n el(\"h2\", { class: \"ckw-msgr-doc-t\" }, a.title),\n el(\"p\", { class: \"ckw-msgr-doc-c\" }, `Updated ${timeAgo(a.updatedAt)}`),\n el(\"div\", { class: \"ckw-msgr-doc-b\" }, ...a.blocks.map(blockOf)),\n foot,\n ask,\n );\n })\n .catch((e: Error) => {\n articleShown = null;\n node.replaceChildren(el(\"p\", { class: \"ckw-msgr-error\" }, e.message));\n });\n };\n\n let drawn = -1;\n /** What the list shows, so a read that brings nothing new leaves it alone (no flicker, links stay where they are). */\n let listSig = \"\";\n const drawMessages = () => {\n head.replaceChildren(\n el(\"span\", { class: \"ckw-msgr-who\" }, avatar(), el(\"span\", { class: \"ckw-msgr-who-t\" }, el(\"b\", {}, title), el(\"span\", {}, reply))),\n closeBtn(),\n );\n const msgs = thread?.messages ?? [];\n const parts: HTMLElement[] = [];\n if (!loaded) parts.push(el(\"div\", { class: \"ckw-skel\" }));\n else {\n const sig = `${msgs.map((m) => m.id).join(\",\")}|${pending ? pending.body : \"\"}|${Math.floor(Date.now() / 60_000)}`;\n if (sig !== listSig) {\n listSig = sig;\n const greet = el(\"li\", { class: \"ckw-msg\", \"data-from\": \"them\" }, el(\"div\", { class: \"ckw-bubble\" }, greeting));\n list.replaceChildren(greet, ...msgs.map((m) => bubble(m)), ...(pending ? [bubble(pending, true)] : []));\n }\n parts.push(list);\n }\n if (thread?.conversation?.status === \"solved\" && !pending) parts.push(el(\"p\", { class: \"ckw-fine ckw-msgr-note\" }, \"This conversation is closed. Write to start a new one.\"));\n if (body.childNodes.length !== parts.length || parts.some((x, i) => body.childNodes[i] !== x)) body.replaceChildren(...parts);\n const count = msgs.length + (pending ? 1 : 0);\n if (count !== drawn) {\n drawn = count;\n body.scrollTop = body.scrollHeight;\n }\n err.textContent = error;\n if (error && !err.isConnected) form.prepend(err);\n else if (!error) err.remove();\n if (needEmail()) {\n if (emailOk()) email.removeAttribute(\"aria-invalid\");\n else email.setAttribute(\"aria-invalid\", \"true\");\n if (!email.isConnected) form.insertBefore(email, row);\n } else email.remove();\n send.disabled = !canSend();\n };\n\n const drawTabs = () => {\n const current = typeof view === \"string\" ? view : \"help\";\n const tab = (v: MessengerView, name: string, d: string, badge = 0) => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-msgr-tab\", \"aria-current\": current === v ? \"page\" : \"false\" }, icon(d, 18), el(\"span\", {}, name));\n if (badge) b.append(el(\"span\", { class: \"ckw-msgr-count ckw-msgr-count-tab\" }, String(Math.min(badge, 9))));\n b.addEventListener(\"click\", () => go(v));\n return b;\n };\n tabs.replaceChildren(tab(\"home\", \"Home\", I.home), tab(\"messages\", \"Messages\", I.chat, view === \"messages\" ? 0 : unseen.length), ...(helpOn && hasArticles !== false ? [tab(\"help\", \"Help\", I.help)] : []));\n };\n\n const draw = () => {\n if (!open) return;\n pop.dataset.view = typeof view === \"string\" ? view : \"article\";\n if (view === \"home\") drawHome();\n else if (view === \"messages\") drawMessages();\n else if (view === \"help\") drawHelp();\n else drawArticle(view.article);\n const kids: HTMLElement[] = [head, body];\n if (view === \"messages\") kids.push(form);\n kids.push(tabs);\n drawTabs();\n if (pop.childNodes.length !== kids.length || kids.some((k, i) => pop.childNodes[i] !== k)) pop.replaceChildren(...kids);\n };\n\n // ---------- Reading the chat ----------\n const tick = async () => {\n ctrl?.abort();\n ctrl = new AbortController();\n try {\n take(await api().chat(ctrl.signal));\n error = \"\";\n } catch (e) {\n if ((e as Error).name === \"AbortError\") return;\n if (open && view === \"messages\") error = (e as Error).message;\n }\n loaded = true;\n draw();\n drawFab();\n schedule();\n };\n /** The next read: often while the chat is on screen, now and then while the visitor waits for an answer. */\n function schedule(now?: number) {\n clearTimeout(poll);\n const waiting = !!thread?.messages.some((m) => m.from === \"visitor\") && thread?.conversation?.status !== \"solved\";\n const wrote = (thread?.messages ?? []).filter((m) => m.from === \"visitor\").at(-1)?.at;\n const recent = !!wrote && Date.now() - new Date(wrote).getTime() < WAITING_FOR_MS;\n const ms = now ?? (watching() ? POLL_OPEN_MS : waiting && recent ? POLL_WAITING_MS : open || waiting ? POLL_IDLE_MS : 0);\n if (ms || now === 0) poll = setTimeout(() => void tick(), ms);\n }\n document.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"visible\") schedule(0);\n else clearTimeout(poll);\n });\n\n const submit = async () => {\n const msg = text.value.trim();\n if (!msg || pending || !emailOk()) return;\n chime.unlock();\n pending = { id: \"pending\", from: \"visitor\", body: msg, at: new Date().toISOString() };\n text.value = \"\";\n error = \"\";\n draw();\n try {\n take(await api().sendChat({ body: msg, email: needEmail() && email.value.trim() ? email.value.trim() : undefined, url: window.location.href.slice(0, 500) }));\n } catch (e) {\n text.value = msg;\n error = (e as Error).message;\n }\n pending = null;\n draw();\n schedule();\n };\n form.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n void submit();\n });\n text.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey && !e.isComposing) {\n e.preventDefault();\n void submit();\n }\n });\n text.addEventListener(\"input\", () => (send.disabled = !canSend()));\n email.addEventListener(\"input\", () => draw());\n\n function show(v: MessengerView | { article: string } = \"home\") {\n open = true;\n view = v === \"help\" && !helpOn ? \"home\" : v;\n drawn = -1;\n previewGone = true;\n if (!pop.isConnected) root.appendChild(pop);\n if (articles === null || (view === \"help\" && query)) void loadArticles();\n draw();\n drawFab();\n if (view === \"messages\") {\n markSeen();\n text.focus();\n }\n schedule(0);\n }\n function close() {\n if (!open) return;\n open = false;\n pop.remove();\n drawFab();\n schedule();\n if (launcherOn) fab.focus();\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && open) close();\n };\n document.addEventListener(\"keydown\", onKey);\n\n // One read on load (the count and preview of answers not seen yet), and the article count for the Help tab.\n void tick();\n if (helpOn) void loadArticles();\n drawFab();\n\n return {\n open: (v) => show(v ?? \"home\"),\n close,\n toggle: () => (open ? close() : show()),\n destroy: () => {\n clearTimeout(poll);\n ctrl?.abort();\n document.removeEventListener(\"keydown\", onKey);\n root.remove();\n },\n };\n};\n"],"mappings":";AAWA,SAA0H,WAAW,OAAO,iBAAiB;AAC7J,SAAS,oBAAoB;AA2C7B,IAAM,eAAe;AAErB,IAAM,kBAAkB;AACxB,IAAM,eAAe;AACrB,IAAM,iBAAiB,KAAK;AAC5B,IAAM,QAAQ;AACd,IAAM,WAAW;AACjB,IAAM,WAAgD,EAAE,SAAS,OAAO,MAAM,QAAQ,IAAI,YAAY,MAAM,OAAO;AAEnH,IAAM,WAAW,MAAM;AACnB,MAAI;AACA,WAAO,OAAO,aAAa,QAAQ,QAAQ,KAAK;AAAA,EACpD,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AACA,IAAM,YAAY,CAAC,OAAe;AAC9B,MAAI;AACA,WAAO,aAAa,QAAQ,UAAU,EAAE;AAAA,EAC5C,QAAQ;AAAA,EAER;AACJ;AAEA,IAAM,UAAU,CAAC,QAAgB;AAC7B,QAAM,IAAI,IAAI,KAAK,GAAG,EAAE,QAAQ;AAChC,MAAI,OAAO,MAAM,CAAC,EAAG,QAAO;AAC5B,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,IAAI;AACxC,MAAI,IAAI,GAAI,QAAO;AACnB,MAAI,IAAI,KAAM,QAAO,GAAG,KAAK,MAAM,IAAI,EAAE,CAAC;AAC1C,MAAI,IAAI,MAAO,QAAO,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC;AAC7C,MAAI,IAAI,QAAQ,GAAI,QAAO,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC;AACnD,SAAO,IAAI,KAAK,GAAG,EAAE,mBAAmB,QAAW,EAAE,OAAO,SAAS,KAAK,WAAW,MAAM,UAAU,CAAC;AAC1G;AAEA,IAAM,KAAK,CAAwC,KAAQ,QAAgC,CAAC,MAAM,SAAuD;AACrJ,QAAM,IAAI,SAAS,cAAc,GAAG;AACpC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,EAAG,GAAE,aAAa,GAAG,CAAC;AAC/D,aAAW,KAAK,KAAM,KAAI,MAAM,QAAQ,MAAM,SAAS,MAAM,OAAW,GAAE,OAAO,CAAC;AAClF,SAAO;AACX;AAEA,IAAM,SAAS;AACf,IAAM,OAAO,CAAC,GAAW,OAAO,OAAO;AACnC,QAAM,MAAM,SAAS,gBAAgB,QAAQ,KAAK;AAClD,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,EAAE,OAAO,YAAY,OAAO,OAAO,IAAI,GAAG,QAAQ,OAAO,IAAI,GAAG,SAAS,aAAa,MAAM,QAAQ,QAAQ,gBAAgB,gBAAgB,OAAO,kBAAkB,SAAS,mBAAmB,SAAS,eAAe,OAAO,CAAC;AACjQ,QAAI,aAAa,GAAG,CAAC;AACzB,QAAM,OAAO,SAAS,gBAAgB,QAAQ,MAAM;AACpD,OAAK,aAAa,KAAK,CAAC;AACxB,MAAI,YAAY,IAAI;AACpB,SAAO;AACX;AACA,IAAM,IAAI;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AACT;AAGA,IAAM,QAAS,uBAAM;AACjB,MAAI,MAA2B;AAC/B,QAAM,MAAM,MAAM;AACd,UAAM,KAAK,OAAO,gBAAiB,OAAmE;AACtG,QAAI,CAAC,GAAI,QAAO;AAChB,YAAQ,IAAI,GAAG;AACf,WAAO;AAAA,EACX;AACA,SAAO;AAAA;AAAA,IAEH,QAAQ,MAAM;AACV,UAAI;AACA,cAAM,IAAI,IAAI;AACd,YAAI,GAAG,UAAU,YAAa,MAAK,EAAE,OAAO;AAAA,MAChD,QAAQ;AAAA,MAER;AAAA,IACJ;AAAA,IACA,MAAM,MAAM;AACR,UAAI;AACA,cAAM,IAAI,IAAI;AACd,YAAI,CAAC,KAAK,EAAE,UAAU,UAAW;AACjC,cAAM,IAAI,EAAE;AACZ,SAAC,KAAK,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM;AAC5B,gBAAM,IAAI,EAAE,iBAAiB;AAC7B,gBAAM,IAAI,EAAE,WAAW;AACvB,gBAAM,KAAK,IAAI,IAAI;AACnB,YAAE,OAAO;AACT,YAAE,UAAU,QAAQ;AACpB,YAAE,KAAK,eAAe,MAAQ,EAAE;AAChC,YAAE,KAAK,6BAA6B,MAAM,KAAK,KAAK;AACpD,YAAE,KAAK,6BAA6B,MAAQ,KAAK,IAAI;AACrD,YAAE,QAAQ,CAAC;AACX,YAAE,QAAQ,EAAE,WAAW;AACvB,YAAE,MAAM,EAAE;AACV,YAAE,KAAK,KAAK,IAAI;AAAA,QACpB,CAAC;AAAA,MACL,QAAQ;AAAA,MAER;AAAA,IACJ;AAAA,EACJ;AACJ,GAAG;AAEH,IAAM,UAAU,CAAC,UACb,MAAM,IAAI,CAAC,MAAM;AACb,MAAI,OAAoB,EAAE,OAAO,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,UAAU,KAAK,sBAAsB,GAAG,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI;AACxI,MAAI,EAAE,KAAM,QAAO,GAAG,QAAQ,CAAC,GAAG,IAAI;AACtC,MAAI,EAAE,OAAQ,QAAO,GAAG,MAAM,CAAC,GAAG,IAAI;AACtC,MAAI,EAAE,KAAM,QAAO,GAAG,UAAU,CAAC,GAAG,IAAI;AACxC,SAAO;AACX,CAAC;AAEL,IAAM,UAAU,CAAC,MAAiC;AAC9C,UAAQ,EAAE,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACD,aAAO,GAAG,EAAE,MAAM,CAAC,GAAG,GAAG,QAAQ,EAAE,KAAK,CAAC;AAAA,IAC7C,KAAK;AACD,aAAO,GAAG,cAAc,CAAC,GAAG,GAAG,QAAQ,EAAE,KAAK,CAAC;AAAA,IACnD,KAAK;AAAA,IACL,KAAK;AACD,aAAO,GAAG,EAAE,MAAM,CAAC,GAAG,GAAG,EAAE,MAAM,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC;AAAA,IAC9E,KAAK;AACD,aAAO,GAAG,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;AAAA,IAC/C,KAAK;AACD,aAAO,GAAG,IAAI;AAAA,IAClB;AACI,aAAO,GAAG,KAAK,CAAC,GAAG,GAAG,QAAQ,EAAE,KAAK,CAAC;AAAA,EAC9C;AACJ;AAGA,IAAM,eAAe;AAMd,IAAM,iBAAiB,CAAC,MAA2C;AACtE,MAAI,OAA+B;AACnC,MAAI,OAAO;AACX,QAAM,SAA2C,CAAC;AAClD,QAAM,QAAQ,CAAC,OAAsC,OAAO,GAAG,IAAI,IAAI,OAAO,KAAK,EAAE;AACrF,QAAM,OAAO,IAAI,gBAAgB;AACjC,QAAM,QAAQ,CAAC,SAAwC;AACnD,QAAI,QAAQ,KAAM;AAClB,UAAM,UAAU,OAAO,YAAY,OAAO,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAS,CAAC;AACvF,WAAO,MAAM,EAAE,GAAI,QAAQ,CAAC,GAAI,GAAG,SAAS,QAAQ,EAAE,UAAU,MAAM,QAAQ,OAAO,EAAE,SAAS,MAAM,MAAM,CAAC;AAC7G,eAAW,MAAM,OAAO,OAAO,CAAC,EAAG,IAAG,IAAI;AAAA,EAC9C;AACA,QAAM,QAAQ,WAAW,MAAM,MAAM,IAAI,GAAG,YAAY;AACxD,YAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,QAAQ,YAAY,EAAE,WAAW,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EACnF,cAAc,KAAK,MAAM,EACzB,KAAK,CAAC,SAAS,MAAM,IAAI,CAAC,EAC1B,MAAM,MAAM,MAAM,IAAI,CAAC,EACvB,QAAQ,MAAM,aAAa,KAAK,CAAC;AACtC,SAAO;AAAA,IACH,MAAM,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAAA,IACnC,OAAO,MAAM,MAAM,MAAM;AAAA,IACzB,QAAQ,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,IACrC,SAAS,MAAM;AACX,aAAO;AACP,WAAK,MAAM;AACX,mBAAa,KAAK;AAClB,YAAM,QAAQ;AAAA,IAClB;AAAA,EACJ;AACJ;AAEA,IAAM,QAAQ,CAAC,MAA2C;AACtD,eAAa;AACb,QAAM,WAAW,EAAE,YAAY;AAC/B,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,WAAW,EAAE,YAAY;AAC/B,QAAM,WAAW,EAAE,YAAY;AAC/B,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,QAAQ,UAAU,EAAE,SAAS;AAEnC,QAAM,WAAW,MAAM,KAAK,EAAE,CAAC,KAAK,KAAK,YAAY;AACrD,QAAM,aAAa,EAAE,YAAY;AACjC,QAAM,SAAS,EAAE,QAAQ;AACzB,QAAM,UAAU,EAAE,SAAS;AAC3B,QAAM,YAAY,EAAE,WAAW;AAC/B,QAAM,MAAM,MAAM,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,QAAQ,YAAY,EAAE,WAAW,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC;AAE1G,QAAM,OAAO,GAAG,OAAO,EAAE,OAAO,YAAY,cAAc,EAAE,SAAS,OAAO,CAAC;AAC7E,MAAI,EAAE,QAAQ;AACV,SAAK,MAAM,YAAY,gBAAgB,EAAE,MAAM;AAC/C,SAAK,MAAM,YAAY,oBAAoB,MAAM,EAAE,MAAM,CAAC;AAAA,EAC9D;AACA,WAAS,KAAK,YAAY,IAAI;AAE9B,MAAI,OAAO;AACX,MAAI,OAA4C;AAChD,MAAI,SAA4B;AAChC,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,UAA8B;AAElC,MAAI,YAA2B;AAC/B,MAAI,SAAwB,CAAC;AAC7B,MAAI,cAAc;AAClB,MAAI;AACJ,MAAI,OAA+B;AACnC,MAAI,WAAoC;AACxC,MAAI,QAAQ;AACZ,MAAI,QAAQ,oBAAI,IAAY;AAE5B,MAAI,cAA8B;AAElC,QAAM,WAAW,CAAC,OAA0B,GAAG,YAAY,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS;AACjG,QAAM,aAAa,CAAC,MAAyB,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM;AACvE,QAAM,WAAW,MAAM,QAAQ,SAAS,cAAc,SAAS,oBAAoB;AAGnF,QAAM,OAAO,CAAC,MAAkB;AAC5B,UAAM,OAAO,SAAS,CAAC;AACvB,QAAI,cAAc,MAAM;AAEpB,YAAM,OAAO,SAAS;AACtB,YAAM,IAAI,KAAK,UAAU,CAAC,MAAM,EAAE,OAAO,IAAI;AAC7C,eAAS,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS,IAAI,KAAK,MAAM,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,IAAI,CAAC;AAAA,IAClH,OAAO;AACH,YAAM,IAAI,KAAK,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS;AAClD,YAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AAC/D,UAAI,MAAM,QAAQ;AACd,YAAI,QAAS,OAAM,KAAK;AACxB,YAAI,CAAC,SAAS,GAAG;AACb,mBAAS,CAAC,GAAG,QAAQ,GAAG,KAAK;AAC7B,wBAAc;AAAA,QAClB;AAAA,MACJ;AAAA,IACJ;AACA,gBAAY,WAAW,CAAC;AACxB,aAAS;AACT,QAAI,SAAS,EAAG,UAAS;AAAA,EAC7B;AACA,QAAM,WAAW,MAAM;AACnB,aAAS,CAAC;AACV,UAAM,KAAK,WAAW,MAAM;AAC5B,QAAI,GAAI,WAAU,EAAE;AAAA,EACxB;AAEA,QAAM,SAAS,CAAC,SAAgB,GAAG,QAAQ,EAAE,OAAO,cAAc,OAAO,oBAAoB,EAAE,IAAI,eAAe,OAAO,GAAG,OAAO;AAGnI,QAAM,MAAM,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,uBAAuB,QAAQ,KAAK,iBAAiB,IAAI,YAAY,UAAU,iBAAiB,SAAS,CAAC;AAC5J,QAAM,OAAO,GAAG,OAAO,EAAE,OAAO,oBAAoB,YAAY,UAAU,MAAM,SAAS,CAAC;AAE1F,MAAI,WAA2B;AAC/B,QAAM,UAAU,MAAM;AAClB,UAAM,QAAQ,KAAK,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,KAAK,EAAE;AAC3D,QAAI,aAAa,QAAQ,aAAa,KAAM,OAAM,UAAU,IAAI,UAAU;AAC1E,eAAW;AACX,QAAI,gBAAgB,KAAK;AACzB,QAAI,MAAO,KAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC;AAC3C,QAAI,OAAO,UAAU,CAAC,KAAM,KAAI,OAAO,GAAG,QAAQ,EAAE,OAAO,kBAAkB,eAAe,OAAO,GAAG,OAAO,KAAK,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzI,QAAI,aAAa,iBAAiB,OAAO,IAAI,CAAC;AAC9C,QAAI,aAAa,cAAc,OAAO,eAAe,OAAO,SAAS,cAAc,OAAO,MAAM,QAAQ,OAAO,WAAW,IAAI,UAAU,SAAS,KAAK,WAAW;AACjK,gBAAY;AAAA,EAChB;AACA,QAAM,cAAc,MAAM;AACtB,UAAM,IAAI,OAAO,GAAG,EAAE;AACtB,QAAI,CAAC,aAAa,QAAQ,eAAe,CAAC,KAAK,CAAC,WAAY,QAAO,KAAK,OAAO;AAC/E,UAAM,IAAI,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,sBAAsB,cAAc,UAAU,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC;AAClH,MAAE,iBAAiB,SAAS,CAAC,MAAM;AAC/B,QAAE,gBAAgB;AAClB,oBAAc;AACd,kBAAY;AAAA,IAChB,CAAC;AACD,UAAM,OAAO;AAAA,MACT;AAAA,MACA,EAAE,MAAM,UAAU,OAAO,wBAAwB;AAAA,MACjD,OAAO;AAAA,MACP;AAAA,QACI;AAAA,QACA,EAAE,OAAO,wBAAwB;AAAA,QACjC,GAAG,QAAQ,EAAE,OAAO,uBAAuB,GAAG,GAAG,SAAS,EAAE,IAAI,CAAC,GAAG,OAAO,SAAS,IAAI,SAAM,OAAO,MAAM,SAAS,EAAE,EAAE;AAAA,QACxH,GAAG,QAAQ,EAAE,OAAO,wBAAwB,GAAG,EAAE,IAAI;AAAA,MACzD;AAAA,IACJ;AACA,SAAK,iBAAiB,SAAS,MAAM,KAAK,UAAU,CAAC;AACrD,SAAK,gBAAgB,MAAM,CAAC;AAC5B,QAAI,CAAC,KAAK,YAAa,MAAK,YAAY,IAAI;AAAA,EAChD;AACA,MAAI,iBAAiB,SAAS,MAAM;AAChC,UAAM,OAAO;AACb,QAAI,KAAM,OAAM;AAAA,QACX,MAAK,OAAO,SAAS,aAAa,MAAM;AAAA,EACjD,CAAC;AACD,MAAI,WAAY,MAAK,YAAY,GAAG;AAGpC,QAAM,MAAM,GAAG,OAAO,EAAE,OAAO,oBAAoB,YAAY,UAAU,MAAM,UAAU,cAAc,MAAM,CAAC;AAC9G,QAAM,OAAO,GAAG,OAAO,EAAE,OAAO,6BAA6B,CAAC;AAC9D,QAAM,OAAO,GAAG,OAAO,EAAE,OAAO,6BAA6B,CAAC;AAC9D,QAAM,OAAO,GAAG,OAAO,EAAE,OAAO,iBAAiB,cAAc,YAAY,CAAC;AAC5E,MAAI,iBAAiB,SAAS,MAAM,MAAM,OAAO,CAAC;AAGlD,QAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,mBAAmB,CAAC;AACrD,QAAM,MAAM,GAAG,KAAK,EAAE,OAAO,kBAAkB,MAAM,QAAQ,CAAC;AAC9D,QAAM,QAAQ,GAAG,SAAS,EAAE,OAAO,aAAa,MAAM,SAAS,WAAW,SAAS,cAAc,SAAS,aAAa,8CAA8C,cAAc,yBAAyB,WAAW,MAAM,CAAC;AAC9N,QAAM,MAAM,GAAG,OAAO,EAAE,OAAO,eAAe,CAAC;AAC/C,QAAM,OAAO,GAAG,YAAY,EAAE,OAAO,+BAA+B,MAAM,KAAK,aAAa,yBAAoB,cAAc,WAAW,WAAW,OAAO,CAAC;AAC5J,QAAM,OAAO,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,iBAAiB,cAAc,OAAO,GAAG,KAAK,EAAE,EAAE,CAAC;AACtG,MAAI,OAAO,MAAM,IAAI;AACrB,OAAK,OAAO,GAAG;AAEf,QAAM,OAAO,GAAG,MAAM,EAAE,OAAO,YAAY,aAAa,UAAU,cAAc,WAAW,CAAC;AAC5F,QAAM,YAAY,MAAM,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC,QAAQ;AACjE,QAAM,UAAU,MAAM,CAAC,MAAM,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,MAAM,KAAK,CAAC;AAC1E,QAAM,UAAU,MAAM,CAAC,CAAC,KAAK,MAAM,KAAK,KAAK,CAAC,WAAW,QAAQ;AAEjE,QAAM,WAAW,MAAM;AACnB,UAAM,IAAI,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,oCAAoC,cAAc,kBAAkB,GAAG,KAAK,EAAE,KAAK,CAAC;AACpI,MAAE,iBAAiB,SAAS,MAAM,MAAM,CAAC;AACzC,WAAO;AAAA,EACX;AACA,QAAM,KAAK,CAAC,MAA2C;AACnD,WAAO;AACP,YAAQ;AACR,SAAK;AACL,QAAI,MAAM,YAAY;AAClB,eAAS;AACT,cAAQ;AACR,WAAK,MAAM;AAAA,IACf,WAAW,MAAM,OAAQ,WAAU,MAAM;AACzC,aAAS,CAAC;AAAA,EACd;AAEA,QAAM,SAAS,CAAC,GAAgB,YAAY,UAAU;AAClD,UAAM,KAAK,GAAG,MAAM,EAAE,OAAO,WAAW,aAAa,EAAE,SAAS,YAAY,OAAO,OAAO,GAAG,GAAG,OAAO,EAAE,OAAO,aAAa,GAAG,EAAE,IAAI,CAAC;AACvI,QAAI,UAAW,IAAG,aAAa,aAAa,MAAM;AAClD,eAAW,KAAK,EAAE,YAAY,CAAC,GAAG;AAC9B,YAAM,OAAO,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,gBAAgB,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;AAC9G,WAAK,iBAAiB,SAAS,MAAM,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AAC1D,SAAG,OAAO,IAAI;AAAA,IAClB;AACA,OAAG,OAAO,GAAG,QAAQ,EAAE,OAAO,eAAe,GAAG,GAAG,EAAE,SAAS,YAAY,GAAG,SAAS,EAAE,IAAI,CAAC,WAAQ,EAAE,GAAG,YAAY,kBAAa,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC;AACnJ,WAAO;AAAA,EACX;AAEA,QAAM,aAAa,CAAC,MAAsB;AACtC,UAAM,IAAI,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,eAAe,GAAG,GAAG,QAAQ,EAAE,OAAO,iBAAiB,GAAG,EAAE,KAAK,GAAG,KAAK,EAAE,MAAM,EAAE,CAAC;AACpI,MAAE,iBAAiB,SAAS,MAAM,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AACvD,WAAO;AAAA,EACX;AAEA,QAAM,YAAY,MAAM;AACpB,UAAM,OAAO,GAAG,SAAS,EAAE,OAAO,kBAAkB,CAAC;AACrD,UAAM,QAAQ,GAAG,SAAS,EAAE,OAAO,sBAAsB,MAAM,UAAU,aAAa,mBAAmB,cAAc,mBAAmB,WAAW,MAAM,CAAC;AAC5J,UAAM,QAAQ;AACd,QAAI;AACJ,UAAM,iBAAiB,SAAS,MAAM;AAClC,cAAQ,MAAM;AACd,mBAAa,CAAC;AACd,UAAI,WAAW,MAAM;AACjB,YAAI,SAAS,OAAQ,QAAO,GAAG,MAAM;AACrC,aAAK,aAAa,IAAI;AAAA,MAC1B,GAAG,GAAG;AAAA,IACV,CAAC;AACD,UAAM,iBAAiB,WAAW,CAAC,MAAM;AACrC,UAAI,EAAE,QAAQ,SAAS;AACnB,UAAE,eAAe;AACjB,YAAI,SAAS,OAAQ,IAAG,MAAM;AAAA,MAClC;AAAA,IACJ,CAAC;AACD,SAAK,OAAO,OAAO,KAAK,EAAE,QAAQ,EAAE,CAAC;AACrC,WAAO;AAAA,EACX;AAEA,QAAM,aAAa,UAAU;AAC7B,QAAM,YAAY,WAAW,cAAc,OAAO;AAElD,MAAI,kBAAkB;AACtB,QAAM,eAAe,OAAO,QAAQ,UAAU;AAC1C,QAAI,CAAC,UAAW,mBAAmB,CAAC,MAAQ;AAC5C,sBAAkB;AAClB,UAAM,IAAI,MAAM,KAAK;AACrB,QAAI;AACA,YAAM,IAAI,MAAM,IAAI,EAAE,SAAS,KAAK,MAAS;AAC7C,UAAI,MAAM,MAAM,KAAK,EAAG;AACxB,iBAAW,EAAE;AACb,UAAI,CAAC,EAAG,eAAc,EAAE,SAAS,SAAS;AAAA,IAC9C,QAAQ;AACJ,iBAAW,YAAY,CAAC;AAAA,IAC5B,UAAE;AACE,wBAAkB;AAAA,IACtB;AACA,SAAK;AAAA,EACT;AACA,QAAM,WAAW,MAAM;AACnB,SAAK,gBAAgB,GAAG,QAAQ,EAAE,OAAO,iBAAiB,GAAG,OAAO,IAAI,GAAG,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC;AAC7G,UAAM,OAAO,GAAG,OAAO,EAAE,OAAO,gBAAgB,GAAG,GAAG,KAAK,EAAE,OAAO,iBAAiB,GAAG,QAAQ,CAAC;AACjG,UAAM,QAAQ,QAAQ,YAAY,CAAC,GAAG,GAAG,EAAE;AAC3C,UAAM,QAAuB,CAAC,IAAI;AAClC,QAAI,MAAM;AACN,YAAM,SAAS;AAAA,QACX;AAAA,QACA,EAAE,MAAM,UAAU,OAAO,gCAAgC;AAAA,QACzD,GAAG,QAAQ,EAAE,OAAO,sBAAsB,GAAG,gBAAgB;AAAA,QAC7D;AAAA,UACI;AAAA,UACA,EAAE,OAAO,sBAAsB;AAAA,UAC/B,OAAO;AAAA,UACP;AAAA,YACI;AAAA,YACA,EAAE,OAAO,qBAAqB;AAAA,YAC9B,GAAG,QAAQ,EAAE,OAAO,yCAAyC,GAAG,KAAK,IAAI;AAAA,YACzE,GAAG,QAAQ,EAAE,OAAO,qBAAqB,GAAG,GAAG,KAAK,SAAS,YAAY,QAAQ,SAAS,KAAK,IAAI,CAAC,SAAM,QAAQ,KAAK,EAAE,CAAC,EAAE;AAAA,UAChI;AAAA,UACA,OAAO,SAAS,GAAG,QAAQ,EAAE,OAAO,iBAAiB,GAAG,OAAO,OAAO,MAAM,CAAC,IAAI,KAAK,EAAE,MAAM,EAAE;AAAA,QACpG;AAAA,MACJ;AACA,aAAO,iBAAiB,SAAS,MAAM,GAAG,UAAU,CAAC;AACrD,YAAM,KAAK,MAAM;AAAA,IACrB;AACA,UAAM,UAAU;AAAA,MACZ;AAAA,MACA,EAAE,MAAM,UAAU,OAAO,gBAAgB;AAAA,MACzC,GAAG,QAAQ,EAAE,OAAO,qBAAqB,GAAG,GAAG,KAAK,CAAC,GAAG,mBAAmB,GAAG,GAAG,QAAQ,EAAE,OAAO,oBAAoB,GAAG,KAAK,CAAC;AAAA,MAC/H,GAAG,QAAQ,EAAE,OAAO,cAAc,GAAG,KAAK,EAAE,IAAI,CAAC;AAAA,IACrD;AACA,YAAQ,iBAAiB,SAAS,MAAM,GAAG,UAAU,CAAC;AACtD,UAAM,KAAK,OAAO;AAClB,QAAI,UAAU,gBAAgB,OAAO;AACjC,YAAM,WAAW,GAAG,OAAO,EAAE,OAAO,kCAAkC,GAAG,UAAU,CAAC;AACpF,YAAM,OAAO,YAAY,CAAC,GAAG,MAAM,GAAG,CAAC;AACvC,UAAI,IAAI,OAAQ,UAAS,OAAO,GAAG,IAAI,IAAI,UAAU,CAAC;AAAA,eAC7C,aAAa,KAAM,UAAS,OAAO,GAAG,OAAO,EAAE,OAAO,yBAAyB,CAAC,CAAC;AAC1F,YAAM,KAAK,QAAQ;AAAA,IACvB;AACA,SAAK,gBAAgB,GAAG,KAAK;AAAA,EACjC;AAEA,QAAM,WAAW,MAAM;AACnB,SAAK,gBAAgB,GAAG,QAAQ,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;AACvD,QAAI,UAAU,UAAU,MAAO,WAAU,QAAQ;AACjD,UAAM,QAAuB,CAAC,UAAU;AACxC,QAAI,aAAa,KAAM,OAAM,KAAK,GAAG,OAAO,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,aACzD,CAAC,SAAS,QAAQ;AACvB,YAAM,MAAM,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,0BAA0B,GAAG,mBAAmB;AAClG,UAAI,iBAAiB,SAAS,MAAM,GAAG,UAAU,CAAC;AAClD,YAAM,KAAK,GAAG,OAAO,EAAE,OAAO,iBAAiB,GAAG,GAAG,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,2BAAsB,MAAM,KAAK,CAAC,YAAO,uBAAuB,GAAG,GAAG,CAAC;AAAA,IACxJ,WAAW,MAAM,KAAK,EAAG,OAAM,KAAK,GAAG,OAAO,EAAE,OAAO,kCAAkC,GAAG,GAAG,SAAS,IAAI,UAAU,CAAC,CAAC;AAAA,SACnH;AACD,YAAM,SAAS,oBAAI,IAA8B;AACjD,iBAAW,KAAK,SAAU,QAAO,IAAI,EAAE,YAAY,CAAC,GAAI,OAAO,IAAI,EAAE,UAAU,KAAK,CAAC,GAAI,CAAC,CAAC;AAC3F,iBAAW,CAAC,MAAM,KAAK,KAAK;AACxB,cAAM,KAAK,GAAG,WAAW,EAAE,OAAO,iBAAiB,GAAG,GAAG,MAAM,EAAE,OAAO,mBAAmB,GAAG,GAAG,IAAI,SAAM,MAAM,MAAM,EAAE,GAAG,GAAG,OAAO,EAAE,OAAO,kCAAkC,GAAG,GAAG,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC;AAAA,IACtN;AAEA,QAAI,KAAK,eAAe,WAAY,MAAK,gBAAgB,UAAU;AACnE,WAAO,KAAK,WAAW,SAAS,EAAG,MAAK,UAAW,OAAO;AAC1D,SAAK,OAAO,GAAG,MAAM,MAAM,CAAC,CAAC;AAAA,EACjC;AAEA,MAAI,eAAyD;AAC7D,QAAM,cAAc,CAAC,OAAe;AAChC,UAAM,OAAO,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,oCAAoC,cAAc,eAAe,GAAG,KAAK,EAAE,IAAI,CAAC;AACnI,SAAK,iBAAiB,SAAS,MAAM,GAAG,MAAM,CAAC;AAC/C,SAAK,gBAAgB,MAAM,GAAG,QAAQ,EAAE,OAAO,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAAC;AACvF,QAAI,cAAc,OAAO,GAAI,QAAO,KAAK,gBAAgB,aAAa,IAAI;AAC1E,UAAM,OAAO,GAAG,WAAW,EAAE,OAAO,eAAe,GAAG,GAAG,OAAO,EAAE,OAAO,WAAW,CAAC,CAAC;AACtF,mBAAe,EAAE,IAAI,KAAK;AAC1B,SAAK,gBAAgB,IAAI;AACzB,QAAI,EACC,QAAQ,EAAE,EACV,KAAK,CAAC,MAAM;AACT,YAAM,OAAO,GAAG,OAAO,EAAE,OAAO,gBAAgB,CAAC;AACjD,YAAM,WAAW,MAAM;AACnB,YAAI,MAAM,IAAI,EAAE,EAAG,QAAO,KAAK,gBAAgB,GAAG,QAAQ,CAAC,GAAG,6BAA6B,CAAC;AAC5F,cAAM,MAAM,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,UAAU,GAAG,KAAK;AACpE,cAAM,KAAK,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,UAAU,GAAG,IAAI;AAClE,cAAM,OAAO,CAAC,YAAqB;AAC/B,kBAAQ,IAAI,IAAI,KAAK,EAAE,IAAI,EAAE;AAC7B,mBAAS;AACT,cAAI,EACC,YAAY,IAAI,OAAO,EACvB,MAAM,MAAM,MAAS;AAC1B,cAAI,CAAC,QAAS,IAAG,UAAU;AAAA,QAC/B;AACA,YAAI,iBAAiB,SAAS,MAAM,KAAK,IAAI,CAAC;AAC9C,WAAG,iBAAiB,SAAS,MAAM,KAAK,KAAK,CAAC;AAC9C,aAAK,gBAAgB,GAAG,QAAQ,CAAC,GAAG,gCAAgC,GAAG,GAAG,QAAQ,EAAE,OAAO,kBAAkB,GAAG,KAAK,EAAE,CAAC;AAAA,MAC5H;AACA,eAAS;AACT,YAAM,MAAM,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,uBAAuB,GAAG,KAAK,EAAE,IAAI,GAAG,oCAAoC;AAC9H,UAAI,iBAAiB,SAAS,MAAM,GAAG,UAAU,CAAC;AAClD,WAAK;AAAA,QACD,GAAG,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,UAAU;AAAA,QACjD,GAAG,MAAM,EAAE,OAAO,iBAAiB,GAAG,EAAE,KAAK;AAAA,QAC7C,GAAG,KAAK,EAAE,OAAO,iBAAiB,GAAG,WAAW,QAAQ,EAAE,SAAS,CAAC,EAAE;AAAA,QACtE,GAAG,OAAO,EAAE,OAAO,iBAAiB,GAAG,GAAG,EAAE,OAAO,IAAI,OAAO,CAAC;AAAA,QAC/D;AAAA,QACA;AAAA,MACJ;AAAA,IACJ,CAAC,EACA,MAAM,CAAC,MAAa;AACjB,qBAAe;AACf,WAAK,gBAAgB,GAAG,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,OAAO,CAAC;AAAA,IACxE,CAAC;AAAA,EACT;AAEA,MAAI,QAAQ;AAEZ,MAAI,UAAU;AACd,QAAM,eAAe,MAAM;AACvB,SAAK;AAAA,MACD,GAAG,QAAQ,EAAE,OAAO,eAAe,GAAG,OAAO,GAAG,GAAG,QAAQ,EAAE,OAAO,iBAAiB,GAAG,GAAG,KAAK,CAAC,GAAG,KAAK,GAAG,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC;AAAA,MAClI,SAAS;AAAA,IACb;AACA,UAAM,OAAO,QAAQ,YAAY,CAAC;AAClC,UAAM,QAAuB,CAAC;AAC9B,QAAI,CAAC,OAAQ,OAAM,KAAK,GAAG,OAAO,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,SACnD;AACD,YAAM,MAAM,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,CAAC,IAAI,UAAU,QAAQ,OAAO,EAAE,IAAI,KAAK,MAAM,KAAK,IAAI,IAAI,GAAM,CAAC;AAChH,UAAI,QAAQ,SAAS;AACjB,kBAAU;AACV,cAAM,QAAQ,GAAG,MAAM,EAAE,OAAO,WAAW,aAAa,OAAO,GAAG,GAAG,OAAO,EAAE,OAAO,aAAa,GAAG,QAAQ,CAAC;AAC9G,aAAK,gBAAgB,OAAO,GAAG,KAAK,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,GAAG,GAAI,UAAU,CAAC,OAAO,SAAS,IAAI,CAAC,IAAI,CAAC,CAAE;AAAA,MAC1G;AACA,YAAM,KAAK,IAAI;AAAA,IACnB;AACA,QAAI,QAAQ,cAAc,WAAW,YAAY,CAAC,QAAS,OAAM,KAAK,GAAG,KAAK,EAAE,OAAO,yBAAyB,GAAG,wDAAwD,CAAC;AAC5K,QAAI,KAAK,WAAW,WAAW,MAAM,UAAU,MAAM,KAAK,CAAC,GAAG,MAAM,KAAK,WAAW,CAAC,MAAM,CAAC,EAAG,MAAK,gBAAgB,GAAG,KAAK;AAC5H,UAAM,QAAQ,KAAK,UAAU,UAAU,IAAI;AAC3C,QAAI,UAAU,OAAO;AACjB,cAAQ;AACR,WAAK,YAAY,KAAK;AAAA,IAC1B;AACA,QAAI,cAAc;AAClB,QAAI,SAAS,CAAC,IAAI,YAAa,MAAK,QAAQ,GAAG;AAAA,aACtC,CAAC,MAAO,KAAI,OAAO;AAC5B,QAAI,UAAU,GAAG;AACb,UAAI,QAAQ,EAAG,OAAM,gBAAgB,cAAc;AAAA,UAC9C,OAAM,aAAa,gBAAgB,MAAM;AAC9C,UAAI,CAAC,MAAM,YAAa,MAAK,aAAa,OAAO,GAAG;AAAA,IACxD,MAAO,OAAM,OAAO;AACpB,SAAK,WAAW,CAAC,QAAQ;AAAA,EAC7B;AAEA,QAAM,WAAW,MAAM;AACnB,UAAM,UAAU,OAAO,SAAS,WAAW,OAAO;AAClD,UAAM,MAAM,CAAC,GAAkB,MAAc,GAAW,QAAQ,MAAM;AAClE,YAAM,IAAI,GAAG,UAAU,EAAE,MAAM,UAAU,OAAO,gBAAgB,gBAAgB,YAAY,IAAI,SAAS,QAAQ,GAAG,KAAK,GAAG,EAAE,GAAG,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC;AACrJ,UAAI,MAAO,GAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,oCAAoC,GAAG,OAAO,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;AAC1G,QAAE,iBAAiB,SAAS,MAAM,GAAG,CAAC,CAAC;AACvC,aAAO;AAAA,IACX;AACA,SAAK,gBAAgB,IAAI,QAAQ,QAAQ,EAAE,IAAI,GAAG,IAAI,YAAY,YAAY,EAAE,MAAM,SAAS,aAAa,IAAI,OAAO,MAAM,GAAG,GAAI,UAAU,gBAAgB,QAAQ,CAAC,IAAI,QAAQ,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAE;AAAA,EAC7M;AAEA,QAAM,OAAO,MAAM;AACf,QAAI,CAAC,KAAM;AACX,QAAI,QAAQ,OAAO,OAAO,SAAS,WAAW,OAAO;AACrD,QAAI,SAAS,OAAQ,UAAS;AAAA,aACrB,SAAS,WAAY,cAAa;AAAA,aAClC,SAAS,OAAQ,UAAS;AAAA,QAC9B,aAAY,KAAK,OAAO;AAC7B,UAAM,OAAsB,CAAC,MAAM,IAAI;AACvC,QAAI,SAAS,WAAY,MAAK,KAAK,IAAI;AACvC,SAAK,KAAK,IAAI;AACd,aAAS;AACT,QAAI,IAAI,WAAW,WAAW,KAAK,UAAU,KAAK,KAAK,CAAC,GAAG,MAAM,IAAI,WAAW,CAAC,MAAM,CAAC,EAAG,KAAI,gBAAgB,GAAG,IAAI;AAAA,EAC1H;AAGA,QAAM,OAAO,YAAY;AACrB,UAAM,MAAM;AACZ,WAAO,IAAI,gBAAgB;AAC3B,QAAI;AACA,WAAK,MAAM,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC;AAClC,cAAQ;AAAA,IACZ,SAAS,GAAG;AACR,UAAK,EAAY,SAAS,aAAc;AACxC,UAAI,QAAQ,SAAS,WAAY,SAAS,EAAY;AAAA,IAC1D;AACA,aAAS;AACT,SAAK;AACL,YAAQ;AACR,aAAS;AAAA,EACb;AAEA,WAAS,SAAS,KAAc;AAC5B,iBAAa,IAAI;AACjB,UAAM,UAAU,CAAC,CAAC,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS,KAAK,QAAQ,cAAc,WAAW;AACzG,UAAM,SAAS,QAAQ,YAAY,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,EAAE,GAAG;AACnF,UAAM,SAAS,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,QAAQ,IAAI;AACnE,UAAM,KAAK,QAAQ,SAAS,IAAI,eAAe,WAAW,SAAS,kBAAkB,QAAQ,UAAU,eAAe;AACtH,QAAI,MAAM,QAAQ,EAAG,QAAO,WAAW,MAAM,KAAK,KAAK,GAAG,EAAE;AAAA,EAChE;AACA,WAAS,iBAAiB,oBAAoB,MAAM;AAChD,QAAI,SAAS,oBAAoB,UAAW,UAAS,CAAC;AAAA,QACjD,cAAa,IAAI;AAAA,EAC1B,CAAC;AAED,QAAM,SAAS,YAAY;AACvB,UAAM,MAAM,KAAK,MAAM,KAAK;AAC5B,QAAI,CAAC,OAAO,WAAW,CAAC,QAAQ,EAAG;AACnC,UAAM,OAAO;AACb,cAAU,EAAE,IAAI,WAAW,MAAM,WAAW,MAAM,KAAK,KAAI,oBAAI,KAAK,GAAE,YAAY,EAAE;AACpF,SAAK,QAAQ;AACb,YAAQ;AACR,SAAK;AACL,QAAI;AACA,WAAK,MAAM,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,UAAU,KAAK,MAAM,MAAM,KAAK,IAAI,MAAM,MAAM,KAAK,IAAI,QAAW,KAAK,OAAO,SAAS,KAAK,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;AAAA,IAChK,SAAS,GAAG;AACR,WAAK,QAAQ;AACb,cAAS,EAAY;AAAA,IACzB;AACA,cAAU;AACV,SAAK;AACL,aAAS;AAAA,EACb;AACA,OAAK,iBAAiB,UAAU,CAAC,MAAM;AACnC,MAAE,eAAe;AACjB,SAAK,OAAO;AAAA,EAChB,CAAC;AACD,OAAK,iBAAiB,WAAW,CAAC,MAAM;AACpC,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,YAAY,CAAC,EAAE,aAAa;AACpD,QAAE,eAAe;AACjB,WAAK,OAAO;AAAA,IAChB;AAAA,EACJ,CAAC;AACD,OAAK,iBAAiB,SAAS,MAAO,KAAK,WAAW,CAAC,QAAQ,CAAE;AACjE,QAAM,iBAAiB,SAAS,MAAM,KAAK,CAAC;AAE5C,WAAS,KAAK,IAAyC,QAAQ;AAC3D,WAAO;AACP,WAAO,MAAM,UAAU,CAAC,SAAS,SAAS;AAC1C,YAAQ;AACR,kBAAc;AACd,QAAI,CAAC,IAAI,YAAa,MAAK,YAAY,GAAG;AAC1C,QAAI,aAAa,QAAS,SAAS,UAAU,MAAQ,MAAK,aAAa;AACvE,SAAK;AACL,YAAQ;AACR,QAAI,SAAS,YAAY;AACrB,eAAS;AACT,WAAK,MAAM;AAAA,IACf;AACA,aAAS,CAAC;AAAA,EACd;AACA,WAAS,QAAQ;AACb,QAAI,CAAC,KAAM;AACX,WAAO;AACP,QAAI,OAAO;AACX,YAAQ;AACR,aAAS;AACT,QAAI,WAAY,KAAI,MAAM;AAAA,EAC9B;AACA,QAAM,QAAQ,CAAC,MAAqB;AAChC,QAAI,EAAE,QAAQ,YAAY,KAAM,OAAM;AAAA,EAC1C;AACA,WAAS,iBAAiB,WAAW,KAAK;AAG1C,OAAK,KAAK;AACV,MAAI,OAAQ,MAAK,aAAa;AAC9B,UAAQ;AAER,SAAO;AAAA,IACH,MAAM,CAAC,MAAM,KAAK,KAAK,MAAM;AAAA,IAC7B;AAAA,IACA,QAAQ,MAAO,OAAO,MAAM,IAAI,KAAK;AAAA,IACrC,SAAS,MAAM;AACX,mBAAa,IAAI;AACjB,YAAM,MAAM;AACZ,eAAS,oBAAoB,WAAW,KAAK;AAC7C,WAAK,OAAO;AAAA,IAChB;AAAA,EACJ;AACJ;","names":[]}
1
+ {"version":3,"sources":["../src/messenger-ui.ts"],"sourcesContent":["/**\n * The web messenger, after Crisp's: a round launcher (hovered, a small card offers \"Chat with us\" and \"Search\") and a\n * panel with a bar on top (Home, a \"Chat · Help\" switch, a ⋮ menu to minimize or widen it). Home shows the greeting,\n * the latest chat and the help search; Chat is the chat with the team, answered in MRRocket › Support by the owner or\n * the Customer experience agent; Help lists the product's published help articles by collection, searchable, read in\n * the panel. While the panel is closed it checks for answers now and then; a new answer plays a short sound, shows a\n * count on the launcher and a preview card above it. Opening, closing, switching and new messages move softly\n * (none of it with reduced motion).\n *\n * Plain DOM, no React, so `<Messenger />` (Next.js) and the script tag share it; both load it only when it is used (a\n * dynamic import, and `sdk-messenger.js` for the script tag). Every text is set with textContent; articles arrive as\n * blocks, never HTML.\n */\nimport { type Api, type ArticleBlock, type ArticleSpan, type ArticleSummary, type ChatMessage, type ChatThread, type MessengerLook, createApi, inkOn, replyLine } from \"./api-client\";\nimport { injectStyles } from \"./styles-css\";\n\nexport interface MessengerUiOptions {\n host: string;\n apiKey: string;\n /** The visitor id now (it changes on identify and reset). */\n distinctId: () => string;\n /** The signed-in person's id, name and email, when the site called identify. */\n user: () => { id?: string; name?: string; email?: string } | undefined;\n /** Show the round launcher (default true). Without it the panel opens only through `open()`. */\n launcher?: boolean;\n position?: \"bottom-right\" | \"bottom-left\";\n /** The panel's title. */\n title?: string;\n /** The big line on Home and the first line of an empty chat. */\n greeting?: string;\n /** Ask anonymous visitors for an email (optional for them). Default true. */\n askEmail?: boolean;\n /** Text on the launcher; empty shows the icon only. */\n label?: string;\n /** How soon the team usually answers, said under \"Send us a message\" and in the chat's head. */\n replyTime?: \"minutes\" | \"hours\" | \"day\";\n /** The Help tab with the product's published help articles (default true; hidden while there are none). */\n help?: boolean;\n /** A short sound when an answer arrives (default true). */\n sound?: boolean;\n /** A preview of a new answer above the closed launcher (default true). */\n preview?: boolean;\n theme?: \"light\" | \"dark\" | \"auto\";\n accent?: string;\n /** MRRocket's own preview: mount inside this element (positioned) instead of the page. */\n container?: HTMLElement;\n /** MRRocket's own preview: answers from here instead of the server. */\n client?: MessengerClient;\n /** MRRocket's own preview: start open on this view, without the opening motion. */\n opened?: MessengerView;\n}\n\n/** What the messenger asks the server (createApi's part it uses). */\nexport type MessengerClient = Pick<Api, \"chat\" | \"sendChat\" | \"articles\" | \"article\" | \"rateArticle\" | \"messengerLook\">;\n\nexport type MessengerView = \"home\" | \"messages\" | \"help\";\n\nexport interface MessengerHandle {\n /** Opens the panel, on Home or the given tab; `{ article }` opens a help article. */\n open(view?: MessengerView | { article: string }): void;\n close(): void;\n toggle(): void;\n /** Removes the launcher and the panel from the page. */\n destroy(): void;\n}\n\nconst POLL_OPEN_MS = 4000;\n/** While the panel is closed: soon after the visitor wrote, answers are looked for often, later now and then. */\nconst POLL_WAITING_MS = 8000;\nconst POLL_IDLE_MS = 30000;\nconst WAITING_FOR_MS = 10 * 60_000;\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/;\nconst SEEN_KEY = \"ckw_msgr_seen\";\nconst whoLabel: Record<ChatMessage[\"from\"], string> = { visitor: \"You\", team: \"Team\", ai: \"AI agent\", auto: \"Team\" };\n\nconst readSeen = () => {\n try {\n return window.localStorage.getItem(SEEN_KEY) ?? \"\";\n } catch {\n return \"\";\n }\n};\nconst writeSeen = (id: string) => {\n try {\n window.localStorage.setItem(SEEN_KEY, id);\n } catch {\n // Private mode: the count just shows again next time.\n }\n};\n\nconst timeAgo = (iso: string) => {\n const t = new Date(iso).getTime();\n if (Number.isNaN(t)) return \"\";\n const d = Math.max(0, Date.now() - t) / 1000;\n if (d < 60) return \"just now\";\n if (d < 3600) return `${Math.floor(d / 60)}m ago`;\n if (d < 86400) return `${Math.floor(d / 3600)}h ago`;\n if (d < 86400 * 30) return `${Math.floor(d / 86400)}d ago`;\n return new Date(iso).toLocaleDateString(undefined, { month: \"short\", day: \"numeric\", year: \"numeric\" });\n};\n\nconst el = <K extends keyof HTMLElementTagNameMap>(tag: K, attrs: Record<string, string> = {}, ...kids: (Node | string | null | false | undefined)[]) => {\n const e = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) e.setAttribute(k, v);\n for (const k of kids) if (k !== null && k !== false && k !== undefined) e.append(k);\n return e;\n};\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n/** A line icon on a 24-unit grid (Lucide's shapes, ISC). */\nconst icon = (d: string, size = 16) => {\n const svg = document.createElementNS(SVG_NS, \"svg\");\n for (const [k, v] of Object.entries({ class: \"ckw-icon\", width: String(size), height: String(size), viewBox: \"0 0 24 24\", fill: \"none\", stroke: \"currentColor\", \"stroke-width\": \"1.75\", \"stroke-linecap\": \"round\", \"stroke-linejoin\": \"round\", \"aria-hidden\": \"true\" }))\n svg.setAttribute(k, v);\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", d);\n svg.appendChild(path);\n return svg;\n};\nconst I = {\n cross: \"M18 6 6 18M6 6l12 12\",\n chat: \"M7.9 20A9 9 0 1 0 4 16.1L2 22z\",\n send: \"M5 12h14M12 5l7 7-7 7\",\n up: \"M12 19V5M5 12l7-7 7 7\",\n home: \"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\",\n back: \"m15 18-6-6 6-6\",\n next: \"m9 18 6-6-6-6\",\n search: \"M19 11a8 8 0 1 1-16 0 8 8 0 0 1 16 0zM21 21l-4.3-4.3\",\n doc: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7zM14 2v4a2 2 0 0 0 2 2h4M10 9H8M16 13H8M16 17H8\",\n book: \"M12 7v14M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\",\n dots: \"M13 12a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM13 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM13 19a1 1 0 1 1-2 0 1 1 0 0 1 2 0z\",\n expand: \"M15 3h6v6M21 3l-7 7M3 21l7-7M9 21H3v-6\",\n collapse: \"m14 10 7-7M20 10h-6V4M3 21l7-7M4 14h6v6\",\n minus: \"M5 12h14\",\n};\n/** The launcher's filled bubble (24-unit grid). */\nconst BUBBLE = \"M7.9 20A9 9 0 1 0 4 16.1L2 22z\";\nconst filled = (d: string, size: number) => {\n const svg = document.createElementNS(SVG_NS, \"svg\");\n for (const [k, v] of Object.entries({ class: \"ckw-icon\", width: String(size), height: String(size), viewBox: \"0 0 24 24\", fill: \"currentColor\", stroke: \"currentColor\", \"stroke-width\": \"1.5\", \"stroke-linejoin\": \"round\", \"aria-hidden\": \"true\" }))\n svg.setAttribute(k, v);\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", d);\n svg.appendChild(path);\n return svg;\n};\n\n/** A soft two-note chime made with Web Audio (no file to load). Browsers allow it once the visitor has clicked. */\nconst chime = (() => {\n let ctx: AudioContext | null = null;\n const get = () => {\n const AC = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!AC) return null;\n ctx ??= new AC();\n return ctx;\n };\n return {\n /** Call from a click so later sounds may play. */\n unlock: () => {\n try {\n const c = get();\n if (c?.state === \"suspended\") void c.resume();\n } catch {\n // No audio: no sound.\n }\n },\n play: () => {\n try {\n const c = get();\n if (!c || c.state !== \"running\") return;\n const t = c.currentTime;\n [880, 1318.5].forEach((f, i) => {\n const o = c.createOscillator();\n const g = c.createGain();\n const at = t + i * 0.11;\n o.type = \"sine\";\n o.frequency.value = f;\n g.gain.setValueAtTime(0.0001, at);\n g.gain.exponentialRampToValueAtTime(0.12, at + 0.012);\n g.gain.exponentialRampToValueAtTime(0.0001, at + 0.32);\n o.connect(g);\n g.connect(c.destination);\n o.start(at);\n o.stop(at + 0.34);\n });\n } catch {\n // No audio: no sound.\n }\n },\n };\n})();\n\nconst spansOf = (spans: ArticleSpan[]) =>\n spans.map((s) => {\n let node: HTMLElement = s.href ? el(\"a\", { href: s.href, target: \"_blank\", rel: \"noopener noreferrer\" }, s.text) : el(\"span\", {}, s.text);\n if (s.code) node = el(\"code\", {}, node);\n if (s.italic) node = el(\"em\", {}, node);\n if (s.bold) node = el(\"strong\", {}, node);\n return node;\n });\n\nconst blockOf = (b: ArticleBlock): HTMLElement => {\n switch (b.type) {\n case \"h2\":\n case \"h3\":\n return el(b.type, {}, ...spansOf(b.spans));\n case \"quote\":\n return el(\"blockquote\", {}, ...spansOf(b.spans));\n case \"ul\":\n case \"ol\":\n return el(b.type, {}, ...b.items.map((it) => el(\"li\", {}, ...spansOf(it))));\n case \"code\":\n return el(\"pre\", {}, el(\"code\", {}, b.text));\n case \"hr\":\n return el(\"hr\");\n default:\n return el(\"p\", {}, ...spansOf(b.spans));\n }\n};\n\n/** How long the launcher waits for the look from MRRocket before it shows with the code's options and the defaults. */\nconst LOOK_WAIT_MS = 2500;\n\n/**\n * Mounts the messenger with its look from MRRocket (Support › Messenger) underneath what the code passes: an option the\n * code sets wins, one it leaves out comes from MRRocket, then the default. Calls made before the look arrived wait.\n */\nexport const mountMessenger = (o: MessengerUiOptions): MessengerHandle => {\n let real: MessengerHandle | null = null;\n let gone = false;\n const queued: ((h: MessengerHandle) => void)[] = [];\n const later = (fn: (h: MessengerHandle) => void) => (real ? fn(real) : queued.push(fn));\n const ctrl = new AbortController();\n const start = (look: Partial<MessengerLook> | null) => {\n if (real || gone) return;\n const defined = Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as MessengerUiOptions;\n real = build({ ...(look ?? {}), ...defined, accent: o.accent ?? look?.accent, theme: o.theme ?? look?.theme });\n for (const fn of queued.splice(0)) fn(real);\n };\n const timer = setTimeout(() => start(null), LOOK_WAIT_MS);\n (o.client ?? createApi({ host: o.host, apiKey: o.apiKey, distinctId: o.distinctId(), user: o.user() }))\n .messengerLook(ctrl.signal)\n .then((look) => start(look))\n .catch(() => start(null))\n .finally(() => clearTimeout(timer));\n return {\n open: (v) => later((h) => h.open(v)),\n close: () => real?.close(),\n toggle: () => later((h) => h.toggle()),\n destroy: () => {\n gone = true;\n ctrl.abort();\n clearTimeout(timer);\n real?.destroy();\n },\n };\n};\n\nconst build = (o: MessengerUiOptions): MessengerHandle => {\n injectStyles();\n const position = o.position ?? \"bottom-right\";\n const title = o.title || \"Chat with us\";\n const greeting = o.greeting || \"Hi! How can we help?\";\n const askEmail = o.askEmail ?? true;\n const label = o.label ?? \"\";\n const reply = replyLine(o.replyTime);\n /** The team's mark: the first letter of the title, on the accent. */\n const initial = (title.trim()[0] ?? \"?\").toUpperCase();\n const launcherOn = o.launcher ?? true;\n const helpOn = o.help ?? true;\n const soundOn = o.sound ?? true;\n const previewOn = o.preview ?? true;\n const api = (): MessengerClient => o.client ?? createApi({ host: o.host, apiKey: o.apiKey, distinctId: o.distinctId(), user: o.user() });\n\n const root = el(\"div\", { class: \"ckw-root\", \"data-theme\": o.theme ?? \"auto\" });\n if (o.container) root.setAttribute(\"data-contained\", \"\");\n if (o.accent) {\n root.style.setProperty(\"--ckw-accent\", o.accent);\n root.style.setProperty(\"--ckw-accent-ink\", inkOn(o.accent));\n }\n (o.container ?? document.body).appendChild(root);\n\n let open = false;\n let view: MessengerView | { article: string } = \"home\";\n let thread: ChatThread | null = null;\n let loaded = false;\n let error = \"\";\n let pending: ChatMessage | null = null;\n /** The newest team message seen in this page load: what counts as new after it. */\n let lastKnown: string | null = null;\n let unseen: ChatMessage[] = [];\n let previewGone = false;\n let poll: ReturnType<typeof setTimeout> | undefined;\n let ctrl: AbortController | null = null;\n let articles: ArticleSummary[] | null = null;\n let query = \"\";\n let rated = new Set<string>();\n /** Whether the product has any published article: the Help tab and Home's help card hide when it has none. */\n let hasArticles: boolean | null = null;\n /** The help collection opened from Help's list (null: the list of collections). */\n let collection: string | null = null;\n /** The panel widened from the ⋮ menu. */\n let wide = false;\n\n const teamMsgs = (t: ChatThread | null) => (t?.messages ?? []).filter((m) => m.from !== \"visitor\");\n const lastTeamId = (t: ChatThread | null) => teamMsgs(t).at(-1)?.id ?? \"\";\n const watching = () => open && view === \"messages\" && document.visibilityState !== \"hidden\";\n\n /** Takes a thread from the server: new answers count, chime and show in the preview. */\n const take = (t: ChatThread) => {\n const team = teamMsgs(t);\n if (lastKnown === null) {\n // First read: answers the visitor never saw in an earlier visit count, without a sound.\n const seen = readSeen();\n const i = team.findIndex((m) => m.id === seen);\n unseen = t.messages.some((m) => m.from === \"visitor\") ? team.slice(i + 1).filter((m) => m.from !== \"auto\") : [];\n } else {\n const i = team.findIndex((m) => m.id === lastKnown);\n const fresh = team.slice(i + 1).filter((m) => m.from !== \"auto\");\n if (fresh.length) {\n if (soundOn) chime.play();\n if (!watching()) {\n unseen = [...unseen, ...fresh];\n previewGone = false;\n }\n }\n }\n lastKnown = lastTeamId(t);\n thread = t;\n if (watching()) markSeen();\n };\n const markSeen = () => {\n unseen = [];\n const id = lastTeamId(thread);\n if (id) writeSeen(id);\n };\n\n const avatar = (size?: \"sm\") => el(\"span\", { class: `ckw-msgr-av${size ? \" ckw-msgr-av-sm\" : \"\"}`, \"aria-hidden\": \"true\" }, initial);\n\n // ---------- Coming and going ----------\n /** Pending removals: a node that leaves plays its way out first (data-out), unless it is shown again meanwhile. */\n const leaving = new Map<HTMLElement, ReturnType<typeof setTimeout>>();\n const enter = (node: HTMLElement, parent: HTMLElement = root) => {\n clearTimeout(leaving.get(node));\n leaving.delete(node);\n node.removeAttribute(\"data-out\");\n if (!node.isConnected) parent.appendChild(node);\n };\n const leave = (node: HTMLElement, ms = 180) => {\n if (!node.isConnected || leaving.has(node)) return;\n node.setAttribute(\"data-out\", \"\");\n leaving.set(\n node,\n setTimeout(() => {\n leaving.delete(node);\n node.removeAttribute(\"data-out\");\n node.remove();\n }, ms),\n );\n };\n /** Plays an entrance again on a node that stays (a new view in the same body). */\n const replay = (node: HTMLElement, cls: string) => {\n node.classList.remove(cls);\n void node.offsetWidth;\n node.classList.add(cls);\n };\n\n // ---------- Launcher, teaser and preview ----------\n const fab = el(\"button\", { type: \"button\", class: `ckw-fab ckw-msgr-fab${label ? \"\" : \" ckw-msgr-round\"}`, \"data-pos\": position, \"aria-haspopup\": \"dialog\" });\n const fabIcons = el(\n \"span\",\n { class: \"ckw-msgr-fab-ic\", \"aria-hidden\": \"true\" },\n el(\"span\", { class: \"ckw-msgr-fab-i\", \"data-i\": \"chat\" }, filled(BUBBLE, label ? 20 : 28)),\n el(\"span\", { class: \"ckw-msgr-fab-i\", \"data-i\": \"x\" }, icon(I.cross, label ? 16 : 22)),\n );\n const fabCount = el(\"span\", { class: \"ckw-msgr-count\", \"aria-hidden\": \"true\" });\n fab.append(fabIcons);\n if (label) fab.append(el(\"span\", {}, label));\n const prev = el(\"div\", { class: \"ckw-msgr-preview\", \"data-pos\": position, role: \"status\" });\n const drawFab = () => {\n fab.toggleAttribute(\"data-open\", open);\n if (unseen.length && !open) {\n const n = String(Math.min(unseen.length, 9));\n if (fabCount.textContent !== n) fabCount.textContent = n;\n if (!fabCount.isConnected) fab.append(fabCount);\n } else fabCount.remove();\n fab.setAttribute(\"aria-expanded\", String(open));\n fab.setAttribute(\"aria-label\", open ? \"Close chat\" : unseen.length ? `Open chat, ${unseen.length} new ${unseen.length === 1 ? \"reply\" : \"replies\"}` : \"Open chat\");\n drawPreview();\n };\n const previewShown = () => previewOn && !open && !previewGone && !!unseen.length && launcherOn;\n const drawPreview = () => {\n const m = unseen.at(-1);\n if (!previewShown() || !m) return leave(prev);\n hideTeaser(true);\n const x = el(\"button\", { type: \"button\", class: \"ckw-msgr-preview-x\", \"aria-label\": \"Dismiss\" }, icon(I.cross, 12));\n x.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n previewGone = true;\n drawPreview();\n });\n const card = el(\n \"button\",\n { type: \"button\", class: \"ckw-msgr-preview-card\" },\n avatar(),\n el(\n \"span\",\n { class: \"ckw-msgr-preview-main\" },\n el(\"span\", { class: \"ckw-msgr-preview-who\" }, `${whoLabel[m.from]}${unseen.length > 1 ? ` · ${unseen.length} new` : \"\"}`),\n el(\"span\", { class: \"ckw-msgr-preview-text\" }, m.body),\n ),\n );\n card.addEventListener(\"click\", () => show(\"messages\"));\n prev.replaceChildren(card, x);\n enter(prev);\n };\n\n /** Hovering the closed launcher: a small card with the greeting, the reply time, \"Chat with us\" and \"Search\". */\n const teaser = el(\"div\", { class: \"ckw-msgr-teaser\", \"data-pos\": position });\n let teaserTimer: ReturnType<typeof setTimeout> | undefined;\n const showTeaser = () => {\n clearTimeout(teaserTimer);\n if (open || previewShown() || !launcherOn) return;\n const chat = el(\"button\", { type: \"button\", class: \"ckw-msgr-teaser-b\", \"data-main\": \"\" }, icon(I.chat), el(\"span\", {}, \"Chat with us\"));\n chat.addEventListener(\"click\", () => show(\"messages\"));\n const buttons: HTMLElement[] = [chat];\n if (helpOn && hasArticles) {\n const search = el(\"button\", { type: \"button\", class: \"ckw-msgr-teaser-b\" }, icon(I.search), el(\"span\", {}, \"Search\"));\n search.addEventListener(\"click\", () => show(\"help\"));\n buttons.push(search);\n }\n teaser.replaceChildren(\n el(\n \"div\",\n { class: \"ckw-msgr-teaser-top\" },\n el(\"span\", { class: \"ckw-msgr-teaser-t\" }, el(\"b\", {}, greeting), el(\"span\", { class: \"ckw-msgr-online\" }, reply)),\n avatar(),\n ),\n el(\"div\", { class: \"ckw-msgr-teaser-row\" }, ...buttons),\n );\n enter(teaser);\n };\n function hideTeaser(now = false) {\n clearTimeout(teaserTimer);\n if (now) return leave(teaser, 140);\n teaserTimer = setTimeout(() => leave(teaser, 140), 260);\n }\n const hoverable = (e: PointerEvent) => e.pointerType === \"mouse\";\n for (const node of [fab, teaser] as HTMLElement[]) {\n node.addEventListener(\"pointerenter\", (e) => hoverable(e) && (node === fab ? showTeaser() : clearTimeout(teaserTimer)));\n node.addEventListener(\"pointerleave\", (e) => hoverable(e) && hideTeaser());\n }\n\n fab.addEventListener(\"click\", () => {\n chime.unlock();\n hideTeaser(true);\n if (open) close();\n else show(unseen.length ? \"messages\" : \"home\");\n });\n if (launcherOn) root.appendChild(fab);\n\n // ---------- Panel ----------\n const pop = el(\"div\", { class: \"ckw-pop ckw-msgr\", \"data-pos\": position, role: \"dialog\", \"aria-label\": title });\n const bar = el(\"div\", { class: \"ckw-msgr-bar\" });\n const body = el(\"div\", { class: \"ckw-pop-body ckw-msgr-body\" });\n pop.addEventListener(\"click\", () => chime.unlock());\n\n // The bar keeps its elements between draws, so the switch's marker can glide from one tab to the other.\n const lead = el(\"span\", { class: \"ckw-msgr-lead\" });\n const seg = el(\"nav\", { class: \"ckw-msgr-seg\", \"aria-label\": \"Messenger\" });\n const mark = el(\"span\", { class: \"ckw-msgr-seg-mark\", \"aria-hidden\": \"true\" });\n const segTab = (v: \"messages\" | \"help\", name: string, d: string) => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-msgr-seg-b\" }, icon(d, 15), el(\"span\", {}, name));\n b.addEventListener(\"click\", () => {\n collection = null;\n go(v);\n });\n return b;\n };\n const chatTab = segTab(\"messages\", \"Chat\", I.chat);\n const helpTab = segTab(\"help\", \"Help\", I.book);\n const tabCount = el(\"span\", { class: \"ckw-msgr-count ckw-msgr-count-tab\", \"aria-hidden\": \"true\" });\n const menuBtn = el(\"button\", { type: \"button\", class: \"ckw-msgr-ib\", \"aria-label\": \"More\", \"aria-haspopup\": \"menu\", \"aria-expanded\": \"false\" }, icon(I.dots, 18));\n /** On a phone the panel covers the launcher, so it has its own close. */\n const xBtn = el(\"button\", { type: \"button\", class: \"ckw-msgr-ib ckw-msgr-x\", \"aria-label\": \"Close messenger\" }, icon(I.cross));\n xBtn.addEventListener(\"click\", () => close());\n bar.append(lead, seg, el(\"span\", { class: \"ckw-msgr-trail\" }, menuBtn, xBtn));\n\n const menu = el(\"div\", { class: \"ckw-msgr-menu\", role: \"menu\" });\n const menuOpen = () => menu.isConnected && !menu.hasAttribute(\"data-out\");\n const closeMenu = () => {\n menuBtn.setAttribute(\"aria-expanded\", \"false\");\n leave(menu, 120);\n };\n const menuItem = (d: string, name: string, act: () => void) => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-msgr-menu-i\", role: \"menuitem\" }, icon(d, 15), el(\"span\", {}, name));\n b.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n closeMenu();\n act();\n });\n return b;\n };\n menuBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n if (menuOpen()) return closeMenu();\n menu.replaceChildren(\n el(\"span\", { class: \"ckw-msgr-menu-h\" }, \"Quick actions\"),\n menuItem(I.minus, \"Minimize chat\", () => close()),\n menuItem(wide ? I.collapse : I.expand, wide ? \"Collapse view\" : \"Expand view\", () => {\n wide = !wide;\n pop.toggleAttribute(\"data-wide\", wide);\n requestAnimationFrame(placeMark);\n }),\n );\n menuBtn.setAttribute(\"aria-expanded\", \"true\");\n enter(menu, pop);\n (menu.querySelector(\"button\") as HTMLButtonElement | null)?.focus();\n });\n pop.addEventListener(\"click\", () => menuOpen() && closeMenu());\n\n /** Moves the switch's marker under the current tab (none on Home). */\n function placeMark() {\n const current = view === \"messages\" ? chatTab : view !== \"home\" ? helpTab : null;\n if (!current || !current.isConnected) return mark.removeAttribute(\"data-on\");\n const first = !mark.hasAttribute(\"data-on\");\n if (first) mark.setAttribute(\"data-still\", \"\");\n mark.style.width = `${current.offsetWidth}px`;\n mark.style.transform = `translateX(${current.offsetLeft}px)`;\n mark.setAttribute(\"data-on\", \"\");\n if (first) requestAnimationFrame(() => mark.removeAttribute(\"data-still\"));\n }\n\n const drawBar = () => {\n const back = (to: () => void, name: string) => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-msgr-ib\", \"aria-label\": name }, icon(I.back, 18));\n b.addEventListener(\"click\", to);\n return b;\n };\n if (typeof view !== \"string\")\n lead.replaceChildren(\n back(() => go(\"help\"), \"Back to help\"),\n );\n else if (view === \"help\" && collection && !query.trim())\n lead.replaceChildren(\n back(() => {\n collection = null;\n go(\"help\");\n }, \"All collections\"),\n );\n else {\n const home = el(\"button\", { type: \"button\", class: \"ckw-msgr-ib\", \"aria-label\": \"Home\", \"aria-current\": view === \"home\" ? \"page\" : \"false\" }, icon(I.home, 17));\n home.addEventListener(\"click\", () => go(\"home\"));\n lead.replaceChildren(home);\n }\n const tabsWanted = helpOn && hasArticles !== false ? [mark, chatTab, helpTab] : [mark, chatTab];\n if (seg.childNodes.length !== tabsWanted.length) seg.replaceChildren(...tabsWanted);\n chatTab.setAttribute(\"aria-current\", view === \"messages\" ? \"page\" : \"false\");\n helpTab.setAttribute(\"aria-current\", view !== \"home\" && view !== \"messages\" ? \"page\" : \"false\");\n if (unseen.length && view !== \"messages\") {\n tabCount.textContent = String(Math.min(unseen.length, 9));\n if (!tabCount.isConnected) chatTab.append(tabCount);\n } else tabCount.remove();\n };\n\n // The chat's compose form keeps its elements between draws, so the field never loses the focus.\n const form = el(\"form\", { class: \"ckw-msgr-compose\" });\n const err = el(\"p\", { class: \"ckw-msgr-error\", role: \"alert\" });\n const email = el(\"input\", { class: \"ckw-input\", type: \"email\", inputmode: \"email\", autocomplete: \"email\", placeholder: \"Your email (optional), so we can follow up\", \"aria-label\": \"Your email (optional)\", maxlength: \"200\" });\n const row = el(\"div\", { class: \"ckw-msgr-box\" });\n const text = el(\"textarea\", { class: \"ckw-textarea ckw-msgr-input\", rows: \"1\", placeholder: \"Write your message…\", \"aria-label\": \"Message\", maxlength: \"4000\" });\n const send = el(\"button\", { type: \"submit\", class: \"ckw-msgr-send\", \"aria-label\": \"Send\" }, icon(I.up));\n row.append(text, el(\"div\", { class: \"ckw-msgr-box-foot\" }, el(\"span\", { class: \"ckw-msgr-hint\" }, \"Enter to send\"), send));\n row.addEventListener(\"click\", (e) => e.target === row && text.focus());\n form.append(row);\n\n const list = el(\"ol\", { class: \"ckw-msgs\", \"aria-live\": \"polite\", \"aria-label\": \"Messages\" });\n const needEmail = () => askEmail && !o.user()?.email && !thread?.hasEmail;\n const emailOk = () => !email.value.trim() || EMAIL.test(email.value.trim());\n const canSend = () => !!text.value.trim() && !pending && emailOk();\n\n const go = (v: MessengerView | { article: string }) => {\n const changed = JSON.stringify(v) !== JSON.stringify(view);\n view = v;\n drawn = -1;\n draw();\n if (changed) replay(body, \"ckw-msgr-enter\");\n if (v === \"messages\") {\n markSeen();\n drawFab();\n text.focus();\n } else if (v === \"help\") helpInput.focus();\n schedule(0);\n };\n\n const bubble = (m: ChatMessage, isPending = false) => {\n const li = el(\"li\", { class: \"ckw-msg\", \"data-from\": m.from === \"visitor\" ? \"me\" : \"them\" }, el(\"div\", { class: \"ckw-bubble\" }, m.body));\n if (isPending) li.setAttribute(\"aria-busy\", \"true\");\n for (const a of m.articles ?? []) {\n const chip = el(\"button\", { type: \"button\", class: \"ckw-msgr-cite\" }, icon(I.doc, 14), el(\"span\", {}, a.title));\n chip.addEventListener(\"click\", () => go({ article: a.id }));\n li.append(chip);\n }\n li.append(el(\"span\", { class: \"ckw-msg-meta\" }, `${m.from !== \"visitor\" ? `${whoLabel[m.from]} · ` : \"\"}${isPending ? \"Sending…\" : timeAgo(m.at)}`));\n return li;\n };\n\n const articleRow = (a: ArticleSummary) => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-msgr-art\" }, el(\"span\", { class: \"ckw-msgr-art-t\" }, a.title), icon(I.next, 14));\n b.addEventListener(\"click\", () => go({ article: a.id }));\n return b;\n };\n /** A row in Help's lists: a bold name, two lines under it, a count, the arrow. */\n const helpRow = (name: string, sub: string, meta: string, act: () => void) => {\n const b = el(\n \"button\",\n { type: \"button\", class: \"ckw-msgr-hrow\" },\n el(\"span\", { class: \"ckw-msgr-hrow-main\" }, el(\"b\", {}, name), sub ? el(\"span\", { class: \"ckw-msgr-hrow-sub\" }, sub) : null, meta ? el(\"span\", { class: \"ckw-msgr-hrow-meta\" }, meta) : null),\n icon(I.next, 16),\n );\n b.addEventListener(\"click\", act);\n return b;\n };\n\n const searchBox = (placeholder = \"Search for help\") => {\n const wrap = el(\"label\", { class: \"ckw-msgr-search\" });\n const input = el(\"input\", { class: \"ckw-msgr-search-in\", type: \"search\", placeholder, \"aria-label\": \"Search for help\", maxlength: \"200\" });\n input.value = query;\n let t: ReturnType<typeof setTimeout> | undefined;\n input.addEventListener(\"input\", () => {\n query = input.value;\n clearTimeout(t);\n t = setTimeout(() => {\n if (view !== \"help\") return go(\"help\");\n void loadArticles(true);\n }, 250);\n });\n input.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n if (view !== \"help\") go(\"help\");\n }\n });\n wrap.append(icon(I.search, 16), input);\n return wrap;\n };\n // Help's own field stays the same element between draws, so typing never loses the cursor.\n const helpSearch = searchBox(\"Search our help center…\");\n const helpInput = helpSearch.querySelector(\"input\")!;\n\n let loadingArticles = false;\n const loadArticles = async (force = false) => {\n if (!helpOn || (loadingArticles && !force)) return;\n loadingArticles = true;\n const q = query.trim();\n try {\n const r = await api().articles(q || undefined);\n if (q !== query.trim()) return;\n articles = r.articles;\n if (!q) hasArticles = r.articles.length > 0;\n } catch {\n articles = articles ?? [];\n } finally {\n loadingArticles = false;\n }\n draw();\n };\n const drawHome = () => {\n const hero = el(\n \"div\",\n { class: \"ckw-msgr-hero\" },\n el(\"span\", { class: \"ckw-msgr-brand\" }, avatar(\"sm\"), el(\"span\", {}, title)),\n el(\"p\", { class: \"ckw-msgr-hello\" }, greeting),\n el(\"span\", { class: \"ckw-msgr-online\" }, reply),\n );\n const last = (thread?.messages ?? []).at(-1);\n const parts: HTMLElement[] = [hero];\n if (last) {\n const recent = el(\n \"button\",\n { type: \"button\", class: \"ckw-msgr-card ckw-msgr-recent\" },\n el(\"span\", { class: \"ckw-msgr-card-label\" }, \"Recent message\"),\n el(\n \"span\",\n { class: \"ckw-msgr-recent-row\" },\n avatar(),\n el(\n \"span\",\n { class: \"ckw-msgr-card-main\" },\n el(\"span\", { class: \"ckw-msgr-card-sub ckw-msgr-recent-text\" }, last.body),\n el(\"span\", { class: \"ckw-msgr-card-meta\" }, `${last.from === \"visitor\" ? \"You\" : whoLabel[last.from]} · ${timeAgo(last.at)}`),\n ),\n unseen.length ? el(\"span\", { class: \"ckw-msgr-badge\" }, String(unseen.length)) : icon(I.next, 14),\n ),\n );\n recent.addEventListener(\"click\", () => go(\"messages\"));\n parts.push(recent);\n }\n const msgCard = el(\n \"button\",\n { type: \"button\", class: \"ckw-msgr-card\" },\n el(\"span\", { class: \"ckw-msgr-card-main\" }, el(\"b\", {}, \"Send us a message\"), el(\"span\", { class: \"ckw-msgr-card-sub\" }, reply)),\n el(\"span\", { class: \"ckw-msgr-go\" }, icon(I.send)),\n );\n msgCard.addEventListener(\"click\", () => go(\"messages\"));\n parts.push(msgCard);\n if (helpOn && hasArticles !== false) {\n const helpCard = el(\"div\", { class: \"ckw-msgr-card ckw-msgr-card-col\" }, searchBox());\n const top = (articles ?? []).slice(0, 4);\n if (top.length) helpCard.append(...top.map(articleRow));\n else if (articles === null) helpCard.append(el(\"div\", { class: \"ckw-skel ckw-msgr-skel\" }));\n parts.push(helpCard);\n }\n body.replaceChildren(...parts);\n };\n\n const drawHelp = () => {\n if (helpInput.value !== query) helpInput.value = query;\n const q = query.trim();\n const all = articles ?? [];\n const groups = new Map<string, ArticleSummary[]>();\n for (const a of all) groups.set(a.collection, [...(groups.get(a.collection) ?? []), a]);\n const inside = !q && collection !== null ? (groups.get(collection) ?? []) : null;\n const heading = q ? \"Search results\" : inside ? (collection ?? \"\") : \"Most read articles\";\n const parts: HTMLElement[] = [el(\"h2\", { class: \"ckw-msgr-help-h\" }, heading), helpSearch];\n if (articles === null) parts.push(el(\"div\", { class: \"ckw-skel\" }));\n else if (!all.length) {\n const ask = el(\"button\", { type: \"button\", class: \"ckw-btn ckw-btn-primary\" }, \"Send us a message\");\n ask.addEventListener(\"click\", () => go(\"messages\"));\n parts.push(el(\"div\", { class: \"ckw-msgr-empty\" }, el(\"p\", {}, q ? `Nothing found for “${q}”.` : \"No help articles yet.\"), ask));\n } else if (q || inside)\n parts.push(\n el(\n \"div\",\n { class: \"ckw-msgr-hlist\" },\n // The excerpt often opens with the article's own heading; the row shows the title already.\n ...(inside ?? all).map((a) => helpRow(a.title, a.excerpt.startsWith(a.title) ? a.excerpt.slice(a.title.length).trim() : a.excerpt, q ? a.collection : \"\", () => go({ article: a.id }))),\n ),\n );\n else\n parts.push(\n el(\n \"div\",\n { class: \"ckw-msgr-hlist\" },\n ...[...groups].map(([name, items]) =>\n helpRow(name, items.map((a) => a.title).join(\", \"), `${items.length} ${items.length === 1 ? \"article\" : \"articles\"}`, () => {\n collection = name;\n go(\"help\");\n replay(body, \"ckw-msgr-enter\");\n }),\n ),\n ),\n );\n // The field stays in place (moving it would take its focus); only what is around it changes.\n if (body.childNodes[1] !== helpSearch) body.replaceChildren(...parts);\n else {\n (body.firstChild as HTMLElement).replaceWith(parts[0]);\n while (body.childNodes.length > 2) body.lastChild!.remove();\n body.append(...parts.slice(2));\n }\n };\n\n let articleShown: { id: string; node: HTMLElement } | null = null;\n const drawArticle = (id: string) => {\n if (articleShown?.id === id) return body.replaceChildren(articleShown.node);\n const node = el(\"article\", { class: \"ckw-msgr-doc\" }, el(\"div\", { class: \"ckw-skel\" }));\n articleShown = { id, node };\n body.replaceChildren(node);\n api()\n .article(id)\n .then((a) => {\n const foot = el(\"div\", { class: \"ckw-msgr-rate\" });\n const drawRate = () => {\n if (rated.has(id)) return foot.replaceChildren(el(\"span\", {}, \"Thanks for letting us know.\"));\n const yes = el(\"button\", { type: \"button\", class: \"ckw-btn\" }, \"Yes\");\n const no = el(\"button\", { type: \"button\", class: \"ckw-btn\" }, \"No\");\n const rate = (helpful: boolean) => {\n rated = new Set(rated).add(id);\n drawRate();\n api()\n .rateArticle(id, helpful)\n .catch(() => undefined);\n if (!helpful) go(\"messages\");\n };\n yes.addEventListener(\"click\", () => rate(true));\n no.addEventListener(\"click\", () => rate(false));\n foot.replaceChildren(el(\"span\", {}, \"Did this answer your question?\"), el(\"span\", { class: \"ckw-msgr-rate-b\" }, yes, no));\n };\n drawRate();\n const ask = el(\"button\", { type: \"button\", class: \"ckw-btn ckw-msgr-ask\" }, icon(I.chat), \"Still need help? Send us a message\");\n ask.addEventListener(\"click\", () => go(\"messages\"));\n node.replaceChildren(\n el(\"p\", { class: \"ckw-msgr-doc-c\" }, a.collection),\n el(\"h2\", { class: \"ckw-msgr-doc-t\" }, a.title),\n el(\"p\", { class: \"ckw-msgr-doc-c\" }, `Updated ${timeAgo(a.updatedAt)}`),\n el(\"div\", { class: \"ckw-msgr-doc-b\" }, ...a.blocks.map(blockOf)),\n foot,\n ask,\n );\n })\n .catch((e: Error) => {\n articleShown = null;\n node.replaceChildren(el(\"p\", { class: \"ckw-msgr-error\" }, e.message));\n });\n };\n\n let drawn = -1;\n /** What the list shows, so a read that brings nothing new leaves it alone (no flicker, links stay where they are). */\n let listSig = \"\";\n /** How many bubbles the list had: the ones after it are new and glide in. */\n let listCount = -1;\n const intro = () =>\n el(\n \"div\",\n { class: \"ckw-msgr-intro\" },\n el(\"span\", { class: \"ckw-msgr-intro-av\" }, avatar()),\n el(\"span\", { class: \"ckw-msgr-intro-t\" }, el(\"b\", {}, title), el(\"span\", { class: \"ckw-msgr-online\" }, reply)),\n );\n const introNode = intro();\n const suggestions = el(\"div\", { class: \"ckw-msgr-sugg\" });\n const drawMessages = () => {\n const msgs = thread?.messages ?? [];\n const parts: HTMLElement[] = [introNode];\n if (!loaded) parts.push(el(\"div\", { class: \"ckw-skel\" }));\n else {\n const sig = `${msgs.map((m) => m.id).join(\",\")}|${pending ? pending.body : \"\"}|${Math.floor(Date.now() / 60_000)}`;\n if (sig !== listSig) {\n listSig = sig;\n const greet = el(\"li\", { class: \"ckw-msg\", \"data-from\": \"them\" }, el(\"div\", { class: \"ckw-bubble\" }, greeting));\n const items = [greet, ...msgs.map((m) => bubble(m)), ...(pending ? [bubble(pending, true)] : [])];\n if (listCount >= 0) items.slice(listCount).forEach((li) => li.setAttribute(\"data-new\", \"\"));\n listCount = items.length;\n list.replaceChildren(...items);\n }\n parts.push(list);\n // Before the visitor wrote: the most read articles as answers to tap.\n const top = !msgs.some((m) => m.from === \"visitor\") && !pending ? (articles ?? []).slice(0, 3) : [];\n if (top.length) {\n if (suggestions.childNodes.length !== top.length)\n suggestions.replaceChildren(\n ...top.map((a) => {\n const b = el(\"button\", { type: \"button\", class: \"ckw-msgr-sugg-b\" }, a.title);\n b.addEventListener(\"click\", () => go({ article: a.id }));\n return b;\n }),\n );\n parts.push(suggestions);\n }\n }\n if (thread?.conversation?.status === \"solved\" && !pending) parts.push(el(\"p\", { class: \"ckw-fine ckw-msgr-note\" }, \"This conversation is closed. Write to start a new one.\"));\n if (body.childNodes.length !== parts.length || parts.some((x, i) => body.childNodes[i] !== x)) body.replaceChildren(...parts);\n const count = msgs.length + (pending ? 1 : 0);\n if (count !== drawn) {\n drawn = count;\n body.scrollTop = body.scrollHeight;\n }\n err.textContent = error;\n if (error && !err.isConnected) form.prepend(err);\n else if (!error) err.remove();\n if (needEmail()) {\n if (emailOk()) email.removeAttribute(\"aria-invalid\");\n else email.setAttribute(\"aria-invalid\", \"true\");\n if (!email.isConnected) form.insertBefore(email, row);\n } else email.remove();\n send.disabled = !canSend();\n };\n\n const draw = () => {\n if (!open) return;\n pop.dataset.view = typeof view === \"string\" ? view : \"article\";\n drawBar();\n if (view === \"home\") drawHome();\n else if (view === \"messages\") drawMessages();\n else if (view === \"help\") drawHelp();\n else drawArticle(view.article);\n const kids: HTMLElement[] = [bar, body];\n if (view === \"messages\") kids.push(form);\n if (menu.isConnected) kids.push(menu);\n if (pop.childNodes.length !== kids.length || kids.some((k, i) => pop.childNodes[i] !== k)) pop.replaceChildren(...kids);\n placeMark();\n };\n\n // ---------- Reading the chat ----------\n const tick = async () => {\n ctrl?.abort();\n ctrl = new AbortController();\n try {\n take(await api().chat(ctrl.signal));\n error = \"\";\n } catch (e) {\n if ((e as Error).name === \"AbortError\") return;\n if (open && view === \"messages\") error = (e as Error).message;\n }\n loaded = true;\n draw();\n drawFab();\n schedule();\n };\n /** The next read: often while the chat is on screen, now and then while the visitor waits for an answer. */\n function schedule(now?: number) {\n clearTimeout(poll);\n const waiting = !!thread?.messages.some((m) => m.from === \"visitor\") && thread?.conversation?.status !== \"solved\";\n const wrote = (thread?.messages ?? []).filter((m) => m.from === \"visitor\").at(-1)?.at;\n const recent = !!wrote && Date.now() - new Date(wrote).getTime() < WAITING_FOR_MS;\n const ms = now ?? (watching() ? POLL_OPEN_MS : waiting && recent ? POLL_WAITING_MS : open || waiting ? POLL_IDLE_MS : 0);\n if (ms || now === 0) poll = setTimeout(() => void tick(), ms);\n }\n const onVisible = () => {\n if (document.visibilityState === \"visible\") schedule(0);\n else clearTimeout(poll);\n };\n document.addEventListener(\"visibilitychange\", onVisible);\n\n const submit = async () => {\n const msg = text.value.trim();\n if (!msg || pending || !emailOk()) return;\n chime.unlock();\n pending = { id: \"pending\", from: \"visitor\", body: msg, at: new Date().toISOString() };\n text.value = \"\";\n error = \"\";\n draw();\n try {\n take(await api().sendChat({ body: msg, email: needEmail() && email.value.trim() ? email.value.trim() : undefined, url: window.location.href.slice(0, 500) }));\n } catch (e) {\n text.value = msg;\n error = (e as Error).message;\n }\n pending = null;\n draw();\n schedule();\n };\n form.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n void submit();\n });\n text.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey && !e.isComposing) {\n e.preventDefault();\n void submit();\n }\n });\n text.addEventListener(\"input\", () => (send.disabled = !canSend()));\n email.addEventListener(\"input\", () => draw());\n\n function show(v: MessengerView | { article: string } = \"home\", still = false) {\n const was = open;\n open = true;\n view = v === \"help\" && !helpOn ? \"home\" : v;\n drawn = -1;\n previewGone = true;\n hideTeaser(true);\n pop.toggleAttribute(\"data-still\", still);\n enter(pop);\n if (was) replay(body, \"ckw-msgr-enter\");\n if (articles === null || (view === \"help\" && query)) void loadArticles();\n draw();\n drawFab();\n if (view === \"messages\") {\n markSeen();\n text.focus();\n }\n schedule(0);\n }\n function close() {\n if (!open) return;\n open = false;\n if (menu.isConnected) closeMenu();\n leave(pop, 200);\n drawFab();\n schedule();\n if (launcherOn) fab.focus();\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || !open) return;\n if (menuOpen()) {\n closeMenu();\n menuBtn.focus();\n } else close();\n };\n document.addEventListener(\"keydown\", onKey);\n\n // One read on load (the count and preview of answers not seen yet), and the article count for the Help tab.\n void tick();\n if (helpOn) void loadArticles();\n drawFab();\n if (o.opened) show(o.opened, true);\n\n return {\n open: (v) => show(v ?? \"home\"),\n close,\n toggle: () => (open ? close() : show()),\n destroy: () => {\n clearTimeout(poll);\n clearTimeout(teaserTimer);\n for (const t of leaving.values()) clearTimeout(t);\n ctrl?.abort();\n document.removeEventListener(\"keydown\", onKey);\n document.removeEventListener(\"visibilitychange\", onVisible);\n root.remove();\n },\n };\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Paywalls with several pages (SDK 0.14.0): what MRRocket's config serves under `paywalls` (one per placement, built
3
+ * in MRRocket › Conversion › Paywalls) and a small controller that walks the person through its pages, page after page,
4
+ * until the last one hands the chosen plan to the app. No DOM and no React: the web renderer (`mountPaywall` in
5
+ * flows-ui.ts, loaded only when a paywall opens) and the React Native one (native/flows-view.ts) draw `view()` and
6
+ * call the actions.
7
+ *
8
+ * MRRocket never takes a payment. The last page's button calls the app's `onPurchase(plan)`, which buys through the
9
+ * app's own store code (StoreKit or Play through RevenueCat or Adapty, or Stripe Checkout on the web); only when it
10
+ * resolves is the purchase recorded. It throwing keeps the paywall open with an error, resolving `false` (the person
11
+ * closed the store sheet) keeps it open without one.
12
+ *
13
+ * A running test on the paywall (`experiment`) gives each person their variant's pages, by the same stable hash as
14
+ * every other test (`assign`), and records `$exposure` when the paywall opens. What it records, as normal events under
15
+ * the SDK's analytics consent:
16
+ * - `$paywall` `{paywall, placement, variant, page, index, action: "page"}` the first time each page shows in a run,
17
+ * so MRRocket shows how many reach page 2 and 3;
18
+ * - `{action: "purchased", plan}` after `onPurchase` went through (a test's purchase goal counts it), and
19
+ * `{action: "closed", index}` when the person closed it.
20
+ */
21
+ import { type CockpitConfig, type VariantId } from "./core.js";
22
+ export declare const PAYWALL_EVENT = "$paywall";
23
+ /** One page of a paywall. Plans pages list the plans and buy; the others say why and go on. */
24
+ export interface PaywallPage {
25
+ id: string;
26
+ /** "benefits": a list of what the person gets; "proof": quotes of happy customers; "plans": the plans and the buy button. */
27
+ kind: "benefits" | "proof" | "plans";
28
+ title: string;
29
+ body?: string;
30
+ /** Benefits: one line each. */
31
+ items?: string[];
32
+ /** Proof: what customers said, and who. */
33
+ quotes?: {
34
+ text: string;
35
+ by?: string;
36
+ }[];
37
+ /** The button: "Continue" on the way, the buy button on the plans page ("Start free trial"). */
38
+ button?: string;
39
+ }
40
+ /** A plan the paywall offers. `id` is what the app buys: the store product id or the Stripe price, as set in MRRocket. */
41
+ export interface PaywallPlan {
42
+ id: string;
43
+ name: string;
44
+ /** As shown ("€59.99 / year"). The app's own store prices win when it passes `plans`. */
45
+ price: string;
46
+ /** A line under it ("€5 a month", "7 days free"). */
47
+ note?: string;
48
+ }
49
+ /** A published paywall as the config serves it. */
50
+ export interface PaywallConfig {
51
+ id: string;
52
+ /** The placement's key (`onboarding_end`), what the app opens: `paywall.open("onboarding_end")`. */
53
+ placement: string;
54
+ /** The running test on it, a key of `experiments`; each of its variants has pages under `variants`. */
55
+ experiment?: string;
56
+ /** Control (the live paywall) first. */
57
+ variants: {
58
+ id: VariantId;
59
+ pages: PaywallPage[];
60
+ }[];
61
+ plans: PaywallPlan[];
62
+ /** The plan picked before the person picks one. */
63
+ highlight?: string;
64
+ }
65
+ export interface PaywallResult {
66
+ /**
67
+ * "purchased": `onPurchase` went through; "chosen": the person picked a plan and there is no `onPurchase`, so the app
68
+ * buys it now (the store's purchase still counts for a test through RevenueCat or Adapty); "closed": the person
69
+ * closed it (or there was no paywall).
70
+ */
71
+ outcome: "purchased" | "chosen" | "closed";
72
+ plan?: PaywallPlan;
73
+ paywall?: string;
74
+ variant?: VariantId;
75
+ /** The page the person was on, from 0. */
76
+ index: number;
77
+ }
78
+ export interface PaywallOptions {
79
+ /**
80
+ * Buy the plan in your code (RevenueCat `purchasePackage`, Adapty `makePurchase`, Stripe Checkout). Throwing keeps
81
+ * the paywall open with an error; `false` keeps it open without one (the person cancelled the store sheet).
82
+ */
83
+ onPurchase?: (plan: PaywallPlan) => unknown;
84
+ /** Your store's plans with their local prices, by the same ids; they replace what MRRocket has for them. */
85
+ plans?: PaywallPlan[];
86
+ onClose?: (result: PaywallResult) => void;
87
+ }
88
+ export interface PaywallView {
89
+ paywall: PaywallConfig;
90
+ variant: VariantId;
91
+ page: PaywallPage;
92
+ index: number;
93
+ total: number;
94
+ last: boolean;
95
+ plans: PaywallPlan[];
96
+ /** The picked plan's id. */
97
+ plan?: string;
98
+ busy: boolean;
99
+ error?: string;
100
+ }
101
+ export interface PaywallEnv {
102
+ config: () => CockpitConfig | null;
103
+ distinctId: () => string;
104
+ /** Records an event under the SDK's consent. */
105
+ track: (event: string, props?: Record<string, unknown>) => void;
106
+ }
107
+ export interface PaywallHost {
108
+ /** Opens the paywall of a placement; resolves when it is bought or closed (at once with "closed" when there is none). */
109
+ open(placement: string, options?: PaywallOptions): Promise<PaywallResult>;
110
+ view(): PaywallView | null;
111
+ subscribe(listener: () => void): () => void;
112
+ next(): void;
113
+ back(): void;
114
+ pick(planId: string): void;
115
+ close(): void;
116
+ }
117
+ /** The pages of a person's variant: the test's when it runs (or shipped), else control's. */
118
+ export declare const paywallPages: (config: CockpitConfig | null, w: PaywallConfig, distinctId: string) => {
119
+ variant: string;
120
+ pages: PaywallPage[];
121
+ test: string | undefined;
122
+ } | null;
123
+ export declare const createPaywallHost: (env: PaywallEnv) => PaywallHost;
@@ -0,0 +1,131 @@
1
+ // src/paywall.ts
2
+ import { assign } from "./core.js";
3
+ var PAYWALL_EVENT = "$paywall";
4
+ var paywallPages = (config, w, distinctId) => {
5
+ const e = w.experiment ? config?.experiments.find((x) => x.key === w.experiment) : void 0;
6
+ const id = e ? assign(e, distinctId) : w.variants[0]?.id;
7
+ const v = w.variants.find((x) => x.id === id) ?? w.variants[0];
8
+ return v ? { variant: v.id, pages: v.pages, test: e?.status === "running" && !e.winner ? e.key : void 0 } : null;
9
+ };
10
+ var createPaywallHost = (env) => {
11
+ let run = null;
12
+ const listeners = /* @__PURE__ */ new Set();
13
+ const emit = () => {
14
+ for (const l of [...listeners]) {
15
+ try {
16
+ l();
17
+ } catch {
18
+ }
19
+ }
20
+ };
21
+ const base = () => run ? { paywall: run.w.id, placement: run.w.placement, variant: run.variant } : {};
22
+ const show = () => {
23
+ if (run && !run.seen.has(run.index)) {
24
+ run.seen.add(run.index);
25
+ env.track(PAYWALL_EVENT, { ...base(), page: run.pages[run.index].id, index: run.index, action: "page" });
26
+ }
27
+ emit();
28
+ };
29
+ const end = (r) => {
30
+ const c = run;
31
+ if (!c) return;
32
+ run = null;
33
+ if (r.outcome === "closed") c.options.onClose?.(r);
34
+ c.resolve(r);
35
+ emit();
36
+ };
37
+ const result = (outcome) => ({
38
+ outcome,
39
+ index: run?.index ?? 0,
40
+ ...run ? { paywall: run.w.id, variant: run.variant } : {},
41
+ ...outcome !== "closed" && run ? { plan: run.plans.find((p) => p.id === run.plan) } : {}
42
+ });
43
+ const buy = () => {
44
+ const c = run;
45
+ const plan = c?.plans.find((p) => p.id === c.plan);
46
+ if (!c || !plan || c.busy) return;
47
+ if (!c.options.onPurchase) return end(result("chosen"));
48
+ c.busy = true;
49
+ c.error = void 0;
50
+ emit();
51
+ Promise.resolve().then(() => c.options.onPurchase?.(plan)).then(
52
+ (ok) => {
53
+ c.busy = false;
54
+ if (run !== c) return;
55
+ if (ok === false) return emit();
56
+ env.track(PAYWALL_EVENT, { ...base(), page: c.pages[c.index].id, index: c.index, plan: plan.id, action: "purchased" });
57
+ end(result("purchased"));
58
+ },
59
+ () => {
60
+ c.busy = false;
61
+ c.error = "The purchase did not go through. Please try again.";
62
+ emit();
63
+ }
64
+ );
65
+ };
66
+ return {
67
+ open: (placement, options = {}) => {
68
+ if (run) return run.promise;
69
+ const config = env.config();
70
+ const w = config?.paywalls?.find((x) => x.placement === placement);
71
+ const picked = w ? paywallPages(config, w, env.distinctId()) : null;
72
+ if (!w || !picked?.pages.length) return Promise.resolve({ outcome: "closed", index: 0 });
73
+ const own = new Map((options.plans ?? []).map((p) => [p.id, p]));
74
+ const plans = w.plans.map((p) => own.get(p.id) ?? p);
75
+ let resolve = () => {
76
+ };
77
+ const promise = new Promise((r) => resolve = r);
78
+ const plan = plans.some((p) => p.id === w.highlight) ? w.highlight : plans[0]?.id;
79
+ run = { w, variant: picked.variant, pages: picked.pages, plans, index: 0, plan, busy: false, seen: /* @__PURE__ */ new Set(), options, resolve, promise };
80
+ if (picked.test) env.track("$exposure", { experiment: picked.test, variant: picked.variant });
81
+ show();
82
+ return promise;
83
+ },
84
+ view: () => run ? {
85
+ paywall: run.w,
86
+ variant: run.variant,
87
+ page: run.pages[run.index],
88
+ index: run.index,
89
+ total: run.pages.length,
90
+ last: run.index === run.pages.length - 1,
91
+ plans: run.plans,
92
+ plan: run.plan,
93
+ busy: run.busy,
94
+ error: run.error
95
+ } : null,
96
+ subscribe: (l) => {
97
+ listeners.add(l);
98
+ return () => listeners.delete(l);
99
+ },
100
+ next: () => {
101
+ if (!run || run.busy) return;
102
+ if (run.pages[run.index].kind === "plans" || run.index === run.pages.length - 1) return buy();
103
+ run.index++;
104
+ run.error = void 0;
105
+ show();
106
+ },
107
+ back: () => {
108
+ if (!run || run.busy || !run.index) return;
109
+ run.index--;
110
+ run.error = void 0;
111
+ emit();
112
+ },
113
+ pick: (id) => {
114
+ if (!run || run.busy || !run.plans.some((p) => p.id === id)) return;
115
+ run.plan = id;
116
+ run.error = void 0;
117
+ emit();
118
+ },
119
+ close: () => {
120
+ if (!run || run.busy) return;
121
+ env.track(PAYWALL_EVENT, { ...base(), index: run.index, action: "closed" });
122
+ end(result("closed"));
123
+ }
124
+ };
125
+ };
126
+ export {
127
+ PAYWALL_EVENT,
128
+ createPaywallHost,
129
+ paywallPages
130
+ };
131
+ //# sourceMappingURL=paywall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/paywall.ts"],"sourcesContent":["/**\n * Paywalls with several pages (SDK 0.14.0): what MRRocket's config serves under `paywalls` (one per placement, built\n * in MRRocket › Conversion › Paywalls) and a small controller that walks the person through its pages, page after page,\n * until the last one hands the chosen plan to the app. No DOM and no React: the web renderer (`mountPaywall` in\n * flows-ui.ts, loaded only when a paywall opens) and the React Native one (native/flows-view.ts) draw `view()` and\n * call the actions.\n *\n * MRRocket never takes a payment. The last page's button calls the app's `onPurchase(plan)`, which buys through the\n * app's own store code (StoreKit or Play through RevenueCat or Adapty, or Stripe Checkout on the web); only when it\n * resolves is the purchase recorded. It throwing keeps the paywall open with an error, resolving `false` (the person\n * closed the store sheet) keeps it open without one.\n *\n * A running test on the paywall (`experiment`) gives each person their variant's pages, by the same stable hash as\n * every other test (`assign`), and records `$exposure` when the paywall opens. What it records, as normal events under\n * the SDK's analytics consent:\n * - `$paywall` `{paywall, placement, variant, page, index, action: \"page\"}` the first time each page shows in a run,\n * so MRRocket shows how many reach page 2 and 3;\n * - `{action: \"purchased\", plan}` after `onPurchase` went through (a test's purchase goal counts it), and\n * `{action: \"closed\", index}` when the person closed it.\n */\nimport { type CockpitConfig, type VariantId, assign } from \"./core\";\n\nexport const PAYWALL_EVENT = \"$paywall\";\n\n/** One page of a paywall. Plans pages list the plans and buy; the others say why and go on. */\nexport interface PaywallPage {\n id: string;\n /** \"benefits\": a list of what the person gets; \"proof\": quotes of happy customers; \"plans\": the plans and the buy button. */\n kind: \"benefits\" | \"proof\" | \"plans\";\n title: string;\n body?: string;\n /** Benefits: one line each. */\n items?: string[];\n /** Proof: what customers said, and who. */\n quotes?: { text: string; by?: string }[];\n /** The button: \"Continue\" on the way, the buy button on the plans page (\"Start free trial\"). */\n button?: string;\n}\n\n/** A plan the paywall offers. `id` is what the app buys: the store product id or the Stripe price, as set in MRRocket. */\nexport interface PaywallPlan {\n id: string;\n name: string;\n /** As shown (\"€59.99 / year\"). The app's own store prices win when it passes `plans`. */\n price: string;\n /** A line under it (\"€5 a month\", \"7 days free\"). */\n note?: string;\n}\n\n/** A published paywall as the config serves it. */\nexport interface PaywallConfig {\n id: string;\n /** The placement's key (`onboarding_end`), what the app opens: `paywall.open(\"onboarding_end\")`. */\n placement: string;\n /** The running test on it, a key of `experiments`; each of its variants has pages under `variants`. */\n experiment?: string;\n /** Control (the live paywall) first. */\n variants: { id: VariantId; pages: PaywallPage[] }[];\n plans: PaywallPlan[];\n /** The plan picked before the person picks one. */\n highlight?: string;\n}\n\nexport interface PaywallResult {\n /**\n * \"purchased\": `onPurchase` went through; \"chosen\": the person picked a plan and there is no `onPurchase`, so the app\n * buys it now (the store's purchase still counts for a test through RevenueCat or Adapty); \"closed\": the person\n * closed it (or there was no paywall).\n */\n outcome: \"purchased\" | \"chosen\" | \"closed\";\n plan?: PaywallPlan;\n paywall?: string;\n variant?: VariantId;\n /** The page the person was on, from 0. */\n index: number;\n}\n\nexport interface PaywallOptions {\n /**\n * Buy the plan in your code (RevenueCat `purchasePackage`, Adapty `makePurchase`, Stripe Checkout). Throwing keeps\n * the paywall open with an error; `false` keeps it open without one (the person cancelled the store sheet).\n */\n onPurchase?: (plan: PaywallPlan) => unknown;\n /** Your store's plans with their local prices, by the same ids; they replace what MRRocket has for them. */\n plans?: PaywallPlan[];\n onClose?: (result: PaywallResult) => void;\n}\n\nexport interface PaywallView {\n paywall: PaywallConfig;\n variant: VariantId;\n page: PaywallPage;\n index: number;\n total: number;\n last: boolean;\n plans: PaywallPlan[];\n /** The picked plan's id. */\n plan?: string;\n busy: boolean;\n error?: string;\n}\n\nexport interface PaywallEnv {\n config: () => CockpitConfig | null;\n distinctId: () => string;\n /** Records an event under the SDK's consent. */\n track: (event: string, props?: Record<string, unknown>) => void;\n}\n\nexport interface PaywallHost {\n /** Opens the paywall of a placement; resolves when it is bought or closed (at once with \"closed\" when there is none). */\n open(placement: string, options?: PaywallOptions): Promise<PaywallResult>;\n view(): PaywallView | null;\n subscribe(listener: () => void): () => void;\n next(): void;\n back(): void;\n pick(planId: string): void;\n close(): void;\n}\n\n/** The pages of a person's variant: the test's when it runs (or shipped), else control's. */\nexport const paywallPages = (config: CockpitConfig | null, w: PaywallConfig, distinctId: string) => {\n const e = w.experiment ? config?.experiments.find((x) => x.key === w.experiment) : undefined;\n const id = e ? assign(e, distinctId) : w.variants[0]?.id;\n const v = w.variants.find((x) => x.id === id) ?? w.variants[0];\n return v ? { variant: v.id, pages: v.pages, test: e?.status === \"running\" && !e.winner ? e.key : undefined } : null;\n};\n\nexport const createPaywallHost = (env: PaywallEnv): PaywallHost => {\n let run: {\n w: PaywallConfig;\n variant: VariantId;\n pages: PaywallPage[];\n plans: PaywallPlan[];\n index: number;\n plan?: string;\n busy: boolean;\n error?: string;\n seen: Set<number>;\n options: PaywallOptions;\n resolve: (r: PaywallResult) => void;\n promise: Promise<PaywallResult>;\n } | null = null;\n const listeners = new Set<() => void>();\n const emit = () => {\n for (const l of [...listeners]) {\n try {\n l();\n } catch {\n // One renderer must not stop another.\n }\n }\n };\n const base = () => (run ? { paywall: run.w.id, placement: run.w.placement, variant: run.variant } : {});\n const show = () => {\n if (run && !run.seen.has(run.index)) {\n run.seen.add(run.index);\n env.track(PAYWALL_EVENT, { ...base(), page: run.pages[run.index].id, index: run.index, action: \"page\" });\n }\n emit();\n };\n const end = (r: PaywallResult) => {\n const c = run;\n if (!c) return;\n run = null;\n if (r.outcome === \"closed\") c.options.onClose?.(r);\n c.resolve(r);\n emit();\n };\n const result = (outcome: PaywallResult[\"outcome\"]): PaywallResult => ({\n outcome,\n index: run?.index ?? 0,\n ...(run ? { paywall: run.w.id, variant: run.variant } : {}),\n ...(outcome !== \"closed\" && run ? { plan: run.plans.find((p) => p.id === run!.plan) } : {}),\n });\n\n const buy = () => {\n const c = run;\n const plan = c?.plans.find((p) => p.id === c.plan);\n if (!c || !plan || c.busy) return;\n if (!c.options.onPurchase) return end(result(\"chosen\"));\n c.busy = true;\n c.error = undefined;\n emit();\n Promise.resolve()\n .then(() => c.options.onPurchase?.(plan))\n .then(\n (ok) => {\n c.busy = false;\n if (run !== c) return;\n if (ok === false) return emit();\n env.track(PAYWALL_EVENT, { ...base(), page: c.pages[c.index].id, index: c.index, plan: plan.id, action: \"purchased\" });\n end(result(\"purchased\"));\n },\n () => {\n c.busy = false;\n c.error = \"The purchase did not go through. Please try again.\";\n emit();\n },\n );\n };\n\n return {\n open: (placement, options = {}) => {\n if (run) return run.promise;\n const config = env.config();\n const w = config?.paywalls?.find((x) => x.placement === placement);\n const picked = w ? paywallPages(config, w, env.distinctId()) : null;\n if (!w || !picked?.pages.length) return Promise.resolve({ outcome: \"closed\", index: 0 });\n // The app's store prices replace MRRocket's for the same plans.\n const own = new Map((options.plans ?? []).map((p) => [p.id, p]));\n const plans = w.plans.map((p) => own.get(p.id) ?? p);\n let resolve: (r: PaywallResult) => void = () => {};\n const promise = new Promise<PaywallResult>((r) => (resolve = r));\n const plan = plans.some((p) => p.id === w.highlight) ? w.highlight : plans[0]?.id;\n run = { w, variant: picked.variant, pages: picked.pages, plans, index: 0, plan, busy: false, seen: new Set(), options, resolve, promise };\n if (picked.test) env.track(\"$exposure\", { experiment: picked.test, variant: picked.variant });\n show();\n return promise;\n },\n view: () =>\n run\n ? {\n paywall: run.w,\n variant: run.variant,\n page: run.pages[run.index],\n index: run.index,\n total: run.pages.length,\n last: run.index === run.pages.length - 1,\n plans: run.plans,\n plan: run.plan,\n busy: run.busy,\n error: run.error,\n }\n : null,\n subscribe: (l) => {\n listeners.add(l);\n return () => listeners.delete(l);\n },\n next: () => {\n if (!run || run.busy) return;\n // A plans page or the last page buys; any other page goes on.\n if (run.pages[run.index].kind === \"plans\" || run.index === run.pages.length - 1) return buy();\n run.index++;\n run.error = undefined;\n show();\n },\n back: () => {\n if (!run || run.busy || !run.index) return;\n run.index--;\n run.error = undefined;\n emit();\n },\n pick: (id) => {\n if (!run || run.busy || !run.plans.some((p) => p.id === id)) return;\n run.plan = id;\n run.error = undefined;\n emit();\n },\n close: () => {\n if (!run || run.busy) return;\n env.track(PAYWALL_EVENT, { ...base(), index: run.index, action: \"closed\" });\n end(result(\"closed\"));\n },\n };\n};\n"],"mappings":";AAoBA,SAA6C,cAAc;AAEpD,IAAM,gBAAgB;AAmGtB,IAAM,eAAe,CAAC,QAA8B,GAAkB,eAAuB;AAChG,QAAM,IAAI,EAAE,aAAa,QAAQ,YAAY,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,IAAI;AACnF,QAAM,KAAK,IAAI,OAAO,GAAG,UAAU,IAAI,EAAE,SAAS,CAAC,GAAG;AACtD,QAAM,IAAI,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC;AAC7D,SAAO,IAAI,EAAE,SAAS,EAAE,IAAI,OAAO,EAAE,OAAO,MAAM,GAAG,WAAW,aAAa,CAAC,EAAE,SAAS,EAAE,MAAM,OAAU,IAAI;AACnH;AAEO,IAAM,oBAAoB,CAAC,QAAiC;AAC/D,MAAI,MAaO;AACX,QAAM,YAAY,oBAAI,IAAgB;AACtC,QAAM,OAAO,MAAM;AACf,eAAW,KAAK,CAAC,GAAG,SAAS,GAAG;AAC5B,UAAI;AACA,UAAE;AAAA,MACN,QAAQ;AAAA,MAER;AAAA,IACJ;AAAA,EACJ;AACA,QAAM,OAAO,MAAO,MAAM,EAAE,SAAS,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE,WAAW,SAAS,IAAI,QAAQ,IAAI,CAAC;AACrG,QAAM,OAAO,MAAM;AACf,QAAI,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,GAAG;AACjC,UAAI,KAAK,IAAI,IAAI,KAAK;AACtB,UAAI,MAAM,eAAe,EAAE,GAAG,KAAK,GAAG,MAAM,IAAI,MAAM,IAAI,KAAK,EAAE,IAAI,OAAO,IAAI,OAAO,QAAQ,OAAO,CAAC;AAAA,IAC3G;AACA,SAAK;AAAA,EACT;AACA,QAAM,MAAM,CAAC,MAAqB;AAC9B,UAAM,IAAI;AACV,QAAI,CAAC,EAAG;AACR,UAAM;AACN,QAAI,EAAE,YAAY,SAAU,GAAE,QAAQ,UAAU,CAAC;AACjD,MAAE,QAAQ,CAAC;AACX,SAAK;AAAA,EACT;AACA,QAAM,SAAS,CAAC,aAAsD;AAAA,IAClE;AAAA,IACA,OAAO,KAAK,SAAS;AAAA,IACrB,GAAI,MAAM,EAAE,SAAS,IAAI,EAAE,IAAI,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,IACzD,GAAI,YAAY,YAAY,MAAM,EAAE,MAAM,IAAI,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,IAAK,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7F;AAEA,QAAM,MAAM,MAAM;AACd,UAAM,IAAI;AACV,UAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI;AACjD,QAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAM;AAC3B,QAAI,CAAC,EAAE,QAAQ,WAAY,QAAO,IAAI,OAAO,QAAQ,CAAC;AACtD,MAAE,OAAO;AACT,MAAE,QAAQ;AACV,SAAK;AACL,YAAQ,QAAQ,EACX,KAAK,MAAM,EAAE,QAAQ,aAAa,IAAI,CAAC,EACvC;AAAA,MACG,CAAC,OAAO;AACJ,UAAE,OAAO;AACT,YAAI,QAAQ,EAAG;AACf,YAAI,OAAO,MAAO,QAAO,KAAK;AAC9B,YAAI,MAAM,eAAe,EAAE,GAAG,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,OAAO,MAAM,KAAK,IAAI,QAAQ,YAAY,CAAC;AACrH,YAAI,OAAO,WAAW,CAAC;AAAA,MAC3B;AAAA,MACA,MAAM;AACF,UAAE,OAAO;AACT,UAAE,QAAQ;AACV,aAAK;AAAA,MACT;AAAA,IACJ;AAAA,EACR;AAEA,SAAO;AAAA,IACH,MAAM,CAAC,WAAW,UAAU,CAAC,MAAM;AAC/B,UAAI,IAAK,QAAO,IAAI;AACpB,YAAM,SAAS,IAAI,OAAO;AAC1B,YAAM,IAAI,QAAQ,UAAU,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AACjE,YAAM,SAAS,IAAI,aAAa,QAAQ,GAAG,IAAI,WAAW,CAAC,IAAI;AAC/D,UAAI,CAAC,KAAK,CAAC,QAAQ,MAAM,OAAQ,QAAO,QAAQ,QAAQ,EAAE,SAAS,UAAU,OAAO,EAAE,CAAC;AAEvF,YAAM,MAAM,IAAI,KAAK,QAAQ,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAC/D,YAAM,QAAQ,EAAE,MAAM,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC;AACnD,UAAI,UAAsC,MAAM;AAAA,MAAC;AACjD,YAAM,UAAU,IAAI,QAAuB,CAAC,MAAO,UAAU,CAAE;AAC/D,YAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,IAAI,EAAE,YAAY,MAAM,CAAC,GAAG;AAC/E,YAAM,EAAE,GAAG,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,OAAO,OAAO,GAAG,MAAM,MAAM,OAAO,MAAM,oBAAI,IAAI,GAAG,SAAS,SAAS,QAAQ;AACxI,UAAI,OAAO,KAAM,KAAI,MAAM,aAAa,EAAE,YAAY,OAAO,MAAM,SAAS,OAAO,QAAQ,CAAC;AAC5F,WAAK;AACL,aAAO;AAAA,IACX;AAAA,IACA,MAAM,MACF,MACM;AAAA,MACI,SAAS,IAAI;AAAA,MACb,SAAS,IAAI;AAAA,MACb,MAAM,IAAI,MAAM,IAAI,KAAK;AAAA,MACzB,OAAO,IAAI;AAAA,MACX,OAAO,IAAI,MAAM;AAAA,MACjB,MAAM,IAAI,UAAU,IAAI,MAAM,SAAS;AAAA,MACvC,OAAO,IAAI;AAAA,MACX,MAAM,IAAI;AAAA,MACV,MAAM,IAAI;AAAA,MACV,OAAO,IAAI;AAAA,IACf,IACA;AAAA,IACV,WAAW,CAAC,MAAM;AACd,gBAAU,IAAI,CAAC;AACf,aAAO,MAAM,UAAU,OAAO,CAAC;AAAA,IACnC;AAAA,IACA,MAAM,MAAM;AACR,UAAI,CAAC,OAAO,IAAI,KAAM;AAEtB,UAAI,IAAI,MAAM,IAAI,KAAK,EAAE,SAAS,WAAW,IAAI,UAAU,IAAI,MAAM,SAAS,EAAG,QAAO,IAAI;AAC5F,UAAI;AACJ,UAAI,QAAQ;AACZ,WAAK;AAAA,IACT;AAAA,IACA,MAAM,MAAM;AACR,UAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,MAAO;AACpC,UAAI;AACJ,UAAI,QAAQ;AACZ,WAAK;AAAA,IACT;AAAA,IACA,MAAM,CAAC,OAAO;AACV,UAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAG;AAC7D,UAAI,OAAO;AACX,UAAI,QAAQ;AACZ,WAAK;AAAA,IACT;AAAA,IACA,OAAO,MAAM;AACT,UAAI,CAAC,OAAO,IAAI,KAAM;AACtB,UAAI,MAAM,eAAe,EAAE,GAAG,KAAK,GAAG,OAAO,IAAI,OAAO,QAAQ,SAAS,CAAC;AAC1E,UAAI,OAAO,QAAQ,CAAC;AAAA,IACxB;AAAA,EACJ;AACJ;","names":[]}