@mediansh/widget 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +16 -0
- package/dist/index.js +844 -545
- package/dist/index.js.map +1 -1
- package/dist/{message-markdown-5ZZ6COCL.js → message-markdown-LOE74LBE.js} +4 -2
- package/dist/{message-markdown-5ZZ6COCL.js.map → message-markdown-LOE74LBE.js.map} +1 -1
- package/dist/widget.css +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../backend/convex/shared/support.ts","../../../apps/web/src/components/support-widget/sdk/median-support.tsx","../../../apps/web/src/components/support-widget/markdown-chunk.tsx","../../../apps/web/src/components/support-widget/widget-launcher.tsx","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/lib/SSRBase.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowDown.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowDown.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowUp.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowUp.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsClockwise.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowsClockwise.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsIn.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowsIn.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsOut.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowsOut.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Bug.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Bug.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretRight.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/CaretRight.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ChatCircleDots.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ChatCircleDots.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Check.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Check.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/EnvelopeSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/EnvelopeSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/File.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/File.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ImageSquare.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ImageSquare.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Lightbulb.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Lightbulb.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/LockSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/LockSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Play.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Play.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Plus.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Plus.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Sparkle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Sparkle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Star.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Star.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/UserCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/UserCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/WarningCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/WarningCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/X.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/X.es.js","../../../apps/web/src/components/icons.tsx","../../../apps/web/src/components/support-widget/launcher-position.ts","../../../apps/web/src/components/ui/message-scroller.tsx","../../../node_modules/.bun/@shadcn+react@0.3.0+03aa47d54245a271/node_modules/@shadcn/react/dist/chunk-HBS6WEDP.js","../../../node_modules/.bun/@shadcn+react@0.3.0+03aa47d54245a271/node_modules/@shadcn/react/dist/message-scroller/index.js","../../../node_modules/.bun/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.mjs","../../../node_modules/.bun/@radix-ui+react-slot@1.3.3+0f58469d5b3bd39f/node_modules/@radix-ui/react-slot/src/slot.tsx","../../../node_modules/.bun/@radix-ui+react-compose-refs@1.1.5+0f58469d5b3bd39f/node_modules/@radix-ui/react-compose-refs/src/compose-refs.tsx","../../../apps/web/src/components/ui/button.tsx","../../../apps/web/src/hooks/use-is-resizing.ts","../../../apps/web/src/lib/message-groups.ts","../../../apps/web/src/components/support-widget/use-stack-shift.ts","../../../apps/web/src/components/support-widget/motion.ts","../../../apps/web/src/components/support-widget/widget-composer.tsx","../src/next-image-shim.tsx","../../../apps/web/src/components/attachments/attachment-draft-chip.tsx","../../../apps/web/src/components/attachments/use-attachment-drafts.ts","../../../apps/web/src/components/attachments/use-attachment-target.ts","../../../apps/web/src/components/support-widget/widget-button.tsx","../../../apps/web/src/components/ui/text-field.ts","../../../apps/web/src/components/ui/textarea.tsx","../../../apps/web/src/hooks/use-typing-signal.ts","../../../apps/web/src/components/brand-art.ts","../../../apps/web/src/components/brand.tsx","../../../apps/web/src/components/support-widget/widget-badge.tsx","../../../apps/web/src/components/avatar.tsx","../../../apps/web/src/components/initial-badge.tsx","../../../apps/web/src/components/support-widget/widget-avatar.tsx","../../../apps/web/src/components/support-widget/widget-empty.tsx","../../../apps/web/src/components/support-widget/widget-header.tsx","../../../apps/web/src/components/support-widget/widget-loading.tsx","../../../apps/web/src/components/support-widget/widget-locked.tsx","../../../apps/web/src/components/ui/badge.tsx","../../../apps/web/src/components/support-widget/widget-attachments.tsx","../../../apps/web/src/components/ui/morph-bubble.tsx","../../../apps/web/src/components/support-widget/widget-bubble.tsx","../../../apps/web/src/components/support-widget/widget-message-body.tsx","../../../apps/web/src/components/support-widget/widget-typing.tsx","../../../apps/web/src/components/support-widget/widget-message.tsx","../../../apps/web/src/components/support-widget/widget-rating.tsx","../../../apps/web/src/components/ui/collapse.tsx","../../../apps/web/src/components/support-widget/widget-status.tsx","../../../apps/web/src/components/support-widget/support-widget.tsx","../../../apps/web/src/components/support-widget/use-launcher-drag.ts","../../../apps/web/src/components/support-widget/use-widget-sheet.ts","../../../apps/web/src/components/support-widget/use-page-lock.ts","../../../apps/web/src/components/support-widget/widget-spotlight.tsx","../../../apps/web/src/components/support-widget/widget-toast.tsx","../../../apps/web/src/components/support-widget/sdk/control.ts","../../backend/convex/shared/customData.ts","../../../apps/web/src/components/support-widget/sdk/custom-data.ts","../../../apps/web/src/components/support-widget/sdk/open-store.ts","../../backend/convex/_generated/api.js","../../backend/convex/shared/crashes.ts","../../../apps/web/src/components/support-widget/sdk/report-error.ts","../../../apps/web/src/components/support-widget/sdk/context.ts","../../../apps/web/src/components/support-widget/sdk/deployment.ts","../../backend/convex/shared/diagnostics.ts","../../../apps/web/src/components/support-widget/sdk/diagnostics.ts","../../../apps/web/src/components/support-widget/sdk/install.ts","../../../apps/web/src/components/support-widget/sdk/session.ts","../../../apps/web/src/components/support-widget/sdk/use-median-thread.ts","../../../apps/web/src/hooks/use-now.ts","../../../apps/web/src/lib/errors.ts","../../../apps/web/src/lib/time.ts","../../../apps/web/src/lib/upload.ts","../../../apps/web/src/components/support-widget/sdk/rating-skips.ts","../../../apps/web/src/components/support-widget/sdk/read-state.ts","../../../apps/web/src/components/support-widget/sdk/visitor-email.ts","../../../apps/web/src/components/support-widget/sdk/error-boundary.tsx","../../../apps/web/src/components/support-widget/sdk/use-identity.ts","../../../node_modules/.bun/cuelume@0.2.2/node_modules/cuelume/dist/sounds/recipes.js","../../../node_modules/.bun/cuelume@0.2.2/node_modules/cuelume/dist/audio/engine.js","../../../apps/web/src/components/support-widget/sdk/use-message-sound.ts","../../../apps/web/src/components/support-widget/sdk/use-navigation.ts","../../../apps/web/src/components/support-widget/sdk/mount.tsx","../../../apps/web/src/components/support-widget/sdk/median-feedback.tsx","../../backend/convex/shared/feedback.ts","../../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx","../../../apps/web/src/components/support-widget/feedback/feedback-popover.tsx","../../../apps/web/src/components/support-widget/use-hydrated.ts","../../../apps/web/src/components/support-widget/feedback/use-anchor.ts","../../../apps/web/src/components/support-widget/sdk/feedback-control.ts","../../../apps/web/src/components/support-widget/sdk/use-feedback-note.ts","../../../apps/web/src/components/support-widget/sdk/mount-feedback.tsx"],"sourcesContent":["/**\n * The rules the support side of Median follows: how long a message can be,\n * what an agent can be called, what an API key looks like.\n *\n * Deliberately pure, like shared/organizations.ts: no Convex imports, so the\n * web app can import this (`@median/backend/support`) and complain in the same\n * words the mutations would.\n */\n\n/** What an organization's AI agent is called until someone renames it. */\nexport const DEFAULT_AGENT_NAME = \"Median AI\";\n\n/**\n * Whether the agent may end a conversation on its own: resolving one it\n * finished, or closing one that was only ever spam.\n *\n * On unless a team says otherwise. A queue is only useful if what is left in\n * it is what somebody still has to look at, and a thread the agent answered\n * end to end is not one of those. Turning it off means every conversation\n * waits for a person to end it, which is the right call for a team that\n * reads all of them anyway.\n */\nexport const DEFAULT_AUTO_RESOLVE = true;\n\n/**\n * Whether resolved conversations get read for knowledge base suggestions.\n * On by default: the suggestions only ever land in a review queue, so the\n * cost of being wrong is a dismissal, not a bad answer.\n */\nexport const DEFAULT_LEARN_FROM_THREADS = true;\n\n/**\n * Whether the live agent may file knowledge suggestions from the middle of\n * a conversation, the moment something teaches it. On by default for the\n * same reason the reader is: everything lands in the same review queue,\n * so the cost of a bad one is a dismissal.\n */\nexport const DEFAULT_SUGGEST_KNOWLEDGE = true;\n\n/**\n * Whether the nightly sweep may resolve this organization's finished\n * threads. On by default for the same reason auto-resolve is: an inbox\n * that closes what is clearly done is the behavior a team expects.\n */\nexport const DEFAULT_NIGHTLY_SWEEP = true;\n\n/**\n * Whether the agent may file a bug or a suggestion when a customer hands one\n * over. On by default: a signal is a note in a list a person reads, not a\n * change to anything, and a complaint nobody wrote down is a complaint the\n * team never hears.\n */\nexport const DEFAULT_FILE_SIGNALS = true;\n\n/**\n * Whether the widget asks for an email before a visitor's first message. On\n * by default: an anonymous thread cannot be followed up, and half of support\n * is getting back to somebody. A host can waive it in code, and this is the\n * team's side of the same switch.\n */\nexport const DEFAULT_REQUIRE_EMAIL = true;\n\nexport const AGENT_NAME_MIN_LENGTH = 2;\nexport const AGENT_NAME_MAX_LENGTH = 40;\nexport const PERSONALITY_MAX_LENGTH = 2000;\n\nexport const MESSAGE_MAX_LENGTH = 4000;\n\nexport const VISITOR_NAME_MAX_LENGTH = 80;\nexport const VISITOR_EMAIL_MAX_LENGTH = 320;\nexport const VISITOR_AVATAR_URL_MAX_LENGTH = 512;\n/** Extra facts a host attaches to a visitor. Small on purpose. */\nexport const VISITOR_METADATA_MAX_ENTRIES = 16;\nexport const VISITOR_METADATA_MAX_LENGTH = 200;\n\n/** A message can carry a few files, not a filesystem. */\nexport const MESSAGE_MAX_ATTACHMENTS = 6;\nexport const ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;\n\n/**\n * What a visitor makes of a finished conversation: stars, and whatever they\n * wanted to say about it. Both sides check the score, since the widget draws\n * exactly this many stars and the backend takes nothing else.\n */\nexport const RATING_MIN_STARS = 1;\nexport const RATING_MAX_STARS = 5;\nexport const RATING_FEEDBACK_MAX_LENGTH = 1000;\n\n/** Whether a score is one of the stars actually offered. */\nexport function isRatingStars(stars: number): boolean {\n return (\n Number.isInteger(stars) &&\n stars >= RATING_MIN_STARS &&\n stars <= RATING_MAX_STARS\n );\n}\n\n/** Their words, trimmed and capped. Empty means they had none. */\nexport function cleanFeedback(feedback: string): string {\n return feedback.trim().slice(0, RATING_FEEDBACK_MAX_LENGTH);\n}\n\n/**\n * Publishable, like a Stripe pk_ or an Intercom app id: it ships in the\n * browser on the host's site, so it grants nothing beyond opening a support\n * conversation with that organization.\n */\nexport const API_KEY_PREFIX = \"median_pk_\";\n\n/**\n * The only credential a new Median integration needs. The public id is part\n * of the value so server-side SDKs can safely hand the widget its\n * `median_pk_...` identifier without another environment variable. The\n * secret tail never leaves the server.\n */\nexport const MEDIAN_KEY_PREFIX = \"median_key_\";\n\n/** Purpose-separated signing material is derived from the Median key. */\nexport const MEDIAN_SIGNATURE_PREFIX = \"median_sig_\";\n\nexport const MEDIAN_KEY_PUBLIC_ID_LENGTH = 32;\nexport const MEDIAN_KEY_SECRET_LENGTH = 64;\n\n/** Enough separate credentials for production, staging, and local work. */\nexport const MAX_MEDIAN_KEYS_PER_ORG = 10;\nexport const MEDIAN_KEY_NAME_MAX_LENGTH = 40;\n\n/**\n * The other kind, and the opposite of the one above: this one never goes near\n * a browser. It lives on the host's server, where it signs the id of whoever\n * is signed in, and anybody holding it can claim to be any of their users.\n */\nexport const SIGNING_KEY_PREFIX = \"median_sk_\";\n\n/**\n * What the REST API takes. Secret like the signing key: it lives on the\n * host's server and can read and write their whole inbox's visitor side, so\n * shipping one in a browser is handing the room key to the lobby.\n */\nexport const SECRET_API_KEY_PREFIX = \"median_api_\";\n\n/**\n * What webhook deliveries are signed with, one per endpoint. Held by us and\n * by the receiver, so the receiver can tell our POST from anybody else's.\n */\nexport const WEBHOOK_SECRET_PREFIX = \"median_whsec_\";\n\n/**\n * What tool endpoint calls are signed with, one per organization. Held by us\n * and by the host's server, so their handler can tell our POST from anybody\n * else's. The `@mediansh/agent-tools` package mirrors this literal in\n * `src/handler.ts`; change them together.\n */\nexport const TOOL_SECRET_PREFIX = \"median_toolsec_\";\n\n/**\n * What every prefix above starts with, and what it started with when the\n * product was called Portal.\n *\n * A key issued then is still a key. The rename went all the way to the wire\n * for anything minted from here on, but nothing already in somebody's\n * environment was invalidated by it, so every prefix has a twin and one rule\n * makes it. Read through `legacyPrefix` rather than writing `portal_` out\n * again: there is one family to retire, and this is the only line that names\n * it.\n */\nconst FAMILY = \"median_\";\nconst LEGACY_FAMILY = \"portal_\";\n\n/** The same prefix under the old name. */\nexport function legacyPrefix(prefix: string): string {\n return prefix.startsWith(FAMILY)\n ? `${LEGACY_FAMILY}${prefix.slice(FAMILY.length)}`\n : prefix;\n}\n\n/** Whether a credential carries this prefix under either name. */\nexport function hasPrefix(value: string, prefix: string): boolean {\n return value.startsWith(prefix) || value.startsWith(legacyPrefix(prefix));\n}\n\n/**\n * The prefix a credential actually carries, so anything derived from it\n * comes out in the family it belongs to. A legacy key's signing material\n * was derived as `portal_sig_` and is held that way, and re-deriving it as\n * `median_sig_` would stop it matching.\n */\nexport function prefixCarriedBy(value: string, prefix: string): string | null {\n if (value.startsWith(prefix)) return prefix;\n const legacy = legacyPrefix(prefix);\n return value.startsWith(legacy) ? legacy : null;\n}\n\n/**\n * The bounds on a session token, here rather than in the widget so the REST\n * API and the SDK refuse the same strings in the same words.\n */\nexport const SESSION_ID_MIN_LENGTH = 8;\nexport const SESSION_ID_MAX_LENGTH = 128;\n\n/**\n * A host's own id for a person. Long enough for a UUID or a Stripe style id\n * and short enough that nobody is putting a document in it.\n */\nexport const EXTERNAL_ID_MAX_LENGTH = 128;\n\n/**\n * How long a typing signal counts as live. Composers refresh it well inside\n * this while keys are hit, so anything older is a browser that went away.\n */\nexport const TYPING_TTL_MS = 12_000;\n\n/**\n * The bounds on a snooze. When it comes back is worked out on the client,\n * where the clock and the timezone are, so these only catch a number that\n * cannot have been meant: one already gone, or one so far out that nobody was\n * ever going to see the conversation again.\n */\nexport const SNOOZE_MIN_MS = 60_000;\nexport const SNOOZE_MAX_MS = 365 * 24 * 60 * 60_000;\n\n/** What is wrong with this snooze, in a sentence, or null if nothing is. */\nexport function snoozeIssue(until: number, now: number): string | null {\n if (!Number.isFinite(until)) return \"That is not a time to snooze until.\";\n if (until - now < SNOOZE_MIN_MS) {\n return \"Snoozing has to be for at least a minute.\";\n }\n if (until - now > SNOOZE_MAX_MS) {\n return \"Conversations can be snoozed for up to a year.\";\n }\n return null;\n}\n\n/**\n * A visitor's picture, or null if what we were handed cannot be one.\n *\n * https only. It ends up in an `<img>` on the inbox, and anything else is\n * either blocked as mixed content or was never a picture in the first place.\n * Whatever a host sends is theirs, so it is checked rather than trusted.\n */\nexport function cleanAvatarUrl(input: string | undefined): string | null {\n const url = input?.trim();\n if (!url || url.length > VISITOR_AVATAR_URL_MAX_LENGTH) return null;\n\n try {\n return new URL(url).protocol === \"https:\" ? url : null;\n } catch {\n return null;\n }\n}\n\n/**\n * An address, or null if what we were handed cannot be one.\n *\n * Deliberately barely a check: the shape of an address is the only thing\n * anyone can tell without sending mail to it. It is here because the agent\n * writes these down from whatever a customer typed, and \"looks like an\n * address\" should be decided in one place rather than at each caller.\n */\nexport function cleanEmail(input: string | undefined): string | null {\n const email = input?.trim();\n if (!email || email.length > VISITOR_EMAIL_MAX_LENGTH) return null;\n\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email) ? email : null;\n}\n\n/**\n * What to call a customer wherever a name is printed. Their name when we have\n * one, otherwise the number they were handed on arrival, so an anonymous\n * customer is \"Customer #12\" everywhere rather than one of a crowd of\n * anonymous visitors. The last fallback is for rows written before numbers\n * existed.\n */\nexport function customerDisplayName(\n name: string | null | undefined,\n customerNumber: number | null | undefined,\n): string {\n if (name) return name;\n if (customerNumber) return `Customer #${customerNumber}`;\n return \"Anonymous visitor\";\n}\n\n/** Collapses the whitespace someone pasted in without changing their words. */\nexport function normalizeAgentName(input: string): string {\n return input.replace(/\\s+/g, \" \").trim();\n}\n\n/** What is wrong with this agent name, in a sentence, or null if nothing is. */\nexport function agentNameIssue(name: string): string | null {\n if (name.length === 0) return \"Give your agent a name.\";\n if (name.length < AGENT_NAME_MIN_LENGTH) {\n return `Agent names need at least ${AGENT_NAME_MIN_LENGTH} characters.`;\n }\n if (name.length > AGENT_NAME_MAX_LENGTH) {\n return `Agent names have to be ${AGENT_NAME_MAX_LENGTH} characters or fewer.`;\n }\n return null;\n}\n\n/** What is wrong with this personality, or null. Empty is fine: quiet is a personality. */\nexport function personalityIssue(personality: string): string | null {\n if (personality.length > PERSONALITY_MAX_LENGTH) {\n return `Personalities have to be ${PERSONALITY_MAX_LENGTH} characters or fewer.`;\n }\n return null;\n}\n","\"use client\";\n\nimport { API_KEY_PREFIX, hasPrefix } from \"@median/backend/support\";\nimport { ConvexProvider, ConvexReactClient } from \"convex/react\";\nimport { useEffect, useState } from \"react\";\nimport {\n threadRendersMarkdown,\n warmMarkdownWhenIdle,\n} from \"../markdown-chunk\";\nimport { SupportLauncher } from \"../widget-launcher\";\nimport { WidgetSpotlight } from \"../widget-spotlight\";\nimport { WidgetToast } from \"../widget-toast\";\nimport type { SupportLauncherKind } from \"../types\";\nimport { useMedianOpenState, useRegisterMedianSupport } from \"./control\";\nimport { MEDIAN_DEPLOYMENT_URL } from \"./deployment\";\nimport type { MedianDiagnostics } from \"./diagnostics\";\nimport { MedianErrorBoundary } from \"./error-boundary\";\nimport { useMedianIdentity, useMissingCredentials } from \"./use-identity\";\nimport { useRememberInstall } from \"./install\";\nimport { useMessageSound } from \"./use-message-sound\";\nimport { useSupportNavigation } from \"./use-navigation\";\nimport {\n isSignedIn,\n useMedianThread,\n type MedianUser,\n} from \"./use-median-thread\";\n\n/**\n * How often the open panel says so. Well inside the server's window for\n * counting somebody as present, so one dropped beat changes nothing.\n */\nconst PRESENCE_BEAT_MS = 45_000;\n\ntype MedianSupportOptions = {\n /** Who is signed in on the host's site, if anyone. Shown to the team. */\n user?: MedianUser;\n /**\n * Whether a message carries what the browser already knows: time zone,\n * language, browser, OS, device, screen, and the page it was sent from.\n * On by default, because a team that has to ask for all six spends its\n * first reply asking. Pass `false` and none of it is read at all.\n */\n telemetry?: boolean;\n /**\n * Take questions from signed in people only.\n *\n * Until `user` says somebody is there, the panel asks them to sign in\n * instead of offering a composer, and no conversation is opened or read.\n * Pass `user` the moment you have it and the thread takes over.\n *\n * A rule about your own page, kept on your own page: it decides what this\n * widget offers, not what the API accepts. `user.id` with a signed `hash`\n * is the part nobody can talk their way around.\n */\n requireSignIn?: boolean;\n /**\n * Where your sign in lives, for the button on that panel.\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * requireSignIn\n * onSignIn={() => router.push(\"/login\")}\n * />\n *\n * Without it the panel says the same thing and offers no button, which is\n * right for a site whose sign in is already the first thing on the page.\n */\n onSignIn?: () => void;\n /**\n * Ask for an email before a visitor's first message. On by default: an\n * anonymous thread cannot be followed up, and half of support is getting\n * back to somebody. Pass `false` and the composer opens straight away.\n *\n * The composer asks once per browser; the answer rides their first message\n * and lands with their details on your side. A visitor your `user` already\n * names an email for is never asked, and `medianSupport.reset()` asks the\n * next person instead.\n *\n * Your team can turn the question off from the dashboard without a\n * redeploy, and either side saying no is enough to keep it away.\n */\n requireEmail?: boolean;\n /**\n * Watch what goes wrong on the page, so a bug report arrives with the\n * error already attached instead of after four messages of asking.\n *\n * <MedianSupport apiKey=\"median_pk_...\" diagnostics />\n *\n * `true` listens for uncaught errors and rejected promises, which changes\n * nothing about how your page runs. The object form adds the two that wrap\n * something of yours:\n *\n * diagnostics={{ network: true, console: true }}\n *\n * `network` wraps window.fetch to note requests that failed, `console`\n * wraps console.error. Both call through to what they replaced, and both\n * are put back when the widget leaves the page.\n *\n * Off by default: this reads your program's error stream, which is yours\n * to offer rather than ours to take. Nothing is sent on its own. The\n * newest snapshot rides the next message the customer sends, and only when\n * something new is in it.\n */\n diagnostics?: MedianDiagnostics;\n /**\n * Anything about your own app worth having next to a bug report: a build,\n * a route, a flag. Read when a message is sent, so it can change as they\n * move around.\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * diagnostics\n * appState={{ version: BUILD_SHA, plan: user.plan }}\n * />\n *\n * Twenty entries at most, and each one a line rather than a document.\n */\n appState?: Record<string, string | number | boolean>;\n /** Our button in the corner while it is closed, or nothing at all. */\n launcher?: SupportLauncherKind;\n /** Pass it, with `onOpenChange`, to hold the open state yourself. */\n open?: boolean;\n /** Every open and close, whoever asked for it. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Take the visitor to a page, when one of your own tools asks for it.\n *\n * <MedianSupport apiKey=\"median_pk_...\" onNavigate={router.push} />\n *\n * Called with a path on your own site, already checked against this page's\n * origin. Your router decides what happens: pass `router.push` and the\n * conversation stays open across the move.\n *\n * Without it a tool that asks to navigate cannot, and says so in the\n * console while you are building. Nothing else needs it.\n */\n onNavigate?: (path: string) => void;\n};\n\n/**\n * Two ways in, and every app has one of them.\n *\n * `apiKey` is the publishable id, and on its own it opens an anonymous\n * thread. `identity` is the path to a route built with `medianIdentity`,\n * which answers with the key and with whoever is signed in, already signed.\n * A framework that renders its root layout on the server cannot hand this\n * component a session any other way, so that is most of them.\n *\n * Passing both is worth it on a slow session: the button is up on the key\n * from the prop straight away, and the person arrives when the route answers.\n */\nexport type MedianSupportProps = MedianSupportOptions &\n (\n | { apiKey: string; identity?: string }\n | { apiKey?: string; identity: string }\n );\n\n/**\n * The whole SDK, as one component. Drop it on a page with your publishable API\n * key and the launcher, the thread, the AI and the inbox on the other side are\n * all wired up:\n *\n * <MedianSupport apiKey=\"median_pk_...\" />\n *\n * Optionally say who is signed in, and the team sees a person rather than\n * another anonymous visitor:\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * user={{ name: \"Ada\", email: \"ada@example.com\" }}\n * />\n *\n * There are three states rather than two: open, closed as a button in the\n * corner, and not on the page at all. Take the corner back and open it from\n * your own nav, from anywhere in your app, with no state to thread through:\n *\n * <MedianSupport apiKey=\"median_pk_...\" launcher=\"hidden\" />\n *\n * const support = useMedianSupport();\n * <button onClick={support.open}>Contact us</button>\n *\n * On a site nobody uses signed out, say so and the panel asks them to sign in\n * rather than opening a conversation with a stranger:\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * user={session?.user}\n * requireSignIn\n * onSignIn={() => router.push(\"/login\")}\n * />\n *\n * When somebody signs out, `medianSupport.reset()` forgets the conversation\n * along with them, so the next person at the keyboard starts fresh.\n *\n * That is the surface, on purpose. Everything else a support widget could be\n * asked to do is either our decision or a setting on the dashboard, so it can\n * change without every host having to redeploy.\n *\n * It brings its own connection, so it works on pages (and sites) that have\n * never heard of Convex.\n */\nexport function MedianSupport(props: MedianSupportProps) {\n return <MedianSupportPreview {...props} />;\n}\n\n/**\n * The same widget with the handful of knobs Median's own pages need: the\n * gallery pins it inside a frame rather than to the viewport, and `defaultOpen`\n * is there for a screenshot or a page that has room for nothing else.\n *\n * Nothing uses `defaultOpen` today, on purpose. Everywhere the widget is shown\n * it starts as the button, because that is the state a host's visitors meet it\n * in and the morph out of the corner is most of what there is to look at.\n *\n * Not exported from the package. A host gets `MedianSupport` and nothing else,\n * which is why these can exist at all without becoming promises we have to\n * keep.\n */\nexport function MedianSupportPreview({\n defaultOpen = false,\n className,\n ...props\n}: MedianSupportProps & {\n /** Where it starts, until anything opens or closes it. */\n defaultOpen?: boolean;\n className?: string;\n}) {\n return (\n <MedianErrorBoundary>\n <MedianIdentity\n {...props}\n defaultOpen={defaultOpen}\n className={className}\n />\n </MedianErrorBoundary>\n );\n}\n\n/**\n * Settles who the widget is for before anything is connected.\n *\n * Both halves can come from a prop or from the host's identity route, and a\n * prop wins: a host who has the key to hand should not wait on a fetch to put\n * the button up, and one who already knows the signed in person is not told\n * otherwise by a route that answers later.\n *\n * Nothing is rendered until there is a key from one of the two. Without one\n * there is nobody to talk to, and a button that opens onto an error is worse\n * on somebody's page than no button for the moment it takes to answer.\n */\ntype GateProps = MedianSupportOptions & {\n apiKey?: string;\n identity?: string;\n defaultOpen: boolean;\n className?: string;\n};\n\nfunction MedianIdentity({ apiKey, identity, user, ...rest }: GateProps) {\n const resolved = useMedianIdentity(identity);\n useMissingCredentials(\"MedianSupport\", apiKey, identity);\n const key = apiKey ?? resolved.apiKey;\n\n if (key === undefined) return null;\n\n return (\n <MedianConnection\n {...rest}\n apiKey={key}\n user={user ?? resolved.user}\n isResolvingIdentity={resolved.isLoading}\n />\n );\n}\n\ntype ConnectionProps = MedianSupportOptions & {\n apiKey: string;\n /** The host's identity route has been asked and has not answered yet. */\n isResolvingIdentity: boolean;\n defaultOpen: boolean;\n className?: string;\n};\n\n/**\n * A key with the wrong shape would only ever fail later, quietly, as a widget\n * that never appears. Say so now, in the console, while the person who pasted\n * it is still looking at this page.\n *\n * The key is truncated in the message: if what was pasted is a secret from\n * somewhere else, the console should not repeat all of it.\n */\nfunction useApiKeyShapeWarning(apiKey: string) {\n useEffect(() => {\n if (hasPrefix(apiKey, API_KEY_PREFIX)) return;\n\n const shown =\n apiKey === \"\"\n ? \"an empty string\"\n : `\"${apiKey.length > 16 ? `${apiKey.slice(0, 16)}…` : apiKey}\"`;\n console.error(\n `Median: the apiKey passed to <MedianSupport> is ${shown}, which does not look like the browser-safe id from publicKeyFromMedianKey(MEDIAN_KEY). It should start with ${API_KEY_PREFIX}.`,\n );\n }, [apiKey]);\n}\n\nfunction MedianConnection(props: ConnectionProps) {\n // Its own client rather than the app's, so the widget is self contained on a\n // host site. Lazy so a missing URL fails at render, into the boundary.\n const [client] = useState(() => {\n if (!MEDIAN_DEPLOYMENT_URL) {\n throw new Error(\n \"The Median widget was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL.\",\n );\n }\n return new ConvexReactClient(MEDIAN_DEPLOYMENT_URL);\n });\n\n return (\n <ConvexProvider client={client}>\n <MedianLauncher {...props} />\n </ConvexProvider>\n );\n}\n\nfunction MedianLauncher({\n apiKey,\n user,\n telemetry,\n diagnostics,\n appState,\n requireSignIn = false,\n onSignIn,\n requireEmail = true,\n launcher,\n defaultOpen,\n open,\n onOpenChange,\n onNavigate,\n isResolvingIdentity,\n className,\n}: ConnectionProps) {\n useRegisterMedianSupport();\n useApiKeyShapeWarning(apiKey);\n // So a crash screen can file a report from a tree this widget is no\n // longer in. See `install.ts`.\n useRememberInstall(apiKey, user);\n\n const [isOpen, setOpen] = useMedianOpenState({\n open,\n defaultOpen,\n onOpenChange,\n });\n\n // Whoever is at the keyboard has not said who they are, and this host only\n // takes questions from people who have.\n //\n // Not while the identity route is still being read. Nobody has said there\n // is no one signed in yet, and inviting somebody who is already signed in\n // to sign in, for the half second before their own name arrives, reads as a\n // widget that has lost them.\n const isLocked =\n requireSignIn && !isResolvingIdentity && !isSignedIn(user);\n\n const {\n presence,\n messages,\n ask,\n conversationId,\n isLoading,\n isSending,\n askForEmail,\n setVisitorEmail,\n awaitingHuman,\n rating,\n unreadCount,\n markSeen,\n reportPresence,\n sendError,\n send,\n setTyping,\n } = useMedianThread(\n apiKey,\n user,\n telemetry,\n isLocked,\n diagnostics,\n appState,\n requireEmail,\n );\n\n // Nothing here is settled yet: either the thread is on its way, or the\n // route that says whose thread it should be is. The panel shows the same\n // shimmer for both, because from the visitor's side they are one wait.\n const isSettling = isLoading || isResolvingIdentity;\n\n // Open is looking. It runs again as replies land, so a conversation read\n // live never builds up a count behind the panel that is showing it.\n useEffect(() => {\n if (isOpen) markSeen();\n }, [isOpen, markSeen]);\n\n // Somebody who has been answered here before, with the answers still behind\n // the button. They are the likeliest person on the page to open it, so the\n // renderer is fetched once the page has finished its own work rather than\n // waited for on the click. Everybody else pays nothing until they reach for\n // it. See `markdown-chunk.ts`.\n useEffect(() => {\n if (!threadRendersMarkdown(messages)) return;\n return warmMarkdownWhenIdle();\n }, [messages]);\n\n // The same fact, told to the server as a heartbeat: on open, on coming\n // back to the tab, and every so often in between. It is what keeps a\n // reply they are watching arrive from also landing in their email.\n useEffect(() => {\n if (!isOpen) return;\n\n const beat = () => {\n if (document.visibilityState === \"visible\") reportPresence();\n };\n beat();\n const interval = setInterval(beat, PRESENCE_BEAT_MS);\n document.addEventListener(\"visibilitychange\", beat);\n window.addEventListener(\"focus\", beat);\n return () => {\n clearInterval(interval);\n document.removeEventListener(\"visibilitychange\", beat);\n window.removeEventListener(\"focus\", beat);\n };\n }, [isOpen, reportPresence]);\n\n // Whether the panel is up or not: somebody who asked to be taken somewhere\n // and then closed the panel still asked.\n const direction = useSupportNavigation({\n messages,\n ask,\n // Signing in is the case this exists for. A page that has been watching\n // an empty query is handed the account's whole history the moment the\n // widget can say who they are, and an instruction from a conversation\n // they had last week is not an instruction to anybody now.\n conversationId,\n // Locked, there is no thread being read at all, so the first one to\n // arrive after somebody signs in is history like any other first look.\n isLoading: isSettling || isLocked,\n onNavigate,\n });\n\n // Also whether the panel is up or not, and for the same reason as the ring:\n // a reply landing behind a closed panel is the one most worth hearing.\n useMessageSound({\n messages,\n conversationId,\n isLoading: isSettling || isLocked,\n });\n\n // Until the config lands there is no name to put on the header, so the\n // launcher waits as a button and the panel shimmers if opened.\n const resolvedPresence = presence ?? {\n name: \"Support\",\n status: \"Connecting\",\n team: [],\n };\n\n // Whose name goes on the line about the page moving. The AI is the one that\n // called the tool, so it is the one that says so.\n const mover = resolvedPresence.team.find((member) => member.kind === \"ai\");\n\n return (\n <>\n {/* Keyed on the message that asked, so a second instruction is a second\n ring and a second line rather than a stale one carrying on. Two\n keys rather than one: these are siblings, and one message asking for\n both would otherwise hand them the same name. */}\n {direction?.selector != null && (\n <WidgetSpotlight\n key={`ring:${direction.key}`}\n selector={direction.selector}\n />\n )}\n {direction?.didNavigate === true && mover !== undefined && (\n <WidgetToast key={`moved:${direction.key}`} agent={mover}>\n {mover.name} navigated you here\n </WidgetToast>\n )}\n\n <SupportLauncher\n presence={resolvedPresence}\n messages={messages}\n // Passed through as a promise, so the composer can hold the draft on\n // a failed send and clear it on a delivered one.\n onSend={send}\n onTypingChange={setTyping}\n isLoading={isSettling}\n isLocked={isLocked}\n onSignIn={onSignIn}\n askForEmail={askForEmail}\n onSubmitEmail={setVisitorEmail}\n isSending={isSending}\n awaitingHuman={awaitingHuman}\n rating={rating}\n unreadCount={unreadCount}\n notice={sendError}\n launcher={launcher}\n // Always controlled from here: the panel answers to the host's own\n // prop, to their trigger anywhere on the page, and to its own button,\n // and this is where those three are settled into one answer.\n open={isOpen}\n onOpenChange={setOpen}\n className={className}\n />\n </>\n );\n}\n","\"use client\";\n\nimport { lazy, useSyncExternalStore } from \"react\";\nimport type { SupportMessage } from \"./types\";\n\n/**\n * The markdown renderer, fetched when there is a reason to and not before.\n *\n * It is the heaviest thing the widget can reach: a parser, a sanitiser and an\n * HTML tokeniser, and together they outweigh everything else in the package\n * put together. They also cannot render anything until the panel is open, and\n * most visitors on most pages never open it. Loading them with the page\n * spends that on everybody to serve the few.\n *\n * So the import is a call rather than a statement, and the bundle splits\n * where the call is. What a host's page pays for on load is the button. The\n * rest arrives on the first sign that somebody wants it, which is early\n * enough to be there before they do:\n *\n * - the pointer reaching the launcher, or a tab landing on it\n * - the panel opening, whoever opened it\n * - a page going idle with an already answered thread behind the button\n *\n * Until it lands, a reply renders as the text it was written as, which is the\n * same paragraph a visitor's own message gets. A failed fetch leaves that in\n * place rather than leaving a hole where the answer was.\n */\n\nconst load = () => import(\"@/components/ui/message-markdown\");\n\n/**\n * The renderer itself, and the only place it is rendered from.\n *\n * `lazy` rather than a component held in a variable, so this is one component\n * for the life of the page rather than a new one per render. It is only ever\n * put on screen once `useMarkdownReady` says the module is already in hand,\n * so the suspense it can throw is a guard rather than a state anybody waits\n * in.\n */\nexport const MessageMarkdown = lazy(async () => ({\n default: (await load()).MessageMarkdown,\n}));\n\nlet ready = false;\nlet inFlight = false;\nconst listeners = new Set<() => void>();\n\n/**\n * Fetch it, unless it is already here or already on its way.\n *\n * Safe to call from anywhere, as often as you like: everything after the\n * first call in a page's life is a no-op. A fetch that fails clears the flag\n * so a later trigger can try again, which covers the tunnel a phone goes\n * through between the page loading and the visitor asking a question.\n */\nexport function warmMarkdown(): void {\n if (ready || inFlight) return;\n inFlight = true;\n\n void load().then(\n () => {\n ready = true;\n for (const listener of listeners) listener();\n },\n () => {\n inFlight = false;\n },\n );\n}\n\n/** How long to wait for an idle moment that may never come. */\nconst IDLE_FALLBACK_MS = 2_000;\n\n/**\n * The same, once the page has nothing better to do. Returns the cancel, so an\n * effect torn down before the browser gets round to it does not go on to\n * fetch a megabyte for a widget that has left the page.\n *\n * `requestIdleCallback` is missing on Safari before 17, so a timeout stands\n * in. The exact delay does not matter; being after the page's own work does.\n */\nexport function warmMarkdownWhenIdle(): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n if (typeof window.requestIdleCallback === \"function\") {\n const handle = window.requestIdleCallback(() => warmMarkdown());\n return () => window.cancelIdleCallback(handle);\n }\n\n const timer = setTimeout(warmMarkdown, IDLE_FALLBACK_MS);\n return () => clearTimeout(timer);\n}\n\n/**\n * Whether there is anything in this thread that markdown would render\n * differently from a plain paragraph.\n *\n * Only the house voice writes markdown. What a visitor types is quoted\n * verbatim wherever it lands, so a thread of nothing but questions never\n * needs any of this and never fetches it.\n */\nexport function threadRendersMarkdown(messages: SupportMessage[]): boolean {\n return messages.some(\n (message) => message.sender !== \"visitor\" && message.body.length > 0,\n );\n}\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nconst read = () => ready;\n// False on the server and through hydration both, so the first client pass\n// renders what the server sent rather than a tree it has to throw away.\nconst onServer = () => false;\n\n/** Whether the module is in hand, so rendering it will not suspend. */\nexport function useMarkdownReady(): boolean {\n return useSyncExternalStore(subscribe, read, onServer);\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { ChatCircleDots } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport {\n clipOrigin,\n closedClip,\n type LauncherSide,\n} from \"./launcher-position\";\nimport { warmMarkdown } from \"./markdown-chunk\";\nimport { SupportWidget } from \"./support-widget\";\nimport { BUTTON_Y, useLauncherDrag } from \"./use-launcher-drag\";\nimport { useWidgetSheet } from \"./use-widget-sheet\";\nimport type {\n SupportLauncherKind,\n SupportMessage,\n SupportPresence,\n SupportRating,\n} from \"./types\";\n\nconst DEFAULT_WIDTH = \"24rem\";\nconst DEFAULT_HEIGHT = \"34rem\";\nconst DEFAULT_BUTTON_SIZE = \"3.5rem\";\n\n/**\n * Bigger, for a thread you are actually reading rather than glancing at.\n *\n * More of the growth goes into the height than the width, because that is the\n * axis a conversation runs out of: room to see what was said, rather than room\n * per line. The width still moves, and moving it re-wraps every bubble as it\n * goes, so it is kept to the smaller number of the two.\n */\nconst EXPANDED_WIDTH = \"30rem\";\nconst EXPANDED_HEIGHT = \"46rem\";\n\n/**\n * The morph, as a clip rather than a resize.\n *\n * The panel is always laid out at its full size. Closed, it is clipped down to\n * a circle in the corner the size of the button; open, the clip is the panel\n * itself. Only the clip travels.\n *\n * This matters. Animating width and height means the browser lays out the whole\n * panel again on every frame, and the message scroller measures its viewport\n * every time that happens, so it fights the animation the entire way. Clipping\n * touches no layout at all: nothing inside ever moves, reflows or gets measured,\n * it is simply revealed.\n *\n * Where it grows out of is `launcher-position.ts`. The button can be dragged\n * anywhere up or down either edge, and the panel has to follow it there.\n */\n/**\n * The panel's own `rounded-xl`, to the same decimal.\n *\n * The clip used to be a hair rounder than the panel inside it, which is why\n * the panel had to give up its border: two curves that nearly agree meet in a\n * hairline, and a hairline that moves is the thing that makes an animation\n * look broken. Same number, one curve, and the border can come back.\n */\nconst PANEL_RADIUS = \"0.75rem\";\n\nconst OPEN_CLIP = `inset(0px 0px 0px 0px round ${PANEL_RADIUS})`;\n\n/**\n * The button's height inside the box.\n *\n * Measured and written by the drag before paint, because it is the difference\n * between two lengths taken against different boxes and no amount of `calc`\n * gets at that. The fallback is the resting place of a widget nobody has\n * moved, which is the one the server rendered and the only one on screen\n * before the measurement lands.\n */\nconst buttonY = (buttonSize: string) =>\n `var(${BUTTON_Y}, calc(100% - ${buttonSize}))`;\n\n/**\n * How far off the edges the whole thing sits. Close enough to read as parked\n * against the side rather than floating near it, and still clear of the corner\n * radius on a phone.\n */\nconst MARGIN = \"1rem\";\n\n/**\n * The bounce rides on a scale, not on the clip.\n *\n * A clip cannot show an overshoot: carrying past \"fully revealed\" only means\n * clipping outside the box, which looks like nothing at all. So the panel comes\n * up the last few percent of its size as it opens, and that is what carries a\n * touch too far and settles back. Around four pixels on a panel this wide,\n * which is about right for something you feel rather than watch.\n *\n * Scale is composited, so this costs the same as the clip does: nothing.\n */\nconst CLOSED_SCALE = \"scale(0.94)\";\nconst OPEN_SCALE = \"scale(1)\";\n\n/**\n * Where the panel comes from when there is no button for it to come from.\n *\n * A morph needs two shapes and one of them has gone. Clipping down to a circle\n * nobody can see is not an origin, it is a place the panel happens to vanish\n * at, and growing out of it reads as the corner deciding to produce a panel.\n * So it rises the last few pixels into place instead, which is what everything\n * that arrives out of nothing does.\n */\nconst RISEN = \"translateY(0.5rem) scale(0.98)\";\n\n/**\n * The shape, shared by the panel and the shadow layer behind it. One function\n * so the two cannot drift a frame apart.\n */\nconst shape = (\n isOpen: boolean,\n buttonSize: string,\n side: LauncherSide,\n hasBubble: boolean,\n) =>\n hasBubble\n ? {\n clipPath: isOpen\n ? OPEN_CLIP\n : closedClip(side, buttonY(buttonSize), buttonSize),\n transform: isOpen ? OPEN_SCALE : CLOSED_SCALE,\n // The point it grows out of, so the closed circle stays put under the\n // button rather than shrinking towards the middle.\n transformOrigin: clipOrigin(side, buttonY(buttonSize), buttonSize),\n }\n : { clipPath: OPEN_CLIP, transform: isOpen ? \"none\" : RISEN };\n\n/**\n * The two properties the morph is actually about, named rather than `all`.\n *\n * `transform-origin` is the one deliberately left out. It moves whenever the\n * button does, and easing a shape's origin across a panel while the shape\n * itself holds still is a swim, not a morph.\n */\nconst MORPH =\n \"transition-[clip-path,transform] duration-450 ease-spring motion-reduce:transition-none\";\n\n/**\n * The other one, for a widget with no button. Shorter and a pure deceleration:\n * a spring's overshoot is the button's swagger, and a panel that simply\n * appeared has not earned it.\n */\nconst ARRIVE =\n \"transition-transform duration-200 ease-out-quint motion-reduce:transition-none\";\n\n/**\n * The phone's version of the morph: none. A panel about to be the whole\n * screen has no corner to grow out of, so it rises into place as a sheet,\n * which is the shape every thumb has already been taught. A touch longer than\n * ARRIVE because it travels further, and the same pure deceleration.\n */\nconst SHEET =\n \"fixed transition-[opacity,transform] duration-300 ease-out-quint motion-reduce:transition-none\";\n\n/** Where the sheet waits: a little below its feet, ready to come up. */\nconst SHEET_RISEN = \"translateY(2rem)\";\n\n/**\n * A sheet is the screen, so the card's own dress goes: no corners against\n * edges that already have their own, no border where the screen ends, and\n * room for the notch and the home bar on hosts that let content under them.\n *\n * The home bar's room goes back while the keyboard has the bottom of the\n * screen, which is the sheet's own attribute for it: the panel's foot is then\n * the keyboard's top edge, and the inset would hold the composer a thumb's\n * width above the keys for no reason. It transitions rather than snapping,\n * since the keyboard is on its way in while this changes its mind.\n */\nconst SHEET_PANEL = cn(\n \"rounded-none border-0 pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]\",\n \"transition-[padding] duration-200 ease-out motion-reduce:transition-none\",\n \"[[data-keyboard=up]_&]:pb-0\",\n);\n\n/**\n * The three things about the box itself that move: whether it is there at all,\n * and how wide and tall it is.\n *\n * One declaration rather than two named ones, because they are one property\n * list. Two classes reads better and does not work: both set\n * `transition-property`, so the second simply replaces the first.\n *\n * With no button in the corner there is nothing to show while it is closed, so\n * the whole thing fades with the morph. Quicker than the morph either way: the\n * clip still carries the panel out of the corner and back into it, but the few\n * frames where that is an empty circle are spent at zero.\n *\n * What is not in the list is the travel between corners. That is an animation\n * on the node rather than a transition on this class, so a drag can move the\n * box every frame without a transition trying to catch up with it.\n *\n * `ease-out` rather than the app's usual `ease-out-quint`, which is the one\n * exception in here and is about what is moving. Quint spends about seven\n * tenths of the distance in the first quarter of the time, which is what makes\n * it feel quick on something composited. This is a size, so every one of those\n * frames lays the panel out again and re-wraps the text in it, and thirty odd\n * pixels of that per frame reads as the panel stuttering rather than growing.\n * A gentler curve over slightly longer moves the same distance in far more\n * even steps.\n */\nconst BOX =\n \"transition-[opacity,width,height] duration-300 ease-out motion-reduce:transition-none\";\n\n/**\n * The button, and the panel it turns into.\n *\n * The shadow sits on a layer above the clip rather than on it, because a filter\n * is painted before a clip and would otherwise be cut away with everything\n * else. On the parent it reads the clipped shape's alpha instead, so the shadow\n * follows the corner round as it opens.\n *\n * Uncontrolled by default. Pass `open` and `onOpenChange` to drive it yourself,\n * for a host that opens support from its own menu. Pass `launcher=\"hidden\"`\n * too and the corner is theirs again: nothing is on the page until they ask\n * for it.\n */\nexport function SupportLauncher({\n presence,\n messages,\n onSend,\n onTypingChange,\n isLoading = false,\n isLocked = false,\n onSignIn,\n askForEmail = false,\n onSubmitEmail,\n isSending = false,\n awaitingHuman = false,\n rating,\n unreadCount = 0,\n notice,\n showBadge = true,\n width = DEFAULT_WIDTH,\n height = DEFAULT_HEIGHT,\n expandedWidth = EXPANDED_WIDTH,\n expandedHeight = EXPANDED_HEIGHT,\n buttonSize = DEFAULT_BUTTON_SIZE,\n launcher = \"bubble\",\n defaultOpen = false,\n open,\n onOpenChange,\n className,\n}: {\n presence: SupportPresence;\n messages: SupportMessage[];\n /** Awaited by the composer, which keeps the draft if it rejects. */\n onSend?: (body: string, files: File[]) => unknown;\n /** The visitor's own typing, throttled by the composer. */\n onTypingChange?: (isTyping: boolean) => unknown;\n isLoading?: boolean;\n /** Nobody is signed in, on a host that asks people to be. */\n isLocked?: boolean;\n /** Takes the visitor to the host's own sign in. */\n onSignIn?: () => void;\n /**\n * The composer asks for an email before a first message. Off here by\n * default: only the SDK decides it, from its prop and the team's switch.\n */\n askForEmail?: boolean;\n /** What the composer's question does with a good answer. */\n onSubmitEmail?: (email: string) => void;\n /** Holds the send button while a message is on its way. */\n isSending?: boolean;\n /** The agent has called for a person and nobody has picked it up yet. */\n awaitingHuman?: boolean;\n /** The finished conversation's one question, while it is worth asking. */\n rating?: SupportRating | null;\n /** Replies that arrived while the panel was closed. Sits on the button. */\n unreadCount?: number;\n /** One line above the composer, for a send that went wrong. */\n notice?: string | null;\n showBadge?: boolean;\n /** Any CSS length. The panel never grows past the viewport whatever this says. */\n width?: string;\n height?: string;\n /** What the header's own control grows it to, and back from. */\n expandedWidth?: string;\n expandedHeight?: string;\n /** The closed circle, and the corner the panel opens out of. */\n buttonSize?: string;\n /** Our button while it is closed, or nothing at all. */\n launcher?: SupportLauncherKind;\n /** Uncontrolled starting state. Ignored when `open` is passed. */\n defaultOpen?: boolean;\n /** Pass it to control the panel yourself. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Lands on the outer box. Override the default corner from here. */\n className?: string;\n}) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isOpen = open ?? uncontrolledOpen;\n const hasBubble = launcher === \"bubble\";\n\n // Kept while it is closed rather than reset, so a panel that was too small\n // once is not too small again the next time it is opened. Nothing is stored\n // between visits: it is a reach for more room right now, not a setting.\n const [isExpanded, setExpanded] = useState(false);\n\n const launcherRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const boxRef = useRef<HTMLDivElement>(null);\n\n // Where it lives, and how it gets moved. The button while it is closed, the\n // panel by its own header once it is open: one position, held by whichever\n // end of the widget is on the page at the time.\n const drag = useLauncherDrag({\n boxRef,\n buttonRef: launcherRef,\n margin: MARGIN,\n enabled: isOpen || hasBubble,\n subject: isOpen ? \"panel\" : \"button\",\n });\n\n // On a phone the open panel is the screen, not a card: it leaves the box,\n // covers the viewport, and follows the keyboard. The button and the box it\n // lives in never hear about any of this.\n const isSheet = useWidgetSheet({ boxRef, panelRef, isOpen });\n // Whatever had focus when the panel came up, so closing can hand it back.\n // Our own button, usually; the host's own trigger when there is no button.\n const opener = useRef<HTMLElement | null>(null);\n // Focus only moves once the panel has actually changed state. Without this a\n // widget that starts open would steal focus on page load.\n const wasOpen = useRef(isOpen);\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (open === undefined) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [open, onOpenChange],\n );\n\n const close = useCallback(() => setOpen(false), [setOpen]);\n\n // The panel is up, so the renderer is wanted now whether or not anything\n // touched the button on the way. A host opening it from their own nav never\n // does, and neither does a phone.\n useEffect(() => {\n if (isOpen) warmMarkdown();\n }, [isOpen]);\n\n // Escape closes, wherever focus happens to be inside the panel.\n useEffect(() => {\n if (!isOpen) return;\n\n function handleKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") close();\n }\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, close]);\n\n // Opening moves focus into the panel rather than onto the composer, so a\n // keyboard carries on from here without a phone throwing up its keyboard.\n // Closing hands it back where it came from.\n //\n // In an effect rather than in the handlers, because whichever end focus is\n // going to is still `inert` until the state that opened or closed it has\n // rendered, and focusing an inert element does nothing at all. It also has to\n // run for a host driving `open` themselves, who never touches a handler here.\n useEffect(() => {\n if (wasOpen.current === isOpen) return;\n wasOpen.current = isOpen;\n\n if (isOpen) {\n const active = document.activeElement;\n opener.current = active instanceof HTMLElement ? active : null;\n // Without `preventScroll` the browser scrolls the host's page to bring\n // the panel into view, and a panel that covers the screen is already in\n // view: all it does is drag the page out from under the sheet.\n panelRef.current?.focus({ preventScroll: true });\n return;\n }\n\n const back = launcherRef.current ?? opener.current;\n opener.current = null;\n // Only somewhere focus can actually land, and only if it is still on the\n // page: a menu that closed behind the panel is not there to take it back,\n // and leaving focus where it is beats throwing it at the body.\n if (back && back !== document.body && back.isConnected) back.focus();\n }, [isOpen]);\n\n return (\n // The box is panel sized whether it is open or not, so it never lets a\n // click through to the host's page. Only what is actually on screen takes\n // pointer events back.\n <div\n ref={boxRef}\n // The hook the published stylesheet scopes its resets to. On a page\n // without Tailwind there is no preflight, so the package ships one that\n // reaches no further than this box and its siblings below.\n data-median-widget=\"\"\n style={{\n width: isExpanded ? expandedWidth : width,\n height: isExpanded ? expandedHeight : height,\n ...drag.style,\n }}\n className={cn(\n \"pointer-events-none fixed z-50\",\n // Twice the margin, so the panel is inset by the same gap on both\n // sides however close to the edge the button has been put.\n //\n // Against whatever is positioning it as well as against the window,\n // which are the same thing for a widget on a host's page and are not\n // for one pinned inside a frame. Expanded is what finds the\n // difference: it is bigger than some of the boxes this turns up in,\n // and a panel hanging out the side of its own preview is not a panel\n // anybody is going to trust on their site.\n \"max-h-[min(calc(100svh-2rem),calc(100%-2rem))] max-w-[min(calc(100vw-2rem),calc(100%-2rem))]\",\n BOX,\n // Closed with no button on it, there is nothing here to see. The panel\n // stays mounted and stays `inert`, so the conversation is still live\n // and nothing behind it can be tabbed into by mistake.\n !hasBubble && !isOpen && \"opacity-0\",\n // The body wears the closed hand while a drag is on, which covers the\n // host's page. It does not reach in here, where the composer asks for\n // a caret and every button asks for a pointer, so this says it again\n // for everything inside.\n drag.isMoving && \"cursor-grabbing **:cursor-grabbing\",\n className,\n )}\n >\n {/* The shadow, on an empty layer of its own behind the panel.\n\n It cannot go on the panel, because a filter is painted before a clip\n and would be cut away with everything else. It also cannot go on a\n parent of the panel, which is where it used to be: a filter anywhere\n above a scrolling area stops the browser scrolling it the cheap way\n and makes it re-paint the whole thread on every frame instead, which\n is what made the thread stutter.\n\n So it goes on a sibling with nothing inside it. Same shape, same\n timing, no children to re-paint. */}\n {/* Not when the panel is a sheet: a full screen has no edges to throw a\n shadow past, and the closed circle it would leave in the corner sits\n entirely under the button, which carries a shadow of its own. */}\n {!isSheet && (\n <div aria-hidden className=\"absolute inset-0 drop-shadow-xl\">\n <div\n style={shape(isOpen, buttonSize, drag.side, hasBubble)}\n className={cn(\n \"size-full bg-card\",\n hasBubble ? MORPH : ARRIVE,\n drag.isMoving && \"transition-none\",\n )}\n />\n </div>\n )}\n\n <div\n ref={panelRef}\n tabIndex={-1}\n inert={!isOpen}\n // As a sheet it wears no clip at all: it fades and rises as one piece,\n // and the keyboard fit writes its edges straight onto the node.\n style={\n isSheet\n ? { transform: isOpen ? \"none\" : SHEET_RISEN }\n : shape(isOpen, buttonSize, drag.side, hasBubble)\n }\n className={cn(\n \"absolute inset-0 outline-none\",\n isSheet\n ? [SHEET, !isOpen && \"opacity-0\"]\n : [\n hasBubble ? MORPH : ARRIVE,\n // While it is travelling, the clip changes corners and there\n // is nothing to animate about that. Transitioning it wipes\n // the panel across the box on the way from one circle to the\n // other.\n drag.isMoving && \"transition-none\",\n ],\n isOpen && \"pointer-events-auto\",\n )}\n >\n <SupportWidget\n presence={presence}\n messages={messages}\n onSend={onSend}\n onTypingChange={onTypingChange}\n onClose={close}\n isExpanded={isExpanded}\n // A sheet is already every pixel there is, so a control that asks\n // for more would be a lie with an icon.\n onToggleExpanded={\n isSheet ? undefined : () => setExpanded((current) => !current)\n }\n isLoading={isLoading}\n isLocked={isLocked}\n onSignIn={onSignIn}\n askForEmail={askForEmail}\n onSubmitEmail={onSubmitEmail}\n isSending={isSending}\n awaitingHuman={awaitingHuman}\n rating={rating}\n notice={notice}\n showBadge={showBadge}\n // The header is the handle. Same four handlers the button wears,\n // and only one of the two is ever reachable at a time. A sheet has\n // nowhere to be dragged to, so there it is only a header.\n grabHandlers={isSheet ? undefined : drag.dragHandlers}\n isMoving={drag.isMoving}\n // Its own border and its own radius, which the clip is cut to match.\n // The panel is a card sitting on somebody else's page, and a card\n // here has an edge like a card anywhere else in the app. Unless it\n // is the screen, which has neither.\n className={isSheet ? SHEET_PANEL : undefined}\n />\n </div>\n\n {/* A sibling rather than a child of the clip, so its focus ring is not\n clipped away with it. Gone entirely when the host is doing the\n opening: an invisible button in the corner of somebody else's page\n would still be there to tab into. */}\n {hasBubble && (\n <button\n ref={launcherRef}\n type=\"button\"\n {...drag.dragHandlers}\n draggable={false}\n // The first sign anybody wants the panel. Fetching the renderer\n // here rather than on the click buys it the time between reaching\n // for the button and pressing it, which is usually all it needs.\n onPointerEnter={warmMarkdown}\n onFocus={warmMarkdown}\n onClick={() => {\n // The pointerup that ended a drag still arrives here as a click.\n // Opening on it would mean the panel came up every time somebody\n // moved the button, which is the one thing they did not ask for.\n if (drag.swallowClick()) return;\n setOpen(true);\n }}\n aria-expanded={isOpen}\n aria-label={\n unreadCount > 0\n ? `Chat with ${presence.name} support, ${unreadCount} unread`\n : `Chat with ${presence.name} support`\n }\n inert={isOpen}\n style={{\n width: buttonSize,\n height: buttonSize,\n // The same height the clip is cut at, from the same variable, so\n // the button and the circle under it cannot end up a pixel apart.\n top: buttonY(buttonSize),\n [drag.side]: 0,\n }}\n className={cn(\n \"absolute grid place-items-center rounded-full\",\n \"bg-primary text-primary-foreground shadow-lg outline-none\",\n // Struck off its own foreground rather than the border token. The\n // button is the inverse of the page it sits on, so `border` is a\n // colour picked to separate a card from the background and lands\n // invisible here: white at a tenth, over white. This reads as a\n // rim in both, because it is a tenth of whatever the icon is.\n \"border border-primary-foreground/15\",\n // Named properties rather than `all`, and the names matter.\n //\n // Its height inside the box is a real length now, and it changes\n // the instant a drag is committed. Under `transition-all` that is\n // an animatable property, so the button eased to its new height\n // over three hundred milliseconds after a two hundred millisecond\n // delay, while the clipped circle it is supposed to be sitting on\n // moved immediately. Half a second of a button beside its own\n // shadow rather than on it.\n //\n // Nothing about where it is should ever animate. The box carries\n // it, in one animation, and that is the only travel there is.\n \"transition-[opacity,transform,filter] motion-reduce:transition-none\",\n \"hover:brightness-125 focus-visible:ring-3 focus-visible:ring-ring/50\",\n // The browser must not claim the gesture for scrolling, or a drag\n // on a phone moves the page instead of the button.\n \"touch-none\",\n isOpen\n ? // Gone before the clip has opened far enough to show what is\n // underneath it.\n \"scale-90 opacity-0 duration-150 ease-out-quint\"\n : \"pointer-events-auto scale-100 opacity-100 delay-200 duration-300 ease-spring\",\n // Nothing on it is selectable, and it is not a thing the browser\n // may pick up and drag as an image either. Both of those end the\n // same way: the gesture becomes the browser's instead of ours.\n \"select-none\",\n // No scale while it is being dragged, and not only because the\n // press-in belongs to a tap. A scaled button measures scaled, and\n // every sum here starts from where its edges are.\n // A pointer at rest, not a grab hand. The button is a button first\n // and a thing you can move second, and hovering it should say the\n // first of those. The grab shows up once one is actually underway.\n !isOpen &&\n (drag.isMoving ? \"cursor-grabbing\" : \"cursor-pointer active:scale-95\"),\n )}\n >\n <ChatCircleDots className=\"size-6\" />\n\n {/* What arrived while they were not looking. The count is already in\n the button's own label, so this is only the picture of it.\n\n Struck off `background` rather than a fixed white, so it inverts\n with the theme and stays legible on the red either way. */}\n {unreadCount > 0 && (\n <span\n aria-hidden\n className={cn(\n \"absolute -top-0.5 -right-0.5 grid min-w-5 place-items-center rounded-full px-1\",\n \"bg-destructive text-xs font-semibold text-background tabular-nums\",\n \"ring-2 ring-card\",\n \"animate-in duration-300 ease-spring fade-in-0 zoom-in-50 motion-reduce:animate-none\",\n )}\n >\n {unreadCount > 9 ? \"9+\" : unreadCount}\n </span>\n )}\n </button>\n )}\n </div>\n );\n}\n","import * as e from \"react\";\nconst w = e.forwardRef((l, s) => {\n const {\n alt: r,\n color: a = \"currentColor\",\n size: t = \"1em\",\n weight: o = \"regular\",\n mirrored: i = !1,\n children: n,\n weights: c,\n ...m\n } = l;\n return /* @__PURE__ */ e.createElement(\n \"svg\",\n {\n ref: s,\n xmlns: \"http://www.w3.org/2000/svg\",\n width: t,\n height: t,\n fill: a,\n viewBox: \"0 0 256 256\",\n transform: i ? \"scale(-1, 1)\" : void 0,\n ...m\n },\n !!r && /* @__PURE__ */ e.createElement(\"title\", null, r),\n n,\n c.get(o)\n );\n});\nw.displayName = \"SSRBase\";\nexport {\n w as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/ArrowDown.es.js\";\nconst r = o.forwardRef((e, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...e, weights: m }));\nr.displayName = \"ArrowDownIcon\";\nconst s = r;\nexport {\n s as ArrowDown,\n r as ArrowDownIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208.49,152.49l-72,72a12,12,0,0,1-17,0l-72-72a12,12,0,0,1,17-17L116,187V40a12,12,0,0,1,24,0V187l51.51-51.52a12,12,0,0,1,17,17Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M200,144l-72,72L56,144Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M207.39,140.94A8,8,0,0,0,200,136H136V40a8,8,0,0,0-16,0v96H56a8,8,0,0,0-5.66,13.66l72,72a8,8,0,0,0,11.32,0l72-72A8,8,0,0,0,207.39,140.94ZM128,204.69,75.31,152H180.69Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72A8,8,0,0,1,56,136h64V40a8,8,0,0,1,16,0v96h64a8,8,0,0,1,5.66,13.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M204.24,148.24l-72,72a6,6,0,0,1-8.48,0l-72-72a6,6,0,0,1,8.48-8.48L122,201.51V40a6,6,0,0,1,12,0V201.51l61.76-61.75a6,6,0,0,1,8.48,8.48Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72a8,8,0,0,1,11.32-11.32L120,196.69V40a8,8,0,0,1,16,0V196.69l58.34-58.35a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M202.83,146.83l-72,72a4,4,0,0,1-5.66,0l-72-72a4,4,0,0,1,5.66-5.66L124,206.34V40a4,4,0,0,1,8,0V206.34l65.17-65.17a4,4,0,0,1,5.66,5.66Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as r from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/ArrowUp.es.js\";\nconst o = r.forwardRef((e, t) => /* @__PURE__ */ r.createElement(a, { ref: t, ...e, weights: m }));\no.displayName = \"ArrowUpIcon\";\nconst c = o;\nexport {\n c as ArrowUp,\n o as ArrowUpIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208.49,120.49a12,12,0,0,1-17,0L140,69V216a12,12,0,0,1-24,0V69L64.49,120.49a12,12,0,0,1-17-17l72-72a12,12,0,0,1,17,0l72,72A12,12,0,0,1,208.49,120.49Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M200,112H56l72-72Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,106.34l-72-72a8,8,0,0,0-11.32,0l-72,72A8,8,0,0,0,56,120h64v96a8,8,0,0,0,16,0V120h64a8,8,0,0,0,5.66-13.66ZM75.31,104,128,51.31,180.69,104Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M207.39,115.06A8,8,0,0,1,200,120H136v96a8,8,0,0,1-16,0V120H56a8,8,0,0,1-5.66-13.66l72-72a8,8,0,0,1,11.32,0l72,72A8,8,0,0,1,207.39,115.06Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M204.24,116.24a6,6,0,0,1-8.48,0L134,54.49V216a6,6,0,0,1-12,0V54.49L60.24,116.24a6,6,0,0,1-8.48-8.48l72-72a6,6,0,0,1,8.48,0l72,72A6,6,0,0,1,204.24,116.24Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,117.66a8,8,0,0,1-11.32,0L136,59.31V216a8,8,0,0,1-16,0V59.31L61.66,117.66a8,8,0,0,1-11.32-11.32l72-72a8,8,0,0,1,11.32,0l72,72A8,8,0,0,1,205.66,117.66Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M202.83,114.83a4,4,0,0,1-5.66,0L132,49.66V216a4,4,0,0,1-8,0V49.66L58.83,114.83a4,4,0,0,1-5.66-5.66l72-72a4,4,0,0,1,5.66,0l72,72A4,4,0,0,1,202.83,114.83Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport c from \"../defs/ArrowsClockwise.es.js\";\nconst r = o.forwardRef((e, s) => /* @__PURE__ */ o.createElement(t, { ref: s, ...e, weights: c }));\nr.displayName = \"ArrowsClockwiseIcon\";\nconst m = r;\nexport {\n m as ArrowsClockwise,\n r as ArrowsClockwiseIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M228,48V96a12,12,0,0,1-12,12H168a12,12,0,0,1,0-24h19l-7.8-7.8a75.55,75.55,0,0,0-53.32-22.26h-.43A75.49,75.49,0,0,0,72.39,75.57,12,12,0,1,1,55.61,58.41a99.38,99.38,0,0,1,69.87-28.47H126A99.42,99.42,0,0,1,196.2,59.23L204,67V48a12,12,0,0,1,24,0ZM183.61,180.43a75.49,75.49,0,0,1-53.09,21.63h-.43A75.55,75.55,0,0,1,76.77,179.8L69,172H88a12,12,0,0,0,0-24H40a12,12,0,0,0-12,12v48a12,12,0,0,0,24,0V189l7.8,7.8A99.42,99.42,0,0,0,130,226.06h.56a99.38,99.38,0,0,0,69.87-28.47,12,12,0,0,0-16.78-17.16Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1-5.66-13.66L180.65,72a79.48,79.48,0,0,0-54.72-22.09h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27,96,96,0,0,1,192,60.7l18.36-18.36A8,8,0,0,1,224,48ZM186.41,183.29A80,80,0,0,1,75.35,184l18.31-18.31A8,8,0,0,0,88,152H40a8,8,0,0,0-8,8v48a8,8,0,0,0,13.66,5.66L64,195.3a95.42,95.42,0,0,0,66,26.76h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M222,48V96a6,6,0,0,1-6,6H168a6,6,0,0,1,0-12h33.52L183.47,72a81.51,81.51,0,0,0-57.53-24h-.46A81.5,81.5,0,0,0,68.19,71.28a6,6,0,1,1-8.38-8.58,93.38,93.38,0,0,1,65.67-26.76H126a93.45,93.45,0,0,1,66,27.53l18,18V48a6,6,0,0,1,12,0ZM187.81,184.72a81.5,81.5,0,0,1-57.29,23.34h-.46a81.51,81.51,0,0,1-57.53-24L54.48,166H88a6,6,0,0,0,0-12H40a6,6,0,0,0-6,6v48a6,6,0,0,0,12,0V174.48l18,18.05a93.45,93.45,0,0,0,66,27.53h.52a93.38,93.38,0,0,0,65.67-26.76,6,6,0,1,0-8.38-8.58Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M220,48V96a4,4,0,0,1-4,4H168a4,4,0,0,1,0-8h38.34L184.89,70.54A84,84,0,0,0,66.8,69.85a4,4,0,1,1-5.6-5.72,92,92,0,0,1,129.34.76L212,86.34V48a4,4,0,0,1,8,0ZM189.2,186.15a83.44,83.44,0,0,1-58.68,23.91h-.47a83.52,83.52,0,0,1-58.94-24.6L49.66,164H88a4,4,0,0,0,0-8H40a4,4,0,0,0-4,4v48a4,4,0,0,0,8,0V169.66l21.46,21.45A91.43,91.43,0,0,0,130,218.06h.51a91.45,91.45,0,0,0,64.28-26.19,4,4,0,1,0-5.6-5.72Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as r from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/ArrowsIn.es.js\";\nconst o = r.forwardRef((e, s) => /* @__PURE__ */ r.createElement(t, { ref: s, ...e, weights: a }));\no.displayName = \"ArrowsInIcon\";\nconst c = o;\nexport {\n c as ArrowsIn,\n o as ArrowsInIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M140,104V64a12,12,0,0,1,24,0V75l35.51-35.52a12,12,0,0,1,17,17L181,92h11a12,12,0,0,1,0,24H152A12,12,0,0,1,140,104Zm-36,36H64a12,12,0,0,0,0,24H75L39.51,199.51a12,12,0,0,0,17,17L92,181v11a12,12,0,0,0,24,0V152A12,12,0,0,0,104,140Zm77,24h11a12,12,0,0,0,0-24H152a12,12,0,0,0-12,12v40a12,12,0,0,0,24,0V181l35.51,35.52a12,12,0,0,0,17-17ZM104,52A12,12,0,0,0,92,64V75L56.49,39.51a12,12,0,0,0-17,17L75,92H64a12,12,0,0,0,0,24h40a12,12,0,0,0,12-12V64A12,12,0,0,0,104,52Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,104V64a8,8,0,0,1,16,0V84.69l42.34-42.35a8,8,0,0,1,11.32,11.32L171.31,96H192a8,8,0,0,1,0,16H152A8,8,0,0,1,144,104Zm-40,40H64a8,8,0,0,0,0,16H84.69L42.34,202.34a8,8,0,0,0,11.32,11.32L96,171.31V192a8,8,0,0,0,16,0V152A8,8,0,0,0,104,144Zm67.31,16H192a8,8,0,0,0,0-16H152a8,8,0,0,0-8,8v40a8,8,0,0,0,16,0V171.31l42.34,42.35a8,8,0,0,0,11.32-11.32ZM104,56a8,8,0,0,0-8,8V84.69L53.66,42.34A8,8,0,0,0,42.34,53.66L84.69,96H64a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V64A8,8,0,0,0,104,56Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,104V64a8,8,0,0,1,13.66-5.66L172,72.69l30.34-30.35a8,8,0,0,1,11.32,11.32L183.31,84l14.35,14.34A8,8,0,0,1,192,112H152A8,8,0,0,1,144,104Zm-40,40H64a8,8,0,0,0-5.66,13.66L72.69,172,42.34,202.34a8,8,0,0,0,11.32,11.32L84,183.31l14.34,14.35A8,8,0,0,0,112,192V152A8,8,0,0,0,104,144Zm3.06-87.39a8,8,0,0,0-8.72,1.73L84,72.69,53.66,42.34A8,8,0,0,0,42.34,53.66L72.69,84,58.34,98.34A8,8,0,0,0,64,112h40a8,8,0,0,0,8-8V64A8,8,0,0,0,107.06,56.61ZM183.31,172l14.35-14.34A8,8,0,0,0,192,144H152a8,8,0,0,0-8,8v40a8,8,0,0,0,13.66,5.66L172,183.31l30.34,30.35a8,8,0,0,0,11.32-11.32Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M146,104V64a6,6,0,0,1,12,0V89.51l45.76-45.75a6,6,0,0,1,8.48,8.48L166.48,98H192a6,6,0,0,1,0,12H152A6,6,0,0,1,146,104Zm-42,42H64a6,6,0,0,0,0,12H89.52L43.76,203.76a6,6,0,1,0,8.48,8.48L98,166.48V192a6,6,0,0,0,12,0V152A6,6,0,0,0,104,146Zm62.48,12H192a6,6,0,0,0,0-12H152a6,6,0,0,0-6,6v40a6,6,0,0,0,12,0V166.48l45.76,45.76a6,6,0,0,0,8.48-8.48ZM104,58a6,6,0,0,0-6,6V89.51L52.24,43.76a6,6,0,0,0-8.48,8.48L89.52,98H64a6,6,0,0,0,0,12h40a6,6,0,0,0,6-6V64A6,6,0,0,0,104,58Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,104V64a8,8,0,0,1,16,0V84.69l42.34-42.35a8,8,0,0,1,11.32,11.32L171.31,96H192a8,8,0,0,1,0,16H152A8,8,0,0,1,144,104Zm-40,40H64a8,8,0,0,0,0,16H84.69L42.34,202.34a8,8,0,0,0,11.32,11.32L96,171.31V192a8,8,0,0,0,16,0V152A8,8,0,0,0,104,144Zm67.31,16H192a8,8,0,0,0,0-16H152a8,8,0,0,0-8,8v40a8,8,0,0,0,16,0V171.31l42.34,42.35a8,8,0,0,0,11.32-11.32ZM104,56a8,8,0,0,0-8,8V84.69L53.66,42.34A8,8,0,0,0,42.34,53.66L84.69,96H64a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V64A8,8,0,0,0,104,56Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M148,104V64a4,4,0,0,1,8,0V94.34l49.17-49.17a4,4,0,1,1,5.66,5.66L161.66,100H192a4,4,0,0,1,0,8H152A4,4,0,0,1,148,104Zm-44,44H64a4,4,0,0,0,0,8H94.34L45.17,205.17a4,4,0,0,0,5.66,5.66L100,161.66V192a4,4,0,0,0,8,0V152A4,4,0,0,0,104,148Zm57.66,8H192a4,4,0,0,0,0-8H152a4,4,0,0,0-4,4v40a4,4,0,0,0,8,0V161.66l49.17,49.17a4,4,0,0,0,5.66-5.66ZM104,60a4,4,0,0,0-4,4V94.34L50.83,45.17a4,4,0,0,0-5.66,5.66L94.34,100H64a4,4,0,0,0,0,8h40a4,4,0,0,0,4-4V64A4,4,0,0,0,104,60Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as r from \"react\";\nimport s from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/ArrowsOut.es.js\";\nconst o = r.forwardRef((t, e) => /* @__PURE__ */ r.createElement(s, { ref: e, ...t, weights: a }));\no.displayName = \"ArrowsOutIcon\";\nconst f = o;\nexport {\n f as ArrowsOut,\n o as ArrowsOutIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M220,48V96a12,12,0,0,1-24,0V77l-35.51,35.52a12,12,0,0,1-17-17L179,60H160a12,12,0,0,1,0-24h48A12,12,0,0,1,220,48ZM95.51,143.51,60,179V160a12,12,0,0,0-24,0v48a12,12,0,0,0,12,12H96a12,12,0,0,0,0-24H77l35.52-35.51a12,12,0,0,0-17-17ZM208,148a12,12,0,0,0-12,12v19l-35.51-35.52a12,12,0,0,0-17,17L179,196H160a12,12,0,0,0,0,24h48a12,12,0,0,0,12-12V160A12,12,0,0,0,208,148ZM77,60H96a12,12,0,0,0,0-24H48A12,12,0,0,0,36,48V96a12,12,0,0,0,24,0V77l35.51,35.52a12,12,0,0,0,17-17Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,48V208H48V48Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,48V96a8,8,0,0,1-16,0V67.31l-42.34,42.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM98.34,146.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l42.35-42.34a8,8,0,0,0-11.32-11.32ZM208,152a8,8,0,0,0-8,8v28.69l-42.34-42.35a8,8,0,0,0-11.32,11.32L188.69,200H160a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V160A8,8,0,0,0,208,152ZM67.31,56H96a8,8,0,0,0,0-16H48a8,8,0,0,0-8,8V96a8,8,0,0,0,16,0V67.31l42.34,42.35a8,8,0,0,0,11.32-11.32Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M109.66,146.34a8,8,0,0,1,0,11.32L83.31,184l18.35,18.34A8,8,0,0,1,96,216H48a8,8,0,0,1-8-8V160a8,8,0,0,1,13.66-5.66L72,172.69l26.34-26.35A8,8,0,0,1,109.66,146.34ZM83.31,72l18.35-18.34A8,8,0,0,0,96,40H48a8,8,0,0,0-8,8V96a8,8,0,0,0,13.66,5.66L72,83.31l26.34,26.35a8,8,0,0,0,11.32-11.32ZM208,40H160a8,8,0,0,0-5.66,13.66L172.69,72,146.34,98.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Zm3.06,112.61a8,8,0,0,0-8.72,1.73L184,172.69l-26.34-26.35a8,8,0,0,0-11.32,11.32L172.69,184l-18.35,18.34A8,8,0,0,0,160,216h48a8,8,0,0,0,8-8V160A8,8,0,0,0,211.06,152.61Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M214,48V96a6,6,0,0,1-12,0V62.48l-45.76,45.76a6,6,0,0,1-8.48-8.48L193.52,54H160a6,6,0,0,1,0-12h48A6,6,0,0,1,214,48ZM99.76,147.76,54,193.52V160a6,6,0,0,0-12,0v48a6,6,0,0,0,6,6H96a6,6,0,0,0,0-12H62.48l45.76-45.76a6,6,0,0,0-8.48-8.48ZM208,154a6,6,0,0,0-6,6v33.52l-45.76-45.76a6,6,0,0,0-8.48,8.48L193.52,202H160a6,6,0,0,0,0,12h48a6,6,0,0,0,6-6V160A6,6,0,0,0,208,154ZM62.48,54H96a6,6,0,0,0,0-12H48a6,6,0,0,0-6,6V96a6,6,0,0,0,12,0V62.48l45.76,45.76a6,6,0,0,0,8.48-8.48Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,48V96a8,8,0,0,1-16,0V67.31l-42.34,42.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM98.34,146.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l42.35-42.34a8,8,0,0,0-11.32-11.32ZM208,152a8,8,0,0,0-8,8v28.69l-42.34-42.35a8,8,0,0,0-11.32,11.32L188.69,200H160a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V160A8,8,0,0,0,208,152ZM67.31,56H96a8,8,0,0,0,0-16H48a8,8,0,0,0-8,8V96a8,8,0,0,0,16,0V67.31l42.34,42.35a8,8,0,0,0,11.32-11.32Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M212,48V96a4,4,0,0,1-8,0V57.66l-49.17,49.17a4,4,0,0,1-5.66-5.66L198.34,52H160a4,4,0,0,1,0-8h48A4,4,0,0,1,212,48ZM101.17,149.17,52,198.34V160a4,4,0,0,0-8,0v48a4,4,0,0,0,4,4H96a4,4,0,0,0,0-8H57.66l49.17-49.17a4,4,0,0,0-5.66-5.66ZM208,156a4,4,0,0,0-4,4v38.34l-49.17-49.17a4,4,0,0,0-5.66,5.66L198.34,204H160a4,4,0,0,0,0,8h48a4,4,0,0,0,4-4V160A4,4,0,0,0,208,156ZM57.66,52H96a4,4,0,0,0,0-8H48a4,4,0,0,0-4,4V96a4,4,0,0,0,8,0V57.66l49.17,49.17a4,4,0,0,0,5.66-5.66Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Bug.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...r, weights: m }));\ne.displayName = \"BugIcon\";\nconst f = e;\nexport {\n f as Bug,\n e as BugIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M140,88a16,16,0,1,1,16,16A16,16,0,0,1,140,88ZM100,72a16,16,0,1,0,16,16A16,16,0,0,0,100,72Zm120,72a91.84,91.84,0,0,1-2.34,20.64L236.81,173a12,12,0,0,1-9.62,22l-18-7.85a92,92,0,0,1-162.46,0l-18,7.85a12,12,0,1,1-9.62-22l19.15-8.36A91.84,91.84,0,0,1,36,144v-4H16a12,12,0,0,1,0-24H36v-4a91.84,91.84,0,0,1,2.34-20.64L19.19,83a12,12,0,0,1,9.62-22l18,7.85a92,92,0,0,1,162.46,0l18-7.85a12,12,0,1,1,9.62,22l-19.15,8.36A91.84,91.84,0,0,1,220,112v4h20a12,12,0,0,1,0,24H220ZM60,116H196v-4a68,68,0,0,0-136,0Zm56,94.92V140H60v4A68.1,68.1,0,0,0,116,210.92ZM196,144v-4H140v70.92A68.1,68.1,0,0,0,196,144Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,128v16a80,80,0,0,1-160,0V128Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,92a12,12,0,1,1,12,12A12,12,0,0,1,144,92ZM100,80a12,12,0,1,0,12,12A12,12,0,0,0,100,80Zm116,64A87.76,87.76,0,0,1,213,167l22.24,9.72A8,8,0,0,1,232,192a7.89,7.89,0,0,1-3.2-.67L207.38,182a88,88,0,0,1-158.76,0L27.2,191.33A7.89,7.89,0,0,1,24,192a8,8,0,0,1-3.2-15.33L43,167A87.76,87.76,0,0,1,40,144v-8H16a8,8,0,0,1,0-16H40v-8a87.76,87.76,0,0,1,3-23L20.8,79.33a8,8,0,1,1,6.4-14.66L48.62,74a88,88,0,0,1,158.76,0l21.42-9.36a8,8,0,0,1,6.4,14.66L213,89.05a87.76,87.76,0,0,1,3,23v8h24a8,8,0,0,1,0,16H216ZM56,120H200v-8a72,72,0,0,0-144,0Zm64,95.54V136H56v8A72.08,72.08,0,0,0,120,215.54ZM200,144v-8H136v79.54A72.08,72.08,0,0,0,200,144Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M168,92a12,12,0,1,1-12-12A12,12,0,0,1,168,92ZM100,80a12,12,0,1,0,12,12A12,12,0,0,0,100,80Zm116,64A87.76,87.76,0,0,1,213,167l22.24,9.72A8,8,0,0,1,232,192a7.89,7.89,0,0,1-3.2-.67L207.38,182a88,88,0,0,1-158.76,0L27.2,191.33A7.89,7.89,0,0,1,24,192a8,8,0,0,1-3.2-15.33L43,167A87.76,87.76,0,0,1,40,144v-8H16a8,8,0,0,1,0-16H40v-8a87.76,87.76,0,0,1,3-23L20.8,79.33a8,8,0,1,1,6.4-14.66L48.62,74a88,88,0,0,1,158.76,0l21.42-9.36a8,8,0,0,1,6.4,14.66L213,89.05a87.76,87.76,0,0,1,3,23v8h24a8,8,0,0,1,0,16H216Zm-80,0a8,8,0,0,0-16,0v64a8,8,0,0,0,16,0Zm64-32a72,72,0,0,0-144,0v8H200Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M146,92a10,10,0,1,1,10,10A10,10,0,0,1,146,92ZM100,82a10,10,0,1,0,10,10A10,10,0,0,0,100,82Zm146,46a6,6,0,0,1-6,6H214v10a85.88,85.88,0,0,1-3.45,24.08L234.4,178.5a6,6,0,0,1-4.8,11l-23.23-10.15a86,86,0,0,1-156.74,0L26.4,189.5a6,6,0,1,1-4.8-11l23.85-10.42A85.88,85.88,0,0,1,42,144V134H16a6,6,0,0,1,0-12H42V112a85.88,85.88,0,0,1,3.45-24.08L21.6,77.5a6,6,0,0,1,4.8-11L49.63,76.65a86,86,0,0,1,156.74,0L229.6,66.5a6,6,0,1,1,4.8,11L210.55,87.92A85.88,85.88,0,0,1,214,112v10h26A6,6,0,0,1,246,128ZM54,122H202V112a74,74,0,0,0-148,0Zm68,95.74V134H54v10A74.09,74.09,0,0,0,122,217.74ZM202,134H134v83.74A74.09,74.09,0,0,0,202,144Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,92a12,12,0,1,1,12,12A12,12,0,0,1,144,92ZM100,80a12,12,0,1,0,12,12A12,12,0,0,0,100,80Zm116,64A87.76,87.76,0,0,1,213,167l22.24,9.72A8,8,0,0,1,232,192a7.89,7.89,0,0,1-3.2-.67L207.38,182a88,88,0,0,1-158.76,0L27.2,191.33A7.89,7.89,0,0,1,24,192a8,8,0,0,1-3.2-15.33L43,167A87.76,87.76,0,0,1,40,144v-8H16a8,8,0,0,1,0-16H40v-8a87.76,87.76,0,0,1,3-23L20.8,79.33a8,8,0,1,1,6.4-14.66L48.62,74a88,88,0,0,1,158.76,0l21.42-9.36a8,8,0,0,1,6.4,14.66L213,89.05a87.76,87.76,0,0,1,3,23v8h24a8,8,0,0,1,0,16H216ZM56,120H200v-8a72,72,0,0,0-144,0Zm64,95.54V136H56v8A72.08,72.08,0,0,0,120,215.54ZM200,144v-8H136v79.54A72.08,72.08,0,0,0,200,144Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M148,92a8,8,0,1,1,8,8A8,8,0,0,1,148,92Zm-48-8a8,8,0,1,0,8,8A8,8,0,0,0,100,84Zm144,44a4,4,0,0,1-4,4H212v12a83.64,83.64,0,0,1-3.87,25.2l25.47,11.13A4,4,0,0,1,232,188a4.09,4.09,0,0,1-1.6-.33l-25-10.95a84,84,0,0,1-154.72,0l-25,10.95A4.09,4.09,0,0,1,24,188a4,4,0,0,1-1.6-7.67L47.87,169.2A83.64,83.64,0,0,1,44,144V132H16a4,4,0,0,1,0-8H44V112a83.64,83.64,0,0,1,3.87-25.2L22.4,75.67a4,4,0,0,1,3.2-7.34l25,11a84,84,0,0,1,154.72,0l25-11a4,4,0,1,1,3.2,7.34L208.13,86.8A83.64,83.64,0,0,1,212,112v12h28A4,4,0,0,1,244,128ZM52,124H204V112a76,76,0,0,0-152,0Zm72,95.89V132H52v12A76.09,76.09,0,0,0,124,219.89ZM204,132H132v87.89A76.09,76.09,0,0,0,204,144Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as t from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport i from \"../defs/CaretRight.es.js\";\nconst e = t.forwardRef((r, o) => /* @__PURE__ */ t.createElement(a, { ref: o, ...r, weights: i }));\ne.displayName = \"CaretRightIcon\";\nconst c = e;\nexport {\n c as CaretRight,\n e as CaretRightIcon\n};\n","import * as e from \"react\";\nconst t = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M184.49,136.49l-80,80a12,12,0,0,1-17-17L159,128,87.51,56.49a12,12,0,1,1,17-17l80,80A12,12,0,0,1,184.49,136.49Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M176,128,96,208V48Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M181.66,122.34l-80-80A8,8,0,0,0,88,48V208a8,8,0,0,0,13.66,5.66l80-80A8,8,0,0,0,181.66,122.34ZM104,188.69V67.31L164.69,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M181.66,133.66l-80,80A8,8,0,0,1,88,208V48a8,8,0,0,1,13.66-5.66l80,80A8,8,0,0,1,181.66,133.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M180.24,132.24l-80,80a6,6,0,0,1-8.48-8.48L167.51,128,91.76,52.24a6,6,0,0,1,8.48-8.48l80,80A6,6,0,0,1,180.24,132.24Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M178.83,130.83l-80,80a4,4,0,0,1-5.66-5.66L170.34,128,93.17,50.83a4,4,0,0,1,5.66-5.66l80,80A4,4,0,0,1,178.83,130.83Z\" }))\n ]\n]);\nexport {\n t as default\n};\n","import * as t from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport s from \"../defs/ChatCircleDots.es.js\";\nconst o = t.forwardRef((e, r) => /* @__PURE__ */ t.createElement(a, { ref: r, ...e, weights: s }));\no.displayName = \"ChatCircleDotsIcon\";\nconst m = o;\nexport {\n m as ChatCircleDots,\n o as ChatCircleDotsIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M120,128a16,16,0,1,1-16-16A16,16,0,0,1,120,128Zm32-16a16,16,0,1,0,16,16A16,16,0,0,0,152,112Zm84,16A108,108,0,0,1,78.77,224.15L46.34,235A20,20,0,0,1,21,209.66l10.81-32.43A108,108,0,1,1,236,128Zm-24,0A84,84,0,1,0,55.27,170.06a12,12,0,0,1,1,9.81l-9.93,29.79,29.79-9.93a12.1,12.1,0,0,1,3.8-.62,12,12,0,0,1,6,1.62A84,84,0,0,0,212,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M224,128A96,96,0,0,1,79.93,211.11h0L42.54,223.58a8,8,0,0,1-10.12-10.12l12.47-37.39h0A96,96,0,1,1,224,128Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24Zm0,192a87.87,87.87,0,0,1-44.06-11.81,8,8,0,0,0-4-1.08,7.85,7.85,0,0,0-2.53.42L40,216,52.47,178.6a8,8,0,0,0-.66-6.54A88,88,0,1,1,128,216Zm12-88a12,12,0,1,1-12-12A12,12,0,0,1,140,128Zm-44,0a12,12,0,1,1-12-12A12,12,0,0,1,96,128Zm88,0a12,12,0,1,1-12-12A12,12,0,0,1,184,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24ZM84,140a12,12,0,1,1,12-12A12,12,0,0,1,84,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,128,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,172,140Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M138,128a10,10,0,1,1-10-10A10,10,0,0,1,138,128ZM84,118a10,10,0,1,0,10,10A10,10,0,0,0,84,118Zm88,0a10,10,0,1,0,10,10A10,10,0,0,0,172,118Zm58,10A102,102,0,0,1,79.31,217.65L44.44,229.27a14,14,0,0,1-17.71-17.71l11.62-34.87A102,102,0,1,1,230,128Zm-12,0A90,90,0,1,0,50.08,173.06a6,6,0,0,1,.5,4.91L38.12,215.35a2,2,0,0,0,2.53,2.53L78,205.42a6.2,6.2,0,0,1,1.9-.31,6.09,6.09,0,0,1,3,.81A90,90,0,0,0,218,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128ZM84,116a12,12,0,1,0,12,12A12,12,0,0,0,84,116Zm88,0a12,12,0,1,0,12,12A12,12,0,0,0,172,116Zm60,12A104,104,0,0,1,79.12,219.82L45.07,231.17a16,16,0,0,1-20.24-20.24l11.35-34.05A104,104,0,1,1,232,128Zm-16,0A88,88,0,1,0,51.81,172.06a8,8,0,0,1,.66,6.54L40,216,77.4,203.53a7.85,7.85,0,0,1,2.53-.42,8,8,0,0,1,4,1.08A88,88,0,0,0,216,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M136,128a8,8,0,1,1-8-8A8,8,0,0,1,136,128Zm-52-8a8,8,0,1,0,8,8A8,8,0,0,0,84,120Zm88,0a8,8,0,1,0,8,8A8,8,0,0,0,172,120Zm56,8A100,100,0,0,1,79.5,215.47l-35.69,11.9a12,12,0,0,1-15.18-15.18l11.9-35.69A100,100,0,1,1,228,128Zm-8,0A92,92,0,1,0,48.35,174.07a4,4,0,0,1,.33,3.27L36.22,214.72a4,4,0,0,0,5.06,5.06l37.38-12.46a3.93,3.93,0,0,1,1.27-.21,4.05,4.05,0,0,1,2,.54A92,92,0,0,0,220,128Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as e from \"react\";\nimport c from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/Check.es.js\";\nconst o = e.forwardRef((r, t) => /* @__PURE__ */ e.createElement(c, { ref: t, ...r, weights: a }));\no.displayName = \"CheckIcon\";\nconst f = o;\nexport {\n f as Check,\n o as CheckIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M232,56V200a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,85.66l-96,96a8,8,0,0,1-11.32,0l-40-40a8,8,0,0,1,11.32-11.32L104,164.69l90.34-90.35a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM205.66,85.66l-96,96a8,8,0,0,1-11.32,0l-40-40a8,8,0,0,1,11.32-11.32L104,164.69l90.34-90.35a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M228.24,76.24l-128,128a6,6,0,0,1-8.48,0l-56-56a6,6,0,0,1,8.48-8.48L96,191.51,219.76,67.76a6,6,0,0,1,8.48,8.48Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M229.66,77.66l-128,128a8,8,0,0,1-11.32,0l-56-56a8,8,0,0,1,11.32-11.32L96,188.69,218.34,66.34a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M226.83,74.83l-128,128a4,4,0,0,1-5.66,0l-56-56a4,4,0,0,1,5.66-5.66L96,194.34,221.17,69.17a4,4,0,1,1,5.66,5.66Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport r from \"../lib/SSRBase.es.js\";\nimport t from \"../defs/EnvelopeSimple.es.js\";\nconst o = e.forwardRef((m, p) => /* @__PURE__ */ e.createElement(r, { ref: p, ...m, weights: t }));\no.displayName = \"EnvelopeSimpleIcon\";\nconst l = o;\nexport {\n l as EnvelopeSimple,\n o as EnvelopeSimpleIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,44H32A12,12,0,0,0,20,56V192a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A12,12,0,0,0,224,44ZM193.15,68,128,127.72,62.85,68ZM44,188V83.28l75.89,69.57a12,12,0,0,0,16.22,0L212,83.28V188Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,56l-96,88L32,56Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM203.43,64,128,133.15,52.57,64ZM216,192H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48Zm-8,144H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,50H32a6,6,0,0,0-6,6V192a14,14,0,0,0,14,14H216a14,14,0,0,0,14-14V56A6,6,0,0,0,224,50ZM208.58,62,128,135.86,47.42,62ZM216,194H40a2,2,0,0,1-2-2V69.64l86,78.78a6,6,0,0,0,8.1,0L218,69.64V192A2,2,0,0,1,216,194Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM203.43,64,128,133.15,52.57,64ZM216,192H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,52H32a4,4,0,0,0-4,4V192a12,12,0,0,0,12,12H216a12,12,0,0,0,12-12V56A4,4,0,0,0,224,52Zm-10.28,8L128,138.57,42.28,60ZM216,196H40a4,4,0,0,1-4-4V65.09L125.3,147a4,4,0,0,0,5.4,0L220,65.09V192A4,4,0,0,1,216,196Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport i from \"../defs/File.es.js\";\nconst o = e.forwardRef((r, t) => /* @__PURE__ */ e.createElement(a, { ref: t, ...r, weights: i }));\no.displayName = \"FileIcon\";\nconst c = o;\nexport {\n c as File,\n o as FileIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208,88H152V32Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM152,88V44l44,44Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M212.24,83.76l-56-56A6,6,0,0,0,152,26H56A14,14,0,0,0,42,40V216a14,14,0,0,0,14,14H200a14,14,0,0,0,14-14V88A6,6,0,0,0,212.24,83.76ZM158,46.48,193.52,82H158ZM200,218H56a2,2,0,0,1-2-2V40a2,2,0,0,1,2-2h90V88a6,6,0,0,0,6,6h50V216A2,2,0,0,1,200,218Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M210.83,85.17l-56-56A4,4,0,0,0,152,28H56A12,12,0,0,0,44,40V216a12,12,0,0,0,12,12H200a12,12,0,0,0,12-12V88A4,4,0,0,0,210.83,85.17ZM156,41.65,198.34,84H156ZM200,220H56a4,4,0,0,1-4-4V40a4,4,0,0,1,4-4h92V88a4,4,0,0,0,4,4h52V216A4,4,0,0,1,200,220Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport m from \"../lib/SSRBase.es.js\";\nimport t from \"../defs/ImageSquare.es.js\";\nconst a = e.forwardRef((r, o) => /* @__PURE__ */ e.createElement(m, { ref: o, ...r, weights: t }));\na.displayName = \"ImageSquareIcon\";\nconst I = a;\nexport {\n I as ImageSquare,\n a as ImageSquareIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,28H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V48A20,20,0,0,0,208,28Zm-4,24v63.72L186.14,97.86a20,20,0,0,0-28.28,0L52,203.72V52ZM85.66,204,172,117.66l32,32V204ZM76,96a20,20,0,1,1,20,20A20,20,0,0,1,76,96Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M208,40H48a8,8,0,0,0-8,8V208a8,8,0,0,0,8,8h8.69L166.34,106.34a8,8,0,0,1,11.32,0L216,144.69V48A8,8,0,0,0,208,40ZM96,112a16,16,0,1,1,16-16A16,16,0,0,1,96,112Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM48,48H208v77.38l-24.69-24.7a16,16,0,0,0-22.62,0L53.37,208H48ZM208,208H76l96-96,36,36v60ZM96,120A24,24,0,1,0,72,96,24,24,0,0,0,96,120Zm0-32a8,8,0,1,1-8,8A8,8,0,0,1,96,88Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM48,48H208v77.38l-24.69-24.7a16,16,0,0,0-22.62,0L53.37,208H48ZM80,96a16,16,0,1,1,16,16A16,16,0,0,1,80,96Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,34H48A14,14,0,0,0,34,48V208a14,14,0,0,0,14,14H208a14,14,0,0,0,14-14V48A14,14,0,0,0,208,34ZM46,208V48a2,2,0,0,1,2-2H208a2,2,0,0,1,2,2v82.2l-28.1-28.1a14,14,0,0,0-19.8,0L54.2,210H48A2,2,0,0,1,46,208Zm162,2H71.17l99.41-99.41a2,2,0,0,1,2.83,0L210,147.17V208A2,2,0,0,1,208,210ZM96,118A22,22,0,1,0,74,96,22,22,0,0,0,96,118Zm0-32A10,10,0,1,1,86,96,10,10,0,0,1,96,86Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM48,48H208v77.38l-24.69-24.7a16,16,0,0,0-22.62,0L53.37,208H48ZM208,208H76l96-96,36,36v60ZM96,120A24,24,0,1,0,72,96,24,24,0,0,0,96,120Zm0-32a8,8,0,1,1-8,8A8,8,0,0,1,96,88Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,36H48A12,12,0,0,0,36,48V208a12,12,0,0,0,12,12H208a12,12,0,0,0,12-12V48A12,12,0,0,0,208,36ZM44,208V48a4,4,0,0,1,4-4H208a4,4,0,0,1,4,4v87l-31.51-31.52a12,12,0,0,0-17,0L55,212H48A4,4,0,0,1,44,208Zm164,4H66.34L169.17,109.17a4,4,0,0,1,5.66,0L212,146.34V208A4,4,0,0,1,208,212ZM96,116A20,20,0,1,0,76,96,20,20,0,0,0,96,116Zm0-32A12,12,0,1,1,84,96,12,12,0,0,1,96,84Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as t from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport i from \"../defs/Lightbulb.es.js\";\nconst o = t.forwardRef((e, r) => /* @__PURE__ */ t.createElement(a, { ref: r, ...e, weights: i }));\no.displayName = \"LightbulbIcon\";\nconst b = o;\nexport {\n b as Lightbulb,\n o as LightbulbIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M180,232a12,12,0,0,1-12,12H88a12,12,0,0,1,0-24h80A12,12,0,0,1,180,232Zm40-128a91.51,91.51,0,0,1-35.17,72.35A12.26,12.26,0,0,0,180,186v2a20,20,0,0,1-20,20H96a20,20,0,0,1-20-20v-2a12,12,0,0,0-4.7-9.51A91.57,91.57,0,0,1,36,104.52C35.73,54.69,76,13.2,125.79,12A92,92,0,0,1,220,104Zm-24,0a68,68,0,0,0-69.65-68C89.56,36.88,59.8,67.55,60,104.38a67.71,67.71,0,0,0,26.1,53.19A35.87,35.87,0,0,1,100,184h56.1A36.13,36.13,0,0,1,170,157.49,67.68,67.68,0,0,0,196,104Zm-20.07-5.32a48.5,48.5,0,0,0-31.91-40,12,12,0,0,0-8,22.62,24.31,24.31,0,0,1,16.09,20,12,12,0,0,0,23.86-2.64Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M208,104a79.86,79.86,0,0,1-30.59,62.92A24.29,24.29,0,0,0,168,186v6a8,8,0,0,1-8,8H96a8,8,0,0,1-8-8v-6a24.11,24.11,0,0,0-9.3-19A79.87,79.87,0,0,1,48,104.45C47.76,61.09,82.72,25,126.07,24A80,80,0,0,1,208,104Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-16,0a72,72,0,0,0-73.74-72c-39,.92-70.47,33.39-70.26,72.39a71.65,71.65,0,0,0,27.64,56.3A32,32,0,0,1,96,186v6h64v-6a32.15,32.15,0,0,1,12.47-25.35A71.65,71.65,0,0,0,200,104Zm-16.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-32.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M174,232a6,6,0,0,1-6,6H88a6,6,0,0,1,0-12h80A6,6,0,0,1,174,232Zm40-128a85.56,85.56,0,0,1-32.88,67.64A18.23,18.23,0,0,0,174,186v6a14,14,0,0,1-14,14H96a14,14,0,0,1-14-14v-6a18,18,0,0,0-7-14.23h0a85.59,85.59,0,0,1-33-67.24C41.74,57.91,79.39,19.12,125.93,18A86,86,0,0,1,214,104Zm-12,0a74,74,0,0,0-75.79-74C86.17,31,53.78,64.34,54,104.42a73.67,73.67,0,0,0,28.4,57.87A29.92,29.92,0,0,1,94,186v6a2,2,0,0,0,2,2h64a2,2,0,0,0,2-2v-6a30.18,30.18,0,0,1,11.7-23.78A73.59,73.59,0,0,0,202,104Zm-20.08-9A55.58,55.58,0,0,0,137,50.08a6,6,0,1,0-2,11.84C152.38,64.84,167.13,79.6,170.08,97a6,6,0,0,0,5.91,5,6.87,6.87,0,0,0,1-.08A6,6,0,0,0,181.92,95Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-16,0a72,72,0,0,0-73.74-72c-39,.92-70.47,33.39-70.26,72.39a71.65,71.65,0,0,0,27.64,56.3A32,32,0,0,1,96,186v6h64v-6a32.15,32.15,0,0,1,12.47-25.35A71.65,71.65,0,0,0,200,104Zm-16.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M172,232a4,4,0,0,1-4,4H88a4,4,0,0,1,0-8h80A4,4,0,0,1,172,232Zm40-128a83.59,83.59,0,0,1-32.11,66.06A20.2,20.2,0,0,0,172,186v6a12,12,0,0,1-12,12H96a12,12,0,0,1-12-12v-6a20,20,0,0,0-7.76-15.81A83.58,83.58,0,0,1,44,104.47C43.75,59,80.52,21.09,126,20a84,84,0,0,1,86,84Zm-8,0a76,76,0,0,0-77.83-76C85,29,51.77,63.27,52,104.43a75.62,75.62,0,0,0,29.17,59.43A28,28,0,0,1,92,186v6a4,4,0,0,0,4,4h64a4,4,0,0,0,4-4v-6a28.14,28.14,0,0,1,10.94-22.2A75.62,75.62,0,0,0,204,104ZM136.66,52.06a4,4,0,0,0-1.32,7.88C153.53,63,169,78.45,172.06,96.67A4,4,0,0,0,176,100a3.88,3.88,0,0,0,.67-.06,4,4,0,0,0,3.27-4.61A53.51,53.51,0,0,0,136.66,52.06Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport c from \"../defs/LockSimple.es.js\";\nconst e = o.forwardRef((m, r) => /* @__PURE__ */ o.createElement(t, { ref: r, ...m, weights: c }));\ne.displayName = \"LockSimpleIcon\";\nconst p = e;\nexport {\n p as LockSimple,\n e as LockSimpleIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,76H180V56A52,52,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76ZM100,56a28,28,0,0,1,56,0V76H100ZM204,204H52V100H204Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M216,96V208a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V96a8,8,0,0,1,8-8H208A8,8,0,0,1,216,96Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,82H174V56a46,46,0,0,0-92,0V82H48A14,14,0,0,0,34,96V208a14,14,0,0,0,14,14H208a14,14,0,0,0,14-14V96A14,14,0,0,0,208,82ZM94,56a34,34,0,0,1,68,0V82H94ZM210,208a2,2,0,0,1-2,2H48a2,2,0,0,1-2-2V96a2,2,0,0,1,2-2H208a2,2,0,0,1,2,2Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,84H172V56a44,44,0,0,0-88,0V84H48A12,12,0,0,0,36,96V208a12,12,0,0,0,12,12H208a12,12,0,0,0,12-12V96A12,12,0,0,0,208,84ZM92,56a36,36,0,0,1,72,0V84H92ZM212,208a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V96a4,4,0,0,1,4-4H208a4,4,0,0,1,4,4Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Play.es.js\";\nconst a = o.forwardRef((e, r) => /* @__PURE__ */ o.createElement(t, { ref: r, ...e, weights: m }));\na.displayName = \"PlayIcon\";\nconst f = a;\nexport {\n f as Play,\n a as PlayIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M234.49,111.07,90.41,22.94A20,20,0,0,0,60,39.87V216.13a20,20,0,0,0,30.41,16.93l144.08-88.13a19.82,19.82,0,0,0,0-33.86ZM84,208.85V47.15L216.16,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M228.23,134.69,84.15,222.81A8,8,0,0,1,72,216.12V39.88a8,8,0,0,1,12.15-6.69l144.08,88.12A7.82,7.82,0,0,1,228.23,134.69Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M231.36,116.19,87.28,28.06a14,14,0,0,0-14.18-.27A13.69,13.69,0,0,0,66,39.87V216.13a13.69,13.69,0,0,0,7.1,12.08,14,14,0,0,0,14.18-.27l144.08-88.13a13.82,13.82,0,0,0,0-23.62Zm-6.26,13.38L81,217.7a2,2,0,0,1-2.06,0,1.78,1.78,0,0,1-1-1.61V39.87a1.78,1.78,0,0,1,1-1.61A2.06,2.06,0,0,1,80,38a2,2,0,0,1,1,.31L225.1,126.43a1.82,1.82,0,0,1,0,3.14Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M230.32,117.9,86.24,29.79a11.91,11.91,0,0,0-12.17-.23A11.71,11.71,0,0,0,68,39.89V216.11a11.71,11.71,0,0,0,6.07,10.33,11.91,11.91,0,0,0,12.17-.23L230.32,138.1a11.82,11.82,0,0,0,0-20.2Zm-4.18,13.37L82.06,219.39a4,4,0,0,1-4.07.07,3.77,3.77,0,0,1-2-3.35V39.89a3.77,3.77,0,0,1,2-3.35,4,4,0,0,1,4.07.07l144.08,88.12a3.8,3.8,0,0,1,0,6.54Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/Plus.es.js\";\nconst e = o.forwardRef((r, s) => /* @__PURE__ */ o.createElement(t, { ref: s, ...r, weights: a }));\ne.displayName = \"PlusIcon\";\nconst f = e;\nexport {\n f as Plus,\n e as PlusIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M216,56V200a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V56A16,16,0,0,1,56,40H200A16,16,0,0,1,216,56Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM184,136H136v48a8,8,0,0,1-16,0V136H72a8,8,0,0,1,0-16h48V72a8,8,0,0,1,16,0v48h48a8,8,0,0,1,0,16Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M222,128a6,6,0,0,1-6,6H134v82a6,6,0,0,1-12,0V134H40a6,6,0,0,1,0-12h82V40a6,6,0,0,1,12,0v82h82A6,6,0,0,1,222,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M220,128a4,4,0,0,1-4,4H132v84a4,4,0,0,1-8,0V132H40a4,4,0,0,1,0-8h84V40a4,4,0,0,1,8,0v84h84A4,4,0,0,1,220,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Sparkle.es.js\";\nconst r = e.forwardRef((o, a) => /* @__PURE__ */ e.createElement(t, { ref: a, ...o, weights: m }));\nr.displayName = \"SparkleIcon\";\nconst c = r;\nexport {\n c as Sparkle,\n r as SparkleIcon\n};\n","import * as a from \"react\";\nconst l = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M199,125.31l-49.88-18.39L130.69,57a19.92,19.92,0,0,0-37.38,0L74.92,106.92,25,125.31a19.92,19.92,0,0,0,0,37.38l49.88,18.39L93.31,231a19.92,19.92,0,0,0,37.38,0l18.39-49.88L199,162.69a19.92,19.92,0,0,0,0-37.38Zm-63.38,35.16a12,12,0,0,0-7.11,7.11L112,212.28l-16.47-44.7a12,12,0,0,0-7.11-7.11L43.72,144l44.7-16.47a12,12,0,0,0,7.11-7.11L112,75.72l16.47,44.7a12,12,0,0,0,7.11,7.11L180.28,144ZM140,40a12,12,0,0,1,12-12h12V16a12,12,0,0,1,24,0V28h12a12,12,0,0,1,0,24H188V64a12,12,0,0,1-24,0V52H152A12,12,0,0,1,140,40ZM252,88a12,12,0,0,1-12,12h-4v4a12,12,0,0,1-24,0v-4h-4a12,12,0,0,1,0-24h4V72a12,12,0,0,1,24,0v4h4A12,12,0,0,1,252,88Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M194.82,151.43l-55.09,20.3-20.3,55.09a7.92,7.92,0,0,1-14.86,0l-20.3-55.09-55.09-20.3a7.92,7.92,0,0,1,0-14.86l55.09-20.3,20.3-55.09a7.92,7.92,0,0,1,14.86,0l20.3,55.09,55.09,20.3A7.92,7.92,0,0,1,194.82,151.43Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M197.58,129.06,146,110l-19-51.62a15.92,15.92,0,0,0-29.88,0L78,110l-51.62,19a15.92,15.92,0,0,0,0,29.88L78,178l19,51.62a15.92,15.92,0,0,0,29.88,0L146,178l51.62-19a15.92,15.92,0,0,0,0-29.88ZM137,164.22a8,8,0,0,0-4.74,4.74L112,223.85,91.78,169A8,8,0,0,0,87,164.22L32.15,144,87,123.78A8,8,0,0,0,91.78,119L112,64.15,132.22,119a8,8,0,0,0,4.74,4.74L191.85,144ZM144,40a8,8,0,0,1,8-8h16V16a8,8,0,0,1,16,0V32h16a8,8,0,0,1,0,16H184V64a8,8,0,0,1-16,0V48H152A8,8,0,0,1,144,40ZM248,88a8,8,0,0,1-8,8h-8v8a8,8,0,0,1-16,0V96h-8a8,8,0,0,1,0-16h8V72a8,8,0,0,1,16,0v8h8A8,8,0,0,1,248,88Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,144a15.78,15.78,0,0,1-10.42,14.94L146,178l-19,51.62a15.92,15.92,0,0,1-29.88,0L78,178l-51.62-19a15.92,15.92,0,0,1,0-29.88L78,110l19-51.62a15.92,15.92,0,0,1,29.88,0L146,110l51.62,19A15.78,15.78,0,0,1,208,144ZM152,48h16V64a8,8,0,0,0,16,0V48h16a8,8,0,0,0,0-16H184V16a8,8,0,0,0-16,0V32H152a8,8,0,0,0,0,16Zm88,32h-8V72a8,8,0,0,0-16,0v8h-8a8,8,0,0,0,0,16h8v8a8,8,0,0,0,16,0V96h8a8,8,0,0,0,0-16Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M196.89,130.94,144.4,111.6,125.06,59.11a13.92,13.92,0,0,0-26.12,0L79.6,111.6,27.11,130.94a13.92,13.92,0,0,0,0,26.12L79.6,176.4l19.34,52.49a13.92,13.92,0,0,0,26.12,0L144.4,176.4l52.49-19.34a13.92,13.92,0,0,0,0-26.12Zm-4.15,14.86-55.08,20.3a6,6,0,0,0-3.56,3.56l-20.3,55.08a1.92,1.92,0,0,1-3.6,0L89.9,169.66a6,6,0,0,0-3.56-3.56L31.26,145.8a1.92,1.92,0,0,1,0-3.6l55.08-20.3a6,6,0,0,0,3.56-3.56l20.3-55.08a1.92,1.92,0,0,1,3.6,0l20.3,55.08a6,6,0,0,0,3.56,3.56l55.08,20.3a1.92,1.92,0,0,1,0,3.6ZM146,40a6,6,0,0,1,6-6h18V16a6,6,0,0,1,12,0V34h18a6,6,0,0,1,0,12H182V64a6,6,0,0,1-12,0V46H152A6,6,0,0,1,146,40ZM246,88a6,6,0,0,1-6,6H230v10a6,6,0,0,1-12,0V94H208a6,6,0,0,1,0-12h10V72a6,6,0,0,1,12,0V82h10A6,6,0,0,1,246,88Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M197.58,129.06,146,110l-19-51.62a15.92,15.92,0,0,0-29.88,0L78,110l-51.62,19a15.92,15.92,0,0,0,0,29.88L78,178l19,51.62a15.92,15.92,0,0,0,29.88,0L146,178l51.62-19a15.92,15.92,0,0,0,0-29.88ZM137,164.22a8,8,0,0,0-4.74,4.74L112,223.85,91.78,169A8,8,0,0,0,87,164.22L32.15,144,87,123.78A8,8,0,0,0,91.78,119L112,64.15,132.22,119a8,8,0,0,0,4.74,4.74L191.85,144ZM144,40a8,8,0,0,1,8-8h16V16a8,8,0,0,1,16,0V32h16a8,8,0,0,1,0,16H184V64a8,8,0,0,1-16,0V48H152A8,8,0,0,1,144,40ZM248,88a8,8,0,0,1-8,8h-8v8a8,8,0,0,1-16,0V96h-8a8,8,0,0,1,0-16h8V72a8,8,0,0,1,16,0v8h8A8,8,0,0,1,248,88Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M196.2,132.81l-53.36-19.65L123.19,59.8a11.93,11.93,0,0,0-22.38,0L81.16,113.16,27.8,132.81a11.93,11.93,0,0,0,0,22.38l53.36,19.65,19.65,53.36a11.93,11.93,0,0,0,22.38,0l19.65-53.36,53.36-19.65a11.93,11.93,0,0,0,0-22.38Zm-2.77,14.87L138.35,168a4,4,0,0,0-2.37,2.37l-20.3,55.08a3.92,3.92,0,0,1-7.36,0L88,170.35A4,4,0,0,0,85.65,168l-55.08-20.3a3.92,3.92,0,0,1,0-7.36L85.65,120A4,4,0,0,0,88,117.65l20.3-55.08a3.92,3.92,0,0,1,7.36,0L136,117.65a4,4,0,0,0,2.37,2.37l55.08,20.3a3.92,3.92,0,0,1,0,7.36ZM148,40a4,4,0,0,1,4-4h20V16a4,4,0,0,1,8,0V36h20a4,4,0,0,1,0,8H180V64a4,4,0,0,1-8,0V44H152A4,4,0,0,1,148,40Zm96,48a4,4,0,0,1-4,4H228v12a4,4,0,0,1-8,0V92H208a4,4,0,0,1,0-8h12V72a4,4,0,0,1,8,0V84h12A4,4,0,0,1,244,88Z\" }))\n ]\n]);\nexport {\n l as default\n};\n","import * as r from \"react\";\nimport e from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Star.es.js\";\nconst t = r.forwardRef((o, a) => /* @__PURE__ */ r.createElement(e, { ref: a, ...o, weights: m }));\nt.displayName = \"StarIcon\";\nconst f = t;\nexport {\n f as Star,\n t as StarIcon\n};\n","import * as a from \"react\";\nconst l = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M243,96a20.33,20.33,0,0,0-17.74-14l-56.59-4.57L146.83,24.62a20.36,20.36,0,0,0-37.66,0L87.35,77.44,30.76,82A20.45,20.45,0,0,0,19.1,117.88l43.18,37.24-13.2,55.7A20.37,20.37,0,0,0,79.57,233L128,203.19,176.43,233a20.39,20.39,0,0,0,30.49-22.15l-13.2-55.7,43.18-37.24A20.43,20.43,0,0,0,243,96ZM172.53,141.7a12,12,0,0,0-3.84,11.86L181.58,208l-47.29-29.08a12,12,0,0,0-12.58,0L74.42,208l12.89-54.4a12,12,0,0,0-3.84-11.86L41.2,105.24l55.4-4.47a12,12,0,0,0,10.13-7.38L128,41.89l21.27,51.5a12,12,0,0,0,10.13,7.38l55.4,4.47Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M229.06,108.79l-48.7,42,14.88,62.79a8.4,8.4,0,0,1-12.52,9.17L128,189.09,73.28,222.74a8.4,8.4,0,0,1-12.52-9.17l14.88-62.79-48.7-42A8.46,8.46,0,0,1,31.73,94L95.64,88.8l24.62-59.6a8.36,8.36,0,0,1,15.48,0l24.62,59.6L224.27,94A8.46,8.46,0,0,1,229.06,108.79Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M239.18,97.26A16.38,16.38,0,0,0,224.92,86l-59-4.76L143.14,26.15a16.36,16.36,0,0,0-30.27,0L90.11,81.23,31.08,86a16.46,16.46,0,0,0-9.37,28.86l45,38.83L53,211.75a16.38,16.38,0,0,0,24.5,17.82L128,198.49l50.53,31.08A16.4,16.4,0,0,0,203,211.75l-13.76-58.07,45-38.83A16.43,16.43,0,0,0,239.18,97.26Zm-15.34,5.47-48.7,42a8,8,0,0,0-2.56,7.91l14.88,62.8a.37.37,0,0,1-.17.48c-.18.14-.23.11-.38,0l-54.72-33.65a8,8,0,0,0-8.38,0L69.09,215.94c-.15.09-.19.12-.38,0a.37.37,0,0,1-.17-.48l14.88-62.8a8,8,0,0,0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16A8,8,0,0,0,103,91.86l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153,91.86a8,8,0,0,0,6.75,4.92l63.92,5.16c.15,0,.24,0,.33.29S224,102.63,223.84,102.73Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M234.29,114.85l-45,38.83L203,211.75a16.4,16.4,0,0,1-24.5,17.82L128,198.49,77.47,229.57A16.4,16.4,0,0,1,53,211.75l13.76-58.07-45-38.83A16.46,16.46,0,0,1,31.08,86l59-4.76,22.76-55.08a16.36,16.36,0,0,1,30.27,0l22.75,55.08,59,4.76a16.46,16.46,0,0,1,9.37,28.86Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M237.28,97.87A14.18,14.18,0,0,0,224.76,88l-60.25-4.87-23.22-56.2a14.37,14.37,0,0,0-26.58,0L91.49,83.11,31.24,88a14.18,14.18,0,0,0-12.52,9.89A14.43,14.43,0,0,0,23,113.32L69,152.93l-14,59.25a14.4,14.4,0,0,0,5.59,15,14.1,14.1,0,0,0,15.91.6L128,196.12l51.58,31.71a14.1,14.1,0,0,0,15.91-.6,14.4,14.4,0,0,0,5.59-15l-14-59.25L233,113.32A14.43,14.43,0,0,0,237.28,97.87Zm-12.14,6.37-48.69,42a6,6,0,0,0-1.92,5.92l14.88,62.79a2.35,2.35,0,0,1-.95,2.57,2.24,2.24,0,0,1-2.6.1L131.14,184a6,6,0,0,0-6.28,0L70.14,217.61a2.24,2.24,0,0,1-2.6-.1,2.35,2.35,0,0,1-1-2.57l14.88-62.79a6,6,0,0,0-1.92-5.92l-48.69-42a2.37,2.37,0,0,1-.73-2.65,2.28,2.28,0,0,1,2.07-1.65l63.92-5.16a6,6,0,0,0,5.06-3.69l24.63-59.6a2.35,2.35,0,0,1,4.38,0l24.63,59.6a6,6,0,0,0,5.06,3.69l63.92,5.16a2.28,2.28,0,0,1,2.07,1.65A2.37,2.37,0,0,1,225.14,104.24Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M239.18,97.26A16.38,16.38,0,0,0,224.92,86l-59-4.76L143.14,26.15a16.36,16.36,0,0,0-30.27,0L90.11,81.23,31.08,86a16.46,16.46,0,0,0-9.37,28.86l45,38.83L53,211.75a16.38,16.38,0,0,0,24.5,17.82L128,198.49l50.53,31.08A16.4,16.4,0,0,0,203,211.75l-13.76-58.07,45-38.83A16.43,16.43,0,0,0,239.18,97.26Zm-15.34,5.47-48.7,42a8,8,0,0,0-2.56,7.91l14.88,62.8a.37.37,0,0,1-.17.48c-.18.14-.23.11-.38,0l-54.72-33.65a8,8,0,0,0-8.38,0L69.09,215.94c-.15.09-.19.12-.38,0a.37.37,0,0,1-.17-.48l14.88-62.8a8,8,0,0,0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16A8,8,0,0,0,103,91.86l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153,91.86a8,8,0,0,0,6.75,4.92l63.92,5.16c.15,0,.24,0,.33.29S224,102.63,223.84,102.73Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M235.36,98.49A12.21,12.21,0,0,0,224.59,90l-61.47-5L139.44,27.67a12.37,12.37,0,0,0-22.88,0L92.88,85,31.41,90a12.45,12.45,0,0,0-7.07,21.84l46.85,40.41L56.87,212.64a12.35,12.35,0,0,0,18.51,13.49L128,193.77l52.62,32.36a12.12,12.12,0,0,0,13.69-.51,12.28,12.28,0,0,0,4.82-13l-14.32-60.42,46.85-40.41A12.29,12.29,0,0,0,235.36,98.49Zm-8.93,7.26-48.68,42a4,4,0,0,0-1.28,3.95l14.87,62.79a4.37,4.37,0,0,1-1.72,4.65,4.24,4.24,0,0,1-4.81.18L130.1,185.67a4,4,0,0,0-4.2,0L71.19,219.32a4.24,4.24,0,0,1-4.81-.18,4.37,4.37,0,0,1-1.72-4.65L79.53,151.7a4,4,0,0,0-1.28-3.95l-48.68-42A4.37,4.37,0,0,1,28.25,101a4.31,4.31,0,0,1,3.81-3L96,92.79a4,4,0,0,0,3.38-2.46L124,30.73a4.35,4.35,0,0,1,8.08,0l24.62,59.6A4,4,0,0,0,160,92.79l63.9,5.15a4.31,4.31,0,0,1,3.81,3A4.37,4.37,0,0,1,226.43,105.75Z\" }))\n ]\n]);\nexport {\n l as default\n};\n","import * as e from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport c from \"../defs/UserCircle.es.js\";\nconst r = e.forwardRef((o, s) => /* @__PURE__ */ e.createElement(t, { ref: s, ...o, weights: c }));\nr.displayName = \"UserCircleIcon\";\nconst m = r;\nexport {\n m as UserCircle,\n r as UserCircleIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20ZM79.57,196.57a60,60,0,0,1,96.86,0,83.72,83.72,0,0,1-96.86,0ZM100,120a28,28,0,1,1,28,28A28,28,0,0,1,100,120ZM194,179.94a83.48,83.48,0,0,0-29-23.42,52,52,0,1,0-74,0,83.48,83.48,0,0,0-29,23.42,84,84,0,1,1,131.9,0Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M224,128a95.76,95.76,0,0,1-31.8,71.37A72,72,0,0,0,128,160a40,40,0,1,0-40-40,40,40,0,0,0,40,40,72,72,0,0,0-64.2,39.37h0A96,96,0,1,1,224,128Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM74.08,197.5a64,64,0,0,1,107.84,0,87.83,87.83,0,0,1-107.84,0ZM96,120a32,32,0,1,1,32,32A32,32,0,0,1,96,120Zm97.76,66.41a79.66,79.66,0,0,0-36.06-28.75,48,48,0,1,0-59.4,0,79.66,79.66,0,0,0-36.06,28.75,88,88,0,1,1,131.52,0Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M172,120a44,44,0,1,1-44-44A44.05,44.05,0,0,1,172,120Zm60,8A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88.09,88.09,0,0,0-91.47-87.93C77.43,41.89,39.87,81.12,40,128.25a87.65,87.65,0,0,0,22.24,58.16A79.71,79.71,0,0,1,84,165.1a4,4,0,0,1,4.83.32,59.83,59.83,0,0,0,78.28,0,4,4,0,0,1,4.83-.32,79.71,79.71,0,0,1,21.79,21.31A87.62,87.62,0,0,0,216,128Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26ZM71.44,198a66,66,0,0,1,113.12,0,89.8,89.8,0,0,1-113.12,0ZM94,120a34,34,0,1,1,34,34A34,34,0,0,1,94,120Zm99.51,69.64a77.53,77.53,0,0,0-40-31.38,46,46,0,1,0-51,0,77.53,77.53,0,0,0-40,31.38,90,90,0,1,1,131,0Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM74.08,197.5a64,64,0,0,1,107.84,0,87.83,87.83,0,0,1-107.84,0ZM96,120a32,32,0,1,1,32,32A32,32,0,0,1,96,120Zm97.76,66.41a79.66,79.66,0,0,0-36.06-28.75,48,48,0,1,0-59.4,0,79.66,79.66,0,0,0-36.06,28.75,88,88,0,1,1,131.52,0Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,28A100,100,0,1,0,228,128,100.11,100.11,0,0,0,128,28ZM68.87,198.42a68,68,0,0,1,118.26,0,91.8,91.8,0,0,1-118.26,0Zm124.3-5.55a75.61,75.61,0,0,0-44.51-34,44,44,0,1,0-41.32,0,75.61,75.61,0,0,0-44.51,34,92,92,0,1,1,130.34,0ZM128,156a36,36,0,1,1,36-36A36,36,0,0,1,128,156Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as r from \"react\";\nimport i from \"../lib/SSRBase.es.js\";\nimport n from \"../defs/WarningCircle.es.js\";\nconst e = r.forwardRef((o, a) => /* @__PURE__ */ r.createElement(i, { ref: a, ...o, weights: n }));\ne.displayName = \"WarningCircleIcon\";\nconst m = e;\nexport {\n m as WarningCircle,\n e as WarningCircleIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm-12-80V80a12,12,0,0,1,24,0v52a12,12,0,0,1-24,0Zm28,40a16,16,0,1,1-16-16A16,16,0,0,1,144,172Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-8,56a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm8,104a12,12,0,1,1,12-12A12,12,0,0,1,128,184Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26Zm0,192a90,90,0,1,1,90-90A90.1,90.1,0,0,1,128,218Zm-6-82V80a6,6,0,0,1,12,0v56a6,6,0,0,1-12,0Zm16,36a10,10,0,1,1-10-10A10,10,0,0,1,138,172Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,28A100,100,0,1,0,228,128,100.11,100.11,0,0,0,128,28Zm0,192a92,92,0,1,1,92-92A92.1,92.1,0,0,1,128,220Zm-4-84V80a4,4,0,0,1,8,0v56a4,4,0,0,1-8,0Zm12,36a8,8,0,1,1-8-8A8,8,0,0,1,136,172Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/X.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...r, weights: m }));\ne.displayName = \"XIcon\";\nconst f = e;\nexport {\n f as X,\n e as XIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208.49,191.51a12,12,0,0,1-17,17L128,145,64.49,208.49a12,12,0,0,1-17-17L111,128,47.51,64.49a12,12,0,0,1,17-17L128,111l63.51-63.52a12,12,0,0,1,17,17L145,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M216,56V200a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V56A16,16,0,0,1,56,40H200A16,16,0,0,1,216,56Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM181.66,170.34a8,8,0,0,1-11.32,11.32L128,139.31,85.66,181.66a8,8,0,0,1-11.32-11.32L116.69,128,74.34,85.66A8,8,0,0,1,85.66,74.34L128,116.69l42.34-42.35a8,8,0,0,1,11.32,11.32L139.31,128Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M204.24,195.76a6,6,0,1,1-8.48,8.48L128,136.49,60.24,204.24a6,6,0,0,1-8.48-8.48L119.51,128,51.76,60.24a6,6,0,0,1,8.48-8.48L128,119.51l67.76-67.75a6,6,0,0,1,8.48,8.48L136.49,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M202.83,197.17a4,4,0,0,1-5.66,5.66L128,133.66,58.83,202.83a4,4,0,0,1-5.66-5.66L122.34,128,53.17,58.83a4,4,0,0,1,5.66-5.66L128,122.34l69.17-69.17a4,4,0,1,1,5.66,5.66L133.66,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import type { Icon, IconProps, IconWeight } from \"@phosphor-icons/react\";\nimport {\n AlarmIcon,\n ArchiveIcon,\n ArrowBendUpLeftIcon,\n ArrowDownIcon,\n ArrowUpIcon,\n ArrowsClockwiseIcon,\n ArrowSquareOutIcon,\n ArrowsInIcon,\n ArrowsOutIcon,\n BookOpenTextIcon,\n BugIcon,\n BuildingsIcon,\n CopyIcon,\n CalendarBlankIcon,\n CaretDownIcon,\n CaretLeftIcon,\n CaretRightIcon,\n CellSignalHighIcon,\n CellSignalLowIcon,\n CellSignalMediumIcon,\n ChatCircleDotsIcon,\n ChatsCircleIcon,\n CheckIcon,\n CheckCircleIcon,\n CircleDashedIcon,\n CircleHalfIcon,\n CircleIcon,\n ClockIcon,\n ClockCounterClockwiseIcon,\n CodeIcon,\n CodeBlockIcon,\n CreditCardIcon,\n DeviceMobileIcon,\n DotsThreeIcon,\n EnvelopeSimpleIcon,\n FileIcon,\n FolderIcon,\n FolderOpenIcon,\n FolderPlusIcon,\n FunnelIcon,\n GitCommitIcon,\n GlobeSimpleIcon,\n ImageSquareIcon,\n KeyIcon,\n LightbulbIcon,\n LinkSimpleIcon,\n ListBulletsIcon,\n ListChecksIcon,\n ListNumbersIcon,\n LockSimpleIcon,\n MagicWandIcon,\n MagnifyingGlassIcon,\n MapPinIcon,\n MegaphoneIcon,\n MonitorIcon,\n MoonIcon,\n NoteIcon,\n NotionLogoIcon,\n PaperclipIcon,\n PaperPlaneRightIcon,\n PencilSimpleIcon,\n PlayIcon,\n PlugsConnectedIcon,\n PlusIcon,\n QuotesIcon,\n ShieldWarningIcon,\n SidebarSimpleIcon,\n SignOutIcon,\n SlidersHorizontalIcon,\n SparkleIcon,\n SquareIcon,\n StarIcon,\n SunIcon,\n TableIcon,\n TagIcon,\n TextBIcon,\n TextItalicIcon,\n TextStrikethroughIcon,\n TrashIcon,\n TrendUpIcon,\n UploadSimpleIcon,\n UserCircleIcon,\n UsersIcon,\n WarningCircleIcon,\n WrenchIcon,\n XCircleIcon,\n XIcon,\n} from \"@phosphor-icons/react/dist/ssr\";\n\n/**\n * Icons are the filled weight in this app.\n *\n * Phosphor sets weight per icon and the SSR entry does not read IconContext,\n * so the rule is applied here once instead of at every call site. Import from\n * this file rather than from @phosphor-icons/react directly.\n *\n * Props spread after the weight, so a caller can still override it.\n *\n * Every export below is annotated `@__PURE__`. A bundler cannot know that a\n * call at the top level of a module does nothing else, so without the\n * annotation one import from this file drags in all eighty-seven. That is\n * invisible in the app, which loads the whole set anyway, and was a fifth of\n * the published widget: it shipped Notion's logo and a signal meter to answer\n * a support question. Keep the annotation on anything added here.\n */\nfunction icon(Base: Icon, name: string, weight: IconWeight = \"fill\") {\n function Wrapped(props: IconProps) {\n return <Base weight={weight} {...props} />;\n }\n Wrapped.displayName = `${name}Icon`;\n return Wrapped;\n}\n\nexport const Alarm = /* @__PURE__ */ icon(AlarmIcon, \"Alarm\");\nexport const Archive = /* @__PURE__ */ icon(ArchiveIcon, \"Archive\");\nexport const BookOpenText = /* @__PURE__ */ icon(BookOpenTextIcon, \"BookOpenText\");\nexport const Bug = /* @__PURE__ */ icon(BugIcon, \"Bug\");\nexport const Buildings = /* @__PURE__ */ icon(BuildingsIcon, \"Buildings\");\nexport const CalendarBlank = /* @__PURE__ */ icon(CalendarBlankIcon, \"CalendarBlank\");\nexport const ChatCircleDots = /* @__PURE__ */ icon(ChatCircleDotsIcon, \"ChatCircleDots\");\nexport const ChatsCircle = /* @__PURE__ */ icon(ChatsCircleIcon, \"ChatsCircle\");\nexport const CellSignalHigh = /* @__PURE__ */ icon(CellSignalHighIcon, \"CellSignalHigh\");\nexport const CellSignalLow = /* @__PURE__ */ icon(CellSignalLowIcon, \"CellSignalLow\");\nexport const CellSignalMedium = /* @__PURE__ */ icon(CellSignalMediumIcon, \"CellSignalMedium\");\nexport const CheckCircle = /* @__PURE__ */ icon(CheckCircleIcon, \"CheckCircle\");\n// Half a body by design; the fill weight is the half that shows.\nexport const CircleHalf = /* @__PURE__ */ icon(CircleHalfIcon, \"CircleHalf\");\nexport const Clock = /* @__PURE__ */ icon(ClockIcon, \"Clock\");\nexport const ClockCounterClockwise = /* @__PURE__ */ icon(\n ClockCounterClockwiseIcon,\n \"ClockCounterClockwise\",\n);\nexport const CodeBlock = /* @__PURE__ */ icon(CodeBlockIcon, \"CodeBlock\");\nexport const Copy = /* @__PURE__ */ icon(CopyIcon, \"Copy\");\nexport const CreditCard = /* @__PURE__ */ icon(CreditCardIcon, \"CreditCard\");\nexport const DeviceMobile = /* @__PURE__ */ icon(DeviceMobileIcon, \"DeviceMobile\");\nexport const EnvelopeSimple = /* @__PURE__ */ icon(EnvelopeSimpleIcon, \"EnvelopeSimple\");\nexport const File = /* @__PURE__ */ icon(FileIcon, \"File\");\nexport const Folder = /* @__PURE__ */ icon(FolderIcon, \"Folder\");\nexport const FolderOpen = /* @__PURE__ */ icon(FolderOpenIcon, \"FolderOpen\");\nexport const FolderPlus = /* @__PURE__ */ icon(FolderPlusIcon, \"FolderPlus\");\nexport const Funnel = /* @__PURE__ */ icon(FunnelIcon, \"Funnel\");\nexport const GlobeSimple = /* @__PURE__ */ icon(GlobeSimpleIcon, \"GlobeSimple\");\n// Linear has no logo in this set, and a board is what the integration is\n// about anyway.\nexport const ImageSquare = /* @__PURE__ */ icon(ImageSquareIcon, \"ImageSquare\");\nexport const Key = /* @__PURE__ */ icon(KeyIcon, \"Key\");\nexport const Lightbulb = /* @__PURE__ */ icon(LightbulbIcon, \"Lightbulb\");\nexport const LockSimple = /* @__PURE__ */ icon(LockSimpleIcon, \"LockSimple\");\nexport const MagicWand = /* @__PURE__ */ icon(MagicWandIcon, \"MagicWand\");\nexport const MapPin = /* @__PURE__ */ icon(MapPinIcon, \"MapPin\");\nexport const Megaphone = /* @__PURE__ */ icon(MegaphoneIcon, \"Megaphone\");\nexport const Monitor = /* @__PURE__ */ icon(MonitorIcon, \"Monitor\");\nexport const Moon = /* @__PURE__ */ icon(MoonIcon, \"Moon\");\nexport const Note = /* @__PURE__ */ icon(NoteIcon, \"Note\");\nexport const NotionLogo = /* @__PURE__ */ icon(NotionLogoIcon, \"NotionLogo\");\nexport const Paperclip = /* @__PURE__ */ icon(PaperclipIcon, \"Paperclip\");\nexport const PaperPlaneRight = /* @__PURE__ */ icon(PaperPlaneRightIcon, \"PaperPlaneRight\");\nexport const PencilSimple = /* @__PURE__ */ icon(PencilSimpleIcon, \"PencilSimple\");\nexport const Play = /* @__PURE__ */ icon(PlayIcon, \"Play\");\nexport const PlugsConnected = /* @__PURE__ */ icon(PlugsConnectedIcon, \"PlugsConnected\");\nexport const Quotes = /* @__PURE__ */ icon(QuotesIcon, \"Quotes\");\nexport const Reply = /* @__PURE__ */ icon(ArrowBendUpLeftIcon, \"Reply\");\nexport const ShieldWarning = /* @__PURE__ */ icon(ShieldWarningIcon, \"ShieldWarning\");\nexport const SidebarSimple = /* @__PURE__ */ icon(SidebarSimpleIcon, \"SidebarSimple\");\nexport const SignOut = /* @__PURE__ */ icon(SignOutIcon, \"SignOut\");\nexport const SlidersHorizontal = /* @__PURE__ */ icon(\n SlidersHorizontalIcon,\n \"SlidersHorizontal\",\n);\nexport const Sparkle = /* @__PURE__ */ icon(SparkleIcon, \"Sparkle\");\n// The stop button's own glyph. Filled, because a stop is a solid block and\n// an outline of one reads as a checkbox.\nexport const Square = /* @__PURE__ */ icon(SquareIcon, \"Square\");\n// Filled either way: an empty star is this one wearing a quieter colour, so\n// the row cannot change shape as it fills.\nexport const Star = /* @__PURE__ */ icon(StarIcon, \"Star\");\nexport const Sun = /* @__PURE__ */ icon(SunIcon, \"Sun\");\nexport const Table = /* @__PURE__ */ icon(TableIcon, \"Table\");\nexport const Tag = /* @__PURE__ */ icon(TagIcon, \"Tag\");\nexport const Trash = /* @__PURE__ */ icon(TrashIcon, \"Trash\");\nexport const TrendUp = /* @__PURE__ */ icon(TrendUpIcon, \"TrendUp\");\nexport const UserCircle = /* @__PURE__ */ icon(UserCircleIcon, \"UserCircle\");\nexport const Users = /* @__PURE__ */ icon(UsersIcon, \"Users\");\nexport const WarningCircle = /* @__PURE__ */ icon(WarningCircleIcon, \"WarningCircle\");\nexport const Wrench = /* @__PURE__ */ icon(WrenchIcon, \"Wrench\");\nexport const XCircle = /* @__PURE__ */ icon(XCircleIcon, \"XCircle\");\n\n// Exceptions. These are line glyphs with nothing to fill in, so Phosphor's\n// fill weight gives them a shape instead of a body: Check becomes a filled\n// box, the carets become solid triangles, the magnifier becomes a solid disc,\n// the three dots swell into blobs, and the arrow turns into a slab. Bold is\n// the heavier version of the same icon, which is what fill is meant to look\n// like here.\nexport const ArrowDown = /* @__PURE__ */ icon(ArrowDownIcon, \"ArrowDown\", \"bold\");\nexport const ArrowUp = /* @__PURE__ */ icon(ArrowUpIcon, \"ArrowUp\", \"bold\");\nexport const ArrowsClockwise = /* @__PURE__ */ icon(\n ArrowsClockwiseIcon,\n \"ArrowsClockwise\",\n \"bold\",\n);\nexport const ArrowSquareOut = /* @__PURE__ */ icon(ArrowSquareOutIcon, \"ArrowSquareOut\", \"bold\");\nexport const ArrowsIn = /* @__PURE__ */ icon(ArrowsInIcon, \"ArrowsIn\", \"bold\");\nexport const ArrowsOut = /* @__PURE__ */ icon(ArrowsOutIcon, \"ArrowsOut\", \"bold\");\nexport const CaretDown = /* @__PURE__ */ icon(CaretDownIcon, \"CaretDown\", \"bold\");\nexport const CaretLeft = /* @__PURE__ */ icon(CaretLeftIcon, \"CaretLeft\", \"bold\");\nexport const CaretRight = /* @__PURE__ */ icon(CaretRightIcon, \"CaretRight\", \"bold\");\n// Rings, not discs: filling them leaves a dot where a status should be.\nexport const Circle = /* @__PURE__ */ icon(CircleIcon, \"Circle\", \"bold\");\nexport const CircleDashed = /* @__PURE__ */ icon(CircleDashedIcon, \"CircleDashed\", \"bold\");\nexport const Check = /* @__PURE__ */ icon(CheckIcon, \"Check\", \"bold\");\n// A line drawing of a node on a line, like the carets: filling it makes a\n// blob rather than a heavier commit.\nexport const GitCommit = /* @__PURE__ */ icon(GitCommitIcon, \"GitCommit\", \"bold\");\nexport const DotsThree = /* @__PURE__ */ icon(DotsThreeIcon, \"DotsThree\", \"bold\");\nexport const X = /* @__PURE__ */ icon(XIcon, \"X\", \"bold\");\nexport const Plus = /* @__PURE__ */ icon(PlusIcon, \"Plus\", \"bold\");\nexport const UploadSimple = /* @__PURE__ */ icon(UploadSimpleIcon, \"UploadSimple\", \"bold\");\nexport const MagnifyingGlass = /* @__PURE__ */ icon(\n MagnifyingGlassIcon,\n \"MagnifyingGlass\",\n \"bold\",\n);\n\n// The editor toolbar's glyphs live here too: letterforms, list markers, and\n// brackets are all line drawings, so they take the bold weight for the same\n// reason the carets do. CodeBlock and Quotes are up in the filled group,\n// having actual bodies to fill.\nexport const Code = /* @__PURE__ */ icon(CodeIcon, \"Code\", \"bold\");\nexport const LinkSimple = /* @__PURE__ */ icon(LinkSimpleIcon, \"LinkSimple\", \"bold\");\nexport const ListBullets = /* @__PURE__ */ icon(ListBulletsIcon, \"ListBullets\", \"bold\");\nexport const ListChecks = /* @__PURE__ */ icon(ListChecksIcon, \"ListChecks\", \"bold\");\nexport const ListNumbers = /* @__PURE__ */ icon(ListNumbersIcon, \"ListNumbers\", \"bold\");\nexport const TextB = /* @__PURE__ */ icon(TextBIcon, \"TextB\", \"bold\");\nexport const TextItalic = /* @__PURE__ */ icon(TextItalicIcon, \"TextItalic\", \"bold\");\nexport const TextStrikethrough = /* @__PURE__ */ icon(\n TextStrikethroughIcon,\n \"TextStrikethrough\",\n \"bold\",\n);\n","/**\n * Where the widget lives, and everything that follows from it.\n *\n * A side and a height. The button snaps to the left or the right edge, because\n * an edge is where a thing parked on somebody's page belongs, and keeps\n * whatever height it was let go at, because that is the half nobody can guess\n * for them: the button is in the way of a cart, a banner or a footer, and only\n * the person looking at it knows which.\n *\n * The height is kept as a fraction of the travel rather than a number of\n * pixels, so a window that changes size moves it proportionally instead of\n * stranding it off the bottom.\n */\n\nexport type LauncherSide = \"left\" | \"right\";\n\n/** `y` runs 0 at the top of its travel to 1 at the bottom. */\nexport type LauncherSpot = { side: LauncherSide; y: number };\n\nexport const DEFAULT_SPOT: LauncherSpot = { side: \"right\", y: 1 };\n\nexport type Bounds = { left: number; top: number; width: number; height: number };\nexport type Size = { width: number; height: number };\n\nfunction clamp(value: number, low: number, high: number): number {\n return Math.min(Math.max(value, low), Math.max(low, high));\n}\n\n/** How far the button can travel between the top margin and the bottom one. */\nexport function travelOf(bounds: Bounds, button: Size, margin: number): number {\n return Math.max(0, bounds.height - 2 * margin - button.height);\n}\n\n/** The spot a button that landed here belongs to. */\nexport function spotFrom(\n at: { x: number; y: number },\n bounds: Bounds,\n button: Size,\n margin: number,\n): LauncherSpot {\n const travel = travelOf(bounds, button, margin);\n\n return {\n side:\n at.x + button.width / 2 < bounds.left + bounds.width / 2\n ? \"left\"\n : \"right\",\n y: travel === 0 ? 0 : clamp((at.y - bounds.top - margin) / travel, 0, 1),\n };\n}\n\n/**\n * The spot a panel dropped here belongs to.\n *\n * The other way round from the one above: an open panel is dragged by its own\n * header, so what landed somewhere is the box, not the button. The box hangs\n * upward from the button, so the button is at the box's bottom edge, and that\n * is the height the spot is a fraction of.\n *\n * The two do not cover the same range, and should not. A panel dragged to the\n * top of a short window still leaves its button at the panel's bottom edge,\n * which is exactly where the bubble should be waiting when it closes.\n */\nexport function spotFromPanel(\n at: { x: number; y: number },\n bounds: Bounds,\n button: Size,\n box: Size,\n margin: number,\n): LauncherSpot {\n const travel = travelOf(bounds, button, margin);\n const buttonY = at.y + box.height - button.height;\n\n return {\n side:\n at.x + box.width / 2 < bounds.left + bounds.width / 2 ? \"left\" : \"right\",\n y: travel === 0 ? 0 : clamp((buttonY - bounds.top - margin) / travel, 0, 1),\n };\n}\n\n/**\n * Everything the widget is positioned by, worked out from a spot.\n *\n * The box is panel sized and hangs upward from the button, which is where it\n * hung when this was a corner. Clamped so it never leaves the space it is in:\n * a button near the top drags the panel down below it instead, and the button\n * simply sits further up inside the same box.\n */\nexport function metricsFor(\n spot: LauncherSpot,\n bounds: Bounds,\n button: Size,\n boxHeight: number,\n margin: number,\n): { buttonY: number; boxTop: number; buttonInBox: number } {\n const buttonY = bounds.top + margin + spot.y * travelOf(bounds, button, margin);\n\n const highest = bounds.top + margin;\n const lowest = bounds.top + bounds.height - margin - boxHeight;\n const boxTop = clamp(buttonY + button.height - boxHeight, highest, lowest);\n\n return { buttonY, boxTop, buttonInBox: buttonY - boxTop };\n}\n\n/**\n * The closed shape: a circle the size of the button, at the button's own\n * height on the side it is parked against.\n *\n * `buttonY` is handed in as a CSS length rather than a number, so the same\n * function writes the resting shape from a variable the layout has filled in\n * and the fallback shape from a plain calc.\n */\nexport function closedClip(\n side: LauncherSide,\n buttonY: string,\n buttonSize: string,\n): string {\n const far = `calc(100% - ${buttonSize})`;\n\n return [\n `inset(${buttonY}`,\n side === \"left\" ? far : \"0px\",\n `calc(100% - ${buttonY} - ${buttonSize})`,\n side === \"left\" ? \"0px\" : far,\n `round calc(${buttonSize} / 2))`,\n ].join(\" \");\n}\n\n/** The point the scale grows from, so the circle stays under the button. */\nexport function clipOrigin(\n side: LauncherSide,\n buttonY: string,\n buttonSize: string,\n): string {\n return `${side === \"left\" ? \"0%\" : \"100%\"} calc(${buttonY} + ${buttonSize} / 2)`;\n}\n\n/**\n * Where this browser last left it.\n *\n * A small store rather than a bare read, the same shape `session.ts` uses and\n * for the same two reasons. The server cannot know, so it renders the default\n * and the store hands the real answer over on the client without a mismatched\n * attribute in between; and a snapshot has to be stable across calls, which is\n * what the cache is for.\n */\nconst STORAGE_KEY = \"median:launcher-spot\";\n\nconst listeners = new Set<() => void>();\nlet current: LauncherSpot | null = null;\n\nexport function subscribeSpot(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function getSpot(): LauncherSpot {\n if (current !== null) return current;\n\n current = DEFAULT_SPOT;\n try {\n const stored = window.localStorage.getItem(STORAGE_KEY);\n const parsed: unknown = stored === null ? null : JSON.parse(stored);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"side\" in parsed &&\n \"y\" in parsed\n ) {\n const { side, y } = parsed as { side: unknown; y: unknown };\n if ((side === \"left\" || side === \"right\") && typeof y === \"number\") {\n current = { side, y: clamp(y, 0, 1) };\n }\n }\n } catch {\n // Blocked storage, or something else's key with our name on it. Either\n // way the default is a perfectly good place for a support button.\n }\n return current;\n}\n\nexport function getDefaultSpot(): LauncherSpot {\n return DEFAULT_SPOT;\n}\n\nexport function setSpot(spot: LauncherSpot): void {\n current = spot;\n\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(spot));\n } catch {\n // It stays where they put it until the page goes away, which is the same\n // deal the session token gets.\n }\n\n for (const listener of listeners) listener();\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n MessageScroller as MessageScrollerPrimitive,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\";\n\n// Phosphor instead of the registry default, per the project icon rule.\nimport { ArrowDown } from \"@/components/icons\";\nimport { Button } from \"@/components/ui/button\";\nimport { useIsResizing } from \"@/hooks/use-is-resizing\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * From the shadcn registry (@shadcn/message-scroller, radix-nova style), with\n * two changes: the icon comes from our own set, and the registry's\n * `scrollbar-*` and `inset-s-*` utilities are written as plain properties,\n * since neither the scrollbar plugin nor logical inset utilities are here.\n *\n * `scrollbar-width` is said here as well as on the app's own `html`, and the\n * repetition is the point: this is the one scroller that also runs inside the\n * widget on somebody else's page, where there is no `html` of ours to inherit\n * from and a thread would otherwise wear whatever their site wears.\n */\n\nfunction MessageScrollerProvider({\n autoScroll = true,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>) {\n // Every thread here is a chat, so the chat behavior is the default: stay\n // pinned to the newest message while at the bottom, stay put while reading\n // older ones, and let the button offer the way back down. The primitive's\n // own default (off, with per-item scroll anchors) is built for pin-the-\n // question streaming UIs and yanks the viewport around in a live thread.\n return <MessageScrollerPrimitive.Provider autoScroll={autoScroll} {...props} />;\n}\n\nfunction MessageScroller({\n className,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Root>) {\n return (\n <MessageScrollerPrimitive.Root\n data-slot=\"message-scroller\"\n className={cn(\n \"group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Within this of the foot of the thread counts as being at it. */\nconst AT_END_PX = 8;\n/** Less than a pixel adrift is not worth correcting. */\nconst DRIFT_PX = 1;\n\n/**\n * Holds the newest message against the foot of the viewport while the viewport\n * is changing size.\n *\n * The scroller already does this, one frame late. Both of its resize observers\n * hand their work to `requestAnimationFrame`, so every frame of a resize is\n * painted with the scroll position the frame before it asked for.\n *\n * Growing hides that. A viewport that gets taller leaves its scroll offset out\n * of range, and the browser has to pull it back in as part of the same layout,\n * which lands the thread exactly where the late correction was going to put it\n * anyway. Shrinking has nothing doing that: the offset stays valid, the foot of\n * the viewport comes down past the thread, and the newest message drops a dozen\n * pixels behind and is dragged back a frame later. Every frame. That is the\n * shiver, and it is why only shrinking has it, and why it is worst on a panel\n * parked at the bottom, where the whole of the change comes off the top.\n *\n * So the same correction is made here first, in the observer itself, which is\n * before the frame is painted rather than after.\n */\nfunction usePinnedToEnd(viewport: React.RefObject<HTMLDivElement | null>) {\n React.useEffect(() => {\n const node = viewport.current;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n\n // Whether the thread was against the foot of the viewport, written down as\n // it happens: by the time a resize is reported the new size is already on\n // and the answer to that has changed.\n let wasAtEnd = true;\n const remember = () => {\n wasAtEnd =\n node.scrollHeight - node.scrollTop - node.clientHeight <= AT_END_PX;\n };\n\n const observer = new ResizeObserver(() => {\n const drift = node.scrollHeight - node.scrollTop - node.clientHeight;\n\n // Only ever catching up, never restating. A viewport that grew has had\n // its offset put back in range by the browser already, to a precision\n // this cannot match: `scrollHeight` and `clientHeight` are whole pixels\n // and the box between them is not, so saying it again would replace an\n // exact answer with one up to a pixel out, differently on every frame.\n if (wasAtEnd && drift > DRIFT_PX) {\n // Not `auto`, which would take the smooth scrolling below and ease a\n // correction that is meant to be invisible.\n node.scrollTo({\n top: node.scrollHeight - node.clientHeight,\n behavior: \"instant\",\n });\n }\n\n remember();\n });\n\n node.addEventListener(\"scroll\", remember, { passive: true });\n observer.observe(node);\n return () => {\n node.removeEventListener(\"scroll\", remember);\n observer.disconnect();\n };\n }, [viewport]);\n}\n\n/**\n * True from the frame after the viewport mounts, which is a frame after the\n * scroller has put itself at the newest message.\n */\nfunction useHasLanded() {\n const [hasLanded, setHasLanded] = React.useState(false);\n\n React.useEffect(() => {\n const frame = requestAnimationFrame(() => setHasLanded(true));\n\n return () => cancelAnimationFrame(frame);\n }, []);\n\n return hasLanded;\n}\n\nfunction MessageScrollerViewport({\n className,\n ref,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Viewport>) {\n const viewport = React.useRef<HTMLDivElement | null>(null);\n\n // Two scrolls are never worth watching, and this is both of them.\n //\n // The first one: a thread opens at the top and lands on the newest message,\n // and easing that drags the whole history past before you can read any of it.\n //\n // And every one during a resize: a panel growing, a window dragged, a phone\n // keyboard coming up. Each of those re-pins the thread on every frame, and\n // easing towards a target that moves every frame leaves the messages\n // trailing the box they are in.\n const hasLanded = useHasLanded();\n const isResizing = useIsResizing(viewport);\n const isSettled = hasLanded && !isResizing;\n\n usePinnedToEnd(viewport);\n\n // Ours as well as whoever else asked for it. The primitive keeps its own\n // separately, so this is only the two of us.\n const holdViewport = React.useCallback(\n (node: HTMLDivElement | null) => {\n viewport.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n },\n [ref],\n );\n\n return (\n <MessageScrollerPrimitive.Viewport\n ref={holdViewport}\n data-slot=\"message-scroller-viewport\"\n // Every scroll the scroller makes for itself asks for `auto`, which\n // hands the decision to this element, so the thread is either all\n // animated or none of it. Only the button picks smooth on its own.\n //\n // All of them are a pin to the newest message today. The one to watch\n // for is the correction that holds your place when older messages are\n // loaded in above: that one wants to be instant, and it would have to\n // stop asking for `auto` to stay that way.\n data-settled={isSettled ? \"\" : undefined}\n className={cn(\n \"size-full min-h-0 min-w-0 overflow-y-auto overscroll-contain contain-content [scrollbar-gutter:stable] [scrollbar-width:thin]\",\n // A reply landing while you are at the bottom should carry you down\n // rather than teleport you, and the button should travel the distance\n // it is offering to cover. See above for the two that are left out.\n //\n // Granted rather than taken away, since `motion-reduce:scroll-auto`\n // would lose to an attribute selector and never get a say.\n \"motion-safe:data-settled:scroll-smooth\",\n // The fade says \"there is more below\", so it only belongs to a\n // viewport that has more below.\n //\n // The registry hangs `scroll-fade-b` on unconditionally and retracts\n // it with a scroll driven animation. That leaves the newest message\n // dimmed at the foot of every thread: a browser without scroll\n // timelines takes the utility's own fallback and pins the fade on\n // forever, and even where they work the mask is still painted over a\n // thread too short to scroll at all. `data-scrollable` is the same\n // question answered by measurement, and the primitive already writes\n // it here. It drops \"end\" as soon as you are within a few pixels of\n // the bottom, and while it is following the bottom it never claims it.\n \"data-[scrollable~=end]:scroll-fade-b\",\n // The registry also blanks the scrollbar while the scroller is moving\n // on its own. That was covering for the jump: the bar flicked from one\n // place to another with nothing in between. Now it slides, so hiding it\n // is the flicker, and it holds the thumb back for a fixed 180ms that\n // has nothing to do with how far the thread actually travelled.\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MessageScrollerContent({\n className,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Content>) {\n return (\n <MessageScrollerPrimitive.Content\n data-slot=\"message-scroller-content\"\n className={cn(\"flex h-max min-h-full flex-col gap-6\", className)}\n {...props}\n />\n );\n}\n\nfunction MessageScrollerItem({\n className,\n scrollAnchor = false,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Item>) {\n return (\n <MessageScrollerPrimitive.Item\n data-slot=\"message-scroller-item\"\n scrollAnchor={scrollAnchor}\n className={cn(\n \"min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MessageScrollerButton({\n direction = \"end\",\n className,\n children,\n render,\n variant = \"secondary\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Button> &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">) {\n return (\n <MessageScrollerPrimitive.Button\n data-slot=\"message-scroller-button\"\n data-direction={direction}\n data-variant={variant}\n data-size={size}\n direction={direction}\n className={cn(\n \"absolute start-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180\",\n className,\n )}\n render={render ?? <Button variant={variant} size={size} />}\n {...props}\n >\n {children ?? (\n <>\n <ArrowDown />\n <span className=\"sr-only\">\n {direction === \"end\" ? \"Scroll to end\" : \"Scroll to start\"}\n </span>\n </>\n )}\n </MessageScrollerPrimitive.Button>\n );\n}\n\nexport {\n MessageScrollerProvider,\n MessageScroller,\n MessageScrollerViewport,\n MessageScrollerContent,\n MessageScrollerItem,\n MessageScrollerButton,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n};\n","import*as i from'react';function S({defaultTagName:a,props:r,render:t,state:n={},stateAttributesMapping:e}){let o=d(R(n,e),r);if(!t)return i.createElement(a,o);if(typeof t==\"function\")return t(o,n);if(!i.isValidElement(t))return null;let s=t.props,u={...d(o,s),ref:f(o.ref,s.ref)};return i.cloneElement(t,u)}function d(...a){let r={};for(let t of a){if(!t)continue;let n=t;for(let e of Object.keys(n)){let o=n[e];if(o===void 0)continue;let s=r[e];e===\"className\"?r[e]=[s,o].filter(Boolean).join(\" \"):e===\"style\"?r[e]={...s,...o}:e===\"ref\"?r[e]=f(s,o):l(e)&&typeof s==\"function\"&&typeof o==\"function\"?r[e]=p(o,s):r[e]=o;}}return r}function R(a,r){let t={};for(let n of Object.keys(a)){let e=a[n],o=r?.[n]?.(e);if(o){Object.assign(t,o);continue}if(n===\"slot\"){t[\"data-slot\"]=e;continue}let s=`data-${String(n).replace(/[A-Z]/g,c=>`-${c.toLowerCase()}`)}`;typeof e==\"boolean\"?t[s]=e?\"\":void 0:e!=null&&(t[s]=String(e));}return t}function p(a,r){return function(n){a(n),n.defaultPrevented||r(n);}}function l(a){return /^on[A-Z]/.test(a)}function f(...a){let r=a.filter(Boolean);if(r.length!==0)return t=>{for(let n of r)typeof n==\"function\"?n(t):n&&(n.current=t);}}export{S as a,d as b,f as c};","\"use client\";\nimport {c,a,b}from'../chunk-HBS6WEDP.js';import*as g from'react';import {jsx,jsxs}from'react/jsx-runtime';var xe=8,Ve=64,_e=0,J=.5,ke=180,Be=new Set([\"ArrowDown\",\"ArrowUp\",\"End\",\"Home\",\"PageDown\",\"PageUp\",\" \"]),ge={start:false,end:false},dt=[],Q={currentAnchorId:null,visibleMessageIds:dt};function De({content:e,scrollEdgeThreshold:t,spacer:r,viewport:n}){if(!n||!e)return ge;let o=Se({content:e,spacer:r,viewport:n});return {start:n.scrollTop>t,end:o-n.scrollTop-n.clientHeight>t}}function Fe({content:e,scrollMargin:t,scrollPreviousItemPeek:r,spacer:n,viewport:o,visibleMessageIds:i}){if(!e||!o)return Q;let S=o.getBoundingClientRect(),l=S.top+t+r,d=typeof IntersectionObserver>\"u\",E=[],b=null;for(let C of ee(e,n)){let p=C.dataset.messageId;if(!p)continue;let m=C.dataset.scrollAnchor===\"true\",L=m||d?C.getBoundingClientRect():null;(d&&L?L.bottom>l&&L.top<S.bottom:i.has(p))&&E.push(p),m&&L&&L.top<=l+J&&(b=p);}return E.length===0&&b===null?Q:{currentAnchorId:b,visibleMessageIds:E}}function ee(e,t){return Array.from(e.children).filter(r=>r instanceof HTMLElement&&r!==t)}function je(e,t){for(let r=t;r<e.length;r++){let n=e[r];if(n?.dataset.scrollAnchor===\"true\")return n}return null}function Ge(e,t){for(let r of e)if(r.dataset.scrollAnchor===\"true\"&&!t.has(r))return r;return null}function Ne(e,t){let r=0;for(let n=t;n<e.length;n++)if(e[n]?.dataset.scrollAnchor===\"true\"&&(r+=1,r>1))return true;return false}function Ue(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(r?.dataset.scrollAnchor===\"true\")return r}return null}function Ye({content:e,spacer:t,viewport:r}){let n=r.getBoundingClientRect();for(let o of ee(e,t)){if(!o.dataset.messageId)continue;let i=o.getBoundingClientRect();if(i.bottom>n.top&&i.top<n.bottom)return o}return null}function ze({align:e,element:t,scrollMargin:r,spacer:n,viewport:o}){let i=pe(t,o),S=t.getBoundingClientRect().height,l=bt(n);if(e===\"center\"){let d=Math.max(0,o.clientHeight-l.start-l.end);return i-l.start-(d-S)/2-r}if(e===\"end\")return i-o.clientHeight+S+l.end+r;if(e===\"nearest\"){let d=i+S,E=o.scrollTop+l.start,b=o.scrollTop+o.clientHeight-l.end;return i>=E&&d<=b?o.scrollTop:i<E?i-l.start-r:d-o.clientHeight+l.end+r}return i-l.start-r}function pe(e,t){let r=e.getBoundingClientRect(),n=t.getBoundingClientRect();return r.top-n.top+t.scrollTop}function te(e,t){return e.getBoundingClientRect().top-t.getBoundingClientRect().top}function qe({content:e,scrollTop:t,spacer:r,viewport:n}){let o=Se({content:e,spacer:r,viewport:n});return t+n.clientHeight-o}function Se({content:e,spacer:t,viewport:r}){let n=ee(e,t),o=We(e),i=r.getBoundingClientRect(),S=r.scrollTop,l=o.start+o.end;for(let d of n){let E=d.getBoundingClientRect();l=Math.max(l,E.bottom-i.top+S+o.end);}return l}function Ke(e){return Math.max(0,e.scrollHeight-e.clientHeight)}function We(e){let t=window.getComputedStyle(e);return {end:Re(t.paddingBlockEnd||t.paddingBottom),start:Re(t.paddingBlockStart||t.paddingTop)}}function bt(e){let t=e?.parentElement;return t?We(t):{end:0,start:0}}function $e(e){if(!e)return 0;let t=window.getComputedStyle(e),r=t.rowGap===\"normal\"?t.gap:t.rowGap;return Re(r)}function Re(e){if(!e)return 0;let t=Number.parseFloat(e);return Number.isFinite(t)?t:0}function Je({refs:e,commitScrollState:t,scheduleStateCommit:r,scheduleVisibilitySync:n}){let{streamingTurnRef:o,autoScrollRef:i,autoscrollingRef:S,autoscrollingTimeoutRef:l,contentRef:d,defaultScrollPositionAppliedRef:E,itemCountRef:b,messageElementsRef:C,modeRef:p,pendingScrollToMessageRef:m,prependRestoreRef:L,scrollMarginRef:y,scrollPreviousItemPeekRef:u,spacerGapRef:x,spacerHeightRef:Y,spacerRef:k,viewportRef:_}=e,G=g.useCallback(c=>{l.current!==null&&(window.clearTimeout(l.current),l.current=null),S.current!==c&&(S.current=c,t()),c&&(l.current=window.setTimeout(()=>{l.current=null,S.current=false,t();},ke));},[t]),v=g.useCallback(c=>{let f=k.current;if(!f)return;let h=Math.max(0,Math.ceil(c));Y.current!==h&&(Y.current=h,f.hidden=h===0,f.style.height=`${h}px`,f.style.marginTop=h>0?`${-x.current}px`:\"\");},[]),H=g.useCallback((c,{behavior:f=\"auto\",autoscrolling:h=false}={})=>{let P=_.current;if(!P)return;let V=Math.max(0,c);if(Math.abs(P.scrollTop-V)<=J){P.scrollTop=V,t();return}h&&G(true),P.scrollTo({top:V,behavior:f}),r();},[t,r,G]),N=g.useCallback(({behavior:c=\"auto\"}={})=>_.current?(v(0),o.current=null,p.current=\"free-scrolling\",H(0,{behavior:c}),n(),true):false,[n,H,v]),ne=g.useCallback(({behavior:c=\"auto\"}={})=>{let f=_.current;return f?(v(0),o.current=null,p.current=i.current?\"following-bottom\":\"free-scrolling\",H(Ke(f),{autoscrolling:true,behavior:c}),n(),true):false},[n,H,v]),A=g.useCallback((c,{align:f=\"start\",behavior:h=\"auto\",scrollMargin:P=y.current}={},{keepPreviousPeek:V=false}={})=>{let z=d.current,q=_.current;if(!z||!q||!z.contains(c))return false;let K=ze({align:f,element:c,scrollMargin:V?P+u.current:P,spacer:k.current,viewport:q}),se=qe({content:z,scrollTop:K,spacer:k.current,viewport:q});return v(se),L.current={element:c,viewportTop:te(c,q)},p.current=V?\"anchored-to-message\":\"settling-jump\",o.current=V?c:null,H(K,{behavior:h}),n(),true},[n,H,v]),B=g.useCallback(()=>{let c=o.current;return !c||!c.isConnected||p.current!==\"anchored-to-message\"?false:A(c,{align:\"start\"},{keepPreviousPeek:true})},[A]),D=g.useCallback((c,f)=>{let h=C.current.get(c);return h?(E.current=true,A(h,f)?(m.current=null,true):(m.current={messageId:c,options:f},true)):b.current===0?(m.current={messageId:c,options:f},E.current=true,true):false},[A]);return {flushPendingScrollToMessage:g.useCallback(()=>{let c=m.current;if(!c)return false;let f=C.current.get(c.messageId);return !f||!A(f,c.options)?false:(m.current=null,E.current=true,true)},[A]),reanchorToAnchoredMessage:B,scrollToElement:A,scrollToEnd:ne,scrollToMessage:D,scrollToStart:N}}function Qe(e,t){let r=e,n=new Set;return {getSnapshot:()=>r,hasListeners:()=>n.size>0,setSnapshot:o=>{t(r,o)||(r=o,n.forEach(i=>i()));},subscribe:(o,i,S)=>{let l=n.size===0;return n.add(o),l&&i?.(),()=>{n.delete(o),n.size===0&&S?.();}}}}function Xe(e,t){return Qe(e,t)}function Ze(){return Qe(Q,Tt)}function et(e,t){return e.start===t.start&&e.end===t.end}function Tt(e,t){return e.currentAnchorId!==t.currentAnchorId||e.visibleMessageIds.length!==t.visibleMessageIds.length?false:e.visibleMessageIds.every((r,n)=>r===t.visibleMessageIds[n])}function tt({autoScroll:e,scrollEdgeThreshold:t,scrollMargin:r,scrollPreviousItemPeek:n}){let o=g.useRef(e),i=g.useRef(false),S=g.useRef(null),l=g.useRef(false),d=g.useRef(t),E=g.useRef(0),b=g.useRef(null),C=g.useRef(0),p=g.useRef(e?\"following-bottom\":\"free-scrolling\"),m=g.useRef(new Map),L=g.useRef(null),y=g.useRef(null),u=g.useRef(null),x=g.useRef(n),Y=g.useRef(true),k=g.useRef(null),_=g.useRef(r),G=g.useRef(null),v=g.useRef(0),H=g.useRef(0),N=g.useRef(null),ne=g.useRef(null),A=g.useRef(null),B=g.useRef(null),D=g.useRef(null),U=g.useRef(null),c=g.useRef(null),f=g.useRef(null),h=g.useRef(new Set),P=g.useRef(new WeakSet);return A.current===null&&(A.current=Xe(ge,et)),f.current===null&&(f.current=Ze()),o.current=e,d.current=t,_.current=r,x.current=n,{autoScrollRef:o,autoscrollingRef:i,autoscrollingTimeoutRef:B,streamingTurnRef:u,contentRef:S,defaultScrollPositionAppliedRef:l,firstItemRef:b,itemCountRef:E,lastScrollTopRef:C,messageElementsRef:m,modeRef:p,pendingScrollFrameRef:G,pendingScrollToMessageRef:L,prependRestoreRef:y,preserveScrollOnPrependRef:Y,rootRef:k,scrollEdgeThresholdRef:d,scrollMarginRef:_,scrollPreviousItemPeekRef:x,spacerGapRef:v,spacerHeightRef:H,spacerRef:N,stateFrameRef:ne,stateStore:A.current,viewportRef:D,visibilityFrameRef:U,visibilityObserverRef:c,visibilityStore:f.current,visibleMessageIdsRef:h,handledScrollAnchorsRef:P}}function rt(e,t){return g.useCallback(r=>{e.current=r,r&&t();},[e,t])}function nt({autoScroll:e=false,defaultScrollPosition:t=\"end\",scrollEdgeThreshold:r=xe,scrollPreviousItemPeek:n=Ve,scrollMargin:o=_e}){let i=tt({autoScroll:e,scrollEdgeThreshold:r,scrollMargin:o,scrollPreviousItemPeek:n}),{streamingTurnRef:S,autoScrollRef:l,autoscrollingRef:d,autoscrollingTimeoutRef:E,contentRef:b,defaultScrollPositionAppliedRef:C,firstItemRef:p,itemCountRef:m,lastScrollTopRef:L,messageElementsRef:y,modeRef:u,pendingScrollFrameRef:x,pendingScrollToMessageRef:Y,prependRestoreRef:k,preserveScrollOnPrependRef:_,rootRef:G,scrollEdgeThresholdRef:v,scrollMarginRef:H,scrollPreviousItemPeekRef:N,spacerGapRef:ne,spacerHeightRef:A,spacerRef:B,stateFrameRef:D,stateStore:U,viewportRef:c,visibilityFrameRef:f,visibilityObserverRef:h,visibilityStore:P,visibleMessageIdsRef:V,handledScrollAnchorsRef:z}=i,q=g.useRef(t);q.current!==t&&(q.current=t,C.current=false);let K=g.useCallback(s=>{let a=G.current,T=c.current,O=[s.start&&\"start\",s.end&&\"end\"].filter(Boolean).join(\" \"),ue=d.current;for(let W of [a,T])W&&(O?W.setAttribute(\"data-scrollable\",O):W.removeAttribute(\"data-scrollable\"),W.toggleAttribute(\"data-autoscrolling\",ue));},[]),se=g.useCallback(s=>{let a=c.current?.scrollTop??0,T=a<L.current-J;L.current=a,l.current&&!s.end&&u.current!==\"settling-jump\"&&u.current!==\"anchored-to-message\"?u.current=\"following-bottom\":u.current===\"following-bottom\"&&s.end&&T&&!d.current&&(u.current=\"free-scrolling\");},[]),F=g.useCallback(()=>{let s=De({content:b.current,scrollEdgeThreshold:v.current,spacer:B.current,viewport:c.current});se(s);let a=u.current===\"following-bottom\"?{...s,end:false}:s;K(a),U.setSnapshot(a);},[se,U,K]),oe=g.useCallback(()=>{D.current===null&&(D.current=window.requestAnimationFrame(()=>{D.current=null,F();}));},[F]),w=g.useCallback(()=>{P.hasListeners()&&f.current===null&&(f.current=window.requestAnimationFrame(()=>{f.current=null,P.hasListeners()&&P.setSnapshot(Fe({content:b.current,scrollMargin:H.current,scrollPreviousItemPeek:N.current,spacer:B.current,viewport:c.current,visibleMessageIds:V.current}));}));},[P]),{flushPendingScrollToMessage:ce,reanchorToAnchoredMessage:me,scrollToElement:le,scrollToEnd:I,scrollToMessage:Me,scrollToStart:ae}=Je({refs:i,commitScrollState:F,scheduleStateCommit:oe,scheduleVisibilitySync:w}),de=g.useCallback(()=>{let s=k.current,a=c.current;if(!s||!a||!s.element.isConnected)return false;let O=te(s.element,a)-s.viewportTop;return Math.abs(O)<=J?false:(a.scrollTop+=O,s.viewportTop=te(s.element,a),oe(),w(),true)},[oe,w]),Z=g.useCallback(()=>{let s=b.current,a=c.current;if(!s||!a){k.current=null;return}let T=Ye({content:s,spacer:B.current,viewport:a});k.current=T?{element:T,viewportTop:te(T,a)}:null;},[]),be=g.useCallback(()=>{x.current===null&&(x.current=window.requestAnimationFrame(()=>{x.current=null,ce()&&Z();}));},[Z,ce]),ie=g.useCallback(()=>{if(!t||C.current||m.current===0)return false;let s=false;if(t===\"last-anchor\"){let a=b.current,T=c.current,O=a&&T?Ue(ee(a,B.current)):null;if(!a||!T||!O)s=I({behavior:\"auto\"});else {let ue=pe(O,T);s=Se({content:a,spacer:B.current,viewport:T})-ue<=T.clientHeight?I({behavior:\"auto\"}):le(O,{align:\"start\"},{keepPreviousPeek:true});}}else s=t===\"end\"?I({behavior:\"auto\"}):ae({behavior:\"auto\"});return s?(C.current=true,true):false},[t,le,I,ae]),Te=g.useCallback(()=>{let s=b.current;if(!s)return;let a=ee(s,B.current),T=m.current,O=p.current;m.current=a.length,p.current=a[0]??null,(()=>{if(ce())return;if(T===0){if(ie()||a.length>0&&l.current&&I({behavior:\"auto\"}))return;F(),w();return}let W=O?a.indexOf(O):-1;if(_.current&&W>0){de();return}if(a.length>T){let $=je(a,T);if($){if(l.current&&u.current===\"following-bottom\"&&Ne(a,T)){I({behavior:\"auto\"});return}le($,{align:\"start\"},{keepPreviousPeek:true}),z.current.add($);return}}if(a.length===T){let $=Ge(a,z.current);if($){le($,{align:\"start\"},{keepPreviousPeek:true}),z.current.add($);return}}u.current===\"following-bottom\"&&l.current?I({behavior:\"auto\"}):(F(),w());})(),Z();},[ie,Z,F,ce,de,w,le,I]),Ee=g.useCallback(()=>{if(u.current===\"following-bottom\"&&l.current){I({behavior:\"auto\"});return}let s=A.current;if(me()){l.current&&s>0&&A.current===0&&I({behavior:\"auto\"});return}oe(),w();},[me,oe,w,I]),ve=g.useCallback(()=>{let s=c.current;if(!(!s||!P.hasListeners())){if(typeof IntersectionObserver>\"u\"){w();return}h.current||(h.current=new IntersectionObserver(a=>{for(let T of a){let O=T.target.dataset.messageId;O&&(T.isIntersecting?V.current.add(O):V.current.delete(O));}w();},{root:s,rootMargin:`${-(H.current+N.current)}px 0px 0px 0px`,threshold:[0,.01,.5,1]})),y.current.forEach(a=>{h.current?.observe(a);}),w();}},[w,P]),he=g.useCallback(()=>{f.current!==null&&(window.cancelAnimationFrame(f.current),f.current=null),h.current?.disconnect(),h.current=null,V.current.clear(),P.setSnapshot(Q);},[P]),pt=g.useCallback((s,a,T)=>{if(a){y.current.set(s,a),h.current?.observe(a),w(),Y.current?.messageId===s&&be();return}T&&y.current.get(s)===T&&(y.current.delete(s),V.current.delete(s),h.current?.unobserve(T),w());},[be,w]),Le=g.useCallback(()=>{(u.current===\"following-bottom\"||u.current===\"anchored-to-message\"||u.current===\"settling-jump\")&&(S.current=null,u.current=\"free-scrolling\");},[]),Ce=g.useCallback(()=>K(U.getSnapshot()),[U,K]),Pe=rt(G,Ce),we=rt(c,Ce),Oe=g.useCallback(s=>{b.current=s;},[]),ye=g.useCallback(s=>{B.current=s,ne.current=$e(s?.parentElement??null);},[]),He=g.useCallback(()=>{F(),w(),Z();},[Z,F,w]),mt=g.useMemo(()=>({handleContentChange:Te,handleResize:Ee,observeVisibility:ve,preserveScrollOnPrependRef:_,scrollToEnd:I,scrollToMessage:Me,scrollToStart:ae,setContentElement:Oe,setRootElement:Pe,setSpacerElement:ye,setViewportElement:we,stateStore:U,syncAfterScroll:He,unobserveVisibility:he,userScrollIntent:Le,viewportRef:c,visibilityStore:P}),[Te,Ee,ve,I,Me,ae,Oe,Pe,ye,we,U,He,he,Le,P]);return g.useLayoutEffect(()=>{ie();},[ie]),g.useEffect(()=>()=>{D.current!==null&&(window.cancelAnimationFrame(D.current),D.current=null),f.current!==null&&(window.cancelAnimationFrame(f.current),f.current=null),E.current!==null&&(window.clearTimeout(E.current),E.current=null),x.current!==null&&(window.cancelAnimationFrame(x.current),x.current=null),h.current?.disconnect(),h.current=null;},[]),g.useLayoutEffect(()=>{if(e&&u.current===\"following-bottom\"&&m.current>0){I({behavior:\"auto\"});return}F();},[e,F,I]),{context:mt,registerMessage:pt}}function lt(e){let t=g.useRef(e);return t.current=e,t}var st=g.createContext(null),ct=g.createContext(null);function X(){let e=g.useContext(st);if(!e)throw new Error(\"useMessageScroller must be used within a MessageScroller.\");return e}function Et(){let e=g.useContext(ct);if(!e)throw new Error(\"MessageScrollerItem must be used within a MessageScroller.\");return e}function vt(){let{scrollToEnd:e,scrollToMessage:t,scrollToStart:r}=X();return g.useMemo(()=>({scrollToEnd:e,scrollToMessage:t,scrollToStart:r}),[e,t,r])}function ht(){let{stateStore:e}=X();return g.useSyncExternalStore(e.subscribe,e.getSnapshot,e.getSnapshot)}function Lt(){let{observeVisibility:e,unobserveVisibility:t,visibilityStore:r}=X(),n=g.useCallback(o=>r.subscribe(o,e,t),[e,t,r]);return g.useSyncExternalStore(n,r.getSnapshot,r.getSnapshot)}function at({autoScroll:e=false,children:t,defaultScrollPosition:r=\"end\",scrollEdgeThreshold:n,scrollPreviousItemPeek:o,scrollMargin:i}){let{context:S,registerMessage:l}=nt({autoScroll:e,defaultScrollPosition:r,scrollEdgeThreshold:n,scrollPreviousItemPeek:o,scrollMargin:i});return jsx(st.Provider,{value:S,children:jsx(ct.Provider,{value:l,children:t})})}function it({children:e,...t}){let{setRootElement:r}=X();return jsx(\"div\",{ref:r,...t,children:e})}function ut({\"aria-label\":e,children:t,onKeyDown:r,onScroll:n,onTouchMove:o,onWheel:i,preserveScrollOnPrepend:S=true,ref:l,role:d,tabIndex:E,...b}){let{handleResize:C,preserveScrollOnPrependRef:p,setViewportElement:m,syncAfterScroll:L,userScrollIntent:y,viewportRef:u}=X();p.current=S;let x=g.useCallback(v=>{m(v),c(l)?.(v);},[l,m]);function Y(v){L(),n?.(v);}function k(v){y(),i?.(v);}function _(v){y(),o?.(v);}function G(v){Be.has(v.key)&&y(),r?.(v);}return g.useEffect(()=>{let v=u.current;if(!v||typeof ResizeObserver>\"u\")return;let H=0,N=new ResizeObserver(()=>{window.cancelAnimationFrame(H),H=window.requestAnimationFrame(C);});return N.observe(v),()=>{window.cancelAnimationFrame(H),N.disconnect();}},[C,u]),jsx(\"div\",{ref:x,role:d??\"region\",\"aria-label\":e??\"Messages\",tabIndex:E??0,onKeyDown:G,onScroll:Y,onTouchMove:_,onWheel:k,...b,children:t})}function ft({\"aria-relevant\":e,children:t,ref:r,role:n,spacerClassName:o,...i}){let{handleContentChange:S,handleResize:l,setContentElement:d,setSpacerElement:E}=X(),b=g.useRef(null),C=g.useCallback(p=>{b.current=p,d(p),c(r)?.(p);},[r,d]);return g.useLayoutEffect(()=>{let p=b.current;if(!p||(S(),typeof MutationObserver>\"u\"))return;let m=new MutationObserver(()=>{S();});return m.observe(p,{childList:true}),()=>m.disconnect()},[S]),g.useEffect(()=>{let p=b.current;if(!p||typeof ResizeObserver>\"u\")return;let m=0,L=new ResizeObserver(()=>{window.cancelAnimationFrame(m),m=window.requestAnimationFrame(l);});return L.observe(p),()=>{window.cancelAnimationFrame(m),L.disconnect();}},[l]),jsxs(\"div\",{ref:C,role:n??\"log\",\"aria-relevant\":e??\"additions\",...i,children:[t,jsx(\"div\",{ref:E,\"aria-hidden\":\"true\",\"data-message-scroller-spacer\":\"\",hidden:true,className:o})]})}function gt({messageId:e,ref:t,scrollAnchor:r=false,...n}){let o=Et(),i=g.useRef(null),S=g.useCallback(l=>{let d=i.current;i.current=l,e&&o(e,l,d),c(t)?.(l);},[e,t,o]);return jsx(\"div\",{ref:S,\"data-message-id\":e,\"data-scroll-anchor\":r?\"true\":\"false\",...n})}function St({behavior:e=\"smooth\",children:t,direction:r=\"end\",onClick:n,render:o,tabIndex:i,type:S=\"button\",...l}){let{scrollToEnd:d,scrollToStart:E,stateStore:b$1}=X(),C=lt(n),p=g.useCallback(u=>b$1.subscribe(u),[b$1]),m=g.useCallback(()=>{let u=b$1.getSnapshot();return r===\"start\"?u.start:u.end},[r,b$1]),L=g.useSyncExternalStore(p,m,m),y=g.useCallback(u=>{L&&(C.current?.(u),u.defaultPrevented||(u.currentTarget.blur(),r===\"start\"?E({behavior:e}):d({behavior:e})));},[e,r,L,C,d,E]);return a({defaultTagName:\"button\",props:b({type:S,inert:!L,tabIndex:L?i:-1,children:t??jsxs(\"span\",{children:[\"Scroll to \",r]}),onClick:y},l),render:o,state:{active:L,direction:r},stateAttributesMapping:{active:u=>({\"data-active\":u?\"true\":\"false\"})}})}var $t={Provider:at,Root:it,Viewport:ut,Content:ft,Item:gt,Button:St};export{$t as MessageScroller,vt as useMessageScroller,ht as useMessageScrollerScrollable,Lt as useMessageScrollerVisibility};","/**\n * Copyright 2022 Joe Bell. All rights reserved.\n *\n * This file is licensed to you under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with the\n * License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */ import { clsx } from \"clsx\";\nconst falsyToString = (value)=>typeof value === \"boolean\" ? `${value}` : value === 0 ? \"0\" : value;\nexport const cx = clsx;\nexport const cva = (base, config)=>(props)=>{\n var _config_compoundVariants;\n if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n const { variants, defaultVariants } = config;\n const getVariantClassNames = Object.keys(variants).map((variant)=>{\n const variantProp = props === null || props === void 0 ? void 0 : props[variant];\n const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];\n if (variantProp === null) return null;\n const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);\n return variants[variant][variantKey];\n });\n const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param)=>{\n let [key, value] = param;\n if (value === undefined) {\n return acc;\n }\n acc[key] = value;\n return acc;\n }, {});\n const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param)=>{\n let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;\n return Object.entries(compoundVariantOptions).every((param)=>{\n let [key, value] = param;\n return Array.isArray(value) ? value.includes({\n ...defaultVariants,\n ...propsWithoutUndefined\n }[key]) : ({\n ...defaultVariants,\n ...propsWithoutUndefined\n })[key] === value;\n }) ? [\n ...acc,\n cvClass,\n cvClassName\n ] : acc;\n }, []);\n return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n };\n\n","import * as React from 'react';\nimport { useComposedRefs } from '@radix-ui/react-compose-refs';\n\ndeclare module 'react' {\n interface ReactElement {\n $$typeof?: symbol | string;\n }\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Slot\n * -----------------------------------------------------------------------------------------------*/\n\nexport type Usable<T> = PromiseLike<T> | React.Context<T>;\n\ntype SlotProps<Elem extends Element = HTMLElement, Props = React.HTMLAttributes<Elem>> = Props & {\n children?: React.ReactNode;\n};\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlot<\n Elem extends Element = HTMLElement,\n Props = React.HTMLAttributes<Elem>,\n>(ownerName: string) {\n const Slot = React.forwardRef<Elem, SlotProps<Elem, Props>>((props, forwardedRef) => {\n let { children, ...slotProps } = props;\n let slottableElement: React.ReactElement | null = null;\n let hasSlottable = false;\n const newChildren: React.ReactNode[] = [];\n\n if (isLazyComponent(children) && typeof use === 'function') {\n children = use(children._payload);\n }\n\n React.Children.forEach(children, (maybeSlottable) => {\n if (isSlottable(maybeSlottable)) {\n hasSlottable = true;\n const slottable = maybeSlottable;\n let child = 'child' in slottable.props ? slottable.props.child : slottable.props.children;\n\n if (isLazyComponent(child) && typeof use === 'function') {\n child = use(child._payload);\n }\n\n slottableElement = getSlottableElementFromSlottable(slottable, child);\n newChildren.push((slottableElement?.props as any)?.children);\n } else {\n newChildren.push(maybeSlottable);\n }\n });\n\n if (slottableElement) {\n slottableElement = React.cloneElement(slottableElement, undefined, newChildren);\n } else if (\n // A `Slottable` was found but it didn't resolve to a single element (e.g.\n // it wrapped multiple elements, text, or a render-prop `child` that\n // wasn't an element). Don't fall back to treating the `Slottable` wrapper\n // itself as the slot target — throw a descriptive error below instead.\n !hasSlottable &&\n React.Children.count(children) === 1 &&\n React.isValidElement(children)\n ) {\n slottableElement = children;\n }\n\n const slottableElementRef = slottableElement ? getElementRef(slottableElement) : undefined;\n const composedRef = useComposedRefs(forwardedRef, slottableElementRef);\n\n if (!slottableElement) {\n // Empty/falsy children (`null`, `undefined`, `false`, no children, etc.) are valid and\n // render nothing. Anything else is content we couldn't slot onto a single element, which\n // is a usage error, so we fail loudly with a clear message.\n if (children || children === 0) {\n throw new Error(\n hasSlottable ? createSlottableError(ownerName) : createSlotError(ownerName),\n );\n }\n return children;\n }\n\n const mergedProps = mergeProps(slotProps, slottableElement.props ?? {});\n\n // do not pass ref to React.Fragment for React 19 compatibility\n if (slottableElement.type !== React.Fragment) {\n mergedProps.ref = forwardedRef ? composedRef : slottableElementRef;\n }\n\n return React.cloneElement(slottableElement, mergedProps);\n });\n\n Slot.displayName = `${ownerName}.Slot`;\n return Slot;\n}\n\nconst Slot = createSlot('Slot');\n\n/* -------------------------------------------------------------------------------------------------\n * Slottable\n * -----------------------------------------------------------------------------------------------*/\n\nconst SLOTTABLE_IDENTIFIER = Symbol.for('radix.slottable');\n\ntype SlottableChildrenProps = { children: React.ReactNode };\ntype SlottableRenderFnProps = {\n child: React.ReactNode;\n children: (slottable: React.ReactNode) => React.ReactNode;\n};\n\ntype SlottableProps = SlottableRenderFnProps | SlottableChildrenProps;\ninterface SlottableComponent extends React.FC<SlottableProps> {\n __radixId: symbol;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlottable(ownerName: string) {\n const Slottable: SlottableComponent = (props) =>\n 'child' in props ? props.children(props.child) : props.children;\n\n Slottable.displayName = `${ownerName}.Slottable`;\n Slottable.__radixId = SLOTTABLE_IDENTIFIER;\n return Slottable;\n}\n\nconst Slottable = createSlottable('Slottable');\n\n/* -------------------------------------------------------------------------------------------------\n * getSlottableElementFromSlottable\n * -----------------------------------------------------------------------------------------------*/\n\nconst getSlottableElementFromSlottable = (slottable: SlottableElement, child: React.ReactNode) => {\n if ('child' in slottable.props) {\n const child = slottable.props.child;\n if (!React.isValidElement<React.PropsWithChildren>(child)) return null;\n return React.cloneElement(child, undefined, slottable.props.children(child.props.children));\n }\n\n return React.isValidElement(child) ? child : null;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * mergeProps\n * -----------------------------------------------------------------------------------------------*/\n\ntype AnyProps = Record<string, any>;\n\nfunction mergeProps(slotProps: AnyProps, childProps: AnyProps) {\n // all child props should override\n const overrideProps = { ...childProps };\n\n for (const propName in childProps) {\n const slotPropValue = slotProps[propName];\n const childPropValue = childProps[propName];\n\n const isHandler = /^on[A-Z]/.test(propName);\n if (isHandler) {\n // if the handler exists on both, we compose them\n if (slotPropValue && childPropValue) {\n overrideProps[propName] = (...args: unknown[]) => {\n const result = childPropValue(...args);\n slotPropValue(...args);\n return result;\n };\n }\n // but if it exists only on the slot, we use only this one\n else if (slotPropValue) {\n overrideProps[propName] = slotPropValue;\n }\n }\n // if it's `style`, we merge them\n else if (propName === 'style') {\n overrideProps[propName] = { ...slotPropValue, ...childPropValue };\n } else if (propName === 'className') {\n overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(' ');\n }\n }\n\n return { ...slotProps, ...overrideProps };\n}\n\n/* -------------------------------------------------------------------------------------------------\n * getElementRef\n * -----------------------------------------------------------------------------------------------*/\n\n// Before React 19 accessing `element.props.ref` will throw a warning and suggest using `element.ref`\n// After React 19 accessing `element.ref` does the opposite.\n// https://github.com/facebook/react/pull/28348\n//\n// Access the ref using the method that doesn't yield a warning.\nfunction getElementRef(element: React.ReactElement) {\n // React <=18 in DEV\n let getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get;\n let mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element as any).ref;\n }\n\n // React 19 in DEV\n getter = Object.getOwnPropertyDescriptor(element, 'ref')?.get;\n mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element.props as { ref?: React.Ref<unknown> }).ref;\n }\n\n // Not DEV\n return (element.props as { ref?: React.Ref<unknown> }).ref || (element as any).ref;\n}\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype SlottableElement = React.ReactElement<SlottableProps, SlottableComponent>;\n\nfunction isSlottable(\n child: React.ReactNode,\n): child is React.ReactElement<SlottableProps, typeof Slottable> {\n return (\n React.isValidElement(child) &&\n typeof child.type === 'function' &&\n '__radixId' in child.type &&\n child.type.__radixId === SLOTTABLE_IDENTIFIER\n );\n}\n\nconst REACT_LAZY_TYPE = Symbol.for('react.lazy');\n\ninterface LazyReactElement extends React.ReactElement {\n $$typeof: typeof REACT_LAZY_TYPE;\n _payload: PromiseLike<Exclude<React.ReactNode, PromiseLike<any>>>;\n}\n\nfunction isLazyComponent(element: React.ReactNode): element is LazyReactElement {\n return (\n element != null &&\n typeof element === 'object' &&\n '$$typeof' in element &&\n element.$$typeof === REACT_LAZY_TYPE &&\n '_payload' in element &&\n isPromiseLike(element._payload)\n );\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return typeof value === 'object' && value !== null && 'then' in value;\n}\n\nconst createSlotError = (ownerName: string) => {\n return `${ownerName} failed to slot onto its children. Expected a single React element child or \\`Slottable\\`.`;\n};\n\nconst createSlottableError = (ownerName: string) => {\n return `${ownerName} failed to slot onto its \\`Slottable\\`. Expected \\`Slottable\\` to receive a single React element child.`;\n};\n\nconst use: typeof React.use | undefined = (React as any)[' use '.trim().toString()];\n\nexport {\n Slot,\n Slottable,\n //\n Slot as Root,\n};\nexport type { SlotProps };\n","import * as React from 'react';\n\ntype PossibleRef<T> = React.Ref<T> | undefined;\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === 'function') {\n return ref(value);\n } else if (ref !== null && ref !== undefined) {\n ref.current = value;\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false;\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node);\n if (!hasCleanup && typeof cleanup == 'function') {\n hasCleanup = true;\n }\n return cleanup;\n });\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i];\n if (typeof cleanup == 'function') {\n cleanup();\n } else {\n setRef(refs[i], null);\n }\n }\n };\n }\n };\n}\n\n/**\n * A custom hook that composes multiple refs\n * Accepts callback refs and RefObject(s)\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return React.useCallback(composeRefs(...refs), refs);\n}\n\nexport { composeRefs, useComposedRefs };\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-full border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n xs: \"h-7 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 text-[0.8rem] has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-7 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport { useEffect, useState, type RefObject } from \"react\";\n\n/**\n * How long the box has to hold still before it counts as done. Long enough to\n * outlast the gap between two frames of an animation, short enough that\n * whatever was waiting on it is not left waiting.\n */\nconst SETTLE_MS = 120;\n\n/**\n * Whether an element is in the middle of changing size.\n *\n * For the things that correct themselves against a box, so they can hold off\n * while it moves. Correcting on every frame of a resize means aiming at a\n * target that moves every frame, and the numbers those corrections are made of\n * are whole pixels while the box between them is not, so each one lands a\n * fraction out from the last and the result shimmers rather than travels.\n *\n * False until something actually changes, and false again a moment after it\n * stops. The observer's opening report is the size the box already had rather\n * than a change to it, so it is not counted.\n */\nexport function useIsResizing(target: RefObject<HTMLElement | null>): boolean {\n const [isResizing, setIsResizing] = useState(false);\n\n useEffect(() => {\n const node = target.current;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n\n let settle = 0;\n let isOpeningReport = true;\n\n const observer = new ResizeObserver(() => {\n if (isOpeningReport) {\n isOpeningReport = false;\n return;\n }\n\n setIsResizing(true);\n window.clearTimeout(settle);\n settle = window.setTimeout(() => setIsResizing(false), SETTLE_MS);\n });\n\n observer.observe(node);\n return () => {\n window.clearTimeout(settle);\n observer.disconnect();\n };\n }, [target]);\n\n return isResizing;\n}\n","/**\n * Runs of consecutive messages from the same voice, so a burst of three reads\n * as one turn rather than as three separate arrivals. A run says who is\n * speaking once, at the top, and carries the time and the face at the foot;\n * everything in between is just a bubble.\n *\n * What joins what is the caller's rule, since the inbox and the widget hold\n * different shapes. All this does is walk the list and mark the edges.\n */\n\n/** How long a run stays open. A message later than this starts a new one. */\nconst RUN_MS = 5 * 60_000;\n\n/** Where a message sits in its run. Both true when it is a run of one. */\nexport type MessageGroup = {\n /** Carries the name. */\n isFirst: boolean;\n /** Carries the face and the time. */\n isLast: boolean;\n};\n\n/** A message standing on its own, for anywhere nothing is grouped. */\nexport const LONE_MESSAGE: MessageGroup = { isFirst: true, isLast: true };\n\n/**\n * Marks each message with where it sits in its run.\n *\n * `joinsPrevious` is only ever asked about neighbours, so it can compare\n * senders, timestamps, day labels, or whatever else the shape at hand knows.\n */\nexport function groupMessages<T>(\n messages: T[],\n joinsPrevious: (message: T, previous: T) => boolean,\n): MessageGroup[] {\n /** Whether the message at `index` carries on the one above it. */\n const continues = (index: number) => {\n const message = messages[index];\n const previous = messages[index - 1];\n if (message === undefined || previous === undefined) return false;\n return joinsPrevious(message, previous);\n };\n\n return messages.map((_, index) => ({\n isFirst: !continues(index),\n isLast: !continues(index + 1),\n }));\n}\n\n/**\n * Whether two messages are close enough together to belong to one run. A\n * missing timestamp means canned content with no clock behind it, which groups\n * on who is speaking alone.\n */\nexport function withinRun(previous?: number, next?: number): boolean {\n if (previous === undefined || next === undefined) return true;\n return next - previous <= RUN_MS;\n}\n","\"use client\";\n\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport { prefersReducedMotion } from \"./motion\";\n\nconst SHIFT_MS = 420;\n/** Matches --ease-spring. Kept in step by hand, since JS cannot read a theme token. */\nconst SHIFT_EASING = \"cubic-bezier(0.34, 1.45, 0.64, 1)\";\n\n/** How far the first message sits from the top of the stack, or null if there is none. */\nfunction topOfStack(element: HTMLElement | null): number | null {\n const first = element?.firstElementChild as HTMLElement | null;\n\n return first ? first.offsetTop : null;\n}\n\n/**\n * Slides a bottom anchored stack up as it grows, rather than letting it jump.\n *\n * A short thread sits on the composer, so a new message does not push the ones\n * above it down: it lifts them. Left alone that happens between two frames and\n * the whole conversation teleports.\n *\n * So it is measured instead. The first message's offset from the top of the\n * stack says how far everything moved, the stack is put straight back where it\n * was, and it travels the distance properly. Nothing moves once the thread is\n * long enough to scroll, because then the first message stops moving, the\n * distance is zero, and the scroller has it.\n *\n * The starting measurement is taken as the element attaches rather than in the\n * effect below, because the effect only runs when the message count changes. A\n * thread that arrives after a loading state would otherwise have nothing to\n * compare against until its second message, and the first one would jump.\n */\nexport function useStackShift(dependency: number) {\n const stack = useRef<HTMLDivElement | null>(null);\n const previousTop = useRef<number | null>(null);\n const watcher = useRef<ResizeObserver | null>(null);\n\n // Attaching also starts watching the stack for a change of size, and letting\n // go stops. Both here rather than in an effect, because the stack arrives\n // whenever the first message does: a thread that starts empty has nothing to\n // attach to on mount, and an effect that ran then would have found nothing\n // and never looked again.\n const ref = useCallback((node: HTMLDivElement | null) => {\n stack.current = node;\n previousTop.current = topOfStack(node);\n\n watcher.current?.disconnect();\n watcher.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n\n // The stack moves when the panel changes size too, and that is not a shift\n // worth animating: nothing arrived, the box around it grew. It does have to\n // be written down though. The effect below only runs on a new message, so\n // without this the measurement from before a resize is the one the next\n // message is compared against, and it travels the difference between two\n // panel heights on its way in.\n watcher.current = new ResizeObserver(() => {\n previousTop.current = topOfStack(node);\n });\n watcher.current.observe(node);\n }, []);\n\n useLayoutEffect(() => {\n const element = stack.current;\n if (!element) return;\n\n const top = topOfStack(element);\n const from = previousTop.current;\n previousTop.current = top;\n\n if (from === null || top === null) return;\n\n const distance = from - top;\n if (distance <= 0) return;\n if (prefersReducedMotion()) return;\n\n element.animate(\n [\n { transform: `translateY(${distance}px)` },\n { transform: \"translateY(0)\" },\n ],\n { duration: SHIFT_MS, easing: SHIFT_EASING },\n );\n }, [dependency]);\n\n return ref;\n}\n","/**\n * CSS carries `motion-reduce:` for anything animated in a stylesheet. The two\n * animations driven from JavaScript cannot read that, so they ask here.\n *\n * Guarded for the server, where there is no window to ask.\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\") return false;\n\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n","\"use client\";\n\nimport {\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type KeyboardEvent,\n} from \"react\";\nimport {\n AttachmentDraftChip,\n useAttachmentDrafts,\n useAttachmentTarget,\n} from \"@/components/attachments\";\nimport { ArrowUp, Check, EnvelopeSimple, Plus } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { TEXT_FIELD_SHELL } from \"@/components/ui/text-field\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { useTypingSignal } from \"@/hooks/use-typing-signal\";\nimport { cn } from \"@/lib/utils\";\nimport { PoweredByMedian } from \"./widget-badge\";\n\n/**\n * Loose on purpose: it decides whether the arrow lights up, not whether the\n * address is real. Only a mail server can answer that, and a visitor locked\n * out by a suspicious regex has nobody to appeal to.\n */\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/**\n * How the pill changes its mind.\n *\n * `translate` rather than `transform`, because that is the property Tailwind's\n * `translate-y-*` actually sets. Named as `transform` it transitions nothing:\n * the opacity eases and the travel lands in one frame, which is the jump this\n * was written to avoid.\n */\nconst SWAP =\n \"transition-[opacity,translate] duration-300 ease-out motion-reduce:transition-none\";\n\n/**\n * The notch coming up out of the composer, with the spring's small overshoot\n * at the top of the travel: it is a thing being pushed up from underneath, and\n * a thing pushed up passes where it lands.\n */\nconst RISE =\n \"transition-transform duration-450 ease-spring motion-reduce:transition-none\";\n\n/**\n * And going back into it. Quicker, and accelerating rather than easing off,\n * which is the difference between something leaving and something being taken\n * back: it is not travelling to a new place, it is going home.\n */\nconst SINK =\n \"transition-transform duration-250 ease-in motion-reduce:transition-none\";\n\n/**\n * The two phrases passing each other, both moving the same way, like a word on\n * a wheel. No fade in it: two things at half opacity on top of each other is\n * what makes a swap look like a smudge.\n *\n * A pure deceleration rather than the spring above, because this one runs\n * inside a box exactly one line tall. Anything that overshoots its landing has\n * its ascenders shaved off on the way past.\n */\nconst ROLL =\n \"transition-transform duration-350 ease-out-quint motion-reduce:transition-none\";\n\n/**\n * How long the tab holds its answer before tucking away. Long enough to read\n * two words, and short enough that nobody is waiting on it: the box to write\n * in is already underneath by then.\n */\nconst SAVED_MS = 1200;\n\n/**\n * One pill at the foot of the panel: add on the left, write in the middle,\n * send on the right. The shape is round rather than square so the composer\n * reads as a control rather than as another message, and it holds that shape\n * as the box grows because the corners are already as round as they get.\n *\n * Enter sends, shift and enter starts a new line. Files arrive from the plus\n * button, from a drop anywhere along the foot of the panel, or from a paste,\n * which is how anybody who has just taken a screenshot expects to send it.\n * They stack above the pill as chips, each with a thumbnail and a way out, and\n * one that is too big says so and holds the send button until it goes. Nothing\n * is uploaded yet.\n *\n * The draft clears when the send lands rather than when the button goes down,\n * so a send that fails costs a retry, not a retype.\n *\n * Before a first message, the same pill can ask who they are instead: a tab\n * rises from behind its top edge and says what is being asked, while the\n * writing box makes way for an email field underneath. Nothing remounts, so\n * both movements are transitions rather than things appearing.\n *\n * An answer is taken here rather than waited on. The tab says it has it, the\n * box to write in comes back under it, and the caret is already there before\n * the tab has finished tucking away, so a phone keeps the keyboard it has\n * instead of losing it and asking for it again.\n */\nexport function WidgetComposer({\n onSend,\n onTypingChange,\n askForEmail = false,\n onSubmitEmail,\n placeholder = \"Type your message...\",\n showBadge = true,\n isSending = false,\n}: {\n /** Awaited if it returns a promise. A rejection keeps the draft in place. */\n onSend?: (body: string, files: File[]) => unknown;\n /** Best effort, throttled here. */\n onTypingChange?: (isTyping: boolean) => unknown;\n /**\n * Ask for an email before a first message. The pill asks instead of the\n * composer: no attachments, no typing dots, nothing to send but the\n * address.\n */\n askForEmail?: boolean;\n /** Called with the address once it looks like one. */\n onSubmitEmail?: (email: string) => void;\n placeholder?: string;\n /** The \"Powered by Median\" line. Hosts on a paid plan can turn it off. */\n showBadge?: boolean;\n isSending?: boolean;\n}) {\n const [draft, setDraft] = useState(\"\");\n const [email, setEmail] = useState(\"\");\n // Where the notch has got to. `none` is the question, `saved` is the word\n // that answers it, and `settled` is that same word on its way down: the\n // notch goes back to asking only if the question itself comes back.\n const [answer, setAnswer] = useState<\"none\" | \"saved\" | \"settled\">(\"none\");\n const fileInputRef = useRef<HTMLInputElement>(null);\n const draftRef = useRef<HTMLTextAreaElement>(null);\n const attachments = useAttachmentDrafts();\n const target = useAttachmentTarget({ onFiles: attachments.add });\n const typing = useTypingSignal(onTypingChange);\n\n const hasContent = draft.trim().length > 0 || attachments.drafts.length > 0;\n const canSend = hasContent && !attachments.hasBlocker && !isSending;\n\n // True once what they typed could be an address. It decides the arrow, not\n // whether the address is real.\n const isValid = EMAIL_PATTERN.test(email.trim());\n\n // A question that has come back outranks an answer already given, which is\n // `medianSupport.reset()` and nothing else: the stored address went, so the\n // notch has something to ask again rather than something to hold. Worked out\n // here rather than written back into the state, since the two facts are the\n // prop and the beat, and this is only what they add up to.\n const stage = askForEmail && answer === \"settled\" ? \"none\" : answer;\n\n // What the notch says, and whether it is up at all. It holds the word it\n // answered with the whole way down: a notch that changed its mind back to\n // the question as it left would be asking on its way out the door.\n const isAsking = askForEmail && stage === \"none\";\n const isSaved = stage !== \"none\";\n const showTab = isAsking || stage === \"saved\";\n\n function submitEmail() {\n if (!isValid || !onSubmitEmail) return;\n setAnswer(\"saved\");\n onSubmitEmail(email.trim());\n }\n\n // The beat itself. Nothing waits on it: the composer is already back\n // underneath, so this only decides how long the word stays up before the\n // notch takes it down.\n useEffect(() => {\n if (answer !== \"saved\") return;\n const timer = setTimeout(() => setAnswer(\"settled\"), SAVED_MS);\n return () => clearTimeout(timer);\n }, [answer]);\n\n // Straight on to the message, since that is what the address was in the way\n // of. On a phone it also keeps the keyboard where it is: sending it away and\n // asking for it back is the whole screen bouncing twice for nothing.\n // `preventScroll`, because the browser's idea of bringing a field into view\n // is to scroll a page that is holding a sheet still.\n useEffect(() => {\n if (answer !== \"saved\" || askForEmail) return;\n draftRef.current?.focus({ preventScroll: true });\n }, [answer, askForEmail]);\n\n async function send() {\n if (!canSend) return;\n // Quiet locally only: the message itself is the stop, server side.\n typing.settle();\n\n const body = draft.trim();\n try {\n await onSend?.(body, attachments.files);\n } catch {\n // The notice above the composer says why it failed. The draft stays\n // where it was written.\n return;\n }\n\n // Only what was sent is cleared: anything typed while the message was in\n // flight is the next draft, not part of the one that just went.\n setDraft((now) => (now.trim() === body ? \"\" : now));\n attachments.clear();\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {\n if (event.key !== \"Enter\") return;\n // Shift for a new line, and never while an IME is open, where Enter is\n // accepting a candidate rather than finishing the message.\n if (event.shiftKey || event.nativeEvent.isComposing) return;\n\n event.preventDefault();\n void send();\n }\n\n function handlePick(event: ChangeEvent<HTMLInputElement>) {\n if (event.target.files?.length) attachments.add(event.target.files);\n // Cleared so picking the same file twice in a row still fires a change.\n event.target.value = \"\";\n }\n\n return (\n // The whole foot of the panel takes a drop, not just the pill: the pill is\n // a thin thing to aim a file at, and the chips that appear sit up here\n // anyway. Paste rides on the same element, so it is caught wherever the\n // caret happens to be inside the composer. None of that while the email\n // is asked for: there is no message yet to attach anything to.\n <div\n className=\"flex shrink-0 flex-col gap-1.5 px-3 pt-1 pb-3\"\n {...(isAsking ? {} : target.targetProps)}\n >\n {!isAsking && attachments.drafts.length > 0 && (\n <ul className=\"flex flex-wrap gap-1.5 px-1\">\n {attachments.drafts.map((item) => (\n <li key={item.id} className=\"min-w-0\">\n <AttachmentDraftChip\n draft={item}\n onRemove={() => attachments.remove(item.id)}\n />\n </li>\n ))}\n </ul>\n )}\n\n <div className=\"relative\">\n {/* The slot the notch lives in: the full width of the pill, ending two\n pixels inside its top edge, and clipped.\n\n That clip is the whole trick. The notch does not fade and does not\n need to: it slides down the height of itself and the slot cuts it\n off exactly where the pill begins, so it goes into the composer\n rather than off it. Coming back it comes up out of the same seam.\n The two pixels are what guarantee no hairline of daylight between\n the two shapes, and they are behind the pill, which paints over\n them. */}\n <div\n aria-hidden={!showTab}\n inert={!showTab}\n // The headroom is for the spring: the notch passes where it lands on\n // the way up, and a clip tight to its resting height would flatten\n // the top edge for those few frames.\n className=\"pointer-events-none absolute inset-x-0 bottom-full z-0 -mb-0.5 flex items-end justify-center overflow-hidden pt-2\"\n >\n {/* Square at the bottom and no bottom hairline: that edge is the\n seam with the pill, not an edge of its own. */}\n <div\n className={cn(\n \"grid max-w-[calc(100%-2rem)] select-none\",\n \"rounded-t-2xl border border-b-0 bg-muted px-3 pt-1.5 pb-2 text-sm text-muted-foreground\",\n showTab ? RISE : SINK,\n !showTab && \"translate-y-full\",\n )}\n >\n {/* One line tall and clipped, so the phrases roll through it.\n\n Both share the cell, so the notch is as wide as the longer of\n the two and holds that width while they change: the words move\n inside a shape that does not. Each is centred, so the short one\n sits in the middle of the notch rather than off to its left. */}\n <span className=\"grid overflow-hidden\">\n <span\n aria-hidden={isSaved}\n className={cn(\n \"col-start-1 row-start-1 flex items-center gap-2 justify-self-center\",\n ROLL,\n isSaved && \"-translate-y-full\",\n )}\n >\n <EnvelopeSimple aria-hidden className=\"size-4 shrink-0\" />\n <span className=\"truncate\">Enter your email</span>\n </span>\n\n <span\n aria-hidden={!isSaved}\n className={cn(\n \"col-start-1 row-start-1 flex items-center gap-2 justify-self-center\",\n ROLL,\n !isSaved && \"translate-y-full\",\n )}\n >\n <Check aria-hidden className=\"size-4 shrink-0\" />\n <span className=\"truncate\">Saved</span>\n </span>\n </span>\n </div>\n </div>\n\n {/* The same surface as the panel behind it, so the composer is a shape\n rather than a slab. Painted rather than left transparent, since it\n is what hides the foot of the tab. A grid with both composers in\n one cell: they sit exactly on top of each other, same height, so\n the swap moves nothing. Whichever one is waiting wears `inert`,\n which takes it out of the tab order and the accessibility tree\n along with the pointer events. */}\n <div\n className={cn(\n TEXT_FIELD_SHELL,\n \"relative z-10 grid items-center rounded-3xl bg-card p-1.5 transition-colors dark:bg-card\",\n // The pill lights up rather than the whole foot of the panel, so a\n // file being dragged in points at the thing it is about to join.\n !isAsking &&\n target.isDropTarget &&\n \"border-ring bg-muted/60 ring-1 ring-ring dark:bg-muted/60\",\n )}\n >\n {/* The message half. Both halves travel down together, the same way\n the notch above them goes, so an answer settles the whole thing\n rather than sending three pieces of it in three directions. */}\n <div\n aria-hidden={isAsking}\n inert={isAsking}\n className={cn(\n \"col-start-1 row-start-1 flex items-end gap-1.5\",\n SWAP,\n isAsking && \"-translate-y-1 opacity-0 pointer-events-none\",\n )}\n >\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n tabIndex={-1}\n onChange={handlePick}\n className=\"sr-only\"\n />\n <WidgetButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Add an attachment\"\n className=\"rounded-full text-muted-foreground hover:rotate-90 motion-reduce:hover:rotate-0\"\n >\n <Plus />\n </WidgetButton>\n\n <Textarea\n ref={draftRef}\n rows={1}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n typing.ping();\n }}\n onKeyDown={handleKeyDown}\n // The same swap the inbox does, so both ends of a conversation\n // confirm a drop the same way.\n placeholder={\n target.isDropTarget ? \"Drop to attach\" : placeholder\n }\n aria-label=\"Message\"\n // 16px on phones, and in pixels: any focused field smaller than\n // that makes iOS zoom the host's whole page in, and a host who has\n // resized their root rem would smuggle the zoom back past `text-base`.\n className=\"max-h-32 min-h-8 flex-1 px-1 py-1.5 max-sm:text-[16px]\"\n />\n\n {/* Pops in as the first character lands, rather than sitting there\n greyed out waiting to be earned. */}\n <WidgetButton\n type=\"button\"\n size=\"icon\"\n disabled={!canSend}\n onClick={() => void send()}\n aria-label=\"Send message\"\n className={cn(\n \"rounded-full\",\n canSend\n ? \"scale-100 opacity-100\"\n : \"scale-90 opacity-40 motion-reduce:scale-100\",\n )}\n >\n <ArrowUp />\n </WidgetButton>\n </div>\n\n {/* The answer half. */}\n <div\n aria-hidden={!isAsking}\n inert={!isAsking}\n className={cn(\n \"col-start-1 row-start-1 flex items-center gap-1.5\",\n SWAP,\n !isAsking && \"pointer-events-none translate-y-1 opacity-0\",\n )}\n >\n <input\n type=\"email\"\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n onKeyDown={(event) => {\n if (event.key !== \"Enter\" || event.nativeEvent.isComposing)\n return;\n event.preventDefault();\n submitEmail();\n }}\n placeholder=\"you@example.com\"\n aria-label=\"Email address\"\n autoComplete=\"email\"\n spellCheck={false}\n // The same rule as the message field, for the same reason.\n className=\"h-8 min-w-0 flex-1 px-1 outline-none placeholder:text-muted-foreground max-sm:text-[16px]\"\n />\n\n <WidgetButton\n type=\"button\"\n size=\"icon\"\n disabled={!isValid}\n onClick={() => submitEmail()}\n aria-label=\"Continue with this email\"\n className={cn(\n \"rounded-full\",\n isValid\n ? \"scale-100 opacity-100\"\n : \"scale-90 opacity-40 motion-reduce:scale-100\",\n )}\n >\n <ArrowUp />\n </WidgetButton>\n </div>\n </div>\n </div>\n\n {showBadge && <PoweredByMedian />}\n </div>\n );\n}\n","import { forwardRef, type ImgHTMLAttributes } from \"react\";\n\n/**\n * Stands in for `next/image` when the widget is bundled for npm, via the\n * `paths` entry in this package's tsconfig. The app renders avatars and\n * marks through the framework's image pipeline; the package has no framework,\n * and everything in the widget's closure is an avatar, a mark, or an object\n * URL that never left the browser, all of which a plain img carries the same.\n *\n * Next-only props are swallowed here so they do not land on a DOM element\n * that has never heard of them.\n */\ntype NextOnlyProps = {\n unoptimized?: boolean;\n priority?: boolean;\n quality?: number | string;\n placeholder?: string;\n blurDataURL?: string;\n fill?: boolean;\n loader?: unknown;\n};\n\nconst Image = forwardRef<\n HTMLImageElement,\n ImgHTMLAttributes<HTMLImageElement> & NextOnlyProps\n>(function Image(\n {\n unoptimized: _unoptimized,\n priority: _priority,\n quality: _quality,\n placeholder: _placeholder,\n blurDataURL: _blurDataURL,\n fill: _fill,\n loader: _loader,\n ...props\n },\n ref,\n) {\n return <img ref={ref} {...props} />;\n});\n\nexport default Image;\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { File, ImageSquare, Play, WarningCircle, X } from \"@/components/icons\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport type { AttachmentDraft } from \"./use-attachment-drafts\";\n\nconst KIND_ICONS = {\n image: ImageSquare,\n video: Play,\n file: File,\n};\n\n/**\n * One staged file, with a thumbnail where there is one and a way out.\n *\n * `max-w-full` so the chip gives up its preferred width inside something\n * narrow, like the support widget, rather than pushing out of the box.\n */\nexport function AttachmentDraftChip({\n draft,\n onRemove,\n className,\n}: {\n draft: AttachmentDraft;\n onRemove: () => void;\n className?: string;\n}) {\n const hasError = draft.error !== null;\n const Glyph = hasError ? WarningCircle : KIND_ICONS[draft.kind];\n\n return (\n <div\n className={cn(\n \"flex w-48 max-w-full items-center gap-2 rounded-lg border bg-card/60 p-1.5\",\n \"animate-in fade-in-0 zoom-in-95 duration-200 ease-out motion-reduce:animate-none\",\n hasError && \"border-destructive/40\",\n className,\n )}\n >\n {draft.previewUrl ? (\n // Object URLs cannot be optimised, and there is nothing to optimise:\n // the file has not left the browser.\n <Image\n src={draft.previewUrl}\n alt=\"\"\n width={64}\n height={64}\n unoptimized\n className=\"size-8 shrink-0 rounded-md object-cover\"\n />\n ) : (\n <span className=\"grid size-8 shrink-0 place-items-center rounded-md bg-muted\">\n <Glyph\n className={cn(\n \"size-4\",\n hasError ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n />\n </span>\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <p className=\"truncate text-xs font-medium\">{draft.name}</p>\n <p\n className={cn(\n \"truncate text-xs\",\n hasError ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {draft.error ?? draft.size}\n </p>\n </div>\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n onClick={onRemove}\n aria-label={`Remove ${draft.name}`}\n className=\"shrink-0 rounded-full text-muted-foreground\"\n >\n <X />\n </Button>\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { AttachmentKind } from \"./types\";\n\nconst MAX_BYTES = 25 * 1024 * 1024;\n\nexport type AttachmentDraft = {\n id: string;\n /** The file itself, kept so a caller can hand it on once it is sent. */\n file: File;\n name: string;\n size: string;\n kind: AttachmentKind;\n /** An object URL for pictures, so the chip can show what was picked. */\n previewUrl: string | null;\n /** Set when the file cannot be sent. Shown on the chip in place of the size. */\n error: string | null;\n};\n\nlet nextDraftId = 0;\n\n/**\n * Bytes, written the way a person would say them. Exported because whoever\n * receives a sent file has to label it the same way the chip that staged it\n * did, or the same file changes size on its way into the thread.\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n\n const units = [\"KB\", \"MB\", \"GB\"];\n let value = bytes / 1024;\n let unit = 0;\n\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit += 1;\n }\n\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${units[unit]}`;\n}\n\n/** What a file is, from its MIME type. Anything unrecognised is just a file. */\nexport function attachmentKindOf(type: string): AttachmentKind {\n if (type.startsWith(\"image/\")) return \"image\";\n if (type.startsWith(\"video/\")) return \"video\";\n return \"file\";\n}\n\nfunction release(draft: AttachmentDraft) {\n if (draft.previewUrl) URL.revokeObjectURL(draft.previewUrl);\n}\n\n/**\n * Files staged on a composer, from either the picker or a drop. Shared by the\n * agent's composer in the inbox and the visitor's in the support widget, so\n * the two agree on what is too big and what a size looks like written down.\n *\n * Nothing is uploaded: a draft is checked, previewed and then thrown away when\n * the message is sent. A file that fails the check stays in the list wearing\n * its reason, so it gets read rather than silently dropped.\n *\n * `files` hands back the originals in the same order, which is what a caller\n * passes on once there is somewhere to send them.\n */\nexport function useAttachmentDrafts() {\n const [drafts, setDrafts] = useState<AttachmentDraft[]>([]);\n\n // Object URLs outlive the elements that used them, so any still open when\n // the composer goes away get revoked on the way out.\n const draftsRef = useRef(drafts);\n useEffect(() => {\n draftsRef.current = drafts;\n }, [drafts]);\n useEffect(() => () => draftsRef.current.forEach(release), []);\n\n function add(files: FileList | File[]) {\n const picked = Array.from(files).map((file): AttachmentDraft => {\n const isTooBig = file.size > MAX_BYTES;\n const kind = attachmentKindOf(file.type);\n\n return {\n id: `draft-${(nextDraftId += 1)}`,\n file,\n name: file.name,\n size: formatFileSize(file.size),\n kind,\n previewUrl:\n kind === \"image\" && !isTooBig ? URL.createObjectURL(file) : null,\n error: isTooBig\n ? `Larger than the ${formatFileSize(MAX_BYTES)} limit`\n : null,\n };\n });\n\n setDrafts([...drafts, ...picked]);\n }\n\n function remove(id: string) {\n const going = drafts.find((draft) => draft.id === id);\n if (going) release(going);\n setDrafts(drafts.filter((draft) => draft.id !== id));\n }\n\n function clear() {\n drafts.forEach(release);\n setDrafts([]);\n }\n\n return {\n drafts,\n add,\n remove,\n clear,\n /** The originals, in the order they were picked. */\n files: drafts.map((draft) => draft.file),\n /** True while something in the list cannot be sent. */\n hasBlocker: drafts.some((draft) => draft.error !== null),\n };\n}\n","\"use client\";\n\nimport { useRef, useState, type ClipboardEvent, type DragEvent } from \"react\";\n\n/**\n * The two ways a file arrives that are not the picker: dragged onto the\n * composer, or pasted into it. Both are how somebody who has just taken a\n * screenshot expects to send it, and neither should need the plus button.\n *\n * Shared by the inbox and the widget, so a screenshot lands the same way on\n * both sides of a conversation. This only notices and collects; what becomes\n * of the files is the caller's business, which is what lets an internal note\n * turn them away.\n */\nexport function useAttachmentTarget({\n onFiles,\n disabled = false,\n}: {\n onFiles: (files: File[]) => void;\n /** Somewhere a file is not welcome, like a note the backend keeps to words. */\n disabled?: boolean;\n}) {\n const [isDropTarget, setIsDropTarget] = useState(false);\n\n // Dragging over a child element fires leave on the parent, so the highlight\n // counts its way in and out rather than trusting a single leave to mean the\n // pointer has actually gone.\n const depth = useRef(0);\n\n function handleDragEnter(event: DragEvent<HTMLElement>) {\n // Dragging a selection of text across the page is not an attachment.\n if (disabled || !event.dataTransfer.types.includes(\"Files\")) return;\n depth.current += 1;\n setIsDropTarget(true);\n }\n\n function handleDragLeave() {\n depth.current = Math.max(0, depth.current - 1);\n if (depth.current === 0) setIsDropTarget(false);\n }\n\n function handleDrop(event: DragEvent<HTMLElement>) {\n event.preventDefault();\n depth.current = 0;\n setIsDropTarget(false);\n if (disabled) return;\n\n const files = Array.from(event.dataTransfer.files);\n if (files.length > 0) onFiles(files);\n }\n\n function handlePaste(event: ClipboardEvent<HTMLElement>) {\n if (disabled) return;\n\n // Ordinary text carries no files, and is left alone entirely: caret,\n // selection, undo history and all. A screenshot does carry one, and\n // taking it means the markup the clipboard came with does not also end\n // up in the message.\n const files = Array.from(event.clipboardData.files);\n if (files.length === 0) return;\n\n event.preventDefault();\n onFiles(files);\n }\n\n return {\n /** True while something is being dragged over it, for the highlight. */\n isDropTarget,\n /** Spread onto whatever counts as the target. */\n targetProps: {\n onDragEnter: handleDragEnter,\n onDragLeave: handleDragLeave,\n // Without this the browser refuses the drop and opens the file instead,\n // taking the page, and whatever was being written, with it.\n onDragOver: (event: DragEvent<HTMLElement>) => event.preventDefault(),\n onDrop: handleDrop,\n onPaste: handlePaste,\n },\n };\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * The widget's own button, deliberately forked from `ui/button`.\n *\n * The widget ships on other people's sites, so its look is a contract with\n * them, not with our chrome. When the app restyles its buttons, the widget\n * must not come along for the ride; this file is where it stays put.\n */\nconst widgetButtonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-7 rounded-[min(var(--radius-md),12px)]\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction WidgetButton({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof widgetButtonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : \"button\";\n\n return (\n <Comp\n data-slot=\"widget-button\"\n data-variant={variant}\n data-size={size}\n className={cn(widgetButtonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { WidgetButton, widgetButtonVariants };\n","/**\n * The shell every text field wears: surface, border, and focus outline. Kept\n * in one place so a single line box and a multi line composer cannot drift\n * into different colours.\n *\n * `focus-within` rather than `focus-visible`, so it reads the same whether the\n * element wearing it is the field itself or the box around one. For a text\n * field the two fire together anyway.\n */\nexport const TEXT_FIELD_SHELL = [\n \"rounded-lg border border-input bg-transparent text-sm transition-[color,box-shadow] outline-none dark:bg-input/30\",\n \"placeholder:text-muted-foreground\",\n // Focus recolours the hairline rather than adding a ring on top of it, so\n // the outline stays exactly 1px and nothing swells on click.\n \"focus-within:border-ring\",\n \"aria-invalid:border-destructive\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n].join(\" \");\n","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Grows with its content up to `max-h`, courtesy of `field-sizing-content`.\n * Browsers without it fall back to the `rows` the caller sets.\n */\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"field-sizing-content w-full resize-none bg-transparent text-sm outline-none\",\n \"placeholder:text-muted-foreground\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Textarea };\n","\"use client\";\n\nimport { useCallback, useEffect, useRef } from \"react\";\n\n/** Refreshed well inside the server's TTL, without spamming a mutation. */\nconst REFRESH_MS = 2500;\n/**\n * This long without a keystroke means the sentence stalled. Generous on\n * purpose: dots that vanish at every thinking pause and pop back at the next\n * key read as flicker, not presence.\n */\nconst IDLE_MS = 8000;\n\n/**\n * Turns keystrokes into a calm typing signal: `ping` on every change sends\n * \"typing\" at most every couple of seconds, going quiet after a pause, on\n * `stop`, and on unmount.\n *\n * `settle` goes quiet locally without announcing it. That is for sending:\n * the message itself is the stop, and racing a \"stopped typing\" mutation in\n * ahead of it would delete the pending bubble the reply is about to fill,\n * which is the difference between a bubble that morphs and one that flashes.\n *\n * Failures are swallowed on purpose. A typing indicator is decoration, and\n * decoration does not get to put errors in front of anyone.\n */\nexport function useTypingSignal(onChange?: (isTyping: boolean) => unknown) {\n // Held in a ref so ping and stop keep stable identities while the caller\n // re-renders with fresh closures.\n const onChangeRef = useRef(onChange);\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n const isTypingRef = useRef(false);\n const lastSentRef = useRef(0);\n const idleTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const send = useCallback((isTyping: boolean) => {\n try {\n void Promise.resolve(onChangeRef.current?.(isTyping)).catch(() => {});\n } catch {\n // Decorative; see above.\n }\n }, []);\n\n /** Goes quiet without telling anyone. The send that follows says it. */\n const settle = useCallback(() => {\n if (idleTimer.current) clearTimeout(idleTimer.current);\n idleTimer.current = null;\n isTypingRef.current = false;\n lastSentRef.current = 0;\n }, []);\n\n const stop = useCallback(() => {\n const wasTyping = isTypingRef.current;\n settle();\n if (wasTyping) send(false);\n }, [send, settle]);\n\n const ping = useCallback(() => {\n if (idleTimer.current) clearTimeout(idleTimer.current);\n idleTimer.current = setTimeout(stop, IDLE_MS);\n\n const now = Date.now();\n if (!isTypingRef.current || now - lastSentRef.current > REFRESH_MS) {\n isTypingRef.current = true;\n lastSentRef.current = now;\n send(true);\n }\n }, [send, stop]);\n\n useEffect(() => () => stop(), [stop]);\n\n return { ping, stop, settle };\n}\n","/**\n * The Median marks, as geometry rather than as files.\n *\n * The same brand components render inside the widget package, which is\n * installed into someone else's app and has no way to reach our public\n * directory. Keeping the paths here is what lets a mark draw itself\n * anywhere: in the app, in the npm bundle, and through a CSS mask, all from\n * one copy.\n *\n * `public/` still carries the SVGs, for the things outside the app that want\n * a file to point at: favicons, OG images, the docs site.\n */\n\n/** What the artwork is drawn in. Dark mode inverts it rather than restating it. */\nexport const BRAND_INK = \"#191919\";\n\n/** The mark, in its own square box. */\nexport const LOGO = {\n viewBox: \"0 0 58 58\",\n paths: [\n \"M48.9788 0H8.97304C4.01742 0 0 4.11877 0 9.22508V20.7384C0 21.5573 0.577354 22.0631 1.37122 21.8223L46.068 10.1885C47.2227 9.87541 47.8963 10.7666 47.5595 11.9228L35.8922 56.5789C35.6757 57.446 36.2049 58 37.0709 58H48.7383C53.7661 58 58 53.6885 58 48.799V9.22508C58 4.11877 53.9585 0 48.9788 0Z\",\n \"M0 26.976V49.0151C0 53.9287 3.99336 57.9993 8.97304 57.9993H30.8884C31.7545 57.9993 32.1634 57.2767 31.9229 56.4337L28.579 44.3182C28.4347 43.8606 28.4587 43.4511 28.6993 42.9935L39.3803 21.5084C39.9818 20.3041 38.5384 19.4129 37.6723 20.3282L10.4164 47.3531C9.64662 48.1721 8.41974 47.2327 8.85276 46.1488L13.9527 30.9744C14.2173 30.1073 13.8565 29.2642 12.8221 29.0716L1.4915 25.9644C0.60141 25.6513 0 26.133 0 26.976Z\",\n ],\n} as const;\n\n/** The word, sharing the mark's 58 unit height so the two set together. */\nexport const WORDMARK = {\n viewBox: \"0 0 253 58\",\n width: 253,\n height: 58,\n paths: [\n \"M10.1999 2.52174L29.0138 35.0522L47.8637 2.52174H57.8834V56.9913H47.7916V21.1106L33.1586 46.2199H24.6527L9.98362 20.9665V56.9913H0V2.52174H10.1999Z\",\n \"M102.616 40.6H71.5115C72.1363 43.4099 73.5058 45.5834 75.6203 47.1205C77.7588 48.6335 80.3778 49.3901 83.4775 49.3901C85.664 49.3901 87.6823 48.9458 89.5325 48.0571C91.4067 47.1445 92.8363 45.9317 93.8215 44.4186L101.57 49.318C99.8165 51.9598 97.3176 54.0613 94.0738 55.6224C90.83 57.2075 87.2979 58 83.4775 58C79.2966 58 75.5362 57.0874 72.1963 55.2621C68.8805 53.4609 66.2975 50.9752 64.4473 47.805C62.6212 44.6108 61.7081 41.0563 61.7081 37.1416C61.7081 34.2116 62.2247 31.4617 63.2579 28.8919C64.3152 26.2981 65.7448 24.0766 67.5469 22.2273C69.349 20.3781 71.5235 18.9251 74.0705 17.8683C76.6175 16.7876 79.3326 16.2472 82.216 16.2472C88.1509 16.2472 93.0526 18.1085 96.9211 21.8311C100.814 25.5536 102.76 30.3329 102.76 36.1689C102.76 36.8654 102.712 38.3424 102.616 40.6ZM71.5115 33.5031H93.0646C92.8003 30.8373 91.695 28.6998 89.7487 27.0907C87.8265 25.4816 85.3396 24.677 82.2881 24.677C79.5969 24.677 77.2662 25.4576 75.2959 27.0186C73.3497 28.5797 72.0882 30.7412 71.5115 33.5031Z\",\n \"M136.608 1.54907H146.735V56.9913H136.608V51.3714C135.286 53.5329 133.508 55.1781 131.273 56.3068C129.039 57.4356 126.516 58 123.705 58C118.202 58 113.601 55.9946 109.901 51.9839C106.2 47.9731 104.35 43.0257 104.35 37.1416C104.326 34.2836 104.807 31.5578 105.792 28.964C106.777 26.3702 108.122 24.1366 109.828 22.2634C111.558 20.366 113.625 18.877 116.028 17.7963C118.454 16.7155 121.013 16.1992 123.705 16.2472C126.516 16.2472 129.039 16.8116 131.273 17.9404C133.508 19.0451 135.286 20.6663 136.608 22.8037V1.54907ZM133.436 45.8957C135.55 43.6861 136.608 40.7681 136.608 37.1416C136.608 33.5151 135.55 30.5971 133.436 28.3876C131.345 26.154 128.642 25.0373 125.326 25.0373C122.011 25.0373 119.271 26.1901 117.109 28.4957C115.042 30.7772 114.009 33.6592 114.009 37.1416C114.009 40.6 115.067 43.482 117.181 45.7876C119.295 48.0692 122.011 49.2099 125.326 49.2099C128.642 49.2099 131.345 48.1052 133.436 45.8957Z\",\n \"M150.957 5.98012C150.957 4.29896 151.557 2.88199 152.759 1.72919C153.984 0.576398 155.486 0 157.264 0C159.018 0 160.496 0.588406 161.697 1.76522C162.923 2.91801 163.535 4.32298 163.535 5.98012C163.535 7.70932 162.935 9.1383 161.733 10.2671C160.556 11.3959 159.066 11.9602 157.264 11.9602C155.462 11.9602 153.96 11.3959 152.759 10.2671C151.557 9.1383 150.957 7.70932 150.957 5.98012ZM162.274 17.2919V56.9913H152.218V17.2919H162.274Z\",\n \"M198.176 17.2919H208.304V56.9913H198.176V51.3714C196.854 53.5329 195.076 55.1781 192.842 56.3068C190.607 57.4356 188.084 58 185.273 58C179.77 58 175.169 55.9946 171.469 51.9839C167.768 47.9731 165.918 43.0257 165.918 37.1416C165.894 34.2836 166.375 31.5578 167.36 28.964C168.345 26.3702 169.691 24.1366 171.397 22.2634C173.127 20.366 175.193 18.877 177.596 17.7963C180.023 16.7155 182.582 16.1992 185.273 16.2472C188.084 16.2472 190.607 16.8116 192.842 17.9404C195.076 19.0451 196.854 20.6663 198.176 22.8037V17.2919ZM195.004 45.8957C197.119 43.6861 198.176 40.7681 198.176 37.1416C198.176 33.5151 197.119 30.5971 195.004 28.3876C192.914 26.154 190.211 25.0373 186.895 25.0373C183.579 25.0373 180.84 26.1901 178.677 28.4957C176.611 30.7772 175.578 33.6592 175.578 37.1416C175.578 40.6 176.635 43.482 178.749 45.7876C180.864 48.0692 183.579 49.2099 186.895 49.2099C190.211 49.2099 192.914 48.1052 195.004 45.8957Z\",\n \"M253 34.5478V56.9913H242.872V35.2683C242.872 31.882 242.115 29.3362 240.602 27.6311C239.088 25.9019 236.865 25.0373 233.934 25.0373C231.002 25.0373 228.588 26.082 226.689 28.1714C224.791 30.2369 223.842 32.9267 223.842 36.241V56.9913H213.786V17.2919H223.842V22.9478C224.995 20.8824 226.665 19.2493 228.852 18.0484C231.062 16.8476 233.549 16.2472 236.313 16.2472C241.503 16.2472 245.575 17.8563 248.531 21.0745C251.51 24.2928 253 28.7839 253 34.5478Z\",\n ],\n} as const;\n\n/**\n * The mark as a `url()`, for CSS that paints through its shape rather than\n * painting the artwork itself. Inline, because a mask is fetched the way an\n * image is and a host has nothing at `/median-logo.svg` to answer with.\n *\n * A mask reads only coverage, so the paths go in without a fill and come out\n * opaque.\n */\nexport const LOGO_MASK_URL = `url(\"data:image/svg+xml,${encodeURIComponent(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${LOGO.viewBox}\">` +\n LOGO.paths.map((d) => `<path d=\"${d}\"/>`).join(\"\") +\n `</svg>`,\n)}\")`;\n","import { BRAND_INK, LOGO, WORDMARK } from \"@/components/brand-art\";\n\n/** The artwork is solid black, so it gets inverted for dark mode. */\nconst INVERT_IN_DARK = \"dark:invert\";\n\n/**\n * The marks, drawn inline.\n *\n * Inline rather than fetched, because these render inside the widget package\n * too, where there is no public directory of ours to ask. See\n * `brand-art.ts` for the geometry.\n */\n\nexport function Wordmark({\n width = 132,\n className = \"\",\n}: {\n width?: number;\n className?: string;\n}) {\n return (\n <svg\n viewBox={WORDMARK.viewBox}\n width={width}\n height={Math.round((width * WORDMARK.height) / WORDMARK.width)}\n role=\"img\"\n aria-label=\"Median\"\n className={`${INVERT_IN_DARK} ${className}`}\n >\n {WORDMARK.paths.map((d) => (\n <path key={d} d={d} fill={BRAND_INK} />\n ))}\n </svg>\n );\n}\n\nexport function Logo({\n size = 104,\n className = \"\",\n}: {\n size?: number;\n className?: string;\n}) {\n return (\n <svg\n viewBox={LOGO.viewBox}\n width={size}\n height={size}\n aria-hidden\n className={`${INVERT_IN_DARK} ${className}`}\n >\n {LOGO.paths.map((d) => (\n <path key={d} d={d} fill={BRAND_INK} />\n ))}\n </svg>\n );\n}\n","import { Logo, Wordmark } from \"@/components/brand\";\nimport { cn } from \"@/lib/utils\";\n\nconst MEDIAN_URL = \"https://median.sh\";\n\n/**\n * Our name on somebody else's site, so it sits under the composer rather than\n * inside it: a quiet line at the foot of the panel, not a control.\n *\n * It opens in a new tab, since a visitor who taps it is halfway through asking\n * for help and should not lose the page they were on.\n */\nexport function PoweredByMedian({ className }: { className?: string }) {\n return (\n <a\n href={MEDIAN_URL}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className={cn(\n \"flex items-center justify-center gap-1.5 rounded-md py-1 text-xs text-muted-foreground\",\n \"transition-opacity hover:opacity-70\",\n \"focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none\",\n className,\n )}\n >\n Powered by\n <Logo size={12} className=\"opacity-80\" />\n <Wordmark width={40} className=\"opacity-80\" />\n </a>\n );\n}\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { useState } from \"react\";\nimport { InitialBadge } from \"@/components/initial-badge\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * A profile photo, falling back to a letter if there is no image or it fails\n * to load. `className` lands last on both branches, so a caller can override\n * the size and the letter's type scale together.\n */\nexport function Avatar({\n src,\n name,\n sourceSize = 48,\n unoptimized = false,\n className,\n}: {\n src: string | null;\n name: string;\n /** Intrinsic pixels to request. Aim for twice the rendered size. */\n sourceSize?: number;\n /**\n * Serve the picture as it came rather than through the image optimizer.\n * For faces from somebody else's site: the optimizer only fetches hosts\n * next.config names, and a customer's picture could be on any of them.\n */\n unoptimized?: boolean;\n className?: string;\n}) {\n // Which picture failed, rather than whether one did. A plain boolean never\n // cleared itself, so one bad response left the letter in place for the life\n // of the component: switch organizations and the next face inherited the\n // last one's failure, and a picture that was fine again stayed a letter\n // until the whole page reloaded.\n const [failedSrc, setFailedSrc] = useState<string | null>(null);\n const hasFailed = failedSrc !== null && failedSrc === src;\n const shape = \"size-4.5 shrink-0 rounded-full\";\n\n if (!src || hasFailed) {\n return (\n <InitialBadge\n value={name}\n className={cn(shape, \"border-none bg-muted text-[10px]\", className)}\n />\n );\n }\n\n return (\n <Image\n src={src}\n alt=\"\"\n width={sourceSize}\n height={sourceSize}\n unoptimized={unoptimized}\n onError={() => setFailedSrc(src)}\n draggable={false}\n className={cn(shape, \"bg-muted object-cover\", className)}\n />\n );\n}\n","import { cn } from \"@/lib/utils\";\n\n/**\n * A letter stand in for an avatar. Decorative: the readable name always sits\n * next to it, so this stays out of the accessibility tree.\n */\nexport function InitialBadge({\n value,\n className,\n}: {\n value: string;\n className?: string;\n}) {\n return (\n <span\n aria-hidden\n className={cn(\n // Sized to match UserAvatar, since the two sit side by side in the nav.\n \"grid size-4.5 shrink-0 place-items-center rounded border text-[10px] font-semibold text-muted-foreground\",\n className,\n )}\n >\n {value.trim().charAt(0).toUpperCase() || \"?\"}\n </span>\n );\n}\n","import { Avatar } from \"@/components/avatar\";\nimport { Sparkle } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport type { SupportAgent } from \"./types\";\n\n/**\n * An agent's face, or a mark where the AI is concerned. Squares rather than\n * the circles the inbox uses: the widget sits on somebody else's site next to\n * their own chrome, and a rounded square reads as a product mark there instead\n * of as another person's photo.\n *\n * Sizing comes from `className` so a caller can pick one scale for the header\n * and a smaller one for a read receipt. `label` overrides the name a screen\n * reader hears, which is how a receipt says \"Seen by Median AI\" from the same\n * one element rather than announcing the name twice.\n */\nexport function WidgetAvatar({\n agent,\n label,\n className,\n}: {\n agent: SupportAgent;\n label?: string;\n className?: string;\n}) {\n const shape = \"size-7 shrink-0 rounded-lg\";\n\n // The AI wears the mark until somebody gives it a face in settings; a\n // configured picture takes over and renders like anyone else's.\n if (agent.kind === \"ai\" && !agent.avatarUrl) {\n return (\n <span\n role=\"img\"\n aria-label={label ?? agent.name}\n className={cn(\n \"grid place-items-center bg-foreground text-background\",\n shape,\n className,\n )}\n >\n <Sparkle className=\"size-[55%]\" />\n </span>\n );\n }\n\n // Wrapped rather than labelled directly, because Avatar renders a decorative\n // image and has no name of its own to override.\n return (\n <span\n role=\"img\"\n aria-label={label ?? agent.name}\n className={cn(\"inline-flex\", shape, className)}\n >\n <Avatar\n src={agent.avatarUrl}\n name={agent.name}\n className=\"size-full rounded-[inherit]\"\n />\n </span>\n );\n}\n\n/**\n * Who is around, in the corner of the header. A row rather than an overlap,\n * since two or three faces read more clearly side by side at this size.\n */\nexport function WidgetAvatarStack({\n team,\n className,\n}: {\n team: SupportAgent[];\n className?: string;\n}) {\n if (team.length === 0) return null;\n\n return (\n <div className={cn(\"flex items-center gap-1\", className)}>\n {team.map((agent) => (\n <WidgetAvatar key={agent.id} agent={agent} className=\"size-8\" />\n ))}\n </div>\n );\n}\n","import type { ComponentType } from \"react\";\nimport { Bug, CaretRight, ChatCircleDots, Lightbulb } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport { WidgetAvatar } from \"./widget-avatar\";\nimport { WidgetButton } from \"./widget-button\";\nimport type { SupportAgent } from \"./types\";\n\n/**\n * The three things people open a support widget to do, and the message each\n * row sends.\n *\n * The messages are written as something a person would actually type, since\n * that is exactly what they become: the row sends it and the agent takes it\n * from there.\n */\nconst STARTERS: {\n label: string;\n glyph: ComponentType<{ className?: string }>;\n message: string;\n}[] = [\n {\n label: \"Ask a question\",\n glyph: ChatCircleDots,\n message: \"I have a question\",\n },\n {\n label: \"Report a bug\",\n glyph: Bug,\n message: \"I want to report a bug\",\n },\n {\n label: \"Make a suggestion\",\n glyph: Lightbulb,\n message: \"I have a suggestion\",\n },\n];\n\n/**\n * A conversation with nothing in it yet.\n *\n * Who is about to answer, and three ways to start. The AI goes first because\n * it is the one that always replies; a team of only people falls back to\n * whoever is at the front.\n *\n * The invitation names the organization, because that is the whole of what\n * the agent will talk about. Saying so here is cheaper than declining later.\n *\n * The rows send rather than fill the box in. Somebody who knows what they\n * want types it; somebody who is looking at three rows wants the shortest\n * way to the first reply.\n */\nexport function WidgetEmpty({\n team,\n orgName,\n onPick,\n isSending = false,\n isWaiting = false,\n}: {\n team: SupportAgent[];\n /** Whose site this is, so the invitation can say what it covers. */\n orgName?: string;\n /** Omit to leave the rows off, for a widget with nowhere to send them. */\n onPick?: (message: string) => void;\n /** Holds the rows while a message is on its way. */\n isSending?: boolean;\n /**\n * Holds them for something else the visitor has to do first, which is the\n * composer's question. The rows stay where they are while it is up rather\n * than arriving once it is answered: three rows appearing in a column that\n * centres itself would shove everything above them up the panel, and an\n * answer should not move the furniture.\n */\n isWaiting?: boolean;\n}) {\n const agent = team.find((member) => member.kind === \"ai\") ?? team[0];\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col items-center justify-center gap-4 px-5 pb-2 text-center\">\n {agent && (\n <WidgetAvatar\n agent={agent}\n className=\"size-14 animate-in rounded-2xl duration-500 ease-out fade-in-0 zoom-in-95 motion-reduce:animate-none\"\n />\n )}\n\n {/* A beat behind the mark, so the two read as one thing settling rather\n than as a block appearing. Backwards fill holds it out of sight\n through the delay instead of showing it and taking it away. */}\n <div className=\"flex max-w-64 animate-in flex-col gap-1 delay-150 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\">\n {agent && (\n <p className=\"text-base font-semibold tracking-tight\">{agent.name}</p>\n )}\n <p className=\"text-sm text-balance text-muted-foreground\">\n {orgName ? `Ask me anything about ${orgName}.` : \"Ask me anything.\"}\n </p>\n </div>\n\n {onPick && (\n <div className=\"flex w-full flex-col gap-1.5 pt-1\">\n {STARTERS.map((starter, index) => (\n <WidgetButton\n key={starter.label}\n type=\"button\"\n variant=\"outline\"\n disabled={isSending || isWaiting}\n onClick={() => onPick(starter.message)}\n // Each one a beat behind the last, so the three deal out rather\n // than land as a block. Backwards fill keeps them out of sight\n // until their turn.\n style={{ animationDelay: `${300 + index * 60}ms` }}\n className={cn(\n \"group/row h-auto w-full animate-in justify-start gap-2.5 px-3 py-2.5 text-left\",\n \"duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\",\n \"hover:border-foreground/15 hover:shadow-sm\",\n )}\n >\n <starter.glyph className=\"size-4 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{starter.label}</span>\n <CaretRight\n aria-hidden\n className=\"size-3 text-muted-foreground/50 transition-transform group-hover/row:translate-x-0.5\"\n />\n </WidgetButton>\n ))}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { ArrowsIn, ArrowsOut, X } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { cn } from \"@/lib/utils\";\nimport type { DragHandlers } from \"./use-launcher-drag\";\nimport { WidgetAvatarStack } from \"./widget-avatar\";\nimport type { SupportPresence } from \"./types\";\n\n/**\n * Who you are talking to, and the one way out. There is no way back, because\n * there is nothing behind it: a visitor gets one thread, not a queue of them.\n *\n * It is also the handle. A panel floating on somebody's page is in the way of\n * something eventually, and the strip along the top is where anyone would\n * reach for to move it. The close button and the faces stay their own: a press\n * that lands on a control belongs to that control, which the drag checks\n * before it takes hold of anything.\n */\nexport function WidgetHeader({\n presence,\n onClose,\n isExpanded = false,\n onToggleExpanded,\n grabHandlers,\n isMoving = false,\n}: {\n presence: SupportPresence;\n onClose?: () => void;\n /** Standing taller than it normally does. */\n isExpanded?: boolean;\n /** Omit to hide the control, for a widget whose size is not its own. */\n onToggleExpanded?: () => void;\n /** Omit for a widget that is framed rather than floating. */\n grabHandlers?: DragHandlers;\n isMoving?: boolean;\n}) {\n return (\n <header\n {...grabHandlers}\n className={cn(\n \"flex shrink-0 items-start gap-2 px-3 pt-3 pb-2\",\n grabHandlers && [\n // Nothing here is selectable while it is being used to drag, and the\n // browser must not claim the gesture for scrolling either. Both end\n // the same way: the drag becomes the page's instead of ours.\n \"touch-none select-none\",\n isMoving ? \"cursor-grabbing\" : \"cursor-grab\",\n ],\n )}\n >\n <div className=\"flex min-w-0 flex-1 flex-col pt-0.5\">\n <h2 className=\"truncate text-base font-semibold tracking-tight\">\n {presence.name}\n </h2>\n <p className=\"truncate text-sm text-muted-foreground\">\n {presence.status}\n </p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-2\">\n <WidgetAvatarStack team={presence.team} />\n\n {/* The controls sit closer to each other than to the faces, so they\n read as a pair rather than as the end of the row. */}\n <div className=\"flex items-center gap-0.5\">\n {onToggleExpanded && (\n <WidgetButton\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onToggleExpanded}\n aria-pressed={isExpanded}\n aria-label={isExpanded ? \"Shrink the panel\" : \"Expand the panel\"}\n className=\"text-muted-foreground\"\n >\n {isExpanded ? <ArrowsIn /> : <ArrowsOut />}\n </WidgetButton>\n )}\n\n {onClose && (\n <WidgetButton\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClose}\n aria-label=\"Close support\"\n className=\"-mr-1 text-muted-foreground\"\n >\n <X />\n </WidgetButton>\n )}\n </div>\n </div>\n </header>\n );\n}\n","import { LOGO_MASK_URL } from \"@/components/brand-art\";\n\n/**\n * Waiting on the conversation.\n *\n * The mark is painted by a gradient showing through a mask cut in its shape,\n * rather than by the artwork itself, so the band of light travels across the\n * logo instead of over the top of it. The gradient is angled, so sliding it\n * sideways reads as a diagonal sweep.\n *\n * One mark and nothing else. Skeleton bubbles would be guessing at a shape\n * nobody knows yet, and they always guess wrong.\n */\nexport function WidgetLoading() {\n return (\n <div className=\"grid min-h-0 flex-1 place-items-center p-6\">\n <span\n role=\"status\"\n aria-label=\"Loading the conversation\"\n style={{\n maskImage: LOGO_MASK_URL,\n maskSize: \"contain\",\n maskRepeat: \"no-repeat\",\n maskPosition: \"center\",\n WebkitMaskImage: LOGO_MASK_URL,\n WebkitMaskSize: \"contain\",\n WebkitMaskRepeat: \"no-repeat\",\n WebkitMaskPosition: \"center\",\n backgroundImage:\n \"linear-gradient(115deg, var(--muted) 34%, var(--muted-foreground) 50%, var(--muted) 66%)\",\n backgroundSize: \"300% 100%\",\n }}\n className=\"size-12 animate-shimmer motion-reduce:animate-none motion-reduce:bg-muted\"\n />\n </div>\n );\n}\n","import { LockSimple } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { PoweredByMedian } from \"./widget-badge\";\n\n/**\n * What a visitor meets when the host only takes questions from people who are\n * signed in.\n *\n * The same shape as the empty conversation it stands in for, and it arrives\n * the same way: the mark, then the words a beat behind it, then the one thing\n * to do about it. The button is only there when the host said where their\n * sign in lives, because a button that goes nowhere is worse than none.\n */\nexport function WidgetLocked({\n orgName,\n onSignIn,\n showBadge = true,\n}: {\n /** Whose site this is, so the line can name who is waiting. */\n orgName?: string;\n onSignIn?: () => void;\n /** The line the composer usually carries, which is not here to carry it. */\n showBadge?: boolean;\n}) {\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"flex min-h-0 flex-1 flex-col items-center justify-center gap-4 px-6 text-center\">\n <span className=\"grid size-14 animate-in place-items-center rounded-2xl bg-muted duration-500 ease-out fade-in-0 zoom-in-95 motion-reduce:animate-none\">\n <LockSimple className=\"size-6 text-muted-foreground\" />\n </span>\n\n <div className=\"flex max-w-64 animate-in flex-col gap-1 delay-150 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\">\n <p className=\"text-base font-semibold tracking-tight\">\n Sign in to chat\n </p>\n <p className=\"text-sm text-balance text-muted-foreground\">\n {orgName\n ? `Ask ${orgName} anything once you are signed in.`\n : \"Ask us anything once you are signed in.\"}\n </p>\n </div>\n\n {onSignIn && (\n <WidgetButton\n onClick={onSignIn}\n className=\"animate-in delay-300 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\"\n >\n Sign in\n </WidgetButton>\n )}\n </div>\n\n {showBadge && <PoweredByMedian className=\"shrink-0 px-3 pb-3\" />}\n </div>\n );\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"@/lib/utils\";\n\n// The palette is greyscale on purpose, so badges separate by weight rather\n// than by hue. Anything that needs to shout can reach for `solid`.\nconst badgeVariants = cva(\n \"inline-flex w-fit shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium whitespace-nowrap [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3\",\n {\n variants: {\n variant: {\n default: \"bg-secondary text-secondary-foreground\",\n muted: \"bg-muted text-muted-foreground\",\n outline: \"border border-border text-muted-foreground\",\n solid: \"bg-primary text-primary-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Badge({\n className,\n variant = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : \"span\";\n\n return (\n <Comp\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nexport { Badge, badgeVariants };\n","\"use client\";\n\nimport { useState, type ReactNode } from \"react\";\nimport { File, ImageSquare, Play } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport type { SupportAttachment } from \"./types\";\n\n/** Tiles sit on the panel colour so they read as objects inside the bubble. */\nconst SURFACE = \"rounded-xl border border-foreground/10 bg-card/70\";\n\n/**\n * Opens the file, for anything that has somewhere to be opened.\n *\n * A new tab, because this is running on somebody else's page and a visitor\n * halfway through asking for help should not lose it. No `download`: the file\n * is served from another origin, where browsers ignore that attribute, so it\n * would promise a save and quietly do something else.\n *\n * Falls through to the plain contents when there is no URL, which is a file\n * still on its way or one whose link could not be signed. Better a tile that\n * does nothing than a link that goes nowhere.\n */\nfunction OpenAttachment({\n attachment,\n className,\n children,\n}: {\n attachment: SupportAttachment;\n className?: string;\n children: ReactNode;\n}) {\n if (!attachment.url) return <>{children}</>;\n\n return (\n <a\n href={attachment.url}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n aria-label={`Open ${attachment.name}`}\n className={cn(\n \"block rounded-xl transition-opacity outline-none hover:opacity-80\",\n \"focus-visible:ring-3 focus-visible:ring-ring/50\",\n className,\n )}\n >\n {children}\n </a>\n );\n}\n\nfunction MediaTile({\n attachment,\n className,\n}: {\n attachment: SupportAttachment;\n className?: string;\n}) {\n const [hasFailed, setHasFailed] = useState(false);\n\n // A preview that will not load says so in place, rather than leaving a grey\n // rectangle to puzzle over.\n if (!attachment.previewUrl || hasFailed) {\n return (\n <div\n className={cn(\n SURFACE,\n \"flex flex-col items-center justify-center gap-1 px-2 text-center\",\n className,\n )}\n >\n <ImageSquare className=\"size-5 text-muted-foreground\" />\n <p className=\"text-xs text-muted-foreground\">Preview unavailable</p>\n </div>\n );\n }\n\n return (\n <figure className={cn(SURFACE, \"relative overflow-hidden\", className)}>\n {/* A plain img, not the framework's: a freshly picked file is an object\n URL that has not left the browser, so there is nothing for an image\n pipeline to do, and this file also ships in the npm package where\n there is no framework to ask. */}\n {/* eslint-disable-next-line @next/next/no-img-element -- an object URL or signed link, nothing for the optimizer to do, and the npm bundle has no next/image. */}\n <img\n src={attachment.previewUrl}\n alt={attachment.name}\n width={640}\n height={480}\n onError={() => setHasFailed(true)}\n draggable={false}\n className=\"size-full object-cover\"\n />\n\n {attachment.kind === \"video\" && (\n <span\n aria-hidden\n className=\"absolute inset-0 grid place-items-center bg-foreground/15\"\n >\n <span className=\"grid size-8 place-items-center rounded-full bg-background/85 shadow-sm\">\n <Play className=\"size-3.5 translate-x-px\" />\n </span>\n </span>\n )}\n </figure>\n );\n}\n\nfunction FileRow({ attachment }: { attachment: SupportAttachment }) {\n return (\n <OpenAttachment attachment={attachment}>\n <div className={cn(SURFACE, \"flex items-center gap-2 px-2 py-1.5\")}>\n <File className=\"size-4 shrink-0 text-muted-foreground\" />\n\n <div className=\"flex min-w-0 flex-1 flex-col text-left\">\n <p className=\"truncate text-xs font-medium\">{attachment.name}</p>\n <p className=\"truncate text-xs text-muted-foreground\">\n {attachment.size}\n </p>\n </div>\n </div>\n </OpenAttachment>\n );\n}\n\n/**\n * Everything hanging off a message. Pictures and clips get a tile, anything\n * else gets a named row.\n *\n * Tiles go shorter once they share a row, so a pair reads as a pair rather than\n * two letterboxes stacked in a box.\n */\nexport function WidgetAttachments({\n attachments,\n}: {\n attachments: SupportAttachment[];\n}) {\n const media = attachments.filter((one) => one.kind !== \"file\");\n const files = attachments.filter((one) => one.kind === \"file\");\n\n return (\n <div className=\"flex w-56 max-w-full flex-col gap-1.5\">\n {media.length > 0 && (\n <div className={cn(\"grid gap-1.5\", media.length > 1 && \"grid-cols-2\")}>\n {media.map((attachment) => (\n <OpenAttachment\n key={attachment.id}\n attachment={attachment}\n className={media.length > 1 ? \"h-20\" : \"h-32\"}\n >\n {/* Opens in a tab rather than a lightbox. The inbox has one\n because a teammate is working through a queue; a visitor is\n looking at a picture they sent a minute ago. */}\n <MediaTile attachment={attachment} className=\"size-full\" />\n </OpenAttachment>\n ))}\n </div>\n )}\n\n {files.map((attachment) => (\n <FileRow key={attachment.id} attachment={attachment} />\n ))}\n </div>\n );\n}\n","\"use client\";\n\nimport { useLayoutEffect, useRef, type ReactNode } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst MORPH_MS = 260;\n/**\n * Matches --ease-out-quint. A pure deceleration on purpose: a spring's\n * overshoot carries the box past its final size and back, and since the box\n * clips its contents that reads as the text being cut off and restored.\n */\nconst MORPH_EASING = \"cubic-bezier(0.22, 1, 0.36, 1)\";\n\n/** How long the new contents take to appear once the box has room for them. */\nconst CONTENT_FADE_MS = 140;\n\n/** Sub pixel differences are not worth an animation. */\nconst EPSILON = 1;\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/**\n * Hand the contents back to the layout: no held width, no held opacity.\n *\n * Also what has to happen before measuring, since a box still pinned by the\n * last morph measures at the size that morph was holding it at.\n */\nfunction release(inner: HTMLElement) {\n inner.style.width = \"\";\n inner.style.boxSizing = \"\";\n inner.style.opacity = \"\";\n}\n\n/**\n * Hold the contents at the width they just laid out at, in full precision.\n *\n * The precision is the whole point. `offsetWidth` is rounded to a whole\n * pixel, and a bubble that sizes itself to its own text sits on a fractional\n * width far more often than not, so half the time that rounding goes down and\n * pins the text a hair narrower than the width it measured at. That is enough\n * to push the last word of a line onto the next one. It happens under the\n * pin, where it is hidden, so the box travels to the height it measured\n * before the wrap and the words spring back a line the moment the pin comes\n * off. The computed width is the used width, fractions and all, and it is\n * layout space rather than screen space, so an ancestor mid animation cannot\n * skew it either.\n *\n * Held as a content box so the number means the same thing going back in as\n * it did coming out, whatever padding the contents carry.\n */\nfunction pin(inner: HTMLElement) {\n const width = getComputedStyle(inner).width;\n inner.style.boxSizing = \"content-box\";\n inner.style.width = width;\n inner.style.opacity = \"0\";\n}\n\n/**\n * A bubble that grows into its new contents rather than snapping to them.\n *\n * `morphKey` is what it watches. Change it and the bubble measures where it\n * was, where it now is, and travels between the two. That is what turns three\n * bouncing dots into an answer: same element, same node, a different size.\n *\n * The contents wait, and they wait for the whole morph. React puts the new\n * text in at its full size the moment it arrives, so without this it is\n * already sitting there while the box is still growing, and the box, which\n * clips, wipes it into view a sliver at a time. Fading it in partway through\n * only moves the problem: a multi line reply is taller than the box until the\n * very end, so it fades in already cut off. The box travels first and the\n * words arrive in it once there is room for all of them.\n *\n * They are also pinned to the width they just laid out at for the duration.\n * Without that the text re-wraps on every frame while the box around it is\n * still moving, which looks far worse than no animation at all.\n */\nexport function MorphBubble({\n morphKey,\n className,\n contentClassName,\n children,\n}: {\n /** Derive it from the content, so any change to that content morphs. */\n morphKey: string;\n className?: string;\n contentClassName?: string;\n children: ReactNode;\n}) {\n const box = useRef<HTMLDivElement>(null);\n const content = useRef<HTMLDivElement>(null);\n const previous = useRef<{ width: number; height: number } | null>(null);\n const running = useRef<Animation[]>([]);\n\n useLayoutEffect(() => {\n const outer = box.current;\n const inner = content.current;\n if (!outer || !inner) return;\n\n // Where the box is right now, mid travel included, so a change that lands\n // during a morph carries on from what is on screen rather than from where\n // that morph happened to start.\n const from = running.current.length\n ? { width: outer.offsetWidth, height: outer.offsetHeight }\n : previous.current;\n\n // Everything the last morph was holding comes off before this one\n // measures, or \"the natural size of the new contents\" is really just the\n // size the last one was pinning them at.\n const interrupted = running.current;\n running.current = [];\n release(inner);\n for (const animation of interrupted) animation.cancel();\n\n const next = { width: outer.offsetWidth, height: outer.offsetHeight };\n previous.current = next;\n\n // Nothing to travel from on the first paint, and nothing to travel to if\n // the new contents happen to be the same size.\n if (!from) return;\n if (\n Math.abs(from.width - next.width) < EPSILON &&\n Math.abs(from.height - next.height) < EPSILON\n ) {\n return;\n }\n if (prefersReducedMotion()) return;\n\n // Set before the browser paints, so the new contents are never on screen\n // at full size for even one frame while the box is still small.\n pin(inner);\n\n const size = outer.animate(\n [\n { width: `${from.width}px`, height: `${from.height}px` },\n { width: `${next.width}px`, height: `${next.height}px` },\n ],\n { duration: MORPH_MS, easing: MORPH_EASING },\n );\n // Filled both ways on purpose. Backwards holds it invisible through the\n // delay, while the box is still moving. Forwards is what stops it\n // blinking at the other end: the inline opacity above is what hides it\n // before the animation starts, and without a forwards fill the finished\n // animation stops applying and that inline zero shows through again for\n // a frame before the cleanup below can clear it.\n const reveal = inner.animate([{ opacity: 0 }, { opacity: 1 }], {\n duration: CONTENT_FADE_MS,\n delay: MORPH_MS,\n easing: \"ease-out\",\n fill: \"both\",\n });\n\n running.current = [size, reveal];\n\n reveal.finished\n .catch(() => {})\n .finally(() => {\n if (!running.current.includes(reveal)) return;\n running.current = [];\n // Drop the inline hold first and only then the animation holding it\n // open, so there is never a frame where neither is keeping it up.\n release(inner);\n reveal.cancel();\n });\n }, [morphKey]);\n\n return (\n <div ref={box} className={cn(\"overflow-hidden\", className)}>\n <div ref={content} className={contentClassName}>\n {children}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { MorphBubble } from \"@/components/ui/morph-bubble\";\n\n/**\n * The widget's bubble. The morph itself is shared with the inbox, so both\n * sides of a conversation grow into a reply the same way; this only fixes\n * how the contents stack inside it.\n */\nexport function WidgetBubble({\n morphKey,\n className,\n children,\n}: {\n morphKey: string;\n className?: string;\n children: ReactNode;\n}) {\n return (\n <MorphBubble\n morphKey={morphKey}\n className={className}\n contentClassName=\"flex flex-col gap-2\"\n >\n {children}\n </MorphBubble>\n );\n}\n","import { Suspense } from \"react\";\nimport { MessageMarkdown, useMarkdownReady } from \"./markdown-chunk\";\nimport type { SupportSender } from \"./types\";\n\n/**\n * What was said.\n *\n * The agent's side renders markdown, because the house voice writes it: a\n * bold word, a short list, a line of code. The visitor's side is quoted\n * verbatim, asterisks and all, since nothing they type is markup.\n *\n * No animation of its own, on purpose. The bubble around it is already\n * growing and clipping as the words land, and anything fading or sliding in\n * here fights that: text appears, gets clipped, fades again. The morph is\n * the animation. The words just sit in it.\n */\nexport function WidgetMessageBody({\n body,\n sender,\n}: {\n body: string;\n sender: SupportSender;\n}) {\n // False until the renderer has been fetched. See `markdown-chunk.tsx` for\n // when that happens and why it is not simply imported.\n const isReady = useMarkdownReady();\n\n const plain = <p className=\"break-words whitespace-pre-line\">{body}</p>;\n if (sender === \"visitor\" || !isReady) return plain;\n\n // The same paragraph again as the fallback, so a render that beats the\n // module here by a frame shows the words rather than a gap.\n return (\n <Suspense fallback={plain}>\n <MessageMarkdown body={body} />\n </Suspense>\n );\n}\n","/** Offsets, so the bounce travels along the row instead of all three hopping together. */\nconst DOTS = [0, 160, 320];\n\n/**\n * An agent mid sentence. It lives inside the reply's own bubble rather than in\n * a bubble of its own, which is what lets the bubble stay put and grow into the\n * answer when it arrives.\n */\nexport function WidgetTyping({ label }: { label: string }) {\n return (\n <span className=\"flex items-center gap-1 py-1.5\">\n <span className=\"sr-only\">{label}</span>\n\n {DOTS.map((delay) => (\n <span\n key={delay}\n aria-hidden\n style={{ animationDelay: `${delay}ms` }}\n className=\"size-1.5 animate-typing-dot rounded-full bg-foreground/45 motion-reduce:animate-none\"\n />\n ))}\n </span>\n );\n}\n","import { Badge } from \"@/components/ui/badge\";\nimport { LONE_MESSAGE, type MessageGroup } from \"@/lib/message-groups\";\nimport { cn } from \"@/lib/utils\";\nimport { WidgetAttachments } from \"./widget-attachments\";\nimport { WidgetAvatar } from \"./widget-avatar\";\nimport { WidgetBubble } from \"./widget-bubble\";\nimport { WidgetMessageBody } from \"./widget-message-body\";\nimport { WidgetTyping } from \"./widget-typing\";\nimport type { SupportMessage } from \"./types\";\n\n/**\n * Both bubbles keep the page's text colour and separate by surface instead.\n * The visitor's own is a step further from the panel than the agent's, which\n * tells the two apart without a slab of pure black in the light, or pure white\n * in the dark.\n */\nconst BUBBLE = \"max-w-[80%] rounded-2xl px-3.5 py-2 text-sm\";\nconst VISITOR_BUBBLE =\n \"bg-[color-mix(in_oklch,var(--muted),var(--foreground)_12%)]\";\n\n/**\n * New messages arrive rather than appear. Short and small on purpose: the\n * scroller is easing down to the newest message at the same time, and a bubble\n * travelling any further than this reads as a wobble against it rather than as\n * one thing arriving. Off for anyone who asked.\n */\nconst ARRIVES =\n \"animate-in fade-in-0 slide-in-from-bottom-1 duration-200 ease-out motion-reduce:animate-none\";\n\n/**\n * The break above a message, when there is one: a new day, or a conversation\n * that starts here because the one before it was resolved.\n *\n * One line either way, and never two stacked. A conversation starting is the\n * bigger of the two breaks, so it stands in for the date rather than sitting\n * under it.\n */\nexport function WidgetDivider({ message }: { message: SupportMessage }) {\n const label = message.startsConversation\n ? \"New conversation\"\n : message.dayLabel;\n if (!label) return null;\n\n return (\n <div className=\"flex items-center gap-3 py-1\">\n <span className=\"h-px flex-1 bg-border\" />\n <span className=\"text-xs text-muted-foreground\">{label}</span>\n <span className=\"h-px flex-1 bg-border\" />\n </div>\n );\n}\n\n/**\n * One message. The two sides are built differently on purpose.\n *\n * A visitor's own message is only the bubble. They know what they said and\n * when, so a name, a time and a read receipt underneath are three things that\n * earn nothing. An agent's turn gets one line above it saying who is speaking\n * and when, because you want both before you read what they said. One line per\n * turn, not per message: a reply that comes in three parts says it once.\n */\nexport function WidgetMessage({\n message,\n group = LONE_MESSAGE,\n}: {\n message: SupportMessage;\n /** Where it sits in a run from the same voice. Alone, by default. */\n group?: MessageGroup;\n}) {\n return message.sender === \"visitor\" ? (\n <VisitorMessage message={message} />\n ) : (\n <AgentMessage message={message} group={group} />\n );\n}\n\n/**\n * What goes in a bubble: the files first, then what was said about them. The\n * text is skipped entirely when there is none, so a picture sent on its own\n * gets a bubble that hugs it rather than one with an empty line underneath.\n *\n * A reply that has not landed yet holds three bouncing dots in the same place\n * the words are about to be, which is what the bubble grows out of.\n */\nfunction BubbleContent({ message }: { message: SupportMessage }) {\n const hasAttachments = (message.attachments?.length ?? 0) > 0;\n\n if (message.pending) {\n return (\n <WidgetTyping\n label={`${message.agent?.name ?? \"Support\"} is writing a reply`}\n />\n );\n }\n\n return (\n <>\n {hasAttachments && (\n <WidgetAttachments attachments={message.attachments ?? []} />\n )}\n\n {message.body && (\n <WidgetMessageBody body={message.body} sender={message.sender} />\n )}\n </>\n );\n}\n\nfunction VisitorMessage({ message }: { message: SupportMessage }) {\n return (\n <div className={cn(\"flex justify-end\", ARRIVES)}>\n <WidgetBubble morphKey=\"settled\" className={cn(BUBBLE, VISITOR_BUBBLE)}>\n <BubbleContent message={message} />\n </WidgetBubble>\n </div>\n );\n}\n\nfunction AgentMessage({\n message,\n group,\n}: {\n message: SupportMessage;\n group: MessageGroup;\n}) {\n const { agent } = message;\n\n return (\n // One line saying who and when, then the thing they said. The face used to\n // sit in a gutter beside the bubble with the name above it and the time\n // below, which spread four small things across three rows and pushed every\n // bubble in off the edge. All of it is one line now, and the bubble gets\n // the full width back.\n <div className={cn(\"flex flex-col items-start gap-1\", ARRIVES)}>\n {/* Once per turn rather than once per message: a reply that arrives in\n three parts is still one agent saying one thing. */}\n {group.isFirst && (\n <div className=\"flex max-w-full items-center gap-1.5 px-0.5\">\n {agent && (\n <>\n <WidgetAvatar agent={agent} className=\"size-5 rounded-md\" />\n <span className=\"truncate text-xs font-medium\">{agent.name}</span>\n\n {/* Said plainly, because a name and a face are exactly what a\n machine can be given, and a visitor should never have to\n work out which one they got. Once per turn, since that is\n where the name is: a burst of three says it once. */}\n {agent.kind === \"ai\" && (\n <Badge variant=\"muted\" className=\"shrink-0 rounded-md px-1\">\n AI\n </Badge>\n )}\n </>\n )}\n\n {/* No time on a reply that has not been written yet. */}\n {!message.pending && (\n <span className=\"shrink-0 text-xs text-muted-foreground tabular-nums\">\n {message.time}\n </span>\n )}\n </div>\n )}\n\n {/* The same bubble either way. It is what the dots are in, so when the\n answer replaces them it grows out of where they were rather than\n appearing somewhere near them. */}\n <WidgetBubble\n // Derived from the contents, so an answer that arrives in pieces\n // keeps growing rather than morphing once and then snapping.\n morphKey={\n message.pending\n ? \"pending\"\n : `${message.body.length}:${message.attachments?.length ?? 0}`\n }\n className={cn(BUBBLE, \"bg-muted\")}\n >\n <BubbleContent message={message} />\n </WidgetBubble>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n RATING_FEEDBACK_MAX_LENGTH,\n RATING_MAX_STARS,\n} from \"@median/backend/support\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { Star } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { Collapse, COLLAPSE_MS } from \"@/components/ui/collapse\";\nimport { TEXT_FIELD_SHELL } from \"@/components/ui/text-field\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { cn } from \"@/lib/utils\";\nimport type { SupportRating } from \"./types\";\n\nconst STARS = Array.from({ length: RATING_MAX_STARS }, (_, index) => index + 1);\n\n/** How long the thank you stays before the card folds itself away. */\nconst THANKS_MS = 1400;\n\n/** Between one star lighting up and the next, so a pick reads as a sweep. */\nconst STAR_STAGGER_MS = 40;\n\n/**\n * The question a resolved conversation asks, sitting on the composer.\n *\n * A star saves the moment it is pressed rather than waiting for a Send,\n * because most people stop there and four stars with nothing after them is\n * still the answer. The box for words opens underneath afterwards, so\n * somebody who has more to say has somewhere to say it and nobody is held up\n * by a form they did not want.\n *\n * Nothing here appears or vanishes. The card opens out of the composer, the\n * box for words opens under the stars, the thank you takes the question's\n * place, and the whole thing folds away when it is finished, each of them the\n * same height travelling. Which is why leaving tells the panel it is done\n * only once it has finished folding: unmounting on the click would take the\n * animation with it.\n *\n * Above the composer rather than in place of it: the thread is finished, not\n * closed, and writing again is how a visitor starts the next one.\n */\nexport function WidgetRating({ rating }: { rating: SupportRating }) {\n const [isOpen, setIsOpen] = useState(false);\n const [picked, setPicked] = useState<number | null>(rating.stars);\n const [hovered, setHovered] = useState<number | null>(null);\n const [feedback, setFeedback] = useState(\"\");\n const [isSending, setIsSending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [isDone, setIsDone] = useState(false);\n\n const timers = useRef<ReturnType<typeof setTimeout>[]>([]);\n useEffect(() => {\n // Shut for one frame, open on the next, which is what turns a card that\n // was suddenly there into one that grew out of the composer.\n const frame = requestAnimationFrame(() => setIsOpen(true));\n const pending = timers.current;\n return () => {\n cancelAnimationFrame(frame);\n for (const timer of pending) clearTimeout(timer);\n };\n }, []);\n\n function later(ms: number, run: () => void) {\n timers.current.push(setTimeout(run, ms));\n }\n\n /** Fold away first, and only then tell the panel there is nothing to ask. */\n function leave() {\n setIsOpen(false);\n later(COLLAPSE_MS, rating.skip);\n }\n\n const shown = hovered ?? picked ?? 0;\n\n async function send(stars: number, words?: string) {\n setError(null);\n setIsSending(true);\n try {\n await rating.submit(stars, words);\n return true;\n } catch (caught) {\n console.error(\"Rating the conversation failed\", caught);\n setError(\"That did not send. Try again.\");\n return false;\n } finally {\n setIsSending(false);\n }\n }\n\n async function choose(stars: number) {\n // On screen first: the star they pressed is the answer whether or not\n // the network agrees yet.\n setPicked(stars);\n await send(stars);\n }\n\n /**\n * Finishing, with or without words. The stars are already saved, so an\n * empty box is somebody who has said all they wanted to and does not owe\n * anybody a sentence about it: no round trip, straight to the thanks.\n */\n async function finish() {\n if (picked === null) return;\n const words = feedback.trim();\n if (words.length > 0 && !(await send(picked, words))) return;\n\n setIsDone(true);\n later(THANKS_MS, leave);\n }\n\n return (\n <Collapse isOpen={isOpen} className=\"shrink-0\">\n {/* The spacing lives inside each section rather than as a gap between\n them, so a section that is closed takes up nothing at all. */}\n <div className=\"mx-3 mb-2 rounded-xl border bg-muted/40 px-3 dark:bg-muted/20\">\n <Collapse isOpen={!isDone}>\n <div className=\"py-2.5\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-medium\">\n {picked === null ? \"How did we do?\" : \"Thanks. Tell us more?\"}\n </p>\n {/* A word rather than a cross: this is a question, and the way\n out of a question is an answer, not a close button. */}\n <WidgetButton\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n className=\"-mt-0.5 -mr-1 text-muted-foreground\"\n disabled={isSending}\n onClick={leave}\n >\n Skip\n </WidgetButton>\n </div>\n\n <div\n role=\"radiogroup\"\n aria-label=\"How did we do?\"\n className=\"flex items-center justify-center gap-1 pt-1.5\"\n onMouseLeave={() => setHovered(null)}\n >\n {STARS.map((value) => (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={picked === value}\n aria-label={`${value} of ${RATING_MAX_STARS}`}\n disabled={isSending}\n onMouseEnter={() => setHovered(value)}\n onFocus={() => setHovered(value)}\n onBlur={() => setHovered(null)}\n onClick={() => void choose(value)}\n className={cn(\n \"rounded-md p-1 outline-none transition-transform duration-150 ease-out\",\n \"hover:scale-115 focus-visible:ring-3 focus-visible:ring-ring/50\",\n \"active:scale-95 disabled:pointer-events-none\",\n \"motion-reduce:transition-none\",\n )}\n >\n <Star\n // A pick lights the row up one star at a time, left to\n // right. Only a pick: a stagger under the pointer would\n // read as the widget lagging behind the mouse.\n style={{\n transitionDelay:\n hovered === null && picked !== null\n ? `${(value - 1) * STAR_STAGGER_MS}ms`\n : undefined,\n }}\n className={cn(\n \"size-6 transition-colors duration-200 ease-out motion-reduce:transition-none\",\n value <= shown\n ? \"text-foreground\"\n : \"text-muted-foreground/30\",\n )}\n />\n </button>\n ))}\n </div>\n\n <Collapse isOpen={picked !== null}>\n <div className=\"flex flex-col gap-2 pt-2\">\n <Textarea\n value={feedback}\n onChange={(event) => setFeedback(event.target.value)}\n placeholder=\"Anything to add? Optional\"\n aria-label=\"Anything to add, optional\"\n rows={2}\n maxLength={RATING_FEEDBACK_MAX_LENGTH}\n disabled={isSending}\n // The field's own shell, over the card's tint rather than in\n // it, so the box to write in reads as a box to write in.\n className={cn(\n TEXT_FIELD_SHELL,\n \"max-h-24 min-h-16 bg-card px-2.5 py-2\",\n )}\n />\n {/* Never held shut by an empty box. The words are the optional\n half of this, and a button that refuses to finish without\n them is a required field in a hat. */}\n <WidgetButton\n type=\"button\"\n size=\"sm\"\n className=\"self-end\"\n disabled={isSending}\n onClick={() => void finish()}\n >\n {isSending\n ? \"Sending\"\n : feedback.trim().length === 0\n ? \"Done\"\n : \"Send\"}\n </WidgetButton>\n </div>\n </Collapse>\n\n <Collapse isOpen={error !== null}>\n <p className=\"pt-1.5 text-center text-xs text-destructive\">\n {error}\n </p>\n </Collapse>\n </div>\n </Collapse>\n\n <Collapse isOpen={isDone}>\n <p className=\"py-3 text-center text-sm font-medium\">\n Thanks for the feedback.\n </p>\n </Collapse>\n </div>\n </Collapse>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * How long one takes to open or close. Anything that has to act after a\n * collapse has finished reads this rather than guessing, so the two cannot\n * drift; it matches the `duration-200` below.\n */\nexport const COLLAPSE_MS = 200;\n\n/**\n * A section that opens and closes rather than appearing and disappearing.\n *\n * The height is a grid row travelling between nothing and whatever the\n * contents want to be, which is the one way to animate to `auto` without\n * measuring anything on every frame. The contents keep their own size\n * throughout and are clipped rather than squashed, so words never reflow\n * mid animation.\n *\n * Closed, it is inert: a keyboard cannot land in a section that is not on\n * screen, and nothing inside one can be clicked through the clip.\n *\n * No gap between this and its neighbours. A closed section is zero pixels\n * tall but a flex gap around it is not, so spacing belongs inside the\n * contents; otherwise closing one leaves a hole where it used to be.\n */\nexport function Collapse({\n isOpen,\n id,\n children,\n className,\n}: {\n isOpen: boolean;\n /** For whatever toggles it to point at with `aria-controls`. */\n id?: string;\n children: ReactNode;\n className?: string;\n}) {\n return (\n <div\n id={id}\n inert={isOpen ? undefined : true}\n className={cn(\n \"grid transition-[grid-template-rows,opacity] duration-200 ease-out motion-reduce:transition-none\",\n isOpen ? \"grid-rows-[1fr] opacity-100\" : \"grid-rows-[0fr] opacity-0\",\n className,\n )}\n >\n <div className=\"overflow-hidden\">{children}</div>\n </div>\n );\n}\n","import { UserCircle } from \"@/components/icons\";\n\n/**\n * A quiet line about where the conversation stands, rather than about the\n * last thing said in it.\n *\n * Above the composer rather than under the header, for the same reason the\n * inbox puts its own status line there: the question it settles is who writes\n * the next reply, and that belongs next to the box you would write it in.\n *\n * Not a live region. The handoff arrives as a message too, in a thread that\n * already announces itself, and a screen reader should hear that once.\n */\nexport function WidgetAwaitingHuman() {\n return (\n <p className=\"flex animate-in items-center justify-center gap-1.5 px-4 pb-1 text-xs text-muted-foreground duration-200 ease-out fade-in-0 slide-in-from-bottom-1 motion-reduce:animate-none\">\n <UserCircle aria-hidden className=\"size-3.5\" />\n Waiting for a teammate\n </p>\n );\n}\n","\"use client\";\n\nimport {\n MessageScroller,\n MessageScrollerButton,\n MessageScrollerContent,\n MessageScrollerItem,\n MessageScrollerProvider,\n MessageScrollerViewport,\n} from \"@/components/ui/message-scroller\";\nimport { groupMessages, withinRun } from \"@/lib/message-groups\";\nimport { cn } from \"@/lib/utils\";\nimport type { DragHandlers } from \"./use-launcher-drag\";\nimport { useStackShift } from \"./use-stack-shift\";\nimport { WidgetComposer } from \"./widget-composer\";\nimport { WidgetEmpty } from \"./widget-empty\";\nimport { WidgetHeader } from \"./widget-header\";\nimport { WidgetLoading } from \"./widget-loading\";\nimport { WidgetLocked } from \"./widget-locked\";\nimport { WidgetDivider, WidgetMessage } from \"./widget-message\";\nimport { WidgetRating } from \"./widget-rating\";\nimport { WidgetAwaitingHuman } from \"./widget-status\";\nimport type {\n SupportMessage,\n SupportPresence,\n SupportRating,\n} from \"./types\";\n\n/**\n * What keeps a run going: the same voice, close together, and no divider\n * cutting in. The agent is compared by id rather than by side, so a handover\n * from the AI to a person always starts a fresh run and says so. A new\n * conversation always does too, whoever is speaking either side of it.\n */\nfunction joinsPreviousTurn(message: SupportMessage, previous: SupportMessage) {\n return (\n !message.dayLabel &&\n !message.startsConversation &&\n message.sender === previous.sender &&\n message.agent?.id === previous.agent?.id &&\n withinRun(previous.sentAt, message.sentAt)\n );\n}\n\n/**\n * The support panel a visitor sees on a host's site: who is around, the\n * thread, and a box to write in.\n *\n * It fills whatever it is given rather than picking its own size, so the same\n * component works as a floating bubble on desktop, a full screen sheet on a\n * phone, and a framed preview in the gallery. Whoever mounts it decides the\n * box; this decides what goes in it.\n *\n * Uncontrolled on purpose for now: `messages` come in, `onSend` goes out, and\n * nothing here holds a thread of its own. That is the seam the SDK will sit on\n * once this is wired to a real conversation.\n */\nexport function SupportWidget({\n presence,\n messages,\n onSend,\n onTypingChange,\n onClose,\n isExpanded = false,\n onToggleExpanded,\n isLoading = false,\n isLocked = false,\n onSignIn,\n askForEmail = false,\n onSubmitEmail,\n isSending = false,\n awaitingHuman = false,\n rating,\n notice,\n showBadge = true,\n grabHandlers,\n isMoving = false,\n className,\n}: {\n presence: SupportPresence;\n messages: SupportMessage[];\n /** Awaited by the composer, which keeps the draft if it rejects. */\n onSend?: (body: string, files: File[]) => unknown;\n /** The visitor's own typing, throttled by the composer. */\n onTypingChange?: (isTyping: boolean) => unknown;\n /** Omit to hide the close button, for a widget that is always on the page. */\n onClose?: () => void;\n /** Standing taller than it normally does. */\n isExpanded?: boolean;\n /**\n * Omit to hide the control. Only whoever owns the box the panel is drawn in\n * can grow it, so a widget that fills a frame it was given does not offer it.\n */\n onToggleExpanded?: () => void;\n /** Holds the mark while the conversation is on its way. */\n isLoading?: boolean;\n /**\n * Nobody is signed in, on a host that only takes questions from people who\n * are. The thread and the composer make way for the invitation to sign in.\n */\n isLocked?: boolean;\n /** Takes the visitor to the host's own sign in, and gives it its button. */\n onSignIn?: () => void;\n /**\n * The composer asks for an email before a first message, and the starter\n * rows stand down while it does: a pick would send before the question\n * was answered.\n */\n askForEmail?: boolean;\n /** What the composer's question does with a good answer. */\n onSubmitEmail?: (email: string) => void;\n /** Holds the send button while a message is. */\n isSending?: boolean;\n /** The agent has called for a person and nobody has picked it up yet. */\n awaitingHuman?: boolean;\n /**\n * The conversation is over and nobody has asked how it went yet. Null the\n * rest of the time, which is most of it.\n */\n rating?: SupportRating | null;\n /** One line above the composer, for a send that went wrong. */\n notice?: string | null;\n showBadge?: boolean;\n /**\n * Makes the header the thing the panel is dragged around by. Omitted by\n * anything that frames the widget rather than floats it, which is most of\n * the places it turns up outside a host's page.\n */\n grabHandlers?: DragHandlers;\n /** Being dragged right now, so the header can hold the closed hand. */\n isMoving?: boolean;\n className?: string;\n}) {\n const stack = useStackShift(messages.length);\n return (\n <section\n aria-label={`${presence.name} support`}\n className={cn(\n // The widget keeps its own radius scale. The app's token can climb as\n // the chrome gets rounder without the widget changing shape under the\n // hosts embedding it.\n \"flex h-full w-full flex-col overflow-hidden rounded-xl border bg-card text-card-foreground [--radius:0.625rem]\",\n className,\n )}\n >\n <WidgetHeader\n presence={presence}\n onClose={onClose}\n isExpanded={isExpanded}\n onToggleExpanded={onToggleExpanded}\n grabHandlers={grabHandlers}\n isMoving={isMoving}\n />\n\n {isLoading ? (\n <WidgetLoading />\n ) : isLocked ? (\n /* After the loading rather than before it: the line names the host,\n so it waits for the name the same as everything else does. */\n <WidgetLocked\n orgName={presence.name}\n onSignIn={onSignIn}\n showBadge={showBadge}\n />\n ) : (\n <Conversation\n presence={presence}\n messages={messages}\n onSend={onSend}\n onTypingChange={onTypingChange}\n askForEmail={askForEmail}\n onSubmitEmail={onSubmitEmail}\n isSending={isSending}\n awaitingHuman={awaitingHuman}\n rating={rating}\n notice={notice}\n showBadge={showBadge}\n stackRef={stack}\n />\n )}\n </section>\n );\n}\n\n/**\n * Everything under the header. Split out so it mounts as one thing when the\n * conversation lands, which is what gives the whole lot a single fade in\n * rather than a thread and a composer arriving separately.\n */\nfunction Conversation({\n presence,\n messages,\n onSend,\n onTypingChange,\n askForEmail = false,\n onSubmitEmail,\n isSending = false,\n awaitingHuman = false,\n rating,\n notice,\n showBadge,\n stackRef,\n}: {\n presence: SupportPresence;\n messages: SupportMessage[];\n onSend?: (body: string, files: File[]) => unknown;\n onTypingChange?: (isTyping: boolean) => unknown;\n /** The composer asks for an email before a first message. */\n askForEmail?: boolean;\n /** What the composer's question does with a good answer. */\n onSubmitEmail?: (email: string) => void;\n isSending?: boolean;\n awaitingHuman?: boolean;\n rating?: SupportRating | null;\n notice?: string | null;\n showBadge: boolean;\n stackRef: (node: HTMLDivElement | null) => void;\n}) {\n const groups = groupMessages(messages, joinsPreviousTurn);\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col animate-in fade-in-0 duration-500 ease-out motion-reduce:animate-none\">\n {messages.length === 0 ? (\n <WidgetEmpty\n team={presence.team}\n orgName={presence.name}\n onPick={\n onSend === undefined\n ? undefined\n : (message) => void onSend(message, [])\n }\n isSending={isSending}\n // Held rather than taken away while the email is asked for: a row\n // would send before the question above it was answered, and rows\n // that leave and come back move everything above them twice.\n isWaiting={askForEmail}\n />\n ) : (\n /* The same scroller the inbox thread uses, so both sides of a\n conversation stick to the newest message the same way, and both grow\n the same button when you scroll back up.\n\n It keeps following the bottom while the panel is resizing, and it\n has to. A panel shrinking takes its top edge down past the thread,\n so a scroller left alone slides the newest message under the\n composer and has to catch up afterwards. Following it is what the\n scroller stops easing for, so this tracks frame by frame. */\n <MessageScrollerProvider>\n {/* h-auto so the scroller takes the space the header and composer\n leave, rather than the full column its own `size-full` asks for. */}\n <MessageScroller className=\"h-auto min-h-0 flex-1\">\n <MessageScrollerViewport\n // A log with a polite live region, so a reply is announced as it\n // lands without pulling focus out of the box being typed in.\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n aria-label=\"Conversation\"\n className=\"px-3 py-2\"\n >\n {/* justify-end so a short thread sits on the composer rather than\n hanging from the header with a field of nothing under it. The\n content is already at least a viewport tall, so this only\n decides where the slack goes: above the first message, not\n below the last.\n\n The space between messages is on the items rather than here,\n since a message carrying on the one above it sits closer to\n it than one starting a new turn. */}\n <MessageScrollerContent\n ref={stackRef}\n className=\"justify-end gap-0\"\n >\n {messages.map((message, index) => (\n <MessageScrollerItem\n key={message.id}\n messageId={message.id}\n // The scroller skips rendering off screen items and holds\n // 10rem open for each one until it arrives. That is a fair\n // guess in the inbox, where the column is wide and a\n // message is tall. Here it is roughly double: a bubble in a\n // panel this narrow is nearer 4rem, so every item resized\n // the moment it scrolled into view and the whole thread\n // jumped. A support thread is short enough that skipping\n // any of it buys nothing anyway.\n className={cn(\n \"flex flex-col gap-4 [content-visibility:visible] first:pt-0\",\n groups[index].isFirst ? \"pt-4\" : \"pt-1\",\n )}\n >\n <WidgetDivider message={message} />\n <WidgetMessage message={message} group={groups[index]} />\n </MessageScrollerItem>\n ))}\n </MessageScrollerContent>\n </MessageScrollerViewport>\n\n {/* Outside the viewport: it is positioned against the scroller, so\n inside it would scroll away with the messages. */}\n <MessageScrollerButton />\n </MessageScroller>\n </MessageScrollerProvider>\n )}\n\n {/* The question a finished thread asks. Never at the same time as the\n line below it: one is a conversation that is over and the other is\n one waiting on a person. */}\n {rating && <WidgetRating rating={rating} />}\n\n {/* Above the failed send, since it is the older of the two facts and\n the one that is still true after a retry works. */}\n {awaitingHuman && <WidgetAwaitingHuman />}\n\n {/* A send that failed says so right where the retry happens. */}\n {notice && (\n <p className=\"animate-in px-4 pb-1 text-center text-xs text-destructive fade-in duration-150\">\n {notice}\n </p>\n )}\n\n <WidgetComposer\n onSend={onSend}\n onTypingChange={onTypingChange}\n askForEmail={askForEmail}\n onSubmitEmail={onSubmitEmail}\n isSending={isSending}\n showBadge={showBadge}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport {\n getDefaultSpot,\n getSpot,\n metricsFor,\n setSpot,\n spotFrom,\n spotFromPanel,\n subscribeSpot,\n type Bounds,\n type Size,\n} from \"./launcher-position\";\nimport { prefersReducedMotion } from \"./motion\";\n\n/** Further than this and it is a drag. Under it, it is a click that wobbled. */\nconst DRAG_THRESHOLD = 5;\n\n/**\n * What a press takes hold of: the button while it is closed, and the panel\n * itself, by its header, once it is open.\n *\n * Both move the same box. The difference is what is being kept on the page\n * while it travels, and what the spot is read back off when it lands.\n */\nexport type DragSubject = \"button\" | \"panel\";\n\n/** What a surface wears to become something the widget can be dragged by. */\nexport type DragHandlers = {\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n onPointerMove: (event: ReactPointerEvent<HTMLElement>) => void;\n onPointerUp: (event: ReactPointerEvent<HTMLElement>) => void;\n onPointerCancel: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\n/**\n * A press that landed on a control belongs to that control.\n *\n * Only the panel needs asking. The button is the handle and the whole of it,\n * so a press anywhere on it is a press on the thing being dragged; the header\n * is a strip with a close button and a row of faces on it, and grabbing the\n * panel by the close button would be a drag that shuts it.\n */\nfunction isControl(target: EventTarget | null): boolean {\n return (\n target instanceof Element &&\n target.closest(\"a, button, input, select, textarea\") !== null\n );\n}\n\n/** The flight to the edge once it is let go. Matches --ease-spring. */\nconst SNAP_MS = 420;\nconst SNAP_EASING = \"cubic-bezier(0.34, 1.45, 0.64, 1)\";\n\n/**\n * The button's height inside the box, which the clip and the button both read.\n * A custom property because it inherits: one write on the box reaches the\n * panel, the shadow and the button, and none of them has to be told twice.\n */\nexport const BUTTON_Y = \"--median-button-y\";\n\n/** Everything the drag needs, measured once, while it is still standing still. */\ntype Grip = {\n subject: DragSubject;\n grabX: number;\n grabY: number;\n startX: number;\n startY: number;\n bounds: Bounds;\n margin: number;\n /** The button, which the spot is always defined in terms of. */\n size: Size;\n box: Size;\n /** The one actually travelling: the button, or the whole box. */\n dragged: Size;\n /** Where that one was before any of this, and where it is now. */\n resting: { x: number; y: number };\n at: { x: number; y: number };\n moved: boolean;\n};\n\n/**\n * Dragging the launcher, and the edge it settles against.\n *\n * The box that holds the panel is positioned to contain the button, and the\n * button is pinned inside it, so moving one moves both. The closed panel is a\n * circle sitting exactly under the button; if only the button travelled it\n * would slide off its own shadow.\n *\n * Nothing goes through React state while a finger is down. The offset is\n * written straight onto the box, because a `setState` per pointermove renders\n * the whole panel underneath, and the panel is an entire conversation. React\n * hears the spot once, at the end.\n *\n * The resting geometry cannot be written in CSS, because the button's height\n * inside the box is the difference between two things measured against\n * different boxes. So it is measured and written, before paint, and the style\n * carries a plain calc as a fallback for the frame before that happens, which\n * is the one the server rendered.\n */\nexport function useLauncherDrag({\n boxRef,\n buttonRef,\n margin,\n enabled,\n subject,\n}: {\n boxRef: RefObject<HTMLDivElement | null>;\n buttonRef: RefObject<HTMLButtonElement | null>;\n /** Any CSS length. How far off the edges it sits. */\n margin: string;\n /** Off when there is nothing on the page to take hold of. */\n enabled: boolean;\n /** Which of the two a press is grabbing, which is to say whether it is open. */\n subject: DragSubject;\n}) {\n const spot = useSyncExternalStore(subscribeSpot, getSpot, getDefaultSpot);\n\n // Two renders a drag, at the ends of it. Never one per move. It stays true\n // through the flight as well, because the clip is keyed to the button's\n // height and that changes as it lands; transitioning between the two would\n // wipe the panel across the box on the way.\n const [isMoving, setIsMoving] = useState(false);\n\n const grip = useRef<Grip | null>(null);\n /** Set by the drag that just ended, read by the click it turns into. */\n const justDragged = useRef(false);\n\n /** The space it lives in: the page, or whatever is positioning it. */\n const measure = useCallback((): {\n bounds: Bounds;\n margin: number;\n size: Size;\n box: Size;\n } | null => {\n const box = boxRef.current;\n const button = buttonRef.current;\n if (!box) return null;\n\n const parent = box.offsetParent;\n const rect =\n parent instanceof HTMLElement\n ? parent.getBoundingClientRect()\n : new DOMRect(0, 0, window.innerWidth, window.innerHeight);\n const boxRect = box.getBoundingClientRect();\n\n return {\n bounds: {\n left: rect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n },\n // Asked of the resolved style rather than parsed out of the string we\n // were handed, so a margin in any unit at all comes back in pixels.\n margin: Math.round(\n Number.parseFloat(getComputedStyle(box).getPropertyValue(spot.side)) ||\n 0,\n ),\n // Offset sizes, so a button mid press is not measured through whatever\n // scale it happens to be wearing.\n //\n // No button at all is a widget the host opens themselves. Nothing\n // hangs below the panel then, so it is a button of no size: the same\n // arithmetic, with the box parked against the bottom margin.\n size: button\n ? { width: button.offsetWidth, height: button.offsetHeight }\n : { width: 0, height: 0 },\n // The box gets the fractional one instead, and the difference is the\n // whole of whether a resize is smooth. Its top is worked out as its\n // bottom edge minus its height, so a height rounded to a whole pixel\n // against a box that is mid animation puts the bottom edge up to half a\n // pixel out, in a different direction on every frame. The panel shimmers\n // in place rather than growing. Nothing scales the box, so a rect is as\n // safe here as an offset and says the same thing more precisely.\n box: { width: boxRect.width, height: boxRect.height },\n };\n }, [boxRef, buttonRef, spot.side]);\n\n /**\n * Writes the resting geometry onto the nodes. Before paint on the way in,\n * and again whenever the space it is measured against changes.\n */\n const place = useCallback(() => {\n const box = boxRef.current;\n const taken = measure();\n if (!box || taken === null) return;\n\n const metrics = metricsFor(\n spot,\n taken.bounds,\n taken.size,\n taken.box.height,\n taken.margin,\n );\n\n box.style.top = `${metrics.boxTop - taken.bounds.top}px`;\n box.style.setProperty(BUTTON_Y, `${metrics.buttonInBox}px`);\n }, [boxRef, measure, spot]);\n\n useLayoutEffect(place, [place]);\n\n useEffect(() => {\n window.addEventListener(\"resize\", place);\n return () => window.removeEventListener(\"resize\", place);\n }, [place]);\n\n // Its own size counts as the space changing too, and this is the one that\n // moves on its own. The box hangs upward from the button, so where its top\n // belongs is worked out from how tall it is, and a panel growing into its\n // expanded height has a different answer on every frame of the way there.\n // Left to the effect above it would get the final answer on the first frame,\n // and the panel would jump off the button and then grow back down onto it.\n useEffect(() => {\n const box = boxRef.current;\n if (!box || typeof ResizeObserver === \"undefined\") return;\n\n // Nothing here changes the box's size, so this cannot feed itself.\n const observer = new ResizeObserver(place);\n observer.observe(box);\n return () => observer.disconnect();\n }, [boxRef, place]);\n\n /** Puts the box back where `place` left it, with no animation. */\n const settle = useCallback(() => {\n const box = boxRef.current;\n if (box) box.style.transform = \"\";\n }, [boxRef]);\n\n /**\n * The page while something is being dragged across it: nothing selectable,\n * and the closed hand everywhere.\n *\n * Both belong on the body rather than on what is being held, because the\n * pointer spends the whole drag over everything else. Left to the handle's\n * own classes the cursor turns back into a caret the moment it crosses the\n * thread, and the browser reads the gesture as a sweep through the host's\n * text, which leaves the next press picking up that selection instead of\n * the widget.\n *\n * Written and cleared in one place because these outlive the widget: a drag\n * that ended without this running leaves somebody else's page unselectable\n * and wearing a cursor that is not theirs.\n */\n const holdPointer = useCallback((held: boolean) => {\n document.body.style.userSelect = held ? \"none\" : \"\";\n document.body.style.cursor = held ? \"grabbing\" : \"\";\n if (held) window.getSelection()?.removeAllRanges();\n }, []);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n justDragged.current = false;\n\n // A press starts from nothing held. If the last one never heard its own\n // release, this is where the page gets its cursor and its selection\n // back, rather than the next drag inheriting them.\n if (grip.current !== null) {\n grip.current = null;\n holdPointer(false);\n setIsMoving(false);\n }\n\n if (!enabled || !event.isPrimary) return;\n // A right click is a menu, not a move.\n if (event.pointerType === \"mouse\" && event.button !== 0) return;\n if (subject === \"panel\" && isControl(event.target)) return;\n\n // The button when it is closed, the whole box when it is open. Either\n // way the box is what travels; this is only what is being aimed.\n const moving = subject === \"panel\" ? boxRef.current : buttonRef.current;\n const taken = measure();\n if (moving === null || taken === null) return;\n\n // Refused so the press cannot begin a selection, or pick up one already\n // lying around and drag that instead. Focus is handed back by hand,\n // since that was the other thing the default was going to do.\n event.preventDefault();\n // Only the button takes it. An open panel is being moved, not entered,\n // so whatever was half typed in the composer keeps the caret.\n if (subject === \"button\") buttonRef.current?.focus({ preventScroll: true });\n\n const rect = moving.getBoundingClientRect();\n grip.current = {\n subject,\n grabX: event.clientX - rect.left,\n grabY: event.clientY - rect.top,\n startX: event.clientX,\n startY: event.clientY,\n ...taken,\n dragged: subject === \"panel\" ? taken.box : taken.size,\n resting: { x: rect.left, y: rect.top },\n at: { x: rect.left, y: rect.top },\n moved: false,\n };\n\n event.currentTarget.setPointerCapture(event.pointerId);\n },\n [boxRef, buttonRef, enabled, holdPointer, measure, subject],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n const held = grip.current;\n const box = boxRef.current;\n if (held === null || box === null) return;\n\n if (!held.moved) {\n const travelled = Math.hypot(\n event.clientX - held.startX,\n event.clientY - held.startY,\n );\n if (travelled < DRAG_THRESHOLD) return;\n held.moved = true;\n holdPointer(true);\n setIsMoving(true);\n }\n\n // Kept inside the edges it can settle against. Arithmetic only:\n // everything it needs was measured on the way down.\n held.at = {\n x: clamp(\n event.clientX - held.grabX,\n held.bounds.left + held.margin,\n held.bounds.left +\n held.bounds.width -\n held.margin -\n held.dragged.width,\n ),\n y: clamp(\n event.clientY - held.grabY,\n held.bounds.top + held.margin,\n held.bounds.top +\n held.bounds.height -\n held.margin -\n held.dragged.height,\n ),\n };\n\n box.style.transform = `translate3d(${held.at.x - held.resting.x}px, ${held.at.y - held.resting.y}px, 0)`;\n },\n [boxRef, holdPointer],\n );\n\n /**\n * The end of a drag, wherever the news of it came from.\n *\n * Separate from the handler because a release is not reliably an event on\n * the thing that was grabbed. Pointer capture usually delivers it there, but\n * a capture lost to the window manager, a switch to another window mid\n * press, or an element that went away underneath one all end the gesture\n * with nothing firing on the handle at all. Every one of those used to leave\n * the page holding a grabbing cursor and nothing selectable, with no way\n * back except starting another drag.\n *\n * Nothing to end is not a problem to report: the flight home runs after the\n * grip is let go, and the same release arrives twice on the way out.\n */\n const finishDrag = useCallback(() => {\n const held = grip.current;\n if (held === null) return;\n grip.current = null;\n\n holdPointer(false);\n\n const box = boxRef.current;\n if (!held.moved || box === null) {\n setIsMoving(false);\n return;\n }\n\n justDragged.current = true;\n\n // Where it landed, read back as a spot. Which end of the widget that is\n // asked of is the whole of the difference between the two drags.\n const target =\n held.subject === \"panel\"\n ? spotFromPanel(held.at, held.bounds, held.size, held.box, held.margin)\n : spotFrom(held.at, held.bounds, held.size, held.margin);\n\n const home = metricsFor(\n target,\n held.bounds,\n held.size,\n held.box.height,\n held.margin,\n );\n // Where the thing that travelled belongs once it is there, so the flight\n // below is exactly the gap between that and the finger.\n const from = {\n x:\n held.at.x -\n (target.side === \"left\"\n ? held.bounds.left + held.margin\n : held.bounds.left +\n held.bounds.width -\n held.margin -\n held.dragged.width),\n y: held.at.y - (held.subject === \"panel\" ? home.boxTop : home.buttonY),\n };\n\n // All of this is one frame, and the order is the whole trick.\n //\n // Committing the spot synchronously runs the layout effect above with it,\n // so the box is already positioned where it is going before anything is\n // painted. Clearing the transform then puts it there, which is not where\n // the finger left it, and the animation starts from exactly the gap\n // between the two. The first frame drawn still has whatever was being\n // held under the finger, and the rest of them carry it home.\n flushSync(() => setSpot(target));\n settle();\n\n if (prefersReducedMotion()) {\n setIsMoving(false);\n return;\n }\n\n const flight = box.animate(\n [\n { transform: `translate3d(${from.x}px, ${from.y}px, 0)` },\n { transform: \"none\" },\n ],\n { duration: SNAP_MS, easing: SNAP_EASING },\n );\n // Only once it has landed: the clip must not start transitioning between\n // heights while one of them is still travelling.\n flight.finished.catch(() => {}).finally(() => setIsMoving(false));\n }, [boxRef, holdPointer, settle]);\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n finishDrag();\n },\n [finishDrag],\n );\n\n // The safety net, live only while something is actually being dragged. A\n // release anywhere at all ends it, and so does the window losing focus,\n // which is the one that catches a press abandoned to another app.\n useEffect(() => {\n if (!isMoving) return;\n\n const end = () => finishDrag();\n window.addEventListener(\"pointerup\", end);\n window.addEventListener(\"pointercancel\", end);\n window.addEventListener(\"blur\", end);\n return () => {\n window.removeEventListener(\"pointerup\", end);\n window.removeEventListener(\"pointercancel\", end);\n window.removeEventListener(\"blur\", end);\n };\n }, [isMoving, finishDrag]);\n\n const dragHandlers: DragHandlers = {\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: handlePointerUp,\n onPointerCancel: handlePointerUp,\n };\n\n // Everything above was measured against a page that is no longer that size.\n // Nothing to rescue: it goes back to wherever `place` puts it.\n useEffect(() => {\n function abandon() {\n if (grip.current === null) return;\n grip.current = null;\n holdPointer(false);\n settle();\n setIsMoving(false);\n }\n\n window.addEventListener(\"resize\", abandon);\n return () => {\n window.removeEventListener(\"resize\", abandon);\n // A widget that goes away mid drag must not leave the host's whole page\n // unselectable and wearing a cursor it never asked for. This is their\n // body, not ours.\n holdPointer(false);\n };\n }, [holdPointer, settle]);\n\n return {\n side: spot.side,\n /** Being dragged, or on its way to an edge. Nothing may transition. */\n isMoving,\n /** The side only. Height is measured and written straight to the node. */\n style: { [spot.side]: margin } as { left?: string; right?: string },\n /** True for the click that ended a drag, so it does not also open. */\n swallowClick: () => {\n if (!justDragged.current) return false;\n justDragged.current = false;\n return true;\n },\n /**\n * The same four handlers whichever end is being held. Both ends can wear\n * them at once: only one of the two is ever reachable, since the button is\n * inert while the panel is up and the panel is inert while it is down.\n */\n dragHandlers,\n };\n}\n\nfunction clamp(value: number, low: number, high: number): number {\n return Math.min(Math.max(value, low), Math.max(low, high));\n}\n","\"use client\";\n\nimport {\n useLayoutEffect,\n useState,\n useSyncExternalStore,\n type RefObject,\n} from \"react\";\nimport { usePageLock } from \"./use-page-lock\";\n\n/**\n * When the panel stops floating and takes the screen.\n *\n * Tailwind's `sm` breakpoint, written out, so this hook and any `max-sm:`\n * styles riding along with it change their minds at the same width.\n */\nconst PHONE = \"(max-width: 40rem)\";\n\n/**\n * How long the panel keeps following the visual viewport after it last heard\n * from it.\n *\n * The keyboard takes about a quarter of a second to come up and reports its\n * progress two or three times on the way, so a panel that moved only when it\n * was told would arrive in two or three jumps. This keeps it measuring every\n * frame for a beat afterwards instead, which is what turns those jumps into\n * the panel riding the keyboard up.\n */\nconst SETTLE_MS = 400;\n\n/**\n * How much of the visible height has to go missing before it is the keyboard\n * and not the browser's own chrome sliding away.\n */\nconst KEYBOARD_PX = 96;\n\nfunction subscribePhone(onChange: () => void) {\n const media = window.matchMedia(PHONE);\n media.addEventListener(\"change\", onChange);\n return () => media.removeEventListener(\"change\", onChange);\n}\n\nconst isPhoneNow = () => window.matchMedia(PHONE).matches;\n\n/** The server's answer. Nothing is open on the server, so nothing is lost. */\nconst isPhoneOnServer = () => false;\n\n/**\n * Whether the open panel should be the whole screen rather than a floating\n * card, and everything that has to be true while it is.\n *\n * A phone has no room for a card floating over a page: the card is nearly the\n * page already, and the margins around it are the only thing the extra rem\n * buys. So under `sm` the panel opens edge to edge instead, the way every\n * sheet on a phone does.\n *\n * Only when the widget is the viewport's, though. The gallery pins its\n * previews inside a frame with `absolute`, and a preview that burst out of\n * its frame to swallow the page would be demonstrating exactly the wrong\n * thing. `offsetParent` is the tell: a `fixed` box answers null, a framed one\n * answers with its frame. An ancestor wearing a transform also answers, and\n * should: a box positioned against somebody's transformed container is not\n * positioned against the screen, so it has no business covering it.\n *\n * While the sheet is up this also does two jobs the floating panel never\n * needed:\n *\n * - The panel is sized to `visualViewport` rather than to `inset-0`, and keeps\n * measuring for a beat after each report so it rides the keyboard up instead\n * of arriving in two jumps. The keyboard shrinks the visual viewport and not\n * the layout one, so a panel pinned to the layout viewport keeps its composer\n * underneath the keyboard, which is the one place the thing being typed into\n * cannot be. Written straight onto the node, the way the drag writes its\n * travel: a render per frame of that would run the whole conversation through\n * React to move an edge.\n *\n * - The host's page is pinned where it stands, by `usePageLock`. A full screen\n * sheet with a live page rumbling underneath it reads as broken, and a page\n * the keyboard is free to scroll takes the sheet's own footing with it.\n */\nexport function useWidgetSheet({\n boxRef,\n panelRef,\n isOpen,\n}: {\n boxRef: RefObject<HTMLDivElement | null>;\n panelRef: RefObject<HTMLDivElement | null>;\n isOpen: boolean;\n}): boolean {\n const isPhone = useSyncExternalStore(\n subscribePhone,\n isPhoneNow,\n isPhoneOnServer,\n );\n\n // Asked once the box is on the page, and asked again if the viewport\n // changed, since that is the only thing here that changes the answer's\n // consequences. The layout effect answers before anything is painted.\n const [isFramed, setIsFramed] = useState(false);\n useLayoutEffect(() => {\n setIsFramed(boxRef.current?.offsetParent != null);\n }, [boxRef, isPhone]);\n\n const isSheet = isPhone && !isFramed;\n const isUp = isSheet && isOpen;\n\n useLayoutEffect(() => {\n if (!isUp) return;\n const panel = panelRef.current;\n const viewport = window.visualViewport;\n if (!panel || !viewport) return;\n\n let frame = 0;\n let until = 0;\n let top = -1;\n let height = -1;\n let keyboard = \"\";\n\n // Exactly what can be seen, top edge included: the keyboard coming up can\n // shove the layout viewport as well as shrink the visible one, and\n // `offsetTop` is the sum of that shove.\n //\n // Whole pixels, and only ever written when they change. Measuring runs\n // every frame while the keyboard moves, and the browser cannot tell a\n // style it has already been given from a new one: it lays the panel out\n // again either way, and a fractional height rewritten sixty times a second\n // is the thread re-wrapping sixty times a second.\n const fit = () => {\n const nextTop = Math.round(viewport.offsetTop);\n const nextHeight = Math.round(viewport.height);\n if (nextTop === top && nextHeight === height) return;\n top = nextTop;\n height = nextHeight;\n\n panel.style.top = `${top}px`;\n panel.style.height = `${height}px`;\n panel.style.bottom = \"auto\";\n\n // The home bar's inset is only worth room while the home bar is what is\n // down there. With the keyboard up the foot of the panel is the top of\n // the keyboard, and the inset is a strip of nothing between the two.\n const next = height < window.innerHeight - KEYBOARD_PX ? \"up\" : \"down\";\n if (next === keyboard) return;\n keyboard = next;\n panel.dataset.keyboard = next;\n };\n\n const follow = () => {\n fit();\n frame = performance.now() < until ? requestAnimationFrame(follow) : 0;\n };\n\n // The viewport reports where it has got to, not where it is going. Each\n // report is taken as a sign it is still moving, and the panel measures for\n // itself until the reports stop coming.\n const track = () => {\n until = performance.now() + SETTLE_MS;\n if (frame === 0) frame = requestAnimationFrame(follow);\n };\n\n fit();\n viewport.addEventListener(\"resize\", track);\n viewport.addEventListener(\"scroll\", track);\n // A tap on the composer is the first anybody knows about a keyboard: the\n // viewport says nothing until it has already started moving.\n panel.addEventListener(\"focusin\", track);\n\n return () => {\n if (frame !== 0) cancelAnimationFrame(frame);\n viewport.removeEventListener(\"resize\", track);\n viewport.removeEventListener(\"scroll\", track);\n panel.removeEventListener(\"focusin\", track);\n // Back to the classes' `inset-0`, for the floating panel these would\n // otherwise misplace.\n panel.style.top = \"\";\n panel.style.height = \"\";\n panel.style.bottom = \"\";\n delete panel.dataset.keyboard;\n };\n }, [panelRef, isUp]);\n\n usePageLock(isUp);\n\n return isSheet;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\n\n/**\n * Holds the host's page still underneath a full screen sheet.\n *\n * `overflow: hidden` is not a lock on a phone. Tapping a field inside a fixed\n * panel makes the browser scroll the page to bring the field above the\n * keyboard, and it scrolls a page that only said it had no overflow: the sheet\n * stays where it is, the page slides about behind it, and everything pinned to\n * the visual viewport chases that a frame late. That is the shudder.\n *\n * So the page is pinned instead, fixed at the offset it is already scrolled to.\n * It looks exactly the same and there is nothing left to scroll, which is the\n * only answer the keyboard takes. Letting go puts the offset back first, so the\n * page never flashes at the top on the way out.\n *\n * Width is deliberately not set. A fixed box with both edges pinned already\n * works out to the width the page had, margins and all, and saying `100%` on\n * top of that hangs the host's own margin off the right hand side.\n *\n * Everything it touches is written down first and put back after. This is\n * somebody else's body, and they may have had an opinion about all of it.\n */\nexport function usePageLock(isLocked: boolean) {\n useEffect(() => {\n if (!isLocked) return;\n\n const { style } = document.body;\n const held = {\n position: style.position,\n top: style.top,\n left: style.left,\n right: style.right,\n overflow: style.overflow,\n };\n const scrollY = window.scrollY;\n\n style.position = \"fixed\";\n style.top = `${-scrollY}px`;\n style.left = \"0\";\n style.right = \"0\";\n style.overflow = \"hidden\";\n\n return () => {\n style.position = held.position;\n style.top = held.top;\n style.left = held.left;\n style.right = held.right;\n style.overflow = held.overflow;\n // Instant, or a host who asked for smooth scrolling watches their page\n // sail back down from the top while the sheet is still coming off it.\n window.scrollTo({ top: scrollY, behavior: \"instant\" });\n };\n }, [isLocked]);\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\n/**\n * How long to keep looking for something that may not be on the page yet.\n * A navigation is usually still resolving when the instruction lands, so the\n * element the tool means is often a route change away.\n */\nconst FIND_TIMEOUT_MS = 4_000;\n\n/** How long the ring stays once it has found something. */\nconst HOLD_MS = 2_600;\n\n/** The fade at the end, which is also how long the node outlives the hold. */\nconst FADE_MS = 300;\n\n/** Above the host's own chrome. Their z-indexes are not ours to guess at. */\nconst LAYER = 2_147_483_000;\n\nfunction prefersReducedMotion(): boolean {\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/**\n * A ring drawn over something on the host's page, because one of their tools\n * asked for it to be pointed at.\n *\n * Nothing on their page is touched. The ring is a box of our own, positioned\n * over the element's rectangle and following it every frame, so a page that\n * scrolls, resizes or animates underneath keeps the ring where the thing is,\n * and there is no style of theirs to put back afterwards.\n *\n * It also waits. The instruction rides the same reply that moves the page, so\n * the element it names is usually a route change away and not in the document\n * yet; this keeps looking for a few seconds and gives up quietly rather than\n * ringing the wrong thing or nothing at all.\n *\n * In `document.body` rather than where the widget sits, since a `fixed` box\n * inside a host container that happens to carry a transform is fixed to that\n * container instead of to the window, and this one has to line up with an\n * element anywhere on their page.\n */\nexport function WidgetSpotlight({ selector }: { selector: string }) {\n const [isShown, setIsShown] = useState(false);\n const [isLeaving, setIsLeaving] = useState(false);\n const ring = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n let target: Element | null = null;\n let frame = 0;\n let startedAt = 0;\n let foundAt = 0;\n let stopped = false;\n let leaveTimer: ReturnType<typeof setTimeout> | undefined;\n\n function find(): Element | null {\n try {\n return document.querySelector(selector);\n } catch {\n // Not a selector at all. Median checks the shape of one before it is\n // stored, but only a browser can say whether it parses.\n console.error(\n `Median: a tool asked to highlight ${selector}, which is not a valid CSS selector.`,\n );\n stopped = true;\n return null;\n }\n }\n\n function tick(now: number) {\n if (stopped) return;\n if (startedAt === 0) startedAt = now;\n\n if (target === null) {\n target = find();\n if (stopped) return;\n\n if (target === null) {\n // Still not there. It may be one route change behind us.\n if (now - startedAt > FIND_TIMEOUT_MS) return;\n frame = requestAnimationFrame(tick);\n return;\n }\n\n foundAt = now;\n target.scrollIntoView({\n behavior: prefersReducedMotion() ? \"auto\" : \"smooth\",\n block: \"center\",\n });\n setIsShown(true);\n }\n\n // Written straight onto the node rather than held in state: this runs\n // every frame for a couple of seconds, and a re-render per frame to\n // move one box is a cost the host's page would pay for nothing.\n const node = ring.current;\n if (node !== null) {\n const rect = target.getBoundingClientRect();\n node.style.transform = `translate(${rect.left}px, ${rect.top}px)`;\n node.style.width = `${rect.width}px`;\n node.style.height = `${rect.height}px`;\n }\n\n if (now - foundAt > HOLD_MS) {\n setIsLeaving(true);\n leaveTimer = setTimeout(() => setIsShown(false), FADE_MS);\n return;\n }\n frame = requestAnimationFrame(tick);\n }\n\n frame = requestAnimationFrame(tick);\n return () => {\n stopped = true;\n cancelAnimationFrame(frame);\n clearTimeout(leaveTimer);\n };\n }, [selector]);\n\n if (!isShown || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n ref={ring}\n aria-hidden\n // Portalled to the body, outside the launcher's box, so it carries the\n // published stylesheet's scope hook itself.\n data-median-widget=\"\"\n style={{ zIndex: LAYER, top: 0, left: 0 }}\n className=\"pointer-events-none fixed\"\n >\n {/* Two layers of the same box: one that holds the outline, and one\n that swells out of it and fades, which is the part the eye catches\n on a page somebody is already looking at. */}\n <span\n className={[\n \"absolute -inset-1 rounded-lg outline-2 outline-offset-0 outline-primary\",\n \"shadow-[0_0_0_6px_color-mix(in_oklch,var(--primary)_20%,transparent)]\",\n \"transition-opacity duration-300 ease-out motion-reduce:transition-none\",\n isLeaving ? \"opacity-0\" : \"opacity-100\",\n ].join(\" \")}\n />\n <span\n className={[\n \"absolute -inset-1 rounded-lg outline-2 outline-primary\",\n \"animate-ping opacity-60 motion-reduce:animate-none\",\n isLeaving ? \"hidden\" : \"\",\n ].join(\" \")}\n />\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"@/lib/utils\";\nimport { WidgetAvatar } from \"./widget-avatar\";\nimport type { SupportAgent } from \"./types\";\n\n/** How long it stays. Long enough to read twice, short enough to forgive. */\nconst STAY_MS = 5_000;\n\n/** The travel at either end. */\nconst MOVE_MS = 250;\n\n/** Above the host's own chrome, and above the ring it explains. */\nconst LAYER = 2_147_483_001;\n\n/**\n * A line at the foot of the page saying who moved it.\n *\n * A page changing under somebody who did not touch anything is the one thing\n * a widget can do that feels like it has been let loose, so it says so, by\n * name, where a browser already puts its own status line.\n *\n * Nothing to click: it cannot be in the way of whatever they came to do, and\n * it takes itself off. In `document.body` for the same reason the ring is: a\n * host container with a transform on it would otherwise capture the fixed\n * position and put this somewhere that is not the bottom of the window.\n */\nexport function WidgetToast({\n agent,\n children,\n}: {\n /** Who did it, so the line can say so with their own face on it. */\n agent: SupportAgent;\n children: React.ReactNode;\n}) {\n const [isShown, setIsShown] = useState(false);\n\n useEffect(() => {\n // Up on the frame after it mounts, so it rises into place rather than\n // being there suddenly.\n const frame = requestAnimationFrame(() => setIsShown(true));\n const timer = setTimeout(() => setIsShown(false), STAY_MS);\n return () => {\n cancelAnimationFrame(frame);\n clearTimeout(timer);\n };\n }, []);\n\n if (typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n // Portalled to the body, outside the launcher's box, so it carries the\n // published stylesheet's scope hook itself.\n data-median-widget=\"\"\n style={{ zIndex: LAYER, transitionDuration: `${MOVE_MS}ms` }}\n // A live region rather than a thing to find: somebody using a screen\n // reader is told the page moved without having to go looking for the\n // line that says so.\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n \"pointer-events-none fixed bottom-4 left-1/2 flex max-w-[calc(100vw-2rem)] items-center gap-2\",\n \"-translate-x-1/2 rounded-full border bg-card py-1.5 pr-4 pl-1.5 shadow-lg\",\n \"text-sm text-card-foreground\",\n // `translate`, which is the property `translate-y-*` sets. Under\n // `transform` the line used to arrive in one frame with only its\n // opacity easing.\n \"transition-[opacity,translate] ease-out motion-reduce:transition-none\",\n isShown\n ? \"translate-y-0 opacity-100\"\n : \"pointer-events-none translate-y-2 opacity-0\",\n )}\n >\n <WidgetAvatar agent={agent} className=\"size-6 rounded-full\" />\n <span className=\"truncate\">{children}</span>\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport { queueCustomData } from \"./custom-data\";\nimport {\n createOpenStore,\n isDevelopment,\n useOpenState,\n useRegister,\n} from \"./open-store\";\nimport {\n reportError,\n type MedianErrorReportOptions,\n type MedianErrorReportOutcome,\n} from \"./report-error\";\nimport { resetSessions } from \"./session\";\nimport { resetVisitorEmails } from \"./visitor-email\";\n\n/**\n * Driving the support panel from anywhere on the page. The open state lives\n * in `open-store.ts`, which the feedback panel keeps its own copy of; this\n * file is the three things that are the support widget's alone, `attach`,\n * `reportError` and `reset`, and the shape a host reaches for them through.\n */\nconst store = createOpenStore(\"MedianSupport\");\n\n/**\n * The widget from anywhere, React or not: the same shape the hook hands\n * back, for a plain `onclick` or a shortcut listener that never sees a\n * component. `isOpen` reads live but does not re-render anything; the hook\n * is for that.\n */\nexport const medianSupport = {\n /** What the panel is doing right now. */\n get isOpen() {\n return store.readEffective();\n },\n open() {\n store.request(true);\n store.warnIfNothingIsMounted(\"the widget was asked to open\");\n },\n close() {\n store.request(false);\n },\n toggle() {\n const next = !store.readEffective();\n store.request(next);\n if (next) store.warnIfNothingIsMounted(\"the widget was asked to open\");\n },\n /**\n * Put your own data on the next bug report: a crash trace from your error\n * handler, a request id, the state of a store. Objects are written out as\n * JSON. Entries ride the visitor's next message and land on the report,\n * whether or not diagnostics are on.\n */\n attach(label: string, value: unknown) {\n if (!queueCustomData(label, value)) {\n if (isDevelopment) {\n console.warn(\n \"Median: attach() needs a label and a value, and nothing was queued. Pass a short label naming the data, and the data itself.\",\n );\n }\n return;\n }\n store.warnIfNothingIsMounted(\"data was attached\");\n },\n /**\n * File the crash your error screen is showing, with everything the browser\n * was doing when it happened. One press from a \"Report error\" button:\n *\n * const outcome = await medianSupport.reportError(error);\n *\n * It answers rather than throws, so the screen can say whether it landed.\n * It works from a boundary with no widget left under it, which is most of\n * them.\n */\n reportError(error: unknown, options?: MedianErrorReportOptions) {\n return reportError(error, options);\n },\n /**\n * Forget this browser's conversation, so the next one starts fresh and\n * anonymous. Call it when your user signs out: whoever sits down next\n * should not find somebody else's thread waiting.\n */\n reset() {\n resetSessions();\n resetVisitorEmails();\n },\n} satisfies MedianSupportControl;\n\n/** The shape of {@link medianSupport}, and of what the hook returns. */\nexport type MedianSupportControl = {\n /** Whether the panel is open. */\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n /** Put your own data on the next bug report: a crash trace, an id. */\n attach: (label: string, value: unknown) => void;\n /** File the crash your error screen is showing. For a report button. */\n reportError: (\n error: unknown,\n options?: MedianErrorReportOptions,\n ) => Promise<MedianErrorReportOutcome>;\n /** Forget this browser's conversation. For sign out. */\n reset: () => void;\n};\n\n/**\n * The widget, from anywhere else on the page:\n *\n * const support = useMedianSupport();\n *\n * <button onClick={support.open}>Contact us</button>\n *\n * `isOpen` follows the panel however it was opened, so a trigger can render\n * itself as pressed, or step out of the way while the panel is up.\n */\nexport function useMedianSupport(): MedianSupportControl {\n const isOpen = useSyncExternalStore(\n store.subscribe,\n store.readEffective,\n store.readServerEffective,\n );\n\n return {\n isOpen,\n open: medianSupport.open,\n close: medianSupport.close,\n toggle: medianSupport.toggle,\n attach: medianSupport.attach,\n reportError: medianSupport.reportError,\n reset: medianSupport.reset,\n };\n}\n\n/** The panel's own settled open state. See {@link useOpenState}. */\nexport function useMedianOpenState(options: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): [boolean, (next: boolean) => void] {\n return useOpenState(store, options);\n}\n\n/** One widget per page, and a word in the console when there are two. */\nexport function useRegisterMedianSupport() {\n useRegister(store);\n}\n","/**\n * Data somebody chose to put on a bug report: a crash trace, a request id,\n * the state of a store when it fell over.\n *\n * The deliberate third of the telemetry. Context is what the browser knows,\n * diagnostics are what the widget caught on its own; this is what the host's\n * code or the agent decided the team should see, word for word. Because it is\n * handed over on purpose, it does not wait behind the diagnostics switch.\n *\n * Pure on purpose, like `diagnostics.ts` next door: the SDK cleans what it\n * queues with this file before it sends, and the backend cleans it again with\n * the same file before it stores, so neither side is trusting the other's\n * arithmetic.\n */\n\nexport type CustomDataEntry = {\n /** What the value is, in a few words. The entry's heading on the report. */\n label: string;\n /** The thing itself, kept exactly as written, up to the cap. */\n value: string;\n};\n\n/** The most entries one report carries. Newest kept, oldest dropped. */\nexport const MAX_CUSTOM_ENTRIES = 8;\n\nexport const CUSTOM_LABEL_MAX_LENGTH = 60;\n\n/** Room for a real stack trace, not just its first line. */\nexport const CUSTOM_VALUE_MAX_LENGTH = 4_000;\n\nfunction cleanLabel(input: unknown): string | undefined {\n if (typeof input !== \"string\") return undefined;\n const label = input.trim().slice(0, CUSTOM_LABEL_MAX_LENGTH);\n return label.length > 0 ? label : undefined;\n}\n\n/**\n * Whatever was handed over, written out as text. Objects become readable\n * JSON, because \"the state of the store\" arrives as an object, and making the\n * caller serialize it first is exactly the chore this exists to remove.\n */\nfunction cleanValue(input: unknown): string | undefined {\n let written: string | undefined;\n if (typeof input === \"string\") {\n written = input.trim();\n } else if (typeof input === \"number\" || typeof input === \"boolean\") {\n written = String(input);\n } else {\n try {\n written = JSON.stringify(input, null, 2);\n } catch {\n written = undefined;\n }\n }\n\n if (written === undefined || written.length === 0) return undefined;\n return written.length > CUSTOM_VALUE_MAX_LENGTH\n ? `${written.slice(0, CUSTOM_VALUE_MAX_LENGTH)}…`\n : written;\n}\n\n/**\n * Whatever arrived, cut down to what may be stored. Undefined when nothing\n * survived, so an empty list never lands on a row and reads later as \"they\n * attached something and it was blank\".\n *\n * One entry per label, the newest one winning: attaching a second crash\n * trace means the first one is no longer the crash.\n */\nexport function cleanCustomData(input: unknown): CustomDataEntry[] | undefined {\n if (!Array.isArray(input)) return undefined;\n\n const byLabel = new Map<string, string>();\n for (const raw of input) {\n if (typeof raw !== \"object\" || raw === null) continue;\n const entry = raw as Record<string, unknown>;\n const label = cleanLabel(entry.label);\n const value = cleanValue(entry.value);\n if (label === undefined || value === undefined) continue;\n // Re-set so a replaced label moves to the end, where the newest live.\n byLabel.delete(label);\n byLabel.set(label, value);\n }\n\n const entries = [...byLabel].map(([label, value]) => ({ label, value }));\n return entries.length > 0 ? entries.slice(-MAX_CUSTOM_ENTRIES) : undefined;\n}\n\n/**\n * Several sources of entries, oldest source first, folded into one list. The\n * same rules as cleaning: one entry per label, later wins, newest kept when\n * the cap says something has to go.\n */\nexport function mergeCustomData(\n ...sources: (CustomDataEntry[] | undefined)[]\n): CustomDataEntry[] | undefined {\n return cleanCustomData(sources.flatMap((entries) => entries ?? []));\n}\n","\"use client\";\n\nimport {\n cleanCustomData,\n mergeCustomData,\n type CustomDataEntry,\n} from \"@median/backend/customData\";\n\n/**\n * Data the host hands over on purpose, waiting to ride the next message: a\n * crash trace from their error handler, a request id, the state of a store.\n *\n * The deliberate cousin of the diagnostics ring buffer next door, and module\n * level for the same reason: a crash handler runs wherever the crash was,\n * usually nowhere near React, and sometimes before the widget has mounted.\n * Unlike diagnostics it does not wait behind a switch, because calling\n * `attach` is the host offering it.\n *\n * Nothing is sent on its own. Entries ride the next message the visitor\n * sends, land on the conversation, and are copied onto a bug report the\n * moment one is filed.\n */\n\nlet queued: CustomDataEntry[] = [];\n\n/** True when the entry survived cleaning and is waiting for a send. */\nexport function queueCustomData(label: unknown, value: unknown): boolean {\n const cleaned = cleanCustomData([{ label, value }]);\n if (cleaned === undefined) return false;\n\n queued = mergeCustomData(queued, cleaned) ?? [];\n return true;\n}\n\n/**\n * What a send takes with it: everything attached since the last one, or\n * nothing, so a quiet page costs nothing. Drained rather than copied; a send\n * that fails hands its entries back through {@link restoreCustomData}.\n */\nexport function takeCustomData(): CustomDataEntry[] | undefined {\n if (queued.length === 0) return undefined;\n const taken = queued;\n queued = [];\n return taken;\n}\n\n/** A failed send's entries, back in the queue so the retry still has them. */\nexport function restoreCustomData(entries: CustomDataEntry[]): void {\n // The failed send's entries are the older side: anything attached since\n // the failure wins a collision.\n queued = mergeCustomData(entries, queued) ?? [];\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useSyncExternalStore } from \"react\";\n\n/**\n * Whether a panel is open, kept outside React.\n *\n * The widget is mounted once, usually in a root layout. The thing that opens\n * it is usually somewhere else entirely: a \"Contact us\" item in a nav, a\n * \"Share feedback\" row in a menu, a keyboard shortcut. Holding this in a\n * module rather than in the panel's own state is what lets those reach it\n * without a host threading state through their whole tree, or wrapping their\n * app in a provider of ours.\n *\n * Two values rather than one, because the host has the last word:\n *\n * - `requested` is what the page last asked for, including the widget's own\n * controls. Null until something asks, so `defaultOpen` still means\n * something on first paint.\n * - `effective` is what the panel is actually doing. A host driving it with\n * the `open` prop can ignore a request, so anything reading the state back\n * reads this one.\n *\n * One store per panel: the support widget and the feedback panel are two\n * things a page can open, and opening one must never open the other.\n */\n\n// The `typeof` guard is for the published bundle, where no framework has\n// promised that `process` exists. A bundler that defines it leaves this line\n// statically true or false; a page without one gets production behavior.\nexport const isDevelopment =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"development\";\n\nexport type OpenStore = ReturnType<typeof createOpenStore>;\n\nexport function createOpenStore(component: string) {\n let requested: boolean | null = null;\n let effective = false;\n let mounted = 0;\n const listeners = new Set<() => void>();\n\n function emit() {\n for (const listener of listeners) listener();\n }\n\n return {\n /** The component a warning should name, so it reads like the host's code. */\n component,\n\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n\n readRequested: () => requested,\n readEffective: () => effective,\n\n /**\n * The server has no page to open a panel on, and neither does the first\n * client paint, which is what keeps hydration quiet.\n */\n readServerRequested: () => null as boolean | null,\n readServerEffective: () => false,\n\n request(next: boolean) {\n requested = next;\n emit();\n },\n\n /** Told, not asked: the panel saying what it settled on. */\n settle(next: boolean) {\n if (effective === next) return;\n effective = next;\n emit();\n },\n\n countMounted() {\n mounted += 1;\n return mounted;\n },\n\n countUnmounted() {\n mounted -= 1;\n // With nothing on the page, nothing is open, whatever the last one to\n // leave was doing. What was asked for is kept, so a widget that comes\n // back on the next route comes back the way it went.\n if (mounted === 0 && effective) {\n effective = false;\n emit();\n }\n },\n\n /**\n * The likeliest way to spend an afternoon on this: call `open()`, watch\n * nothing happen, and never find out that the component is not on the\n * page. So it says so, in the console, where that afternoon is being\n * spent.\n *\n * Asked a second later rather than now, because a static button wired up\n * before React has hydrated is early, not wrong. The request is kept\n * either way, so a panel that mounts afterwards picks it up.\n */\n warnIfNothingIsMounted(did: string) {\n if (!isDevelopment || mounted > 0) return;\n\n setTimeout(() => {\n if (mounted > 0) return;\n console.warn(\n `Median: ${did}, but no <${component}> is on the page. Mount it once, near the root of your app.`,\n );\n }, 1000);\n },\n };\n}\n\n/**\n * The state a panel actually renders with, and the one place the three ways\n * of driving it are settled:\n *\n * 1. `open`, if the host passed it. Controlled wins, always.\n * 2. Whatever the page last asked for, through a trigger or the hook.\n * 3. `defaultOpen`, until anything at all has happened.\n *\n * A request is reported to `onOpenChange` either way, so a controlled host\n * hears about their own nav item pressing open just as they hear about ours.\n */\nexport function useOpenState(\n store: OpenStore,\n {\n open,\n defaultOpen = false,\n onOpenChange,\n }: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n },\n): [boolean, (next: boolean) => void] {\n const asked = useSyncExternalStore(\n store.subscribe,\n store.readRequested,\n store.readServerRequested,\n );\n const isOpen = open ?? asked ?? defaultOpen;\n\n // So a trigger reading `isOpen` back is never a frame behind the panel it\n // opened.\n useEffect(() => {\n store.settle(isOpen);\n }, [store, isOpen]);\n\n const setOpen = useCallback(\n (next: boolean) => {\n store.request(next);\n onOpenChange?.(next);\n },\n [store, onOpenChange],\n );\n\n return [isOpen, setOpen];\n}\n\n/**\n * One of each per page. Two would share the state above and open together,\n * which is never what anyone meant, so it says so where it will be read.\n */\nexport function useRegister(store: OpenStore) {\n useEffect(() => {\n if (store.countMounted() > 1 && isDevelopment) {\n console.warn(\n `Median: more than one <${store.component}> is mounted. They share one open state and open together. Mount it once, near the root of your app.`,\n );\n }\n return () => store.countUnmounted();\n }, [store]);\n}\n","/* eslint-disable */\n/**\n * Generated `api` utility.\n *\n * THIS CODE IS AUTOMATICALLY GENERATED.\n *\n * To regenerate, run `npx convex dev`.\n * @module\n */\n\nimport { anyApi, componentsGeneric } from \"convex/server\";\n\n/**\n * A utility for referencing Convex functions in your app's API.\n *\n * Usage:\n * ```js\n * const myFunctionReference = api.myModule.myFunction;\n * ```\n */\nexport const api = anyApi;\nexport const internal = anyApi;\nexport const components = componentsGeneric();\n","import { cleanTitle } from \"./signals\";\n\n/**\n * A crash, in the vocabulary both sides share.\n *\n * A page that has fallen over is the one report nobody types: whoever was\n * using it can see that it broke and has nothing to add about why. So the\n * error describes itself, and this file is what it turns into on the Signal\n * tab.\n *\n * Deliberately pure, like `signals.ts` and `feedback.ts` next door. The SDK\n * trims a crash with this file before it sends and the mutation trims it\n * again on arrival, so neither side is trusting the other's arithmetic.\n *\n * Nothing here asks a model. A report somebody pressed a button for has to\n * land, and it has to land under the same title as the last twenty copies of\n * the same crash, which is what makes the list one row rather than twenty.\n */\n\n/** What the boundary saw, as it hands it over. */\nexport type Crash = {\n /** The error's own line, without its stack. */\n message: string;\n /** \"TypeError\", when the thrown thing had a name worth keeping. */\n name?: string;\n stack?: string;\n /** The framework's id for an error that happened on the server. */\n digest?: string;\n /** The component stack, when the boundary was handed one. */\n componentStack?: string;\n /** The route it happened on, as the app's own router writes it. */\n route?: string;\n};\n\n/** One line of error, the same cap a diagnostic message gets. */\nexport const CRASH_MESSAGE_MAX_LENGTH = 300;\n\n/** Room for a real stack, matching what one attachment may hold. */\nexport const CRASH_STACK_MAX_LENGTH = 4_000;\n\nexport const CRASH_NAME_MAX_LENGTH = 60;\nexport const CRASH_ROUTE_MAX_LENGTH = 200;\n\n/** When the thrown thing said nothing for itself. */\nconst UNNAMED = \"Unnamed error\";\n\n/**\n * Names that add nothing to a title. Every thrown thing in a browser is an\n * error, so saying so twice only costs room the message wanted.\n */\nconst GENERIC_NAMES = [\"error\", \"exception\"];\n\nfunction trim(value: unknown, limit: number): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const clean = value.trim().slice(0, limit);\n return clean.length > 0 ? clean : undefined;\n}\n\n/** Whatever arrived, cut down to what may be stored. */\nexport function cleanCrash(input: unknown): Crash {\n const raw =\n typeof input === \"object\" && input !== null\n ? (input as Record<string, unknown>)\n : {};\n\n const name = trim(raw.name, CRASH_NAME_MAX_LENGTH);\n const stack = trim(raw.stack, CRASH_STACK_MAX_LENGTH);\n const digest = trim(raw.digest, CRASH_NAME_MAX_LENGTH);\n const componentStack = trim(raw.componentStack, CRASH_STACK_MAX_LENGTH);\n const route = trim(raw.route, CRASH_ROUTE_MAX_LENGTH);\n\n return {\n message: trim(raw.message, CRASH_MESSAGE_MAX_LENGTH) ?? UNNAMED,\n ...(name !== undefined ? { name } : {}),\n ...(stack !== undefined ? { stack } : {}),\n ...(digest !== undefined ? { digest } : {}),\n ...(componentStack !== undefined ? { componentStack } : {}),\n ...(route !== undefined ? { route } : {}),\n };\n}\n\n/**\n * The error on one line: \"TypeError: user.plan is not a function\".\n *\n * The name is dropped when the message already opens with it, which is what\n * a stack's first line looks like when a host passes one straight through.\n */\nexport function crashLabel(crash: Crash): string {\n const name = crash.name;\n if (name === undefined) return crash.message;\n if (GENERIC_NAMES.includes(name.toLowerCase())) return crash.message;\n if (crash.message.toLowerCase().startsWith(name.toLowerCase())) {\n return crash.message;\n }\n return `${name}: ${crash.message}`;\n}\n\n/**\n * How the row reads in the bug list.\n *\n * The route leads, because it is what makes two crashes the same crash: the\n * error's own line can run long and be cut, and what survives the cut should\n * still be the thing that groups them. The exact words matter more here than\n * anywhere else, since the filing mutation dedupes on them.\n */\nexport function crashTitle(crash: Crash): string {\n const label = crashLabel(crash);\n return cleanTitle(\n crash.route === undefined\n ? `Crash: ${label}`\n : `Crash on ${crash.route}: ${label}`,\n );\n}\n\n/** What the team reads first: what broke, and where. */\nexport function crashBody(crash: Crash): string {\n return [\n `The page stopped working${\n crash.route === undefined ? \"\" : ` on ${crash.route}`\n } and somebody reported it from the error screen.`,\n \"\",\n `**Error**: ${crashLabel(crash)}`,\n ...(crash.digest === undefined ? [] : [`**Digest**: ${crash.digest}`]),\n ].join(\"\\n\");\n}\n\n/**\n * The reporter's own line on the report. They pressed a button rather than\n * writing a sentence, so it says what the button did and what it saw.\n */\nexport function crashQuote(crash: Crash): string {\n return `Reported from the error screen: ${crashLabel(crash)}`;\n}\n\n/**\n * The long parts, as attachments rather than as body text: the stack belongs\n * to this one crash, and the body is shared with every other report of it.\n */\nexport function crashAttachments(crash: Crash): { label: string; value: string }[] {\n return [\n ...(crash.stack === undefined\n ? []\n : [{ label: \"Crash trace\", value: crash.stack }]),\n ...(crash.componentStack === undefined\n ? []\n : [{ label: \"Component stack\", value: crash.componentStack }]),\n ];\n}\n","\"use client\";\n\nimport { api } from \"@median/backend\";\nimport { cleanCrash, type Crash } from \"@median/backend/crashes\";\nimport { mergeCustomData } from \"@median/backend/customData\";\nimport { ConvexHttpClient } from \"convex/browser\";\nimport { useSyncExternalStore } from \"react\";\nimport { collectContext, collectPage } from \"./context\";\nimport { restoreCustomData, takeCustomData } from \"./custom-data\";\nimport { MEDIAN_DEPLOYMENT_URL } from \"./deployment\";\nimport { snapshotNow } from \"./diagnostics\";\nimport { hasInstall, readInstall, subscribeInstall } from \"./install\";\nimport { getOrCreateSessionId } from \"./session\";\nimport { splitIdentity, type MedianUser } from \"./use-median-thread\";\n\n/**\n * Filing the crash the visitor is looking at.\n *\n * Every other send in the SDK starts with somebody typing. This one starts\n * with a page that has stopped working, which is the report nobody writes:\n * whoever was using it can see that it broke and has nothing to add about\n * why. So the error describes itself, the browser hands over what it was\n * doing, and one press files it.\n *\n * It brings its own connection and reads its key from the last widget that\n * mounted, because by the time this runs the tree that widget lived in has\n * usually been replaced by the error screen calling it. Nothing here needs a\n * component, a provider, or a panel on the page.\n *\n * It never throws. A crash screen that crashes reporting a crash is a poor\n * apology, so everything that can go wrong comes back as a reason instead.\n */\n\nexport type MedianErrorReportOptions = {\n /**\n * The key, when no widget has mounted on this page to remember it. Both\n * panels write theirs down as they mount, so an app with either one\n * installed can leave this alone.\n */\n apiKey?: string;\n /** Who is in the chair. Defaults to whoever the mounted widget was given. */\n user?: MedianUser;\n /**\n * Where it happened, when your router names the page better than its URL\n * does: \"/orders/[id]\" rather than \"/orders/8912\". It leads the title, so\n * the same crash on the same route is one row on the list however many\n * people hit it. Defaults to the path in the address bar.\n */\n route?: string;\n /** React's component stack, when your boundary was handed one. */\n componentStack?: string;\n /** Facts to put on the report, the same shape as `appState`. */\n state?: Record<string, string | number | boolean>;\n /** Blocks to attach, the same shape and limits as `attach`. */\n attach?: Record<string, unknown>;\n /** Whether the report carries what the browser knows. On by default. */\n telemetry?: boolean;\n};\n\n/** Where the report went, or why it did not go. */\nexport type MedianErrorReportOutcome =\n | {\n reported: true;\n /** True when somebody had already reported this one. */\n joined: boolean;\n }\n | { reported: false; reason: string };\n\n/** Why a report did not land, in words the host can act on. */\nconst REASONS = {\n noKey:\n \"Median has no API key on this page, so the crash could not be reported. Mount <MedianSupport> or pass apiKey to reportError.\",\n noDeployment:\n \"The Median widget was built without a deployment URL, so the crash could not be reported.\",\n noBrowser: \"reportError only runs in a browser.\",\n off: \"This site is not taking reports right now.\",\n failed: \"The report could not be sent. Check the connection and try again.\",\n} as const;\n\nlet client: ConvexHttpClient | null = null;\n\n/**\n * Anything thrown, as the fields a report is made of.\n *\n * Hosts throw all sorts. An Error is the common case, a string is the lazy\n * one, and a framework error is an Error with an id stapled to it. All three\n * arrive here and none of them should cost the report.\n */\nfunction crashFrom(error: unknown, options: MedianErrorReportOptions): Crash {\n const raw = (\n typeof error === \"object\" && error !== null ? error : {}\n ) as Record<string, unknown>;\n\n const message =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : typeof raw.message === \"string\"\n ? raw.message\n : String(error);\n\n return cleanCrash({\n message,\n name: error instanceof Error ? error.name : raw.name,\n stack: raw.stack,\n // Next puts one on every error that came from the server, and it is the\n // id in that server's own log line.\n digest: raw.digest,\n componentStack: options.componentStack ?? raw.componentStack,\n route: options.route ?? currentRoute(),\n });\n}\n\n/** The page it happened on, minus anything after the path. */\nfunction currentRoute(): string | undefined {\n if (typeof window === \"undefined\") return undefined;\n return window.location.pathname || undefined;\n}\n\n/**\n * The facts that belong beside the browser's, rather than inside the write-up.\n * Both of these read as a row on the report next to the viewport and the page.\n */\nfunction factsOf(crash: Crash): Record<string, string> {\n return {\n ...(crash.route !== undefined ? { route: crash.route } : {}),\n ...(crash.digest !== undefined ? { digest: crash.digest } : {}),\n };\n}\n\nexport async function reportError(\n error: unknown,\n options: MedianErrorReportOptions = {},\n): Promise<MedianErrorReportOutcome> {\n if (typeof window === \"undefined\") {\n return { reported: false, reason: REASONS.noBrowser };\n }\n\n const apiKey = options.apiKey ?? readInstall()?.apiKey;\n if (!apiKey) {\n console.error(REASONS.noKey);\n return { reported: false, reason: REASONS.noKey };\n }\n if (!MEDIAN_DEPLOYMENT_URL) {\n console.error(REASONS.noDeployment);\n return { reported: false, reason: REASONS.noDeployment };\n }\n\n const sessionId = getOrCreateSessionId(apiKey);\n if (sessionId === null) {\n return { reported: false, reason: REASONS.failed };\n }\n\n const crash = crashFrom(error, options);\n const telemetry = options.telemetry ?? true;\n const user = options.user ?? readInstall()?.user;\n const { facts, claim } = splitIdentity(user ?? null);\n\n // Whatever the host attached since the last send, plus whatever they handed\n // this call, drained the way a message drains it so nothing is sent twice.\n const custom = mergeCustomData(\n takeCustomData(),\n Object.entries(options.attach ?? {}).map(([label, value]) => ({\n label,\n value: typeof value === \"string\" ? value : JSON.stringify(value),\n })),\n );\n\n // Read here rather than on mount, like every other send: all of it is\n // wanted as \"what was true when it broke\".\n const context = telemetry ? collectContext() : undefined;\n const page = telemetry ? collectPage() : undefined;\n const diagnostics = snapshotNow({ ...factsOf(crash), ...options.state });\n\n try {\n client ??= new ConvexHttpClient(MEDIAN_DEPLOYMENT_URL);\n const outcome = await client.mutation(api.feedback.reportError, {\n apiKey,\n sessionId,\n error: crash,\n ...(user ? { user: facts } : {}),\n ...(claim ? { identity: claim } : {}),\n ...(context ? { context } : {}),\n ...(page ? { page } : {}),\n ...(diagnostics ? { diagnostics } : {}),\n ...(custom ? { customData: custom } : {}),\n });\n\n if (outcome === \"off\") {\n if (custom) restoreCustomData(custom);\n return { reported: false, reason: REASONS.off };\n }\n return { reported: true, joined: outcome === \"joined\" };\n } catch (caught) {\n // Back in the queue, so a second press still carries them.\n if (custom) restoreCustomData(custom);\n console.error(\"Median: sending the crash report failed\", caught);\n return { reported: false, reason: REASONS.failed };\n }\n}\n\n/**\n * Whether a report has anywhere to go: a widget has mounted on this page and\n * left its key, and this build knows which Median to send to.\n *\n * For a \"Report error\" button, which should not be on the screen at all if\n * pressing it could only ever fail. It follows the install rather than\n * reading it once, since an error screen can render before the widget does.\n */\nexport function useCanReportError(): boolean {\n const isInstalled = useSyncExternalStore(\n subscribeInstall,\n hasInstall,\n // The server renders nothing installed: it has no page to have mounted\n // on, and a button that flickered away on hydration is worse than one\n // that arrives a moment late.\n () => false,\n );\n\n return isInstalled && Boolean(MEDIAN_DEPLOYMENT_URL);\n}\n","import type {\n ConversationPage,\n DeviceKind,\n VisitorContext,\n} from \"@median/backend/telemetry\";\n\n/**\n * The handful of things the browser already knows that a support reply needs.\n *\n * Read at send time rather than watched, because all of it is only ever wanted\n * as \"what was true when they wrote\". Nothing is stored, nothing is polled,\n * and nothing leaves the page unless somebody actually gets in touch.\n *\n * The user agent is parsed here rather than sent up raw. A name and a major\n * version is what the inbox shows and all it can act on; the full string is a\n * fingerprint we would then be keeping on somebody else's customers.\n */\n\n/**\n * Browser names in the order they have to be tested.\n *\n * Every one of these lies about being the others. Chrome's string contains\n * Safari, Edge's contains Chrome and Safari, Opera's contains all three, so\n * the only thing that works is checking the most specific claim first and\n * taking the first hit.\n */\nconst BROWSERS: { name: string; token: RegExp }[] = [\n { name: \"Edge\", token: /Edg(?:e|A|iOS)?\\/(\\d+)/ },\n { name: \"Opera\", token: /OPR\\/(\\d+)/ },\n { name: \"Samsung Internet\", token: /SamsungBrowser\\/(\\d+)/ },\n { name: \"Firefox\", token: /(?:Firefox|FxiOS)\\/(\\d+)/ },\n { name: \"Chrome\", token: /(?:Chrome|CriOS)\\/(\\d+)/ },\n { name: \"Safari\", token: /Version\\/(\\d+).*Safari/ },\n];\n\nconst OPERATING_SYSTEMS: { name: string; token: RegExp }[] = [\n // Before Android, whose string also says Linux.\n { name: \"Android\", token: /Android/ },\n { name: \"iOS\", token: /iPhone|iPad|iPod/ },\n { name: \"macOS\", token: /Mac OS X|Macintosh/ },\n { name: \"Windows\", token: /Windows NT/ },\n { name: \"ChromeOS\", token: /CrOS/ },\n { name: \"Linux\", token: /Linux/ },\n];\n\nfunction browserOf(ua: string): string | undefined {\n for (const { name, token } of BROWSERS) {\n const match = ua.match(token);\n if (match) return match[1] ? `${name} ${match[1]}` : name;\n }\n return undefined;\n}\n\nfunction osOf(ua: string): string | undefined {\n return OPERATING_SYSTEMS.find(({ token }) => token.test(ua))?.name;\n}\n\n/**\n * Desktop, tablet, or phone.\n *\n * An iPad reports itself as a Mac and has done for years, so the touch check\n * is what tells the two apart. Everything else is honest enough about it.\n */\nfunction deviceOf(ua: string): DeviceKind {\n const isTouchMac =\n /Macintosh/.test(ua) && navigator.maxTouchPoints > 1;\n\n if (/iPad|Tablet/.test(ua) || isTouchMac) return \"tablet\";\n if (/Mobi|iPhone|iPod|Android.*Mobile/.test(ua)) return \"mobile\";\n if (/Android/.test(ua)) return \"tablet\";\n return \"desktop\";\n}\n\n/** What the browser will admit to, or nothing if it is not a browser at all. */\nexport function collectContext(): VisitorContext | undefined {\n if (typeof navigator === \"undefined\" || typeof window === \"undefined\") {\n return undefined;\n }\n\n const ua = navigator.userAgent ?? \"\";\n const { width, height } = window.screen ?? { width: 0, height: 0 };\n\n const context: VisitorContext = {\n // Wrapped: a browser with a broken or absent Intl is rare but real, and\n // failing to work out a time zone should not stop a message sending.\n timeZone: safely(() => Intl.DateTimeFormat().resolvedOptions().timeZone),\n locale: navigator.language || undefined,\n browser: browserOf(ua),\n os: osOf(ua),\n device: deviceOf(ua),\n // The multiplication sign rather than an x, since this is being read as a\n // measurement rather than run as one.\n screen: width && height ? `${width} × ${height}` : undefined,\n };\n\n return Object.values(context).some((one) => one !== undefined)\n ? context\n : undefined;\n}\n\n/**\n * The page they are writing from.\n *\n * The query string is dropped on the way out, before it is ever sent, and\n * again on the way in. A support agent needs to know somebody was on the\n * checkout page; the password reset token that got them there is not ours to\n * put in somebody's inbox.\n */\nexport function collectPage(): ConversationPage | undefined {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return undefined;\n }\n\n const url = withoutQuery(window.location.href);\n if (url === undefined) return undefined;\n\n return {\n url,\n title: document.title || undefined,\n referrer: withoutQuery(document.referrer),\n };\n}\n\nfunction withoutQuery(href: string): string | undefined {\n if (!href) return undefined;\n try {\n const url = new URL(href);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") return undefined;\n return `${url.origin}${url.pathname}`;\n } catch {\n return undefined;\n }\n}\n\nfunction safely<T>(read: () => T): T | undefined {\n try {\n return read();\n } catch {\n return undefined;\n }\n}\n","/**\n * Which Median the widget talks to.\n *\n * Deliberately not a prop. A host plugs in their API key and that is the whole\n * install; our address is our business, not something they should have to know\n * or keep in sync. It reads from the env while the widget ships inside this\n * app, and the published package bakes it in at build time.\n */\nexport const MEDIAN_DEPLOYMENT_URL = process.env.NEXT_PUBLIC_CONVEX_URL;\n","/**\n * What was going wrong around a bug report, from both ends.\n *\n * The client half is collected by the widget SDK: uncaught errors, rejected\n * promises, failed requests, and whatever the host chose to tell us about\n * their own app. The server half is asked for at report time, from the same\n * endpoint the agent's tools live at, so a team that has already wired up\n * tools gets it for nothing.\n *\n * Pure on purpose. The widget cleans what it collects with this file before\n * it sends, and the backend cleans it again with the same file before it\n * stores, so neither side is trusting the other's arithmetic.\n *\n * The rule everywhere here is the one the rest of the telemetry follows: a\n * fact about a program, never a fact about a person. Nothing reads cookies,\n * nothing reads storage, and every URL loses its query string on the way.\n */\n\n/**\n * Where one entry came from. `error` is an uncaught exception, `rejection`\n * is a promise nobody caught, `console` is a console.error, and `network` is\n * a request that failed or came back unhappy.\n */\nexport const DIAGNOSTIC_KINDS = [\n \"error\",\n \"rejection\",\n \"console\",\n \"network\",\n] as const;\n\nexport type DiagnosticKind = (typeof DIAGNOSTIC_KINDS)[number];\n\nexport type DiagnosticEvent = {\n at: number;\n kind: DiagnosticKind;\n message: string;\n /** The file, or the request's method and path. Never a query string. */\n source?: string;\n /** The first frames, for an exception. */\n stack?: string;\n /** The HTTP status, on a network entry that got one. */\n status?: number;\n};\n\nexport type ClientDiagnostics = {\n /** When the snapshot was taken, by the browser's own clock. */\n at: number;\n /** The page they were on. Query string already dropped. */\n url?: string;\n /** \"1512 × 982\", already formatted, like the rest of the telemetry. */\n viewport?: string;\n /** Whatever the host declared about their own app: version, route, flags. */\n state?: Record<string, string>;\n events: DiagnosticEvent[];\n};\n\n/** One tool endpoint's answer to \"how are you\". */\nexport type ServerDiagnostics = {\n /** Which endpoint answered, so a team with two can tell them apart. */\n url: string;\n ok: boolean;\n /** What it said, as JSON text, or why it could not be asked. */\n detail: string;\n};\n\n/** The most entries one snapshot carries. Newest kept, oldest dropped. */\nexport const MAX_EVENTS = 12;\n\nexport const MESSAGE_MAX_LENGTH = 300;\nexport const SOURCE_MAX_LENGTH = 200;\nexport const STACK_MAX_LENGTH = 800;\n\n/** The host's own state, bounded the same way visitor metadata is. */\nexport const MAX_STATE_ENTRIES = 20;\nexport const STATE_KEY_MAX_LENGTH = 60;\nexport const STATE_VALUE_MAX_LENGTH = 200;\n\n/** What one endpoint may say for itself. Enough to hold a health payload. */\nexport const SERVER_DETAIL_MAX_LENGTH = 2_000;\n\n/** How long the widget waits before deciding an endpoint is not answering. */\nexport const SERVER_TIMEOUT_MS = 8_000;\n\nfunction trim(value: unknown, limit: number): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const clean = value.trim().slice(0, limit);\n return clean.length > 0 ? clean : undefined;\n}\n\n/** A URL with its query string taken off, or nothing if it is not one. */\nexport function withoutQuery(href: unknown): string | undefined {\n if (typeof href !== \"string\" || href.length === 0) return undefined;\n try {\n const url = new URL(href);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") return undefined;\n return `${url.origin}${url.pathname}`.slice(0, SOURCE_MAX_LENGTH);\n } catch {\n // Relative paths and the like arrive here. The path is the useful half\n // anyway, so it is kept as written, minus anything after a \"?\".\n return trim(href.split(\"?\")[0], SOURCE_MAX_LENGTH);\n }\n}\n\nfunction cleanEvent(input: unknown): DiagnosticEvent | null {\n if (typeof input !== \"object\" || input === null) return null;\n const raw = input as Record<string, unknown>;\n\n const kind = DIAGNOSTIC_KINDS.find((one) => one === raw.kind);\n const message = trim(raw.message, MESSAGE_MAX_LENGTH);\n if (kind === undefined || message === undefined) return null;\n\n const status =\n typeof raw.status === \"number\" && Number.isFinite(raw.status)\n ? Math.trunc(raw.status)\n : undefined;\n\n return {\n at: typeof raw.at === \"number\" && Number.isFinite(raw.at) ? raw.at : 0,\n kind,\n message,\n ...(trim(raw.source, SOURCE_MAX_LENGTH) !== undefined\n ? { source: trim(raw.source, SOURCE_MAX_LENGTH)! }\n : {}),\n ...(trim(raw.stack, STACK_MAX_LENGTH) !== undefined\n ? { stack: trim(raw.stack, STACK_MAX_LENGTH)! }\n : {}),\n ...(status !== undefined ? { status } : {}),\n };\n}\n\nfunction cleanState(input: unknown): Record<string, string> | undefined {\n if (typeof input !== \"object\" || input === null) return undefined;\n\n const state: Record<string, string> = {};\n for (const [key, value] of Object.entries(input).slice(0, MAX_STATE_ENTRIES)) {\n if (value === null || value === undefined) continue;\n const label = trim(key, STATE_KEY_MAX_LENGTH);\n // Numbers and booleans are the other two things anybody puts in here, so\n // they are written out rather than refused.\n const written =\n typeof value === \"string\"\n ? trim(value, STATE_VALUE_MAX_LENGTH)\n : typeof value === \"number\" || typeof value === \"boolean\"\n ? String(value).slice(0, STATE_VALUE_MAX_LENGTH)\n : undefined;\n if (label === undefined || written === undefined) continue;\n state[label] = written;\n }\n\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\n/**\n * Whatever arrived, cut down to what may be stored. Undefined when there was\n * nothing worth keeping, so an empty snapshot never lands on a row and reads\n * later as \"we looked and the page was fine\".\n */\nexport function cleanClientDiagnostics(\n input: unknown,\n): ClientDiagnostics | undefined {\n if (typeof input !== \"object\" || input === null) return undefined;\n const raw = input as Record<string, unknown>;\n\n const events = Array.isArray(raw.events)\n ? raw.events\n .map(cleanEvent)\n .filter((one): one is DiagnosticEvent => one !== null)\n .slice(-MAX_EVENTS)\n : [];\n\n const url = withoutQuery(raw.url);\n const viewport = trim(raw.viewport, 40);\n const state = cleanState(raw.state);\n\n if (events.length === 0 && state === undefined && url === undefined) {\n return undefined;\n }\n\n return {\n at: typeof raw.at === \"number\" && Number.isFinite(raw.at) ? raw.at : 0,\n ...(url !== undefined ? { url } : {}),\n ...(viewport !== undefined ? { viewport } : {}),\n ...(state !== undefined ? { state } : {}),\n events,\n };\n}\n\n/** One endpoint's answer, trimmed to something a card can show. */\nexport function cleanServerDetail(text: string): string {\n return text.length > SERVER_DETAIL_MAX_LENGTH\n ? `${text.slice(0, SERVER_DETAIL_MAX_LENGTH)}…`\n : text;\n}\n","\"use client\";\n\nimport {\n cleanClientDiagnostics,\n MAX_EVENTS,\n MESSAGE_MAX_LENGTH,\n SOURCE_MAX_LENGTH,\n STACK_MAX_LENGTH,\n withoutQuery,\n type ClientDiagnostics,\n type DiagnosticEvent,\n} from \"@median/backend/diagnostics\";\nimport { useCallback, useEffect, useRef } from \"react\";\n\n/**\n * What has been going wrong on the page, kept ready in case somebody asks\n * for help about it.\n *\n * A support agent's first three questions are always the same: what were you\n * doing, what did it say, and what does the console show. The customer can\n * answer the first one. This answers the other two, so a bug report arrives\n * with the error already attached rather than after four messages of asking.\n *\n * Off unless a host switches it on. Everything here reads their program's\n * error stream, which is theirs to offer rather than ours to take.\n *\n * A bounded ring buffer and nothing else. Nothing is sent on its own, nothing\n * is stored, and nothing is polled: the newest snapshot rides the next message\n * the customer sends, and only when there is something new in it.\n */\n\n/** What a host can switch on. `true` is the passive half. */\nexport type MedianDiagnostics =\n | boolean\n | {\n /** Uncaught errors and rejected promises. On whenever diagnostics are. */\n errors?: boolean;\n /** Requests that failed or came back unhappy. Wraps window.fetch. */\n network?: boolean;\n /** console.error calls. Wraps console.error. */\n console?: boolean;\n };\n\ntype Settings = { errors: boolean; network: boolean; console: boolean };\n\nfunction settingsOf(option: MedianDiagnostics | undefined): Settings | null {\n if (option === undefined || option === false) return null;\n if (option === true) return { errors: true, network: false, console: false };\n return {\n errors: option.errors ?? true,\n network: option.network ?? false,\n console: option.console ?? false,\n };\n}\n\n/**\n * The buffer, and how many things have gone into it.\n *\n * Module level rather than per component: a page has one widget, and an\n * error that happened before React mounted it is exactly the kind worth\n * keeping. The count is what lets a sender ask \"anything new since last\n * time\" without comparing arrays.\n */\nconst events: DiagnosticEvent[] = [];\nlet recorded = 0;\n\n/**\n * The host's own state, as the last mounted widget was given it. Here rather\n * than only in the hook's ref because a crash report is sent from a tree\n * where that hook no longer exists, and the route a page fell over on is\n * exactly the sort of thing hosts put in `appState`.\n */\nlet latestState: Record<string, string | number | boolean> | undefined;\n\nfunction record(event: DiagnosticEvent): void {\n events.push(event);\n if (events.length > MAX_EVENTS) events.shift();\n recorded += 1;\n}\n\nfunction messageOf(value: unknown): string {\n if (value instanceof Error) return value.message.slice(0, MESSAGE_MAX_LENGTH);\n if (typeof value === \"string\") return value.slice(0, MESSAGE_MAX_LENGTH);\n try {\n return JSON.stringify(value).slice(0, MESSAGE_MAX_LENGTH);\n } catch {\n return String(value).slice(0, MESSAGE_MAX_LENGTH);\n }\n}\n\nfunction stackOf(value: unknown): string | undefined {\n return value instanceof Error && typeof value.stack === \"string\"\n ? value.stack.slice(0, STACK_MAX_LENGTH)\n : undefined;\n}\n\n/**\n * Installs whatever the host asked for, and gives back the way to take it all\n * off again. Every wrapper calls through to what it replaced first, so a page\n * behaves exactly as it did before the widget arrived.\n */\nfunction collect(settings: Settings): () => void {\n const undo: (() => void)[] = [];\n\n if (settings.errors) {\n const onError = (event: ErrorEvent) => {\n // A failed image or script fires here too, with no error on it. Those\n // are the browser's business, not a bug report's.\n if (!event.error && !event.message) return;\n record({\n at: Date.now(),\n kind: \"error\",\n message: messageOf(event.error ?? event.message),\n ...(event.filename\n ? {\n source: `${withoutQuery(event.filename) ?? \"\"}:${event.lineno}`.slice(\n 0,\n SOURCE_MAX_LENGTH,\n ),\n }\n : {}),\n ...(stackOf(event.error) !== undefined\n ? { stack: stackOf(event.error)! }\n : {}),\n });\n };\n const onRejection = (event: PromiseRejectionEvent) => {\n record({\n at: Date.now(),\n kind: \"rejection\",\n message: messageOf(event.reason),\n ...(stackOf(event.reason) !== undefined\n ? { stack: stackOf(event.reason)! }\n : {}),\n });\n };\n\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n undo.push(() => {\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n });\n }\n\n if (settings.network && typeof window.fetch === \"function\") {\n const original = window.fetch;\n window.fetch = async function medianFetch(this: unknown, ...args) {\n const [input, init] = args;\n const method = (init?.method ?? \"GET\").toUpperCase();\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n\n try {\n const response = await original.apply(this as never, args);\n if (!response.ok) {\n record({\n at: Date.now(),\n kind: \"network\",\n message: `${method} ${response.status}`,\n source: `${method} ${withoutQuery(url) ?? \"\"}`.slice(\n 0,\n SOURCE_MAX_LENGTH,\n ),\n status: response.status,\n });\n }\n return response;\n } catch (thrown) {\n record({\n at: Date.now(),\n kind: \"network\",\n message: messageOf(thrown),\n source: `${method} ${withoutQuery(url) ?? \"\"}`.slice(\n 0,\n SOURCE_MAX_LENGTH,\n ),\n });\n // Rethrown untouched. Watching a request is not catching it.\n throw thrown;\n }\n } as typeof window.fetch;\n\n undo.push(() => {\n window.fetch = original;\n });\n }\n\n if (settings.console) {\n const original = console.error;\n console.error = function medianConsoleError(...args: unknown[]) {\n record({\n at: Date.now(),\n kind: \"console\",\n message: args.map(messageOf).join(\" \").slice(0, MESSAGE_MAX_LENGTH),\n ...(stackOf(args.find((one) => one instanceof Error)) !== undefined\n ? { stack: stackOf(args.find((one) => one instanceof Error))! }\n : {}),\n });\n original.apply(console, args);\n };\n\n undo.push(() => {\n console.error = original;\n });\n }\n\n return () => {\n for (const off of undo) off();\n };\n}\n\n/** Everything worth saying about the page right now, or nothing. */\nfunction snapshot(\n state: Record<string, string | number | boolean> | undefined,\n): ClientDiagnostics | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n return cleanClientDiagnostics({\n at: Date.now(),\n url: window.location.href,\n viewport: `${window.innerWidth} × ${window.innerHeight}`,\n state,\n events,\n });\n}\n\n/**\n * Everything the page can say for itself right now, for a send that cannot\n * wait to be asked twice.\n *\n * The hook's `take` answers with nothing when nothing has been recorded since\n * the last send, which is right for a chat message and wrong for a crash\n * report: the viewport and the route are worth having whether or not the ring\n * buffer moved. So this one always answers, and takes anything the caller\n * knows that the host's own state does not.\n */\nexport function snapshotNow(\n extraState?: Record<string, string | number | boolean>,\n): ClientDiagnostics | undefined {\n return snapshot({ ...latestState, ...extraState });\n}\n\n/**\n * The collector, as a component uses it: on while the host wants it, off\n * again when they change their mind or the widget leaves the page.\n *\n * `take` is what a send calls. It answers with a snapshot the first time and\n * whenever something new has been recorded since, and with nothing the rest\n * of the time, so a long conversation on a healthy page sends the state once\n * rather than on every line.\n */\nexport function useDiagnostics(\n option: MedianDiagnostics | undefined,\n appState: Record<string, string | number | boolean> | undefined,\n) {\n const settings = settingsOf(option);\n // Serialised so a host building the object inline does not reinstall the\n // wrappers on every render. The same trick `user` gets in the thread hook.\n const key = settings === null ? null : JSON.stringify(settings);\n\n // Read at send time rather than closed over, since a route or a flag can\n // change between the widget mounting and somebody typing. Written after\n // the render rather than during it: nothing on screen depends on it, and a\n // ref written mid-render is a render that cannot be replayed.\n const stateRef = useRef(appState);\n useEffect(() => {\n stateRef.current = appState;\n latestState = appState;\n });\n\n const sentAt = useRef<number | null>(null);\n\n useEffect(() => {\n if (key === null) return;\n return collect(JSON.parse(key) as Settings);\n }, [key]);\n\n const take = useCallback((): ClientDiagnostics | undefined => {\n if (key === null) return undefined;\n if (sentAt.current !== null && sentAt.current === recorded) return undefined;\n\n sentAt.current = recorded;\n return snapshot(stateRef.current);\n }, [key]);\n\n return take;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport type { MedianUser } from \"./use-median-thread\";\n\n/**\n * What the install on this page said, kept where a crash can still reach it.\n *\n * Everything else in the SDK reads its API key and its visitor from props,\n * which is fine while there is a widget on the page to hold them. A crash is\n * the case where there is not: the boundary that catches it has replaced the\n * tree the widget was mounted in, and in the worst of them, the root layout,\n * there is nothing of the app left at all.\n *\n * Module level for the same reason the diagnostics buffer is: it outlives\n * every React tree on the page. A panel writes here as it mounts, and\n * `reportError` reads it long after that panel has been unmounted by the\n * error it is reporting.\n */\n\ntype Install = { apiKey: string; user?: MedianUser };\n\nlet install: Install | null = null;\n\nconst listeners = new Set<() => void>();\n\n/** Called by whichever widget mounted. The newest one wins. */\nexport function rememberInstall(next: Install): void {\n // Only a new key is news. The panels write here after every render, and a\n // report button that re-rendered on each of them would be a waste of a\n // subscription.\n const isNews = install?.apiKey !== next.apiKey;\n install = { apiKey: next.apiKey, ...(next.user ? { user: next.user } : {}) };\n if (!isNews) return;\n for (const listener of listeners) listener();\n}\n\n/** What the last mounted widget was given, or nothing if none ever was. */\nexport function readInstall(): Install | null {\n return install;\n}\n\n/**\n * Whether anything has been installed yet, as an external store.\n *\n * A report button rendered by an error screen can easily be on the page one\n * commit before the widget whose key it needs: a page that failed on the\n * server paints its error boundary and its layout together. Reading this\n * live is what lets that button appear the moment reporting becomes\n * possible, rather than sitting hidden until something else re-renders.\n */\nexport function subscribeInstall(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function hasInstall(): boolean {\n return install !== null;\n}\n\n/**\n * Both panels call this as they mount, and again whenever the host changes\n * its mind about who is in the chair.\n *\n * Written after the render rather than during it, and on every one rather\n * than behind a dependency list, because `user` is an object a host builds\n * inline and the write is one assignment.\n */\nexport function useRememberInstall(apiKey: string, user?: MedianUser): void {\n useEffect(() => {\n rememberInstall({ apiKey, ...(user ? { user } : {}) });\n });\n}\n","/**\n * Who this browser is, as far as the widget cares: a random token minted on\n * first visit and kept in localStorage, one per API key, so coming back\n * reopens the same conversation without anyone signing in.\n *\n * A small store rather than a bare read, so `resetSessions` can tell a\n * mounted widget its token is gone and the thread re-reads through\n * `useSyncExternalStore`.\n */\n\nconst STORAGE_PREFIX = \"median:session:\";\n\n/**\n * When localStorage is blocked, the token lives here instead: gone on\n * reload, but stable within the page, which is what the reads below need.\n */\nconst inMemorySessions = new Map<string, string>();\n\nconst listeners = new Set<() => void>();\n\nexport function subscribeSession(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n/**\n * Stable across calls on purpose: this is read as an external-store snapshot,\n * so two calls in a row must agree.\n */\nexport function getOrCreateSessionId(apiKey: string): string | null {\n if (typeof window === \"undefined\") return null;\n\n const storageKey = `${STORAGE_PREFIX}${apiKey}`;\n try {\n const existing = window.localStorage.getItem(storageKey);\n if (existing && existing.length >= 8) return existing;\n\n const created = crypto.randomUUID();\n window.localStorage.setItem(storageKey, created);\n return created;\n } catch {\n // Storage can be blocked entirely. A session that lasts one page load\n // still beats no support at all.\n const remembered = inMemorySessions.get(apiKey) ?? crypto.randomUUID();\n inMemorySessions.set(apiKey, remembered);\n return remembered;\n }\n}\n\n/**\n * Forget every token this browser holds. The next read mints a fresh one, so\n * the next message starts a conversation with nothing behind it.\n *\n * This is for sign out: the conversation belongs to the person who was in the\n * chair, not to the chair. The old thread stays in the team's inbox; it just\n * stops being reachable from this browser.\n */\nexport function resetSessions() {\n inMemorySessions.clear();\n\n if (typeof window !== \"undefined\") {\n try {\n const stale: string[] = [];\n for (let i = 0; i < window.localStorage.length; i += 1) {\n const key = window.localStorage.key(i);\n if (key !== null && key.startsWith(STORAGE_PREFIX)) stale.push(key);\n }\n for (const key of stale) window.localStorage.removeItem(key);\n } catch {\n // Storage was blocked, so there was nothing durable to forget.\n }\n }\n\n for (const listener of listeners) listener();\n}\n","\"use client\";\n\nimport { api } from \"@median/backend\";\nimport { TYPING_TTL_MS } from \"@median/backend/support\";\nimport { useMutation, useQuery } from \"convex/react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { attachmentKindOf, formatFileSize } from \"@/components/attachments\";\nimport { useNow } from \"@/hooks/use-now\";\nimport { errorMessage } from \"@/lib/errors\";\nimport { formatClockTime, formatDayLabel, isNewDay } from \"@/lib/time\";\nimport { uploadAttachments } from \"@/lib/upload\";\nimport type {\n SupportAgent,\n SupportAsk,\n SupportMessage,\n SupportPresence,\n SupportRating,\n} from \"../types\";\nimport { collectContext, collectPage } from \"./context\";\nimport { restoreCustomData, takeCustomData } from \"./custom-data\";\nimport { useDiagnostics, type MedianDiagnostics } from \"./diagnostics\";\nimport { readSkippedRatings, writeSkippedRating } from \"./rating-skips\";\nimport { readLastSeenAt, writeLastSeenAt } from \"./read-state\";\nimport { getOrCreateSessionId, subscribeSession } from \"./session\";\nimport { useVisitorEmail } from \"./visitor-email\";\n\n/** What a host can tell us about who is in the widget. All of it optional. */\nexport type MedianUser = {\n /**\n * Your own id for this person, and that id signed from MEDIAN_KEY.\n *\n * The pair is what makes a conversation follow somebody rather than a\n * browser: sign in on a phone and the thread from the laptop is already\n * there. Both or neither, and the signing belongs on your server, because\n * whoever holds the key can claim to be any of your customers.\n *\n * Without them the widget still works. It is just this browser's thread,\n * which is what it has always been.\n */\n id?: string;\n hash?: string;\n name?: string;\n email?: string;\n /**\n * Their profile picture, so the team sees who they are talking to rather\n * than a letter. Has to be an https URL; anything else is ignored.\n */\n avatarUrl?: string;\n /** Anything else worth showing the team: plan, company, whatever. */\n metadata?: Record<string, string>;\n};\n\n/**\n * Whether the host has told us somebody is in the chair.\n *\n * Anything they say about the person counts, because only they can know it: a\n * host who passes a name and an email for whoever is signed in is as sure as\n * one who passes a signed id. An empty object is not an answer, so a session\n * that is still loading does not open the door on its way past.\n */\nexport function isSignedIn(user: MedianUser | undefined): boolean {\n if (user === undefined) return false;\n\n // Every field checked as it arrives rather than as it is typed: a host\n // spreading a session that is not there yet passes `{ name: undefined }`,\n // and a widget that threw on that would be a page broken by signing out.\n const { metadata, ...facts } = user;\n return (\n Object.values(facts).some(\n (value) => typeof value === \"string\" && value.trim().length > 0,\n ) || Object.keys(metadata ?? {}).length > 0\n );\n}\n\n/**\n * The claim, split from the rest.\n *\n * Two things go up rather than one, and the difference between them is the\n * whole of the security. A name is decoration and is taken at its word; an id\n * decides whose history the widget can reach, so it travels with its signature\n * and is believed only if that checks out. Sending them as one object would\n * blur a line the backend needs to keep sharp.\n */\nexport function splitIdentity(user: MedianUser | null): {\n facts: Omit<MedianUser, \"id\" | \"hash\">;\n claim: { userId: string; userHash: string } | undefined;\n} {\n if (user === null) return { facts: {}, claim: undefined };\n\n const { id, hash, ...facts } = user;\n return {\n facts,\n claim: id && hash ? { userId: id, userHash: hash } : undefined,\n };\n}\n\n/** What the backend made of a claim, and what to say about it. */\nconst IDENTITY_COMPLAINTS: Record<string, string> = {\n unverified:\n \"Median: the user hash passed to <MedianSupport> did not match. Sign the same string you pass as `user.id` with the Median key that produced this widget id. Until it matches, this visitor gets a conversation of their own on every device.\",\n unconfigured:\n \"Median: a user hash was passed to <MedianSupport>, but its widget id and hash came from different Median keys. Derive both from the same key.\",\n};\n\n/**\n * The live conversation behind the widget: a session token for this browser,\n * the thread as Convex sees it, and a send that uploads files first. The\n * widget itself stays dumb; this is the seam the SDK promised it.\n */\nexport function useMedianThread(\n apiKey: string,\n user?: MedianUser,\n /** Whether to read the browser's own answers along with a message. */\n telemetry = true,\n /**\n * Nobody may write yet, so nothing is read either: a visitor who has to\n * sign in first is not shown a thread they cannot answer, and the widget\n * holds no conversation open behind the invitation to sign in.\n */\n isLocked = false,\n /** What to watch going wrong on the page, if the host wants any of it. */\n diagnostics?: MedianDiagnostics,\n /** The host's own state, read at send time. */\n appState?: Record<string, string | number | boolean>,\n /**\n * Whether this page asks for an email before a visitor's first message.\n * The team answers through `config.requireEmail`, and both have to agree:\n * either side can waive the question.\n */\n requireEmail = true,\n) {\n // The session token is external state (localStorage), read as a store: the\n // server snapshot is null, so SSR and the first client paint agree, and the\n // browser's token takes over from there. Subscribed so `reset()` lands\n // here, mints a new token, and the thread starts over.\n const sessionId = useSyncExternalStore(\n subscribeSession,\n useCallback(() => getOrCreateSessionId(apiKey), [apiKey]),\n () => null,\n );\n\n const config = useQuery(api.widget.config, { apiKey });\n\n // The answer to the composer's question, if this browser has given one.\n const [visitorEmail, setVisitorEmail] = useVisitorEmail(apiKey);\n\n /**\n * Whether the composer asks who they are before it takes a message. All\n * three have to say so: the page's own rule, the team's switch, and the\n * fact that nobody here knows an address already. A host who passes\n * `user.email` has answered on their visitor's behalf; the question never\n * comes up. Before the config lands there is no team answer yet, and the\n * panel is still shimmering besides, so the default holds.\n */\n const askForEmail =\n requireEmail &&\n (config?.requireEmail ?? true) &&\n !visitorEmail &&\n !(typeof user?.email === \"string\" && user.email.trim().length > 0);\n\n const thread = useQuery(\n api.widget.thread,\n sessionId === null || isLocked ? \"skip\" : { apiKey, sessionId },\n );\n const send = useMutation(api.widget.send);\n const sendTyping = useMutation(api.widget.setTyping);\n const sendPresence = useMutation(api.widget.presence);\n const rateConversation = useMutation(api.widget.rate);\n const identify = useMutation(api.widget.identify);\n const generateUploadUrl = useMutation(api.widget.generateUploadUrl);\n\n // Who they are can change without them saying a word: they sign in on the\n // host's page while the thread a teammate is reading still says nobody.\n //\n // Serialised and parsed back, which looks like a detour and is the point.\n // A host almost always builds this object inline, so it is a new one on\n // every render and a new identity to any effect watching it; the string is\n // the same until the facts in it are not.\n const identityKey = user ? JSON.stringify(user) : null;\n const identity = useMemo(\n () => (identityKey === null ? null : (JSON.parse(identityKey) as MedianUser)),\n [identityKey],\n );\n\n useEffect(() => {\n if (sessionId === null || identity === null) return;\n const { facts, claim } = splitIdentity(identity);\n\n // Best effort on the facts: they ride along with the next message anyway,\n // which is exactly where they were before this existed. A signature that\n // was offered and refused is worth saying out loud though, because the\n // host is the only one who can fix it and nothing visibly breaks.\n identify({\n apiKey,\n sessionId,\n user: facts,\n ...(claim ? { identity: claim } : {}),\n })\n .then((status) => {\n const complaint = IDENTITY_COMPLAINTS[status];\n if (complaint) console.error(complaint);\n })\n .catch(() => {});\n }, [apiKey, sessionId, identity, identify]);\n\n // A fast clock only while a teammate's dots are on screen, so they expire\n // on time without the widget re-rendering every second forever.\n const hasLiveDots =\n thread?.messages.some(\n (message) => message.pending && message.typingAt !== null,\n ) ?? false;\n const now = useNow(hasLiveDots ? 1000 : 60_000);\n\n const takeDiagnostics = useDiagnostics(diagnostics, appState);\n\n const [isSending, setIsSending] = useState(false);\n const [sendError, setSendError] = useState<string | null>(null);\n\n const agent: SupportAgent | null = useMemo(\n () =>\n config === undefined\n ? null\n : {\n id: \"median-agent\",\n name: config.agent.name,\n kind: \"ai\",\n avatarUrl: config.agent.avatarUrl,\n },\n [config],\n );\n\n const messages: SupportMessage[] = useMemo(() => {\n if (!thread || agent === null) return [];\n\n const out: SupportMessage[] = [];\n let previousAt: number | undefined;\n let previousConversationId: string | undefined;\n\n for (const message of thread.messages) {\n // A typing bubble whose teammate stopped refreshing it: the browser on\n // the other end went away, so the dots go too.\n if (\n message.pending &&\n message.typingAt !== null &&\n now - message.typingAt > TYPING_TTL_MS\n ) {\n continue;\n }\n\n out.push({\n id: message._id,\n sender: message.sender,\n body: message.body,\n time: formatClockTime(message.createdAt),\n sentAt: message.createdAt,\n dayLabel: isNewDay(previousAt, message.createdAt)\n ? formatDayLabel(message.createdAt, now)\n : undefined,\n // Not on the very first message: the history has to start somewhere,\n // and a line above the only conversation there has ever been would be\n // marking a boundary that does not exist.\n startsConversation:\n previousConversationId !== undefined &&\n previousConversationId !== message.conversationId\n ? true\n : undefined,\n agent:\n message.agent === null\n ? undefined\n : message.agent.kind === \"ai\"\n ? agent\n : {\n id: `human-${message.agent.name}`,\n name: message.agent.name,\n kind: \"human\",\n avatarUrl: message.agent.avatarUrl,\n },\n pending: message.pending || undefined,\n attachments:\n message.attachments.length > 0\n ? message.attachments.map((attachment) => {\n const kind = attachmentKindOf(attachment.type);\n return {\n id: attachment.id,\n kind,\n name: attachment.name,\n size: formatFileSize(attachment.size),\n // Only what can actually be shown small. A text file had\n // one of these too, which read as \"there is a thumbnail\n // here\" everywhere it was checked.\n previewUrl:\n kind === \"file\" ? undefined : (attachment.url ?? undefined),\n url: attachment.url ?? undefined,\n };\n })\n : undefined,\n navigateTo: message.navigateTo ?? undefined,\n highlight: message.highlight ?? undefined,\n });\n previousAt = message.createdAt;\n previousConversationId = message.conversationId;\n }\n\n return out;\n }, [thread, agent, now]);\n\n // The faces in the corner: the AI, then anyone human who has spoken.\n const presence: SupportPresence | null = useMemo(() => {\n if (config === undefined || agent === null) return null;\n\n const humans = new Map<string, SupportAgent>();\n for (const message of messages) {\n if (message.agent && message.agent.kind === \"human\") {\n humans.set(message.agent.id, message.agent);\n }\n }\n\n return {\n name: config.orgName,\n status: \"Support online\",\n team: [...[...humans.values()].slice(-2), agent],\n };\n }, [config, agent, messages]);\n\n // What they had seen last time the panel was open. Read once, from storage,\n // so a reply that landed while it was closed survives them clicking through\n // to another page on the host's site.\n const [lastSeenAt, setLastSeenAt] = useState(() => readLastSeenAt(apiKey));\n\n /**\n * Replies they have not looked at. Only the other side's, and only ones\n * that have actually been written: a bubble still holding dots is not news.\n */\n const unreadCount = useMemo(\n () =>\n messages.filter(\n (message) =>\n message.sender === \"agent\" &&\n !message.pending &&\n (message.sentAt ?? 0) > lastSeenAt,\n ).length,\n [messages, lastSeenAt],\n );\n\n // Asking how it went, once, on a conversation that is over.\n //\n // Three things decide whether the card is up, and all three are read\n // rather than remembered: the thread is resolved, nobody has answered yet,\n // and they have not waved it away. Pressing a star writes a rating, which\n // would otherwise take the card off screen mid-sentence, so a pick made\n // here keeps it open until they are finished with it.\n const [picked, setPicked] = useState<{\n conversationId: string;\n stars: number;\n } | null>(null);\n // Read from storage rather than started empty: a skip has to outlive the\n // remount that clicking a link on the host's site costs us.\n const [skipped, setSkipped] = useState<ReadonlySet<string>>(() =>\n readSkippedRatings(apiKey),\n );\n\n const conversationId = thread?.conversationId ?? null;\n const savedRating = thread?.rating ?? null;\n const isMine = picked?.conversationId === conversationId;\n\n const rating: SupportRating | null =\n thread?.status === \"resolved\" &&\n conversationId !== null &&\n !skipped.has(conversationId) &&\n (savedRating === null || isMine)\n ? {\n stars: isMine ? picked.stars : (savedRating?.stars ?? null),\n submit: async (stars, feedback) => {\n // Never null by the time a thread has been read, and a quiet\n // return here would read on screen as a rating that landed.\n if (sessionId === null) throw new Error(\"No session yet.\");\n setPicked({ conversationId, stars });\n await rateConversation({\n apiKey,\n sessionId,\n conversationId,\n stars,\n ...(feedback ? { feedback } : {}),\n });\n },\n skip: () => {\n writeSkippedRating(apiKey, conversationId);\n setSkipped((current) => new Set(current).add(conversationId));\n },\n }\n : null;\n\n /** They are looking at it, so the newest thing in it has been seen. */\n const markSeen = useCallback(() => {\n const newest = messages.reduce(\n (latest, message) => Math.max(latest, message.sentAt ?? 0),\n 0,\n );\n if (newest <= lastSeenAt) return;\n\n writeLastSeenAt(apiKey, newest);\n setLastSeenAt(newest);\n }, [apiKey, messages, lastSeenAt]);\n\n async function handleSend(body: string, files: File[]) {\n if (sessionId === null || isSending) return;\n\n setSendError(null);\n setIsSending(true);\n // Whatever the host attached since the last send rides this message.\n // Taken outside the try so a failed upload hands it back too.\n const custom = takeCustomData();\n try {\n const attachments = await uploadAttachments(\n () => generateUploadUrl({ apiKey }),\n files,\n );\n\n // Read now rather than on mount: all of it is wanted as \"what was true\n // when they wrote\", and a widget can sit closed on a page for an hour\n // before anybody says anything.\n const context = telemetry ? collectContext() : undefined;\n const page = telemetry ? collectPage() : undefined;\n\n // Nothing the first time a healthy page sends twice in a row: the\n // snapshot only travels when something new has gone wrong since.\n const collected = takeDiagnostics();\n\n // The same split as above, and this is the call that needs it most: a\n // visitor's first message is what creates them, so it is the only chance\n // to put them straight onto the account they are already signed in to.\n const { facts, claim } = splitIdentity(user ?? null);\n\n // The address typed at the composer's question rides along the same way\n // a host's facts do, but never over one the host already knows.\n const withEmail =\n facts.email || !visitorEmail ? facts : { ...facts, email: visitorEmail };\n\n await send({\n apiKey,\n sessionId,\n body,\n ...(Object.keys(withEmail).length > 0 ? { user: withEmail } : {}),\n ...(claim ? { identity: claim } : {}),\n ...(context ? { context } : {}),\n ...(page ? { page } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n ...(collected ? { diagnostics: collected } : {}),\n ...(custom ? { customData: custom } : {}),\n });\n } catch (caught) {\n // Back in the queue, so the retry carries them like it keeps the draft.\n if (custom) restoreCustomData(custom);\n console.error(\"Sending from the support widget failed\", caught);\n setSendError(errorMessage(caught));\n // Rethrown so the composer keeps the draft: a failed send should cost\n // a retry, never a retype.\n throw caught;\n } finally {\n setIsSending(false);\n }\n }\n\n function handleTypingChange(isTyping: boolean) {\n if (sessionId === null) return;\n // Best effort: dots that fail to show are not worth an error.\n sendTyping({ apiKey, sessionId, isTyping }).catch(() => {});\n }\n\n /**\n * The panel is visible right now. Whatever renders the thread calls this\n * on open and every so often after, and it is what stands between a\n * customer and an email copy of a reply they are already reading.\n */\n const reportPresence = useCallback(() => {\n if (sessionId === null || isLocked) return;\n // Best effort, like typing: a missed heartbeat costs one stray email at\n // worst, and an error here has nobody to be shown to.\n sendPresence({ apiKey, sessionId }).catch(() => {});\n }, [apiKey, sessionId, isLocked, sendPresence]);\n\n // Nearly always null. Its own value rather than a message in the list,\n // because it belongs to a tool run and not to anything anybody said.\n const ask: SupportAsk | null = thread?.direction ?? null;\n\n return {\n presence,\n messages,\n /** Something a tool run asked of this page, with no message to ride on. */\n ask,\n /**\n * The live thread, or null before there is one. Read by whatever has to\n * tell \"the next thing in this conversation\" from \"a different\n * conversation altogether\", which is what signing in produces.\n */\n conversationId,\n /**\n * Still finding out whether this browser has a conversation already.\n * Locked, there is only the host's name to wait for, and the invitation\n * to sign in names them.\n */\n isLoading:\n config === undefined ||\n (!isLocked && (sessionId === null || thread === undefined)),\n isSending,\n /**\n * Whether the composer asks for an email before a first message. The\n * page's rule and the team's switch both have to want it, and nobody\n * here may know an address already.\n */\n askForEmail,\n /** What the composer's question does with a good answer. */\n setVisitorEmail,\n /** The agent asked for a person, and nobody has answered yet. */\n awaitingHuman: thread?.awaitingHuman ?? false,\n /** The question a finished conversation asks, while it is worth asking. */\n rating,\n /** Replies that arrived while they were not looking. */\n unreadCount,\n markSeen,\n /** Say the panel is on screen, so replies are not also emailed. */\n reportPresence,\n sendError,\n send: handleSend,\n setTyping: handleTypingChange,\n };\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * The current time, refreshed on an interval, so relative timestamps (\"2m\")\n * drift forward without anyone touching the page. One state per caller keeps\n * this dumb; the inbox only needs it once.\n */\nexport function useNow(intervalMs = 30_000): number {\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), intervalMs);\n return () => clearInterval(timer);\n }, [intervalMs]);\n\n return now;\n}\n","import { ConvexError } from \"convex/values\";\n\nconst FALLBACK = \"Something went wrong on our end. Please try again.\";\n\ntype ErrorPayload = { code: string; message: string };\n\nfunction isErrorPayload(data: unknown): data is ErrorPayload {\n return (\n typeof data === \"object\" &&\n data !== null &&\n \"message\" in data &&\n typeof (data as ErrorPayload).message === \"string\"\n );\n}\n\n/**\n * Turns anything thrown by a Convex call into a sentence worth showing.\n * Only errors we raised on purpose are surfaced; everything else falls back so\n * we never paste a stack trace into the UI.\n */\nexport function errorMessage(error: unknown): string {\n if (error instanceof ConvexError) {\n if (typeof error.data === \"string\") return error.data;\n if (isErrorPayload(error.data)) return error.data.message;\n }\n return FALLBACK;\n}\n","/**\n * Timestamps, written the way the inbox and the widget say them. All of it\n * runs on the client with a real clock, so the backend only ever stores\n * numbers.\n */\n\nconst MINUTE = 60_000;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\n/**\n * A time of day, wherever one is printed: beside a message, and under a\n * visitor's name for the clock where they are.\n *\n * Twelve hour on purpose rather than by the reader's locale. Two clocks can\n * sit on one screen here, one for the message and one for the customer, and\n * they came from different formatters; leaving the shape to the locale meant\n * they agreed only by luck, and a reader in a country that counts to\n * twenty-four saw a screen that could not decide.\n *\n * The rest is still the reader's. Which characters mark the afternoon is a\n * question their locale answers better than we can.\n */\nexport const CLOCK_FORMAT = {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n} as const satisfies Intl.DateTimeFormatOptions;\n\n/** \"3:58 PM\", for the line beside a message. */\nexport function formatClockTime(timestamp: number): string {\n return new Date(timestamp).toLocaleTimeString([], CLOCK_FORMAT);\n}\n\n/** \"now\", \"2m\", \"3h\", \"2d\", then a date, for a queue row. */\nexport function formatTimeAgo(timestamp: number, now: number): string {\n const elapsed = now - timestamp;\n if (elapsed < MINUTE) return \"now\";\n if (elapsed < HOUR) return `${Math.floor(elapsed / MINUTE)}m`;\n if (elapsed < DAY) return `${Math.floor(elapsed / HOUR)}h`;\n if (elapsed < 7 * DAY) return `${Math.floor(elapsed / DAY)}d`;\n return new Date(timestamp).toLocaleDateString([], {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/**\n * \"just now\", \"2m ago\", \"Mar 3\", for a line about when something last ran.\n *\n * The queue's own shorthand reads as a column of times, which is right beside\n * a conversation and wrong in a sentence: \"synced 2m\" is not a thing anybody\n * says. Same clock, said out loud.\n */\nexport function formatSyncedAgo(timestamp: number, now: number): string {\n const ago = formatTimeAgo(timestamp, now);\n if (ago === \"now\") return \"just now\";\n return /^\\d/.test(ago) ? `${ago} ago` : ago;\n}\n\n/** Minutes since, for sorting rows the way the demo data did. */\nexport function minutesSince(timestamp: number, now: number): number {\n return Math.max(0, Math.floor((now - timestamp) / MINUTE));\n}\n\n/** \"March 2023\", for the customer since row and past conversations. */\nexport function formatMonthYear(timestamp: number): string {\n return new Date(timestamp).toLocaleDateString([], {\n month: \"long\",\n year: \"numeric\",\n });\n}\n\nfunction startOfDay(timestamp: number): number {\n const date = new Date(timestamp);\n date.setHours(0, 0, 0, 0);\n return date.getTime();\n}\n\n/** \"Today\", \"Yesterday\", \"Monday\", then a date, for a thread divider. */\nexport function formatDayLabel(timestamp: number, now: number): string {\n const days = Math.round((startOfDay(now) - startOfDay(timestamp)) / DAY);\n if (days <= 0) return \"Today\";\n if (days === 1) return \"Yesterday\";\n if (days < 7) {\n return new Date(timestamp).toLocaleDateString([], { weekday: \"long\" });\n }\n return new Date(timestamp).toLocaleDateString([], {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** How many whole days apart two timestamps land, by the calendar. */\nfunction daysApart(from: number, to: number): number {\n return Math.round((startOfDay(to) - startOfDay(from)) / DAY);\n}\n\n/**\n * \"9:00 AM\", \"tomorrow, 9:00 AM\", \"Mon, 9:00 AM\", \"Mar 4\": when a snooze is\n * up, as short as it can be said without leaving anyone guessing which day.\n */\nexport function formatSnoozeAt(until: number, now: number): string {\n const days = daysApart(now, until);\n if (days >= 7) {\n return new Date(until).toLocaleDateString([], {\n month: \"short\",\n day: \"numeric\",\n });\n }\n\n const time = formatClockTime(until);\n if (days <= 0) return time;\n if (days === 1) return `tomorrow, ${time}`;\n return `${new Date(until).toLocaleDateString([], { weekday: \"short\" })}, ${time}`;\n}\n\n/** Whether two timestamps land on different days, so a thread can divide. */\nexport function isNewDay(previous: number | undefined, next: number): boolean {\n if (previous === undefined) return true;\n return startOfDay(previous) !== startOfDay(next);\n}\n","import type { Id } from \"@median/backend/dataModel\";\n\n/**\n * POSTs one file to a one shot Convex upload URL and hands back its storage\n * id. The URL comes from whichever mutation guards the caller, so the same\n * helper serves the inbox, the widget, and the settings page.\n */\nexport async function uploadFile(\n getUploadUrl: () => Promise<string>,\n file: File,\n): Promise<Id<\"_storage\">> {\n const url = await getUploadUrl();\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": file.type || \"application/octet-stream\" },\n body: file,\n });\n if (!response.ok) {\n throw new Error(`Uploading ${file.name} failed with ${response.status}`);\n }\n\n const { storageId } = (await response.json()) as {\n storageId: Id<\"_storage\">;\n };\n return storageId;\n}\n\n/** The shape a message mutation wants a sent file described in. */\nexport type SentAttachment = {\n storageId: Id<\"_storage\">;\n name: string;\n size: number;\n type: string;\n};\n\n/** Uploads a batch in order and describes each one for the send mutation. */\nexport async function uploadAttachments(\n getUploadUrl: () => Promise<string>,\n files: File[],\n): Promise<SentAttachment[]> {\n const attachments: SentAttachment[] = [];\n for (const file of files) {\n attachments.push({\n storageId: await uploadFile(getUploadUrl, file),\n name: file.name,\n size: file.size,\n type: file.type || \"application/octet-stream\",\n });\n }\n return attachments;\n}\n","/**\n * Which finished conversations somebody has already waved the rating card\n * away on.\n *\n * Beside the session token and the read marker, and kept for the same\n * reason: a host's site is several pages, so the widget is remounted every\n * time somebody clicks a link. Held in memory, a skip would last until the\n * next click and the card would be back. Skipping is a no thanks, and asking\n * again is how a no thanks turns into a nuisance.\n *\n * One entry per API key, like the others, and capped: a browser that has\n * skipped a hundred conversations has no reason to carry all hundred ids\n * around, and the oldest of them are threads nobody will see again anyway.\n */\n\nconst STORAGE_PREFIX = \"median:rating-skips:\";\n\n/** How many are worth remembering. Past this, the oldest fall off. */\nconst MAX_REMEMBERED = 20;\n\n/** Where they live when localStorage is blocked. Lasts the page load. */\nconst inMemory = new Map<string, string[]>();\n\nfunction read(apiKey: string): string[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const stored = window.localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`);\n if (stored === null) return [];\n const parsed: unknown = JSON.parse(stored);\n return Array.isArray(parsed)\n ? parsed.filter((one): one is string => typeof one === \"string\")\n : [];\n } catch {\n // Blocked, or somebody put something else under our key.\n return inMemory.get(apiKey) ?? [];\n }\n}\n\n/** The conversations this browser has already said no thanks to. */\nexport function readSkippedRatings(apiKey: string): ReadonlySet<string> {\n return new Set(read(apiKey));\n}\n\n/** One more no thanks, remembered across the pages of a host's site. */\nexport function writeSkippedRating(\n apiKey: string,\n conversationId: string,\n): void {\n if (typeof window === \"undefined\") return;\n\n const next = [\n ...read(apiKey).filter((one) => one !== conversationId),\n conversationId,\n ].slice(-MAX_REMEMBERED);\n\n inMemory.set(apiKey, next);\n try {\n window.localStorage.setItem(\n `${STORAGE_PREFIX}${apiKey}`,\n JSON.stringify(next),\n );\n } catch {\n // Blocked, so the in-memory copy above is all there is. It still holds\n // for as long as they are on the page they skipped it from.\n }\n}\n","/**\n * How much of the conversation this browser has already seen.\n *\n * Kept beside the session token and for the same reason: a host's site is\n * usually several pages, so the widget is remounted every time somebody\n * clicks a link. Held in memory, a reply that arrived while the panel was\n * closed would stop being new the moment they wandered to another page.\n *\n * One entry per API key, like the session, so two widgets on one browser\n * cannot mark each other's messages read.\n */\n\nconst STORAGE_PREFIX = \"median:read:\";\n\n/** Where it lives when localStorage is blocked. Lasts the page load. */\nconst inMemory = new Map<string, number>();\n\n/** When they last had the panel open, or 0 if they never have. */\nexport function readLastSeenAt(apiKey: string): number {\n if (typeof window === \"undefined\") return 0;\n\n try {\n const stored = window.localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`);\n const at = stored === null ? Number.NaN : Number(stored);\n return Number.isFinite(at) ? at : 0;\n } catch {\n return inMemory.get(apiKey) ?? 0;\n }\n}\n\nexport function writeLastSeenAt(apiKey: string, at: number): void {\n if (typeof window === \"undefined\") return;\n\n inMemory.set(apiKey, at);\n try {\n window.localStorage.setItem(`${STORAGE_PREFIX}${apiKey}`, String(at));\n } catch {\n // Blocked, so the in-memory copy above is all there is. It still stops\n // the badge coming back while they are looking straight at the panel.\n }\n}\n","\"use client\";\n\n/**\n * The address a visitor typed at the composer's question, kept beside the\n * session token and for the same reason: a host's site is usually several\n * pages, so the widget is remounted every time somebody clicks a link, and\n * asking all over again on each one is not a question, it is a wall.\n *\n * It rides the visitor's first message like any other fact the host passes,\n * which is what puts it on their row in the team's inbox.\n */\n\nimport { useCallback, useSyncExternalStore } from \"react\";\n\nconst STORAGE_PREFIX = \"median:email:\";\n\n/** Where it lives when localStorage is blocked. Lasts the page load. */\nconst inMemory = new Map<string, string>();\n\nconst listeners = new Set<() => void>();\n\nexport function subscribeVisitorEmail(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n/** The address this browser gave, or null before it has. */\nexport function readVisitorEmail(apiKey: string): string | null {\n if (typeof window === \"undefined\") return null;\n\n try {\n const stored = window.localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`);\n return stored && stored.length > 0 ? stored : null;\n } catch {\n return inMemory.get(apiKey) ?? null;\n }\n}\n\nfunction writeVisitorEmail(apiKey: string, email: string): void {\n inMemory.set(apiKey, email);\n try {\n window.localStorage.setItem(`${STORAGE_PREFIX}${apiKey}`, email);\n } catch {\n // Blocked, so the in-memory copy above is all there is. It still gets\n // them through this page, where the message that carries it goes out.\n }\n\n for (const listener of listeners) listener();\n}\n\n/**\n * Forget every address this browser holds. Part of `medianSupport.reset()`,\n * which has to detach a browser from its conversation completely: an email\n * that survived a sign out would greet the next person at the keyboard with\n * somebody else's name.\n */\nexport function resetVisitorEmails() {\n inMemory.clear();\n\n if (typeof window !== \"undefined\") {\n try {\n const stale: string[] = [];\n for (let i = 0; i < window.localStorage.length; i += 1) {\n const key = window.localStorage.key(i);\n if (key !== null && key.startsWith(STORAGE_PREFIX)) stale.push(key);\n }\n for (const key of stale) window.localStorage.removeItem(key);\n } catch {\n // Storage was blocked, so there was nothing durable to forget.\n }\n }\n\n for (const listener of listeners) listener();\n}\n\n/**\n * The address, live: subscribed, so a reset while the widget is mounted asks\n * again rather than trusting state that outlived its storage. The setter is\n * what the composer's question calls once the answer checks out.\n */\nexport function useVisitorEmail(\n apiKey: string,\n): [string | null, (email: string) => void] {\n const email = useSyncExternalStore(\n subscribeVisitorEmail,\n useCallback(() => readVisitorEmail(apiKey), [apiKey]),\n () => null,\n );\n\n const setEmail = useCallback(\n (next: string) => writeVisitorEmail(apiKey, next),\n [apiKey],\n );\n\n return [email, setEmail];\n}\n","\"use client\";\n\nimport { ConvexError } from \"convex/values\";\nimport { Component, type ReactNode } from \"react\";\n\n/**\n * The widget runs on somebody else's page, so whatever goes wrong in here must\n * never take the host's site down with it. The widget quietly steps off the\n * page and says why in the console, where the person installing it is already\n * looking.\n */\n\n/**\n * Name the actual problem when we can. \"Check the apiKey\" is the right advice\n * for a rejected key and a wild goose chase for everything else.\n */\nfunction adviceFor(error: unknown): string {\n if (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n (error.data as { code?: string }).code === \"invalid_api_key\"\n ) {\n return \"Median did not recognize the apiKey passed to <MedianSupport>, so the widget has been hidden. Derive it from an active MEDIAN_KEY with publicKeyFromMedianKey.\";\n }\n return \"The Median support widget hit an error and has been hidden. Your page is unaffected.\";\n}\n\nexport class MedianErrorBoundary extends Component<\n { children: ReactNode },\n { hasFailed: boolean }\n> {\n state = { hasFailed: false };\n\n static getDerivedStateFromError() {\n return { hasFailed: true };\n }\n\n componentDidCatch(error: unknown) {\n console.error(adviceFor(error), error);\n }\n\n render() {\n return this.state.hasFailed ? null : this.props.children;\n }\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { MedianUser } from \"./use-median-thread\";\n\n/**\n * Who is signed in, fetched from the host's own route rather than passed down\n * their tree.\n *\n * The widget is a client component and the signature can only be made on a\n * server, so on an app with a server rendered root layout there is nowhere\n * that has both the session and this component. The route in the middle is\n * always the same one, so `medianIdentity` in @mediansh/agent-tools ships it\n * and this reads it.\n *\n * The publishable key comes down the same way. A host who points at a route\n * has one Median value in their app instead of two, and the browser safe half\n * of the key never has to be plumbed into a client environment by hand.\n */\n\n/** What `medianIdentity` answers with. Both fields absent is a valid answer. */\ntype IdentityResponse = {\n apiKey?: string;\n user?: MedianUser;\n};\n\nexport type ResolvedIdentity = {\n apiKey: string | undefined;\n user: MedianUser | undefined;\n /**\n * The answer is still on its way. True only while a route is actually being\n * read: a widget given no route is never waiting for one.\n *\n * The panel holds its loading state on this rather than showing the sign in\n * invitation, because \"we have not asked yet\" and \"they are not signed in\"\n * look identical from here and only one of them is worth telling somebody.\n */\n isLoading: boolean;\n};\n\nconst NOTHING: ResolvedIdentity = {\n apiKey: undefined,\n user: undefined,\n isLoading: false,\n};\n\n/** A route has been named and has not answered yet. */\nconst WAITING: ResolvedIdentity = { ...NOTHING, isLoading: true };\n\n/**\n * The request, while it is in the air, shared by everything waiting on it.\n *\n * A page with the support panel and the feedback panel on it mounts two\n * components that both want the same answer from the same route. One asks and\n * the other joins, rather than the host's server signing the same person\n * twice.\n *\n * Dropped the moment it settles, so nothing here outlives the answer. Signing\n * out and back in re-reads the route rather than being handed the last\n * person's signature out of a cache.\n */\nconst inFlight = new Map<string, Promise<IdentityResponse>>();\n\nfunction read(endpoint: string): Promise<IdentityResponse> {\n const existing = inFlight.get(endpoint);\n if (existing !== undefined) return existing;\n\n const request = (async () => {\n const response = await fetch(endpoint, {\n // The session lives in a cookie, and a cross origin route only sees it\n // if the request asks. Same origin routes are unaffected.\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n });\n if (!response.ok) {\n throw new Error(\n `${endpoint} answered ${response.status}. It should return { apiKey, user } from medianIdentity().`,\n );\n }\n return (await response.json()) as IdentityResponse;\n })().finally(() => inFlight.delete(endpoint));\n\n inFlight.set(endpoint, request);\n return request;\n}\n\n/**\n * Neither half was passed, so there is nothing to connect to and nothing on\n * the page. Silence here is the worst outcome: the install looks done, the\n * corner is empty, and there is no error anywhere to explain it.\n *\n * Said from the browser rather than checked by the types alone, because a\n * host on plain JavaScript, or one building options up across an `update()`\n * call, never sees the types.\n */\nexport function useMissingCredentials(\n component: string,\n apiKey: string | undefined,\n endpoint: string | undefined,\n): void {\n useEffect(() => {\n if (apiKey !== undefined || endpoint !== undefined) return;\n console.error(\n `Median: <${component}> was given neither apiKey nor identity, so nothing is on the page. Pass the median_pk_ id from publicKeyFromMedianKey(MEDIAN_KEY), or the path of a route built with medianIdentity().`,\n );\n }, [component, apiKey, endpoint]);\n}\n\nexport function useMedianIdentity(\n endpoint: string | undefined,\n): ResolvedIdentity {\n // The answer, with the route it is an answer to.\n //\n // Kept as a pair, and read back below only when the two still agree,\n // because that is what makes \"we are waiting\" a fact about the current\n // route rather than a flag something has to remember to set. Nothing here\n // writes state on the way in, and a route that changes is one comparison\n // rather than a reset.\n const [answered, setAnswered] = useState<{\n endpoint: string;\n identity: ResolvedIdentity;\n } | null>(null);\n\n useEffect(() => {\n if (endpoint === undefined) return;\n\n // A flag rather than an AbortController: the request can be shared with\n // the other panel on the page, and one of them unmounting must not cancel\n // the answer the other is still waiting for.\n let listening = true;\n\n void (async () => {\n try {\n const body = await read(endpoint);\n if (!listening) return;\n setAnswered({\n endpoint,\n identity: {\n apiKey: body.apiKey,\n // An id without its signature is ignored by the backend anyway,\n // so it is dropped here rather than sent up to be refused.\n user: body.user?.hash ? body.user : undefined,\n isLoading: false,\n },\n });\n } catch (caught) {\n if (!listening) return;\n // Support stays on the page. Without a key from anywhere the widget\n // has nothing to talk to and says so through its own boundary; with\n // one, this is a visitor whose thread belongs to their browser, which\n // is where every anonymous visitor already is.\n console.error(\n \"Median: could not read the identity route.\",\n caught instanceof Error ? caught.message : caught,\n );\n setAnswered({ endpoint, identity: NOTHING });\n }\n })();\n\n return () => {\n listening = false;\n };\n }, [endpoint]);\n\n if (endpoint === undefined) return NOTHING;\n if (answered?.endpoint === endpoint) return answered.identity;\n return WAITING;\n}\n","/**\n * The sound palette — layer/recipe types plus the seventeen built-in recipes.\n * Each sound has its own distinct shape — a chime, an arpeggio, a pitch\n * glide, a warm pad, a breath — rather than being a volume/EQ tweak on\n * the same click. Add a new one here without touching any audio graph code.\n */\nexport const RECIPES = {\n /** A soft two-note ascending bell, like an iOS/macOS confirmation tink. */\n chime: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 1046.5, attack: 0.006, decay: 0.22, peak: 0.09 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1568, offset: 0.09, attack: 0.006, decay: 0.26, peak: 0.08 },\n ],\n shimmer: { delay: 0.12, feedback: 0.25, wet: 0.18, lowpass: 4000 },\n },\n /** A quick ascending twinkle of four notes — bright and playful. */\n sparkle: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 1760, offset: 0, attack: 0.003, decay: 0.09, peak: 0.045 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2217, offset: 0.045, attack: 0.003, decay: 0.09, peak: 0.04 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2637, offset: 0.09, attack: 0.003, decay: 0.1, peak: 0.038 },\n { kind: \"tone\", waveform: \"sine\", frequency: 3520, offset: 0.135, attack: 0.003, decay: 0.12, peak: 0.032 },\n ],\n shimmer: { delay: 0.07, feedback: 0.35, wet: 0.22, lowpass: 6000 },\n },\n /** A single note gliding smoothly downward, like a drop of water. */\n droplet: {\n masterGain: 0.55,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 1200, glideTo: 550, glideTime: 0.14, attack: 0.004, decay: 0.2, peak: 0.075 },\n ],\n shimmer: { delay: 0.09, feedback: 0.2, wet: 0.15, lowpass: 3000 },\n },\n /** A warm, slow-swelling pad from two gently detuned sines. */\n bloom: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 528, attack: 0.06, decay: 0.32, peak: 0.06 },\n { kind: \"tone\", waveform: \"sine\", frequency: 528, detune: 12, attack: 0.06, decay: 0.34, peak: 0.05 },\n ],\n shimmer: { delay: 0.15, feedback: 0.2, wet: 0.12, lowpass: 2500 },\n },\n /** A soft hush with a falling tone — for tooltips and low-priority previews. */\n whisper: {\n masterGain: 0.48,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 1600, filterQ: 0.7, attack: 0.025, decay: 0.13, peak: 0.04 },\n { kind: \"tone\", waveform: \"sine\", frequency: 880, glideTo: 660, glideTime: 0.14, offset: 0.01, attack: 0.012, decay: 0.14, peak: 0.025 },\n ],\n },\n /** A focused, bandpass-filtered tick with a bright sine ping on top — crisp and instant. */\n tick: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 5400, filterQ: 1.8, attack: 0.001, decay: 0.018, peak: 0.14 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2600, attack: 0.001, decay: 0.012, peak: 0.018 },\n ],\n },\n /** A dull, muted knock — the \"down\" half of a press/release pair, like a key bottoming out. */\n press: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 1700, filterQ: 1.4, attack: 0.001, decay: 0.02, peak: 0.13 },\n ],\n },\n /** A brighter, springier tick — the \"up\" half of a press/release pair, like a key returning. */\n release: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 4600, filterQ: 1.8, attack: 0.001, decay: 0.016, peak: 0.12 },\n { kind: \"tone\", waveform: \"sine\", frequency: 3200, offset: 0.006, attack: 0.001, decay: 0.05, peak: 0.02 },\n ],\n },\n /** A two-part click-clack, like a mechanical switch flipping between states. */\n toggle: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 2200, filterQ: 1.6, attack: 0.001, decay: 0.016, peak: 0.12 },\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 3800, filterQ: 1.6, offset: 0.024, attack: 0.001, decay: 0.02, peak: 0.1 },\n ],\n },\n /** A short, warm three-note ascending confirmation — \"done\", not a fanfare. */\n success: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 880, attack: 0.004, decay: 0.09, peak: 0.06 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1108.73, offset: 0.06, attack: 0.004, decay: 0.1, peak: 0.06 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1318.51, offset: 0.12, attack: 0.004, decay: 0.18, peak: 0.07 },\n ],\n shimmer: { delay: 0.1, feedback: 0.22, wet: 0.16, lowpass: 4500 },\n },\n /** A muted knock followed by two descending tones — a calm, recoverable refusal. */\n error: {\n masterGain: 0.42,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 850, filterQ: 1.1, attack: 0.001, decay: 0.035, peak: 0.13 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 440, offset: 0.025, attack: 0.004, decay: 0.09, peak: 0.045 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 349.23, offset: 0.1, attack: 0.004, decay: 0.14, peak: 0.04 },\n ],\n },\n /** A papery filtered flick with a tiny glass tick — for pages, galleries, and carousels. */\n page: {\n masterGain: 0.38,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 1800, filterQ: 0.7, attack: 0.006, decay: 0.08, peak: 0.11 },\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 4200, filterQ: 1.2, offset: 0.04, attack: 0.004, decay: 0.065, peak: 0.08 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2400, offset: 0.075, attack: 0.002, decay: 0.045, peak: 0.02 },\n ],\n },\n /** A brief unresolved lift — signals that user-initiated work has started. */\n loading: {\n masterGain: 0.42,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 1400, filterQ: 0.6, attack: 0.035, decay: 0.14, peak: 0.035 },\n { kind: \"tone\", waveform: \"sine\", frequency: 420, glideTo: 630, glideTime: 0.18, attack: 0.025, decay: 0.18, peak: 0.05 },\n ],\n shimmer: { delay: 0.11, feedback: 0.18, wet: 0.12, lowpass: 2800 },\n },\n /** A quick lock-on sweep resolving to a clear tone — the system is ready. */\n ready: {\n masterGain: 0.48,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 3600, filterQ: 1.8, attack: 0.001, decay: 0.02, peak: 0.11 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 330, glideTo: 660, glideTime: 0.12, offset: 0.012, attack: 0.004, decay: 0.16, peak: 0.055 },\n { kind: \"tone\", waveform: \"sine\", frequency: 990, offset: 0.13, attack: 0.004, decay: 0.22, peak: 0.06 },\n ],\n shimmer: { delay: 0.1, feedback: 0.16, wet: 0.1, lowpass: 4200 },\n },\n /** A compact synthetic chirp — crisp feedback for primary buttons and controls. */\n pulse: {\n masterGain: 0.42,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 2600, filterQ: 2.4, attack: 0.001, decay: 0.022, peak: 0.08 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 620, glideTo: 1240, glideTime: 0.07, attack: 0.002, decay: 0.085, peak: 0.055 },\n ],\n },\n /** A fast three-step locator signal — playful feedback for menus and secondary buttons. */\n scan: {\n masterGain: 0.4,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 740, attack: 0.002, decay: 0.055, peak: 0.05 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1110, offset: 0.045, attack: 0.002, decay: 0.055, peak: 0.045 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1665, offset: 0.09, attack: 0.002, decay: 0.07, peak: 0.04 },\n ],\n shimmer: { delay: 0.065, feedback: 0.16, wet: 0.1, lowpass: 4200 },\n },\n /** A rising harmonic portal with a soft tail — for client-side page arrivals. */\n arrival: {\n masterGain: 0.44,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 900, filterQ: 0.8, attack: 0.05, decay: 0.24, peak: 0.035 },\n { kind: \"tone\", waveform: \"sine\", frequency: 220, glideTo: 440, glideTime: 0.32, attack: 0.04, decay: 0.34, peak: 0.055 },\n { kind: \"tone\", waveform: \"sine\", frequency: 659.25, offset: 0.12, attack: 0.045, decay: 0.32, peak: 0.04 },\n { kind: \"tone\", waveform: \"sine\", frequency: 987.77, offset: 0.19, attack: 0.045, decay: 0.34, peak: 0.032 },\n ],\n shimmer: { delay: 0.16, feedback: 0.28, wet: 0.18, lowpass: 3200 },\n },\n};\nexport function isSoundName(value) {\n return typeof value === \"string\" && Object.prototype.hasOwnProperty.call(RECIPES, value);\n}\n/** All available sound names, derived from the recipe palette. */\nexport const sounds = Object.keys(RECIPES);\n","/**\n * The audio engine — synthesizes each sound live via the Web Audio API\n * on one shared, lazily created `AudioContext`. No audio files, no\n * dependencies. Every sound carries a gentle envelope (and often a soft\n * shimmer tail) instead of a hard transient, so nothing feels harsh.\n */\nimport { RECIPES, isSoundName, } from \"../sounds/recipes.js\";\nconst SOURCE_STOP_PADDING = 0.05;\nconst CLEANUP_MARGIN = 0.05;\nconst INAUDIBLE_GAIN = 0.001;\nconst OUTPUT_GAIN = 4;\nfunction renderTone(context, destination, layer, startTime) {\n const oscillator = context.createOscillator();\n oscillator.type = layer.waveform;\n oscillator.frequency.setValueAtTime(layer.frequency, startTime);\n if (layer.detune)\n oscillator.detune.value = layer.detune;\n if (layer.glideTo !== undefined) {\n const glideTime = layer.glideTime ?? layer.attack + layer.decay;\n oscillator.frequency.exponentialRampToValueAtTime(layer.glideTo, startTime + glideTime);\n }\n const gain = context.createGain();\n gain.gain.setValueAtTime(0.0001, startTime);\n gain.gain.exponentialRampToValueAtTime(layer.peak, startTime + layer.attack);\n gain.gain.exponentialRampToValueAtTime(0.0001, startTime + layer.attack + layer.decay);\n oscillator.connect(gain).connect(destination);\n oscillator.start(startTime);\n oscillator.stop(startTime + layer.attack + layer.decay + SOURCE_STOP_PADDING);\n}\nfunction renderNoise(context, destination, layer, startTime) {\n const duration = layer.attack + layer.decay + SOURCE_STOP_PADDING;\n const length = Math.max(1, Math.floor(duration * context.sampleRate));\n const buffer = context.createBuffer(1, length, context.sampleRate);\n const data = buffer.getChannelData(0);\n for (let i = 0; i < length; i++)\n data[i] = 2 * Math.random() - 1;\n const source = context.createBufferSource();\n source.buffer = buffer;\n const filter = context.createBiquadFilter();\n filter.type = layer.filterType;\n filter.frequency.value = layer.filterFrequency;\n if (layer.filterQ !== undefined)\n filter.Q.value = layer.filterQ;\n const gain = context.createGain();\n gain.gain.setValueAtTime(0.0001, startTime);\n gain.gain.exponentialRampToValueAtTime(layer.peak, startTime + layer.attack);\n gain.gain.exponentialRampToValueAtTime(0.0001, startTime + layer.attack + layer.decay);\n source.connect(filter).connect(gain).connect(destination);\n source.start(startTime);\n source.stop(startTime + duration);\n}\n/** Wires a soft echo/shimmer send off `source`, feeding back into `destination`. */\nfunction attachShimmer(context, source, destination, shimmer) {\n const delay = context.createDelay(1);\n delay.delayTime.value = shimmer.delay;\n const feedbackFilter = context.createBiquadFilter();\n feedbackFilter.type = \"lowpass\";\n feedbackFilter.frequency.value = shimmer.lowpass;\n const feedbackGain = context.createGain();\n feedbackGain.gain.value = shimmer.feedback;\n const wetGain = context.createGain();\n wetGain.gain.value = shimmer.wet;\n source.connect(delay);\n delay.connect(feedbackFilter);\n feedbackFilter.connect(feedbackGain);\n feedbackGain.connect(delay);\n feedbackFilter.connect(wetGain);\n wetGain.connect(destination);\n return [delay, feedbackFilter, feedbackGain, wetGain];\n}\nfunction sourceEnd(recipe) {\n return Math.max(...recipe.layers.map((layer) => (layer.offset ?? 0) + layer.attack + layer.decay + SOURCE_STOP_PADDING));\n}\nfunction shimmerTail(shimmer) {\n if (!shimmer || shimmer.feedback <= 0)\n return 0;\n if (shimmer.feedback >= 1)\n return shimmer.delay;\n return shimmer.delay * (1 + Math.ceil(Math.log(INAUDIBLE_GAIN) / Math.log(shimmer.feedback)));\n}\nlet sharedOutput = null;\nfunction getOutput(context) {\n if (sharedOutput)\n return sharedOutput;\n const output = context.createGain();\n output.gain.value = OUTPUT_GAIN;\n const limiter = context.createDynamicsCompressor();\n limiter.threshold.value = -8;\n limiter.knee.value = 6;\n limiter.ratio.value = 12;\n limiter.attack.value = 0.002;\n limiter.release.value = 0.08;\n output.connect(limiter).connect(context.destination);\n sharedOutput = output;\n return output;\n}\nfunction renderRecipe(context, recipe, volume) {\n const now = context.currentTime;\n const output = getOutput(context);\n const master = context.createGain();\n master.gain.value = recipe.masterGain * volume;\n master.connect(output);\n const shimmerNodes = recipe.shimmer\n ? attachShimmer(context, master, output, recipe.shimmer)\n : [];\n for (const layer of recipe.layers) {\n const startTime = now + (layer.offset ?? 0);\n if (layer.kind === \"tone\")\n renderTone(context, master, layer, startTime);\n else\n renderNoise(context, master, layer, startTime);\n }\n const cleanupAfterMs = (sourceEnd(recipe) + shimmerTail(recipe.shimmer) + CLEANUP_MARGIN) * 1000;\n setTimeout(() => {\n master.disconnect();\n for (const node of shimmerNodes)\n node.disconnect();\n }, cleanupAfterMs);\n}\nlet sharedContext = null;\nlet enabled = true;\nlet globalVolume = 1;\nfunction normalizeVolume(value, fallback) {\n return typeof value === \"number\" && Number.isFinite(value)\n ? Math.min(1, Math.max(0, value))\n : fallback;\n}\n/** Enables or disables future playback. Preference storage stays with the app. */\nexport function setEnabled(value) {\n if (typeof value === \"boolean\")\n enabled = value;\n}\n/** Sets the volume multiplier for future playback. Preference storage stays with the app. */\nexport function setVolume(value) {\n globalVolume = normalizeVolume(value, globalVolume);\n}\nfunction getAudioContext() {\n if (sharedContext)\n return sharedContext;\n if (typeof window === \"undefined\")\n return null;\n const Ctor = window.AudioContext ??\n window.webkitAudioContext;\n if (!Ctor)\n return null;\n try {\n sharedContext = new Ctor();\n }\n catch {\n return null;\n }\n return sharedContext;\n}\n/**\n * Plays a sound immediately. Safe to call from anywhere — lazily creates\n * the shared `AudioContext` on first use, resumes it if the browser\n * started it suspended (e.g. before any user gesture), and is a no-op\n * when Web Audio is unavailable (SSR, old browsers).\n */\nexport function play(sound = \"chime\", options) {\n if (!enabled || !isSoundName(sound))\n return;\n if (typeof navigator !== \"undefined\" && navigator.userActivation?.hasBeenActive === false)\n return;\n const playVolume = globalVolume * normalizeVolume(options?.volume, 1);\n if (playVolume === 0)\n return;\n const context = getAudioContext();\n if (!context)\n return;\n const recipe = RECIPES[sound];\n if (context.state === \"running\") {\n renderRecipe(context, recipe, playVolume);\n }\n else {\n try {\n void context.resume().then(() => {\n if (enabled && context.state === \"running\")\n renderRecipe(context, recipe, playVolume);\n }, () => { });\n }\n catch {\n // Some browsers throw synchronously when audio is blocked.\n }\n }\n}\n","\"use client\";\n\nimport { play } from \"cuelume\";\nimport { useEffect, useRef } from \"react\";\nimport type { SupportMessage } from \"../types\";\n\n/**\n * Under the default, because this plays on somebody else's site while they are\n * reading it. Loud enough to catch with the panel closed, quiet enough to sit\n * behind whatever else they have on.\n */\nconst ARRIVAL_VOLUME = 0.45;\n\n/**\n * The twinkle a reply lands on, whether the panel is open or not. Closed is\n * where it earns its keep: the count on the launcher is the only other thing\n * saying anything came in, and nobody is looking at the corner.\n *\n * The same rule the ring and the navigation follow, for the same reason: the\n * first snapshot is history, however recent, and history does not ring. Without\n * it, every page of a host's site would open on a sparkle for a conversation\n * from last week. A thread being fetched again is a thread this page has not\n * read either, so whatever lands after that is history too.\n *\n * And a change of thread is a first snapshot of its own. Somebody signing in\n * hands this page an account's whole history at once, which is a great many\n * replies it has never heard and not one of them worth a sound.\n *\n * Only the other side's messages, and only once they are written. A bubble\n * holding dots keeps its id and fills in later, so waiting for the words means\n * the sound arrives with them rather than with the promise of them.\n *\n * `play` neither throws nor asks: it is a no-op without Web Audio, and stays\n * quiet until the visitor has interacted with the page at all. That last one is\n * the browser's rule about autoplay, and it is a rule worth keeping.\n */\nexport function useMessageSound({\n messages,\n conversationId = null,\n isLoading,\n}: {\n messages: SupportMessage[];\n /** The thread being watched. A different one starts the listening over. */\n conversationId?: string | null;\n /** Nothing is history until the first answer has arrived. */\n isLoading: boolean;\n}) {\n /** Every written reply this page has already heard. */\n const heard = useRef<Set<string> | null>(null);\n /** Which thread that set is about. */\n const watching = useRef<string | null>(null);\n\n useEffect(() => {\n if (isLoading) {\n heard.current = null;\n return;\n }\n\n const written = messages.filter(\n (message) => message.sender === \"agent\" && !message.pending,\n );\n\n if (heard.current === null || watching.current !== conversationId) {\n heard.current = new Set(written.map((message) => message.id));\n watching.current = conversationId;\n return;\n }\n\n // One sparkle however many arrived together: a person taking over and\n // answering in the same breath is still one thing to look up at.\n let hasArrived = false;\n for (const message of written) {\n if (heard.current.has(message.id)) continue;\n heard.current.add(message.id);\n hasArrived = true;\n }\n\n if (hasArrived) play(\"sparkle\", { volume: ARRIVAL_VOLUME });\n }, [messages, conversationId, isLoading]);\n}\n","\"use client\";\n\nimport { useLayoutEffect, useRef, useState } from \"react\";\nimport type { SupportAsk, SupportMessage } from \"../types\";\n\n/**\n * Doing what one of the team's own tools asked to be done to the page: taking\n * the reader somewhere, pointing at something there, or both.\n *\n * The instruction rides on the message that explains it, but a layout effect\n * acts before those words are painted. Everything here is about making sure\n * that ordering happens exactly once.\n *\n * The thread is a live query and the message stays in it forever, so \"act on\n * what I can see\" would move somebody every time the query re-ran, and again\n * every time they came back to the page. What actually counts as new is what\n * arrived after the widget started watching: the first snapshot is history,\n * however recent, and history is not an instruction. That also covers the\n * loop this would otherwise be, where a host who navigates with a full page\n * load remounts the widget onto the message that moved it.\n *\n * A thread can also change under a page that never stopped watching it.\n * Somebody signs in, the widget says who they are, and a query that answered\n * \"no conversation\" a second ago answers with the account's whole history\n * instead. Every word of it is new to this page and none of it is news, so a\n * change of thread starts the first look over, and an instruction has to be\n * recent as well as unseen before anything is done about it.\n *\n * Nothing navigates at all without `onNavigate`. Moving a host's page because\n * their server answered with a field is not a thing to do by default, and a\n * host who wired the tool but not the handler hears about it in the console\n * rather than by watching nothing happen. Pointing at something needs no\n * handler: the ring is ours, drawn over their page and taken away again.\n */\n\n// Guarded as in control.ts: the published bundle cannot assume `process`.\nconst isDevelopment =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"development\";\n\n/**\n * How recently an instruction has to have been asked for to be worth acting\n * on.\n *\n * Long enough that a slow network, a reconnect, or a tab coming back from\n * sleep still lands the one that just happened. Short enough that a\n * conversation from last week cannot move anybody, whatever route it takes\n * into the query: the person reading this page did not ask for it, and\n * whoever did is long gone.\n *\n * Generous because the two ends of the comparison are two different clocks.\n * The instruction is stamped by the server and the age is worked out on a\n * machine that may be a minute out either way, so the window is minutes\n * rather than seconds. Nothing about a live exchange needs it tighter.\n */\nconst STALE_AFTER_MS = 5 * 60 * 1000;\n\n/** What a message asked for, once it is this page's business to do it. */\nexport type SupportDirection = {\n /** The message that asked, so a second ask is a new one. */\n key: string;\n /** Whether the page was actually moved, which is the only thing worth\n * announcing: a destination nobody could act on moved nothing. */\n didNavigate: boolean;\n /** What to point at once they are looking at the right page, if anything. */\n selector: string | null;\n};\n\n/**\n * The destination as somewhere on this site, or null.\n *\n * Median checks the path when the tool answers and again before it is stored,\n * and neither of those is on the machine that navigates. This one is. `//host`\n * and `/\\host` resolve to another origin rather than a path, which is the\n * whole reason this asks the URL parser instead of reading the string.\n */\nfunction pathOnThisSite(destination: string): string | null {\n if (typeof window === \"undefined\") return null;\n if (!destination.startsWith(\"/\")) return null;\n\n let url: URL;\n try {\n url = new URL(destination, window.location.origin);\n } catch {\n return null;\n }\n if (url.origin !== window.location.origin) return null;\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\n/**\n * Everything asking for something to be done rather than only said, oldest\n * first.\n *\n * Two carriers, one list. A message carries the instruction the agent's own\n * turn produced; a standalone ask carries one from a run that never produced\n * a message, which is a teammate running a tool themselves. The loose one\n * goes last because it is the newer of the two whenever both land together:\n * a teammate reaches for a tool in a thread the agent has already answered.\n */\nfunction directed(\n messages: SupportMessage[],\n ask: SupportAsk | null,\n): SupportAsk[] {\n const asked: SupportAsk[] = messages\n .filter(\n (message) =>\n message.navigateTo !== undefined || message.highlight !== undefined,\n )\n .map((message) => ({\n key: message.id,\n // Canned content may leave the clock off, and a message with no time on\n // it reads as old here rather than as now. Nothing that moves a page\n // should be doing it on a guess.\n at: message.sentAt ?? 0,\n navigateTo: message.navigateTo ?? null,\n highlight: message.highlight ?? null,\n }));\n\n if (ask !== null) asked.push(ask);\n return asked;\n}\n\nexport function useSupportNavigation({\n messages,\n ask = null,\n conversationId = null,\n isLoading,\n onNavigate,\n}: {\n messages: SupportMessage[];\n /** The one not riding a message, when a run produced one. */\n ask?: SupportAsk | null;\n /**\n * The thread being watched. When it changes, what is on screen is somebody\n * else's history rather than this page's next line, so the first look\n * starts again.\n */\n conversationId?: string | null;\n /** Nothing is history until the first answer has arrived. */\n isLoading: boolean;\n onNavigate?: (path: string) => void;\n}): SupportDirection | null {\n /** Every message carrying an instruction that this page has already seen. */\n const seen = useRef<Set<string> | null>(null);\n /** Which thread that set is about. */\n const watching = useRef<string | null>(null);\n const [direction, setDirection] = useState<SupportDirection | null>(null);\n\n // A layout effect is deliberate: the direction and its message arrive in\n // one live-query update, so the host gets to move before the browser paints\n // a confirmation claiming that it already did.\n useLayoutEffect(() => {\n if (isLoading) return;\n\n const asked = directed(messages, ask);\n\n // The first look is the thread as it already was. Remembered, never\n // acted on: whatever is in it happened before this page existed.\n //\n // A different thread than the one this set was built for is a first look\n // as well. That is signing in: the account's history arrives whole, into\n // a page that has been watching an empty query, and none of it happened\n // here.\n if (seen.current === null || watching.current !== conversationId) {\n seen.current = new Set(asked.map((one) => one.key));\n watching.current = conversationId;\n return;\n }\n\n // Only the newest is worth showing afterwards. Two in one turn is a turn\n // that has already gone wrong, and the later of them is the one the words\n // underneath are about.\n let latest: SupportDirection | null = null;\n\n for (const one of asked) {\n if (seen.current.has(one.key)) continue;\n // Marked before it is acted on, so a handler that throws, or one that\n // navigates without unmounting, cannot be asked twice.\n seen.current.add(one.key);\n\n // Unseen and still not news. An instruction is a thing somebody is\n // doing to a page in front of a reader, so one that has been sitting in\n // a thread since yesterday is not carried out late: not the navigation,\n // and not the ring either.\n //\n // An instruction with no time on it moves nobody either. That is a\n // deployment answering from before any of this, and the safe reading of\n // \"I cannot tell how old this is\" is to leave the page alone.\n const age = Date.now() - one.at;\n if (!Number.isFinite(age) || age > STALE_AFTER_MS) continue;\n\n let didNavigate = false;\n const destination = one.navigateTo;\n\n if (destination !== null) {\n const path = pathOnThisSite(destination);\n if (onNavigate === undefined) {\n if (isDevelopment) {\n console.warn(\n `Median: a tool asked to take this visitor to ${destination}, but <MedianSupport> has no onNavigate. Pass one, such as onNavigate={router.push}, or the tool cannot move anybody.`,\n );\n }\n } else if (path === null) {\n console.error(\n `Median: refused to navigate to ${destination}, which is not a path on this site.`,\n );\n } else {\n onNavigate(path);\n didNavigate = true;\n }\n }\n\n latest = { key: one.key, didNavigate, selector: one.highlight };\n }\n\n // Said on the next frame rather than in the middle of this one. What the\n // ring and the line are is settled here, where what actually happened is\n // known; showing them is the render after, like any other arrival.\n let frame = 0;\n if (latest !== null) {\n const announced = latest;\n frame = requestAnimationFrame(() => setDirection(announced));\n }\n return () => cancelAnimationFrame(frame);\n }, [messages, ask, conversationId, isLoading, onNavigate]);\n\n return direction;\n}\n","\"use client\";\n\nimport { createRoot } from \"react-dom/client\";\nimport { MedianSupport, type MedianSupportProps } from \"./median-support\";\n\n/**\n * What a mounted widget hands back: the two things a host without React has\n * no re-render to do for them. Everything else goes through `medianSupport`,\n * same as anywhere.\n */\nexport type MedianSupportInstance = {\n /**\n * Change any option after mount. Only the keys passed change, so\n * `update({ user })` when somebody signs in leaves the rest alone.\n */\n update: (options: Partial<MedianSupportProps>) => void;\n /** Take the widget off the page: panel, launcher, connection, all of it. */\n unmount: () => void;\n};\n\n// Guarded as in control.ts: the published bundle cannot assume `process`.\nconst isDevelopment =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"development\";\n\n/**\n * The same widget, for a page that has never heard of React: Vue, Svelte,\n * Rails, a script on plain HTML. One call puts the launcher in the corner,\n * wired to the same panel, thread and inbox as the component:\n *\n * const support = mountMedianSupport({ apiKey: \"median_pk_...\" });\n *\n * It takes the component's props, as one options object, and the rest of the\n * SDK does not know the difference: `medianSupport.open()` opens this widget\n * exactly as it opens the component.\n *\n * What would have been new props on a re-render is `update`:\n *\n * support.update({ user: { name: \"Ada\", email: \"ada@example.com\" } });\n *\n * It renders into a container of its own, appended to `<body>`, with the\n * package's copy of React. The host's page needs none and never sees it.\n */\nexport function mountMedianSupport(\n options: MedianSupportProps,\n): MedianSupportInstance {\n // A server rendering the page has nowhere to put a widget. Say so where\n // the installer is looking, and hand back an instance that is safe to\n // hold, because a broken widget must never take the page down with it.\n if (typeof document === \"undefined\") {\n console.error(\n \"Median: mountMedianSupport() was called where there is no document, so nothing was mounted. Call it in the browser, after the page exists.\",\n );\n return { update: () => {}, unmount: () => {} };\n }\n\n const container = document.createElement(\"div\");\n container.dataset.medianSupport = \"\";\n document.body.appendChild(container);\n\n const root = createRoot(container);\n let current = options;\n let mounted = true;\n\n const render = () => {\n root.render(<MedianSupport {...current} />);\n };\n render();\n\n return {\n update(next) {\n if (!mounted) {\n if (isDevelopment) {\n console.warn(\n \"Median: update() was called after unmount(), so nothing changed. Mount again with mountMedianSupport() if the widget should come back.\",\n );\n }\n return;\n }\n current = { ...current, ...next };\n render();\n },\n unmount() {\n if (!mounted) return;\n mounted = false;\n root.unmount();\n container.remove();\n },\n };\n}\n","\"use client\";\n\nimport { API_KEY_PREFIX, hasPrefix } from \"@median/backend/support\";\nimport { ConvexProvider, ConvexReactClient } from \"convex/react\";\nimport { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { FeedbackPanel } from \"../feedback/feedback-panel\";\nimport { FeedbackPopover } from \"../feedback/feedback-popover\";\nimport { MEDIAN_DEPLOYMENT_URL } from \"./deployment\";\nimport type { MedianDiagnostics } from \"./diagnostics\";\nimport { MedianErrorBoundary } from \"./error-boundary\";\nimport {\n useMedianFeedbackOpenState,\n useRegisterMedianFeedback,\n} from \"./feedback-control\";\nimport { useRememberInstall } from \"./install\";\nimport { useMedianIdentity, useMissingCredentials } from \"./use-identity\";\nimport { useFeedbackNote } from \"./use-feedback-note\";\nimport type { MedianUser } from \"./use-median-thread\";\n\n/** Wide enough for a paragraph, narrow enough to hang off a menu item. */\nconst DEFAULT_WIDTH = \"20rem\";\n\ntype MedianFeedbackOptions = {\n /**\n * Your own trigger. Whatever you pass is rendered where you put it and the\n * panel hangs off it, the way a dropdown hangs off the thing that opens\n * it:\n *\n * <MedianFeedback apiKey=\"median_pk_...\">\n * <button>Share feedback</button>\n * </MedianFeedback>\n *\n * It is wrapped in an inline span that takes the click, so your button\n * keeps its own styles and needs to know nothing about any of this.\n *\n * Without children the panel sits in the bottom right corner instead, for\n * a host opening it from somewhere else entirely with\n * `useMedianFeedback()`.\n */\n children?: ReactNode;\n /**\n * Something already on your page for the panel to hang off, as a CSS\n * selector. For the case children cannot cover: a row inside a dropdown,\n * which closes itself opening this and takes the trigger with it.\n *\n * <MedianFeedback apiKey=\"median_pk_...\" anchor=\"#account-button\" />\n *\n * Looked up each time the panel is placed, so it works for anything that\n * comes and goes. Unlike a trigger it is only a position: pressing it does\n * not open or close the panel, and a press on it dismisses the panel like\n * a press anywhere else. Ignored when `children` are passed.\n */\n anchor?: string;\n /** Who is signed in on your site, if anyone. Shown to your team. */\n user?: MedianUser;\n /**\n * Whether a note carries what the browser already knows: time zone,\n * language, browser, OS, device, screen, and the page it was written on.\n * On by default, because the page is most of what makes a note actionable,\n * which is what the panel says out loud. Pass `false` and none of it is\n * read at all.\n */\n telemetry?: boolean;\n /**\n * Watch what goes wrong on the page, so a bug filed from a note arrives\n * with the error already attached. The same switch `<MedianSupport>`\n * takes, and the same buffer behind it: mount either one with it on.\n */\n diagnostics?: MedianDiagnostics;\n /**\n * Anything about your own app worth having next to a bug report: a build,\n * a route, a flag. Read when a note is sent.\n */\n appState?: Record<string, string | number | boolean>;\n /** Pass it, with `onOpenChange`, to hold the open state yourself. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Any CSS length. The panel never grows past the viewport whatever this says. */\n width?: string;\n /** The heading, for a host whose product calls this something else. */\n title?: string;\n /** The line under it. */\n description?: string;\n placeholder?: string;\n};\n\n/**\n * Two ways in, the same two `<MedianSupport>` takes.\n *\n * `apiKey` is the publishable id on its own. `identity` is the path to a\n * route built with `medianIdentity`, which answers with the key and with\n * whoever is signed in, already signed. Pass both and the panel is usable on\n * the key from the prop while the route is still answering.\n */\nexport type MedianFeedbackProps = MedianFeedbackOptions &\n (\n | { apiKey: string; identity?: string }\n | { apiKey?: string; identity: string }\n );\n\n/** The same, once the gate below has settled which key and which person. */\ntype ConnectedFeedbackProps = MedianFeedbackOptions & { apiKey: string };\n\n/**\n * The same two ways in, for a host without JSX. Spelled out rather than\n * `Omit`ped off the props above, because omitting a key from a union of two\n * shapes flattens it into one and loses the \"either, but not neither\" the\n * union is there to say.\n */\nexport type MedianFeedbackMountOptions = Omit<MedianFeedbackOptions, \"children\"> &\n (\n | { apiKey: string; identity?: string }\n | { apiKey?: string; identity: string }\n );\n\n/**\n * A feedback panel, hung off a trigger of your own.\n *\n * One box and one button. Whoever is on the page types a sentence, and a\n * fast model reads it: a bug goes on the bug list, an idea goes on the\n * suggestions list, and an advert goes nowhere. Nobody has to pick a\n * category, rank anything, or write a title, which is the point, because a\n * form that asks for those is a form nobody fills in.\n *\n * <MedianFeedback apiKey=\"median_pk_...\">\n * <MenuItem>Share feedback</MenuItem>\n * </MedianFeedback>\n *\n * The page they were on rides along on its own, which the line under the\n * title says plainly.\n *\n * It brings its own connection, so it works on pages that have never heard\n * of Convex, and it is independent of `<MedianSupport>`: mount either, both,\n * or neither. Mounted together they share a visitor, so the same person\n * writing in and leaving a note is one customer with both to their name.\n */\nexport function MedianFeedback(props: MedianFeedbackProps) {\n return (\n <MedianErrorBoundary>\n <FeedbackIdentity {...props} />\n </MedianErrorBoundary>\n );\n}\n\n/**\n * The same gate `<MedianSupport>` has, for the same reason: the signature can\n * only be made on a server and this is a client component. Both panels on one\n * page read the one route between them. See `use-identity.ts`.\n */\nfunction FeedbackIdentity({\n apiKey,\n identity,\n user,\n ...rest\n}: MedianFeedbackOptions & { apiKey?: string; identity?: string }) {\n const resolved = useMedianIdentity(identity);\n useMissingCredentials(\"MedianFeedback\", apiKey, identity);\n const key = apiKey ?? resolved.apiKey;\n const person = user ?? resolved.user;\n\n if (key === undefined) return null;\n\n return (\n <FeedbackConnection\n {...rest}\n apiKey={key}\n {...(person ? { user: person } : {})}\n />\n );\n}\n\n/**\n * A key with the wrong shape would only ever fail later, quietly, as a panel\n * that never sends. Say so now, in the console, while the person who pasted\n * it is still looking at this page.\n */\nfunction useApiKeyShapeWarning(apiKey: string) {\n useEffect(() => {\n if (hasPrefix(apiKey, API_KEY_PREFIX)) return;\n\n const shown =\n apiKey === \"\"\n ? \"an empty string\"\n : `\"${apiKey.length > 16 ? `${apiKey.slice(0, 16)}…` : apiKey}\"`;\n console.error(\n `Median: the apiKey passed to <MedianFeedback> is ${shown}, which does not look like the browser-safe id from publicKeyFromMedianKey(MEDIAN_KEY). It should start with ${API_KEY_PREFIX}.`,\n );\n }, [apiKey]);\n}\n\nfunction FeedbackConnection(props: ConnectedFeedbackProps) {\n // Its own client rather than the app's, so the panel is self contained on\n // a host site. Lazy so a missing URL fails at render, into the boundary.\n const [client] = useState(() => {\n if (!MEDIAN_DEPLOYMENT_URL) {\n throw new Error(\n \"The Median feedback panel was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL.\",\n );\n }\n return new ConvexReactClient(MEDIAN_DEPLOYMENT_URL);\n });\n\n return (\n <ConvexProvider client={client}>\n <Feedback {...props} />\n </ConvexProvider>\n );\n}\n\nfunction Feedback({\n apiKey,\n children,\n anchor,\n user,\n telemetry,\n diagnostics,\n appState,\n open,\n onOpenChange,\n width = DEFAULT_WIDTH,\n title,\n description,\n placeholder,\n}: ConnectedFeedbackProps) {\n useRegisterMedianFeedback();\n useApiKeyShapeWarning(apiKey);\n // The support panel writes the same thing down. Either one is enough for a\n // crash screen to have a key to report with.\n useRememberInstall(apiKey, user);\n\n const triggerRef = useRef<HTMLSpanElement>(null);\n const [isOpen, setOpen] = useMedianFeedbackOpenState({\n ...(open !== undefined ? { open } : {}),\n ...(onOpenChange ? { onOpenChange } : {}),\n });\n\n const note = useFeedbackNote({\n apiKey,\n ...(user ? { user } : {}),\n ...(telemetry !== undefined ? { telemetry } : {}),\n ...(diagnostics !== undefined ? { diagnostics } : {}),\n ...(appState ? { appState } : {}),\n });\n\n const close = useCallback(() => setOpen(false), [setOpen]);\n\n // A fresh box for the next note, but not until this one is out of sight:\n // resetting as the panel closes would swap the thank-you back to an empty\n // form halfway through the fade. So the panel is remounted on the way\n // back in, and only when there is something to clear. A draft somebody\n // closed without sending is theirs, and survives.\n const [attempt, setAttempt] = useState(0);\n const hasSent = useRef(false);\n useEffect(() => {\n if (!isOpen || !hasSent.current) return;\n hasSent.current = false;\n setAttempt((count) => count + 1);\n }, [isOpen]);\n\n return (\n <>\n {children !== undefined && (\n // An inline span rather than a clone of whatever was passed: the\n // host's trigger keeps its own props, its own ref and its own\n // styles, and the click is caught on the way past. `display:\n // contents` would lose the rectangle the panel is measured against.\n <span\n ref={triggerRef}\n onClick={() => setOpen(!isOpen)}\n className=\"inline-flex\"\n >\n {children}\n </span>\n )}\n\n <FeedbackPopover\n isOpen={isOpen}\n onClose={close}\n triggerRef={triggerRef}\n {...(anchor !== undefined ? { anchor } : {})}\n width={width}\n >\n <FeedbackPanel\n key={attempt}\n onSubmit={note.submit}\n onClose={close}\n onSent={() => {\n hasSent.current = true;\n close();\n }}\n notice={note.notice}\n {...(title !== undefined ? { title } : {})}\n {...(description !== undefined ? { description } : {})}\n {...(placeholder !== undefined ? { placeholder } : {})}\n />\n </FeedbackPopover>\n </>\n );\n}\n","/**\n * The feedback panel's vocabulary: what a note may be, what it may point at,\n * and the three answers a reader can give about one.\n *\n * Deliberately pure, like `shared/signals.ts`: no Convex imports, nothing\n * that touches a database. The widget reads these limits before it sends and\n * the mutation enforces them on arrival, so neither side can drift.\n */\n\n/**\n * How much one note may be. Longer than a chat message would be worth\n * reading in a bubble and shorter than the write-up it turns into, because\n * this is a box somebody types a paragraph into, not a document.\n */\nexport const NOTE_MAX_LENGTH = 2_000;\n\n/**\n * Where a note goes.\n *\n * The first two are the Signal tab's own kinds, so a note that survives\n * reading lands on the list the team already triages. The third is the one\n * that goes nowhere: a page open to the internet collects adverts, keyboard\n * mashing, and people testing whether the box works, and none of that is\n * worth a row somebody has to close.\n */\nexport const FEEDBACK_VERDICTS = [\"bug\", \"suggestion\", \"spam\"] as const;\n\nexport type FeedbackVerdict = (typeof FEEDBACK_VERDICTS)[number];\n\n/** Trims a note, keeping its line breaks: somebody wrote it in a textarea. */\nexport function cleanNote(input: string): string {\n return input.trim().slice(0, NOTE_MAX_LENGTH);\n}\n\n/** What is wrong with this note, in a sentence, or null if nothing is. */\nexport function noteIssue(note: string): string | null {\n if (note.trim().length === 0) return \"Write something first.\";\n if (note.length > NOTE_MAX_LENGTH) {\n return `Feedback has to be ${NOTE_MAX_LENGTH} characters or fewer.`;\n }\n return null;\n}\n","\"use client\";\n\nimport { NOTE_MAX_LENGTH } from \"@median/backend/feedback\";\nimport { useEffect, useState, type KeyboardEvent } from \"react\";\nimport { ArrowsClockwise, Check, X } from \"@/components/icons\";\nimport { Collapse } from \"@/components/ui/collapse\";\nimport { TEXT_FIELD_SHELL } from \"@/components/ui/text-field\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { cn } from \"@/lib/utils\";\nimport { PoweredByMedian } from \"../widget-badge\";\nimport { WidgetButton } from \"../widget-button\";\nimport { AUTOFOCUS_ATTRIBUTE } from \"./feedback-popover\";\n\n/** How long the thank-you sits there before whoever owns the panel closes it. */\nconst THANKS_MS = 1_600;\n\n/**\n * The feedback panel: one box, one button, and no questions in front of them.\n *\n * A visitor with something to say should not first have to decide whether it\n * is a bug or an idea, rank it, or write a title. So the panel asks for a\n * sentence and nothing else, and the reader on the other side does the rest.\n * The page rides along on its own, which the line under the title says\n * plainly, because collecting it quietly would be somebody else's business\n * to be told about rather than ours to assume.\n *\n * One surface, not two. The box sits straight on the card rather than inside\n * a tray of its own: a panel this small has no room for a container that\n * contains one thing, and the extra edge only made it look like there was\n * more here than there is.\n *\n * Presentational, like `SupportWidget`: a note goes out through `onSubmit`\n * and nothing is held here but the draft.\n */\nexport function FeedbackPanel({\n onSubmit,\n onClose,\n onSent,\n notice,\n showBadge = true,\n title = \"Share feedback\",\n description = \"This page is included automatically.\",\n placeholder = \"What should change?\",\n className,\n}: {\n /**\n * Awaited. A rejection keeps the draft, so a send that fails costs a retry\n * rather than a retype.\n */\n onSubmit?: (note: string) => unknown;\n /** Omit to hide the close button, for a panel that is always on the page. */\n onClose?: () => void;\n /** The thank-you has been read. Whoever opened the panel closes it. */\n onSent?: () => void;\n /** One line under the box, for a send that went wrong. */\n notice?: string | null;\n /** The \"Powered by Median\" line. Hosts on a paid plan can turn it off. */\n showBadge?: boolean;\n title?: string;\n description?: string;\n placeholder?: string;\n className?: string;\n}) {\n const [draft, setDraft] = useState(\"\");\n const [isSending, setSending] = useState(false);\n const [isSent, setSent] = useState(false);\n\n const canSend = draft.trim().length > 0 && !isSending && !isSent;\n\n // The thank-you is read, then the panel is somebody else's problem. In an\n // effect rather than in the handler so a panel unmounted in between never\n // calls back into a host that has moved on.\n useEffect(() => {\n if (!isSent) return;\n const timer = setTimeout(() => onSent?.(), THANKS_MS);\n return () => clearTimeout(timer);\n }, [isSent, onSent]);\n\n async function send() {\n if (!canSend) return;\n setSending(true);\n try {\n await onSubmit?.(draft.trim());\n } catch {\n // The notice under the box says why. The draft stays put.\n return;\n } finally {\n setSending(false);\n }\n setSent(true);\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {\n // Enter is a new line here, not a send: this is a paragraph box rather\n // than a chat composer, and the button is right there. Meta and enter\n // still sends, which is what anybody who tries it expects.\n if (event.key !== \"Enter\") return;\n if (!event.metaKey && !event.ctrlKey) return;\n event.preventDefault();\n void send();\n }\n\n return (\n <section\n aria-label={title}\n className={cn(\n // The widget's own radius scale, so the app's token can climb as the\n // chrome gets rounder without this changing shape under its hosts.\n \"flex w-full flex-col gap-2 overflow-hidden rounded-xl border bg-card p-3 text-card-foreground [--radius:0.625rem]\",\n className,\n )}\n >\n <header className=\"flex items-start gap-2\">\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <h2 className=\"truncate text-sm font-semibold tracking-tight\">\n {title}\n </h2>\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n </div>\n\n {onClose && (\n <WidgetButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n onClick={onClose}\n aria-label=\"Close feedback\"\n className=\"-mt-0.5 -mr-1 shrink-0 text-muted-foreground\"\n >\n <X />\n </WidgetButton>\n )}\n </header>\n\n {/* Two rows of one grid, one opening as the other closes, so the swap\n is the panel changing height rather than two panels. */}\n <div className=\"grid\">\n <Collapse isOpen={!isSent}>\n <div className=\"flex flex-col gap-1.5\">\n <Textarea\n rows={3}\n value={draft}\n maxLength={NOTE_MAX_LENGTH}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n aria-label={title}\n {...{ [AUTOFOCUS_ATTRIBUTE]: \"\" }}\n className={cn(\n TEXT_FIELD_SHELL,\n \"max-h-40 min-h-18 px-2.5 py-2\",\n // 16px on phones, in pixels: any focused field smaller than\n // that makes iOS zoom the host's whole page in.\n \"max-sm:text-[16px]\",\n )}\n />\n\n {notice && (\n <p className=\"animate-in px-0.5 text-xs text-destructive fade-in duration-150\">\n {notice}\n </p>\n )}\n </div>\n </Collapse>\n\n <Collapse isOpen={isSent}>\n <div className=\"flex items-center justify-center gap-2 py-4 text-sm font-medium\">\n <span className=\"grid size-5 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground\">\n <Check className=\"size-3\" />\n </span>\n Thanks, we got it.\n </div>\n </Collapse>\n </div>\n\n {/* Our name and the one action, on the same line: the foot of a panel\n this small is a row rather than two.\n\n The height is held whether or not the button is in it, so the row\n does not shrink under the thank-you while the panel above it is\n already animating. */}\n <div className=\"flex min-h-8 items-center gap-2\">\n {showBadge && <PoweredByMedian className=\"justify-start\" />}\n\n {!isSent && (\n <WidgetButton\n type=\"button\"\n disabled={!canSend}\n aria-busy={isSending}\n onClick={() => void send()}\n className=\"relative ml-auto shrink-0 rounded-full px-3\"\n >\n {/* The label stays in the box while the spinner is over it, so\n it goes on setting the width and a send never moves the\n button it is happening in. */}\n <span\n className={cn(\n \"transition-opacity duration-150 motion-reduce:transition-none\",\n isSending && \"opacity-0\",\n )}\n >\n Submit feedback\n </span>\n\n {isSending && (\n <ArrowsClockwise\n aria-hidden\n className=\"absolute inset-0 m-auto animate-spin motion-reduce:animate-none\"\n />\n )}\n </WidgetButton>\n )}\n </div>\n </section>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"@/lib/utils\";\nimport { useHydrated } from \"../use-hydrated\";\nimport { useAnchor } from \"./use-anchor\";\n\n/** Above the host's own chrome. Their z-indexes are not ours to guess at. */\nconst LAYER = 2_147_483_000;\n\n/**\n * What inside the panel takes focus when it opens. The panel says which,\n * because which field is the one somebody came to fill in is the panel's\n * business rather than the box it is drawn in.\n */\nexport const AUTOFOCUS_ATTRIBUTE = \"data-median-autofocus\";\n\n/**\n * How the panel arrives and leaves.\n *\n * A dropdown, so it comes out of the thing that opened it: a little smaller\n * and a little towards its trigger, growing into place. The spring is the\n * same one the support panel opens with, and it overshoots by a hair, which\n * is the difference between a panel that appears and one that pops.\n *\n * Leaving is quicker and has no spring. An overshoot on the way out is a\n * panel arguing about being closed.\n */\n// `scale` and `translate` by name: those are the properties Tailwind's\n// `scale-*` and `translate-y-*` set. Listed as `transform` the panel had\n// neither, and popped open on opacity alone.\nconst MOTION =\n \"transition-[opacity,scale,translate] motion-reduce:transition-none\";\nconst OPEN = \"duration-250 ease-spring\";\nconst SHUT = \"duration-150 ease-out-quint\";\n\n/**\n * The panel, in a layer of its own, under whatever opened it.\n *\n * Portalled to the body rather than rendered where the trigger is. A host's\n * trigger lives inside their layout, and a panel rendered there inherits\n * every `overflow: hidden`, stacking context and transform between it and\n * the page. Out here it answers to the window and to nothing else.\n *\n * Closed, it stays mounted and goes `inert`: the draft somebody was halfway\n * through survives a close, and nothing behind the fade can be tabbed into.\n */\nexport function FeedbackPopover({\n isOpen,\n onClose,\n triggerRef,\n anchor,\n width,\n children,\n}: {\n isOpen: boolean;\n onClose: () => void;\n /** The host's own trigger, when they wrapped one. */\n triggerRef: RefObject<HTMLElement | null>;\n /**\n * Something else on their page to hang off, as a selector. Unlike the\n * trigger it is only a position: a press on it closes the panel like a\n * press anywhere else, because it is not the thing doing the opening.\n */\n anchor?: string;\n /** Any CSS length. Never wider than the window, whatever this says. */\n width: string;\n children: ReactNode;\n}) {\n const panelRef = useRef<HTMLDivElement>(null);\n const side = useAnchor({ triggerRef, anchor, panelRef, isOpen });\n // The panel is medianled into `document.body`, which does not exist until\n // there is one. Nothing at all until then, on the server and through\n // hydration alike, so both passes agree.\n const isHydrated = useHydrated();\n\n // Whatever had focus when the panel came up, so closing can hand it back.\n const opener = useRef<HTMLElement | null>(null);\n // Focus only moves once the panel has actually changed state, or a panel\n // that started open would steal focus on page load.\n const wasOpen = useRef(isOpen);\n\n // Escape closes, wherever focus is inside the panel. The element picker\n // takes its own Escape first, in the capture phase, so backing out of\n // pointing at something never closes the whole panel with it.\n useEffect(() => {\n if (!isOpen) return;\n\n function handleKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") onClose();\n }\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onClose]);\n\n // A press anywhere else closes it, the way every dropdown does. On\n // pointerdown rather than click, so it closes as the press lands rather\n // than when it is let go, and the trigger is left out: it does its own\n // toggling, and closing here first would make a second press reopen.\n useEffect(() => {\n if (!isOpen) return;\n\n function handlePointerDown(event: PointerEvent) {\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (panelRef.current?.contains(target)) return;\n if (triggerRef.current?.contains(target)) return;\n onClose();\n }\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [isOpen, onClose, triggerRef]);\n\n useEffect(() => {\n if (wasOpen.current === isOpen) return;\n wasOpen.current = isOpen;\n\n if (isOpen) {\n const active = document.activeElement;\n opener.current = active instanceof HTMLElement ? active : null;\n // Straight into whatever the panel says takes focus, which is the box\n // they are here to type in. Unlike the support widget's launcher this\n // is never opened by accident: somebody chose it from a menu or a\n // button, and landing anywhere but the field would cost them a Tab.\n const field = panelRef.current?.querySelector<HTMLElement>(\n `[${AUTOFOCUS_ATTRIBUTE}]`,\n );\n (field ?? panelRef.current)?.focus();\n return;\n }\n\n const back = triggerRef.current ?? opener.current;\n opener.current = null;\n // Only somewhere focus can actually land, and only if it is still on the\n // page: a menu that closed behind the panel is not there to take it back.\n if (back && back !== document.body && back.isConnected) back.focus();\n }, [isOpen, triggerRef]);\n\n if (!isHydrated) return null;\n\n return createPortal(\n <div\n ref={panelRef}\n tabIndex={-1}\n inert={!isOpen}\n // The hook the published stylesheet scopes its resets to. On a page\n // without Tailwind there is no preflight, so the package ships one\n // that reaches no further than this box.\n data-median-widget=\"\"\n style={{\n zIndex: LAYER,\n width,\n top: 0,\n left: 0,\n // Grows out of the edge nearest its trigger rather than out of its\n // own middle, which is what makes it read as the trigger opening.\n transformOrigin: side === \"top\" ? \"bottom center\" : \"top center\",\n }}\n className={cn(\n \"fixed max-w-[calc(100vw-2rem)] outline-none\",\n // The shadow is on the box rather than inside the panel: a filter on\n // a parent of anything that scrolls makes the browser repaint it on\n // every frame, and there is nothing scrolling in here to protect.\n \"drop-shadow-xl\",\n MOTION,\n isOpen\n ? [OPEN, \"pointer-events-auto scale-100 opacity-100 translate-y-0\"]\n : [\n SHUT,\n \"pointer-events-none scale-[0.97] opacity-0\",\n // Towards its trigger, which is above it or below it.\n side === \"top\" ? \"translate-y-1\" : \"-translate-y-1\",\n ],\n )}\n >\n {children}\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\n\n/**\n * Whether this is running in a browser that has finished hydrating.\n *\n * For the things that cannot exist until there is a document: a median has to\n * be handed a node, and there is no `document.body` on a server. Returning\n * null for those and the real thing once mounted is a server/client branch,\n * which is the first thing React names when it reports a hydration mismatch:\n * the server sends nothing, the client's first pass renders a panel, and the\n * whole tree is thrown away and built again.\n *\n * So it is read as an external store rather than as a mounted flag. React\n * takes the server snapshot both on the server and through hydration, so both\n * passes agree on nothing, and only the commit after it moves. Same trick the\n * session token is read with, for the same reason.\n *\n * The store never changes, so nothing ever subscribes to anything.\n */\nconst subscribe = () => () => {};\nconst onClient = () => true;\nconst onServer = () => false;\n\nexport function useHydrated(): boolean {\n return useSyncExternalStore(subscribe, onClient, onServer);\n}\n","\"use client\";\n\nimport { useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * Keeping the panel under whatever opened it.\n *\n * The host owns the trigger: it is a nav item, a menu row, a button in a\n * toolbar, and it can be anywhere on their page. So the panel is measured\n * against it rather than pinned to a corner, and it follows it: a page that\n * scrolls or resizes under an open panel keeps the two together.\n *\n * The edges are written straight onto the node rather than held in state,\n * because scrolling fires far more often than anything worth re-rendering\n * for, and the panel's own opening animation is a transform. Position and\n * motion on two different properties is what keeps them from fighting.\n */\n\n/** Between the trigger and the panel. */\nconst GAP = 8;\n\n/** How close to the edge of the window the panel is allowed to sit. */\nconst MARGIN = 16;\n\n/** Which side of the trigger the panel ended up on, for the motion. */\nexport type AnchorSide = \"top\" | \"bottom\";\n\n/**\n * Whatever the selector finds, or nothing.\n *\n * Read every time it is placed rather than once, because the point of taking\n * a selector at all is that the thing it names may not have been on the page\n * when the panel opened. A menu item that opens this closes itself doing it;\n * the button the menu hangs off is still there, and that is what a selector\n * is for.\n */\nfunction findAnchor(selector: string | undefined): HTMLElement | null {\n if (selector === undefined || typeof document === \"undefined\") return null;\n try {\n return document.querySelector<HTMLElement>(selector);\n } catch {\n console.error(\n `Median: the anchor passed to <MedianFeedback> is ${selector}, which is not a valid CSS selector.`,\n );\n return null;\n }\n}\n\nexport function useAnchor({\n triggerRef,\n anchor,\n panelRef,\n isOpen,\n}: {\n /** The host's own trigger, when they wrapped one. */\n triggerRef: RefObject<HTMLElement | null>;\n /** Something on their page to hang off instead. Both absent is the corner. */\n anchor?: string;\n panelRef: RefObject<HTMLDivElement | null>;\n isOpen: boolean;\n}): AnchorSide {\n const [side, setSide] = useState<AnchorSide>(\"bottom\");\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let frame = 0;\n\n function place() {\n const panel = panelRef.current;\n const trigger = triggerRef.current ?? findAnchor(anchor);\n if (panel === null) return;\n\n const width = panel.offsetWidth;\n const height = panel.offsetHeight;\n const room = {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n\n // Nothing to hang off, so it sits in the corner every widget sits in.\n if (trigger === null) {\n panel.style.left = `${Math.max(MARGIN, room.width - width - MARGIN)}px`;\n panel.style.top = `${Math.max(MARGIN, room.height - height - MARGIN)}px`;\n setSide(\"bottom\");\n return;\n }\n\n const rect = trigger.getBoundingClientRect();\n\n // Under the trigger, unless the panel would not fit and there is more\n // room above it. Flipping only when it actually helps: a panel that\n // jumped over its trigger the moment the page got short would move\n // for nothing most of the time.\n const below = room.height - rect.bottom - GAP - MARGIN;\n const above = rect.top - GAP - MARGIN;\n const onTop = height > below && above > below;\n setSide(onTop ? \"top\" : \"bottom\");\n\n const top = onTop ? rect.top - GAP - height : rect.bottom + GAP;\n\n // Aligned to whichever edge of the trigger keeps the panel on screen:\n // its left edge normally, its right edge when the trigger is over\n // towards the right, which is where a nav item usually is.\n const fromStart = rect.left;\n const fromEnd = rect.right - width;\n const left =\n fromStart + width + MARGIN <= room.width ? fromStart : fromEnd;\n\n panel.style.left = `${clamp(left, MARGIN, room.width - width - MARGIN)}px`;\n panel.style.top = `${clamp(top, MARGIN, room.height - height - MARGIN)}px`;\n }\n\n /** One placement per frame at most, however hard the page is scrolling. */\n function schedule() {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(place);\n }\n\n place();\n window.addEventListener(\"scroll\", schedule, true);\n window.addEventListener(\"resize\", schedule);\n\n // The panel changes height as the box grows and as the thank-you takes\n // over, and a panel flipped above its trigger has to move when it does.\n const observer = new ResizeObserver(schedule);\n if (panelRef.current !== null) observer.observe(panelRef.current);\n\n return () => {\n cancelAnimationFrame(frame);\n window.removeEventListener(\"scroll\", schedule, true);\n window.removeEventListener(\"resize\", schedule);\n observer.disconnect();\n };\n }, [isOpen, anchor, panelRef, triggerRef]);\n\n return side;\n}\n\nfunction clamp(value: number, low: number, high: number): number {\n // High can be below low on a window shorter than the panel, and then the\n // top edge wins: the way out is up there.\n return Math.max(low, Math.min(value, Math.max(low, high)));\n}\n","\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport {\n createOpenStore,\n useOpenState,\n useRegister,\n} from \"./open-store\";\n\n/**\n * Driving the feedback panel from anywhere on the page.\n *\n * The panel usually hangs off a trigger the host wrapped it around, and for\n * that this is not needed at all. It is here for the other way of putting\n * feedback on a page: a row in a menu somewhere else entirely, a keyboard\n * shortcut, a link at the foot of an error screen. Same shape as\n * `medianSupport`, and a store of its own, so opening one never opens the\n * other.\n */\nconst store = createOpenStore(\"MedianFeedback\");\n\nexport const medianFeedback = {\n /** What the panel is doing right now. */\n get isOpen() {\n return store.readEffective();\n },\n open() {\n store.request(true);\n store.warnIfNothingIsMounted(\"the feedback panel was asked to open\");\n },\n close() {\n store.request(false);\n },\n toggle() {\n const next = !store.readEffective();\n store.request(next);\n if (next) {\n store.warnIfNothingIsMounted(\"the feedback panel was asked to open\");\n }\n },\n} satisfies MedianFeedbackControl;\n\n/** The shape of {@link medianFeedback}, and of what the hook returns. */\nexport type MedianFeedbackControl = {\n /** Whether the panel is open. */\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n};\n\n/**\n * The feedback panel, from anywhere else on the page:\n *\n * const feedback = useMedianFeedback();\n *\n * <button onClick={feedback.open}>Share feedback</button>\n *\n * `isOpen` follows the panel however it was opened, so a menu row can render\n * itself as pressed while it is up.\n */\nexport function useMedianFeedback(): MedianFeedbackControl {\n const isOpen = useSyncExternalStore(\n store.subscribe,\n store.readEffective,\n store.readServerEffective,\n );\n\n return {\n isOpen,\n open: medianFeedback.open,\n close: medianFeedback.close,\n toggle: medianFeedback.toggle,\n };\n}\n\n/** The panel's own settled open state. See {@link useOpenState}. */\nexport function useMedianFeedbackOpenState(options: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): [boolean, (next: boolean) => void] {\n return useOpenState(store, options);\n}\n\n/** One panel per page, and a word in the console when there are two. */\nexport function useRegisterMedianFeedback() {\n useRegister(store);\n}\n","\"use client\";\n\nimport { api } from \"@median/backend\";\nimport { useMutation } from \"convex/react\";\nimport { useCallback, useState, useSyncExternalStore } from \"react\";\nimport { errorMessage } from \"@/lib/errors\";\nimport { collectContext, collectPage } from \"./context\";\nimport { restoreCustomData, takeCustomData } from \"./custom-data\";\nimport { useDiagnostics, type MedianDiagnostics } from \"./diagnostics\";\nimport { getOrCreateSessionId, subscribeSession } from \"./session\";\nimport { splitIdentity, type MedianUser } from \"./use-median-thread\";\n\n/**\n * Sending one note, and everything that rides along with it.\n *\n * The same session token the support widget uses, so a person who has\n * written in and then left feedback is one customer with both to their name\n * rather than two strangers who happen to share a browser. The same\n * telemetry, the same diagnostics ring buffer, and the same attached data\n * too: a bug report filed off a note deserves what a bug report filed off a\n * conversation gets.\n *\n * Nothing is read here. A note is a thing you hand over, not a thread you\n * watch, so there is no subscription and nothing to keep in step.\n */\n\n/** What the panel is told about a note that could not be taken. */\nconst REFUSALS: Record<string, string> = {\n off: \"This site is not taking feedback right now.\",\n empty: \"Write something first.\",\n};\n\nexport function useFeedbackNote({\n apiKey,\n user,\n telemetry = true,\n diagnostics,\n appState,\n}: {\n apiKey: string;\n user?: MedianUser;\n telemetry?: boolean;\n diagnostics?: MedianDiagnostics;\n appState?: Record<string, string | number | boolean>;\n}) {\n // The session token is external state (localStorage), read as a store: the\n // server snapshot is null, so SSR and the first client paint agree, and\n // `reset()` on sign out lands here like it lands on the thread.\n const sessionId = useSyncExternalStore(\n subscribeSession,\n useCallback(() => getOrCreateSessionId(apiKey), [apiKey]),\n () => null,\n );\n\n const submitNote = useMutation(api.feedback.submit);\n const takeDiagnostics = useDiagnostics(diagnostics, appState);\n const [notice, setNotice] = useState<string | null>(null);\n\n /**\n * Rejects when the note did not land, which is what keeps the draft in the\n * box. The reason is in `notice` by then, where the panel shows it.\n */\n const submit = useCallback(\n async (body: string) => {\n setNotice(null);\n if (sessionId === null) {\n setNotice(\"This browser is still waking up. Try again in a moment.\");\n throw new Error(\"No session yet.\");\n }\n\n // Whatever the host attached since the last send rides this note.\n // Taken outside the try so a failed send hands it back too.\n const custom = takeCustomData();\n // Whether a refusal has already said its own piece. State cannot\n // answer that here: it is set and read inside one tick.\n let explained = false;\n try {\n // Read now rather than on mount: all of it is wanted as \"what was\n // true when they wrote\", and a panel can sit closed on a page for an\n // hour before anybody opens it.\n const context = telemetry ? collectContext() : undefined;\n const page = telemetry ? collectPage() : undefined;\n const collected = takeDiagnostics();\n const { facts, claim } = splitIdentity(user ?? null);\n\n const outcome = await submitNote({\n apiKey,\n sessionId,\n body,\n ...(user ? { user: facts } : {}),\n ...(claim ? { identity: claim } : {}),\n ...(context ? { context } : {}),\n ...(page ? { page } : {}),\n ...(collected ? { diagnostics: collected } : {}),\n ...(custom ? { customData: custom } : {}),\n });\n\n if (outcome !== \"taken\") {\n explained = true;\n setNotice(REFUSALS[outcome] ?? \"That did not send.\");\n throw new Error(outcome);\n }\n } catch (caught) {\n // Back in the queue, so the retry carries them like it keeps the draft.\n if (custom) restoreCustomData(custom);\n if (!explained) {\n console.error(\"Sending feedback from the Median panel failed\", caught);\n setNotice(errorMessage(caught));\n }\n // Rethrown so the panel keeps the draft: a failed send should cost a\n // retry, never a retype.\n throw caught;\n }\n },\n [apiKey, sessionId, user, telemetry, takeDiagnostics, submitNote],\n );\n\n return { submit, notice, clearNotice: () => setNotice(null) };\n}\n","\"use client\";\n\nimport { createRoot } from \"react-dom/client\";\nimport { isDevelopment } from \"./open-store\";\nimport {\n MedianFeedback,\n type MedianFeedbackMountOptions,\n type MedianFeedbackProps,\n} from \"./median-feedback\";\n\n/**\n * What a mounted panel hands back: the two things a host without React has\n * no re-render to do for them. Opening and closing go through\n * `medianFeedback`, same as anywhere.\n */\nexport type MedianFeedbackInstance = {\n /**\n * Change any option after mount. Only the keys passed change, so\n * `update({ user })` when somebody signs in leaves the rest alone.\n */\n update: (options: Partial<MedianFeedbackProps>) => void;\n /** Take the panel off the page. */\n unmount: () => void;\n};\n\n/**\n * The same panel, for a page that has never heard of React: Vue, Svelte,\n * Rails, a script on plain HTML.\n *\n * const feedback = mountMedianFeedback({ apiKey: \"median_pk_...\" });\n *\n * document.querySelector(\"#feedback\").onclick = () => medianFeedback.open();\n *\n * There is no trigger to wrap out here, so the panel opens in the bottom\n * right corner and your own button says when. Everything else is the\n * component's, unchanged.\n */\nexport function mountMedianFeedback(\n options: MedianFeedbackMountOptions,\n): MedianFeedbackInstance {\n // A server rendering the page has nowhere to put a panel. Say so where the\n // installer is looking, and hand back an instance that is safe to hold,\n // because a broken panel must never take the page down with it.\n if (typeof document === \"undefined\") {\n console.error(\n \"Median: mountMedianFeedback() was called where there is no document, so nothing was mounted. Call it in the browser, after the page exists.\",\n );\n return { update: () => {}, unmount: () => {} };\n }\n\n const container = document.createElement(\"div\");\n container.dataset.medianFeedback = \"\";\n document.body.appendChild(container);\n\n const root = createRoot(container);\n let current = options;\n let mounted = true;\n\n const render = () => {\n root.render(<MedianFeedback {...current} />);\n };\n render();\n\n return {\n update(next) {\n if (!mounted) {\n if (isDevelopment) {\n console.warn(\n \"Median: update() was called after unmount(), so nothing changed. Mount again with mountMedianFeedback() if the panel should come back.\",\n );\n }\n return;\n }\n current = { ...current, ...next };\n render();\n },\n unmount() {\n if (!mounted) return;\n mounted = false;\n root.unmount();\n container.remove();\n },\n };\n}\n"],"mappings":"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","names":["useEffect","useState","useCallback","useEffect","useRef","useState","l","s","r","a","t","o","i","c","m","e","e","t","r","e","a","o","e","t","a","o","a","e","r","e","s","r","a","e","o","e","s","r","a","e","o","t","e","o","a","e","e","r","t","t","e","e","r","o","t","a","e","o","e","r","e","e","a","o","r","t","a","e","e","a","o","m","p","a","e","e","a","o","r","t","a","e","a","e","a","r","o","e","t","a","e","o","e","r","o","a","e","e","m","r","o","e","a","a","e","r","o","e","a","e","r","s","a","e","a","r","o","a","r","a","l","t","o","a","l","e","e","a","r","o","s","a","r","e","a","e","o","a","o","e","a","e","r","t","a","e","o","o","a","o","e","a","r","t","r","e","o","r","o","e","o","e","at","buttonY","listeners","React","i","a","r","t","e","o","s","f","l","p","c","jsx","e","t","r","o","i","S","l","d","b","p","m","c","f","s","a","w","I","X","e","t","r","o","i","S","l","jsx","X","d","b","p","m","f","param","React","i","Slot","__name","Slottable","child","React","jsx","useEffect","Fragment","jsx","jsxs","useCallback","useLayoutEffect","useRef","useRef","useCallback","useLayoutEffect","useEffect","useRef","useState","forwardRef","jsx","Image","jsx","jsxs","useEffect","useRef","useState","useRef","useState","jsx","jsx","useCallback","useEffect","useRef","d","jsx","d","jsx","jsxs","jsx","jsxs","useState","useRef","useEffect","useState","jsx","jsx","useState","shape","jsx","shape","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs","jsx","useState","Fragment","jsx","jsxs","useState","useLayoutEffect","useRef","jsx","prefersReducedMotion","release","useRef","useLayoutEffect","jsx","jsx","jsx","jsxs","Fragment","jsx","jsxs","useEffect","useRef","useState","jsx","jsx","jsxs","useState","useRef","useEffect","jsx","jsxs","jsx","jsxs","useCallback","useEffect","useLayoutEffect","useRef","useState","useSyncExternalStore","enabled","useSyncExternalStore","useState","useRef","useCallback","useLayoutEffect","useEffect","clamp","useLayoutEffect","useState","useSyncExternalStore","useEffect","SETTLE_MS","useSyncExternalStore","useState","useLayoutEffect","jsx","jsxs","useState","useRef","useCallback","useEffect","current","useEffect","useRef","useState","jsx","jsxs","prefersReducedMotion","useEffect","useState","createPortal","jsx","jsxs","LAYER","useState","useEffect","createPortal","useSyncExternalStore","useCallback","useEffect","useSyncExternalStore","listeners","store","useSyncExternalStore","read","trim","withoutQuery","events","useCallback","useEffect","useRef","withoutQuery","useEffect","listeners","listeners","i","useCallback","useEffect","useMemo","useState","useSyncExternalStore","useEffect","useState","STORAGE_PREFIX","read","STORAGE_PREFIX","inMemory","at","useCallback","useSyncExternalStore","STORAGE_PREFIX","inMemory","listeners","i","useSyncExternalStore","useCallback","useMemo","useEffect","useState","current","useSyncExternalStore","useSyncExternalStore","ConvexError","useEffect","useState","inFlight","read","i","useEffect","useRef","useLayoutEffect","useRef","useState","isDevelopment","Fragment","jsx","jsxs","useEffect","client","useState","jsx","isDevelopment","current","ConvexProvider","ConvexReactClient","useCallback","useEffect","useRef","useState","useEffect","useState","useEffect","useRef","createPortal","useSyncExternalStore","subscribe","onServer","useLayoutEffect","useState","MARGIN","clamp","jsx","LAYER","useRef","useEffect","createPortal","jsx","jsxs","THANKS_MS","useState","useEffect","useSyncExternalStore","store","useSyncExternalStore","useMutation","useCallback","useState","useSyncExternalStore","useSyncExternalStore","useCallback","useMutation","useState","Fragment","jsx","jsxs","DEFAULT_WIDTH","useApiKeyShapeWarning","useEffect","client","useState","ConvexReactClient","ConvexProvider","useRef","useCallback","createRoot","jsx","createRoot","current"]}
|
|
1
|
+
{"version":3,"sources":["../../backend/convex/shared/support.ts","../../../apps/web/src/components/support-widget/sdk/median-support.tsx","../../../apps/web/src/components/support-widget/markdown-chunk.tsx","../../../apps/web/src/components/support-widget/widget-launcher.tsx","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/lib/SSRBase.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowDown.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowDown.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowUp.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowUp.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsClockwise.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowsClockwise.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsIn.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowsIn.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ArrowsOut.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ArrowsOut.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Bug.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Bug.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/CaretRight.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/CaretRight.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ChatCircleDots.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ChatCircleDots.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Check.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Check.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/EnvelopeSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/EnvelopeSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/File.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/File.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/ImageSquare.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/ImageSquare.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Lightbulb.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Lightbulb.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/LockSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/LockSimple.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Play.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Play.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Plus.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Plus.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Sparkle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Sparkle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/Star.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/Star.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/UserCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/UserCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/WarningCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/WarningCircle.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/ssr/X.es.js","../../../node_modules/.bun/@phosphor-icons+react@2.1.10+005eabf3d8b6ef06/node_modules/@phosphor-icons/react/dist/defs/X.es.js","../../../apps/web/src/components/icons.tsx","../../../apps/web/src/components/support-widget/launcher-position.ts","../../../apps/web/src/components/ui/message-scroller.tsx","../../../node_modules/.bun/@shadcn+react@0.3.0+03aa47d54245a271/node_modules/@shadcn/react/dist/chunk-HBS6WEDP.js","../../../node_modules/.bun/@shadcn+react@0.3.0+03aa47d54245a271/node_modules/@shadcn/react/dist/message-scroller/index.js","../../../node_modules/.bun/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.mjs","../../../node_modules/.bun/@radix-ui+react-slot@1.3.3+0f58469d5b3bd39f/node_modules/@radix-ui/react-slot/src/slot.tsx","../../../node_modules/.bun/@radix-ui+react-compose-refs@1.1.5+0f58469d5b3bd39f/node_modules/@radix-ui/react-compose-refs/src/compose-refs.tsx","../../../apps/web/src/components/ui/button.tsx","../../../apps/web/src/hooks/use-is-resizing.ts","../../../apps/web/src/lib/message-groups.ts","../../../apps/web/src/components/support-widget/use-stack-shift.ts","../../../apps/web/src/components/support-widget/motion.ts","../../../apps/web/src/components/support-widget/widget-composer.tsx","../src/next-image-shim.tsx","../../../apps/web/src/components/attachments/attachment-image.tsx","../../../apps/web/src/components/attachments/attachment-draft-chip.tsx","../../../apps/web/src/components/attachments/use-attachment-drafts.ts","../../../apps/web/src/components/attachments/use-attachment-target.ts","../../../apps/web/src/components/support-widget/widget-button.tsx","../../../apps/web/src/components/ui/text-field.ts","../../../apps/web/src/components/ui/textarea.tsx","../../../apps/web/src/hooks/use-typing-signal.ts","../../../apps/web/src/components/brand-art.ts","../../../apps/web/src/components/brand.tsx","../../../apps/web/src/components/support-widget/widget-badge.tsx","../../../apps/web/src/components/avatar.tsx","../../../apps/web/src/components/initial-badge.tsx","../../../apps/web/src/components/support-widget/widget-avatar.tsx","../../../apps/web/src/components/support-widget/widget-empty.tsx","../../../apps/web/src/components/support-widget/widget-header.tsx","../../../apps/web/src/components/support-widget/widget-loading.tsx","../../../apps/web/src/components/support-widget/widget-locked.tsx","../../../apps/web/src/components/ui/badge.tsx","../../../apps/web/src/components/support-widget/widget-attachments.tsx","../../../apps/web/src/components/ui/morph-bubble.tsx","../../../apps/web/src/components/support-widget/widget-bubble.tsx","../../../apps/web/src/components/support-widget/widget-message-body.tsx","../../../apps/web/src/components/support-widget/widget-typing.tsx","../../../apps/web/src/components/support-widget/widget-message.tsx","../../../apps/web/src/components/support-widget/widget-rating.tsx","../../../apps/web/src/components/ui/collapse.tsx","../../../apps/web/src/components/support-widget/widget-status.tsx","../../../apps/web/src/components/support-widget/support-widget.tsx","../../../apps/web/src/components/support-widget/use-launcher-drag.ts","../../../apps/web/src/components/support-widget/use-teaser-placement.ts","../../../apps/web/src/components/support-widget/use-widget-sheet.ts","../../../apps/web/src/components/support-widget/use-page-lock.ts","../../../apps/web/src/components/support-widget/widget-teaser.tsx","../../../apps/web/src/components/support-widget/plain-text.ts","../../../apps/web/src/components/support-widget/widget-spotlight.tsx","../../../apps/web/src/components/support-widget/widget-toast.tsx","../../../apps/web/src/components/support-widget/sdk/control.ts","../../backend/convex/shared/customData.ts","../../../apps/web/src/components/support-widget/sdk/custom-data.ts","../../../apps/web/src/components/support-widget/sdk/open-store.ts","../../backend/convex/_generated/api.js","../../backend/convex/shared/crashes.ts","../../../apps/web/src/components/support-widget/sdk/report-error.ts","../../../apps/web/src/components/support-widget/sdk/context.ts","../../../apps/web/src/components/support-widget/sdk/deployment.ts","../../backend/convex/shared/diagnostics.ts","../../../apps/web/src/components/support-widget/sdk/diagnostics.ts","../../../apps/web/src/components/support-widget/sdk/install.ts","../../../apps/web/src/components/support-widget/sdk/session.ts","../../../apps/web/src/components/support-widget/sdk/use-median-thread.ts","../../../apps/web/src/hooks/use-now.ts","../../../apps/web/src/lib/errors.ts","../../../apps/web/src/lib/time.ts","../../../apps/web/src/lib/upload.ts","../../../apps/web/src/components/support-widget/sdk/rating-skips.ts","../../../apps/web/src/components/support-widget/sdk/stamps.ts","../../../apps/web/src/components/support-widget/sdk/read-state.ts","../../../apps/web/src/components/support-widget/sdk/visitor-email.ts","../../../apps/web/src/components/support-widget/sdk/error-boundary.tsx","../../../apps/web/src/components/support-widget/sdk/use-identity.ts","../../../node_modules/.bun/cuelume@0.2.2/node_modules/cuelume/dist/sounds/recipes.js","../../../node_modules/.bun/cuelume@0.2.2/node_modules/cuelume/dist/audio/engine.js","../../../apps/web/src/components/support-widget/sdk/use-message-sound.ts","../../../apps/web/src/components/support-widget/sdk/use-navigation.ts","../../../apps/web/src/components/support-widget/sdk/use-teaser.ts","../../../apps/web/src/components/support-widget/sdk/teaser-state.ts","../../../apps/web/src/components/support-widget/sdk/mount.tsx","../../../apps/web/src/components/support-widget/sdk/median-feedback.tsx","../../backend/convex/shared/feedback.ts","../../backend/convex/shared/reportImages.ts","../../../apps/web/src/components/support-widget/feedback/feedback-panel.tsx","../../../apps/web/src/components/support-widget/feedback/feedback-popover.tsx","../../../apps/web/src/components/support-widget/use-hydrated.ts","../../../apps/web/src/components/support-widget/feedback/use-anchor.ts","../../../apps/web/src/components/support-widget/sdk/feedback-control.ts","../../../apps/web/src/components/support-widget/sdk/use-feedback-note.ts","../../../apps/web/src/components/support-widget/sdk/mount-feedback.tsx"],"sourcesContent":["/**\n * The rules the support side of Median follows: how long a message can be,\n * what an agent can be called, what an API key looks like.\n *\n * Deliberately pure, like shared/organizations.ts: no Convex imports, so the\n * web app can import this (`@median/backend/support`) and complain in the same\n * words the mutations would.\n */\n\n/** What an organization's AI agent is called until someone renames it. */\nexport const DEFAULT_AGENT_NAME = \"Median AI\";\n\n/**\n * Whether the agent may end a conversation on its own: resolving one it\n * finished, or closing one that was only ever spam.\n *\n * On unless a team says otherwise. A queue is only useful if what is left in\n * it is what somebody still has to look at, and a thread the agent answered\n * end to end is not one of those. Turning it off means every conversation\n * waits for a person to end it, which is the right call for a team that\n * reads all of them anyway.\n */\nexport const DEFAULT_AUTO_RESOLVE = true;\n\n/**\n * Whether resolved conversations get read for knowledge base suggestions.\n * On by default: the suggestions only ever land in a review queue, so the\n * cost of being wrong is a dismissal, not a bad answer.\n */\nexport const DEFAULT_LEARN_FROM_THREADS = true;\n\n/**\n * Whether the live agent may file knowledge and tool suggestions from the\n * middle of a conversation, the moment something teaches it or stumps it.\n * On by default for the same reason the reader is: everything lands in a\n * review queue, so the cost of a bad one is a dismissal.\n */\nexport const DEFAULT_SUGGEST_KNOWLEDGE = true;\n\n/**\n * Whether the nightly sweep may resolve this organization's finished\n * threads. On by default for the same reason auto-resolve is: an inbox\n * that closes what is clearly done is the behavior a team expects.\n */\nexport const DEFAULT_NIGHTLY_SWEEP = true;\n\n/**\n * Whether the agent may file a bug or a suggestion when a customer hands one\n * over. On by default: a signal is a note in a list a person reads, not a\n * change to anything, and a complaint nobody wrote down is a complaint the\n * team never hears.\n */\nexport const DEFAULT_FILE_SIGNALS = true;\n\n/**\n * Whether the widget asks for an email before a visitor's first message. On\n * by default: an anonymous thread cannot be followed up, and half of support\n * is getting back to somebody. A host can waive it in code, and this is the\n * team's side of the same switch.\n */\nexport const DEFAULT_REQUIRE_EMAIL = true;\n\n/**\n * Whether the closed widget shows the first lines of a reply nobody has read\n * yet. On by default: a count on the button says something arrived, and the\n * card is what says whether it is worth opening. A host can waive it in\n * code, and this is the team's side of the same switch.\n */\nexport const DEFAULT_MESSAGE_PREVIEW = true;\n\nexport const AGENT_NAME_MIN_LENGTH = 2;\nexport const AGENT_NAME_MAX_LENGTH = 40;\nexport const PERSONALITY_MAX_LENGTH = 2000;\n\nexport const MESSAGE_MAX_LENGTH = 4000;\n\nexport const VISITOR_NAME_MAX_LENGTH = 80;\nexport const VISITOR_EMAIL_MAX_LENGTH = 320;\nexport const VISITOR_AVATAR_URL_MAX_LENGTH = 512;\n/** Extra facts a host attaches to a visitor. Small on purpose. */\nexport const VISITOR_METADATA_MAX_ENTRIES = 16;\nexport const VISITOR_METADATA_MAX_LENGTH = 200;\n\n/** A message can carry a few files, not a filesystem. */\nexport const MESSAGE_MAX_ATTACHMENTS = 6;\nexport const ATTACHMENT_MAX_BYTES = 25 * 1024 * 1024;\n\n/**\n * What a visitor makes of a finished conversation: stars, and whatever they\n * wanted to say about it. Both sides check the score, since the widget draws\n * exactly this many stars and the backend takes nothing else.\n */\nexport const RATING_MIN_STARS = 1;\nexport const RATING_MAX_STARS = 5;\nexport const RATING_FEEDBACK_MAX_LENGTH = 1000;\n\n/** Whether a score is one of the stars actually offered. */\nexport function isRatingStars(stars: number): boolean {\n return (\n Number.isInteger(stars) &&\n stars >= RATING_MIN_STARS &&\n stars <= RATING_MAX_STARS\n );\n}\n\n/** Their words, trimmed and capped. Empty means they had none. */\nexport function cleanFeedback(feedback: string): string {\n return feedback.trim().slice(0, RATING_FEEDBACK_MAX_LENGTH);\n}\n\n/**\n * Publishable, like a Stripe pk_ or an Intercom app id: it ships in the\n * browser on the host's site, so it grants nothing beyond opening a support\n * conversation with that organization.\n */\nexport const API_KEY_PREFIX = \"median_pk_\";\n\n/**\n * The only credential a new Median integration needs. The public id is part\n * of the value so server-side SDKs can safely hand the widget its\n * `median_pk_...` identifier without another environment variable. The\n * secret tail never leaves the server.\n */\nexport const MEDIAN_KEY_PREFIX = \"median_key_\";\n\n/** Purpose-separated signing material is derived from the Median key. */\nexport const MEDIAN_SIGNATURE_PREFIX = \"median_sig_\";\n\nexport const MEDIAN_KEY_PUBLIC_ID_LENGTH = 32;\nexport const MEDIAN_KEY_SECRET_LENGTH = 64;\n\n/** Enough separate credentials for production, staging, and local work. */\nexport const MAX_MEDIAN_KEYS_PER_ORG = 10;\nexport const MEDIAN_KEY_NAME_MAX_LENGTH = 40;\n\n/**\n * The other kind, and the opposite of the one above: this one never goes near\n * a browser. It lives on the host's server, where it signs the id of whoever\n * is signed in, and anybody holding it can claim to be any of their users.\n */\nexport const SIGNING_KEY_PREFIX = \"median_sk_\";\n\n/**\n * What the REST API takes. Secret like the signing key: it lives on the\n * host's server and can read and write their whole inbox's visitor side, so\n * shipping one in a browser is handing the room key to the lobby.\n */\nexport const SECRET_API_KEY_PREFIX = \"median_api_\";\n\n/**\n * What webhook deliveries are signed with, one per endpoint. Held by us and\n * by the receiver, so the receiver can tell our POST from anybody else's.\n */\nexport const WEBHOOK_SECRET_PREFIX = \"median_whsec_\";\n\n/**\n * What tool endpoint calls are signed with, one per organization. Held by us\n * and by the host's server, so their handler can tell our POST from anybody\n * else's. The `@mediansh/agent-tools` package mirrors this literal in\n * `src/handler.ts`; change them together.\n */\nexport const TOOL_SECRET_PREFIX = \"median_toolsec_\";\n\n/**\n * What every prefix above starts with, and what it started with when the\n * product was called Portal.\n *\n * A key issued then is still a key. The rename went all the way to the wire\n * for anything minted from here on, but nothing already in somebody's\n * environment was invalidated by it, so every prefix has a twin and one rule\n * makes it. Read through `legacyPrefix` rather than writing `portal_` out\n * again: there is one family to retire, and this is the only line that names\n * it.\n */\nconst FAMILY = \"median_\";\nconst LEGACY_FAMILY = \"portal_\";\n\n/** The same prefix under the old name. */\nexport function legacyPrefix(prefix: string): string {\n return prefix.startsWith(FAMILY)\n ? `${LEGACY_FAMILY}${prefix.slice(FAMILY.length)}`\n : prefix;\n}\n\n/** Whether a credential carries this prefix under either name. */\nexport function hasPrefix(value: string, prefix: string): boolean {\n return value.startsWith(prefix) || value.startsWith(legacyPrefix(prefix));\n}\n\n/**\n * The prefix a credential actually carries, so anything derived from it\n * comes out in the family it belongs to. A legacy key's signing material\n * was derived as `portal_sig_` and is held that way, and re-deriving it as\n * `median_sig_` would stop it matching.\n */\nexport function prefixCarriedBy(value: string, prefix: string): string | null {\n if (value.startsWith(prefix)) return prefix;\n const legacy = legacyPrefix(prefix);\n return value.startsWith(legacy) ? legacy : null;\n}\n\n/**\n * The bounds on a session token, here rather than in the widget so the REST\n * API and the SDK refuse the same strings in the same words.\n */\nexport const SESSION_ID_MIN_LENGTH = 8;\nexport const SESSION_ID_MAX_LENGTH = 128;\n\n/**\n * A host's own id for a person. Long enough for a UUID or a Stripe style id\n * and short enough that nobody is putting a document in it.\n */\nexport const EXTERNAL_ID_MAX_LENGTH = 128;\n\n/**\n * How long a typing signal counts as live. Composers refresh it well inside\n * this while keys are hit, so anything older is a browser that went away.\n */\nexport const TYPING_TTL_MS = 12_000;\n\n/**\n * The bounds on a snooze. When it comes back is worked out on the client,\n * where the clock and the timezone are, so these only catch a number that\n * cannot have been meant: one already gone, or one so far out that nobody was\n * ever going to see the conversation again.\n */\nexport const SNOOZE_MIN_MS = 60_000;\nexport const SNOOZE_MAX_MS = 365 * 24 * 60 * 60_000;\n\n/** What is wrong with this snooze, in a sentence, or null if nothing is. */\nexport function snoozeIssue(until: number, now: number): string | null {\n if (!Number.isFinite(until)) return \"That is not a time to snooze until.\";\n if (until - now < SNOOZE_MIN_MS) {\n return \"Snoozing has to be for at least a minute.\";\n }\n if (until - now > SNOOZE_MAX_MS) {\n return \"Conversations can be snoozed for up to a year.\";\n }\n return null;\n}\n\n/**\n * A visitor's picture, or null if what we were handed cannot be one.\n *\n * https only. It ends up in an `<img>` on the inbox, and anything else is\n * either blocked as mixed content or was never a picture in the first place.\n * Whatever a host sends is theirs, so it is checked rather than trusted.\n */\nexport function cleanAvatarUrl(input: string | undefined): string | null {\n const url = input?.trim();\n if (!url || url.length > VISITOR_AVATAR_URL_MAX_LENGTH) return null;\n\n try {\n return new URL(url).protocol === \"https:\" ? url : null;\n } catch {\n return null;\n }\n}\n\n/**\n * An address, or null if what we were handed cannot be one.\n *\n * Deliberately barely a check: the shape of an address is the only thing\n * anyone can tell without sending mail to it. It is here because the agent\n * writes these down from whatever a customer typed, and \"looks like an\n * address\" should be decided in one place rather than at each caller.\n */\nexport function cleanEmail(input: string | undefined): string | null {\n const email = input?.trim();\n if (!email || email.length > VISITOR_EMAIL_MAX_LENGTH) return null;\n\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email) ? email : null;\n}\n\n/**\n * What to call a customer wherever a name is printed. Their name when we have\n * one, otherwise the number they were handed on arrival, so an anonymous\n * customer is \"Customer #12\" everywhere rather than one of a crowd of\n * anonymous visitors. The last fallback is for rows written before numbers\n * existed.\n */\nexport function customerDisplayName(\n name: string | null | undefined,\n customerNumber: number | null | undefined,\n): string {\n if (name) return name;\n if (customerNumber) return `Customer #${customerNumber}`;\n return \"Anonymous visitor\";\n}\n\n/** Collapses the whitespace someone pasted in without changing their words. */\nexport function normalizeAgentName(input: string): string {\n return input.replace(/\\s+/g, \" \").trim();\n}\n\n/** What is wrong with this agent name, in a sentence, or null if nothing is. */\nexport function agentNameIssue(name: string): string | null {\n if (name.length === 0) return \"Give your agent a name.\";\n if (name.length < AGENT_NAME_MIN_LENGTH) {\n return `Agent names need at least ${AGENT_NAME_MIN_LENGTH} characters.`;\n }\n if (name.length > AGENT_NAME_MAX_LENGTH) {\n return `Agent names have to be ${AGENT_NAME_MAX_LENGTH} characters or fewer.`;\n }\n return null;\n}\n\n/** What is wrong with this personality, or null. Empty is fine: quiet is a personality. */\nexport function personalityIssue(personality: string): string | null {\n if (personality.length > PERSONALITY_MAX_LENGTH) {\n return `Personalities have to be ${PERSONALITY_MAX_LENGTH} characters or fewer.`;\n }\n return null;\n}\n\n/**\n * File types an attachment may not be, whatever it says it is.\n *\n * Storage serves a file back under the type it was stored with, on its own\n * host under the same registrable domain as the app. A browser opening one of\n * these runs it there: a teammate clicking what a stranger called `invoice.pdf`\n * would land on a real Median subdomain running somebody else's page.\n *\n * A refusal list rather than an allow list, because support is where people\n * send whatever they have. Logs, archives, dumps and video are all somebody\n * trying to explain a problem; only the handful of types a browser treats as\n * a document to run have to be turned away.\n *\n * Short on purpose, and it costs something. An exported HTML error report and\n * a diagram saved as SVG are both ordinary evidence, and both are turned away\n * here, because a browser opening either one runs it. Plain XML stays: a\n * config file or a SOAP body is read, not run.\n */\nexport const UNSAFE_ATTACHMENT_TYPES = [\n \"text/html\",\n \"application/xhtml+xml\",\n \"image/svg+xml\",\n \"text/xsl\",\n \"application/xslt+xml\",\n];\n\n/** Whether a content type is one a browser would run rather than show. */\nexport function isUnsafeAttachmentType(contentType: string): boolean {\n const bare = contentType.split(\";\")[0].trim().toLowerCase();\n return UNSAFE_ATTACHMENT_TYPES.includes(bare);\n}\n\n/**\n * The session id namespaces the channels own.\n *\n * A browser mints a random token for itself, but an email or a Discord\n * account is not a browser: those doors derive a session from the address or\n * the account so that everything a person writes from it lands on one\n * visitor. Derived means workable out, and an address is not a secret.\n *\n * What makes them safe is that nothing on the outside may present one.\n * `cleanSessionId` refuses the whole namespace, so an id in it can only ever\n * have come from the ingest that made it.\n */\nexport const CHANNEL_SESSION_PREFIXES = [\"email:\", \"discord:\"] as const;\n\n/** Whether a session token belongs to a channel rather than to a browser. */\nexport function isChannelSessionId(sessionId: string): boolean {\n const lowered = sessionId.toLowerCase();\n return CHANNEL_SESSION_PREFIXES.some((prefix) => lowered.startsWith(prefix));\n}\n","\"use client\";\n\nimport { API_KEY_PREFIX, hasPrefix } from \"@median/backend/support\";\nimport { ConvexProvider, ConvexReactClient } from \"convex/react\";\nimport { useEffect, useState } from \"react\";\nimport {\n threadRendersMarkdown,\n warmMarkdownWhenIdle,\n} from \"../markdown-chunk\";\nimport { SupportLauncher } from \"../widget-launcher\";\nimport { WidgetSpotlight } from \"../widget-spotlight\";\nimport { WidgetToast } from \"../widget-toast\";\nimport type { SupportLauncherKind } from \"../types\";\nimport { useMedianOpenState, useRegisterMedianSupport } from \"./control\";\nimport { MEDIAN_DEPLOYMENT_URL } from \"./deployment\";\nimport type { MedianDiagnostics } from \"./diagnostics\";\nimport { MedianErrorBoundary } from \"./error-boundary\";\nimport { useMedianIdentity, useMissingCredentials } from \"./use-identity\";\nimport { useRememberInstall } from \"./install\";\nimport { useMessageSound } from \"./use-message-sound\";\nimport { useSupportNavigation } from \"./use-navigation\";\nimport { useTeaser } from \"./use-teaser\";\nimport {\n isSignedIn,\n useMedianThread,\n type MedianUser,\n} from \"./use-median-thread\";\n\n/**\n * How often the open panel says so. Well inside the server's window for\n * counting somebody as present, so one dropped beat changes nothing.\n */\nconst PRESENCE_BEAT_MS = 45_000;\n\ntype MedianSupportOptions = {\n /** Who is signed in on the host's site, if anyone. Shown to the team. */\n user?: MedianUser;\n /**\n * Whether a message carries what the browser already knows: time zone,\n * language, browser, OS, device, screen, and the page it was sent from.\n * On by default, because a team that has to ask for all six spends its\n * first reply asking. Pass `false` and none of it is read at all.\n */\n telemetry?: boolean;\n /**\n * Take questions from signed in people only.\n *\n * Until `user` says somebody is there, the panel asks them to sign in\n * instead of offering a composer, and no conversation is opened or read.\n * Pass `user` the moment you have it and the thread takes over.\n *\n * A rule about your own page, kept on your own page: it decides what this\n * widget offers, not what the API accepts. `user.id` with a signed `hash`\n * is the part nobody can talk their way around.\n */\n requireSignIn?: boolean;\n /**\n * Where your sign in lives, for the button on that panel.\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * requireSignIn\n * onSignIn={() => router.push(\"/login\")}\n * />\n *\n * Without it the panel says the same thing and offers no button, which is\n * right for a site whose sign in is already the first thing on the page.\n */\n onSignIn?: () => void;\n /**\n * Ask for an email before a visitor's first message. On by default: an\n * anonymous thread cannot be followed up, and half of support is getting\n * back to somebody. Pass `false` and the composer opens straight away.\n *\n * The composer asks once per browser; the answer rides their first message\n * and lands with their details on your side. A visitor your `user` already\n * names an email for is never asked, and `medianSupport.reset()` asks the\n * next person instead.\n *\n * Your team can turn the question off from the dashboard without a\n * redeploy, and either side saying no is enough to keep it away.\n */\n requireEmail?: boolean;\n /**\n * Show the first lines of an unread reply on the closed button. On by\n * default: the count says something arrived, and the card is what says\n * whether it is worth opening.\n *\n * <MedianSupport apiKey=\"median_pk_...\" messagePreview={false} />\n *\n * Pass `false` and the corner stays a button with a count on it. Nothing\n * else changes: the reply is still there, still counted, still announced.\n * For a page where a customer's words should never appear unprompted,\n * over somebody's shoulder or in a screen share.\n *\n * Your team can turn it off from the dashboard without a redeploy, and\n * either side saying no is enough to keep the card away.\n */\n messagePreview?: boolean;\n /**\n * Watch what goes wrong on the page, so a bug report arrives with the\n * error already attached instead of after four messages of asking.\n *\n * <MedianSupport apiKey=\"median_pk_...\" diagnostics />\n *\n * `true` listens for uncaught errors and rejected promises, which changes\n * nothing about how your page runs. The object form adds the two that wrap\n * something of yours:\n *\n * diagnostics={{ network: true, console: true }}\n *\n * `network` wraps window.fetch to note requests that failed, `console`\n * wraps console.error. Both call through to what they replaced, and both\n * are put back when the widget leaves the page.\n *\n * Off by default: this reads your program's error stream, which is yours\n * to offer rather than ours to take. Nothing is sent on its own. The\n * newest snapshot rides the next message the customer sends, and only when\n * something new is in it.\n */\n diagnostics?: MedianDiagnostics;\n /**\n * Anything about your own app worth having next to a bug report: a build,\n * a route, a flag. Read when a message is sent, so it can change as they\n * move around.\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * diagnostics\n * appState={{ version: BUILD_SHA, plan: user.plan }}\n * />\n *\n * Twenty entries at most, and each one a line rather than a document.\n */\n appState?: Record<string, string | number | boolean>;\n /** Our button in the corner while it is closed, or nothing at all. */\n launcher?: SupportLauncherKind;\n /** Pass it, with `onOpenChange`, to hold the open state yourself. */\n open?: boolean;\n /** Every open and close, whoever asked for it. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Take the visitor to a page, when one of your own tools asks for it.\n *\n * <MedianSupport apiKey=\"median_pk_...\" onNavigate={router.push} />\n *\n * Called with a path on your own site, already checked against this page's\n * origin. Your router decides what happens: pass `router.push` and the\n * conversation stays open across the move.\n *\n * Without it a tool that asks to navigate cannot, and says so in the\n * console while you are building. Nothing else needs it.\n */\n onNavigate?: (path: string) => void;\n};\n\n/**\n * Two ways in, and every app has one of them.\n *\n * `apiKey` is the publishable id, and on its own it opens an anonymous\n * thread. `identity` is the path to a route built with `medianIdentity`,\n * which answers with the key and with whoever is signed in, already signed.\n * A framework that renders its root layout on the server cannot hand this\n * component a session any other way, so that is most of them.\n *\n * Passing both is worth it on a slow session: the button is up on the key\n * from the prop straight away, and the person arrives when the route answers.\n */\nexport type MedianSupportProps = MedianSupportOptions &\n (\n | { apiKey: string; identity?: string }\n | { apiKey?: string; identity: string }\n );\n\n/**\n * The whole SDK, as one component. Drop it on a page with your publishable API\n * key and the launcher, the thread, the AI and the inbox on the other side are\n * all wired up:\n *\n * <MedianSupport apiKey=\"median_pk_...\" />\n *\n * Optionally say who is signed in, and the team sees a person rather than\n * another anonymous visitor:\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * user={{ name: \"Ada\", email: \"ada@example.com\" }}\n * />\n *\n * There are three states rather than two: open, closed as a button in the\n * corner, and not on the page at all. Take the corner back and open it from\n * your own nav, from anywhere in your app, with no state to thread through:\n *\n * <MedianSupport apiKey=\"median_pk_...\" launcher=\"hidden\" />\n *\n * const support = useMedianSupport();\n * <button onClick={support.open}>Contact us</button>\n *\n * On a site nobody uses signed out, say so and the panel asks them to sign in\n * rather than opening a conversation with a stranger:\n *\n * <MedianSupport\n * apiKey=\"median_pk_...\"\n * user={session?.user}\n * requireSignIn\n * onSignIn={() => router.push(\"/login\")}\n * />\n *\n * When somebody signs out, `medianSupport.reset()` forgets the conversation\n * along with them, so the next person at the keyboard starts fresh.\n *\n * That is the surface, on purpose. Everything else a support widget could be\n * asked to do is either our decision or a setting on the dashboard, so it can\n * change without every host having to redeploy.\n *\n * It brings its own connection, so it works on pages (and sites) that have\n * never heard of Convex.\n */\nexport function MedianSupport(props: MedianSupportProps) {\n return <MedianSupportPreview {...props} />;\n}\n\n/**\n * The same widget with the handful of knobs Median's own pages need: the\n * gallery pins it inside a frame rather than to the viewport, and `defaultOpen`\n * is there for a screenshot or a page that has room for nothing else.\n *\n * Nothing uses `defaultOpen` today, on purpose. Everywhere the widget is shown\n * it starts as the button, because that is the state a host's visitors meet it\n * in and the morph out of the corner is most of what there is to look at.\n *\n * Not exported from the package. A host gets `MedianSupport` and nothing else,\n * which is why these can exist at all without becoming promises we have to\n * keep.\n */\nexport function MedianSupportPreview({\n defaultOpen = false,\n className,\n ...props\n}: MedianSupportProps & {\n /** Where it starts, until anything opens or closes it. */\n defaultOpen?: boolean;\n className?: string;\n}) {\n return (\n <MedianErrorBoundary>\n <MedianIdentity\n {...props}\n defaultOpen={defaultOpen}\n className={className}\n />\n </MedianErrorBoundary>\n );\n}\n\n/**\n * Settles who the widget is for before anything is connected.\n *\n * Both halves can come from a prop or from the host's identity route, and a\n * prop wins: a host who has the key to hand should not wait on a fetch to put\n * the button up, and one who already knows the signed in person is not told\n * otherwise by a route that answers later.\n *\n * Nothing is rendered until there is a key from one of the two. Without one\n * there is nobody to talk to, and a button that opens onto an error is worse\n * on somebody's page than no button for the moment it takes to answer.\n */\ntype GateProps = MedianSupportOptions & {\n apiKey?: string;\n identity?: string;\n defaultOpen: boolean;\n className?: string;\n};\n\nfunction MedianIdentity({ apiKey, identity, user, ...rest }: GateProps) {\n const resolved = useMedianIdentity(identity);\n useMissingCredentials(\"MedianSupport\", apiKey, identity);\n const key = apiKey ?? resolved.apiKey;\n\n if (key === undefined) return null;\n\n return (\n <MedianConnection\n {...rest}\n apiKey={key}\n user={user ?? resolved.user}\n isResolvingIdentity={resolved.isLoading}\n />\n );\n}\n\ntype ConnectionProps = MedianSupportOptions & {\n apiKey: string;\n /** The host's identity route has been asked and has not answered yet. */\n isResolvingIdentity: boolean;\n defaultOpen: boolean;\n className?: string;\n};\n\n/**\n * A key with the wrong shape would only ever fail later, quietly, as a widget\n * that never appears. Say so now, in the console, while the person who pasted\n * it is still looking at this page.\n *\n * The key is truncated in the message: if what was pasted is a secret from\n * somewhere else, the console should not repeat all of it.\n */\nfunction useApiKeyShapeWarning(apiKey: string) {\n useEffect(() => {\n if (hasPrefix(apiKey, API_KEY_PREFIX)) return;\n\n const shown =\n apiKey === \"\"\n ? \"an empty string\"\n : `\"${apiKey.length > 16 ? `${apiKey.slice(0, 16)}…` : apiKey}\"`;\n console.error(\n `Median: the apiKey passed to <MedianSupport> is ${shown}, which does not look like the browser-safe id from publicKeyFromMedianKey(MEDIAN_KEY). It should start with ${API_KEY_PREFIX}.`,\n );\n }, [apiKey]);\n}\n\nfunction MedianConnection(props: ConnectionProps) {\n // Its own client rather than the app's, so the widget is self contained on a\n // host site. Lazy so a missing URL fails at render, into the boundary.\n const [client] = useState(() => {\n if (!MEDIAN_DEPLOYMENT_URL) {\n throw new Error(\n \"The Median widget was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL.\",\n );\n }\n return new ConvexReactClient(MEDIAN_DEPLOYMENT_URL);\n });\n\n return (\n <ConvexProvider client={client}>\n <MedianLauncher {...props} />\n </ConvexProvider>\n );\n}\n\nfunction MedianLauncher({\n apiKey,\n user,\n telemetry,\n diagnostics,\n appState,\n requireSignIn = false,\n onSignIn,\n requireEmail = true,\n messagePreview = true,\n launcher,\n defaultOpen,\n open,\n onOpenChange,\n onNavigate,\n isResolvingIdentity,\n className,\n}: ConnectionProps) {\n useRegisterMedianSupport();\n useApiKeyShapeWarning(apiKey);\n // So a crash screen can file a report from a tree this widget is no\n // longer in. See `install.ts`.\n useRememberInstall(apiKey, user);\n\n const [isOpen, setOpen] = useMedianOpenState({\n open,\n defaultOpen,\n onOpenChange,\n });\n\n // Whoever is at the keyboard has not said who they are, and this host only\n // takes questions from people who have.\n //\n // Not while the identity route is still being read. Nobody has said there\n // is no one signed in yet, and inviting somebody who is already signed in\n // to sign in, for the half second before their own name arrives, reads as a\n // widget that has lost them.\n const isLocked =\n requireSignIn && !isResolvingIdentity && !isSignedIn(user);\n\n const {\n presence,\n messages,\n ask,\n conversationId,\n isLoading,\n isSending,\n askForEmail,\n setVisitorEmail,\n awaitingHuman,\n rating,\n unreadCount,\n latestUnread,\n markSeen,\n reportPresence,\n sendError,\n send,\n setTyping,\n } = useMedianThread(\n apiKey,\n user,\n telemetry,\n isLocked,\n diagnostics,\n appState,\n requireEmail,\n messagePreview,\n );\n\n // The card on the closed button, and the cross that waves it away. Held\n // per browser like the read state, so a dismissed reply stays dismissed\n // across the host's pages.\n const { teaser, dismiss: dismissTeaser } = useTeaser(apiKey, latestUnread);\n\n // Nothing here is settled yet: either the thread is on its way, or the\n // route that says whose thread it should be is. The panel shows the same\n // shimmer for both, because from the visitor's side they are one wait.\n const isSettling = isLoading || isResolvingIdentity;\n\n // Open is looking. It runs again as replies land, so a conversation read\n // live never builds up a count behind the panel that is showing it.\n useEffect(() => {\n if (isOpen) markSeen();\n }, [isOpen, markSeen]);\n\n // Somebody who has been answered here before, with the answers still behind\n // the button. They are the likeliest person on the page to open it, so the\n // renderer is fetched once the page has finished its own work rather than\n // waited for on the click. Everybody else pays nothing until they reach for\n // it. See `markdown-chunk.ts`.\n useEffect(() => {\n if (!threadRendersMarkdown(messages)) return;\n return warmMarkdownWhenIdle();\n }, [messages]);\n\n // The same fact, told to the server as a heartbeat: on open, on coming\n // back to the tab, and every so often in between. It is what keeps a\n // reply they are watching arrive from also landing in their email.\n useEffect(() => {\n if (!isOpen) return;\n\n const beat = () => {\n if (document.visibilityState === \"visible\") reportPresence();\n };\n beat();\n const interval = setInterval(beat, PRESENCE_BEAT_MS);\n document.addEventListener(\"visibilitychange\", beat);\n window.addEventListener(\"focus\", beat);\n return () => {\n clearInterval(interval);\n document.removeEventListener(\"visibilitychange\", beat);\n window.removeEventListener(\"focus\", beat);\n };\n }, [isOpen, reportPresence]);\n\n // Whether the panel is up or not: somebody who asked to be taken somewhere\n // and then closed the panel still asked.\n const direction = useSupportNavigation({\n messages,\n ask,\n // Signing in is the case this exists for. A page that has been watching\n // an empty query is handed the account's whole history the moment the\n // widget can say who they are, and an instruction from a conversation\n // they had last week is not an instruction to anybody now.\n conversationId,\n // Locked, there is no thread being read at all, so the first one to\n // arrive after somebody signs in is history like any other first look.\n isLoading: isSettling || isLocked,\n onNavigate,\n });\n\n // Also whether the panel is up or not, and for the same reason as the ring:\n // a reply landing behind a closed panel is the one most worth hearing.\n useMessageSound({\n messages,\n conversationId,\n isLoading: isSettling || isLocked,\n });\n\n // Until the config lands there is no name to put on the header, so the\n // launcher waits as a button and the panel shimmers if opened.\n const resolvedPresence = presence ?? {\n name: \"Support\",\n status: \"Connecting\",\n team: [],\n };\n\n // Whose name goes on the line about the page moving. The AI is the one that\n // called the tool, so it is the one that says so.\n const mover = resolvedPresence.team.find((member) => member.kind === \"ai\");\n\n return (\n <>\n {/* Keyed on the message that asked, so a second instruction is a second\n ring and a second line rather than a stale one carrying on. Two\n keys rather than one: these are siblings, and one message asking for\n both would otherwise hand them the same name. */}\n {direction?.selector != null && (\n <WidgetSpotlight\n key={`ring:${direction.key}`}\n selector={direction.selector}\n />\n )}\n {direction?.didNavigate === true && mover !== undefined && (\n <WidgetToast key={`moved:${direction.key}`} agent={mover}>\n {mover.name} navigated you here\n </WidgetToast>\n )}\n\n <SupportLauncher\n presence={resolvedPresence}\n messages={messages}\n // Passed through as a promise, so the composer can hold the draft on\n // a failed send and clear it on a delivered one.\n onSend={send}\n onTypingChange={setTyping}\n isLoading={isSettling}\n isLocked={isLocked}\n onSignIn={onSignIn}\n askForEmail={askForEmail}\n onSubmitEmail={setVisitorEmail}\n isSending={isSending}\n awaitingHuman={awaitingHuman}\n rating={rating}\n unreadCount={unreadCount}\n teaser={teaser}\n onDismissTeaser={dismissTeaser}\n notice={sendError}\n launcher={launcher}\n // Always controlled from here: the panel answers to the host's own\n // prop, to their trigger anywhere on the page, and to its own button,\n // and this is where those three are settled into one answer.\n open={isOpen}\n onOpenChange={setOpen}\n className={className}\n />\n </>\n );\n}\n","\"use client\";\n\nimport { lazy, useSyncExternalStore } from \"react\";\nimport type { SupportMessage } from \"./types\";\n\n/**\n * The markdown renderer, fetched when there is a reason to and not before.\n *\n * It is the heaviest thing the widget can reach: a parser, a sanitiser and an\n * HTML tokeniser, and together they outweigh everything else in the package\n * put together. They also cannot render anything until the panel is open, and\n * most visitors on most pages never open it. Loading them with the page\n * spends that on everybody to serve the few.\n *\n * So the import is a call rather than a statement, and the bundle splits\n * where the call is. What a host's page pays for on load is the button. The\n * rest arrives on the first sign that somebody wants it, which is early\n * enough to be there before they do:\n *\n * - the pointer reaching the launcher, or a tab landing on it\n * - the panel opening, whoever opened it\n * - a page going idle with an already answered thread behind the button\n *\n * Until it lands, a reply renders as the text it was written as, which is the\n * same paragraph a visitor's own message gets. A failed fetch leaves that in\n * place rather than leaving a hole where the answer was.\n */\n\nconst load = () => import(\"@/components/ui/message-markdown\");\n\n/**\n * The renderer itself, and the only place it is rendered from.\n *\n * `lazy` rather than a component held in a variable, so this is one component\n * for the life of the page rather than a new one per render. It is only ever\n * put on screen once `useMarkdownReady` says the module is already in hand,\n * so the suspense it can throw is a guard rather than a state anybody waits\n * in.\n */\nexport const MessageMarkdown = lazy(async () => ({\n default: (await load()).MessageMarkdown,\n}));\n\nlet ready = false;\nlet inFlight = false;\nconst listeners = new Set<() => void>();\n\n/**\n * Fetch it, unless it is already here or already on its way.\n *\n * Safe to call from anywhere, as often as you like: everything after the\n * first call in a page's life is a no-op. A fetch that fails clears the flag\n * so a later trigger can try again, which covers the tunnel a phone goes\n * through between the page loading and the visitor asking a question.\n */\nexport function warmMarkdown(): void {\n if (ready || inFlight) return;\n inFlight = true;\n\n void load().then(\n () => {\n ready = true;\n for (const listener of listeners) listener();\n },\n () => {\n inFlight = false;\n },\n );\n}\n\n/** How long to wait for an idle moment that may never come. */\nconst IDLE_FALLBACK_MS = 2_000;\n\n/**\n * The same, once the page has nothing better to do. Returns the cancel, so an\n * effect torn down before the browser gets round to it does not go on to\n * fetch a megabyte for a widget that has left the page.\n *\n * `requestIdleCallback` is missing on Safari before 17, so a timeout stands\n * in. The exact delay does not matter; being after the page's own work does.\n */\nexport function warmMarkdownWhenIdle(): () => void {\n if (typeof window === \"undefined\") return () => {};\n\n if (typeof window.requestIdleCallback === \"function\") {\n const handle = window.requestIdleCallback(() => warmMarkdown());\n return () => window.cancelIdleCallback(handle);\n }\n\n const timer = setTimeout(warmMarkdown, IDLE_FALLBACK_MS);\n return () => clearTimeout(timer);\n}\n\n/**\n * Whether there is anything in this thread that markdown would render\n * differently from a plain paragraph.\n *\n * Only the house voice writes markdown. What a visitor types is quoted\n * verbatim wherever it lands, so a thread of nothing but questions never\n * needs any of this and never fetches it.\n */\nexport function threadRendersMarkdown(messages: SupportMessage[]): boolean {\n return messages.some(\n (message) => message.sender !== \"visitor\" && message.body.length > 0,\n );\n}\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nconst read = () => ready;\n// False on the server and through hydration both, so the first client pass\n// renders what the server sent rather than a tree it has to throw away.\nconst onServer = () => false;\n\n/** Whether the module is in hand, so rendering it will not suspend. */\nexport function useMarkdownReady(): boolean {\n return useSyncExternalStore(subscribe, read, onServer);\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { ChatCircleDots } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport {\n clipOrigin,\n closedClip,\n type LauncherSide,\n} from \"./launcher-position\";\nimport { warmMarkdown } from \"./markdown-chunk\";\nimport { SupportWidget } from \"./support-widget\";\nimport { BUTTON_Y, useLauncherDrag } from \"./use-launcher-drag\";\nimport { useTeaserPlacement } from \"./use-teaser-placement\";\nimport { useWidgetSheet } from \"./use-widget-sheet\";\nimport { WidgetTeaser } from \"./widget-teaser\";\nimport type {\n SupportLauncherKind,\n SupportMessage,\n SupportPresence,\n SupportRating,\n} from \"./types\";\n\nconst DEFAULT_WIDTH = \"24rem\";\nconst DEFAULT_HEIGHT = \"34rem\";\nconst DEFAULT_BUTTON_SIZE = \"3.5rem\";\n\n/**\n * Bigger, for a thread you are actually reading rather than glancing at.\n *\n * More of the growth goes into the height than the width, because that is the\n * axis a conversation runs out of: room to see what was said, rather than room\n * per line. The width still moves, and moving it re-wraps every bubble as it\n * goes, so it is kept to the smaller number of the two.\n */\nconst EXPANDED_WIDTH = \"30rem\";\nconst EXPANDED_HEIGHT = \"46rem\";\n\n/**\n * The morph, as a clip rather than a resize.\n *\n * The panel is always laid out at its full size. Closed, it is clipped down to\n * a circle in the corner the size of the button; open, the clip is the panel\n * itself. Only the clip travels.\n *\n * This matters. Animating width and height means the browser lays out the whole\n * panel again on every frame, and the message scroller measures its viewport\n * every time that happens, so it fights the animation the entire way. Clipping\n * touches no layout at all: nothing inside ever moves, reflows or gets measured,\n * it is simply revealed.\n *\n * Where it grows out of is `launcher-position.ts`. The button can be dragged\n * anywhere up or down either edge, and the panel has to follow it there.\n */\n/**\n * The panel's own `rounded-xl`, to the same decimal.\n *\n * The clip used to be a hair rounder than the panel inside it, which is why\n * the panel had to give up its border: two curves that nearly agree meet in a\n * hairline, and a hairline that moves is the thing that makes an animation\n * look broken. Same number, one curve, and the border can come back.\n */\nconst PANEL_RADIUS = \"0.75rem\";\n\nconst OPEN_CLIP = `inset(0px 0px 0px 0px round ${PANEL_RADIUS})`;\n\n/**\n * The button's height inside the box.\n *\n * Measured and written by the drag before paint, because it is the difference\n * between two lengths taken against different boxes and no amount of `calc`\n * gets at that. The fallback is the resting place of a widget nobody has\n * moved, which is the one the server rendered and the only one on screen\n * before the measurement lands.\n */\nconst buttonY = (buttonSize: string) =>\n `var(${BUTTON_Y}, calc(100% - ${buttonSize}))`;\n\n/**\n * How far off the edges the whole thing sits. Close enough to read as parked\n * against the side rather than floating near it, and still clear of the corner\n * radius on a phone.\n */\nconst MARGIN = \"1rem\";\n\n/**\n * The bounce rides on a scale, not on the clip.\n *\n * A clip cannot show an overshoot: carrying past \"fully revealed\" only means\n * clipping outside the box, which looks like nothing at all. So the panel comes\n * up the last few percent of its size as it opens, and that is what carries a\n * touch too far and settles back. Around four pixels on a panel this wide,\n * which is about right for something you feel rather than watch.\n *\n * Scale is composited, so this costs the same as the clip does: nothing.\n */\nconst CLOSED_SCALE = \"scale(0.94)\";\nconst OPEN_SCALE = \"scale(1)\";\n\n/**\n * Where the panel comes from when there is no button for it to come from.\n *\n * A morph needs two shapes and one of them has gone. Clipping down to a circle\n * nobody can see is not an origin, it is a place the panel happens to vanish\n * at, and growing out of it reads as the corner deciding to produce a panel.\n * So it rises the last few pixels into place instead, which is what everything\n * that arrives out of nothing does.\n */\nconst RISEN = \"translateY(0.5rem) scale(0.98)\";\n\n/**\n * The shape, shared by the panel and the shadow layer behind it. One function\n * so the two cannot drift a frame apart.\n */\nconst shape = (\n isOpen: boolean,\n buttonSize: string,\n side: LauncherSide,\n hasBubble: boolean,\n) =>\n hasBubble\n ? {\n clipPath: isOpen\n ? OPEN_CLIP\n : closedClip(side, buttonY(buttonSize), buttonSize),\n transform: isOpen ? OPEN_SCALE : CLOSED_SCALE,\n // The point it grows out of, so the closed circle stays put under the\n // button rather than shrinking towards the middle.\n transformOrigin: clipOrigin(side, buttonY(buttonSize), buttonSize),\n }\n : { clipPath: OPEN_CLIP, transform: isOpen ? \"none\" : RISEN };\n\n/**\n * The two properties the morph is actually about, named rather than `all`.\n *\n * `transform-origin` is the one deliberately left out. It moves whenever the\n * button does, and easing a shape's origin across a panel while the shape\n * itself holds still is a swim, not a morph.\n */\nconst MORPH =\n \"transition-[clip-path,transform] duration-450 ease-spring motion-reduce:transition-none\";\n\n/**\n * The other one, for a widget with no button. Shorter and a pure deceleration:\n * a spring's overshoot is the button's swagger, and a panel that simply\n * appeared has not earned it.\n */\nconst ARRIVE =\n \"transition-transform duration-200 ease-out-quint motion-reduce:transition-none\";\n\n/**\n * The phone's version of the morph: none. A panel about to be the whole\n * screen has no corner to grow out of, so it rises into place as a sheet,\n * which is the shape every thumb has already been taught. A touch longer than\n * ARRIVE because it travels further, and the same pure deceleration.\n */\nconst SHEET =\n \"fixed transition-[opacity,transform] duration-300 ease-out-quint motion-reduce:transition-none\";\n\n/** Where the sheet waits: a little below its feet, ready to come up. */\nconst SHEET_RISEN = \"translateY(2rem)\";\n\n/**\n * A sheet is the screen, so the card's own dress goes: no corners against\n * edges that already have their own, no border where the screen ends, and\n * room for the notch and the home bar on hosts that let content under them.\n *\n * The home bar's room goes back while the keyboard has the bottom of the\n * screen, which is the sheet's own attribute for it: the panel's foot is then\n * the keyboard's top edge, and the inset would hold the composer a thumb's\n * width above the keys for no reason. It transitions rather than snapping,\n * since the keyboard is on its way in while this changes its mind.\n */\nconst SHEET_PANEL = cn(\n \"rounded-none border-0 pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]\",\n \"transition-[padding] duration-200 ease-out motion-reduce:transition-none\",\n \"[[data-keyboard=up]_&]:pb-0\",\n);\n\n/**\n * The three things about the box itself that move: whether it is there at all,\n * and how wide and tall it is.\n *\n * One declaration rather than two named ones, because they are one property\n * list. Two classes reads better and does not work: both set\n * `transition-property`, so the second simply replaces the first.\n *\n * With no button in the corner there is nothing to show while it is closed, so\n * the whole thing fades with the morph. Quicker than the morph either way: the\n * clip still carries the panel out of the corner and back into it, but the few\n * frames where that is an empty circle are spent at zero.\n *\n * What is not in the list is the travel between corners. That is an animation\n * on the node rather than a transition on this class, so a drag can move the\n * box every frame without a transition trying to catch up with it.\n *\n * `ease-out` rather than the app's usual `ease-out-quint`, which is the one\n * exception in here and is about what is moving. Quint spends about seven\n * tenths of the distance in the first quarter of the time, which is what makes\n * it feel quick on something composited. This is a size, so every one of those\n * frames lays the panel out again and re-wraps the text in it, and thirty odd\n * pixels of that per frame reads as the panel stuttering rather than growing.\n * A gentler curve over slightly longer moves the same distance in far more\n * even steps.\n */\nconst BOX =\n \"transition-[opacity,width,height] duration-300 ease-out motion-reduce:transition-none\";\n\n/**\n * The button, and the panel it turns into.\n *\n * The shadow sits on a layer above the clip rather than on it, because a filter\n * is painted before a clip and would otherwise be cut away with everything\n * else. On the parent it reads the clipped shape's alpha instead, so the shadow\n * follows the corner round as it opens.\n *\n * Uncontrolled by default. Pass `open` and `onOpenChange` to drive it yourself,\n * for a host that opens support from its own menu. Pass `launcher=\"hidden\"`\n * too and the corner is theirs again: nothing is on the page until they ask\n * for it.\n */\nexport function SupportLauncher({\n presence,\n messages,\n onSend,\n onTypingChange,\n isLoading = false,\n isLocked = false,\n onSignIn,\n askForEmail = false,\n onSubmitEmail,\n isSending = false,\n awaitingHuman = false,\n rating,\n unreadCount = 0,\n teaser = null,\n onDismissTeaser,\n notice,\n showBadge = true,\n width = DEFAULT_WIDTH,\n height = DEFAULT_HEIGHT,\n expandedWidth = EXPANDED_WIDTH,\n expandedHeight = EXPANDED_HEIGHT,\n buttonSize = DEFAULT_BUTTON_SIZE,\n launcher = \"bubble\",\n defaultOpen = false,\n open,\n onOpenChange,\n className,\n}: {\n presence: SupportPresence;\n messages: SupportMessage[];\n /** Awaited by the composer, which keeps the draft if it rejects. */\n onSend?: (body: string, files: File[]) => unknown;\n /** The visitor's own typing, throttled by the composer. */\n onTypingChange?: (isTyping: boolean) => unknown;\n isLoading?: boolean;\n /** Nobody is signed in, on a host that asks people to be. */\n isLocked?: boolean;\n /** Takes the visitor to the host's own sign in. */\n onSignIn?: () => void;\n /**\n * The composer asks for an email before a first message. Off here by\n * default: only the SDK decides it, from its prop and the team's switch.\n */\n askForEmail?: boolean;\n /** What the composer's question does with a good answer. */\n onSubmitEmail?: (email: string) => void;\n /** Holds the send button while a message is on its way. */\n isSending?: boolean;\n /** The agent has called for a person and nobody has picked it up yet. */\n awaitingHuman?: boolean;\n /** The finished conversation's one question, while it is worth asking. */\n rating?: SupportRating | null;\n /** Replies that arrived while the panel was closed. Sits on the button. */\n unreadCount?: number;\n /**\n * The newest of those, shown as a card on the closed button so the reply\n * can be read without opening anything. Null for no card.\n */\n teaser?: SupportMessage | null;\n /** The card's cross. Whoever owns `teaser` decides what a dismissal is. */\n onDismissTeaser?: () => void;\n /** One line above the composer, for a send that went wrong. */\n notice?: string | null;\n showBadge?: boolean;\n /** Any CSS length. The panel never grows past the viewport whatever this says. */\n width?: string;\n height?: string;\n /** What the header's own control grows it to, and back from. */\n expandedWidth?: string;\n expandedHeight?: string;\n /** The closed circle, and the corner the panel opens out of. */\n buttonSize?: string;\n /** Our button while it is closed, or nothing at all. */\n launcher?: SupportLauncherKind;\n /** Uncontrolled starting state. Ignored when `open` is passed. */\n defaultOpen?: boolean;\n /** Pass it to control the panel yourself. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Lands on the outer box. Override the default corner from here. */\n className?: string;\n}) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isOpen = open ?? uncontrolledOpen;\n const hasBubble = launcher === \"bubble\";\n\n // Kept while it is closed rather than reset, so a panel that was too small\n // once is not too small again the next time it is opened. Nothing is stored\n // between visits: it is a reach for more room right now, not a setting.\n const [isExpanded, setExpanded] = useState(false);\n\n const launcherRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const boxRef = useRef<HTMLDivElement>(null);\n\n // Where it lives, and how it gets moved. The button while it is closed, the\n // panel by its own header once it is open: one position, held by whichever\n // end of the widget is on the page at the time.\n const drag = useLauncherDrag({\n boxRef,\n buttonRef: launcherRef,\n margin: MARGIN,\n enabled: isOpen || hasBubble,\n subject: isOpen ? \"panel\" : \"button\",\n });\n\n // On a phone the open panel is the screen, not a card: it leaves the box,\n // covers the viewport, and follows the keyboard. The button and the box it\n // lives in never hear about any of this.\n const isSheet = useWidgetSheet({ boxRef, panelRef, isOpen });\n\n // The card over the button, when there is one to show and a button to show\n // it on. Which side of the button is measured, since a button dragged to\n // the top of the window has no room over it.\n const hasTeaser = teaser !== null && hasBubble;\n const teaserPlacement = useTeaserPlacement({\n buttonRef: launcherRef,\n enabled: hasTeaser,\n isMoving: drag.isMoving,\n });\n // Whatever had focus when the panel came up, so closing can hand it back.\n // Our own button, usually; the host's own trigger when there is no button.\n const opener = useRef<HTMLElement | null>(null);\n // Focus only moves once the panel has actually changed state. Without this a\n // widget that starts open would steal focus on page load.\n const wasOpen = useRef(isOpen);\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (open === undefined) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [open, onOpenChange],\n );\n\n const close = useCallback(() => setOpen(false), [setOpen]);\n\n // The panel is up, so the renderer is wanted now whether or not anything\n // touched the button on the way. A host opening it from their own nav never\n // does, and neither does a phone.\n useEffect(() => {\n if (isOpen) warmMarkdown();\n }, [isOpen]);\n\n // Escape closes, wherever focus happens to be inside the panel.\n useEffect(() => {\n if (!isOpen) return;\n\n function handleKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") close();\n }\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, close]);\n\n // Opening moves focus into the panel rather than onto the composer, so a\n // keyboard carries on from here without a phone throwing up its keyboard.\n // Closing hands it back where it came from.\n //\n // In an effect rather than in the handlers, because whichever end focus is\n // going to is still `inert` until the state that opened or closed it has\n // rendered, and focusing an inert element does nothing at all. It also has to\n // run for a host driving `open` themselves, who never touches a handler here.\n useEffect(() => {\n if (wasOpen.current === isOpen) return;\n wasOpen.current = isOpen;\n\n if (isOpen) {\n const active = document.activeElement;\n opener.current = active instanceof HTMLElement ? active : null;\n // Without `preventScroll` the browser scrolls the host's page to bring\n // the panel into view, and a panel that covers the screen is already in\n // view: all it does is drag the page out from under the sheet.\n panelRef.current?.focus({ preventScroll: true });\n return;\n }\n\n const back = launcherRef.current ?? opener.current;\n opener.current = null;\n // Only somewhere focus can actually land, and only if it is still on the\n // page: a menu that closed behind the panel is not there to take it back,\n // and leaving focus where it is beats throwing it at the body.\n if (back && back !== document.body && back.isConnected) back.focus();\n }, [isOpen]);\n\n return (\n // The box is panel sized whether it is open or not, so it never lets a\n // click through to the host's page. Only what is actually on screen takes\n // pointer events back.\n <div\n ref={boxRef}\n // The hook the published stylesheet scopes its resets to. On a page\n // without Tailwind there is no preflight, so the package ships one that\n // reaches no further than this box and its siblings below.\n data-median-widget=\"\"\n style={{\n width: isExpanded ? expandedWidth : width,\n height: isExpanded ? expandedHeight : height,\n ...drag.style,\n }}\n className={cn(\n \"pointer-events-none fixed z-50\",\n // Twice the margin, so the panel is inset by the same gap on both\n // sides however close to the edge the button has been put.\n //\n // Against whatever is positioning it as well as against the window,\n // which are the same thing for a widget on a host's page and are not\n // for one pinned inside a frame. Expanded is what finds the\n // difference: it is bigger than some of the boxes this turns up in,\n // and a panel hanging out the side of its own preview is not a panel\n // anybody is going to trust on their site.\n \"max-h-[min(calc(100svh-2rem),calc(100%-2rem))] max-w-[min(calc(100vw-2rem),calc(100%-2rem))]\",\n BOX,\n // Closed with no button on it, there is nothing here to see. The panel\n // stays mounted and stays `inert`, so the conversation is still live\n // and nothing behind it can be tabbed into by mistake.\n !hasBubble && !isOpen && \"opacity-0\",\n // The body wears the closed hand while a drag is on, which covers the\n // host's page. It does not reach in here, where the composer asks for\n // a caret and every button asks for a pointer, so this says it again\n // for everything inside.\n drag.isMoving && \"cursor-grabbing **:cursor-grabbing\",\n className,\n )}\n >\n {/* The shadow, on an empty layer of its own behind the panel.\n\n It cannot go on the panel, because a filter is painted before a clip\n and would be cut away with everything else. It also cannot go on a\n parent of the panel, which is where it used to be: a filter anywhere\n above a scrolling area stops the browser scrolling it the cheap way\n and makes it re-paint the whole thread on every frame instead, which\n is what made the thread stutter.\n\n So it goes on a sibling with nothing inside it. Same shape, same\n timing, no children to re-paint. */}\n {/* Not when the panel is a sheet: a full screen has no edges to throw a\n shadow past, and the closed circle it would leave in the corner sits\n entirely under the button, which carries a shadow of its own. */}\n {!isSheet && (\n <div aria-hidden className=\"absolute inset-0 drop-shadow-xl\">\n <div\n style={shape(isOpen, buttonSize, drag.side, hasBubble)}\n className={cn(\n \"size-full bg-card\",\n hasBubble ? MORPH : ARRIVE,\n drag.isMoving && \"transition-none\",\n )}\n />\n </div>\n )}\n\n <div\n ref={panelRef}\n tabIndex={-1}\n inert={!isOpen}\n // As a sheet it wears no clip at all: it fades and rises as one piece,\n // and the keyboard fit writes its edges straight onto the node.\n style={\n isSheet\n ? { transform: isOpen ? \"none\" : SHEET_RISEN }\n : shape(isOpen, buttonSize, drag.side, hasBubble)\n }\n className={cn(\n \"absolute inset-0 outline-none\",\n isSheet\n ? [SHEET, !isOpen && \"opacity-0\"]\n : [\n hasBubble ? MORPH : ARRIVE,\n // While it is travelling, the clip changes corners and there\n // is nothing to animate about that. Transitioning it wipes\n // the panel across the box on the way from one circle to the\n // other.\n drag.isMoving && \"transition-none\",\n ],\n isOpen && \"pointer-events-auto\",\n )}\n >\n <SupportWidget\n presence={presence}\n messages={messages}\n onSend={onSend}\n onTypingChange={onTypingChange}\n onClose={close}\n isExpanded={isExpanded}\n // A sheet is already every pixel there is, so a control that asks\n // for more would be a lie with an icon.\n onToggleExpanded={\n isSheet ? undefined : () => setExpanded((current) => !current)\n }\n isLoading={isLoading}\n isLocked={isLocked}\n onSignIn={onSignIn}\n askForEmail={askForEmail}\n onSubmitEmail={onSubmitEmail}\n isSending={isSending}\n awaitingHuman={awaitingHuman}\n rating={rating}\n notice={notice}\n showBadge={showBadge}\n // The header is the handle. Same four handlers the button wears,\n // and only one of the two is ever reachable at a time. A sheet has\n // nowhere to be dragged to, so there it is only a header.\n grabHandlers={isSheet ? undefined : drag.dragHandlers}\n isMoving={drag.isMoving}\n // Its own border and its own radius, which the clip is cut to match.\n // The panel is a card sitting on somebody else's page, and a card\n // here has an edge like a card anywhere else in the app. Unless it\n // is the screen, which has neither.\n className={isSheet ? SHEET_PANEL : undefined}\n />\n </div>\n\n {/* A sibling rather than a child of the clip, so its focus ring is not\n clipped away with it. Gone entirely when the host is doing the\n opening: an invisible button in the corner of somebody else's page\n would still be there to tab into. */}\n {hasBubble && (\n <button\n ref={launcherRef}\n type=\"button\"\n {...drag.dragHandlers}\n draggable={false}\n // The first sign anybody wants the panel. Fetching the renderer\n // here rather than on the click buys it the time between reaching\n // for the button and pressing it, which is usually all it needs.\n onPointerEnter={warmMarkdown}\n onFocus={warmMarkdown}\n onClick={() => {\n // The pointerup that ended a drag still arrives here as a click.\n // Opening on it would mean the panel came up every time somebody\n // moved the button, which is the one thing they did not ask for.\n if (drag.swallowClick()) return;\n setOpen(true);\n }}\n aria-expanded={isOpen}\n aria-label={\n unreadCount > 0\n ? `Chat with ${presence.name} support, ${unreadCount} unread`\n : `Chat with ${presence.name} support`\n }\n inert={isOpen}\n style={{\n width: buttonSize,\n height: buttonSize,\n // The same height the clip is cut at, from the same variable, so\n // the button and the circle under it cannot end up a pixel apart.\n top: buttonY(buttonSize),\n [drag.side]: 0,\n }}\n className={cn(\n \"absolute grid place-items-center rounded-full\",\n \"bg-primary text-primary-foreground shadow-lg outline-none\",\n // Struck off its own foreground rather than the border token. The\n // button is the inverse of the page it sits on, so `border` is a\n // colour picked to separate a card from the background and lands\n // invisible here: white at a tenth, over white. This reads as a\n // rim in both, because it is a tenth of whatever the icon is.\n \"border border-primary-foreground/15\",\n // Named properties rather than `all`, and the names matter.\n //\n // Its height inside the box is a real length now, and it changes\n // the instant a drag is committed. Under `transition-all` that is\n // an animatable property, so the button eased to its new height\n // over three hundred milliseconds after a two hundred millisecond\n // delay, while the clipped circle it is supposed to be sitting on\n // moved immediately. Half a second of a button beside its own\n // shadow rather than on it.\n //\n // Nothing about where it is should ever animate. The box carries\n // it, in one animation, and that is the only travel there is.\n \"transition-[opacity,transform,filter] motion-reduce:transition-none\",\n \"hover:brightness-125 focus-visible:ring-3 focus-visible:ring-ring/50\",\n // The browser must not claim the gesture for scrolling, or a drag\n // on a phone moves the page instead of the button.\n \"touch-none\",\n isOpen\n ? // Gone before the clip has opened far enough to show what is\n // underneath it.\n \"scale-90 opacity-0 duration-150 ease-out-quint\"\n : \"pointer-events-auto scale-100 opacity-100 delay-200 duration-300 ease-spring\",\n // Nothing on it is selectable, and it is not a thing the browser\n // may pick up and drag as an image either. Both of those end the\n // same way: the gesture becomes the browser's instead of ours.\n \"select-none\",\n // No scale while it is being dragged, and not only because the\n // press-in belongs to a tap. A scaled button measures scaled, and\n // every sum here starts from where its edges are.\n // A pointer at rest, not a grab hand. The button is a button first\n // and a thing you can move second, and hovering it should say the\n // first of those. The grab shows up once one is actually underway.\n !isOpen &&\n (drag.isMoving ? \"cursor-grabbing\" : \"cursor-pointer active:scale-95\"),\n )}\n >\n <ChatCircleDots className=\"size-6\" />\n\n {/* What arrived while they were not looking. The count is already in\n the button's own label, so this is only the picture of it.\n\n Struck off `background` rather than a fixed white, so it inverts\n with the theme and stays legible on the red either way. */}\n {unreadCount > 0 && (\n <span\n aria-hidden\n className={cn(\n \"absolute -top-0.5 -right-0.5 grid min-w-5 place-items-center rounded-full px-1\",\n \"bg-destructive text-xs font-semibold text-background tabular-nums\",\n \"ring-2 ring-card\",\n \"animate-in duration-300 ease-spring fade-in-0 zoom-in-50 motion-reduce:animate-none\",\n )}\n >\n {unreadCount > 9 ? \"9+\" : unreadCount}\n </span>\n )}\n </button>\n )}\n\n {/* The newest unread reply, as a card on the button. A sibling of the\n clip for the same reason the button is, and after it so it sits\n over everything else in the box. It hides itself the moment the\n panel is opening, since the panel is about to show the same words\n in full. */}\n {hasBubble && (\n <WidgetTeaser\n message={teaser}\n isShown={hasTeaser && !isOpen}\n side={drag.side}\n placement={teaserPlacement}\n buttonY={buttonY(buttonSize)}\n buttonSize={buttonSize}\n onOpen={() => setOpen(true)}\n onDismiss={() => onDismissTeaser?.()}\n />\n )}\n </div>\n );\n}\n","import * as e from \"react\";\nconst w = e.forwardRef((l, s) => {\n const {\n alt: r,\n color: a = \"currentColor\",\n size: t = \"1em\",\n weight: o = \"regular\",\n mirrored: i = !1,\n children: n,\n weights: c,\n ...m\n } = l;\n return /* @__PURE__ */ e.createElement(\n \"svg\",\n {\n ref: s,\n xmlns: \"http://www.w3.org/2000/svg\",\n width: t,\n height: t,\n fill: a,\n viewBox: \"0 0 256 256\",\n transform: i ? \"scale(-1, 1)\" : void 0,\n ...m\n },\n !!r && /* @__PURE__ */ e.createElement(\"title\", null, r),\n n,\n c.get(o)\n );\n});\nw.displayName = \"SSRBase\";\nexport {\n w as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/ArrowDown.es.js\";\nconst r = o.forwardRef((e, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...e, weights: m }));\nr.displayName = \"ArrowDownIcon\";\nconst s = r;\nexport {\n s as ArrowDown,\n r as ArrowDownIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208.49,152.49l-72,72a12,12,0,0,1-17,0l-72-72a12,12,0,0,1,17-17L116,187V40a12,12,0,0,1,24,0V187l51.51-51.52a12,12,0,0,1,17,17Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M200,144l-72,72L56,144Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M207.39,140.94A8,8,0,0,0,200,136H136V40a8,8,0,0,0-16,0v96H56a8,8,0,0,0-5.66,13.66l72,72a8,8,0,0,0,11.32,0l72-72A8,8,0,0,0,207.39,140.94ZM128,204.69,75.31,152H180.69Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72A8,8,0,0,1,56,136h64V40a8,8,0,0,1,16,0v96h64a8,8,0,0,1,5.66,13.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M204.24,148.24l-72,72a6,6,0,0,1-8.48,0l-72-72a6,6,0,0,1,8.48-8.48L122,201.51V40a6,6,0,0,1,12,0V201.51l61.76-61.75a6,6,0,0,1,8.48,8.48Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72a8,8,0,0,1,11.32-11.32L120,196.69V40a8,8,0,0,1,16,0V196.69l58.34-58.35a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M202.83,146.83l-72,72a4,4,0,0,1-5.66,0l-72-72a4,4,0,0,1,5.66-5.66L124,206.34V40a4,4,0,0,1,8,0V206.34l65.17-65.17a4,4,0,0,1,5.66,5.66Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as r from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/ArrowUp.es.js\";\nconst o = r.forwardRef((e, t) => /* @__PURE__ */ r.createElement(a, { ref: t, ...e, weights: m }));\no.displayName = \"ArrowUpIcon\";\nconst c = o;\nexport {\n c as ArrowUp,\n o as ArrowUpIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208.49,120.49a12,12,0,0,1-17,0L140,69V216a12,12,0,0,1-24,0V69L64.49,120.49a12,12,0,0,1-17-17l72-72a12,12,0,0,1,17,0l72,72A12,12,0,0,1,208.49,120.49Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M200,112H56l72-72Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,106.34l-72-72a8,8,0,0,0-11.32,0l-72,72A8,8,0,0,0,56,120h64v96a8,8,0,0,0,16,0V120h64a8,8,0,0,0,5.66-13.66ZM75.31,104,128,51.31,180.69,104Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M207.39,115.06A8,8,0,0,1,200,120H136v96a8,8,0,0,1-16,0V120H56a8,8,0,0,1-5.66-13.66l72-72a8,8,0,0,1,11.32,0l72,72A8,8,0,0,1,207.39,115.06Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M204.24,116.24a6,6,0,0,1-8.48,0L134,54.49V216a6,6,0,0,1-12,0V54.49L60.24,116.24a6,6,0,0,1-8.48-8.48l72-72a6,6,0,0,1,8.48,0l72,72A6,6,0,0,1,204.24,116.24Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,117.66a8,8,0,0,1-11.32,0L136,59.31V216a8,8,0,0,1-16,0V59.31L61.66,117.66a8,8,0,0,1-11.32-11.32l72-72a8,8,0,0,1,11.32,0l72,72A8,8,0,0,1,205.66,117.66Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M202.83,114.83a4,4,0,0,1-5.66,0L132,49.66V216a4,4,0,0,1-8,0V49.66L58.83,114.83a4,4,0,0,1-5.66-5.66l72-72a4,4,0,0,1,5.66,0l72,72A4,4,0,0,1,202.83,114.83Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport c from \"../defs/ArrowsClockwise.es.js\";\nconst r = o.forwardRef((e, s) => /* @__PURE__ */ o.createElement(t, { ref: s, ...e, weights: c }));\nr.displayName = \"ArrowsClockwiseIcon\";\nconst m = r;\nexport {\n m as ArrowsClockwise,\n r as ArrowsClockwiseIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M228,48V96a12,12,0,0,1-12,12H168a12,12,0,0,1,0-24h19l-7.8-7.8a75.55,75.55,0,0,0-53.32-22.26h-.43A75.49,75.49,0,0,0,72.39,75.57,12,12,0,1,1,55.61,58.41a99.38,99.38,0,0,1,69.87-28.47H126A99.42,99.42,0,0,1,196.2,59.23L204,67V48a12,12,0,0,1,24,0ZM183.61,180.43a75.49,75.49,0,0,1-53.09,21.63h-.43A75.55,75.55,0,0,1,76.77,179.8L69,172H88a12,12,0,0,0,0-24H40a12,12,0,0,0-12,12v48a12,12,0,0,0,24,0V189l7.8,7.8A99.42,99.42,0,0,0,130,226.06h.56a99.38,99.38,0,0,0,69.87-28.47,12,12,0,0,0-16.78-17.16Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1-5.66-13.66L180.65,72a79.48,79.48,0,0,0-54.72-22.09h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27,96,96,0,0,1,192,60.7l18.36-18.36A8,8,0,0,1,224,48ZM186.41,183.29A80,80,0,0,1,75.35,184l18.31-18.31A8,8,0,0,0,88,152H40a8,8,0,0,0-8,8v48a8,8,0,0,0,13.66,5.66L64,195.3a95.42,95.42,0,0,0,66,26.76h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M222,48V96a6,6,0,0,1-6,6H168a6,6,0,0,1,0-12h33.52L183.47,72a81.51,81.51,0,0,0-57.53-24h-.46A81.5,81.5,0,0,0,68.19,71.28a6,6,0,1,1-8.38-8.58,93.38,93.38,0,0,1,65.67-26.76H126a93.45,93.45,0,0,1,66,27.53l18,18V48a6,6,0,0,1,12,0ZM187.81,184.72a81.5,81.5,0,0,1-57.29,23.34h-.46a81.51,81.51,0,0,1-57.53-24L54.48,166H88a6,6,0,0,0,0-12H40a6,6,0,0,0-6,6v48a6,6,0,0,0,12,0V174.48l18,18.05a93.45,93.45,0,0,0,66,27.53h.52a93.38,93.38,0,0,0,65.67-26.76,6,6,0,1,0-8.38-8.58Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M220,48V96a4,4,0,0,1-4,4H168a4,4,0,0,1,0-8h38.34L184.89,70.54A84,84,0,0,0,66.8,69.85a4,4,0,1,1-5.6-5.72,92,92,0,0,1,129.34.76L212,86.34V48a4,4,0,0,1,8,0ZM189.2,186.15a83.44,83.44,0,0,1-58.68,23.91h-.47a83.52,83.52,0,0,1-58.94-24.6L49.66,164H88a4,4,0,0,0,0-8H40a4,4,0,0,0-4,4v48a4,4,0,0,0,8,0V169.66l21.46,21.45A91.43,91.43,0,0,0,130,218.06h.51a91.45,91.45,0,0,0,64.28-26.19,4,4,0,1,0-5.6-5.72Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as r from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/ArrowsIn.es.js\";\nconst o = r.forwardRef((e, s) => /* @__PURE__ */ r.createElement(t, { ref: s, ...e, weights: a }));\no.displayName = \"ArrowsInIcon\";\nconst c = o;\nexport {\n c as ArrowsIn,\n o as ArrowsInIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M140,104V64a12,12,0,0,1,24,0V75l35.51-35.52a12,12,0,0,1,17,17L181,92h11a12,12,0,0,1,0,24H152A12,12,0,0,1,140,104Zm-36,36H64a12,12,0,0,0,0,24H75L39.51,199.51a12,12,0,0,0,17,17L92,181v11a12,12,0,0,0,24,0V152A12,12,0,0,0,104,140Zm77,24h11a12,12,0,0,0,0-24H152a12,12,0,0,0-12,12v40a12,12,0,0,0,24,0V181l35.51,35.52a12,12,0,0,0,17-17ZM104,52A12,12,0,0,0,92,64V75L56.49,39.51a12,12,0,0,0-17,17L75,92H64a12,12,0,0,0,0,24h40a12,12,0,0,0,12-12V64A12,12,0,0,0,104,52Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,104V64a8,8,0,0,1,16,0V84.69l42.34-42.35a8,8,0,0,1,11.32,11.32L171.31,96H192a8,8,0,0,1,0,16H152A8,8,0,0,1,144,104Zm-40,40H64a8,8,0,0,0,0,16H84.69L42.34,202.34a8,8,0,0,0,11.32,11.32L96,171.31V192a8,8,0,0,0,16,0V152A8,8,0,0,0,104,144Zm67.31,16H192a8,8,0,0,0,0-16H152a8,8,0,0,0-8,8v40a8,8,0,0,0,16,0V171.31l42.34,42.35a8,8,0,0,0,11.32-11.32ZM104,56a8,8,0,0,0-8,8V84.69L53.66,42.34A8,8,0,0,0,42.34,53.66L84.69,96H64a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V64A8,8,0,0,0,104,56Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,104V64a8,8,0,0,1,13.66-5.66L172,72.69l30.34-30.35a8,8,0,0,1,11.32,11.32L183.31,84l14.35,14.34A8,8,0,0,1,192,112H152A8,8,0,0,1,144,104Zm-40,40H64a8,8,0,0,0-5.66,13.66L72.69,172,42.34,202.34a8,8,0,0,0,11.32,11.32L84,183.31l14.34,14.35A8,8,0,0,0,112,192V152A8,8,0,0,0,104,144Zm3.06-87.39a8,8,0,0,0-8.72,1.73L84,72.69,53.66,42.34A8,8,0,0,0,42.34,53.66L72.69,84,58.34,98.34A8,8,0,0,0,64,112h40a8,8,0,0,0,8-8V64A8,8,0,0,0,107.06,56.61ZM183.31,172l14.35-14.34A8,8,0,0,0,192,144H152a8,8,0,0,0-8,8v40a8,8,0,0,0,13.66,5.66L172,183.31l30.34,30.35a8,8,0,0,0,11.32-11.32Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M146,104V64a6,6,0,0,1,12,0V89.51l45.76-45.75a6,6,0,0,1,8.48,8.48L166.48,98H192a6,6,0,0,1,0,12H152A6,6,0,0,1,146,104Zm-42,42H64a6,6,0,0,0,0,12H89.52L43.76,203.76a6,6,0,1,0,8.48,8.48L98,166.48V192a6,6,0,0,0,12,0V152A6,6,0,0,0,104,146Zm62.48,12H192a6,6,0,0,0,0-12H152a6,6,0,0,0-6,6v40a6,6,0,0,0,12,0V166.48l45.76,45.76a6,6,0,0,0,8.48-8.48ZM104,58a6,6,0,0,0-6,6V89.51L52.24,43.76a6,6,0,0,0-8.48,8.48L89.52,98H64a6,6,0,0,0,0,12h40a6,6,0,0,0,6-6V64A6,6,0,0,0,104,58Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,104V64a8,8,0,0,1,16,0V84.69l42.34-42.35a8,8,0,0,1,11.32,11.32L171.31,96H192a8,8,0,0,1,0,16H152A8,8,0,0,1,144,104Zm-40,40H64a8,8,0,0,0,0,16H84.69L42.34,202.34a8,8,0,0,0,11.32,11.32L96,171.31V192a8,8,0,0,0,16,0V152A8,8,0,0,0,104,144Zm67.31,16H192a8,8,0,0,0,0-16H152a8,8,0,0,0-8,8v40a8,8,0,0,0,16,0V171.31l42.34,42.35a8,8,0,0,0,11.32-11.32ZM104,56a8,8,0,0,0-8,8V84.69L53.66,42.34A8,8,0,0,0,42.34,53.66L84.69,96H64a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V64A8,8,0,0,0,104,56Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M148,104V64a4,4,0,0,1,8,0V94.34l49.17-49.17a4,4,0,1,1,5.66,5.66L161.66,100H192a4,4,0,0,1,0,8H152A4,4,0,0,1,148,104Zm-44,44H64a4,4,0,0,0,0,8H94.34L45.17,205.17a4,4,0,0,0,5.66,5.66L100,161.66V192a4,4,0,0,0,8,0V152A4,4,0,0,0,104,148Zm57.66,8H192a4,4,0,0,0,0-8H152a4,4,0,0,0-4,4v40a4,4,0,0,0,8,0V161.66l49.17,49.17a4,4,0,0,0,5.66-5.66ZM104,60a4,4,0,0,0-4,4V94.34L50.83,45.17a4,4,0,0,0-5.66,5.66L94.34,100H64a4,4,0,0,0,0,8h40a4,4,0,0,0,4-4V64A4,4,0,0,0,104,60Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as r from \"react\";\nimport s from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/ArrowsOut.es.js\";\nconst o = r.forwardRef((t, e) => /* @__PURE__ */ r.createElement(s, { ref: e, ...t, weights: a }));\no.displayName = \"ArrowsOutIcon\";\nconst f = o;\nexport {\n f as ArrowsOut,\n o as ArrowsOutIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M220,48V96a12,12,0,0,1-24,0V77l-35.51,35.52a12,12,0,0,1-17-17L179,60H160a12,12,0,0,1,0-24h48A12,12,0,0,1,220,48ZM95.51,143.51,60,179V160a12,12,0,0,0-24,0v48a12,12,0,0,0,12,12H96a12,12,0,0,0,0-24H77l35.52-35.51a12,12,0,0,0-17-17ZM208,148a12,12,0,0,0-12,12v19l-35.51-35.52a12,12,0,0,0-17,17L179,196H160a12,12,0,0,0,0,24h48a12,12,0,0,0,12-12V160A12,12,0,0,0,208,148ZM77,60H96a12,12,0,0,0,0-24H48A12,12,0,0,0,36,48V96a12,12,0,0,0,24,0V77l35.51,35.52a12,12,0,0,0,17-17Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,48V208H48V48Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,48V96a8,8,0,0,1-16,0V67.31l-42.34,42.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM98.34,146.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l42.35-42.34a8,8,0,0,0-11.32-11.32ZM208,152a8,8,0,0,0-8,8v28.69l-42.34-42.35a8,8,0,0,0-11.32,11.32L188.69,200H160a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V160A8,8,0,0,0,208,152ZM67.31,56H96a8,8,0,0,0,0-16H48a8,8,0,0,0-8,8V96a8,8,0,0,0,16,0V67.31l42.34,42.35a8,8,0,0,0,11.32-11.32Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M109.66,146.34a8,8,0,0,1,0,11.32L83.31,184l18.35,18.34A8,8,0,0,1,96,216H48a8,8,0,0,1-8-8V160a8,8,0,0,1,13.66-5.66L72,172.69l26.34-26.35A8,8,0,0,1,109.66,146.34ZM83.31,72l18.35-18.34A8,8,0,0,0,96,40H48a8,8,0,0,0-8,8V96a8,8,0,0,0,13.66,5.66L72,83.31l26.34,26.35a8,8,0,0,0,11.32-11.32ZM208,40H160a8,8,0,0,0-5.66,13.66L172.69,72,146.34,98.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Zm3.06,112.61a8,8,0,0,0-8.72,1.73L184,172.69l-26.34-26.35a8,8,0,0,0-11.32,11.32L172.69,184l-18.35,18.34A8,8,0,0,0,160,216h48a8,8,0,0,0,8-8V160A8,8,0,0,0,211.06,152.61Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M214,48V96a6,6,0,0,1-12,0V62.48l-45.76,45.76a6,6,0,0,1-8.48-8.48L193.52,54H160a6,6,0,0,1,0-12h48A6,6,0,0,1,214,48ZM99.76,147.76,54,193.52V160a6,6,0,0,0-12,0v48a6,6,0,0,0,6,6H96a6,6,0,0,0,0-12H62.48l45.76-45.76a6,6,0,0,0-8.48-8.48ZM208,154a6,6,0,0,0-6,6v33.52l-45.76-45.76a6,6,0,0,0-8.48,8.48L193.52,202H160a6,6,0,0,0,0,12h48a6,6,0,0,0,6-6V160A6,6,0,0,0,208,154ZM62.48,54H96a6,6,0,0,0,0-12H48a6,6,0,0,0-6,6V96a6,6,0,0,0,12,0V62.48l45.76,45.76a6,6,0,0,0,8.48-8.48Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M216,48V96a8,8,0,0,1-16,0V67.31l-42.34,42.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM98.34,146.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l42.35-42.34a8,8,0,0,0-11.32-11.32ZM208,152a8,8,0,0,0-8,8v28.69l-42.34-42.35a8,8,0,0,0-11.32,11.32L188.69,200H160a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V160A8,8,0,0,0,208,152ZM67.31,56H96a8,8,0,0,0,0-16H48a8,8,0,0,0-8,8V96a8,8,0,0,0,16,0V67.31l42.34,42.35a8,8,0,0,0,11.32-11.32Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M212,48V96a4,4,0,0,1-8,0V57.66l-49.17,49.17a4,4,0,0,1-5.66-5.66L198.34,52H160a4,4,0,0,1,0-8h48A4,4,0,0,1,212,48ZM101.17,149.17,52,198.34V160a4,4,0,0,0-8,0v48a4,4,0,0,0,4,4H96a4,4,0,0,0,0-8H57.66l49.17-49.17a4,4,0,0,0-5.66-5.66ZM208,156a4,4,0,0,0-4,4v38.34l-49.17-49.17a4,4,0,0,0-5.66,5.66L198.34,204H160a4,4,0,0,0,0,8h48a4,4,0,0,0,4-4V160A4,4,0,0,0,208,156ZM57.66,52H96a4,4,0,0,0,0-8H48a4,4,0,0,0-4,4V96a4,4,0,0,0,8,0V57.66l49.17,49.17a4,4,0,0,0,5.66-5.66Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Bug.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...r, weights: m }));\ne.displayName = \"BugIcon\";\nconst f = e;\nexport {\n f as Bug,\n e as BugIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M140,88a16,16,0,1,1,16,16A16,16,0,0,1,140,88ZM100,72a16,16,0,1,0,16,16A16,16,0,0,0,100,72Zm120,72a91.84,91.84,0,0,1-2.34,20.64L236.81,173a12,12,0,0,1-9.62,22l-18-7.85a92,92,0,0,1-162.46,0l-18,7.85a12,12,0,1,1-9.62-22l19.15-8.36A91.84,91.84,0,0,1,36,144v-4H16a12,12,0,0,1,0-24H36v-4a91.84,91.84,0,0,1,2.34-20.64L19.19,83a12,12,0,0,1,9.62-22l18,7.85a92,92,0,0,1,162.46,0l18-7.85a12,12,0,1,1,9.62,22l-19.15,8.36A91.84,91.84,0,0,1,220,112v4h20a12,12,0,0,1,0,24H220ZM60,116H196v-4a68,68,0,0,0-136,0Zm56,94.92V140H60v4A68.1,68.1,0,0,0,116,210.92ZM196,144v-4H140v70.92A68.1,68.1,0,0,0,196,144Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,128v16a80,80,0,0,1-160,0V128Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,92a12,12,0,1,1,12,12A12,12,0,0,1,144,92ZM100,80a12,12,0,1,0,12,12A12,12,0,0,0,100,80Zm116,64A87.76,87.76,0,0,1,213,167l22.24,9.72A8,8,0,0,1,232,192a7.89,7.89,0,0,1-3.2-.67L207.38,182a88,88,0,0,1-158.76,0L27.2,191.33A7.89,7.89,0,0,1,24,192a8,8,0,0,1-3.2-15.33L43,167A87.76,87.76,0,0,1,40,144v-8H16a8,8,0,0,1,0-16H40v-8a87.76,87.76,0,0,1,3-23L20.8,79.33a8,8,0,1,1,6.4-14.66L48.62,74a88,88,0,0,1,158.76,0l21.42-9.36a8,8,0,0,1,6.4,14.66L213,89.05a87.76,87.76,0,0,1,3,23v8h24a8,8,0,0,1,0,16H216ZM56,120H200v-8a72,72,0,0,0-144,0Zm64,95.54V136H56v8A72.08,72.08,0,0,0,120,215.54ZM200,144v-8H136v79.54A72.08,72.08,0,0,0,200,144Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M168,92a12,12,0,1,1-12-12A12,12,0,0,1,168,92ZM100,80a12,12,0,1,0,12,12A12,12,0,0,0,100,80Zm116,64A87.76,87.76,0,0,1,213,167l22.24,9.72A8,8,0,0,1,232,192a7.89,7.89,0,0,1-3.2-.67L207.38,182a88,88,0,0,1-158.76,0L27.2,191.33A7.89,7.89,0,0,1,24,192a8,8,0,0,1-3.2-15.33L43,167A87.76,87.76,0,0,1,40,144v-8H16a8,8,0,0,1,0-16H40v-8a87.76,87.76,0,0,1,3-23L20.8,79.33a8,8,0,1,1,6.4-14.66L48.62,74a88,88,0,0,1,158.76,0l21.42-9.36a8,8,0,0,1,6.4,14.66L213,89.05a87.76,87.76,0,0,1,3,23v8h24a8,8,0,0,1,0,16H216Zm-80,0a8,8,0,0,0-16,0v64a8,8,0,0,0,16,0Zm64-32a72,72,0,0,0-144,0v8H200Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M146,92a10,10,0,1,1,10,10A10,10,0,0,1,146,92ZM100,82a10,10,0,1,0,10,10A10,10,0,0,0,100,82Zm146,46a6,6,0,0,1-6,6H214v10a85.88,85.88,0,0,1-3.45,24.08L234.4,178.5a6,6,0,0,1-4.8,11l-23.23-10.15a86,86,0,0,1-156.74,0L26.4,189.5a6,6,0,1,1-4.8-11l23.85-10.42A85.88,85.88,0,0,1,42,144V134H16a6,6,0,0,1,0-12H42V112a85.88,85.88,0,0,1,3.45-24.08L21.6,77.5a6,6,0,0,1,4.8-11L49.63,76.65a86,86,0,0,1,156.74,0L229.6,66.5a6,6,0,1,1,4.8,11L210.55,87.92A85.88,85.88,0,0,1,214,112v10h26A6,6,0,0,1,246,128ZM54,122H202V112a74,74,0,0,0-148,0Zm68,95.74V134H54v10A74.09,74.09,0,0,0,122,217.74ZM202,134H134v83.74A74.09,74.09,0,0,0,202,144Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M144,92a12,12,0,1,1,12,12A12,12,0,0,1,144,92ZM100,80a12,12,0,1,0,12,12A12,12,0,0,0,100,80Zm116,64A87.76,87.76,0,0,1,213,167l22.24,9.72A8,8,0,0,1,232,192a7.89,7.89,0,0,1-3.2-.67L207.38,182a88,88,0,0,1-158.76,0L27.2,191.33A7.89,7.89,0,0,1,24,192a8,8,0,0,1-3.2-15.33L43,167A87.76,87.76,0,0,1,40,144v-8H16a8,8,0,0,1,0-16H40v-8a87.76,87.76,0,0,1,3-23L20.8,79.33a8,8,0,1,1,6.4-14.66L48.62,74a88,88,0,0,1,158.76,0l21.42-9.36a8,8,0,0,1,6.4,14.66L213,89.05a87.76,87.76,0,0,1,3,23v8h24a8,8,0,0,1,0,16H216ZM56,120H200v-8a72,72,0,0,0-144,0Zm64,95.54V136H56v8A72.08,72.08,0,0,0,120,215.54ZM200,144v-8H136v79.54A72.08,72.08,0,0,0,200,144Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M148,92a8,8,0,1,1,8,8A8,8,0,0,1,148,92Zm-48-8a8,8,0,1,0,8,8A8,8,0,0,0,100,84Zm144,44a4,4,0,0,1-4,4H212v12a83.64,83.64,0,0,1-3.87,25.2l25.47,11.13A4,4,0,0,1,232,188a4.09,4.09,0,0,1-1.6-.33l-25-10.95a84,84,0,0,1-154.72,0l-25,10.95A4.09,4.09,0,0,1,24,188a4,4,0,0,1-1.6-7.67L47.87,169.2A83.64,83.64,0,0,1,44,144V132H16a4,4,0,0,1,0-8H44V112a83.64,83.64,0,0,1,3.87-25.2L22.4,75.67a4,4,0,0,1,3.2-7.34l25,11a84,84,0,0,1,154.72,0l25-11a4,4,0,1,1,3.2,7.34L208.13,86.8A83.64,83.64,0,0,1,212,112v12h28A4,4,0,0,1,244,128ZM52,124H204V112a76,76,0,0,0-152,0Zm72,95.89V132H52v12A76.09,76.09,0,0,0,124,219.89ZM204,132H132v87.89A76.09,76.09,0,0,0,204,144Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as t from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport i from \"../defs/CaretRight.es.js\";\nconst e = t.forwardRef((r, o) => /* @__PURE__ */ t.createElement(a, { ref: o, ...r, weights: i }));\ne.displayName = \"CaretRightIcon\";\nconst c = e;\nexport {\n c as CaretRight,\n e as CaretRightIcon\n};\n","import * as e from \"react\";\nconst t = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M184.49,136.49l-80,80a12,12,0,0,1-17-17L159,128,87.51,56.49a12,12,0,1,1,17-17l80,80A12,12,0,0,1,184.49,136.49Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M176,128,96,208V48Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M181.66,122.34l-80-80A8,8,0,0,0,88,48V208a8,8,0,0,0,13.66,5.66l80-80A8,8,0,0,0,181.66,122.34ZM104,188.69V67.31L164.69,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M181.66,133.66l-80,80A8,8,0,0,1,88,208V48a8,8,0,0,1,13.66-5.66l80,80A8,8,0,0,1,181.66,133.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M180.24,132.24l-80,80a6,6,0,0,1-8.48-8.48L167.51,128,91.76,52.24a6,6,0,0,1,8.48-8.48l80,80A6,6,0,0,1,180.24,132.24Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M178.83,130.83l-80,80a4,4,0,0,1-5.66-5.66L170.34,128,93.17,50.83a4,4,0,0,1,5.66-5.66l80,80A4,4,0,0,1,178.83,130.83Z\" }))\n ]\n]);\nexport {\n t as default\n};\n","import * as t from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport s from \"../defs/ChatCircleDots.es.js\";\nconst o = t.forwardRef((e, r) => /* @__PURE__ */ t.createElement(a, { ref: r, ...e, weights: s }));\no.displayName = \"ChatCircleDotsIcon\";\nconst m = o;\nexport {\n m as ChatCircleDots,\n o as ChatCircleDotsIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M120,128a16,16,0,1,1-16-16A16,16,0,0,1,120,128Zm32-16a16,16,0,1,0,16,16A16,16,0,0,0,152,112Zm84,16A108,108,0,0,1,78.77,224.15L46.34,235A20,20,0,0,1,21,209.66l10.81-32.43A108,108,0,1,1,236,128Zm-24,0A84,84,0,1,0,55.27,170.06a12,12,0,0,1,1,9.81l-9.93,29.79,29.79-9.93a12.1,12.1,0,0,1,3.8-.62,12,12,0,0,1,6,1.62A84,84,0,0,0,212,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M224,128A96,96,0,0,1,79.93,211.11h0L42.54,223.58a8,8,0,0,1-10.12-10.12l12.47-37.39h0A96,96,0,1,1,224,128Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24Zm0,192a87.87,87.87,0,0,1-44.06-11.81,8,8,0,0,0-4-1.08,7.85,7.85,0,0,0-2.53.42L40,216,52.47,178.6a8,8,0,0,0-.66-6.54A88,88,0,1,1,128,216Zm12-88a12,12,0,1,1-12-12A12,12,0,0,1,140,128Zm-44,0a12,12,0,1,1-12-12A12,12,0,0,1,96,128Zm88,0a12,12,0,1,1-12-12A12,12,0,0,1,184,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24ZM84,140a12,12,0,1,1,12-12A12,12,0,0,1,84,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,128,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,172,140Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M138,128a10,10,0,1,1-10-10A10,10,0,0,1,138,128ZM84,118a10,10,0,1,0,10,10A10,10,0,0,0,84,118Zm88,0a10,10,0,1,0,10,10A10,10,0,0,0,172,118Zm58,10A102,102,0,0,1,79.31,217.65L44.44,229.27a14,14,0,0,1-17.71-17.71l11.62-34.87A102,102,0,1,1,230,128Zm-12,0A90,90,0,1,0,50.08,173.06a6,6,0,0,1,.5,4.91L38.12,215.35a2,2,0,0,0,2.53,2.53L78,205.42a6.2,6.2,0,0,1,1.9-.31,6.09,6.09,0,0,1,3,.81A90,90,0,0,0,218,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128ZM84,116a12,12,0,1,0,12,12A12,12,0,0,0,84,116Zm88,0a12,12,0,1,0,12,12A12,12,0,0,0,172,116Zm60,12A104,104,0,0,1,79.12,219.82L45.07,231.17a16,16,0,0,1-20.24-20.24l11.35-34.05A104,104,0,1,1,232,128Zm-16,0A88,88,0,1,0,51.81,172.06a8,8,0,0,1,.66,6.54L40,216,77.4,203.53a7.85,7.85,0,0,1,2.53-.42,8,8,0,0,1,4,1.08A88,88,0,0,0,216,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M136,128a8,8,0,1,1-8-8A8,8,0,0,1,136,128Zm-52-8a8,8,0,1,0,8,8A8,8,0,0,0,84,120Zm88,0a8,8,0,1,0,8,8A8,8,0,0,0,172,120Zm56,8A100,100,0,0,1,79.5,215.47l-35.69,11.9a12,12,0,0,1-15.18-15.18l11.9-35.69A100,100,0,1,1,228,128Zm-8,0A92,92,0,1,0,48.35,174.07a4,4,0,0,1,.33,3.27L36.22,214.72a4,4,0,0,0,5.06,5.06l37.38-12.46a3.93,3.93,0,0,1,1.27-.21,4.05,4.05,0,0,1,2,.54A92,92,0,0,0,220,128Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as e from \"react\";\nimport c from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/Check.es.js\";\nconst o = e.forwardRef((r, t) => /* @__PURE__ */ e.createElement(c, { ref: t, ...r, weights: a }));\no.displayName = \"CheckIcon\";\nconst f = o;\nexport {\n f as Check,\n o as CheckIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M232,56V200a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,85.66l-96,96a8,8,0,0,1-11.32,0l-40-40a8,8,0,0,1,11.32-11.32L104,164.69l90.34-90.35a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM205.66,85.66l-96,96a8,8,0,0,1-11.32,0l-40-40a8,8,0,0,1,11.32-11.32L104,164.69l90.34-90.35a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M228.24,76.24l-128,128a6,6,0,0,1-8.48,0l-56-56a6,6,0,0,1,8.48-8.48L96,191.51,219.76,67.76a6,6,0,0,1,8.48,8.48Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M229.66,77.66l-128,128a8,8,0,0,1-11.32,0l-56-56a8,8,0,0,1,11.32-11.32L96,188.69,218.34,66.34a8,8,0,0,1,11.32,11.32Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M226.83,74.83l-128,128a4,4,0,0,1-5.66,0l-56-56a4,4,0,0,1,5.66-5.66L96,194.34,221.17,69.17a4,4,0,1,1,5.66,5.66Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport r from \"../lib/SSRBase.es.js\";\nimport t from \"../defs/EnvelopeSimple.es.js\";\nconst o = e.forwardRef((m, p) => /* @__PURE__ */ e.createElement(r, { ref: p, ...m, weights: t }));\no.displayName = \"EnvelopeSimpleIcon\";\nconst l = o;\nexport {\n l as EnvelopeSimple,\n o as EnvelopeSimpleIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,44H32A12,12,0,0,0,20,56V192a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A12,12,0,0,0,224,44ZM193.15,68,128,127.72,62.85,68ZM44,188V83.28l75.89,69.57a12,12,0,0,0,16.22,0L212,83.28V188Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,56l-96,88L32,56Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM203.43,64,128,133.15,52.57,64ZM216,192H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48Zm-8,144H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,50H32a6,6,0,0,0-6,6V192a14,14,0,0,0,14,14H216a14,14,0,0,0,14-14V56A6,6,0,0,0,224,50ZM208.58,62,128,135.86,47.42,62ZM216,194H40a2,2,0,0,1-2-2V69.64l86,78.78a6,6,0,0,0,8.1,0L218,69.64V192A2,2,0,0,1,216,194Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM203.43,64,128,133.15,52.57,64ZM216,192H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,52H32a4,4,0,0,0-4,4V192a12,12,0,0,0,12,12H216a12,12,0,0,0,12-12V56A4,4,0,0,0,224,52Zm-10.28,8L128,138.57,42.28,60ZM216,196H40a4,4,0,0,1-4-4V65.09L125.3,147a4,4,0,0,0,5.4,0L220,65.09V192A4,4,0,0,1,216,196Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport i from \"../defs/File.es.js\";\nconst o = e.forwardRef((r, t) => /* @__PURE__ */ e.createElement(a, { ref: t, ...r, weights: i }));\no.displayName = \"FileIcon\";\nconst c = o;\nexport {\n c as File,\n o as FileIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208,88H152V32Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM152,88V44l44,44Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M212.24,83.76l-56-56A6,6,0,0,0,152,26H56A14,14,0,0,0,42,40V216a14,14,0,0,0,14,14H200a14,14,0,0,0,14-14V88A6,6,0,0,0,212.24,83.76ZM158,46.48,193.52,82H158ZM200,218H56a2,2,0,0,1-2-2V40a2,2,0,0,1,2-2h90V88a6,6,0,0,0,6,6h50V216A2,2,0,0,1,200,218Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M210.83,85.17l-56-56A4,4,0,0,0,152,28H56A12,12,0,0,0,44,40V216a12,12,0,0,0,12,12H200a12,12,0,0,0,12-12V88A4,4,0,0,0,210.83,85.17ZM156,41.65,198.34,84H156ZM200,220H56a4,4,0,0,1-4-4V40a4,4,0,0,1,4-4h92V88a4,4,0,0,0,4,4h52V216A4,4,0,0,1,200,220Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport m from \"../lib/SSRBase.es.js\";\nimport t from \"../defs/ImageSquare.es.js\";\nconst a = e.forwardRef((r, o) => /* @__PURE__ */ e.createElement(m, { ref: o, ...r, weights: t }));\na.displayName = \"ImageSquareIcon\";\nconst I = a;\nexport {\n I as ImageSquare,\n a as ImageSquareIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,28H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V48A20,20,0,0,0,208,28Zm-4,24v63.72L186.14,97.86a20,20,0,0,0-28.28,0L52,203.72V52ZM85.66,204,172,117.66l32,32V204ZM76,96a20,20,0,1,1,20,20A20,20,0,0,1,76,96Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M208,40H48a8,8,0,0,0-8,8V208a8,8,0,0,0,8,8h8.69L166.34,106.34a8,8,0,0,1,11.32,0L216,144.69V48A8,8,0,0,0,208,40ZM96,112a16,16,0,1,1,16-16A16,16,0,0,1,96,112Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM48,48H208v77.38l-24.69-24.7a16,16,0,0,0-22.62,0L53.37,208H48ZM208,208H76l96-96,36,36v60ZM96,120A24,24,0,1,0,72,96,24,24,0,0,0,96,120Zm0-32a8,8,0,1,1-8,8A8,8,0,0,1,96,88Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM48,48H208v77.38l-24.69-24.7a16,16,0,0,0-22.62,0L53.37,208H48ZM80,96a16,16,0,1,1,16,16A16,16,0,0,1,80,96Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,34H48A14,14,0,0,0,34,48V208a14,14,0,0,0,14,14H208a14,14,0,0,0,14-14V48A14,14,0,0,0,208,34ZM46,208V48a2,2,0,0,1,2-2H208a2,2,0,0,1,2,2v82.2l-28.1-28.1a14,14,0,0,0-19.8,0L54.2,210H48A2,2,0,0,1,46,208Zm162,2H71.17l99.41-99.41a2,2,0,0,1,2.83,0L210,147.17V208A2,2,0,0,1,208,210ZM96,118A22,22,0,1,0,74,96,22,22,0,0,0,96,118Zm0-32A10,10,0,1,1,86,96,10,10,0,0,1,96,86Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM48,48H208v77.38l-24.69-24.7a16,16,0,0,0-22.62,0L53.37,208H48ZM208,208H76l96-96,36,36v60ZM96,120A24,24,0,1,0,72,96,24,24,0,0,0,96,120Zm0-32a8,8,0,1,1-8,8A8,8,0,0,1,96,88Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,36H48A12,12,0,0,0,36,48V208a12,12,0,0,0,12,12H208a12,12,0,0,0,12-12V48A12,12,0,0,0,208,36ZM44,208V48a4,4,0,0,1,4-4H208a4,4,0,0,1,4,4v87l-31.51-31.52a12,12,0,0,0-17,0L55,212H48A4,4,0,0,1,44,208Zm164,4H66.34L169.17,109.17a4,4,0,0,1,5.66,0L212,146.34V208A4,4,0,0,1,208,212ZM96,116A20,20,0,1,0,76,96,20,20,0,0,0,96,116Zm0-32A12,12,0,1,1,84,96,12,12,0,0,1,96,84Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as t from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport i from \"../defs/Lightbulb.es.js\";\nconst o = t.forwardRef((e, r) => /* @__PURE__ */ t.createElement(a, { ref: r, ...e, weights: i }));\no.displayName = \"LightbulbIcon\";\nconst b = o;\nexport {\n b as Lightbulb,\n o as LightbulbIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M180,232a12,12,0,0,1-12,12H88a12,12,0,0,1,0-24h80A12,12,0,0,1,180,232Zm40-128a91.51,91.51,0,0,1-35.17,72.35A12.26,12.26,0,0,0,180,186v2a20,20,0,0,1-20,20H96a20,20,0,0,1-20-20v-2a12,12,0,0,0-4.7-9.51A91.57,91.57,0,0,1,36,104.52C35.73,54.69,76,13.2,125.79,12A92,92,0,0,1,220,104Zm-24,0a68,68,0,0,0-69.65-68C89.56,36.88,59.8,67.55,60,104.38a67.71,67.71,0,0,0,26.1,53.19A35.87,35.87,0,0,1,100,184h56.1A36.13,36.13,0,0,1,170,157.49,67.68,67.68,0,0,0,196,104Zm-20.07-5.32a48.5,48.5,0,0,0-31.91-40,12,12,0,0,0-8,22.62,24.31,24.31,0,0,1,16.09,20,12,12,0,0,0,23.86-2.64Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M208,104a79.86,79.86,0,0,1-30.59,62.92A24.29,24.29,0,0,0,168,186v6a8,8,0,0,1-8,8H96a8,8,0,0,1-8-8v-6a24.11,24.11,0,0,0-9.3-19A79.87,79.87,0,0,1,48,104.45C47.76,61.09,82.72,25,126.07,24A80,80,0,0,1,208,104Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-16,0a72,72,0,0,0-73.74-72c-39,.92-70.47,33.39-70.26,72.39a71.65,71.65,0,0,0,27.64,56.3A32,32,0,0,1,96,186v6h64v-6a32.15,32.15,0,0,1,12.47-25.35A71.65,71.65,0,0,0,200,104Zm-16.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-32.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M174,232a6,6,0,0,1-6,6H88a6,6,0,0,1,0-12h80A6,6,0,0,1,174,232Zm40-128a85.56,85.56,0,0,1-32.88,67.64A18.23,18.23,0,0,0,174,186v6a14,14,0,0,1-14,14H96a14,14,0,0,1-14-14v-6a18,18,0,0,0-7-14.23h0a85.59,85.59,0,0,1-33-67.24C41.74,57.91,79.39,19.12,125.93,18A86,86,0,0,1,214,104Zm-12,0a74,74,0,0,0-75.79-74C86.17,31,53.78,64.34,54,104.42a73.67,73.67,0,0,0,28.4,57.87A29.92,29.92,0,0,1,94,186v6a2,2,0,0,0,2,2h64a2,2,0,0,0,2-2v-6a30.18,30.18,0,0,1,11.7-23.78A73.59,73.59,0,0,0,202,104Zm-20.08-9A55.58,55.58,0,0,0,137,50.08a6,6,0,1,0-2,11.84C152.38,64.84,167.13,79.6,170.08,97a6,6,0,0,0,5.91,5,6.87,6.87,0,0,0,1-.08A6,6,0,0,0,181.92,95Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-16,0a72,72,0,0,0-73.74-72c-39,.92-70.47,33.39-70.26,72.39a71.65,71.65,0,0,0,27.64,56.3A32,32,0,0,1,96,186v6h64v-6a32.15,32.15,0,0,1,12.47-25.35A71.65,71.65,0,0,0,200,104Zm-16.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M172,232a4,4,0,0,1-4,4H88a4,4,0,0,1,0-8h80A4,4,0,0,1,172,232Zm40-128a83.59,83.59,0,0,1-32.11,66.06A20.2,20.2,0,0,0,172,186v6a12,12,0,0,1-12,12H96a12,12,0,0,1-12-12v-6a20,20,0,0,0-7.76-15.81A83.58,83.58,0,0,1,44,104.47C43.75,59,80.52,21.09,126,20a84,84,0,0,1,86,84Zm-8,0a76,76,0,0,0-77.83-76C85,29,51.77,63.27,52,104.43a75.62,75.62,0,0,0,29.17,59.43A28,28,0,0,1,92,186v6a4,4,0,0,0,4,4h64a4,4,0,0,0,4-4v-6a28.14,28.14,0,0,1,10.94-22.2A75.62,75.62,0,0,0,204,104ZM136.66,52.06a4,4,0,0,0-1.32,7.88C153.53,63,169,78.45,172.06,96.67A4,4,0,0,0,176,100a3.88,3.88,0,0,0,.67-.06,4,4,0,0,0,3.27-4.61A53.51,53.51,0,0,0,136.66,52.06Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport c from \"../defs/LockSimple.es.js\";\nconst e = o.forwardRef((m, r) => /* @__PURE__ */ o.createElement(t, { ref: r, ...m, weights: c }));\ne.displayName = \"LockSimpleIcon\";\nconst p = e;\nexport {\n p as LockSimple,\n e as LockSimpleIcon\n};\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,76H180V56A52,52,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76ZM100,56a28,28,0,0,1,56,0V76H100ZM204,204H52V100H204Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M216,96V208a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V96a8,8,0,0,1,8-8H208A8,8,0,0,1,216,96Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,82H174V56a46,46,0,0,0-92,0V82H48A14,14,0,0,0,34,96V208a14,14,0,0,0,14,14H208a14,14,0,0,0,14-14V96A14,14,0,0,0,208,82ZM94,56a34,34,0,0,1,68,0V82H94ZM210,208a2,2,0,0,1-2,2H48a2,2,0,0,1-2-2V96a2,2,0,0,1,2-2H208a2,2,0,0,1,2,2Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,84H172V56a44,44,0,0,0-88,0V84H48A12,12,0,0,0,36,96V208a12,12,0,0,0,12,12H208a12,12,0,0,0,12-12V96A12,12,0,0,0,208,84ZM92,56a36,36,0,0,1,72,0V84H92ZM212,208a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V96a4,4,0,0,1,4-4H208a4,4,0,0,1,4,4Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Play.es.js\";\nconst a = o.forwardRef((e, r) => /* @__PURE__ */ o.createElement(t, { ref: r, ...e, weights: m }));\na.displayName = \"PlayIcon\";\nconst f = a;\nexport {\n f as Play,\n a as PlayIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M234.49,111.07,90.41,22.94A20,20,0,0,0,60,39.87V216.13a20,20,0,0,0,30.41,16.93l144.08-88.13a19.82,19.82,0,0,0,0-33.86ZM84,208.85V47.15L216.16,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M228.23,134.69,84.15,222.81A8,8,0,0,1,72,216.12V39.88a8,8,0,0,1,12.15-6.69l144.08,88.12A7.82,7.82,0,0,1,228.23,134.69Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M231.36,116.19,87.28,28.06a14,14,0,0,0-14.18-.27A13.69,13.69,0,0,0,66,39.87V216.13a13.69,13.69,0,0,0,7.1,12.08,14,14,0,0,0,14.18-.27l144.08-88.13a13.82,13.82,0,0,0,0-23.62Zm-6.26,13.38L81,217.7a2,2,0,0,1-2.06,0,1.78,1.78,0,0,1-1-1.61V39.87a1.78,1.78,0,0,1,1-1.61A2.06,2.06,0,0,1,80,38a2,2,0,0,1,1,.31L225.1,126.43a1.82,1.82,0,0,1,0,3.14Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M230.32,117.9,86.24,29.79a11.91,11.91,0,0,0-12.17-.23A11.71,11.71,0,0,0,68,39.89V216.11a11.71,11.71,0,0,0,6.07,10.33,11.91,11.91,0,0,0,12.17-.23L230.32,138.1a11.82,11.82,0,0,0,0-20.2Zm-4.18,13.37L82.06,219.39a4,4,0,0,1-4.07.07,3.77,3.77,0,0,1-2-3.35V39.89a3.77,3.77,0,0,1,2-3.35,4,4,0,0,1,4.07.07l144.08,88.12a3.8,3.8,0,0,1,0,6.54Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport a from \"../defs/Plus.es.js\";\nconst e = o.forwardRef((r, s) => /* @__PURE__ */ o.createElement(t, { ref: s, ...r, weights: a }));\ne.displayName = \"PlusIcon\";\nconst f = e;\nexport {\n f as Plus,\n e as PlusIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M216,56V200a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V56A16,16,0,0,1,56,40H200A16,16,0,0,1,216,56Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM184,136H136v48a8,8,0,0,1-16,0V136H72a8,8,0,0,1,0-16h48V72a8,8,0,0,1,16,0v48h48a8,8,0,0,1,0,16Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M222,128a6,6,0,0,1-6,6H134v82a6,6,0,0,1-12,0V134H40a6,6,0,0,1,0-12h82V40a6,6,0,0,1,12,0v82h82A6,6,0,0,1,222,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M220,128a4,4,0,0,1-4,4H132v84a4,4,0,0,1-8,0V132H40a4,4,0,0,1,0-8h84V40a4,4,0,0,1,8,0v84h84A4,4,0,0,1,220,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as e from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Sparkle.es.js\";\nconst r = e.forwardRef((o, a) => /* @__PURE__ */ e.createElement(t, { ref: a, ...o, weights: m }));\nr.displayName = \"SparkleIcon\";\nconst c = r;\nexport {\n c as Sparkle,\n r as SparkleIcon\n};\n","import * as a from \"react\";\nconst l = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M199,125.31l-49.88-18.39L130.69,57a19.92,19.92,0,0,0-37.38,0L74.92,106.92,25,125.31a19.92,19.92,0,0,0,0,37.38l49.88,18.39L93.31,231a19.92,19.92,0,0,0,37.38,0l18.39-49.88L199,162.69a19.92,19.92,0,0,0,0-37.38Zm-63.38,35.16a12,12,0,0,0-7.11,7.11L112,212.28l-16.47-44.7a12,12,0,0,0-7.11-7.11L43.72,144l44.7-16.47a12,12,0,0,0,7.11-7.11L112,75.72l16.47,44.7a12,12,0,0,0,7.11,7.11L180.28,144ZM140,40a12,12,0,0,1,12-12h12V16a12,12,0,0,1,24,0V28h12a12,12,0,0,1,0,24H188V64a12,12,0,0,1-24,0V52H152A12,12,0,0,1,140,40ZM252,88a12,12,0,0,1-12,12h-4v4a12,12,0,0,1-24,0v-4h-4a12,12,0,0,1,0-24h4V72a12,12,0,0,1,24,0v4h4A12,12,0,0,1,252,88Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M194.82,151.43l-55.09,20.3-20.3,55.09a7.92,7.92,0,0,1-14.86,0l-20.3-55.09-55.09-20.3a7.92,7.92,0,0,1,0-14.86l55.09-20.3,20.3-55.09a7.92,7.92,0,0,1,14.86,0l20.3,55.09,55.09,20.3A7.92,7.92,0,0,1,194.82,151.43Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M197.58,129.06,146,110l-19-51.62a15.92,15.92,0,0,0-29.88,0L78,110l-51.62,19a15.92,15.92,0,0,0,0,29.88L78,178l19,51.62a15.92,15.92,0,0,0,29.88,0L146,178l51.62-19a15.92,15.92,0,0,0,0-29.88ZM137,164.22a8,8,0,0,0-4.74,4.74L112,223.85,91.78,169A8,8,0,0,0,87,164.22L32.15,144,87,123.78A8,8,0,0,0,91.78,119L112,64.15,132.22,119a8,8,0,0,0,4.74,4.74L191.85,144ZM144,40a8,8,0,0,1,8-8h16V16a8,8,0,0,1,16,0V32h16a8,8,0,0,1,0,16H184V64a8,8,0,0,1-16,0V48H152A8,8,0,0,1,144,40ZM248,88a8,8,0,0,1-8,8h-8v8a8,8,0,0,1-16,0V96h-8a8,8,0,0,1,0-16h8V72a8,8,0,0,1,16,0v8h8A8,8,0,0,1,248,88Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M208,144a15.78,15.78,0,0,1-10.42,14.94L146,178l-19,51.62a15.92,15.92,0,0,1-29.88,0L78,178l-51.62-19a15.92,15.92,0,0,1,0-29.88L78,110l19-51.62a15.92,15.92,0,0,1,29.88,0L146,110l51.62,19A15.78,15.78,0,0,1,208,144ZM152,48h16V64a8,8,0,0,0,16,0V48h16a8,8,0,0,0,0-16H184V16a8,8,0,0,0-16,0V32H152a8,8,0,0,0,0,16Zm88,32h-8V72a8,8,0,0,0-16,0v8h-8a8,8,0,0,0,0,16h8v8a8,8,0,0,0,16,0V96h8a8,8,0,0,0,0-16Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M196.89,130.94,144.4,111.6,125.06,59.11a13.92,13.92,0,0,0-26.12,0L79.6,111.6,27.11,130.94a13.92,13.92,0,0,0,0,26.12L79.6,176.4l19.34,52.49a13.92,13.92,0,0,0,26.12,0L144.4,176.4l52.49-19.34a13.92,13.92,0,0,0,0-26.12Zm-4.15,14.86-55.08,20.3a6,6,0,0,0-3.56,3.56l-20.3,55.08a1.92,1.92,0,0,1-3.6,0L89.9,169.66a6,6,0,0,0-3.56-3.56L31.26,145.8a1.92,1.92,0,0,1,0-3.6l55.08-20.3a6,6,0,0,0,3.56-3.56l20.3-55.08a1.92,1.92,0,0,1,3.6,0l20.3,55.08a6,6,0,0,0,3.56,3.56l55.08,20.3a1.92,1.92,0,0,1,0,3.6ZM146,40a6,6,0,0,1,6-6h18V16a6,6,0,0,1,12,0V34h18a6,6,0,0,1,0,12H182V64a6,6,0,0,1-12,0V46H152A6,6,0,0,1,146,40ZM246,88a6,6,0,0,1-6,6H230v10a6,6,0,0,1-12,0V94H208a6,6,0,0,1,0-12h10V72a6,6,0,0,1,12,0V82h10A6,6,0,0,1,246,88Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M197.58,129.06,146,110l-19-51.62a15.92,15.92,0,0,0-29.88,0L78,110l-51.62,19a15.92,15.92,0,0,0,0,29.88L78,178l19,51.62a15.92,15.92,0,0,0,29.88,0L146,178l51.62-19a15.92,15.92,0,0,0,0-29.88ZM137,164.22a8,8,0,0,0-4.74,4.74L112,223.85,91.78,169A8,8,0,0,0,87,164.22L32.15,144,87,123.78A8,8,0,0,0,91.78,119L112,64.15,132.22,119a8,8,0,0,0,4.74,4.74L191.85,144ZM144,40a8,8,0,0,1,8-8h16V16a8,8,0,0,1,16,0V32h16a8,8,0,0,1,0,16H184V64a8,8,0,0,1-16,0V48H152A8,8,0,0,1,144,40ZM248,88a8,8,0,0,1-8,8h-8v8a8,8,0,0,1-16,0V96h-8a8,8,0,0,1,0-16h8V72a8,8,0,0,1,16,0v8h8A8,8,0,0,1,248,88Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M196.2,132.81l-53.36-19.65L123.19,59.8a11.93,11.93,0,0,0-22.38,0L81.16,113.16,27.8,132.81a11.93,11.93,0,0,0,0,22.38l53.36,19.65,19.65,53.36a11.93,11.93,0,0,0,22.38,0l19.65-53.36,53.36-19.65a11.93,11.93,0,0,0,0-22.38Zm-2.77,14.87L138.35,168a4,4,0,0,0-2.37,2.37l-20.3,55.08a3.92,3.92,0,0,1-7.36,0L88,170.35A4,4,0,0,0,85.65,168l-55.08-20.3a3.92,3.92,0,0,1,0-7.36L85.65,120A4,4,0,0,0,88,117.65l20.3-55.08a3.92,3.92,0,0,1,7.36,0L136,117.65a4,4,0,0,0,2.37,2.37l55.08,20.3a3.92,3.92,0,0,1,0,7.36ZM148,40a4,4,0,0,1,4-4h20V16a4,4,0,0,1,8,0V36h20a4,4,0,0,1,0,8H180V64a4,4,0,0,1-8,0V44H152A4,4,0,0,1,148,40Zm96,48a4,4,0,0,1-4,4H228v12a4,4,0,0,1-8,0V92H208a4,4,0,0,1,0-8h12V72a4,4,0,0,1,8,0V84h12A4,4,0,0,1,244,88Z\" }))\n ]\n]);\nexport {\n l as default\n};\n","import * as r from \"react\";\nimport e from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/Star.es.js\";\nconst t = r.forwardRef((o, a) => /* @__PURE__ */ r.createElement(e, { ref: a, ...o, weights: m }));\nt.displayName = \"StarIcon\";\nconst f = t;\nexport {\n f as Star,\n t as StarIcon\n};\n","import * as a from \"react\";\nconst l = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M243,96a20.33,20.33,0,0,0-17.74-14l-56.59-4.57L146.83,24.62a20.36,20.36,0,0,0-37.66,0L87.35,77.44,30.76,82A20.45,20.45,0,0,0,19.1,117.88l43.18,37.24-13.2,55.7A20.37,20.37,0,0,0,79.57,233L128,203.19,176.43,233a20.39,20.39,0,0,0,30.49-22.15l-13.2-55.7,43.18-37.24A20.43,20.43,0,0,0,243,96ZM172.53,141.7a12,12,0,0,0-3.84,11.86L181.58,208l-47.29-29.08a12,12,0,0,0-12.58,0L74.42,208l12.89-54.4a12,12,0,0,0-3.84-11.86L41.2,105.24l55.4-4.47a12,12,0,0,0,10.13-7.38L128,41.89l21.27,51.5a12,12,0,0,0,10.13,7.38l55.4,4.47Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\n \"path\",\n {\n d: \"M229.06,108.79l-48.7,42,14.88,62.79a8.4,8.4,0,0,1-12.52,9.17L128,189.09,73.28,222.74a8.4,8.4,0,0,1-12.52-9.17l14.88-62.79-48.7-42A8.46,8.46,0,0,1,31.73,94L95.64,88.8l24.62-59.6a8.36,8.36,0,0,1,15.48,0l24.62,59.6L224.27,94A8.46,8.46,0,0,1,229.06,108.79Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ a.createElement(\"path\", { d: \"M239.18,97.26A16.38,16.38,0,0,0,224.92,86l-59-4.76L143.14,26.15a16.36,16.36,0,0,0-30.27,0L90.11,81.23,31.08,86a16.46,16.46,0,0,0-9.37,28.86l45,38.83L53,211.75a16.38,16.38,0,0,0,24.5,17.82L128,198.49l50.53,31.08A16.4,16.4,0,0,0,203,211.75l-13.76-58.07,45-38.83A16.43,16.43,0,0,0,239.18,97.26Zm-15.34,5.47-48.7,42a8,8,0,0,0-2.56,7.91l14.88,62.8a.37.37,0,0,1-.17.48c-.18.14-.23.11-.38,0l-54.72-33.65a8,8,0,0,0-8.38,0L69.09,215.94c-.15.09-.19.12-.38,0a.37.37,0,0,1-.17-.48l14.88-62.8a8,8,0,0,0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16A8,8,0,0,0,103,91.86l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153,91.86a8,8,0,0,0,6.75,4.92l63.92,5.16c.15,0,.24,0,.33.29S224,102.63,223.84,102.73Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M234.29,114.85l-45,38.83L203,211.75a16.4,16.4,0,0,1-24.5,17.82L128,198.49,77.47,229.57A16.4,16.4,0,0,1,53,211.75l13.76-58.07-45-38.83A16.46,16.46,0,0,1,31.08,86l59-4.76,22.76-55.08a16.36,16.36,0,0,1,30.27,0l22.75,55.08,59,4.76a16.46,16.46,0,0,1,9.37,28.86Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M237.28,97.87A14.18,14.18,0,0,0,224.76,88l-60.25-4.87-23.22-56.2a14.37,14.37,0,0,0-26.58,0L91.49,83.11,31.24,88a14.18,14.18,0,0,0-12.52,9.89A14.43,14.43,0,0,0,23,113.32L69,152.93l-14,59.25a14.4,14.4,0,0,0,5.59,15,14.1,14.1,0,0,0,15.91.6L128,196.12l51.58,31.71a14.1,14.1,0,0,0,15.91-.6,14.4,14.4,0,0,0,5.59-15l-14-59.25L233,113.32A14.43,14.43,0,0,0,237.28,97.87Zm-12.14,6.37-48.69,42a6,6,0,0,0-1.92,5.92l14.88,62.79a2.35,2.35,0,0,1-.95,2.57,2.24,2.24,0,0,1-2.6.1L131.14,184a6,6,0,0,0-6.28,0L70.14,217.61a2.24,2.24,0,0,1-2.6-.1,2.35,2.35,0,0,1-1-2.57l14.88-62.79a6,6,0,0,0-1.92-5.92l-48.69-42a2.37,2.37,0,0,1-.73-2.65,2.28,2.28,0,0,1,2.07-1.65l63.92-5.16a6,6,0,0,0,5.06-3.69l24.63-59.6a2.35,2.35,0,0,1,4.38,0l24.63,59.6a6,6,0,0,0,5.06,3.69l63.92,5.16a2.28,2.28,0,0,1,2.07,1.65A2.37,2.37,0,0,1,225.14,104.24Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M239.18,97.26A16.38,16.38,0,0,0,224.92,86l-59-4.76L143.14,26.15a16.36,16.36,0,0,0-30.27,0L90.11,81.23,31.08,86a16.46,16.46,0,0,0-9.37,28.86l45,38.83L53,211.75a16.38,16.38,0,0,0,24.5,17.82L128,198.49l50.53,31.08A16.4,16.4,0,0,0,203,211.75l-13.76-58.07,45-38.83A16.43,16.43,0,0,0,239.18,97.26Zm-15.34,5.47-48.7,42a8,8,0,0,0-2.56,7.91l14.88,62.8a.37.37,0,0,1-.17.48c-.18.14-.23.11-.38,0l-54.72-33.65a8,8,0,0,0-8.38,0L69.09,215.94c-.15.09-.19.12-.38,0a.37.37,0,0,1-.17-.48l14.88-62.8a8,8,0,0,0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16A8,8,0,0,0,103,91.86l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153,91.86a8,8,0,0,0,6.75,4.92l63.92,5.16c.15,0,.24,0,.33.29S224,102.63,223.84,102.73Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M235.36,98.49A12.21,12.21,0,0,0,224.59,90l-61.47-5L139.44,27.67a12.37,12.37,0,0,0-22.88,0L92.88,85,31.41,90a12.45,12.45,0,0,0-7.07,21.84l46.85,40.41L56.87,212.64a12.35,12.35,0,0,0,18.51,13.49L128,193.77l52.62,32.36a12.12,12.12,0,0,0,13.69-.51,12.28,12.28,0,0,0,4.82-13l-14.32-60.42,46.85-40.41A12.29,12.29,0,0,0,235.36,98.49Zm-8.93,7.26-48.68,42a4,4,0,0,0-1.28,3.95l14.87,62.79a4.37,4.37,0,0,1-1.72,4.65,4.24,4.24,0,0,1-4.81.18L130.1,185.67a4,4,0,0,0-4.2,0L71.19,219.32a4.24,4.24,0,0,1-4.81-.18,4.37,4.37,0,0,1-1.72-4.65L79.53,151.7a4,4,0,0,0-1.28-3.95l-48.68-42A4.37,4.37,0,0,1,28.25,101a4.31,4.31,0,0,1,3.81-3L96,92.79a4,4,0,0,0,3.38-2.46L124,30.73a4.35,4.35,0,0,1,8.08,0l24.62,59.6A4,4,0,0,0,160,92.79l63.9,5.15a4.31,4.31,0,0,1,3.81,3A4.37,4.37,0,0,1,226.43,105.75Z\" }))\n ]\n]);\nexport {\n l as default\n};\n","import * as e from \"react\";\nimport t from \"../lib/SSRBase.es.js\";\nimport c from \"../defs/UserCircle.es.js\";\nconst r = e.forwardRef((o, s) => /* @__PURE__ */ e.createElement(t, { ref: s, ...o, weights: c }));\nr.displayName = \"UserCircleIcon\";\nconst m = r;\nexport {\n m as UserCircle,\n r as UserCircleIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20ZM79.57,196.57a60,60,0,0,1,96.86,0,83.72,83.72,0,0,1-96.86,0ZM100,120a28,28,0,1,1,28,28A28,28,0,0,1,100,120ZM194,179.94a83.48,83.48,0,0,0-29-23.42,52,52,0,1,0-74,0,83.48,83.48,0,0,0-29,23.42,84,84,0,1,1,131.9,0Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M224,128a95.76,95.76,0,0,1-31.8,71.37A72,72,0,0,0,128,160a40,40,0,1,0-40-40,40,40,0,0,0,40,40,72,72,0,0,0-64.2,39.37h0A96,96,0,1,1,224,128Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM74.08,197.5a64,64,0,0,1,107.84,0,87.83,87.83,0,0,1-107.84,0ZM96,120a32,32,0,1,1,32,32A32,32,0,0,1,96,120Zm97.76,66.41a79.66,79.66,0,0,0-36.06-28.75,48,48,0,1,0-59.4,0,79.66,79.66,0,0,0-36.06,28.75,88,88,0,1,1,131.52,0Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M172,120a44,44,0,1,1-44-44A44.05,44.05,0,0,1,172,120Zm60,8A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88.09,88.09,0,0,0-91.47-87.93C77.43,41.89,39.87,81.12,40,128.25a87.65,87.65,0,0,0,22.24,58.16A79.71,79.71,0,0,1,84,165.1a4,4,0,0,1,4.83.32,59.83,59.83,0,0,0,78.28,0,4,4,0,0,1,4.83-.32,79.71,79.71,0,0,1,21.79,21.31A87.62,87.62,0,0,0,216,128Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26ZM71.44,198a66,66,0,0,1,113.12,0,89.8,89.8,0,0,1-113.12,0ZM94,120a34,34,0,1,1,34,34A34,34,0,0,1,94,120Zm99.51,69.64a77.53,77.53,0,0,0-40-31.38,46,46,0,1,0-51,0,77.53,77.53,0,0,0-40,31.38,90,90,0,1,1,131,0Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM74.08,197.5a64,64,0,0,1,107.84,0,87.83,87.83,0,0,1-107.84,0ZM96,120a32,32,0,1,1,32,32A32,32,0,0,1,96,120Zm97.76,66.41a79.66,79.66,0,0,0-36.06-28.75,48,48,0,1,0-59.4,0,79.66,79.66,0,0,0-36.06,28.75,88,88,0,1,1,131.52,0Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,28A100,100,0,1,0,228,128,100.11,100.11,0,0,0,128,28ZM68.87,198.42a68,68,0,0,1,118.26,0,91.8,91.8,0,0,1-118.26,0Zm124.3-5.55a75.61,75.61,0,0,0-44.51-34,44,44,0,1,0-41.32,0,75.61,75.61,0,0,0-44.51,34,92,92,0,1,1,130.34,0ZM128,156a36,36,0,1,1,36-36A36,36,0,0,1,128,156Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as r from \"react\";\nimport i from \"../lib/SSRBase.es.js\";\nimport n from \"../defs/WarningCircle.es.js\";\nconst e = r.forwardRef((o, a) => /* @__PURE__ */ r.createElement(i, { ref: a, ...o, weights: n }));\ne.displayName = \"WarningCircleIcon\";\nconst m = e;\nexport {\n m as WarningCircle,\n e as WarningCircleIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm-12-80V80a12,12,0,0,1,24,0v52a12,12,0,0,1-24,0Zm28,40a16,16,0,1,1-16-16A16,16,0,0,1,144,172Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-8,56a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm8,104a12,12,0,1,1,12-12A12,12,0,0,1,128,184Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26Zm0,192a90,90,0,1,1,90-90A90.1,90.1,0,0,1,128,218Zm-6-82V80a6,6,0,0,1,12,0v56a6,6,0,0,1-12,0Zm16,36a10,10,0,1,1-10-10A10,10,0,0,1,138,172Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M128,28A100,100,0,1,0,228,128,100.11,100.11,0,0,0,128,28Zm0,192a92,92,0,1,1,92-92A92.1,92.1,0,0,1,128,220Zm-4-84V80a4,4,0,0,1,8,0v56a4,4,0,0,1-8,0Zm12,36a8,8,0,1,1-8-8A8,8,0,0,1,136,172Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import * as o from \"react\";\nimport a from \"../lib/SSRBase.es.js\";\nimport m from \"../defs/X.es.js\";\nconst e = o.forwardRef((r, t) => /* @__PURE__ */ o.createElement(a, { ref: t, ...r, weights: m }));\ne.displayName = \"XIcon\";\nconst f = e;\nexport {\n f as X,\n e as XIcon\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208.49,191.51a12,12,0,0,1-17,17L128,145,64.49,208.49a12,12,0,0,1-17-17L111,128,47.51,64.49a12,12,0,0,1,17-17L128,111l63.51-63.52a12,12,0,0,1,17,17L145,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\n \"path\",\n {\n d: \"M216,56V200a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V56A16,16,0,0,1,56,40H200A16,16,0,0,1,216,56Z\",\n opacity: \"0.2\"\n }\n ), /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM181.66,170.34a8,8,0,0,1-11.32,11.32L128,139.31,85.66,181.66a8,8,0,0,1-11.32-11.32L116.69,128,74.34,85.66A8,8,0,0,1,85.66,74.34L128,116.69l42.34-42.35a8,8,0,0,1,11.32,11.32L139.31,128Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M204.24,195.76a6,6,0,1,1-8.48,8.48L128,136.49,60.24,204.24a6,6,0,0,1-8.48-8.48L119.51,128,51.76,60.24a6,6,0,0,1,8.48-8.48L128,119.51l67.76-67.75a6,6,0,0,1,8.48,8.48L136.49,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M202.83,197.17a4,4,0,0,1-5.66,5.66L128,133.66,58.83,202.83a4,4,0,0,1-5.66-5.66L122.34,128,53.17,58.83a4,4,0,0,1,5.66-5.66L128,122.34l69.17-69.17a4,4,0,1,1,5.66,5.66L133.66,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import type { Icon, IconProps, IconWeight } from \"@phosphor-icons/react\";\nimport {\n AlarmIcon,\n ArchiveIcon,\n ArrowBendUpLeftIcon,\n ArrowDownIcon,\n ArrowElbowDownLeftIcon,\n ArrowUpIcon,\n ArrowsClockwiseIcon,\n ArrowSquareOutIcon,\n ArrowsInIcon,\n ArrowsOutIcon,\n BookOpenTextIcon,\n BugIcon,\n BuildingsIcon,\n CopyIcon,\n CalendarBlankIcon,\n CaretDownIcon,\n CaretLeftIcon,\n CaretRightIcon,\n CellSignalHighIcon,\n CellSignalLowIcon,\n CellSignalMediumIcon,\n ChartBarIcon,\n ChatCircleDotsIcon,\n ChatsCircleIcon,\n CheckIcon,\n CheckCircleIcon,\n CircleDashedIcon,\n CircleHalfIcon,\n CircleIcon,\n ClockIcon,\n ClockCounterClockwiseIcon,\n CodeIcon,\n CodeBlockIcon,\n CreditCardIcon,\n DeviceMobileIcon,\n DotsThreeIcon,\n EnvelopeSimpleIcon,\n FileIcon,\n FolderIcon,\n FolderOpenIcon,\n FolderPlusIcon,\n FunnelIcon,\n GearSixIcon,\n GitCommitIcon,\n GlobeSimpleIcon,\n ImageSquareIcon,\n KanbanIcon,\n KeyIcon,\n LightbulbIcon,\n LinkSimpleIcon,\n ListIcon,\n ListBulletsIcon,\n ListChecksIcon,\n ListNumbersIcon,\n LockSimpleIcon,\n MagicWandIcon,\n MagnifyingGlassIcon,\n MapPinIcon,\n MegaphoneIcon,\n MonitorIcon,\n MoonIcon,\n NoteIcon,\n NotionLogoIcon,\n PaperclipIcon,\n PaperPlaneRightIcon,\n PencilSimpleIcon,\n PlayIcon,\n PlugsConnectedIcon,\n PlusIcon,\n QuotesIcon,\n RobotIcon,\n ShieldCheckIcon,\n ShieldWarningIcon,\n SidebarSimpleIcon,\n SignOutIcon,\n SlidersHorizontalIcon,\n SparkleIcon,\n SquareIcon,\n SquaresFourIcon,\n StarIcon,\n SunIcon,\n TableIcon,\n TagIcon,\n TextBIcon,\n TextItalicIcon,\n TextStrikethroughIcon,\n TimerIcon,\n TrashIcon,\n TrayIcon,\n TrendUpIcon,\n UploadSimpleIcon,\n UserCircleIcon,\n UsersIcon,\n WarningCircleIcon,\n WrenchIcon,\n XCircleIcon,\n XIcon,\n} from \"@phosphor-icons/react/dist/ssr\";\n\n/**\n * Icons are the filled weight in this app.\n *\n * Phosphor sets weight per icon and the SSR entry does not read IconContext,\n * so the rule is applied here once instead of at every call site. Import from\n * this file rather than from @phosphor-icons/react directly.\n *\n * Props spread after the weight, so a caller can still override it.\n *\n * Every export below is annotated `@__PURE__`. A bundler cannot know that a\n * call at the top level of a module does nothing else, so without the\n * annotation one import from this file drags in all eighty-seven. That is\n * invisible in the app, which loads the whole set anyway, and was a fifth of\n * the published widget: it shipped Notion's logo and a signal meter to answer\n * a support question. Keep the annotation on anything added here.\n */\nfunction icon(Base: Icon, name: string, weight: IconWeight = \"fill\") {\n function Wrapped(props: IconProps) {\n return <Base weight={weight} {...props} />;\n }\n Wrapped.displayName = `${name}Icon`;\n return Wrapped;\n}\n\nexport const Alarm = /* @__PURE__ */ icon(AlarmIcon, \"Alarm\");\nexport const Archive = /* @__PURE__ */ icon(ArchiveIcon, \"Archive\");\nexport const BookOpenText = /* @__PURE__ */ icon(BookOpenTextIcon, \"BookOpenText\");\nexport const Bug = /* @__PURE__ */ icon(BugIcon, \"Bug\");\nexport const Buildings = /* @__PURE__ */ icon(BuildingsIcon, \"Buildings\");\nexport const CalendarBlank = /* @__PURE__ */ icon(CalendarBlankIcon, \"CalendarBlank\");\nexport const ChatCircleDots = /* @__PURE__ */ icon(ChatCircleDotsIcon, \"ChatCircleDots\");\nexport const ChatsCircle = /* @__PURE__ */ icon(ChatsCircleIcon, \"ChatsCircle\");\nexport const CellSignalHigh = /* @__PURE__ */ icon(CellSignalHighIcon, \"CellSignalHigh\");\nexport const CellSignalLow = /* @__PURE__ */ icon(CellSignalLowIcon, \"CellSignalLow\");\nexport const CellSignalMedium = /* @__PURE__ */ icon(CellSignalMediumIcon, \"CellSignalMedium\");\nexport const ChartBar = /* @__PURE__ */ icon(ChartBarIcon, \"ChartBar\");\nexport const CheckCircle = /* @__PURE__ */ icon(CheckCircleIcon, \"CheckCircle\");\n// Half a body by design; the fill weight is the half that shows.\nexport const CircleHalf = /* @__PURE__ */ icon(CircleHalfIcon, \"CircleHalf\");\nexport function CircleThreeQuarter(props: IconProps) {\n return (\n <CircleIcon\n {...props}\n weight=\"fill\"\n style={{\n ...props.style,\n clipPath: \"polygon(50% 0, 100% 0, 100% 100%, 0 100%, 0 50%, 50% 50%)\",\n }}\n />\n );\n}\nexport const Clock = /* @__PURE__ */ icon(ClockIcon, \"Clock\");\nexport const ClockCounterClockwise = /* @__PURE__ */ icon(\n ClockCounterClockwiseIcon,\n \"ClockCounterClockwise\",\n);\nexport const CodeBlock = /* @__PURE__ */ icon(CodeBlockIcon, \"CodeBlock\");\nexport const Copy = /* @__PURE__ */ icon(CopyIcon, \"Copy\");\nexport const CreditCard = /* @__PURE__ */ icon(CreditCardIcon, \"CreditCard\");\nexport const DeviceMobile = /* @__PURE__ */ icon(DeviceMobileIcon, \"DeviceMobile\");\nexport const EnvelopeSimple = /* @__PURE__ */ icon(EnvelopeSimpleIcon, \"EnvelopeSimple\");\nexport const File = /* @__PURE__ */ icon(FileIcon, \"File\");\nexport const Folder = /* @__PURE__ */ icon(FolderIcon, \"Folder\");\nexport const FolderOpen = /* @__PURE__ */ icon(FolderOpenIcon, \"FolderOpen\");\nexport const FolderPlus = /* @__PURE__ */ icon(FolderPlusIcon, \"FolderPlus\");\nexport const Funnel = /* @__PURE__ */ icon(FunnelIcon, \"Funnel\");\nexport const GearSix = /* @__PURE__ */ icon(GearSixIcon, \"GearSix\");\nexport const GlobeSimple = /* @__PURE__ */ icon(GlobeSimpleIcon, \"GlobeSimple\");\n// Linear has no logo in this set, and a board is what the integration is\n// about anyway.\nexport const ImageSquare = /* @__PURE__ */ icon(ImageSquareIcon, \"ImageSquare\");\nexport const Kanban = /* @__PURE__ */ icon(KanbanIcon, \"Kanban\");\nexport const Key = /* @__PURE__ */ icon(KeyIcon, \"Key\");\nexport const Lightbulb = /* @__PURE__ */ icon(LightbulbIcon, \"Lightbulb\");\nexport const LockSimple = /* @__PURE__ */ icon(LockSimpleIcon, \"LockSimple\");\nexport const MagicWand = /* @__PURE__ */ icon(MagicWandIcon, \"MagicWand\");\nexport const MapPin = /* @__PURE__ */ icon(MapPinIcon, \"MapPin\");\nexport const Megaphone = /* @__PURE__ */ icon(MegaphoneIcon, \"Megaphone\");\nexport const Monitor = /* @__PURE__ */ icon(MonitorIcon, \"Monitor\");\nexport const Moon = /* @__PURE__ */ icon(MoonIcon, \"Moon\");\nexport const Note = /* @__PURE__ */ icon(NoteIcon, \"Note\");\nexport const NotionLogo = /* @__PURE__ */ icon(NotionLogoIcon, \"NotionLogo\");\nexport const Paperclip = /* @__PURE__ */ icon(PaperclipIcon, \"Paperclip\");\nexport const PaperPlaneRight = /* @__PURE__ */ icon(PaperPlaneRightIcon, \"PaperPlaneRight\");\nexport const PencilSimple = /* @__PURE__ */ icon(PencilSimpleIcon, \"PencilSimple\");\nexport const Play = /* @__PURE__ */ icon(PlayIcon, \"Play\");\nexport const PlugsConnected = /* @__PURE__ */ icon(PlugsConnectedIcon, \"PlugsConnected\");\nexport const Quotes = /* @__PURE__ */ icon(QuotesIcon, \"Quotes\");\nexport const Reply = /* @__PURE__ */ icon(ArrowBendUpLeftIcon, \"Reply\");\nexport const Robot = /* @__PURE__ */ icon(RobotIcon, \"Robot\");\nexport const ShieldCheck = /* @__PURE__ */ icon(ShieldCheckIcon, \"ShieldCheck\");\nexport const ShieldWarning = /* @__PURE__ */ icon(ShieldWarningIcon, \"ShieldWarning\");\nexport const SidebarSimple = /* @__PURE__ */ icon(SidebarSimpleIcon, \"SidebarSimple\");\nexport const SignOut = /* @__PURE__ */ icon(SignOutIcon, \"SignOut\");\nexport const SlidersHorizontal = /* @__PURE__ */ icon(\n SlidersHorizontalIcon,\n \"SlidersHorizontal\",\n);\nexport const Sparkle = /* @__PURE__ */ icon(SparkleIcon, \"Sparkle\");\n// The stop button's own glyph. Filled, because a stop is a solid block and\n// an outline of one reads as a checkbox.\nexport const Square = /* @__PURE__ */ icon(SquareIcon, \"Square\");\nexport const SquaresFour = /* @__PURE__ */ icon(SquaresFourIcon, \"SquaresFour\");\n// Filled either way: an empty star is this one wearing a quieter colour, so\n// the row cannot change shape as it fills.\nexport const Star = /* @__PURE__ */ icon(StarIcon, \"Star\");\nexport const Sun = /* @__PURE__ */ icon(SunIcon, \"Sun\");\nexport const Table = /* @__PURE__ */ icon(TableIcon, \"Table\");\nexport const Tag = /* @__PURE__ */ icon(TagIcon, \"Tag\");\nexport const Timer = /* @__PURE__ */ icon(TimerIcon, \"Timer\");\nexport const Trash = /* @__PURE__ */ icon(TrashIcon, \"Trash\");\nexport const Tray = /* @__PURE__ */ icon(TrayIcon, \"Tray\");\nexport const TrendUp = /* @__PURE__ */ icon(TrendUpIcon, \"TrendUp\");\nexport const UserCircle = /* @__PURE__ */ icon(UserCircleIcon, \"UserCircle\");\nexport const Users = /* @__PURE__ */ icon(UsersIcon, \"Users\");\nexport const WarningCircle = /* @__PURE__ */ icon(WarningCircleIcon, \"WarningCircle\");\nexport const Wrench = /* @__PURE__ */ icon(WrenchIcon, \"Wrench\");\nexport const XCircle = /* @__PURE__ */ icon(XCircleIcon, \"XCircle\");\n\n// Exceptions. These are line glyphs with nothing to fill in, so Phosphor's\n// fill weight gives them a shape instead of a body: Check becomes a filled\n// box, the carets become solid triangles, the magnifier becomes a solid disc,\n// the three dots swell into blobs, and the arrow turns into a slab. Bold is\n// the heavier version of the same icon, which is what fill is meant to look\n// like here.\nexport const ArrowDown = /* @__PURE__ */ icon(ArrowDownIcon, \"ArrowDown\", \"bold\");\n// The return key, drawn as the arrow printed on it.\nexport const EnterKey = /* @__PURE__ */ icon(ArrowElbowDownLeftIcon, \"EnterKey\", \"bold\");\nexport const ArrowUp = /* @__PURE__ */ icon(ArrowUpIcon, \"ArrowUp\", \"bold\");\nexport const ArrowsClockwise = /* @__PURE__ */ icon(\n ArrowsClockwiseIcon,\n \"ArrowsClockwise\",\n \"bold\",\n);\nexport const ArrowSquareOut = /* @__PURE__ */ icon(ArrowSquareOutIcon, \"ArrowSquareOut\", \"bold\");\nexport const ArrowsIn = /* @__PURE__ */ icon(ArrowsInIcon, \"ArrowsIn\", \"bold\");\nexport const ArrowsOut = /* @__PURE__ */ icon(ArrowsOutIcon, \"ArrowsOut\", \"bold\");\nexport const CaretDown = /* @__PURE__ */ icon(CaretDownIcon, \"CaretDown\", \"bold\");\nexport const CaretLeft = /* @__PURE__ */ icon(CaretLeftIcon, \"CaretLeft\", \"bold\");\nexport const CaretRight = /* @__PURE__ */ icon(CaretRightIcon, \"CaretRight\", \"bold\");\n// Rings, not discs: filling them leaves a dot where a status should be.\nexport const Circle = /* @__PURE__ */ icon(CircleIcon, \"Circle\", \"bold\");\nexport const CircleDashed = /* @__PURE__ */ icon(CircleDashedIcon, \"CircleDashed\", \"bold\");\nexport const Check = /* @__PURE__ */ icon(CheckIcon, \"Check\", \"bold\");\n// A line drawing of a node on a line, like the carets: filling it makes a\n// blob rather than a heavier commit.\nexport const GitCommit = /* @__PURE__ */ icon(GitCommitIcon, \"GitCommit\", \"bold\");\nexport const DotsThree = /* @__PURE__ */ icon(DotsThreeIcon, \"DotsThree\", \"bold\");\nexport const X = /* @__PURE__ */ icon(XIcon, \"X\", \"bold\");\nexport const Plus = /* @__PURE__ */ icon(PlusIcon, \"Plus\", \"bold\");\nexport const UploadSimple = /* @__PURE__ */ icon(UploadSimpleIcon, \"UploadSimple\", \"bold\");\nexport const MagnifyingGlass = /* @__PURE__ */ icon(\n MagnifyingGlassIcon,\n \"MagnifyingGlass\",\n \"bold\",\n);\n\n// The editor toolbar's glyphs live here too: letterforms, list markers, and\n// brackets are all line drawings, so they take the bold weight for the same\n// reason the carets do. CodeBlock and Quotes are up in the filled group,\n// having actual bodies to fill.\nexport const Code = /* @__PURE__ */ icon(CodeIcon, \"Code\", \"bold\");\nexport const LinkSimple = /* @__PURE__ */ icon(LinkSimpleIcon, \"LinkSimple\", \"bold\");\n// Three bars: fill would turn them into slabs.\nexport const List = /* @__PURE__ */ icon(ListIcon, \"List\", \"bold\");\nexport const ListBullets = /* @__PURE__ */ icon(ListBulletsIcon, \"ListBullets\", \"bold\");\nexport const ListChecks = /* @__PURE__ */ icon(ListChecksIcon, \"ListChecks\", \"bold\");\nexport const ListNumbers = /* @__PURE__ */ icon(ListNumbersIcon, \"ListNumbers\", \"bold\");\nexport const TextB = /* @__PURE__ */ icon(TextBIcon, \"TextB\", \"bold\");\nexport const TextItalic = /* @__PURE__ */ icon(TextItalicIcon, \"TextItalic\", \"bold\");\nexport const TextStrikethrough = /* @__PURE__ */ icon(\n TextStrikethroughIcon,\n \"TextStrikethrough\",\n \"bold\",\n);\n","/**\n * Where the widget lives, and everything that follows from it.\n *\n * A side and a height. The button snaps to the left or the right edge, because\n * an edge is where a thing parked on somebody's page belongs, and keeps\n * whatever height it was let go at, because that is the half nobody can guess\n * for them: the button is in the way of a cart, a banner or a footer, and only\n * the person looking at it knows which.\n *\n * The height is kept as a fraction of the travel rather than a number of\n * pixels, so a window that changes size moves it proportionally instead of\n * stranding it off the bottom.\n */\n\nexport type LauncherSide = \"left\" | \"right\";\n\n/** `y` runs 0 at the top of its travel to 1 at the bottom. */\nexport type LauncherSpot = { side: LauncherSide; y: number };\n\nexport const DEFAULT_SPOT: LauncherSpot = { side: \"right\", y: 1 };\n\nexport type Bounds = { left: number; top: number; width: number; height: number };\nexport type Size = { width: number; height: number };\n\nfunction clamp(value: number, low: number, high: number): number {\n return Math.min(Math.max(value, low), Math.max(low, high));\n}\n\n/** How far the button can travel between the top margin and the bottom one. */\nexport function travelOf(bounds: Bounds, button: Size, margin: number): number {\n return Math.max(0, bounds.height - 2 * margin - button.height);\n}\n\n/** The spot a button that landed here belongs to. */\nexport function spotFrom(\n at: { x: number; y: number },\n bounds: Bounds,\n button: Size,\n margin: number,\n): LauncherSpot {\n const travel = travelOf(bounds, button, margin);\n\n return {\n side:\n at.x + button.width / 2 < bounds.left + bounds.width / 2\n ? \"left\"\n : \"right\",\n y: travel === 0 ? 0 : clamp((at.y - bounds.top - margin) / travel, 0, 1),\n };\n}\n\n/**\n * The spot a panel dropped here belongs to.\n *\n * The other way round from the one above: an open panel is dragged by its own\n * header, so what landed somewhere is the box, not the button. The box hangs\n * upward from the button, so the button is at the box's bottom edge, and that\n * is the height the spot is a fraction of.\n *\n * The two do not cover the same range, and should not. A panel dragged to the\n * top of a short window still leaves its button at the panel's bottom edge,\n * which is exactly where the bubble should be waiting when it closes.\n */\nexport function spotFromPanel(\n at: { x: number; y: number },\n bounds: Bounds,\n button: Size,\n box: Size,\n margin: number,\n): LauncherSpot {\n const travel = travelOf(bounds, button, margin);\n const buttonY = at.y + box.height - button.height;\n\n return {\n side:\n at.x + box.width / 2 < bounds.left + bounds.width / 2 ? \"left\" : \"right\",\n y: travel === 0 ? 0 : clamp((buttonY - bounds.top - margin) / travel, 0, 1),\n };\n}\n\n/**\n * Everything the widget is positioned by, worked out from a spot.\n *\n * The box is panel sized and hangs upward from the button, which is where it\n * hung when this was a corner. Clamped so it never leaves the space it is in:\n * a button near the top drags the panel down below it instead, and the button\n * simply sits further up inside the same box.\n */\nexport function metricsFor(\n spot: LauncherSpot,\n bounds: Bounds,\n button: Size,\n boxHeight: number,\n margin: number,\n): { buttonY: number; boxTop: number; buttonInBox: number } {\n const buttonY = bounds.top + margin + spot.y * travelOf(bounds, button, margin);\n\n const highest = bounds.top + margin;\n const lowest = bounds.top + bounds.height - margin - boxHeight;\n const boxTop = clamp(buttonY + button.height - boxHeight, highest, lowest);\n\n return { buttonY, boxTop, buttonInBox: buttonY - boxTop };\n}\n\n/**\n * The closed shape: a circle the size of the button, at the button's own\n * height on the side it is parked against.\n *\n * `buttonY` is handed in as a CSS length rather than a number, so the same\n * function writes the resting shape from a variable the layout has filled in\n * and the fallback shape from a plain calc.\n */\nexport function closedClip(\n side: LauncherSide,\n buttonY: string,\n buttonSize: string,\n): string {\n const far = `calc(100% - ${buttonSize})`;\n\n return [\n `inset(${buttonY}`,\n side === \"left\" ? far : \"0px\",\n `calc(100% - ${buttonY} - ${buttonSize})`,\n side === \"left\" ? \"0px\" : far,\n `round calc(${buttonSize} / 2))`,\n ].join(\" \");\n}\n\n/** The point the scale grows from, so the circle stays under the button. */\nexport function clipOrigin(\n side: LauncherSide,\n buttonY: string,\n buttonSize: string,\n): string {\n return `${side === \"left\" ? \"0%\" : \"100%\"} calc(${buttonY} + ${buttonSize} / 2)`;\n}\n\n/**\n * Where this browser last left it.\n *\n * A small store rather than a bare read, the same shape `session.ts` uses and\n * for the same two reasons. The server cannot know, so it renders the default\n * and the store hands the real answer over on the client without a mismatched\n * attribute in between; and a snapshot has to be stable across calls, which is\n * what the cache is for.\n */\nconst STORAGE_KEY = \"median:launcher-spot\";\n\nconst listeners = new Set<() => void>();\nlet current: LauncherSpot | null = null;\n\nexport function subscribeSpot(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function getSpot(): LauncherSpot {\n if (current !== null) return current;\n\n current = DEFAULT_SPOT;\n try {\n const stored = window.localStorage.getItem(STORAGE_KEY);\n const parsed: unknown = stored === null ? null : JSON.parse(stored);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"side\" in parsed &&\n \"y\" in parsed\n ) {\n const { side, y } = parsed as { side: unknown; y: unknown };\n if ((side === \"left\" || side === \"right\") && typeof y === \"number\") {\n current = { side, y: clamp(y, 0, 1) };\n }\n }\n } catch {\n // Blocked storage, or something else's key with our name on it. Either\n // way the default is a perfectly good place for a support button.\n }\n return current;\n}\n\nexport function getDefaultSpot(): LauncherSpot {\n return DEFAULT_SPOT;\n}\n\nexport function setSpot(spot: LauncherSpot): void {\n current = spot;\n\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(spot));\n } catch {\n // It stays where they put it until the page goes away, which is the same\n // deal the session token gets.\n }\n\n for (const listener of listeners) listener();\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n MessageScroller as MessageScrollerPrimitive,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\";\n\n// Phosphor instead of the registry default, per the project icon rule.\nimport { ArrowDown } from \"@/components/icons\";\nimport { Button } from \"@/components/ui/button\";\nimport { useIsResizing } from \"@/hooks/use-is-resizing\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * From the shadcn registry (@shadcn/message-scroller, radix-nova style), with\n * two changes: the icon comes from our own set, and the registry's\n * `scrollbar-*` and `inset-s-*` utilities are written as plain properties,\n * since neither the scrollbar plugin nor logical inset utilities are here.\n *\n * `scrollbar-width` is said here as well as on the app's own `html`, and the\n * repetition is the point: this is the one scroller that also runs inside the\n * widget on somebody else's page, where there is no `html` of ours to inherit\n * from and a thread would otherwise wear whatever their site wears.\n */\n\nfunction MessageScrollerProvider({\n autoScroll = true,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>) {\n // Every thread here is a chat, so the chat behavior is the default: stay\n // pinned to the newest message while at the bottom, stay put while reading\n // older ones, and let the button offer the way back down. The primitive's\n // own default (off, with per-item scroll anchors) is built for pin-the-\n // question streaming UIs and yanks the viewport around in a live thread.\n return <MessageScrollerPrimitive.Provider autoScroll={autoScroll} {...props} />;\n}\n\nfunction MessageScroller({\n className,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Root>) {\n return (\n <MessageScrollerPrimitive.Root\n data-slot=\"message-scroller\"\n className={cn(\n \"group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Within this of the foot of the thread counts as being at it. */\nconst AT_END_PX = 8;\n/** Less than a pixel adrift is not worth correcting. */\nconst DRIFT_PX = 1;\n\n/**\n * Holds the newest message against the foot of the viewport while the viewport\n * is changing size.\n *\n * The scroller already does this, one frame late. Both of its resize observers\n * hand their work to `requestAnimationFrame`, so every frame of a resize is\n * painted with the scroll position the frame before it asked for.\n *\n * Growing hides that. A viewport that gets taller leaves its scroll offset out\n * of range, and the browser has to pull it back in as part of the same layout,\n * which lands the thread exactly where the late correction was going to put it\n * anyway. Shrinking has nothing doing that: the offset stays valid, the foot of\n * the viewport comes down past the thread, and the newest message drops a dozen\n * pixels behind and is dragged back a frame later. Every frame. That is the\n * shiver, and it is why only shrinking has it, and why it is worst on a panel\n * parked at the bottom, where the whole of the change comes off the top.\n *\n * So the same correction is made here first, in the observer itself, which is\n * before the frame is painted rather than after.\n */\nfunction usePinnedToEnd(viewport: React.RefObject<HTMLDivElement | null>) {\n React.useEffect(() => {\n const node = viewport.current;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n\n // Whether the thread was against the foot of the viewport, written down as\n // it happens: by the time a resize is reported the new size is already on\n // and the answer to that has changed.\n let wasAtEnd = true;\n const remember = () => {\n wasAtEnd =\n node.scrollHeight - node.scrollTop - node.clientHeight <= AT_END_PX;\n };\n\n const observer = new ResizeObserver(() => {\n const drift = node.scrollHeight - node.scrollTop - node.clientHeight;\n\n // Only ever catching up, never restating. A viewport that grew has had\n // its offset put back in range by the browser already, to a precision\n // this cannot match: `scrollHeight` and `clientHeight` are whole pixels\n // and the box between them is not, so saying it again would replace an\n // exact answer with one up to a pixel out, differently on every frame.\n if (wasAtEnd && drift > DRIFT_PX) {\n // Not `auto`, which would take the smooth scrolling below and ease a\n // correction that is meant to be invisible.\n node.scrollTo({\n top: node.scrollHeight - node.clientHeight,\n behavior: \"instant\",\n });\n }\n\n remember();\n });\n\n node.addEventListener(\"scroll\", remember, { passive: true });\n observer.observe(node);\n return () => {\n node.removeEventListener(\"scroll\", remember);\n observer.disconnect();\n };\n }, [viewport]);\n}\n\n/**\n * True from the frame after the viewport mounts, which is a frame after the\n * scroller has put itself at the newest message.\n */\nfunction useHasLanded() {\n const [hasLanded, setHasLanded] = React.useState(false);\n\n React.useEffect(() => {\n const frame = requestAnimationFrame(() => setHasLanded(true));\n\n return () => cancelAnimationFrame(frame);\n }, []);\n\n return hasLanded;\n}\n\nfunction MessageScrollerViewport({\n className,\n ref,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Viewport>) {\n const viewport = React.useRef<HTMLDivElement | null>(null);\n\n // Two scrolls are never worth watching, and this is both of them.\n //\n // The first one: a thread opens at the top and lands on the newest message,\n // and easing that drags the whole history past before you can read any of it.\n //\n // And every one during a resize: a panel growing, a window dragged, a phone\n // keyboard coming up. Each of those re-pins the thread on every frame, and\n // easing towards a target that moves every frame leaves the messages\n // trailing the box they are in.\n const hasLanded = useHasLanded();\n const isResizing = useIsResizing(viewport);\n const isSettled = hasLanded && !isResizing;\n\n usePinnedToEnd(viewport);\n\n // Ours as well as whoever else asked for it. The primitive keeps its own\n // separately, so this is only the two of us.\n const holdViewport = React.useCallback(\n (node: HTMLDivElement | null) => {\n viewport.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n },\n [ref],\n );\n\n return (\n <MessageScrollerPrimitive.Viewport\n ref={holdViewport}\n data-slot=\"message-scroller-viewport\"\n // Every scroll the scroller makes for itself asks for `auto`, which\n // hands the decision to this element, so the thread is either all\n // animated or none of it. Only the button picks smooth on its own.\n //\n // All of them are a pin to the newest message today. The one to watch\n // for is the correction that holds your place when older messages are\n // loaded in above: that one wants to be instant, and it would have to\n // stop asking for `auto` to stay that way.\n data-settled={isSettled ? \"\" : undefined}\n className={cn(\n \"size-full min-h-0 min-w-0 overflow-y-auto overscroll-contain contain-content [scrollbar-gutter:stable] [scrollbar-width:thin]\",\n // A reply landing while you are at the bottom should carry you down\n // rather than teleport you, and the button should travel the distance\n // it is offering to cover. See above for the two that are left out.\n //\n // Granted rather than taken away, since `motion-reduce:scroll-auto`\n // would lose to an attribute selector and never get a say.\n \"motion-safe:data-settled:scroll-smooth\",\n // The fade says \"there is more below\", so it only belongs to a\n // viewport that has more below.\n //\n // The registry hangs `scroll-fade-b` on unconditionally and retracts\n // it with a scroll driven animation. That leaves the newest message\n // dimmed at the foot of every thread: a browser without scroll\n // timelines takes the utility's own fallback and pins the fade on\n // forever, and even where they work the mask is still painted over a\n // thread too short to scroll at all. `data-scrollable` is the same\n // question answered by measurement, and the primitive already writes\n // it here. It drops \"end\" as soon as you are within a few pixels of\n // the bottom, and while it is following the bottom it never claims it.\n \"data-[scrollable~=end]:scroll-fade-b\",\n // The registry also blanks the scrollbar while the scroller is moving\n // on its own. That was covering for the jump: the bar flicked from one\n // place to another with nothing in between. Now it slides, so hiding it\n // is the flicker, and it holds the thumb back for a fixed 180ms that\n // has nothing to do with how far the thread actually travelled.\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MessageScrollerContent({\n className,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Content>) {\n return (\n <MessageScrollerPrimitive.Content\n data-slot=\"message-scroller-content\"\n className={cn(\"flex h-max min-h-full flex-col gap-6\", className)}\n {...props}\n />\n );\n}\n\nfunction MessageScrollerItem({\n className,\n scrollAnchor = false,\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Item>) {\n return (\n <MessageScrollerPrimitive.Item\n data-slot=\"message-scroller-item\"\n scrollAnchor={scrollAnchor}\n className={cn(\n \"min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MessageScrollerButton({\n direction = \"end\",\n className,\n children,\n render,\n variant = \"secondary\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof MessageScrollerPrimitive.Button> &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">) {\n return (\n <MessageScrollerPrimitive.Button\n data-slot=\"message-scroller-button\"\n data-direction={direction}\n data-variant={variant}\n data-size={size}\n direction={direction}\n className={cn(\n \"absolute start-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180\",\n className,\n )}\n render={render ?? <Button variant={variant} size={size} />}\n {...props}\n >\n {children ?? (\n <>\n <ArrowDown />\n <span className=\"sr-only\">\n {direction === \"end\" ? \"Scroll to end\" : \"Scroll to start\"}\n </span>\n </>\n )}\n </MessageScrollerPrimitive.Button>\n );\n}\n\nexport {\n MessageScrollerProvider,\n MessageScroller,\n MessageScrollerViewport,\n MessageScrollerContent,\n MessageScrollerItem,\n MessageScrollerButton,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n};\n","import*as i from'react';function S({defaultTagName:a,props:r,render:t,state:n={},stateAttributesMapping:e}){let o=d(R(n,e),r);if(!t)return i.createElement(a,o);if(typeof t==\"function\")return t(o,n);if(!i.isValidElement(t))return null;let s=t.props,u={...d(o,s),ref:f(o.ref,s.ref)};return i.cloneElement(t,u)}function d(...a){let r={};for(let t of a){if(!t)continue;let n=t;for(let e of Object.keys(n)){let o=n[e];if(o===void 0)continue;let s=r[e];e===\"className\"?r[e]=[s,o].filter(Boolean).join(\" \"):e===\"style\"?r[e]={...s,...o}:e===\"ref\"?r[e]=f(s,o):l(e)&&typeof s==\"function\"&&typeof o==\"function\"?r[e]=p(o,s):r[e]=o;}}return r}function R(a,r){let t={};for(let n of Object.keys(a)){let e=a[n],o=r?.[n]?.(e);if(o){Object.assign(t,o);continue}if(n===\"slot\"){t[\"data-slot\"]=e;continue}let s=`data-${String(n).replace(/[A-Z]/g,c=>`-${c.toLowerCase()}`)}`;typeof e==\"boolean\"?t[s]=e?\"\":void 0:e!=null&&(t[s]=String(e));}return t}function p(a,r){return function(n){a(n),n.defaultPrevented||r(n);}}function l(a){return /^on[A-Z]/.test(a)}function f(...a){let r=a.filter(Boolean);if(r.length!==0)return t=>{for(let n of r)typeof n==\"function\"?n(t):n&&(n.current=t);}}export{S as a,d as b,f as c};","\"use client\";\nimport {c,a,b}from'../chunk-HBS6WEDP.js';import*as g from'react';import {jsx,jsxs}from'react/jsx-runtime';var xe=8,Ve=64,_e=0,J=.5,ke=180,Be=new Set([\"ArrowDown\",\"ArrowUp\",\"End\",\"Home\",\"PageDown\",\"PageUp\",\" \"]),ge={start:false,end:false},dt=[],Q={currentAnchorId:null,visibleMessageIds:dt};function De({content:e,scrollEdgeThreshold:t,spacer:r,viewport:n}){if(!n||!e)return ge;let o=Se({content:e,spacer:r,viewport:n});return {start:n.scrollTop>t,end:o-n.scrollTop-n.clientHeight>t}}function Fe({content:e,scrollMargin:t,scrollPreviousItemPeek:r,spacer:n,viewport:o,visibleMessageIds:i}){if(!e||!o)return Q;let S=o.getBoundingClientRect(),l=S.top+t+r,d=typeof IntersectionObserver>\"u\",E=[],b=null;for(let C of ee(e,n)){let p=C.dataset.messageId;if(!p)continue;let m=C.dataset.scrollAnchor===\"true\",L=m||d?C.getBoundingClientRect():null;(d&&L?L.bottom>l&&L.top<S.bottom:i.has(p))&&E.push(p),m&&L&&L.top<=l+J&&(b=p);}return E.length===0&&b===null?Q:{currentAnchorId:b,visibleMessageIds:E}}function ee(e,t){return Array.from(e.children).filter(r=>r instanceof HTMLElement&&r!==t)}function je(e,t){for(let r=t;r<e.length;r++){let n=e[r];if(n?.dataset.scrollAnchor===\"true\")return n}return null}function Ge(e,t){for(let r of e)if(r.dataset.scrollAnchor===\"true\"&&!t.has(r))return r;return null}function Ne(e,t){let r=0;for(let n=t;n<e.length;n++)if(e[n]?.dataset.scrollAnchor===\"true\"&&(r+=1,r>1))return true;return false}function Ue(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(r?.dataset.scrollAnchor===\"true\")return r}return null}function Ye({content:e,spacer:t,viewport:r}){let n=r.getBoundingClientRect();for(let o of ee(e,t)){if(!o.dataset.messageId)continue;let i=o.getBoundingClientRect();if(i.bottom>n.top&&i.top<n.bottom)return o}return null}function ze({align:e,element:t,scrollMargin:r,spacer:n,viewport:o}){let i=pe(t,o),S=t.getBoundingClientRect().height,l=bt(n);if(e===\"center\"){let d=Math.max(0,o.clientHeight-l.start-l.end);return i-l.start-(d-S)/2-r}if(e===\"end\")return i-o.clientHeight+S+l.end+r;if(e===\"nearest\"){let d=i+S,E=o.scrollTop+l.start,b=o.scrollTop+o.clientHeight-l.end;return i>=E&&d<=b?o.scrollTop:i<E?i-l.start-r:d-o.clientHeight+l.end+r}return i-l.start-r}function pe(e,t){let r=e.getBoundingClientRect(),n=t.getBoundingClientRect();return r.top-n.top+t.scrollTop}function te(e,t){return e.getBoundingClientRect().top-t.getBoundingClientRect().top}function qe({content:e,scrollTop:t,spacer:r,viewport:n}){let o=Se({content:e,spacer:r,viewport:n});return t+n.clientHeight-o}function Se({content:e,spacer:t,viewport:r}){let n=ee(e,t),o=We(e),i=r.getBoundingClientRect(),S=r.scrollTop,l=o.start+o.end;for(let d of n){let E=d.getBoundingClientRect();l=Math.max(l,E.bottom-i.top+S+o.end);}return l}function Ke(e){return Math.max(0,e.scrollHeight-e.clientHeight)}function We(e){let t=window.getComputedStyle(e);return {end:Re(t.paddingBlockEnd||t.paddingBottom),start:Re(t.paddingBlockStart||t.paddingTop)}}function bt(e){let t=e?.parentElement;return t?We(t):{end:0,start:0}}function $e(e){if(!e)return 0;let t=window.getComputedStyle(e),r=t.rowGap===\"normal\"?t.gap:t.rowGap;return Re(r)}function Re(e){if(!e)return 0;let t=Number.parseFloat(e);return Number.isFinite(t)?t:0}function Je({refs:e,commitScrollState:t,scheduleStateCommit:r,scheduleVisibilitySync:n}){let{streamingTurnRef:o,autoScrollRef:i,autoscrollingRef:S,autoscrollingTimeoutRef:l,contentRef:d,defaultScrollPositionAppliedRef:E,itemCountRef:b,messageElementsRef:C,modeRef:p,pendingScrollToMessageRef:m,prependRestoreRef:L,scrollMarginRef:y,scrollPreviousItemPeekRef:u,spacerGapRef:x,spacerHeightRef:Y,spacerRef:k,viewportRef:_}=e,G=g.useCallback(c=>{l.current!==null&&(window.clearTimeout(l.current),l.current=null),S.current!==c&&(S.current=c,t()),c&&(l.current=window.setTimeout(()=>{l.current=null,S.current=false,t();},ke));},[t]),v=g.useCallback(c=>{let f=k.current;if(!f)return;let h=Math.max(0,Math.ceil(c));Y.current!==h&&(Y.current=h,f.hidden=h===0,f.style.height=`${h}px`,f.style.marginTop=h>0?`${-x.current}px`:\"\");},[]),H=g.useCallback((c,{behavior:f=\"auto\",autoscrolling:h=false}={})=>{let P=_.current;if(!P)return;let V=Math.max(0,c);if(Math.abs(P.scrollTop-V)<=J){P.scrollTop=V,t();return}h&&G(true),P.scrollTo({top:V,behavior:f}),r();},[t,r,G]),N=g.useCallback(({behavior:c=\"auto\"}={})=>_.current?(v(0),o.current=null,p.current=\"free-scrolling\",H(0,{behavior:c}),n(),true):false,[n,H,v]),ne=g.useCallback(({behavior:c=\"auto\"}={})=>{let f=_.current;return f?(v(0),o.current=null,p.current=i.current?\"following-bottom\":\"free-scrolling\",H(Ke(f),{autoscrolling:true,behavior:c}),n(),true):false},[n,H,v]),A=g.useCallback((c,{align:f=\"start\",behavior:h=\"auto\",scrollMargin:P=y.current}={},{keepPreviousPeek:V=false}={})=>{let z=d.current,q=_.current;if(!z||!q||!z.contains(c))return false;let K=ze({align:f,element:c,scrollMargin:V?P+u.current:P,spacer:k.current,viewport:q}),se=qe({content:z,scrollTop:K,spacer:k.current,viewport:q});return v(se),L.current={element:c,viewportTop:te(c,q)},p.current=V?\"anchored-to-message\":\"settling-jump\",o.current=V?c:null,H(K,{behavior:h}),n(),true},[n,H,v]),B=g.useCallback(()=>{let c=o.current;return !c||!c.isConnected||p.current!==\"anchored-to-message\"?false:A(c,{align:\"start\"},{keepPreviousPeek:true})},[A]),D=g.useCallback((c,f)=>{let h=C.current.get(c);return h?(E.current=true,A(h,f)?(m.current=null,true):(m.current={messageId:c,options:f},true)):b.current===0?(m.current={messageId:c,options:f},E.current=true,true):false},[A]);return {flushPendingScrollToMessage:g.useCallback(()=>{let c=m.current;if(!c)return false;let f=C.current.get(c.messageId);return !f||!A(f,c.options)?false:(m.current=null,E.current=true,true)},[A]),reanchorToAnchoredMessage:B,scrollToElement:A,scrollToEnd:ne,scrollToMessage:D,scrollToStart:N}}function Qe(e,t){let r=e,n=new Set;return {getSnapshot:()=>r,hasListeners:()=>n.size>0,setSnapshot:o=>{t(r,o)||(r=o,n.forEach(i=>i()));},subscribe:(o,i,S)=>{let l=n.size===0;return n.add(o),l&&i?.(),()=>{n.delete(o),n.size===0&&S?.();}}}}function Xe(e,t){return Qe(e,t)}function Ze(){return Qe(Q,Tt)}function et(e,t){return e.start===t.start&&e.end===t.end}function Tt(e,t){return e.currentAnchorId!==t.currentAnchorId||e.visibleMessageIds.length!==t.visibleMessageIds.length?false:e.visibleMessageIds.every((r,n)=>r===t.visibleMessageIds[n])}function tt({autoScroll:e,scrollEdgeThreshold:t,scrollMargin:r,scrollPreviousItemPeek:n}){let o=g.useRef(e),i=g.useRef(false),S=g.useRef(null),l=g.useRef(false),d=g.useRef(t),E=g.useRef(0),b=g.useRef(null),C=g.useRef(0),p=g.useRef(e?\"following-bottom\":\"free-scrolling\"),m=g.useRef(new Map),L=g.useRef(null),y=g.useRef(null),u=g.useRef(null),x=g.useRef(n),Y=g.useRef(true),k=g.useRef(null),_=g.useRef(r),G=g.useRef(null),v=g.useRef(0),H=g.useRef(0),N=g.useRef(null),ne=g.useRef(null),A=g.useRef(null),B=g.useRef(null),D=g.useRef(null),U=g.useRef(null),c=g.useRef(null),f=g.useRef(null),h=g.useRef(new Set),P=g.useRef(new WeakSet);return A.current===null&&(A.current=Xe(ge,et)),f.current===null&&(f.current=Ze()),o.current=e,d.current=t,_.current=r,x.current=n,{autoScrollRef:o,autoscrollingRef:i,autoscrollingTimeoutRef:B,streamingTurnRef:u,contentRef:S,defaultScrollPositionAppliedRef:l,firstItemRef:b,itemCountRef:E,lastScrollTopRef:C,messageElementsRef:m,modeRef:p,pendingScrollFrameRef:G,pendingScrollToMessageRef:L,prependRestoreRef:y,preserveScrollOnPrependRef:Y,rootRef:k,scrollEdgeThresholdRef:d,scrollMarginRef:_,scrollPreviousItemPeekRef:x,spacerGapRef:v,spacerHeightRef:H,spacerRef:N,stateFrameRef:ne,stateStore:A.current,viewportRef:D,visibilityFrameRef:U,visibilityObserverRef:c,visibilityStore:f.current,visibleMessageIdsRef:h,handledScrollAnchorsRef:P}}function rt(e,t){return g.useCallback(r=>{e.current=r,r&&t();},[e,t])}function nt({autoScroll:e=false,defaultScrollPosition:t=\"end\",scrollEdgeThreshold:r=xe,scrollPreviousItemPeek:n=Ve,scrollMargin:o=_e}){let i=tt({autoScroll:e,scrollEdgeThreshold:r,scrollMargin:o,scrollPreviousItemPeek:n}),{streamingTurnRef:S,autoScrollRef:l,autoscrollingRef:d,autoscrollingTimeoutRef:E,contentRef:b,defaultScrollPositionAppliedRef:C,firstItemRef:p,itemCountRef:m,lastScrollTopRef:L,messageElementsRef:y,modeRef:u,pendingScrollFrameRef:x,pendingScrollToMessageRef:Y,prependRestoreRef:k,preserveScrollOnPrependRef:_,rootRef:G,scrollEdgeThresholdRef:v,scrollMarginRef:H,scrollPreviousItemPeekRef:N,spacerGapRef:ne,spacerHeightRef:A,spacerRef:B,stateFrameRef:D,stateStore:U,viewportRef:c,visibilityFrameRef:f,visibilityObserverRef:h,visibilityStore:P,visibleMessageIdsRef:V,handledScrollAnchorsRef:z}=i,q=g.useRef(t);q.current!==t&&(q.current=t,C.current=false);let K=g.useCallback(s=>{let a=G.current,T=c.current,O=[s.start&&\"start\",s.end&&\"end\"].filter(Boolean).join(\" \"),ue=d.current;for(let W of [a,T])W&&(O?W.setAttribute(\"data-scrollable\",O):W.removeAttribute(\"data-scrollable\"),W.toggleAttribute(\"data-autoscrolling\",ue));},[]),se=g.useCallback(s=>{let a=c.current?.scrollTop??0,T=a<L.current-J;L.current=a,l.current&&!s.end&&u.current!==\"settling-jump\"&&u.current!==\"anchored-to-message\"?u.current=\"following-bottom\":u.current===\"following-bottom\"&&s.end&&T&&!d.current&&(u.current=\"free-scrolling\");},[]),F=g.useCallback(()=>{let s=De({content:b.current,scrollEdgeThreshold:v.current,spacer:B.current,viewport:c.current});se(s);let a=u.current===\"following-bottom\"?{...s,end:false}:s;K(a),U.setSnapshot(a);},[se,U,K]),oe=g.useCallback(()=>{D.current===null&&(D.current=window.requestAnimationFrame(()=>{D.current=null,F();}));},[F]),w=g.useCallback(()=>{P.hasListeners()&&f.current===null&&(f.current=window.requestAnimationFrame(()=>{f.current=null,P.hasListeners()&&P.setSnapshot(Fe({content:b.current,scrollMargin:H.current,scrollPreviousItemPeek:N.current,spacer:B.current,viewport:c.current,visibleMessageIds:V.current}));}));},[P]),{flushPendingScrollToMessage:ce,reanchorToAnchoredMessage:me,scrollToElement:le,scrollToEnd:I,scrollToMessage:Me,scrollToStart:ae}=Je({refs:i,commitScrollState:F,scheduleStateCommit:oe,scheduleVisibilitySync:w}),de=g.useCallback(()=>{let s=k.current,a=c.current;if(!s||!a||!s.element.isConnected)return false;let O=te(s.element,a)-s.viewportTop;return Math.abs(O)<=J?false:(a.scrollTop+=O,s.viewportTop=te(s.element,a),oe(),w(),true)},[oe,w]),Z=g.useCallback(()=>{let s=b.current,a=c.current;if(!s||!a){k.current=null;return}let T=Ye({content:s,spacer:B.current,viewport:a});k.current=T?{element:T,viewportTop:te(T,a)}:null;},[]),be=g.useCallback(()=>{x.current===null&&(x.current=window.requestAnimationFrame(()=>{x.current=null,ce()&&Z();}));},[Z,ce]),ie=g.useCallback(()=>{if(!t||C.current||m.current===0)return false;let s=false;if(t===\"last-anchor\"){let a=b.current,T=c.current,O=a&&T?Ue(ee(a,B.current)):null;if(!a||!T||!O)s=I({behavior:\"auto\"});else {let ue=pe(O,T);s=Se({content:a,spacer:B.current,viewport:T})-ue<=T.clientHeight?I({behavior:\"auto\"}):le(O,{align:\"start\"},{keepPreviousPeek:true});}}else s=t===\"end\"?I({behavior:\"auto\"}):ae({behavior:\"auto\"});return s?(C.current=true,true):false},[t,le,I,ae]),Te=g.useCallback(()=>{let s=b.current;if(!s)return;let a=ee(s,B.current),T=m.current,O=p.current;m.current=a.length,p.current=a[0]??null,(()=>{if(ce())return;if(T===0){if(ie()||a.length>0&&l.current&&I({behavior:\"auto\"}))return;F(),w();return}let W=O?a.indexOf(O):-1;if(_.current&&W>0){de();return}if(a.length>T){let $=je(a,T);if($){if(l.current&&u.current===\"following-bottom\"&&Ne(a,T)){I({behavior:\"auto\"});return}le($,{align:\"start\"},{keepPreviousPeek:true}),z.current.add($);return}}if(a.length===T){let $=Ge(a,z.current);if($){le($,{align:\"start\"},{keepPreviousPeek:true}),z.current.add($);return}}u.current===\"following-bottom\"&&l.current?I({behavior:\"auto\"}):(F(),w());})(),Z();},[ie,Z,F,ce,de,w,le,I]),Ee=g.useCallback(()=>{if(u.current===\"following-bottom\"&&l.current){I({behavior:\"auto\"});return}let s=A.current;if(me()){l.current&&s>0&&A.current===0&&I({behavior:\"auto\"});return}oe(),w();},[me,oe,w,I]),ve=g.useCallback(()=>{let s=c.current;if(!(!s||!P.hasListeners())){if(typeof IntersectionObserver>\"u\"){w();return}h.current||(h.current=new IntersectionObserver(a=>{for(let T of a){let O=T.target.dataset.messageId;O&&(T.isIntersecting?V.current.add(O):V.current.delete(O));}w();},{root:s,rootMargin:`${-(H.current+N.current)}px 0px 0px 0px`,threshold:[0,.01,.5,1]})),y.current.forEach(a=>{h.current?.observe(a);}),w();}},[w,P]),he=g.useCallback(()=>{f.current!==null&&(window.cancelAnimationFrame(f.current),f.current=null),h.current?.disconnect(),h.current=null,V.current.clear(),P.setSnapshot(Q);},[P]),pt=g.useCallback((s,a,T)=>{if(a){y.current.set(s,a),h.current?.observe(a),w(),Y.current?.messageId===s&&be();return}T&&y.current.get(s)===T&&(y.current.delete(s),V.current.delete(s),h.current?.unobserve(T),w());},[be,w]),Le=g.useCallback(()=>{(u.current===\"following-bottom\"||u.current===\"anchored-to-message\"||u.current===\"settling-jump\")&&(S.current=null,u.current=\"free-scrolling\");},[]),Ce=g.useCallback(()=>K(U.getSnapshot()),[U,K]),Pe=rt(G,Ce),we=rt(c,Ce),Oe=g.useCallback(s=>{b.current=s;},[]),ye=g.useCallback(s=>{B.current=s,ne.current=$e(s?.parentElement??null);},[]),He=g.useCallback(()=>{F(),w(),Z();},[Z,F,w]),mt=g.useMemo(()=>({handleContentChange:Te,handleResize:Ee,observeVisibility:ve,preserveScrollOnPrependRef:_,scrollToEnd:I,scrollToMessage:Me,scrollToStart:ae,setContentElement:Oe,setRootElement:Pe,setSpacerElement:ye,setViewportElement:we,stateStore:U,syncAfterScroll:He,unobserveVisibility:he,userScrollIntent:Le,viewportRef:c,visibilityStore:P}),[Te,Ee,ve,I,Me,ae,Oe,Pe,ye,we,U,He,he,Le,P]);return g.useLayoutEffect(()=>{ie();},[ie]),g.useEffect(()=>()=>{D.current!==null&&(window.cancelAnimationFrame(D.current),D.current=null),f.current!==null&&(window.cancelAnimationFrame(f.current),f.current=null),E.current!==null&&(window.clearTimeout(E.current),E.current=null),x.current!==null&&(window.cancelAnimationFrame(x.current),x.current=null),h.current?.disconnect(),h.current=null;},[]),g.useLayoutEffect(()=>{if(e&&u.current===\"following-bottom\"&&m.current>0){I({behavior:\"auto\"});return}F();},[e,F,I]),{context:mt,registerMessage:pt}}function lt(e){let t=g.useRef(e);return t.current=e,t}var st=g.createContext(null),ct=g.createContext(null);function X(){let e=g.useContext(st);if(!e)throw new Error(\"useMessageScroller must be used within a MessageScroller.\");return e}function Et(){let e=g.useContext(ct);if(!e)throw new Error(\"MessageScrollerItem must be used within a MessageScroller.\");return e}function vt(){let{scrollToEnd:e,scrollToMessage:t,scrollToStart:r}=X();return g.useMemo(()=>({scrollToEnd:e,scrollToMessage:t,scrollToStart:r}),[e,t,r])}function ht(){let{stateStore:e}=X();return g.useSyncExternalStore(e.subscribe,e.getSnapshot,e.getSnapshot)}function Lt(){let{observeVisibility:e,unobserveVisibility:t,visibilityStore:r}=X(),n=g.useCallback(o=>r.subscribe(o,e,t),[e,t,r]);return g.useSyncExternalStore(n,r.getSnapshot,r.getSnapshot)}function at({autoScroll:e=false,children:t,defaultScrollPosition:r=\"end\",scrollEdgeThreshold:n,scrollPreviousItemPeek:o,scrollMargin:i}){let{context:S,registerMessage:l}=nt({autoScroll:e,defaultScrollPosition:r,scrollEdgeThreshold:n,scrollPreviousItemPeek:o,scrollMargin:i});return jsx(st.Provider,{value:S,children:jsx(ct.Provider,{value:l,children:t})})}function it({children:e,...t}){let{setRootElement:r}=X();return jsx(\"div\",{ref:r,...t,children:e})}function ut({\"aria-label\":e,children:t,onKeyDown:r,onScroll:n,onTouchMove:o,onWheel:i,preserveScrollOnPrepend:S=true,ref:l,role:d,tabIndex:E,...b}){let{handleResize:C,preserveScrollOnPrependRef:p,setViewportElement:m,syncAfterScroll:L,userScrollIntent:y,viewportRef:u}=X();p.current=S;let x=g.useCallback(v=>{m(v),c(l)?.(v);},[l,m]);function Y(v){L(),n?.(v);}function k(v){y(),i?.(v);}function _(v){y(),o?.(v);}function G(v){Be.has(v.key)&&y(),r?.(v);}return g.useEffect(()=>{let v=u.current;if(!v||typeof ResizeObserver>\"u\")return;let H=0,N=new ResizeObserver(()=>{window.cancelAnimationFrame(H),H=window.requestAnimationFrame(C);});return N.observe(v),()=>{window.cancelAnimationFrame(H),N.disconnect();}},[C,u]),jsx(\"div\",{ref:x,role:d??\"region\",\"aria-label\":e??\"Messages\",tabIndex:E??0,onKeyDown:G,onScroll:Y,onTouchMove:_,onWheel:k,...b,children:t})}function ft({\"aria-relevant\":e,children:t,ref:r,role:n,spacerClassName:o,...i}){let{handleContentChange:S,handleResize:l,setContentElement:d,setSpacerElement:E}=X(),b=g.useRef(null),C=g.useCallback(p=>{b.current=p,d(p),c(r)?.(p);},[r,d]);return g.useLayoutEffect(()=>{let p=b.current;if(!p||(S(),typeof MutationObserver>\"u\"))return;let m=new MutationObserver(()=>{S();});return m.observe(p,{childList:true}),()=>m.disconnect()},[S]),g.useEffect(()=>{let p=b.current;if(!p||typeof ResizeObserver>\"u\")return;let m=0,L=new ResizeObserver(()=>{window.cancelAnimationFrame(m),m=window.requestAnimationFrame(l);});return L.observe(p),()=>{window.cancelAnimationFrame(m),L.disconnect();}},[l]),jsxs(\"div\",{ref:C,role:n??\"log\",\"aria-relevant\":e??\"additions\",...i,children:[t,jsx(\"div\",{ref:E,\"aria-hidden\":\"true\",\"data-message-scroller-spacer\":\"\",hidden:true,className:o})]})}function gt({messageId:e,ref:t,scrollAnchor:r=false,...n}){let o=Et(),i=g.useRef(null),S=g.useCallback(l=>{let d=i.current;i.current=l,e&&o(e,l,d),c(t)?.(l);},[e,t,o]);return jsx(\"div\",{ref:S,\"data-message-id\":e,\"data-scroll-anchor\":r?\"true\":\"false\",...n})}function St({behavior:e=\"smooth\",children:t,direction:r=\"end\",onClick:n,render:o,tabIndex:i,type:S=\"button\",...l}){let{scrollToEnd:d,scrollToStart:E,stateStore:b$1}=X(),C=lt(n),p=g.useCallback(u=>b$1.subscribe(u),[b$1]),m=g.useCallback(()=>{let u=b$1.getSnapshot();return r===\"start\"?u.start:u.end},[r,b$1]),L=g.useSyncExternalStore(p,m,m),y=g.useCallback(u=>{L&&(C.current?.(u),u.defaultPrevented||(u.currentTarget.blur(),r===\"start\"?E({behavior:e}):d({behavior:e})));},[e,r,L,C,d,E]);return a({defaultTagName:\"button\",props:b({type:S,inert:!L,tabIndex:L?i:-1,children:t??jsxs(\"span\",{children:[\"Scroll to \",r]}),onClick:y},l),render:o,state:{active:L,direction:r},stateAttributesMapping:{active:u=>({\"data-active\":u?\"true\":\"false\"})}})}var $t={Provider:at,Root:it,Viewport:ut,Content:ft,Item:gt,Button:St};export{$t as MessageScroller,vt as useMessageScroller,ht as useMessageScrollerScrollable,Lt as useMessageScrollerVisibility};","/**\n * Copyright 2022 Joe Bell. All rights reserved.\n *\n * This file is licensed to you under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with the\n * License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */ import { clsx } from \"clsx\";\nconst falsyToString = (value)=>typeof value === \"boolean\" ? `${value}` : value === 0 ? \"0\" : value;\nexport const cx = clsx;\nexport const cva = (base, config)=>(props)=>{\n var _config_compoundVariants;\n if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n const { variants, defaultVariants } = config;\n const getVariantClassNames = Object.keys(variants).map((variant)=>{\n const variantProp = props === null || props === void 0 ? void 0 : props[variant];\n const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];\n if (variantProp === null) return null;\n const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);\n return variants[variant][variantKey];\n });\n const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param)=>{\n let [key, value] = param;\n if (value === undefined) {\n return acc;\n }\n acc[key] = value;\n return acc;\n }, {});\n const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param)=>{\n let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;\n return Object.entries(compoundVariantOptions).every((param)=>{\n let [key, value] = param;\n return Array.isArray(value) ? value.includes({\n ...defaultVariants,\n ...propsWithoutUndefined\n }[key]) : ({\n ...defaultVariants,\n ...propsWithoutUndefined\n })[key] === value;\n }) ? [\n ...acc,\n cvClass,\n cvClassName\n ] : acc;\n }, []);\n return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n };\n\n","import * as React from 'react';\nimport { useComposedRefs } from '@radix-ui/react-compose-refs';\n\ndeclare module 'react' {\n interface ReactElement {\n $$typeof?: symbol | string;\n }\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Slot\n * -----------------------------------------------------------------------------------------------*/\n\nexport type Usable<T> = PromiseLike<T> | React.Context<T>;\n\ntype SlotProps<Elem extends Element = HTMLElement, Props = React.HTMLAttributes<Elem>> = Props & {\n children?: React.ReactNode;\n};\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlot<\n Elem extends Element = HTMLElement,\n Props = React.HTMLAttributes<Elem>,\n>(ownerName: string) {\n const Slot = React.forwardRef<Elem, SlotProps<Elem, Props>>((props, forwardedRef) => {\n let { children, ...slotProps } = props;\n let slottableElement: React.ReactElement | null = null;\n let hasSlottable = false;\n const newChildren: React.ReactNode[] = [];\n\n if (isLazyComponent(children) && typeof use === 'function') {\n children = use(children._payload);\n }\n\n React.Children.forEach(children, (maybeSlottable) => {\n if (isSlottable(maybeSlottable)) {\n hasSlottable = true;\n const slottable = maybeSlottable;\n let child = 'child' in slottable.props ? slottable.props.child : slottable.props.children;\n\n if (isLazyComponent(child) && typeof use === 'function') {\n child = use(child._payload);\n }\n\n slottableElement = getSlottableElementFromSlottable(slottable, child);\n newChildren.push((slottableElement?.props as any)?.children);\n } else {\n newChildren.push(maybeSlottable);\n }\n });\n\n if (slottableElement) {\n slottableElement = React.cloneElement(slottableElement, undefined, newChildren);\n } else if (\n // A `Slottable` was found but it didn't resolve to a single element (e.g.\n // it wrapped multiple elements, text, or a render-prop `child` that\n // wasn't an element). Don't fall back to treating the `Slottable` wrapper\n // itself as the slot target — throw a descriptive error below instead.\n !hasSlottable &&\n React.Children.count(children) === 1 &&\n React.isValidElement(children)\n ) {\n slottableElement = children;\n }\n\n const slottableElementRef = slottableElement ? getElementRef(slottableElement) : undefined;\n const composedRef = useComposedRefs(forwardedRef, slottableElementRef);\n\n if (!slottableElement) {\n // Empty/falsy children (`null`, `undefined`, `false`, no children, etc.) are valid and\n // render nothing. Anything else is content we couldn't slot onto a single element, which\n // is a usage error, so we fail loudly with a clear message.\n if (children || children === 0) {\n throw new Error(\n hasSlottable ? createSlottableError(ownerName) : createSlotError(ownerName),\n );\n }\n return children;\n }\n\n const mergedProps = mergeProps(slotProps, slottableElement.props ?? {});\n\n // do not pass ref to React.Fragment for React 19 compatibility\n if (slottableElement.type !== React.Fragment) {\n mergedProps.ref = forwardedRef ? composedRef : slottableElementRef;\n }\n\n return React.cloneElement(slottableElement, mergedProps);\n });\n\n Slot.displayName = `${ownerName}.Slot`;\n return Slot;\n}\n\nconst Slot = createSlot('Slot');\n\n/* -------------------------------------------------------------------------------------------------\n * Slottable\n * -----------------------------------------------------------------------------------------------*/\n\nconst SLOTTABLE_IDENTIFIER = Symbol.for('radix.slottable');\n\ntype SlottableChildrenProps = { children: React.ReactNode };\ntype SlottableRenderFnProps = {\n child: React.ReactNode;\n children: (slottable: React.ReactNode) => React.ReactNode;\n};\n\ntype SlottableProps = SlottableRenderFnProps | SlottableChildrenProps;\ninterface SlottableComponent extends React.FC<SlottableProps> {\n __radixId: symbol;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlottable(ownerName: string) {\n const Slottable: SlottableComponent = (props) =>\n 'child' in props ? props.children(props.child) : props.children;\n\n Slottable.displayName = `${ownerName}.Slottable`;\n Slottable.__radixId = SLOTTABLE_IDENTIFIER;\n return Slottable;\n}\n\nconst Slottable = createSlottable('Slottable');\n\n/* -------------------------------------------------------------------------------------------------\n * getSlottableElementFromSlottable\n * -----------------------------------------------------------------------------------------------*/\n\nconst getSlottableElementFromSlottable = (slottable: SlottableElement, child: React.ReactNode) => {\n if ('child' in slottable.props) {\n const child = slottable.props.child;\n if (!React.isValidElement<React.PropsWithChildren>(child)) return null;\n return React.cloneElement(child, undefined, slottable.props.children(child.props.children));\n }\n\n return React.isValidElement(child) ? child : null;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * mergeProps\n * -----------------------------------------------------------------------------------------------*/\n\ntype AnyProps = Record<string, any>;\n\nfunction mergeProps(slotProps: AnyProps, childProps: AnyProps) {\n // all child props should override\n const overrideProps = { ...childProps };\n\n for (const propName in childProps) {\n const slotPropValue = slotProps[propName];\n const childPropValue = childProps[propName];\n\n const isHandler = /^on[A-Z]/.test(propName);\n if (isHandler) {\n // if the handler exists on both, we compose them\n if (slotPropValue && childPropValue) {\n overrideProps[propName] = (...args: unknown[]) => {\n const result = childPropValue(...args);\n slotPropValue(...args);\n return result;\n };\n }\n // but if it exists only on the slot, we use only this one\n else if (slotPropValue) {\n overrideProps[propName] = slotPropValue;\n }\n }\n // if it's `style`, we merge them\n else if (propName === 'style') {\n overrideProps[propName] = { ...slotPropValue, ...childPropValue };\n } else if (propName === 'className') {\n overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(' ');\n }\n }\n\n return { ...slotProps, ...overrideProps };\n}\n\n/* -------------------------------------------------------------------------------------------------\n * getElementRef\n * -----------------------------------------------------------------------------------------------*/\n\n// Before React 19 accessing `element.props.ref` will throw a warning and suggest using `element.ref`\n// After React 19 accessing `element.ref` does the opposite.\n// https://github.com/facebook/react/pull/28348\n//\n// Access the ref using the method that doesn't yield a warning.\nfunction getElementRef(element: React.ReactElement) {\n // React <=18 in DEV\n let getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get;\n let mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element as any).ref;\n }\n\n // React 19 in DEV\n getter = Object.getOwnPropertyDescriptor(element, 'ref')?.get;\n mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element.props as { ref?: React.Ref<unknown> }).ref;\n }\n\n // Not DEV\n return (element.props as { ref?: React.Ref<unknown> }).ref || (element as any).ref;\n}\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype SlottableElement = React.ReactElement<SlottableProps, SlottableComponent>;\n\nfunction isSlottable(\n child: React.ReactNode,\n): child is React.ReactElement<SlottableProps, typeof Slottable> {\n return (\n React.isValidElement(child) &&\n typeof child.type === 'function' &&\n '__radixId' in child.type &&\n child.type.__radixId === SLOTTABLE_IDENTIFIER\n );\n}\n\nconst REACT_LAZY_TYPE = Symbol.for('react.lazy');\n\ninterface LazyReactElement extends React.ReactElement {\n $$typeof: typeof REACT_LAZY_TYPE;\n _payload: PromiseLike<Exclude<React.ReactNode, PromiseLike<any>>>;\n}\n\nfunction isLazyComponent(element: React.ReactNode): element is LazyReactElement {\n return (\n element != null &&\n typeof element === 'object' &&\n '$$typeof' in element &&\n element.$$typeof === REACT_LAZY_TYPE &&\n '_payload' in element &&\n isPromiseLike(element._payload)\n );\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return typeof value === 'object' && value !== null && 'then' in value;\n}\n\nconst createSlotError = (ownerName: string) => {\n return `${ownerName} failed to slot onto its children. Expected a single React element child or \\`Slottable\\`.`;\n};\n\nconst createSlottableError = (ownerName: string) => {\n return `${ownerName} failed to slot onto its \\`Slottable\\`. Expected \\`Slottable\\` to receive a single React element child.`;\n};\n\nconst use: typeof React.use | undefined = (React as any)[' use '.trim().toString()];\n\nexport {\n Slot,\n Slottable,\n //\n Slot as Root,\n};\nexport type { SlotProps };\n","import * as React from 'react';\n\ntype PossibleRef<T> = React.Ref<T> | undefined;\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === 'function') {\n return ref(value);\n } else if (ref !== null && ref !== undefined) {\n ref.current = value;\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false;\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node);\n if (!hasCleanup && typeof cleanup == 'function') {\n hasCleanup = true;\n }\n return cleanup;\n });\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i];\n if (typeof cleanup == 'function') {\n cleanup();\n } else {\n setRef(refs[i], null);\n }\n }\n };\n }\n };\n}\n\n/**\n * A custom hook that composes multiple refs\n * Accepts callback refs and RefObject(s)\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return React.useCallback(composeRefs(...refs), refs);\n}\n\nexport { composeRefs, useComposedRefs };\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-full border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none touch-manipulation focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n xs: \"h-7 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 text-[0.8rem] has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-7 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport { useEffect, useState, type RefObject } from \"react\";\n\n/**\n * How long the box has to hold still before it counts as done. Long enough to\n * outlast the gap between two frames of an animation, short enough that\n * whatever was waiting on it is not left waiting.\n */\nconst SETTLE_MS = 120;\n\n/**\n * Whether an element is in the middle of changing size.\n *\n * For the things that correct themselves against a box, so they can hold off\n * while it moves. Correcting on every frame of a resize means aiming at a\n * target that moves every frame, and the numbers those corrections are made of\n * are whole pixels while the box between them is not, so each one lands a\n * fraction out from the last and the result shimmers rather than travels.\n *\n * False until something actually changes, and false again a moment after it\n * stops. The observer's opening report is the size the box already had rather\n * than a change to it, so it is not counted.\n */\nexport function useIsResizing(target: RefObject<HTMLElement | null>): boolean {\n const [isResizing, setIsResizing] = useState(false);\n\n useEffect(() => {\n const node = target.current;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n\n let settle = 0;\n let isOpeningReport = true;\n\n const observer = new ResizeObserver(() => {\n if (isOpeningReport) {\n isOpeningReport = false;\n return;\n }\n\n setIsResizing(true);\n window.clearTimeout(settle);\n settle = window.setTimeout(() => setIsResizing(false), SETTLE_MS);\n });\n\n observer.observe(node);\n return () => {\n window.clearTimeout(settle);\n observer.disconnect();\n };\n }, [target]);\n\n return isResizing;\n}\n","/**\n * Runs of consecutive messages from the same voice, so a burst of three reads\n * as one turn rather than as three separate arrivals. A run says who is\n * speaking once, at the top, and carries the time and the face at the foot;\n * everything in between is just a bubble.\n *\n * What joins what is the caller's rule, since the inbox and the widget hold\n * different shapes. All this does is walk the list and mark the edges.\n */\n\n/** How long a run stays open. A message later than this starts a new one. */\nconst RUN_MS = 5 * 60_000;\n\n/** Where a message sits in its run. Both true when it is a run of one. */\nexport type MessageGroup = {\n /** Carries the name. */\n isFirst: boolean;\n /** Carries the face and the time. */\n isLast: boolean;\n};\n\n/** A message standing on its own, for anywhere nothing is grouped. */\nexport const LONE_MESSAGE: MessageGroup = { isFirst: true, isLast: true };\n\n/**\n * Marks each message with where it sits in its run.\n *\n * `joinsPrevious` is only ever asked about neighbours, so it can compare\n * senders, timestamps, day labels, or whatever else the shape at hand knows.\n */\nexport function groupMessages<T>(\n messages: T[],\n joinsPrevious: (message: T, previous: T) => boolean,\n): MessageGroup[] {\n /** Whether the message at `index` carries on the one above it. */\n const continues = (index: number) => {\n const message = messages[index];\n const previous = messages[index - 1];\n if (message === undefined || previous === undefined) return false;\n return joinsPrevious(message, previous);\n };\n\n return messages.map((_, index) => ({\n isFirst: !continues(index),\n isLast: !continues(index + 1),\n }));\n}\n\n/**\n * Whether two messages are close enough together to belong to one run. A\n * missing timestamp means canned content with no clock behind it, which groups\n * on who is speaking alone.\n */\nexport function withinRun(previous?: number, next?: number): boolean {\n if (previous === undefined || next === undefined) return true;\n return next - previous <= RUN_MS;\n}\n","\"use client\";\n\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport { prefersReducedMotion } from \"./motion\";\n\nconst SHIFT_MS = 420;\n/** Matches --ease-spring. Kept in step by hand, since JS cannot read a theme token. */\nconst SHIFT_EASING = \"cubic-bezier(0.34, 1.45, 0.64, 1)\";\n\n/** How far the first message sits from the top of the stack, or null if there is none. */\nfunction topOfStack(element: HTMLElement | null): number | null {\n const first = element?.firstElementChild as HTMLElement | null;\n\n return first ? first.offsetTop : null;\n}\n\n/**\n * Slides a bottom anchored stack up as it grows, rather than letting it jump.\n *\n * A short thread sits on the composer, so a new message does not push the ones\n * above it down: it lifts them. Left alone that happens between two frames and\n * the whole conversation teleports.\n *\n * So it is measured instead. The first message's offset from the top of the\n * stack says how far everything moved, the stack is put straight back where it\n * was, and it travels the distance properly. Nothing moves once the thread is\n * long enough to scroll, because then the first message stops moving, the\n * distance is zero, and the scroller has it.\n *\n * The starting measurement is taken as the element attaches rather than in the\n * effect below, because the effect only runs when the message count changes. A\n * thread that arrives after a loading state would otherwise have nothing to\n * compare against until its second message, and the first one would jump.\n */\nexport function useStackShift(dependency: number) {\n const stack = useRef<HTMLDivElement | null>(null);\n const previousTop = useRef<number | null>(null);\n const watcher = useRef<ResizeObserver | null>(null);\n\n // Attaching also starts watching the stack for a change of size, and letting\n // go stops. Both here rather than in an effect, because the stack arrives\n // whenever the first message does: a thread that starts empty has nothing to\n // attach to on mount, and an effect that ran then would have found nothing\n // and never looked again.\n const ref = useCallback((node: HTMLDivElement | null) => {\n stack.current = node;\n previousTop.current = topOfStack(node);\n\n watcher.current?.disconnect();\n watcher.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n\n // The stack moves when the panel changes size too, and that is not a shift\n // worth animating: nothing arrived, the box around it grew. It does have to\n // be written down though. The effect below only runs on a new message, so\n // without this the measurement from before a resize is the one the next\n // message is compared against, and it travels the difference between two\n // panel heights on its way in.\n watcher.current = new ResizeObserver(() => {\n previousTop.current = topOfStack(node);\n });\n watcher.current.observe(node);\n }, []);\n\n useLayoutEffect(() => {\n const element = stack.current;\n if (!element) return;\n\n const top = topOfStack(element);\n const from = previousTop.current;\n previousTop.current = top;\n\n if (from === null || top === null) return;\n\n const distance = from - top;\n if (distance <= 0) return;\n if (prefersReducedMotion()) return;\n\n element.animate(\n [\n { transform: `translateY(${distance}px)` },\n { transform: \"translateY(0)\" },\n ],\n { duration: SHIFT_MS, easing: SHIFT_EASING },\n );\n }, [dependency]);\n\n return ref;\n}\n","/**\n * CSS carries `motion-reduce:` for anything animated in a stylesheet. The two\n * animations driven from JavaScript cannot read that, so they ask here.\n *\n * Guarded for the server, where there is no window to ask.\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\") return false;\n\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n","\"use client\";\n\nimport {\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type KeyboardEvent,\n} from \"react\";\nimport {\n AttachmentDraftChip,\n useAttachmentDrafts,\n useAttachmentTarget,\n} from \"@/components/attachments\";\nimport { ArrowUp, Check, EnvelopeSimple, Plus } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { TEXT_FIELD_SHELL } from \"@/components/ui/text-field\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { useTypingSignal } from \"@/hooks/use-typing-signal\";\nimport { cn } from \"@/lib/utils\";\nimport { PoweredByMedian } from \"./widget-badge\";\n\n/**\n * Loose on purpose: it decides whether the arrow lights up, not whether the\n * address is real. Only a mail server can answer that, and a visitor locked\n * out by a suspicious regex has nobody to appeal to.\n */\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/**\n * How the pill changes its mind.\n *\n * `translate` rather than `transform`, because that is the property Tailwind's\n * `translate-y-*` actually sets. Named as `transform` it transitions nothing:\n * the opacity eases and the travel lands in one frame, which is the jump this\n * was written to avoid.\n */\nconst SWAP =\n \"transition-[opacity,translate] duration-300 ease-out motion-reduce:transition-none\";\n\n/**\n * The notch coming up out of the composer, with the spring's small overshoot\n * at the top of the travel: it is a thing being pushed up from underneath, and\n * a thing pushed up passes where it lands.\n */\nconst RISE =\n \"transition-transform duration-450 ease-spring motion-reduce:transition-none\";\n\n/**\n * And going back into it. Quicker, and accelerating rather than easing off,\n * which is the difference between something leaving and something being taken\n * back: it is not travelling to a new place, it is going home.\n */\nconst SINK =\n \"transition-transform duration-250 ease-in motion-reduce:transition-none\";\n\n/**\n * The two phrases passing each other, both moving the same way, like a word on\n * a wheel. No fade in it: two things at half opacity on top of each other is\n * what makes a swap look like a smudge.\n *\n * A pure deceleration rather than the spring above, because this one runs\n * inside a box exactly one line tall. Anything that overshoots its landing has\n * its ascenders shaved off on the way past.\n */\nconst ROLL =\n \"transition-transform duration-350 ease-out-quint motion-reduce:transition-none\";\n\n/**\n * How long the tab holds its answer before tucking away. Long enough to read\n * two words, and short enough that nobody is waiting on it: the box to write\n * in is already underneath by then.\n */\nconst SAVED_MS = 1200;\n\n/**\n * One pill at the foot of the panel: add on the left, write in the middle,\n * send on the right. The shape is round rather than square so the composer\n * reads as a control rather than as another message, and it holds that shape\n * as the box grows because the corners are already as round as they get.\n *\n * Enter sends, shift and enter starts a new line. Files arrive from the plus\n * button, from a drop anywhere along the foot of the panel, or from a paste,\n * which is how anybody who has just taken a screenshot expects to send it.\n * They stack above the pill as chips, each with a thumbnail and a way out, and\n * one that is too big says so and holds the send button until it goes. Nothing\n * is uploaded yet.\n *\n * The draft clears when the send lands rather than when the button goes down,\n * so a send that fails costs a retry, not a retype.\n *\n * Before a first message, the same pill can ask who they are instead: a tab\n * rises from behind its top edge and says what is being asked, while the\n * writing box makes way for an email field underneath. Nothing remounts, so\n * both movements are transitions rather than things appearing.\n *\n * An answer is taken here rather than waited on. The tab says it has it, the\n * box to write in comes back under it, and the caret is already there before\n * the tab has finished tucking away, so a phone keeps the keyboard it has\n * instead of losing it and asking for it again.\n */\nexport function WidgetComposer({\n onSend,\n onTypingChange,\n askForEmail = false,\n onSubmitEmail,\n placeholder = \"Type your message...\",\n showBadge = true,\n isSending = false,\n}: {\n /** Awaited if it returns a promise. A rejection keeps the draft in place. */\n onSend?: (body: string, files: File[]) => unknown;\n /** Best effort, throttled here. */\n onTypingChange?: (isTyping: boolean) => unknown;\n /**\n * Ask for an email before a first message. The pill asks instead of the\n * composer: no attachments, no typing dots, nothing to send but the\n * address.\n */\n askForEmail?: boolean;\n /** Called with the address once it looks like one. */\n onSubmitEmail?: (email: string) => void;\n placeholder?: string;\n /** The \"Powered by Median\" line. Hosts on a paid plan can turn it off. */\n showBadge?: boolean;\n isSending?: boolean;\n}) {\n const [draft, setDraft] = useState(\"\");\n const [email, setEmail] = useState(\"\");\n // Where the notch has got to. `none` is the question, `saved` is the word\n // that answers it, and `settled` is that same word on its way down: the\n // notch goes back to asking only if the question itself comes back.\n const [answer, setAnswer] = useState<\"none\" | \"saved\" | \"settled\">(\"none\");\n const fileInputRef = useRef<HTMLInputElement>(null);\n const draftRef = useRef<HTMLTextAreaElement>(null);\n const attachments = useAttachmentDrafts();\n const target = useAttachmentTarget({ onFiles: attachments.add });\n const typing = useTypingSignal(onTypingChange);\n\n const hasContent = draft.trim().length > 0 || attachments.drafts.length > 0;\n const canSend = hasContent && !attachments.hasBlocker && !isSending;\n\n // True once what they typed could be an address. It decides the arrow, not\n // whether the address is real.\n const isValid = EMAIL_PATTERN.test(email.trim());\n\n // A question that has come back outranks an answer already given, which is\n // `medianSupport.reset()` and nothing else: the stored address went, so the\n // notch has something to ask again rather than something to hold. Worked out\n // here rather than written back into the state, since the two facts are the\n // prop and the beat, and this is only what they add up to.\n const stage = askForEmail && answer === \"settled\" ? \"none\" : answer;\n\n // What the notch says, and whether it is up at all. It holds the word it\n // answered with the whole way down: a notch that changed its mind back to\n // the question as it left would be asking on its way out the door.\n const isAsking = askForEmail && stage === \"none\";\n const isSaved = stage !== \"none\";\n const showTab = isAsking || stage === \"saved\";\n\n function submitEmail() {\n if (!isValid || !onSubmitEmail) return;\n setAnswer(\"saved\");\n onSubmitEmail(email.trim());\n }\n\n // The beat itself. Nothing waits on it: the composer is already back\n // underneath, so this only decides how long the word stays up before the\n // notch takes it down.\n useEffect(() => {\n if (answer !== \"saved\") return;\n const timer = setTimeout(() => setAnswer(\"settled\"), SAVED_MS);\n return () => clearTimeout(timer);\n }, [answer]);\n\n // Straight on to the message, since that is what the address was in the way\n // of. On a phone it also keeps the keyboard where it is: sending it away and\n // asking for it back is the whole screen bouncing twice for nothing.\n // `preventScroll`, because the browser's idea of bringing a field into view\n // is to scroll a page that is holding a sheet still.\n useEffect(() => {\n if (answer !== \"saved\" || askForEmail) return;\n draftRef.current?.focus({ preventScroll: true });\n }, [answer, askForEmail]);\n\n async function send() {\n if (!canSend) return;\n // Quiet locally only: the message itself is the stop, server side.\n typing.settle();\n\n const body = draft.trim();\n try {\n await onSend?.(body, attachments.files);\n } catch {\n // The notice above the composer says why it failed. The draft stays\n // where it was written.\n return;\n }\n\n // Only what was sent is cleared: anything typed while the message was in\n // flight is the next draft, not part of the one that just went.\n setDraft((now) => (now.trim() === body ? \"\" : now));\n attachments.clear();\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {\n if (event.key !== \"Enter\") return;\n // Shift for a new line, and never while an IME is open, where Enter is\n // accepting a candidate rather than finishing the message.\n if (event.shiftKey || event.nativeEvent.isComposing) return;\n\n event.preventDefault();\n void send();\n }\n\n function handlePick(event: ChangeEvent<HTMLInputElement>) {\n if (event.target.files?.length) attachments.add(event.target.files);\n // Cleared so picking the same file twice in a row still fires a change.\n event.target.value = \"\";\n }\n\n return (\n // The whole foot of the panel takes a drop, not just the pill: the pill is\n // a thin thing to aim a file at, and the chips that appear sit up here\n // anyway. Paste rides on the same element, so it is caught wherever the\n // caret happens to be inside the composer. None of that while the email\n // is asked for: there is no message yet to attach anything to.\n <div\n className=\"flex shrink-0 flex-col gap-1.5 px-3 pt-1 pb-3\"\n {...(isAsking ? {} : target.targetProps)}\n >\n {!isAsking && attachments.drafts.length > 0 && (\n <ul className=\"flex flex-wrap gap-1.5 px-1\">\n {attachments.drafts.map((item) => (\n <li key={item.id} className=\"min-w-0\">\n <AttachmentDraftChip\n draft={item}\n onRemove={() => attachments.remove(item.id)}\n />\n </li>\n ))}\n </ul>\n )}\n\n <div className=\"relative\">\n {/* The slot the notch lives in: the full width of the pill, ending two\n pixels inside its top edge, and clipped.\n\n That clip is the whole trick. The notch does not fade and does not\n need to: it slides down the height of itself and the slot cuts it\n off exactly where the pill begins, so it goes into the composer\n rather than off it. Coming back it comes up out of the same seam.\n The two pixels are what guarantee no hairline of daylight between\n the two shapes, and they are behind the pill, which paints over\n them. */}\n <div\n aria-hidden={!showTab}\n inert={!showTab}\n // The headroom is for the spring: the notch passes where it lands on\n // the way up, and a clip tight to its resting height would flatten\n // the top edge for those few frames.\n className=\"pointer-events-none absolute inset-x-0 bottom-full z-0 -mb-0.5 flex items-end justify-center overflow-hidden pt-2\"\n >\n {/* Square at the bottom and no bottom hairline: that edge is the\n seam with the pill, not an edge of its own. */}\n <div\n className={cn(\n \"grid max-w-[calc(100%-2rem)] select-none\",\n \"rounded-t-2xl border border-b-0 bg-muted px-3 pt-1.5 pb-2 text-sm text-muted-foreground\",\n showTab ? RISE : SINK,\n !showTab && \"translate-y-full\",\n )}\n >\n {/* One line tall and clipped, so the phrases roll through it.\n\n Both share the cell, so the notch is as wide as the longer of\n the two and holds that width while they change: the words move\n inside a shape that does not. Each is centred, so the short one\n sits in the middle of the notch rather than off to its left. */}\n <span className=\"grid overflow-hidden\">\n <span\n aria-hidden={isSaved}\n className={cn(\n \"col-start-1 row-start-1 flex items-center gap-2 justify-self-center\",\n ROLL,\n isSaved && \"-translate-y-full\",\n )}\n >\n <EnvelopeSimple aria-hidden className=\"size-4 shrink-0\" />\n <span className=\"truncate\">Enter your email</span>\n </span>\n\n <span\n aria-hidden={!isSaved}\n className={cn(\n \"col-start-1 row-start-1 flex items-center gap-2 justify-self-center\",\n ROLL,\n !isSaved && \"translate-y-full\",\n )}\n >\n <Check aria-hidden className=\"size-4 shrink-0\" />\n <span className=\"truncate\">Saved</span>\n </span>\n </span>\n </div>\n </div>\n\n {/* The same surface as the panel behind it, so the composer is a shape\n rather than a slab. Painted rather than left transparent, since it\n is what hides the foot of the tab. A grid with both composers in\n one cell: they sit exactly on top of each other, same height, so\n the swap moves nothing. Whichever one is waiting wears `inert`,\n which takes it out of the tab order and the accessibility tree\n along with the pointer events. */}\n <div\n className={cn(\n TEXT_FIELD_SHELL,\n \"relative z-10 grid items-center rounded-3xl bg-card p-1.5 transition-colors dark:bg-card\",\n // The pill lights up rather than the whole foot of the panel, so a\n // file being dragged in points at the thing it is about to join.\n !isAsking &&\n target.isDropTarget &&\n \"border-ring bg-muted/60 ring-1 ring-ring dark:bg-muted/60\",\n )}\n >\n {/* The message half. Both halves travel down together, the same way\n the notch above them goes, so an answer settles the whole thing\n rather than sending three pieces of it in three directions. */}\n <div\n aria-hidden={isAsking}\n inert={isAsking}\n className={cn(\n \"col-start-1 row-start-1 flex items-end gap-1.5\",\n SWAP,\n isAsking && \"-translate-y-1 opacity-0 pointer-events-none\",\n )}\n >\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n tabIndex={-1}\n onChange={handlePick}\n className=\"sr-only\"\n />\n <WidgetButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Add an attachment\"\n className=\"rounded-full text-muted-foreground hover:rotate-90 motion-reduce:hover:rotate-0\"\n >\n <Plus />\n </WidgetButton>\n\n <Textarea\n ref={draftRef}\n rows={1}\n value={draft}\n onChange={(event) => {\n setDraft(event.target.value);\n typing.ping();\n }}\n onKeyDown={handleKeyDown}\n // The same swap the inbox does, so both ends of a conversation\n // confirm a drop the same way.\n placeholder={\n target.isDropTarget ? \"Drop to attach\" : placeholder\n }\n aria-label=\"Message\"\n // 16px on phones, and in pixels: any focused field smaller than\n // that makes iOS zoom the host's whole page in, and a host who has\n // resized their root rem would smuggle the zoom back past `text-base`.\n className=\"max-h-32 min-h-8 flex-1 px-1 py-1.5 max-sm:text-[16px]\"\n />\n\n {/* Pops in as the first character lands, rather than sitting there\n greyed out waiting to be earned. */}\n <WidgetButton\n type=\"button\"\n size=\"icon\"\n disabled={!canSend}\n onClick={() => void send()}\n aria-label=\"Send message\"\n className={cn(\n \"rounded-full\",\n canSend\n ? \"scale-100 opacity-100\"\n : \"scale-90 opacity-40 motion-reduce:scale-100\",\n )}\n >\n <ArrowUp />\n </WidgetButton>\n </div>\n\n {/* The answer half. */}\n <div\n aria-hidden={!isAsking}\n inert={!isAsking}\n className={cn(\n \"col-start-1 row-start-1 flex items-center gap-1.5\",\n SWAP,\n !isAsking && \"pointer-events-none translate-y-1 opacity-0\",\n )}\n >\n <input\n type=\"email\"\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n onKeyDown={(event) => {\n if (event.key !== \"Enter\" || event.nativeEvent.isComposing)\n return;\n event.preventDefault();\n submitEmail();\n }}\n placeholder=\"you@example.com\"\n aria-label=\"Email address\"\n autoComplete=\"email\"\n spellCheck={false}\n // The same rule as the message field, for the same reason.\n className=\"h-8 min-w-0 flex-1 px-1 outline-none placeholder:text-muted-foreground max-sm:text-[16px]\"\n />\n\n <WidgetButton\n type=\"button\"\n size=\"icon\"\n disabled={!isValid}\n onClick={() => submitEmail()}\n aria-label=\"Continue with this email\"\n className={cn(\n \"rounded-full\",\n isValid\n ? \"scale-100 opacity-100\"\n : \"scale-90 opacity-40 motion-reduce:scale-100\",\n )}\n >\n <ArrowUp />\n </WidgetButton>\n </div>\n </div>\n </div>\n\n {showBadge && <PoweredByMedian />}\n </div>\n );\n}\n","import { forwardRef, type ImgHTMLAttributes } from \"react\";\n\n/**\n * Stands in for `next/image` when the widget is bundled for npm, via the\n * `paths` entry in this package's tsconfig. The app renders avatars and\n * marks through the framework's image pipeline; the package has no framework,\n * and everything in the widget's closure is an avatar, a mark, or an object\n * URL that never left the browser, all of which a plain img carries the same.\n *\n * Next-only props are swallowed here so they do not land on a DOM element\n * that has never heard of them.\n */\ntype NextOnlyProps = {\n unoptimized?: boolean;\n priority?: boolean;\n quality?: number | string;\n placeholder?: string;\n blurDataURL?: string;\n fill?: boolean;\n loader?: unknown;\n};\n\nconst Image = forwardRef<\n HTMLImageElement,\n ImgHTMLAttributes<HTMLImageElement> & NextOnlyProps\n>(function Image(\n {\n unoptimized: _unoptimized,\n priority: _priority,\n quality: _quality,\n placeholder: _placeholder,\n blurDataURL: _blurDataURL,\n fill: _fill,\n loader: _loader,\n ...props\n },\n ref,\n) {\n return <img ref={ref} {...props} />;\n});\n\nexport default Image;\n","\"use client\";\n\nimport Image from \"next/image\";\n\n/**\n * One picture, drawn by whichever loader is actually allowed to fetch it.\n *\n * A file we hold goes through next/image, which is what keeps a four megabyte\n * screenshot from arriving whole inside a tile the size of a stamp. A linked\n * one lives on somebody else's machine, and the optimizer is deliberately not\n * allowed to fetch arbitrary hosts: `/_next/image` is public and billed per\n * distinct source, so an open host list is somebody else's loop running up\n * our bill. Those are drawn plainly instead.\n *\n * No referrer goes with an outside fetch. Opening a bug report should not\n * tell whoever is hosting the picture which page it was opened from.\n */\nexport function AttachmentImage({\n src,\n alt,\n external = false,\n width,\n height,\n className,\n onError,\n}: {\n src: string;\n alt: string;\n /** True for an address we do not serve, which changes how it is loaded. */\n external?: boolean;\n width: number;\n height: number;\n className?: string;\n onError?: () => void;\n}) {\n if (external) {\n return (\n // eslint-disable-next-line @next/next/no-img-element -- an outside host the optimizer is not allowed to fetch.\n <img\n src={src}\n alt={alt}\n width={width}\n height={height}\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n onError={onError}\n draggable={false}\n className={className}\n />\n );\n }\n\n return (\n <Image\n src={src}\n alt={alt}\n width={width}\n height={height}\n onError={onError}\n draggable={false}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { File, ImageSquare, Play, WarningCircle, X } from \"@/components/icons\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport type { AttachmentDraft } from \"./use-attachment-drafts\";\n\nconst KIND_ICONS = {\n image: ImageSquare,\n video: Play,\n file: File,\n};\n\n/**\n * One staged file, with a thumbnail where there is one and a way out.\n *\n * `max-w-full` so the chip gives up its preferred width inside something\n * narrow, like the support widget, rather than pushing out of the box.\n */\nexport function AttachmentDraftChip({\n draft,\n onRemove,\n className,\n}: {\n draft: AttachmentDraft;\n onRemove: () => void;\n className?: string;\n}) {\n const hasError = draft.error !== null;\n const Glyph = hasError ? WarningCircle : KIND_ICONS[draft.kind];\n\n return (\n <div\n className={cn(\n \"flex w-48 max-w-full items-center gap-2 rounded-lg border bg-card/60 p-1.5\",\n \"animate-in fade-in-0 zoom-in-95 duration-200 ease-out motion-reduce:animate-none\",\n hasError && \"border-destructive/40\",\n className,\n )}\n >\n {draft.previewUrl ? (\n // Object URLs cannot be optimised, and there is nothing to optimise:\n // the file has not left the browser.\n <Image\n src={draft.previewUrl}\n alt=\"\"\n width={64}\n height={64}\n unoptimized\n className=\"size-8 shrink-0 rounded-md object-cover\"\n />\n ) : (\n <span className=\"grid size-8 shrink-0 place-items-center rounded-md bg-muted\">\n <Glyph\n className={cn(\n \"size-4\",\n hasError ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n />\n </span>\n )}\n\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <p className=\"truncate text-xs font-medium\">{draft.name}</p>\n <p\n className={cn(\n \"truncate text-xs\",\n hasError ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {draft.error ?? draft.size}\n </p>\n </div>\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n onClick={onRemove}\n aria-label={`Remove ${draft.name}`}\n className=\"shrink-0 rounded-full text-muted-foreground\"\n >\n <X />\n </Button>\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { AttachmentKind } from \"./types\";\n\nconst MAX_BYTES = 25 * 1024 * 1024;\n\n/**\n * Types the backend turns away, checked here too so the chip says so before\n * anything is uploaded rather than after the send fails. The list that counts\n * is `UNSAFE_ATTACHMENT_TYPES` in the backend's `shared/support.ts`; this one\n * is the same list wearing a friendlier moment.\n */\nconst UNSAFE_TYPES = [\n \"text/html\",\n \"application/xhtml+xml\",\n \"image/svg+xml\",\n \"text/xsl\",\n \"application/xslt+xml\",\n];\n\nfunction isUnsafeType(type: string): boolean {\n return UNSAFE_TYPES.includes(type.split(\";\")[0].trim().toLowerCase());\n}\n\nexport type AttachmentDraft = {\n id: string;\n /** The file itself, kept so a caller can hand it on once it is sent. */\n file: File;\n name: string;\n size: string;\n kind: AttachmentKind;\n /** An object URL for pictures, so the chip can show what was picked. */\n previewUrl: string | null;\n /** Set when the file cannot be sent. Shown on the chip in place of the size. */\n error: string | null;\n};\n\nlet nextDraftId = 0;\n\n/**\n * Bytes, written the way a person would say them. Exported because whoever\n * receives a sent file has to label it the same way the chip that staged it\n * did, or the same file changes size on its way into the thread.\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n\n const units = [\"KB\", \"MB\", \"GB\"];\n let value = bytes / 1024;\n let unit = 0;\n\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit += 1;\n }\n\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${units[unit]}`;\n}\n\n/** The kinds in the plural, for the line on a chip that has to say no. */\nconst KIND_NAMES: Record<AttachmentKind, string> = {\n image: \"pictures\",\n video: \"videos\",\n file: \"files\",\n};\n\n/** What a file is, from its MIME type. Anything unrecognised is just a file. */\nexport function attachmentKindOf(type: string): AttachmentKind {\n if (type.startsWith(\"image/\")) return \"image\";\n if (type.startsWith(\"video/\")) return \"video\";\n return \"file\";\n}\n\nfunction release(draft: AttachmentDraft) {\n if (draft.previewUrl) URL.revokeObjectURL(draft.previewUrl);\n}\n\n/**\n * Files staged on a composer, from either the picker or a drop. Shared by the\n * agent's composer in the inbox, the visitor's in the support widget, and the\n * feedback panel, so all three agree on what is too big and what a size looks\n * like written down.\n *\n * Nothing is uploaded: a draft is checked, previewed and then thrown away when\n * the message is sent. A file that fails the check stays in the list wearing\n * its reason, so it gets read rather than silently dropped.\n *\n * `files` hands back the originals in the same order, which is what a caller\n * passes on once there is somewhere to send them.\n */\nexport function useAttachmentDrafts({\n accept,\n max,\n}: {\n /**\n * The one kind this composer takes. Anything else still appears, wearing\n * the reason it cannot go, because a picture that vanished on the way into\n * the box reads as the box being broken.\n */\n accept?: AttachmentKind;\n /** The most that may be staged at once. Unbounded when left off. */\n max?: number;\n} = {}) {\n const [drafts, setDrafts] = useState<AttachmentDraft[]>([]);\n\n // Object URLs outlive the elements that used them, so any still open when\n // the composer goes away get revoked on the way out.\n const draftsRef = useRef(drafts);\n useEffect(() => {\n draftsRef.current = drafts;\n }, [drafts]);\n useEffect(() => () => draftsRef.current.forEach(release), []);\n\n function add(files: FileList | File[]) {\n const picked = Array.from(files).map((file, index): AttachmentDraft => {\n const isTooBig = file.size > MAX_BYTES;\n const isUnsafe = isUnsafeType(file.type);\n const kind = attachmentKindOf(file.type);\n const isWrongKind = accept !== undefined && kind !== accept;\n const isOverCap = max !== undefined && drafts.length + index >= max;\n const error = isTooBig\n ? `Larger than the ${formatFileSize(MAX_BYTES)} limit`\n : isUnsafe\n ? \"This kind of file cannot be sent\"\n : isWrongKind\n ? `Only ${KIND_NAMES[accept]} can go here`\n : isOverCap\n ? `Only ${max} at a time`\n : null;\n\n return {\n id: `draft-${(nextDraftId += 1)}`,\n file,\n name: file.name,\n size: formatFileSize(file.size),\n kind,\n previewUrl:\n kind === \"image\" && error === null ? URL.createObjectURL(file) : null,\n error,\n };\n });\n\n setDrafts([...drafts, ...picked]);\n }\n\n function remove(id: string) {\n const going = drafts.find((draft) => draft.id === id);\n if (going) release(going);\n setDrafts(drafts.filter((draft) => draft.id !== id));\n }\n\n function clear() {\n drafts.forEach(release);\n setDrafts([]);\n }\n\n return {\n drafts,\n add,\n remove,\n clear,\n /** The originals, in the order they were picked. */\n files: drafts.map((draft) => draft.file),\n /** True while something in the list cannot be sent. */\n hasBlocker: drafts.some((draft) => draft.error !== null),\n /** True once the cap is reached, for a picker that should go quiet. */\n isFull: max !== undefined && drafts.length >= max,\n };\n}\n","\"use client\";\n\nimport { useRef, useState, type ClipboardEvent, type DragEvent } from \"react\";\n\n/**\n * The two ways a file arrives that are not the picker: dragged onto the\n * composer, or pasted into it. Both are how somebody who has just taken a\n * screenshot expects to send it, and neither should need the plus button.\n *\n * Shared by the inbox and the widget, so a screenshot lands the same way on\n * both sides of a conversation. This only notices and collects; what becomes\n * of the files is the caller's business, which is what lets an internal note\n * turn them away.\n */\nexport function useAttachmentTarget({\n onFiles,\n disabled = false,\n}: {\n onFiles: (files: File[]) => void;\n /** Somewhere a file is not welcome, like a note the backend keeps to words. */\n disabled?: boolean;\n}) {\n const [isDropTarget, setIsDropTarget] = useState(false);\n\n // Dragging over a child element fires leave on the parent, so the highlight\n // counts its way in and out rather than trusting a single leave to mean the\n // pointer has actually gone.\n const depth = useRef(0);\n\n function handleDragEnter(event: DragEvent<HTMLElement>) {\n // Dragging a selection of text across the page is not an attachment.\n if (disabled || !event.dataTransfer.types.includes(\"Files\")) return;\n depth.current += 1;\n setIsDropTarget(true);\n }\n\n function handleDragLeave() {\n depth.current = Math.max(0, depth.current - 1);\n if (depth.current === 0) setIsDropTarget(false);\n }\n\n function handleDrop(event: DragEvent<HTMLElement>) {\n event.preventDefault();\n depth.current = 0;\n setIsDropTarget(false);\n if (disabled) return;\n\n const files = Array.from(event.dataTransfer.files);\n if (files.length > 0) onFiles(files);\n }\n\n function handlePaste(event: ClipboardEvent<HTMLElement>) {\n if (disabled) return;\n\n // Ordinary text carries no files, and is left alone entirely: caret,\n // selection, undo history and all. A screenshot does carry one, and\n // taking it means the markup the clipboard came with does not also end\n // up in the message.\n const files = Array.from(event.clipboardData.files);\n if (files.length === 0) return;\n\n event.preventDefault();\n onFiles(files);\n }\n\n return {\n /** True while something is being dragged over it, for the highlight. */\n isDropTarget,\n /** Spread onto whatever counts as the target. */\n targetProps: {\n onDragEnter: handleDragEnter,\n onDragLeave: handleDragLeave,\n // Without this the browser refuses the drop and opens the file instead,\n // taking the page, and whatever was being written, with it.\n onDragOver: (event: DragEvent<HTMLElement>) => event.preventDefault(),\n onDrop: handleDrop,\n onPaste: handlePaste,\n },\n };\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * The widget's own button, deliberately forked from `ui/button`.\n *\n * The widget ships on other people's sites, so its look is a contract with\n * them, not with our chrome. When the app restyles its buttons, the widget\n * must not come along for the ride; this file is where it stays put.\n */\nconst widgetButtonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-7 rounded-[min(var(--radius-md),12px)]\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction WidgetButton({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof widgetButtonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : \"button\";\n\n return (\n <Comp\n data-slot=\"widget-button\"\n data-variant={variant}\n data-size={size}\n className={cn(widgetButtonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { WidgetButton, widgetButtonVariants };\n","/**\n * The shell every text field wears: surface, border, and focus outline. Kept\n * in one place so a single line box and a multi line composer cannot drift\n * into different colours.\n *\n * `focus-within` rather than `focus-visible`, so it reads the same whether the\n * element wearing it is the field itself or the box around one. For a text\n * field the two fire together anyway.\n */\nexport const TEXT_FIELD_SHELL = [\n \"rounded-lg border border-input bg-transparent text-sm max-sm:text-base transition-[color,box-shadow] outline-none dark:bg-input/30\",\n \"placeholder:text-muted-foreground\",\n // Focus recolours the hairline rather than adding a ring on top of it, so\n // the outline stays exactly 1px and nothing swells on click.\n \"focus-within:border-ring\",\n \"aria-invalid:border-destructive\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n].join(\" \");\n","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Grows with its content up to `max-h`, courtesy of `field-sizing-content`.\n * Browsers without it fall back to the `rows` the caller sets.\n */\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"field-sizing-content w-full resize-none bg-transparent text-sm outline-none max-sm:text-base\",\n \"placeholder:text-muted-foreground\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Textarea };\n","\"use client\";\n\nimport { useCallback, useEffect, useRef } from \"react\";\n\n/** Refreshed well inside the server's TTL, without spamming a mutation. */\nconst REFRESH_MS = 2500;\n/**\n * This long without a keystroke means the sentence stalled. Generous on\n * purpose: dots that vanish at every thinking pause and pop back at the next\n * key read as flicker, not presence.\n */\nconst IDLE_MS = 8000;\n\n/**\n * Turns keystrokes into a calm typing signal: `ping` on every change sends\n * \"typing\" at most every couple of seconds, going quiet after a pause, on\n * `stop`, and on unmount.\n *\n * `settle` goes quiet locally without announcing it. That is for sending:\n * the message itself is the stop, and racing a \"stopped typing\" mutation in\n * ahead of it would delete the pending bubble the reply is about to fill,\n * which is the difference between a bubble that morphs and one that flashes.\n *\n * Failures are swallowed on purpose. A typing indicator is decoration, and\n * decoration does not get to put errors in front of anyone.\n */\nexport function useTypingSignal(onChange?: (isTyping: boolean) => unknown) {\n // Held in a ref so ping and stop keep stable identities while the caller\n // re-renders with fresh closures.\n const onChangeRef = useRef(onChange);\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n const isTypingRef = useRef(false);\n const lastSentRef = useRef(0);\n const idleTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const send = useCallback((isTyping: boolean) => {\n try {\n void Promise.resolve(onChangeRef.current?.(isTyping)).catch(() => {});\n } catch {\n // Decorative; see above.\n }\n }, []);\n\n /** Goes quiet without telling anyone. The send that follows says it. */\n const settle = useCallback(() => {\n if (idleTimer.current) clearTimeout(idleTimer.current);\n idleTimer.current = null;\n isTypingRef.current = false;\n lastSentRef.current = 0;\n }, []);\n\n const stop = useCallback(() => {\n const wasTyping = isTypingRef.current;\n settle();\n if (wasTyping) send(false);\n }, [send, settle]);\n\n const ping = useCallback(() => {\n if (idleTimer.current) clearTimeout(idleTimer.current);\n idleTimer.current = setTimeout(stop, IDLE_MS);\n\n const now = Date.now();\n if (!isTypingRef.current || now - lastSentRef.current > REFRESH_MS) {\n isTypingRef.current = true;\n lastSentRef.current = now;\n send(true);\n }\n }, [send, stop]);\n\n useEffect(() => () => stop(), [stop]);\n\n return { ping, stop, settle };\n}\n","/**\n * The Median marks, as geometry rather than as files.\n *\n * The same brand components render inside the widget package, which is\n * installed into someone else's app and has no way to reach our public\n * directory. Keeping the paths here is what lets a mark draw itself\n * anywhere: in the app, in the npm bundle, and through a CSS mask, all from\n * one copy.\n *\n * `public/` still carries the SVGs, for the things outside the app that want\n * a file to point at: favicons, OG images, the docs site.\n */\n\n/** What the artwork is drawn in. Dark mode inverts it rather than restating it. */\nexport const BRAND_INK = \"#191919\";\n\n/** The mark, in its own square box. */\nexport const LOGO = {\n viewBox: \"0 0 58 58\",\n paths: [\n \"M48.9788 0H8.97304C4.01742 0 0 4.11877 0 9.22508V20.7384C0 21.5573 0.577354 22.0631 1.37122 21.8223L46.068 10.1885C47.2227 9.87541 47.8963 10.7666 47.5595 11.9228L35.8922 56.5789C35.6757 57.446 36.2049 58 37.0709 58H48.7383C53.7661 58 58 53.6885 58 48.799V9.22508C58 4.11877 53.9585 0 48.9788 0Z\",\n \"M0 26.976V49.0151C0 53.9287 3.99336 57.9993 8.97304 57.9993H30.8884C31.7545 57.9993 32.1634 57.2767 31.9229 56.4337L28.579 44.3182C28.4347 43.8606 28.4587 43.4511 28.6993 42.9935L39.3803 21.5084C39.9818 20.3041 38.5384 19.4129 37.6723 20.3282L10.4164 47.3531C9.64662 48.1721 8.41974 47.2327 8.85276 46.1488L13.9527 30.9744C14.2173 30.1073 13.8565 29.2642 12.8221 29.0716L1.4915 25.9644C0.60141 25.6513 0 26.133 0 26.976Z\",\n ],\n} as const;\n\n/** The word, sharing the mark's 58 unit height so the two set together. */\nexport const WORDMARK = {\n viewBox: \"0 0 253 58\",\n width: 253,\n height: 58,\n paths: [\n \"M10.1999 2.52174L29.0138 35.0522L47.8637 2.52174H57.8834V56.9913H47.7916V21.1106L33.1586 46.2199H24.6527L9.98362 20.9665V56.9913H0V2.52174H10.1999Z\",\n \"M102.616 40.6H71.5115C72.1363 43.4099 73.5058 45.5834 75.6203 47.1205C77.7588 48.6335 80.3778 49.3901 83.4775 49.3901C85.664 49.3901 87.6823 48.9458 89.5325 48.0571C91.4067 47.1445 92.8363 45.9317 93.8215 44.4186L101.57 49.318C99.8165 51.9598 97.3176 54.0613 94.0738 55.6224C90.83 57.2075 87.2979 58 83.4775 58C79.2966 58 75.5362 57.0874 72.1963 55.2621C68.8805 53.4609 66.2975 50.9752 64.4473 47.805C62.6212 44.6108 61.7081 41.0563 61.7081 37.1416C61.7081 34.2116 62.2247 31.4617 63.2579 28.8919C64.3152 26.2981 65.7448 24.0766 67.5469 22.2273C69.349 20.3781 71.5235 18.9251 74.0705 17.8683C76.6175 16.7876 79.3326 16.2472 82.216 16.2472C88.1509 16.2472 93.0526 18.1085 96.9211 21.8311C100.814 25.5536 102.76 30.3329 102.76 36.1689C102.76 36.8654 102.712 38.3424 102.616 40.6ZM71.5115 33.5031H93.0646C92.8003 30.8373 91.695 28.6998 89.7487 27.0907C87.8265 25.4816 85.3396 24.677 82.2881 24.677C79.5969 24.677 77.2662 25.4576 75.2959 27.0186C73.3497 28.5797 72.0882 30.7412 71.5115 33.5031Z\",\n \"M136.608 1.54907H146.735V56.9913H136.608V51.3714C135.286 53.5329 133.508 55.1781 131.273 56.3068C129.039 57.4356 126.516 58 123.705 58C118.202 58 113.601 55.9946 109.901 51.9839C106.2 47.9731 104.35 43.0257 104.35 37.1416C104.326 34.2836 104.807 31.5578 105.792 28.964C106.777 26.3702 108.122 24.1366 109.828 22.2634C111.558 20.366 113.625 18.877 116.028 17.7963C118.454 16.7155 121.013 16.1992 123.705 16.2472C126.516 16.2472 129.039 16.8116 131.273 17.9404C133.508 19.0451 135.286 20.6663 136.608 22.8037V1.54907ZM133.436 45.8957C135.55 43.6861 136.608 40.7681 136.608 37.1416C136.608 33.5151 135.55 30.5971 133.436 28.3876C131.345 26.154 128.642 25.0373 125.326 25.0373C122.011 25.0373 119.271 26.1901 117.109 28.4957C115.042 30.7772 114.009 33.6592 114.009 37.1416C114.009 40.6 115.067 43.482 117.181 45.7876C119.295 48.0692 122.011 49.2099 125.326 49.2099C128.642 49.2099 131.345 48.1052 133.436 45.8957Z\",\n \"M150.957 5.98012C150.957 4.29896 151.557 2.88199 152.759 1.72919C153.984 0.576398 155.486 0 157.264 0C159.018 0 160.496 0.588406 161.697 1.76522C162.923 2.91801 163.535 4.32298 163.535 5.98012C163.535 7.70932 162.935 9.1383 161.733 10.2671C160.556 11.3959 159.066 11.9602 157.264 11.9602C155.462 11.9602 153.96 11.3959 152.759 10.2671C151.557 9.1383 150.957 7.70932 150.957 5.98012ZM162.274 17.2919V56.9913H152.218V17.2919H162.274Z\",\n \"M198.176 17.2919H208.304V56.9913H198.176V51.3714C196.854 53.5329 195.076 55.1781 192.842 56.3068C190.607 57.4356 188.084 58 185.273 58C179.77 58 175.169 55.9946 171.469 51.9839C167.768 47.9731 165.918 43.0257 165.918 37.1416C165.894 34.2836 166.375 31.5578 167.36 28.964C168.345 26.3702 169.691 24.1366 171.397 22.2634C173.127 20.366 175.193 18.877 177.596 17.7963C180.023 16.7155 182.582 16.1992 185.273 16.2472C188.084 16.2472 190.607 16.8116 192.842 17.9404C195.076 19.0451 196.854 20.6663 198.176 22.8037V17.2919ZM195.004 45.8957C197.119 43.6861 198.176 40.7681 198.176 37.1416C198.176 33.5151 197.119 30.5971 195.004 28.3876C192.914 26.154 190.211 25.0373 186.895 25.0373C183.579 25.0373 180.84 26.1901 178.677 28.4957C176.611 30.7772 175.578 33.6592 175.578 37.1416C175.578 40.6 176.635 43.482 178.749 45.7876C180.864 48.0692 183.579 49.2099 186.895 49.2099C190.211 49.2099 192.914 48.1052 195.004 45.8957Z\",\n \"M253 34.5478V56.9913H242.872V35.2683C242.872 31.882 242.115 29.3362 240.602 27.6311C239.088 25.9019 236.865 25.0373 233.934 25.0373C231.002 25.0373 228.588 26.082 226.689 28.1714C224.791 30.2369 223.842 32.9267 223.842 36.241V56.9913H213.786V17.2919H223.842V22.9478C224.995 20.8824 226.665 19.2493 228.852 18.0484C231.062 16.8476 233.549 16.2472 236.313 16.2472C241.503 16.2472 245.575 17.8563 248.531 21.0745C251.51 24.2928 253 28.7839 253 34.5478Z\",\n ],\n} as const;\n\n/**\n * The mark as a `url()`, for CSS that paints through its shape rather than\n * painting the artwork itself. Inline, because a mask is fetched the way an\n * image is and a host has nothing at `/median-logo.svg` to answer with.\n *\n * A mask reads only coverage, so the paths go in without a fill and come out\n * opaque.\n */\nexport const LOGO_MASK_URL = `url(\"data:image/svg+xml,${encodeURIComponent(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${LOGO.viewBox}\">` +\n LOGO.paths.map((d) => `<path d=\"${d}\"/>`).join(\"\") +\n `</svg>`,\n)}\")`;\n","import { BRAND_INK, LOGO, LOGO_MASK_URL, WORDMARK } from \"@/components/brand-art\";\nimport { cn } from \"@/lib/utils\";\n\n/** The artwork is solid black, so it gets inverted for dark mode. */\nconst INVERT_IN_DARK = \"dark:invert\";\n\n/**\n * The marks, drawn inline.\n *\n * Inline rather than fetched, because these render inside the widget package\n * too, where there is no public directory of ours to ask. See\n * `brand-art.ts` for the geometry.\n */\n\nexport function Wordmark({\n width = 132,\n className = \"\",\n}: {\n width?: number;\n className?: string;\n}) {\n return (\n <svg\n viewBox={WORDMARK.viewBox}\n width={width}\n height={Math.round((width * WORDMARK.height) / WORDMARK.width)}\n role=\"img\"\n aria-label=\"Median\"\n className={`${INVERT_IN_DARK} ${className}`}\n >\n {WORDMARK.paths.map((d) => (\n <path key={d} d={d} fill={BRAND_INK} />\n ))}\n </svg>\n );\n}\n\nexport function Logo({\n size = 104,\n className = \"\",\n}: {\n size?: number;\n className?: string;\n}) {\n return (\n <svg\n viewBox={LOGO.viewBox}\n width={size}\n height={size}\n aria-hidden\n className={`${INVERT_IN_DARK} ${className}`}\n >\n {LOGO.paths.map((d) => (\n <path key={d} d={d} fill={BRAND_INK} />\n ))}\n </svg>\n );\n}\n\n/**\n * The mark with a band of light travelling through it, for a wait that has\n * no shape yet: a conversation loading, an answer on its way.\n *\n * Painted by a gradient showing through a mask cut in the logo's shape,\n * rather than by the artwork itself, so the band travels across the mark\n * instead of over the top of it.\n */\nexport function ShimmerLogo({\n label,\n className,\n}: {\n label: string;\n className?: string;\n}) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n style={{\n maskImage: LOGO_MASK_URL,\n maskSize: \"contain\",\n maskRepeat: \"no-repeat\",\n maskPosition: \"center\",\n WebkitMaskImage: LOGO_MASK_URL,\n WebkitMaskSize: \"contain\",\n WebkitMaskRepeat: \"no-repeat\",\n WebkitMaskPosition: \"center\",\n backgroundImage:\n \"linear-gradient(115deg, var(--muted) 34%, var(--muted-foreground) 50%, var(--muted) 66%)\",\n backgroundSize: \"300% 100%\",\n }}\n className={cn(\n \"size-12 animate-shimmer motion-reduce:animate-none motion-reduce:bg-muted\",\n className,\n )}\n />\n );\n}\n","import { Logo, Wordmark } from \"@/components/brand\";\nimport { cn } from \"@/lib/utils\";\n\nconst MEDIAN_URL = \"https://median.sh\";\n\n/**\n * Our name on somebody else's site, so it sits under the composer rather than\n * inside it: a quiet line at the foot of the panel, not a control.\n *\n * It opens in a new tab, since a visitor who taps it is halfway through asking\n * for help and should not lose the page they were on.\n */\nexport function PoweredByMedian({ className }: { className?: string }) {\n return (\n <a\n href={MEDIAN_URL}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className={cn(\n \"flex items-center justify-center gap-1.5 rounded-md py-1 text-xs text-muted-foreground\",\n \"transition-opacity hover:opacity-70\",\n \"focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none\",\n className,\n )}\n >\n Powered by\n <Logo size={12} className=\"opacity-80\" />\n <Wordmark width={40} className=\"opacity-80\" />\n </a>\n );\n}\n","\"use client\";\n\nimport Image from \"next/image\";\nimport { useState } from \"react\";\nimport { InitialBadge } from \"@/components/initial-badge\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * A profile photo, falling back to a letter if there is no image or it fails\n * to load. `className` lands last on both branches, so a caller can override\n * the size and the letter's type scale together.\n */\nexport function Avatar({\n src,\n name,\n sourceSize = 48,\n unoptimized = false,\n className,\n}: {\n src: string | null;\n name: string;\n /** Intrinsic pixels to request. Aim for twice the rendered size. */\n sourceSize?: number;\n /**\n * Serve the picture as it came rather than through the image optimizer.\n * For faces from somebody else's site: the optimizer only fetches hosts\n * next.config names, and a customer's picture could be on any of them.\n */\n unoptimized?: boolean;\n className?: string;\n}) {\n // Which picture failed, rather than whether one did. A plain boolean never\n // cleared itself, so one bad response left the letter in place for the life\n // of the component: switch organizations and the next face inherited the\n // last one's failure, and a picture that was fine again stayed a letter\n // until the whole page reloaded.\n const [failedSrc, setFailedSrc] = useState<string | null>(null);\n const hasFailed = failedSrc !== null && failedSrc === src;\n const shape = \"size-4.5 shrink-0 rounded-full\";\n\n if (!src || hasFailed) {\n return (\n <InitialBadge\n value={name}\n className={cn(shape, \"border-none bg-muted text-[10px]\", className)}\n />\n );\n }\n\n return (\n <Image\n src={src}\n alt=\"\"\n width={sourceSize}\n height={sourceSize}\n unoptimized={unoptimized}\n onError={() => setFailedSrc(src)}\n draggable={false}\n className={cn(shape, \"bg-muted object-cover\", className)}\n />\n );\n}\n","import { cn } from \"@/lib/utils\";\n\n/**\n * A letter stand in for an avatar. Decorative: the readable name always sits\n * next to it, so this stays out of the accessibility tree.\n */\nexport function InitialBadge({\n value,\n className,\n}: {\n value: string;\n className?: string;\n}) {\n return (\n <span\n aria-hidden\n className={cn(\n // Sized to match UserAvatar, since the two sit side by side in the nav.\n \"grid size-4.5 shrink-0 place-items-center rounded border text-[10px] font-semibold text-muted-foreground\",\n className,\n )}\n >\n {value.trim().charAt(0).toUpperCase() || \"?\"}\n </span>\n );\n}\n","import { Avatar } from \"@/components/avatar\";\nimport { Sparkle } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport type { SupportAgent } from \"./types\";\n\n/**\n * An agent's face, or a mark where the AI is concerned. Squares rather than\n * the circles the inbox uses: the widget sits on somebody else's site next to\n * their own chrome, and a rounded square reads as a product mark there instead\n * of as another person's photo.\n *\n * Sizing comes from `className` so a caller can pick one scale for the header\n * and a smaller one for a read receipt. `label` overrides the name a screen\n * reader hears, which is how a receipt says \"Seen by Median AI\" from the same\n * one element rather than announcing the name twice.\n */\nexport function WidgetAvatar({\n agent,\n label,\n className,\n}: {\n agent: SupportAgent;\n label?: string;\n className?: string;\n}) {\n const shape = \"size-7 shrink-0 rounded-lg\";\n\n // The AI wears the mark until somebody gives it a face in settings; a\n // configured picture takes over and renders like anyone else's.\n if (agent.kind === \"ai\" && !agent.avatarUrl) {\n return (\n <span\n role=\"img\"\n aria-label={label ?? agent.name}\n className={cn(\n \"grid place-items-center bg-foreground text-background\",\n shape,\n className,\n )}\n >\n <Sparkle className=\"size-[55%]\" />\n </span>\n );\n }\n\n // Wrapped rather than labelled directly, because Avatar renders a decorative\n // image and has no name of its own to override.\n return (\n <span\n role=\"img\"\n aria-label={label ?? agent.name}\n className={cn(\"inline-flex\", shape, className)}\n >\n <Avatar\n src={agent.avatarUrl}\n name={agent.name}\n className=\"size-full rounded-[inherit]\"\n />\n </span>\n );\n}\n\n/**\n * Who is around, in the corner of the header. A row rather than an overlap,\n * since two or three faces read more clearly side by side at this size.\n */\nexport function WidgetAvatarStack({\n team,\n className,\n}: {\n team: SupportAgent[];\n className?: string;\n}) {\n if (team.length === 0) return null;\n\n return (\n <div className={cn(\"flex items-center gap-1\", className)}>\n {team.map((agent) => (\n <WidgetAvatar key={agent.id} agent={agent} className=\"size-8\" />\n ))}\n </div>\n );\n}\n","import type { ComponentType } from \"react\";\nimport { Bug, CaretRight, ChatCircleDots, Lightbulb } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport { WidgetAvatar } from \"./widget-avatar\";\nimport { WidgetButton } from \"./widget-button\";\nimport type { SupportAgent } from \"./types\";\n\n/**\n * The three things people open a support widget to do, and the message each\n * row sends.\n *\n * The messages are written as something a person would actually type, since\n * that is exactly what they become: the row sends it and the agent takes it\n * from there.\n */\nconst STARTERS: {\n label: string;\n glyph: ComponentType<{ className?: string }>;\n message: string;\n}[] = [\n {\n label: \"Ask a question\",\n glyph: ChatCircleDots,\n message: \"I have a question\",\n },\n {\n label: \"Report a bug\",\n glyph: Bug,\n message: \"I want to report a bug\",\n },\n {\n label: \"Make a suggestion\",\n glyph: Lightbulb,\n message: \"I have a suggestion\",\n },\n];\n\n/**\n * A conversation with nothing in it yet.\n *\n * Who is about to answer, and three ways to start. The AI goes first because\n * it is the one that always replies; a team of only people falls back to\n * whoever is at the front.\n *\n * The invitation names the organization, because that is the whole of what\n * the agent will talk about. Saying so here is cheaper than declining later.\n *\n * The rows send rather than fill the box in. Somebody who knows what they\n * want types it; somebody who is looking at three rows wants the shortest\n * way to the first reply.\n */\nexport function WidgetEmpty({\n team,\n orgName,\n onPick,\n isSending = false,\n isWaiting = false,\n}: {\n team: SupportAgent[];\n /** Whose site this is, so the invitation can say what it covers. */\n orgName?: string;\n /** Omit to leave the rows off, for a widget with nowhere to send them. */\n onPick?: (message: string) => void;\n /** Holds the rows while a message is on its way. */\n isSending?: boolean;\n /**\n * Holds them for something else the visitor has to do first, which is the\n * composer's question. The rows stay where they are while it is up rather\n * than arriving once it is answered: three rows appearing in a column that\n * centres itself would shove everything above them up the panel, and an\n * answer should not move the furniture.\n */\n isWaiting?: boolean;\n}) {\n const agent = team.find((member) => member.kind === \"ai\") ?? team[0];\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col items-center justify-center gap-4 px-5 pb-2 text-center\">\n {agent && (\n <WidgetAvatar\n agent={agent}\n className=\"size-14 animate-in rounded-2xl duration-500 ease-out fade-in-0 zoom-in-95 motion-reduce:animate-none\"\n />\n )}\n\n {/* A beat behind the mark, so the two read as one thing settling rather\n than as a block appearing. Backwards fill holds it out of sight\n through the delay instead of showing it and taking it away. */}\n <div className=\"flex max-w-64 animate-in flex-col gap-1 delay-150 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\">\n {agent && (\n <p className=\"text-base font-semibold tracking-tight\">{agent.name}</p>\n )}\n <p className=\"text-sm text-balance text-muted-foreground\">\n {orgName ? `Ask me anything about ${orgName}.` : \"Ask me anything.\"}\n </p>\n </div>\n\n {onPick && (\n <div className=\"flex w-full flex-col gap-1.5 pt-1\">\n {STARTERS.map((starter, index) => (\n <WidgetButton\n key={starter.label}\n type=\"button\"\n variant=\"outline\"\n disabled={isSending || isWaiting}\n onClick={() => onPick(starter.message)}\n // Each one a beat behind the last, so the three deal out rather\n // than land as a block. Backwards fill keeps them out of sight\n // until their turn.\n style={{ animationDelay: `${300 + index * 60}ms` }}\n className={cn(\n \"group/row h-auto w-full animate-in justify-start gap-2.5 px-3 py-2.5 text-left\",\n \"duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\",\n \"hover:border-foreground/15 hover:shadow-sm\",\n )}\n >\n <starter.glyph className=\"size-4 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate\">{starter.label}</span>\n <CaretRight\n aria-hidden\n className=\"size-3 text-muted-foreground/50 transition-transform group-hover/row:translate-x-0.5\"\n />\n </WidgetButton>\n ))}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { ArrowsIn, ArrowsOut, X } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { cn } from \"@/lib/utils\";\nimport type { DragHandlers } from \"./use-launcher-drag\";\nimport { WidgetAvatarStack } from \"./widget-avatar\";\nimport type { SupportPresence } from \"./types\";\n\n/**\n * Who you are talking to, and the one way out. There is no way back, because\n * there is nothing behind it: a visitor gets one thread, not a queue of them.\n *\n * It is also the handle. A panel floating on somebody's page is in the way of\n * something eventually, and the strip along the top is where anyone would\n * reach for to move it. The close button and the faces stay their own: a press\n * that lands on a control belongs to that control, which the drag checks\n * before it takes hold of anything.\n */\nexport function WidgetHeader({\n presence,\n onClose,\n isExpanded = false,\n onToggleExpanded,\n grabHandlers,\n isMoving = false,\n}: {\n presence: SupportPresence;\n onClose?: () => void;\n /** Standing taller than it normally does. */\n isExpanded?: boolean;\n /** Omit to hide the control, for a widget whose size is not its own. */\n onToggleExpanded?: () => void;\n /** Omit for a widget that is framed rather than floating. */\n grabHandlers?: DragHandlers;\n isMoving?: boolean;\n}) {\n return (\n <header\n {...grabHandlers}\n className={cn(\n \"flex shrink-0 items-start gap-2 px-3 pt-3 pb-2\",\n grabHandlers && [\n // Nothing here is selectable while it is being used to drag, and the\n // browser must not claim the gesture for scrolling either. Both end\n // the same way: the drag becomes the page's instead of ours.\n \"touch-none select-none\",\n isMoving ? \"cursor-grabbing\" : \"cursor-grab\",\n ],\n )}\n >\n <div className=\"flex min-w-0 flex-1 flex-col pt-0.5\">\n <h2 className=\"truncate text-base font-semibold tracking-tight\">\n {presence.name}\n </h2>\n <p className=\"truncate text-sm text-muted-foreground\">\n {presence.status}\n </p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-2\">\n <WidgetAvatarStack team={presence.team} />\n\n {/* The controls sit closer to each other than to the faces, so they\n read as a pair rather than as the end of the row. */}\n <div className=\"flex items-center gap-0.5\">\n {onToggleExpanded && (\n <WidgetButton\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onToggleExpanded}\n aria-pressed={isExpanded}\n aria-label={isExpanded ? \"Shrink the panel\" : \"Expand the panel\"}\n className=\"text-muted-foreground\"\n >\n {isExpanded ? <ArrowsIn /> : <ArrowsOut />}\n </WidgetButton>\n )}\n\n {onClose && (\n <WidgetButton\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClose}\n aria-label=\"Close support\"\n className=\"-mr-1 text-muted-foreground\"\n >\n <X />\n </WidgetButton>\n )}\n </div>\n </div>\n </header>\n );\n}\n","import { ShimmerLogo } from \"@/components/brand\";\n\n/**\n * Waiting on the conversation.\n *\n * One mark and nothing else. Skeleton bubbles would be guessing at a shape\n * nobody knows yet, and they always guess wrong.\n */\nexport function WidgetLoading() {\n return (\n <div className=\"grid min-h-0 flex-1 place-items-center p-6\">\n <ShimmerLogo label=\"Loading the conversation\" />\n </div>\n );\n}\n","import { LockSimple } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { PoweredByMedian } from \"./widget-badge\";\n\n/**\n * What a visitor meets when the host only takes questions from people who are\n * signed in.\n *\n * The same shape as the empty conversation it stands in for, and it arrives\n * the same way: the mark, then the words a beat behind it, then the one thing\n * to do about it. The button is only there when the host said where their\n * sign in lives, because a button that goes nowhere is worse than none.\n */\nexport function WidgetLocked({\n orgName,\n onSignIn,\n showBadge = true,\n}: {\n /** Whose site this is, so the line can name who is waiting. */\n orgName?: string;\n onSignIn?: () => void;\n /** The line the composer usually carries, which is not here to carry it. */\n showBadge?: boolean;\n}) {\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"flex min-h-0 flex-1 flex-col items-center justify-center gap-4 px-6 text-center\">\n <span className=\"grid size-14 animate-in place-items-center rounded-2xl bg-muted duration-500 ease-out fade-in-0 zoom-in-95 motion-reduce:animate-none\">\n <LockSimple className=\"size-6 text-muted-foreground\" />\n </span>\n\n <div className=\"flex max-w-64 animate-in flex-col gap-1 delay-150 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\">\n <p className=\"text-base font-semibold tracking-tight\">\n Sign in to chat\n </p>\n <p className=\"text-sm text-balance text-muted-foreground\">\n {orgName\n ? `Ask ${orgName} anything once you are signed in.`\n : \"Ask us anything once you are signed in.\"}\n </p>\n </div>\n\n {onSignIn && (\n <WidgetButton\n onClick={onSignIn}\n className=\"animate-in delay-300 duration-500 ease-out fade-in-0 slide-in-from-bottom-2 fill-mode-backwards motion-reduce:animate-none\"\n >\n Sign in\n </WidgetButton>\n )}\n </div>\n\n {showBadge && <PoweredByMedian className=\"shrink-0 px-3 pb-3\" />}\n </div>\n );\n}\n","import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"@/lib/utils\";\n\n// The palette is greyscale on purpose, so badges separate by weight rather\n// than by hue. Anything that needs to shout can reach for `solid`.\nconst badgeVariants = cva(\n \"inline-flex w-fit shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium whitespace-nowrap [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3\",\n {\n variants: {\n variant: {\n default: \"bg-secondary text-secondary-foreground\",\n muted: \"bg-muted text-muted-foreground\",\n outline: \"border border-border text-muted-foreground\",\n solid: \"bg-primary text-primary-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Badge({\n className,\n variant = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : \"span\";\n\n return (\n <Comp\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nexport { Badge, badgeVariants };\n","\"use client\";\n\nimport { useState, type ReactNode } from \"react\";\nimport { File, ImageSquare, Play } from \"@/components/icons\";\nimport { cn } from \"@/lib/utils\";\nimport type { SupportAttachment } from \"./types\";\n\n/** Tiles sit on the panel colour so they read as objects inside the bubble. */\nconst SURFACE = \"rounded-xl border border-foreground/10 bg-card/70\";\n\n/**\n * Opens the file, for anything that has somewhere to be opened.\n *\n * A new tab, because this is running on somebody else's page and a visitor\n * halfway through asking for help should not lose it. No `download`: the file\n * is served from another origin, where browsers ignore that attribute, so it\n * would promise a save and quietly do something else.\n *\n * Falls through to the plain contents when there is no URL, which is a file\n * still on its way or one whose link could not be signed. Better a tile that\n * does nothing than a link that goes nowhere.\n */\nfunction OpenAttachment({\n attachment,\n className,\n children,\n}: {\n attachment: SupportAttachment;\n className?: string;\n children: ReactNode;\n}) {\n if (!attachment.url) return <>{children}</>;\n\n return (\n <a\n href={attachment.url}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n aria-label={`Open ${attachment.name}`}\n className={cn(\n \"block rounded-xl transition-opacity outline-none hover:opacity-80\",\n \"focus-visible:ring-3 focus-visible:ring-ring/50\",\n className,\n )}\n >\n {children}\n </a>\n );\n}\n\nfunction MediaTile({\n attachment,\n className,\n}: {\n attachment: SupportAttachment;\n className?: string;\n}) {\n const [hasFailed, setHasFailed] = useState(false);\n\n // A preview that will not load says so in place, rather than leaving a grey\n // rectangle to puzzle over.\n if (!attachment.previewUrl || hasFailed) {\n return (\n <div\n className={cn(\n SURFACE,\n \"flex flex-col items-center justify-center gap-1 px-2 text-center\",\n className,\n )}\n >\n <ImageSquare className=\"size-5 text-muted-foreground\" />\n <p className=\"text-xs text-muted-foreground\">Preview unavailable</p>\n </div>\n );\n }\n\n return (\n <figure className={cn(SURFACE, \"relative overflow-hidden\", className)}>\n {/* A plain img, not the framework's: a freshly picked file is an object\n URL that has not left the browser, so there is nothing for an image\n pipeline to do, and this file also ships in the npm package where\n there is no framework to ask. */}\n {/* eslint-disable-next-line @next/next/no-img-element -- an object URL or signed link, nothing for the optimizer to do, and the npm bundle has no next/image. */}\n <img\n src={attachment.previewUrl}\n alt={attachment.name}\n width={640}\n height={480}\n onError={() => setHasFailed(true)}\n draggable={false}\n className=\"size-full object-cover\"\n />\n\n {attachment.kind === \"video\" && (\n <span\n aria-hidden\n className=\"absolute inset-0 grid place-items-center bg-foreground/15\"\n >\n <span className=\"grid size-8 place-items-center rounded-full bg-background/85 shadow-sm\">\n <Play className=\"size-3.5 translate-x-px\" />\n </span>\n </span>\n )}\n </figure>\n );\n}\n\nfunction FileRow({ attachment }: { attachment: SupportAttachment }) {\n return (\n <OpenAttachment attachment={attachment}>\n <div className={cn(SURFACE, \"flex items-center gap-2 px-2 py-1.5\")}>\n <File className=\"size-4 shrink-0 text-muted-foreground\" />\n\n <div className=\"flex min-w-0 flex-1 flex-col text-left\">\n <p className=\"truncate text-xs font-medium\">{attachment.name}</p>\n <p className=\"truncate text-xs text-muted-foreground\">\n {attachment.size}\n </p>\n </div>\n </div>\n </OpenAttachment>\n );\n}\n\n/**\n * Everything hanging off a message. Pictures and clips get a tile, anything\n * else gets a named row.\n *\n * Tiles go shorter once they share a row, so a pair reads as a pair rather than\n * two letterboxes stacked in a box.\n */\nexport function WidgetAttachments({\n attachments,\n}: {\n attachments: SupportAttachment[];\n}) {\n const media = attachments.filter((one) => one.kind !== \"file\");\n const files = attachments.filter((one) => one.kind === \"file\");\n\n return (\n <div className=\"flex w-56 max-w-full flex-col gap-1.5\">\n {media.length > 0 && (\n <div className={cn(\"grid gap-1.5\", media.length > 1 && \"grid-cols-2\")}>\n {media.map((attachment) => (\n <OpenAttachment\n key={attachment.id}\n attachment={attachment}\n className={media.length > 1 ? \"h-20\" : \"h-32\"}\n >\n {/* Opens in a tab rather than a lightbox. The inbox has one\n because a teammate is working through a queue; a visitor is\n looking at a picture they sent a minute ago. */}\n <MediaTile attachment={attachment} className=\"size-full\" />\n </OpenAttachment>\n ))}\n </div>\n )}\n\n {files.map((attachment) => (\n <FileRow key={attachment.id} attachment={attachment} />\n ))}\n </div>\n );\n}\n","\"use client\";\n\nimport { useLayoutEffect, useRef, type ReactNode } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst MORPH_MS = 260;\n/**\n * Matches --ease-out-quint. A pure deceleration on purpose: a spring's\n * overshoot carries the box past its final size and back, and since the box\n * clips its contents that reads as the text being cut off and restored.\n */\nconst MORPH_EASING = \"cubic-bezier(0.22, 1, 0.36, 1)\";\n\n/** How long the new contents take to appear once the box has room for them. */\nconst CONTENT_FADE_MS = 140;\n\n/** Sub pixel differences are not worth an animation. */\nconst EPSILON = 1;\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/**\n * Hand the contents back to the layout: no held width, no held opacity.\n *\n * Also what has to happen before measuring, since a box still pinned by the\n * last morph measures at the size that morph was holding it at.\n */\nfunction release(inner: HTMLElement) {\n inner.style.width = \"\";\n inner.style.boxSizing = \"\";\n inner.style.opacity = \"\";\n}\n\n/**\n * Hold the contents at the width they just laid out at, in full precision.\n *\n * The precision is the whole point. `offsetWidth` is rounded to a whole\n * pixel, and a bubble that sizes itself to its own text sits on a fractional\n * width far more often than not, so half the time that rounding goes down and\n * pins the text a hair narrower than the width it measured at. That is enough\n * to push the last word of a line onto the next one. It happens under the\n * pin, where it is hidden, so the box travels to the height it measured\n * before the wrap and the words spring back a line the moment the pin comes\n * off. The computed width is the used width, fractions and all, and it is\n * layout space rather than screen space, so an ancestor mid animation cannot\n * skew it either.\n *\n * Held as a content box so the number means the same thing going back in as\n * it did coming out, whatever padding the contents carry.\n */\nfunction pin(inner: HTMLElement) {\n const width = getComputedStyle(inner).width;\n inner.style.boxSizing = \"content-box\";\n inner.style.width = width;\n inner.style.opacity = \"0\";\n}\n\n/**\n * A bubble that grows into its new contents rather than snapping to them.\n *\n * `morphKey` is what it watches. Change it and the bubble measures where it\n * was, where it now is, and travels between the two. That is what turns three\n * bouncing dots into an answer: same element, same node, a different size.\n *\n * The contents wait, and they wait for the whole morph. React puts the new\n * text in at its full size the moment it arrives, so without this it is\n * already sitting there while the box is still growing, and the box, which\n * clips, wipes it into view a sliver at a time. Fading it in partway through\n * only moves the problem: a multi line reply is taller than the box until the\n * very end, so it fades in already cut off. The box travels first and the\n * words arrive in it once there is room for all of them.\n *\n * They are also pinned to the width they just laid out at for the duration.\n * Without that the text re-wraps on every frame while the box around it is\n * still moving, which looks far worse than no animation at all.\n */\nexport function MorphBubble({\n morphKey,\n className,\n contentClassName,\n children,\n}: {\n /** Derive it from the content, so any change to that content morphs. */\n morphKey: string;\n className?: string;\n contentClassName?: string;\n children: ReactNode;\n}) {\n const box = useRef<HTMLDivElement>(null);\n const content = useRef<HTMLDivElement>(null);\n const previous = useRef<{ width: number; height: number } | null>(null);\n const running = useRef<Animation[]>([]);\n\n useLayoutEffect(() => {\n const outer = box.current;\n const inner = content.current;\n if (!outer || !inner) return;\n\n // Where the box is right now, mid travel included, so a change that lands\n // during a morph carries on from what is on screen rather than from where\n // that morph happened to start.\n const from = running.current.length\n ? { width: outer.offsetWidth, height: outer.offsetHeight }\n : previous.current;\n\n // Everything the last morph was holding comes off before this one\n // measures, or \"the natural size of the new contents\" is really just the\n // size the last one was pinning them at.\n const interrupted = running.current;\n running.current = [];\n release(inner);\n for (const animation of interrupted) animation.cancel();\n\n const next = { width: outer.offsetWidth, height: outer.offsetHeight };\n previous.current = next;\n\n // Nothing to travel from on the first paint, and nothing to travel to if\n // the new contents happen to be the same size.\n if (!from) return;\n if (\n Math.abs(from.width - next.width) < EPSILON &&\n Math.abs(from.height - next.height) < EPSILON\n ) {\n return;\n }\n if (prefersReducedMotion()) return;\n\n // Set before the browser paints, so the new contents are never on screen\n // at full size for even one frame while the box is still small.\n pin(inner);\n\n const size = outer.animate(\n [\n { width: `${from.width}px`, height: `${from.height}px` },\n { width: `${next.width}px`, height: `${next.height}px` },\n ],\n { duration: MORPH_MS, easing: MORPH_EASING },\n );\n // Filled both ways on purpose. Backwards holds it invisible through the\n // delay, while the box is still moving. Forwards is what stops it\n // blinking at the other end: the inline opacity above is what hides it\n // before the animation starts, and without a forwards fill the finished\n // animation stops applying and that inline zero shows through again for\n // a frame before the cleanup below can clear it.\n const reveal = inner.animate([{ opacity: 0 }, { opacity: 1 }], {\n duration: CONTENT_FADE_MS,\n delay: MORPH_MS,\n easing: \"ease-out\",\n fill: \"both\",\n });\n\n running.current = [size, reveal];\n\n reveal.finished\n .catch(() => {})\n .finally(() => {\n if (!running.current.includes(reveal)) return;\n running.current = [];\n // Drop the inline hold first and only then the animation holding it\n // open, so there is never a frame where neither is keeping it up.\n release(inner);\n reveal.cancel();\n });\n }, [morphKey]);\n\n return (\n <div ref={box} className={cn(\"overflow-hidden\", className)}>\n <div ref={content} className={contentClassName}>\n {children}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { MorphBubble } from \"@/components/ui/morph-bubble\";\n\n/**\n * The widget's bubble. The morph itself is shared with the inbox, so both\n * sides of a conversation grow into a reply the same way; this only fixes\n * how the contents stack inside it.\n */\nexport function WidgetBubble({\n morphKey,\n className,\n children,\n}: {\n morphKey: string;\n className?: string;\n children: ReactNode;\n}) {\n return (\n <MorphBubble\n morphKey={morphKey}\n className={className}\n contentClassName=\"flex flex-col gap-2\"\n >\n {children}\n </MorphBubble>\n );\n}\n","import { Suspense } from \"react\";\nimport { MessageMarkdown, useMarkdownReady } from \"./markdown-chunk\";\nimport type { SupportSender } from \"./types\";\n\n/**\n * What was said.\n *\n * The agent's side renders markdown, because the house voice writes it: a\n * bold word, a short list, a line of code. The visitor's side is quoted\n * verbatim, asterisks and all, since nothing they type is markup.\n *\n * No animation of its own, on purpose. The bubble around it is already\n * growing and clipping as the words land, and anything fading or sliding in\n * here fights that: text appears, gets clipped, fades again. The morph is\n * the animation. The words just sit in it.\n */\nexport function WidgetMessageBody({\n body,\n sender,\n}: {\n body: string;\n sender: SupportSender;\n}) {\n // False until the renderer has been fetched. See `markdown-chunk.tsx` for\n // when that happens and why it is not simply imported.\n const isReady = useMarkdownReady();\n\n const plain = <p className=\"break-words whitespace-pre-line\">{body}</p>;\n if (sender === \"visitor\" || !isReady) return plain;\n\n // The same paragraph again as the fallback, so a render that beats the\n // module here by a frame shows the words rather than a gap.\n return (\n <Suspense fallback={plain}>\n <MessageMarkdown body={body} />\n </Suspense>\n );\n}\n","/** Offsets, so the bounce travels along the row instead of all three hopping together. */\nconst DOTS = [0, 160, 320];\n\n/**\n * An agent mid sentence. It lives inside the reply's own bubble rather than in\n * a bubble of its own, which is what lets the bubble stay put and grow into the\n * answer when it arrives.\n */\nexport function WidgetTyping({ label }: { label: string }) {\n return (\n <span className=\"flex items-center gap-1 py-1.5\">\n <span className=\"sr-only\">{label}</span>\n\n {DOTS.map((delay) => (\n <span\n key={delay}\n aria-hidden\n style={{ animationDelay: `${delay}ms` }}\n className=\"size-1.5 animate-typing-dot rounded-full bg-foreground/45 motion-reduce:animate-none\"\n />\n ))}\n </span>\n );\n}\n","import { Badge } from \"@/components/ui/badge\";\nimport { LONE_MESSAGE, type MessageGroup } from \"@/lib/message-groups\";\nimport { cn } from \"@/lib/utils\";\nimport { WidgetAttachments } from \"./widget-attachments\";\nimport { WidgetAvatar } from \"./widget-avatar\";\nimport { WidgetBubble } from \"./widget-bubble\";\nimport { WidgetMessageBody } from \"./widget-message-body\";\nimport { WidgetTyping } from \"./widget-typing\";\nimport type { SupportMessage } from \"./types\";\n\n/**\n * Both bubbles keep the page's text colour and separate by surface instead.\n * The visitor's own is a step further from the panel than the agent's, which\n * tells the two apart without a slab of pure black in the light, or pure white\n * in the dark.\n */\nconst BUBBLE = \"max-w-[80%] rounded-2xl px-3.5 py-2 text-sm\";\nconst VISITOR_BUBBLE =\n \"bg-[color-mix(in_oklch,var(--muted),var(--foreground)_12%)]\";\n\n/**\n * New messages arrive rather than appear. Short and small on purpose: the\n * scroller is easing down to the newest message at the same time, and a bubble\n * travelling any further than this reads as a wobble against it rather than as\n * one thing arriving. Off for anyone who asked.\n */\nconst ARRIVES =\n \"animate-in fade-in-0 slide-in-from-bottom-1 duration-200 ease-out motion-reduce:animate-none\";\n\n/**\n * The break above a message, when there is one: a new day, or a conversation\n * that starts here because the one before it was resolved.\n *\n * One line either way, and never two stacked. A conversation starting is the\n * bigger of the two breaks, so it stands in for the date rather than sitting\n * under it.\n */\nexport function WidgetDivider({ message }: { message: SupportMessage }) {\n const label = message.startsConversation\n ? \"New conversation\"\n : message.dayLabel;\n if (!label) return null;\n\n return (\n <div className=\"flex items-center gap-3 py-1\">\n <span className=\"h-px flex-1 bg-border\" />\n <span className=\"text-xs text-muted-foreground\">{label}</span>\n <span className=\"h-px flex-1 bg-border\" />\n </div>\n );\n}\n\n/**\n * One message. The two sides are built differently on purpose.\n *\n * A visitor's own message is only the bubble. They know what they said and\n * when, so a name, a time and a read receipt underneath are three things that\n * earn nothing. An agent's turn gets one line above it saying who is speaking\n * and when, because you want both before you read what they said. One line per\n * turn, not per message: a reply that comes in three parts says it once.\n */\nexport function WidgetMessage({\n message,\n group = LONE_MESSAGE,\n}: {\n message: SupportMessage;\n /** Where it sits in a run from the same voice. Alone, by default. */\n group?: MessageGroup;\n}) {\n return message.sender === \"visitor\" ? (\n <VisitorMessage message={message} />\n ) : (\n <AgentMessage message={message} group={group} />\n );\n}\n\n/**\n * What goes in a bubble: the files first, then what was said about them. The\n * text is skipped entirely when there is none, so a picture sent on its own\n * gets a bubble that hugs it rather than one with an empty line underneath.\n *\n * A reply that has not landed yet holds three bouncing dots in the same place\n * the words are about to be, which is what the bubble grows out of.\n */\nfunction BubbleContent({ message }: { message: SupportMessage }) {\n const hasAttachments = (message.attachments?.length ?? 0) > 0;\n\n if (message.pending) {\n return (\n <WidgetTyping\n label={`${message.agent?.name ?? \"Support\"} is writing a reply`}\n />\n );\n }\n\n return (\n <>\n {hasAttachments && (\n <WidgetAttachments attachments={message.attachments ?? []} />\n )}\n\n {message.body && (\n <WidgetMessageBody body={message.body} sender={message.sender} />\n )}\n </>\n );\n}\n\nfunction VisitorMessage({ message }: { message: SupportMessage }) {\n return (\n <div className={cn(\"flex justify-end\", ARRIVES)}>\n <WidgetBubble morphKey=\"settled\" className={cn(BUBBLE, VISITOR_BUBBLE)}>\n <BubbleContent message={message} />\n </WidgetBubble>\n </div>\n );\n}\n\nfunction AgentMessage({\n message,\n group,\n}: {\n message: SupportMessage;\n group: MessageGroup;\n}) {\n const { agent } = message;\n\n return (\n // One line saying who and when, then the thing they said. The face used to\n // sit in a gutter beside the bubble with the name above it and the time\n // below, which spread four small things across three rows and pushed every\n // bubble in off the edge. All of it is one line now, and the bubble gets\n // the full width back.\n <div className={cn(\"flex flex-col items-start gap-1\", ARRIVES)}>\n {/* Once per turn rather than once per message: a reply that arrives in\n three parts is still one agent saying one thing. */}\n {group.isFirst && (\n <div className=\"flex max-w-full items-center gap-1.5 px-0.5\">\n {agent && (\n <>\n <WidgetAvatar agent={agent} className=\"size-5 rounded-md\" />\n <span className=\"truncate text-xs font-medium\">{agent.name}</span>\n\n {/* Said plainly, because a name and a face are exactly what a\n machine can be given, and a visitor should never have to\n work out which one they got. Once per turn, since that is\n where the name is: a burst of three says it once. */}\n {agent.kind === \"ai\" && (\n <Badge variant=\"muted\" className=\"shrink-0 rounded-md px-1\">\n AI\n </Badge>\n )}\n </>\n )}\n\n {/* No time on a reply that has not been written yet. */}\n {!message.pending && (\n <span className=\"shrink-0 text-xs text-muted-foreground tabular-nums\">\n {message.time}\n </span>\n )}\n </div>\n )}\n\n {/* The same bubble either way. It is what the dots are in, so when the\n answer replaces them it grows out of where they were rather than\n appearing somewhere near them. */}\n <WidgetBubble\n // Derived from the contents, so an answer that arrives in pieces\n // keeps growing rather than morphing once and then snapping.\n morphKey={\n message.pending\n ? \"pending\"\n : `${message.body.length}:${message.attachments?.length ?? 0}`\n }\n className={cn(BUBBLE, \"bg-muted\")}\n >\n <BubbleContent message={message} />\n </WidgetBubble>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n RATING_FEEDBACK_MAX_LENGTH,\n RATING_MAX_STARS,\n} from \"@median/backend/support\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { Star } from \"@/components/icons\";\nimport { WidgetButton } from \"./widget-button\";\nimport { Collapse, COLLAPSE_MS } from \"@/components/ui/collapse\";\nimport { TEXT_FIELD_SHELL } from \"@/components/ui/text-field\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { cn } from \"@/lib/utils\";\nimport type { SupportRating } from \"./types\";\n\nconst STARS = Array.from({ length: RATING_MAX_STARS }, (_, index) => index + 1);\n\n/** How long the thank you stays before the card folds itself away. */\nconst THANKS_MS = 1400;\n\n/** Between one star lighting up and the next, so a pick reads as a sweep. */\nconst STAR_STAGGER_MS = 40;\n\n/**\n * The question a resolved conversation asks, sitting on the composer.\n *\n * A star saves the moment it is pressed rather than waiting for a Send,\n * because most people stop there and four stars with nothing after them is\n * still the answer. The box for words opens underneath afterwards, so\n * somebody who has more to say has somewhere to say it and nobody is held up\n * by a form they did not want.\n *\n * Nothing here appears or vanishes. The card opens out of the composer, the\n * box for words opens under the stars, the thank you takes the question's\n * place, and the whole thing folds away when it is finished, each of them the\n * same height travelling. Which is why leaving tells the panel it is done\n * only once it has finished folding: unmounting on the click would take the\n * animation with it.\n *\n * Above the composer rather than in place of it: the thread is finished, not\n * closed, and writing again is how a visitor starts the next one.\n */\nexport function WidgetRating({ rating }: { rating: SupportRating }) {\n const [isOpen, setIsOpen] = useState(false);\n const [picked, setPicked] = useState<number | null>(rating.stars);\n const [hovered, setHovered] = useState<number | null>(null);\n const [feedback, setFeedback] = useState(\"\");\n const [isSending, setIsSending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [isDone, setIsDone] = useState(false);\n\n const timers = useRef<ReturnType<typeof setTimeout>[]>([]);\n useEffect(() => {\n // Shut for one frame, open on the next, which is what turns a card that\n // was suddenly there into one that grew out of the composer.\n const frame = requestAnimationFrame(() => setIsOpen(true));\n const pending = timers.current;\n return () => {\n cancelAnimationFrame(frame);\n for (const timer of pending) clearTimeout(timer);\n };\n }, []);\n\n function later(ms: number, run: () => void) {\n timers.current.push(setTimeout(run, ms));\n }\n\n /** Fold away first, and only then tell the panel there is nothing to ask. */\n function leave() {\n setIsOpen(false);\n later(COLLAPSE_MS, rating.skip);\n }\n\n const shown = hovered ?? picked ?? 0;\n\n async function send(stars: number, words?: string) {\n setError(null);\n setIsSending(true);\n try {\n await rating.submit(stars, words);\n return true;\n } catch (caught) {\n console.error(\"Rating the conversation failed\", caught);\n setError(\"That did not send. Try again.\");\n return false;\n } finally {\n setIsSending(false);\n }\n }\n\n async function choose(stars: number) {\n // On screen first: the star they pressed is the answer whether or not\n // the network agrees yet.\n setPicked(stars);\n await send(stars);\n }\n\n /**\n * Finishing, with or without words. The stars are already saved, so an\n * empty box is somebody who has said all they wanted to and does not owe\n * anybody a sentence about it: no round trip, straight to the thanks.\n */\n async function finish() {\n if (picked === null) return;\n const words = feedback.trim();\n if (words.length > 0 && !(await send(picked, words))) return;\n\n setIsDone(true);\n later(THANKS_MS, leave);\n }\n\n return (\n <Collapse isOpen={isOpen} className=\"shrink-0\">\n {/* The spacing lives inside each section rather than as a gap between\n them, so a section that is closed takes up nothing at all. */}\n <div className=\"mx-3 mb-2 rounded-xl border bg-muted/40 px-3 dark:bg-muted/20\">\n <Collapse isOpen={!isDone}>\n <div className=\"py-2.5\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-medium\">\n {picked === null ? \"How did we do?\" : \"Thanks. Tell us more?\"}\n </p>\n {/* A word rather than a cross: this is a question, and the way\n out of a question is an answer, not a close button. */}\n <WidgetButton\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n className=\"-mt-0.5 -mr-1 text-muted-foreground\"\n disabled={isSending}\n onClick={leave}\n >\n Skip\n </WidgetButton>\n </div>\n\n <div\n role=\"radiogroup\"\n aria-label=\"How did we do?\"\n className=\"flex items-center justify-center gap-1 pt-1.5\"\n onMouseLeave={() => setHovered(null)}\n >\n {STARS.map((value) => (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={picked === value}\n aria-label={`${value} of ${RATING_MAX_STARS}`}\n disabled={isSending}\n onMouseEnter={() => setHovered(value)}\n onFocus={() => setHovered(value)}\n onBlur={() => setHovered(null)}\n onClick={() => void choose(value)}\n className={cn(\n \"rounded-md p-1 outline-none transition-transform duration-150 ease-out\",\n \"hover:scale-115 focus-visible:ring-3 focus-visible:ring-ring/50\",\n \"active:scale-95 disabled:pointer-events-none\",\n \"motion-reduce:transition-none\",\n )}\n >\n <Star\n // A pick lights the row up one star at a time, left to\n // right. Only a pick: a stagger under the pointer would\n // read as the widget lagging behind the mouse.\n style={{\n transitionDelay:\n hovered === null && picked !== null\n ? `${(value - 1) * STAR_STAGGER_MS}ms`\n : undefined,\n }}\n className={cn(\n \"size-6 transition-colors duration-200 ease-out motion-reduce:transition-none\",\n value <= shown\n ? \"text-foreground\"\n : \"text-muted-foreground/30\",\n )}\n />\n </button>\n ))}\n </div>\n\n <Collapse isOpen={picked !== null}>\n <div className=\"flex flex-col gap-2 pt-2\">\n <Textarea\n value={feedback}\n onChange={(event) => setFeedback(event.target.value)}\n placeholder=\"Anything to add? Optional\"\n aria-label=\"Anything to add, optional\"\n rows={2}\n maxLength={RATING_FEEDBACK_MAX_LENGTH}\n disabled={isSending}\n // The field's own shell, over the card's tint rather than in\n // it, so the box to write in reads as a box to write in.\n className={cn(\n TEXT_FIELD_SHELL,\n \"max-h-24 min-h-16 bg-card px-2.5 py-2\",\n )}\n />\n {/* Never held shut by an empty box. The words are the optional\n half of this, and a button that refuses to finish without\n them is a required field in a hat. */}\n <WidgetButton\n type=\"button\"\n size=\"sm\"\n className=\"self-end\"\n disabled={isSending}\n onClick={() => void finish()}\n >\n {isSending\n ? \"Sending\"\n : feedback.trim().length === 0\n ? \"Done\"\n : \"Send\"}\n </WidgetButton>\n </div>\n </Collapse>\n\n <Collapse isOpen={error !== null}>\n <p className=\"pt-1.5 text-center text-xs text-destructive\">\n {error}\n </p>\n </Collapse>\n </div>\n </Collapse>\n\n <Collapse isOpen={isDone}>\n <p className=\"py-3 text-center text-sm font-medium\">\n Thanks for the feedback.\n </p>\n </Collapse>\n </div>\n </Collapse>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * How long one takes to open or close. Anything that has to act after a\n * collapse has finished reads this rather than guessing, so the two cannot\n * drift; it matches the `duration-200` below.\n */\nexport const COLLAPSE_MS = 200;\n\n/**\n * A section that opens and closes rather than appearing and disappearing.\n *\n * The height is a grid row travelling between nothing and whatever the\n * contents want to be, which is the one way to animate to `auto` without\n * measuring anything on every frame. The contents keep their own size\n * throughout and are clipped rather than squashed, so words never reflow\n * mid animation.\n *\n * Closed, it is inert: a keyboard cannot land in a section that is not on\n * screen, and nothing inside one can be clicked through the clip.\n *\n * No gap between this and its neighbours. A closed section is zero pixels\n * tall but a flex gap around it is not, so spacing belongs inside the\n * contents; otherwise closing one leaves a hole where it used to be.\n */\nexport function Collapse({\n isOpen,\n id,\n children,\n className,\n}: {\n isOpen: boolean;\n /** For whatever toggles it to point at with `aria-controls`. */\n id?: string;\n children: ReactNode;\n className?: string;\n}) {\n return (\n <div\n id={id}\n inert={isOpen ? undefined : true}\n className={cn(\n \"grid transition-[grid-template-rows,opacity] duration-200 ease-out motion-reduce:transition-none\",\n isOpen ? \"grid-rows-[1fr] opacity-100\" : \"grid-rows-[0fr] opacity-0\",\n className,\n )}\n >\n <div className=\"overflow-hidden\">{children}</div>\n </div>\n );\n}\n","import { UserCircle } from \"@/components/icons\";\n\n/**\n * A quiet line about where the conversation stands, rather than about the\n * last thing said in it.\n *\n * Above the composer rather than under the header, for the same reason the\n * inbox puts its own status line there: the question it settles is who writes\n * the next reply, and that belongs next to the box you would write it in.\n *\n * Not a live region. The handoff arrives as a message too, in a thread that\n * already announces itself, and a screen reader should hear that once.\n */\nexport function WidgetAwaitingHuman() {\n return (\n <p className=\"flex animate-in items-center justify-center gap-1.5 px-4 pb-1 text-xs text-muted-foreground duration-200 ease-out fade-in-0 slide-in-from-bottom-1 motion-reduce:animate-none\">\n <UserCircle aria-hidden className=\"size-3.5\" />\n Waiting for a teammate\n </p>\n );\n}\n","\"use client\";\n\nimport {\n MessageScroller,\n MessageScrollerButton,\n MessageScrollerContent,\n MessageScrollerItem,\n MessageScrollerProvider,\n MessageScrollerViewport,\n} from \"@/components/ui/message-scroller\";\nimport { groupMessages, withinRun } from \"@/lib/message-groups\";\nimport { cn } from \"@/lib/utils\";\nimport type { DragHandlers } from \"./use-launcher-drag\";\nimport { useStackShift } from \"./use-stack-shift\";\nimport { WidgetComposer } from \"./widget-composer\";\nimport { WidgetEmpty } from \"./widget-empty\";\nimport { WidgetHeader } from \"./widget-header\";\nimport { WidgetLoading } from \"./widget-loading\";\nimport { WidgetLocked } from \"./widget-locked\";\nimport { WidgetDivider, WidgetMessage } from \"./widget-message\";\nimport { WidgetRating } from \"./widget-rating\";\nimport { WidgetAwaitingHuman } from \"./widget-status\";\nimport type {\n SupportMessage,\n SupportPresence,\n SupportRating,\n} from \"./types\";\n\n/**\n * What keeps a run going: the same voice, close together, and no divider\n * cutting in. The agent is compared by id rather than by side, so a handover\n * from the AI to a person always starts a fresh run and says so. A new\n * conversation always does too, whoever is speaking either side of it.\n */\nfunction joinsPreviousTurn(message: SupportMessage, previous: SupportMessage) {\n return (\n !message.dayLabel &&\n !message.startsConversation &&\n message.sender === previous.sender &&\n message.agent?.id === previous.agent?.id &&\n withinRun(previous.sentAt, message.sentAt)\n );\n}\n\n/**\n * The support panel a visitor sees on a host's site: who is around, the\n * thread, and a box to write in.\n *\n * It fills whatever it is given rather than picking its own size, so the same\n * component works as a floating bubble on desktop, a full screen sheet on a\n * phone, and a framed preview in the gallery. Whoever mounts it decides the\n * box; this decides what goes in it.\n *\n * Uncontrolled on purpose for now: `messages` come in, `onSend` goes out, and\n * nothing here holds a thread of its own. That is the seam the SDK will sit on\n * once this is wired to a real conversation.\n */\nexport function SupportWidget({\n presence,\n messages,\n onSend,\n onTypingChange,\n onClose,\n isExpanded = false,\n onToggleExpanded,\n isLoading = false,\n isLocked = false,\n onSignIn,\n askForEmail = false,\n onSubmitEmail,\n isSending = false,\n awaitingHuman = false,\n rating,\n notice,\n showBadge = true,\n grabHandlers,\n isMoving = false,\n className,\n}: {\n presence: SupportPresence;\n messages: SupportMessage[];\n /** Awaited by the composer, which keeps the draft if it rejects. */\n onSend?: (body: string, files: File[]) => unknown;\n /** The visitor's own typing, throttled by the composer. */\n onTypingChange?: (isTyping: boolean) => unknown;\n /** Omit to hide the close button, for a widget that is always on the page. */\n onClose?: () => void;\n /** Standing taller than it normally does. */\n isExpanded?: boolean;\n /**\n * Omit to hide the control. Only whoever owns the box the panel is drawn in\n * can grow it, so a widget that fills a frame it was given does not offer it.\n */\n onToggleExpanded?: () => void;\n /** Holds the mark while the conversation is on its way. */\n isLoading?: boolean;\n /**\n * Nobody is signed in, on a host that only takes questions from people who\n * are. The thread and the composer make way for the invitation to sign in.\n */\n isLocked?: boolean;\n /** Takes the visitor to the host's own sign in, and gives it its button. */\n onSignIn?: () => void;\n /**\n * The composer asks for an email before a first message, and the starter\n * rows stand down while it does: a pick would send before the question\n * was answered.\n */\n askForEmail?: boolean;\n /** What the composer's question does with a good answer. */\n onSubmitEmail?: (email: string) => void;\n /** Holds the send button while a message is. */\n isSending?: boolean;\n /** The agent has called for a person and nobody has picked it up yet. */\n awaitingHuman?: boolean;\n /**\n * The conversation is over and nobody has asked how it went yet. Null the\n * rest of the time, which is most of it.\n */\n rating?: SupportRating | null;\n /** One line above the composer, for a send that went wrong. */\n notice?: string | null;\n showBadge?: boolean;\n /**\n * Makes the header the thing the panel is dragged around by. Omitted by\n * anything that frames the widget rather than floats it, which is most of\n * the places it turns up outside a host's page.\n */\n grabHandlers?: DragHandlers;\n /** Being dragged right now, so the header can hold the closed hand. */\n isMoving?: boolean;\n className?: string;\n}) {\n const stack = useStackShift(messages.length);\n return (\n <section\n aria-label={`${presence.name} support`}\n className={cn(\n // The widget keeps its own radius scale. The app's token can climb as\n // the chrome gets rounder without the widget changing shape under the\n // hosts embedding it.\n \"flex h-full w-full flex-col overflow-hidden rounded-xl border bg-card text-card-foreground [--radius:0.625rem]\",\n className,\n )}\n >\n <WidgetHeader\n presence={presence}\n onClose={onClose}\n isExpanded={isExpanded}\n onToggleExpanded={onToggleExpanded}\n grabHandlers={grabHandlers}\n isMoving={isMoving}\n />\n\n {isLoading ? (\n <WidgetLoading />\n ) : isLocked ? (\n /* After the loading rather than before it: the line names the host,\n so it waits for the name the same as everything else does. */\n <WidgetLocked\n orgName={presence.name}\n onSignIn={onSignIn}\n showBadge={showBadge}\n />\n ) : (\n <Conversation\n presence={presence}\n messages={messages}\n onSend={onSend}\n onTypingChange={onTypingChange}\n askForEmail={askForEmail}\n onSubmitEmail={onSubmitEmail}\n isSending={isSending}\n awaitingHuman={awaitingHuman}\n rating={rating}\n notice={notice}\n showBadge={showBadge}\n stackRef={stack}\n />\n )}\n </section>\n );\n}\n\n/**\n * Everything under the header. Split out so it mounts as one thing when the\n * conversation lands, which is what gives the whole lot a single fade in\n * rather than a thread and a composer arriving separately.\n */\nfunction Conversation({\n presence,\n messages,\n onSend,\n onTypingChange,\n askForEmail = false,\n onSubmitEmail,\n isSending = false,\n awaitingHuman = false,\n rating,\n notice,\n showBadge,\n stackRef,\n}: {\n presence: SupportPresence;\n messages: SupportMessage[];\n onSend?: (body: string, files: File[]) => unknown;\n onTypingChange?: (isTyping: boolean) => unknown;\n /** The composer asks for an email before a first message. */\n askForEmail?: boolean;\n /** What the composer's question does with a good answer. */\n onSubmitEmail?: (email: string) => void;\n isSending?: boolean;\n awaitingHuman?: boolean;\n rating?: SupportRating | null;\n notice?: string | null;\n showBadge: boolean;\n stackRef: (node: HTMLDivElement | null) => void;\n}) {\n const groups = groupMessages(messages, joinsPreviousTurn);\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col animate-in fade-in-0 duration-500 ease-out motion-reduce:animate-none\">\n {messages.length === 0 ? (\n <WidgetEmpty\n team={presence.team}\n orgName={presence.name}\n onPick={\n onSend === undefined\n ? undefined\n : (message) => void onSend(message, [])\n }\n isSending={isSending}\n // Held rather than taken away while the email is asked for: a row\n // would send before the question above it was answered, and rows\n // that leave and come back move everything above them twice.\n isWaiting={askForEmail}\n />\n ) : (\n /* The same scroller the inbox thread uses, so both sides of a\n conversation stick to the newest message the same way, and both grow\n the same button when you scroll back up.\n\n It keeps following the bottom while the panel is resizing, and it\n has to. A panel shrinking takes its top edge down past the thread,\n so a scroller left alone slides the newest message under the\n composer and has to catch up afterwards. Following it is what the\n scroller stops easing for, so this tracks frame by frame. */\n <MessageScrollerProvider>\n {/* h-auto so the scroller takes the space the header and composer\n leave, rather than the full column its own `size-full` asks for. */}\n <MessageScroller className=\"h-auto min-h-0 flex-1\">\n <MessageScrollerViewport\n // A log with a polite live region, so a reply is announced as it\n // lands without pulling focus out of the box being typed in.\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n aria-label=\"Conversation\"\n className=\"px-3 py-2\"\n >\n {/* justify-end so a short thread sits on the composer rather than\n hanging from the header with a field of nothing under it. The\n content is already at least a viewport tall, so this only\n decides where the slack goes: above the first message, not\n below the last.\n\n The space between messages is on the items rather than here,\n since a message carrying on the one above it sits closer to\n it than one starting a new turn. */}\n <MessageScrollerContent\n ref={stackRef}\n className=\"justify-end gap-0\"\n >\n {messages.map((message, index) => (\n <MessageScrollerItem\n key={message.id}\n messageId={message.id}\n // The scroller skips rendering off screen items and holds\n // 10rem open for each one until it arrives. That is a fair\n // guess in the inbox, where the column is wide and a\n // message is tall. Here it is roughly double: a bubble in a\n // panel this narrow is nearer 4rem, so every item resized\n // the moment it scrolled into view and the whole thread\n // jumped. A support thread is short enough that skipping\n // any of it buys nothing anyway.\n className={cn(\n \"flex flex-col gap-4 [content-visibility:visible] first:pt-0\",\n groups[index].isFirst ? \"pt-4\" : \"pt-1\",\n )}\n >\n <WidgetDivider message={message} />\n <WidgetMessage message={message} group={groups[index]} />\n </MessageScrollerItem>\n ))}\n </MessageScrollerContent>\n </MessageScrollerViewport>\n\n {/* Outside the viewport: it is positioned against the scroller, so\n inside it would scroll away with the messages. */}\n <MessageScrollerButton />\n </MessageScroller>\n </MessageScrollerProvider>\n )}\n\n {/* The question a finished thread asks. Never at the same time as the\n line below it: one is a conversation that is over and the other is\n one waiting on a person. */}\n {rating && <WidgetRating rating={rating} />}\n\n {/* Above the failed send, since it is the older of the two facts and\n the one that is still true after a retry works. */}\n {awaitingHuman && <WidgetAwaitingHuman />}\n\n {/* A send that failed says so right where the retry happens. */}\n {notice && (\n <p className=\"animate-in px-4 pb-1 text-center text-xs text-destructive fade-in duration-150\">\n {notice}\n </p>\n )}\n\n <WidgetComposer\n onSend={onSend}\n onTypingChange={onTypingChange}\n askForEmail={askForEmail}\n onSubmitEmail={onSubmitEmail}\n isSending={isSending}\n showBadge={showBadge}\n />\n </div>\n );\n}\n","\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport {\n getDefaultSpot,\n getSpot,\n metricsFor,\n setSpot,\n spotFrom,\n spotFromPanel,\n subscribeSpot,\n type Bounds,\n type Size,\n} from \"./launcher-position\";\nimport { prefersReducedMotion } from \"./motion\";\n\n/** Further than this and it is a drag. Under it, it is a click that wobbled. */\nconst DRAG_THRESHOLD = 5;\n\n/**\n * What a press takes hold of: the button while it is closed, and the panel\n * itself, by its header, once it is open.\n *\n * Both move the same box. The difference is what is being kept on the page\n * while it travels, and what the spot is read back off when it lands.\n */\nexport type DragSubject = \"button\" | \"panel\";\n\n/** What a surface wears to become something the widget can be dragged by. */\nexport type DragHandlers = {\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n onPointerMove: (event: ReactPointerEvent<HTMLElement>) => void;\n onPointerUp: (event: ReactPointerEvent<HTMLElement>) => void;\n onPointerCancel: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\n/**\n * A press that landed on a control belongs to that control.\n *\n * Only the panel needs asking. The button is the handle and the whole of it,\n * so a press anywhere on it is a press on the thing being dragged; the header\n * is a strip with a close button and a row of faces on it, and grabbing the\n * panel by the close button would be a drag that shuts it.\n */\nfunction isControl(target: EventTarget | null): boolean {\n return (\n target instanceof Element &&\n target.closest(\"a, button, input, select, textarea\") !== null\n );\n}\n\n/** The flight to the edge once it is let go. Matches --ease-spring. */\nconst SNAP_MS = 420;\nconst SNAP_EASING = \"cubic-bezier(0.34, 1.45, 0.64, 1)\";\n\n/**\n * The button's height inside the box, which the clip and the button both read.\n * A custom property because it inherits: one write on the box reaches the\n * panel, the shadow and the button, and none of them has to be told twice.\n */\nexport const BUTTON_Y = \"--median-button-y\";\n\n/** Everything the drag needs, measured once, while it is still standing still. */\ntype Grip = {\n subject: DragSubject;\n grabX: number;\n grabY: number;\n startX: number;\n startY: number;\n bounds: Bounds;\n margin: number;\n /** The button, which the spot is always defined in terms of. */\n size: Size;\n box: Size;\n /** The one actually travelling: the button, or the whole box. */\n dragged: Size;\n /** Where that one was before any of this, and where it is now. */\n resting: { x: number; y: number };\n at: { x: number; y: number };\n moved: boolean;\n};\n\n/**\n * Dragging the launcher, and the edge it settles against.\n *\n * The box that holds the panel is positioned to contain the button, and the\n * button is pinned inside it, so moving one moves both. The closed panel is a\n * circle sitting exactly under the button; if only the button travelled it\n * would slide off its own shadow.\n *\n * Nothing goes through React state while a finger is down. The offset is\n * written straight onto the box, because a `setState` per pointermove renders\n * the whole panel underneath, and the panel is an entire conversation. React\n * hears the spot once, at the end.\n *\n * The resting geometry cannot be written in CSS, because the button's height\n * inside the box is the difference between two things measured against\n * different boxes. So it is measured and written, before paint, and the style\n * carries a plain calc as a fallback for the frame before that happens, which\n * is the one the server rendered.\n */\nexport function useLauncherDrag({\n boxRef,\n buttonRef,\n margin,\n enabled,\n subject,\n}: {\n boxRef: RefObject<HTMLDivElement | null>;\n buttonRef: RefObject<HTMLButtonElement | null>;\n /** Any CSS length. How far off the edges it sits. */\n margin: string;\n /** Off when there is nothing on the page to take hold of. */\n enabled: boolean;\n /** Which of the two a press is grabbing, which is to say whether it is open. */\n subject: DragSubject;\n}) {\n const spot = useSyncExternalStore(subscribeSpot, getSpot, getDefaultSpot);\n\n // Two renders a drag, at the ends of it. Never one per move. It stays true\n // through the flight as well, because the clip is keyed to the button's\n // height and that changes as it lands; transitioning between the two would\n // wipe the panel across the box on the way.\n const [isMoving, setIsMoving] = useState(false);\n\n const grip = useRef<Grip | null>(null);\n /** Set by the drag that just ended, read by the click it turns into. */\n const justDragged = useRef(false);\n\n /** The space it lives in: the page, or whatever is positioning it. */\n const measure = useCallback((): {\n bounds: Bounds;\n margin: number;\n size: Size;\n box: Size;\n } | null => {\n const box = boxRef.current;\n const button = buttonRef.current;\n if (!box) return null;\n\n const parent = box.offsetParent;\n const rect =\n parent instanceof HTMLElement\n ? parent.getBoundingClientRect()\n : new DOMRect(0, 0, window.innerWidth, window.innerHeight);\n const boxRect = box.getBoundingClientRect();\n\n return {\n bounds: {\n left: rect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n },\n // Asked of the resolved style rather than parsed out of the string we\n // were handed, so a margin in any unit at all comes back in pixels.\n margin: Math.round(\n Number.parseFloat(getComputedStyle(box).getPropertyValue(spot.side)) ||\n 0,\n ),\n // Offset sizes, so a button mid press is not measured through whatever\n // scale it happens to be wearing.\n //\n // No button at all is a widget the host opens themselves. Nothing\n // hangs below the panel then, so it is a button of no size: the same\n // arithmetic, with the box parked against the bottom margin.\n size: button\n ? { width: button.offsetWidth, height: button.offsetHeight }\n : { width: 0, height: 0 },\n // The box gets the fractional one instead, and the difference is the\n // whole of whether a resize is smooth. Its top is worked out as its\n // bottom edge minus its height, so a height rounded to a whole pixel\n // against a box that is mid animation puts the bottom edge up to half a\n // pixel out, in a different direction on every frame. The panel shimmers\n // in place rather than growing. Nothing scales the box, so a rect is as\n // safe here as an offset and says the same thing more precisely.\n box: { width: boxRect.width, height: boxRect.height },\n };\n }, [boxRef, buttonRef, spot.side]);\n\n /**\n * Writes the resting geometry onto the nodes. Before paint on the way in,\n * and again whenever the space it is measured against changes.\n */\n const place = useCallback(() => {\n const box = boxRef.current;\n const taken = measure();\n if (!box || taken === null) return;\n\n const metrics = metricsFor(\n spot,\n taken.bounds,\n taken.size,\n taken.box.height,\n taken.margin,\n );\n\n box.style.top = `${metrics.boxTop - taken.bounds.top}px`;\n box.style.setProperty(BUTTON_Y, `${metrics.buttonInBox}px`);\n }, [boxRef, measure, spot]);\n\n useLayoutEffect(place, [place]);\n\n useEffect(() => {\n window.addEventListener(\"resize\", place);\n return () => window.removeEventListener(\"resize\", place);\n }, [place]);\n\n // Its own size counts as the space changing too, and this is the one that\n // moves on its own. The box hangs upward from the button, so where its top\n // belongs is worked out from how tall it is, and a panel growing into its\n // expanded height has a different answer on every frame of the way there.\n // Left to the effect above it would get the final answer on the first frame,\n // and the panel would jump off the button and then grow back down onto it.\n useEffect(() => {\n const box = boxRef.current;\n if (!box || typeof ResizeObserver === \"undefined\") return;\n\n // Nothing here changes the box's size, so this cannot feed itself.\n const observer = new ResizeObserver(place);\n observer.observe(box);\n return () => observer.disconnect();\n }, [boxRef, place]);\n\n /** Puts the box back where `place` left it, with no animation. */\n const settle = useCallback(() => {\n const box = boxRef.current;\n if (box) box.style.transform = \"\";\n }, [boxRef]);\n\n /**\n * The page while something is being dragged across it: nothing selectable,\n * and the closed hand everywhere.\n *\n * Both belong on the body rather than on what is being held, because the\n * pointer spends the whole drag over everything else. Left to the handle's\n * own classes the cursor turns back into a caret the moment it crosses the\n * thread, and the browser reads the gesture as a sweep through the host's\n * text, which leaves the next press picking up that selection instead of\n * the widget.\n *\n * Written and cleared in one place because these outlive the widget: a drag\n * that ended without this running leaves somebody else's page unselectable\n * and wearing a cursor that is not theirs.\n */\n const holdPointer = useCallback((held: boolean) => {\n document.body.style.userSelect = held ? \"none\" : \"\";\n document.body.style.cursor = held ? \"grabbing\" : \"\";\n if (held) window.getSelection()?.removeAllRanges();\n }, []);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n justDragged.current = false;\n\n // A press starts from nothing held. If the last one never heard its own\n // release, this is where the page gets its cursor and its selection\n // back, rather than the next drag inheriting them.\n if (grip.current !== null) {\n grip.current = null;\n holdPointer(false);\n setIsMoving(false);\n }\n\n if (!enabled || !event.isPrimary) return;\n // A right click is a menu, not a move.\n if (event.pointerType === \"mouse\" && event.button !== 0) return;\n if (subject === \"panel\" && isControl(event.target)) return;\n\n // The button when it is closed, the whole box when it is open. Either\n // way the box is what travels; this is only what is being aimed.\n const moving = subject === \"panel\" ? boxRef.current : buttonRef.current;\n const taken = measure();\n if (moving === null || taken === null) return;\n\n // Refused so the press cannot begin a selection, or pick up one already\n // lying around and drag that instead. Focus is handed back by hand,\n // since that was the other thing the default was going to do.\n event.preventDefault();\n // Only the button takes it. An open panel is being moved, not entered,\n // so whatever was half typed in the composer keeps the caret.\n if (subject === \"button\") buttonRef.current?.focus({ preventScroll: true });\n\n const rect = moving.getBoundingClientRect();\n grip.current = {\n subject,\n grabX: event.clientX - rect.left,\n grabY: event.clientY - rect.top,\n startX: event.clientX,\n startY: event.clientY,\n ...taken,\n dragged: subject === \"panel\" ? taken.box : taken.size,\n resting: { x: rect.left, y: rect.top },\n at: { x: rect.left, y: rect.top },\n moved: false,\n };\n\n event.currentTarget.setPointerCapture(event.pointerId);\n },\n [boxRef, buttonRef, enabled, holdPointer, measure, subject],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n const held = grip.current;\n const box = boxRef.current;\n if (held === null || box === null) return;\n\n if (!held.moved) {\n const travelled = Math.hypot(\n event.clientX - held.startX,\n event.clientY - held.startY,\n );\n if (travelled < DRAG_THRESHOLD) return;\n held.moved = true;\n holdPointer(true);\n setIsMoving(true);\n }\n\n // Kept inside the edges it can settle against. Arithmetic only:\n // everything it needs was measured on the way down.\n held.at = {\n x: clamp(\n event.clientX - held.grabX,\n held.bounds.left + held.margin,\n held.bounds.left +\n held.bounds.width -\n held.margin -\n held.dragged.width,\n ),\n y: clamp(\n event.clientY - held.grabY,\n held.bounds.top + held.margin,\n held.bounds.top +\n held.bounds.height -\n held.margin -\n held.dragged.height,\n ),\n };\n\n box.style.transform = `translate3d(${held.at.x - held.resting.x}px, ${held.at.y - held.resting.y}px, 0)`;\n },\n [boxRef, holdPointer],\n );\n\n /**\n * The end of a drag, wherever the news of it came from.\n *\n * Separate from the handler because a release is not reliably an event on\n * the thing that was grabbed. Pointer capture usually delivers it there, but\n * a capture lost to the window manager, a switch to another window mid\n * press, or an element that went away underneath one all end the gesture\n * with nothing firing on the handle at all. Every one of those used to leave\n * the page holding a grabbing cursor and nothing selectable, with no way\n * back except starting another drag.\n *\n * Nothing to end is not a problem to report: the flight home runs after the\n * grip is let go, and the same release arrives twice on the way out.\n */\n const finishDrag = useCallback(() => {\n const held = grip.current;\n if (held === null) return;\n grip.current = null;\n\n holdPointer(false);\n\n const box = boxRef.current;\n if (!held.moved || box === null) {\n setIsMoving(false);\n return;\n }\n\n justDragged.current = true;\n\n // Where it landed, read back as a spot. Which end of the widget that is\n // asked of is the whole of the difference between the two drags.\n const target =\n held.subject === \"panel\"\n ? spotFromPanel(held.at, held.bounds, held.size, held.box, held.margin)\n : spotFrom(held.at, held.bounds, held.size, held.margin);\n\n const home = metricsFor(\n target,\n held.bounds,\n held.size,\n held.box.height,\n held.margin,\n );\n // Where the thing that travelled belongs once it is there, so the flight\n // below is exactly the gap between that and the finger.\n const from = {\n x:\n held.at.x -\n (target.side === \"left\"\n ? held.bounds.left + held.margin\n : held.bounds.left +\n held.bounds.width -\n held.margin -\n held.dragged.width),\n y: held.at.y - (held.subject === \"panel\" ? home.boxTop : home.buttonY),\n };\n\n // All of this is one frame, and the order is the whole trick.\n //\n // Committing the spot synchronously runs the layout effect above with it,\n // so the box is already positioned where it is going before anything is\n // painted. Clearing the transform then puts it there, which is not where\n // the finger left it, and the animation starts from exactly the gap\n // between the two. The first frame drawn still has whatever was being\n // held under the finger, and the rest of them carry it home.\n flushSync(() => setSpot(target));\n settle();\n\n if (prefersReducedMotion()) {\n setIsMoving(false);\n return;\n }\n\n const flight = box.animate(\n [\n { transform: `translate3d(${from.x}px, ${from.y}px, 0)` },\n { transform: \"none\" },\n ],\n { duration: SNAP_MS, easing: SNAP_EASING },\n );\n // Only once it has landed: the clip must not start transitioning between\n // heights while one of them is still travelling.\n flight.finished.catch(() => {}).finally(() => setIsMoving(false));\n }, [boxRef, holdPointer, settle]);\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n finishDrag();\n },\n [finishDrag],\n );\n\n // The safety net, live only while something is actually being dragged. A\n // release anywhere at all ends it, and so does the window losing focus,\n // which is the one that catches a press abandoned to another app.\n useEffect(() => {\n if (!isMoving) return;\n\n const end = () => finishDrag();\n window.addEventListener(\"pointerup\", end);\n window.addEventListener(\"pointercancel\", end);\n window.addEventListener(\"blur\", end);\n return () => {\n window.removeEventListener(\"pointerup\", end);\n window.removeEventListener(\"pointercancel\", end);\n window.removeEventListener(\"blur\", end);\n };\n }, [isMoving, finishDrag]);\n\n const dragHandlers: DragHandlers = {\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: handlePointerUp,\n onPointerCancel: handlePointerUp,\n };\n\n // Everything above was measured against a page that is no longer that size.\n // Nothing to rescue: it goes back to wherever `place` puts it.\n useEffect(() => {\n function abandon() {\n if (grip.current === null) return;\n grip.current = null;\n holdPointer(false);\n settle();\n setIsMoving(false);\n }\n\n window.addEventListener(\"resize\", abandon);\n return () => {\n window.removeEventListener(\"resize\", abandon);\n // A widget that goes away mid drag must not leave the host's whole page\n // unselectable and wearing a cursor it never asked for. This is their\n // body, not ours.\n holdPointer(false);\n };\n }, [holdPointer, settle]);\n\n return {\n side: spot.side,\n /** Being dragged, or on its way to an edge. Nothing may transition. */\n isMoving,\n /** The side only. Height is measured and written straight to the node. */\n style: { [spot.side]: margin } as { left?: string; right?: string },\n /** True for the click that ended a drag, so it does not also open. */\n swallowClick: () => {\n if (!justDragged.current) return false;\n justDragged.current = false;\n return true;\n },\n /**\n * The same four handlers whichever end is being held. Both ends can wear\n * them at once: only one of the two is ever reachable, since the button is\n * inert while the panel is up and the panel is inert while it is down.\n */\n dragHandlers,\n };\n}\n\nfunction clamp(value: number, low: number, high: number): number {\n return Math.min(Math.max(value, low), Math.max(low, high));\n}\n","\"use client\";\n\nimport { useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * How much room the card needs above the button before it goes there.\n * Roughly its own height plus the gap, with a little to spare.\n */\nconst ROOM_ABOVE_PX = 128;\n\nexport type TeaserPlacement = \"above\" | \"below\";\n\n/**\n * Which side of the button the card hangs off.\n *\n * Above, nearly always: the box the widget lives in hangs upward from the\n * button, so above is where the room is. The exception is a button somebody\n * dragged to the top of the window, where the box is pinned under the top\n * margin and the button sits at its top edge with nothing over it. There\n * the card goes below instead.\n *\n * Measured off the button's own offset inside the box rather than worked\n * out from the spot, since the box is clamped in ways the spot alone does\n * not say. Measured again whenever a drag settles, which is the only time\n * the answer can change short of a resize.\n */\nexport function useTeaserPlacement({\n buttonRef,\n enabled,\n isMoving,\n}: {\n buttonRef: RefObject<HTMLElement | null>;\n /** Whether there is a card to place. Nothing is measured otherwise. */\n enabled: boolean;\n /** A drag is on. The answer waits for it to land. */\n isMoving: boolean;\n}): TeaserPlacement {\n const [placement, setPlacement] = useState<TeaserPlacement>(\"above\");\n\n useLayoutEffect(() => {\n if (!enabled || isMoving) return;\n\n const measure = () => {\n const button = buttonRef.current;\n if (button === null) return;\n setPlacement(button.offsetTop < ROOM_ABOVE_PX ? \"below\" : \"above\");\n };\n\n measure();\n window.addEventListener(\"resize\", measure);\n return () => window.removeEventListener(\"resize\", measure);\n }, [buttonRef, enabled, isMoving]);\n\n return placement;\n}\n","\"use client\";\n\nimport {\n useLayoutEffect,\n useState,\n useSyncExternalStore,\n type RefObject,\n} from \"react\";\nimport { usePageLock } from \"./use-page-lock\";\n\n/**\n * When the panel stops floating and takes the screen.\n *\n * Tailwind's `sm` breakpoint, written out, so this hook and any `max-sm:`\n * styles riding along with it change their minds at the same width.\n */\nconst PHONE = \"(max-width: 40rem)\";\n\n/**\n * How long the panel keeps following the visual viewport after it last heard\n * from it.\n *\n * The keyboard takes about a quarter of a second to come up and reports its\n * progress two or three times on the way, so a panel that moved only when it\n * was told would arrive in two or three jumps. This keeps it measuring every\n * frame for a beat afterwards instead, which is what turns those jumps into\n * the panel riding the keyboard up.\n */\nconst SETTLE_MS = 400;\n\n/**\n * How much of the visible height has to go missing before it is the keyboard\n * and not the browser's own chrome sliding away.\n */\nconst KEYBOARD_PX = 96;\n\nfunction subscribePhone(onChange: () => void) {\n const media = window.matchMedia(PHONE);\n media.addEventListener(\"change\", onChange);\n return () => media.removeEventListener(\"change\", onChange);\n}\n\nconst isPhoneNow = () => window.matchMedia(PHONE).matches;\n\n/** The server's answer. Nothing is open on the server, so nothing is lost. */\nconst isPhoneOnServer = () => false;\n\n/**\n * Whether the open panel should be the whole screen rather than a floating\n * card, and everything that has to be true while it is.\n *\n * A phone has no room for a card floating over a page: the card is nearly the\n * page already, and the margins around it are the only thing the extra rem\n * buys. So under `sm` the panel opens edge to edge instead, the way every\n * sheet on a phone does.\n *\n * Only when the widget is the viewport's, though. The gallery pins its\n * previews inside a frame with `absolute`, and a preview that burst out of\n * its frame to swallow the page would be demonstrating exactly the wrong\n * thing. `offsetParent` is the tell: a `fixed` box answers null, a framed one\n * answers with its frame. An ancestor wearing a transform also answers, and\n * should: a box positioned against somebody's transformed container is not\n * positioned against the screen, so it has no business covering it.\n *\n * While the sheet is up this also does two jobs the floating panel never\n * needed:\n *\n * - The panel is sized to `visualViewport` rather than to `inset-0`, and keeps\n * measuring for a beat after each report so it rides the keyboard up instead\n * of arriving in two jumps. The keyboard shrinks the visual viewport and not\n * the layout one, so a panel pinned to the layout viewport keeps its composer\n * underneath the keyboard, which is the one place the thing being typed into\n * cannot be. Written straight onto the node, the way the drag writes its\n * travel: a render per frame of that would run the whole conversation through\n * React to move an edge.\n *\n * - The host's page is pinned where it stands, by `usePageLock`. A full screen\n * sheet with a live page rumbling underneath it reads as broken, and a page\n * the keyboard is free to scroll takes the sheet's own footing with it.\n */\nexport function useWidgetSheet({\n boxRef,\n panelRef,\n isOpen,\n}: {\n boxRef: RefObject<HTMLDivElement | null>;\n panelRef: RefObject<HTMLDivElement | null>;\n isOpen: boolean;\n}): boolean {\n const isPhone = useSyncExternalStore(\n subscribePhone,\n isPhoneNow,\n isPhoneOnServer,\n );\n\n // Asked once the box is on the page, and asked again if the viewport\n // changed, since that is the only thing here that changes the answer's\n // consequences. The layout effect answers before anything is painted.\n const [isFramed, setIsFramed] = useState(false);\n useLayoutEffect(() => {\n setIsFramed(boxRef.current?.offsetParent != null);\n }, [boxRef, isPhone]);\n\n const isSheet = isPhone && !isFramed;\n const isUp = isSheet && isOpen;\n\n useLayoutEffect(() => {\n if (!isUp) return;\n const panel = panelRef.current;\n const viewport = window.visualViewport;\n if (!panel || !viewport) return;\n\n let frame = 0;\n let until = 0;\n let top = -1;\n let height = -1;\n let keyboard = \"\";\n\n // Exactly what can be seen, top edge included: the keyboard coming up can\n // shove the layout viewport as well as shrink the visible one, and\n // `offsetTop` is the sum of that shove.\n //\n // Whole pixels, and only ever written when they change. Measuring runs\n // every frame while the keyboard moves, and the browser cannot tell a\n // style it has already been given from a new one: it lays the panel out\n // again either way, and a fractional height rewritten sixty times a second\n // is the thread re-wrapping sixty times a second.\n const fit = () => {\n const nextTop = Math.round(viewport.offsetTop);\n const nextHeight = Math.round(viewport.height);\n if (nextTop === top && nextHeight === height) return;\n top = nextTop;\n height = nextHeight;\n\n panel.style.top = `${top}px`;\n panel.style.height = `${height}px`;\n panel.style.bottom = \"auto\";\n\n // The home bar's inset is only worth room while the home bar is what is\n // down there. With the keyboard up the foot of the panel is the top of\n // the keyboard, and the inset is a strip of nothing between the two.\n const next = height < window.innerHeight - KEYBOARD_PX ? \"up\" : \"down\";\n if (next === keyboard) return;\n keyboard = next;\n panel.dataset.keyboard = next;\n };\n\n const follow = () => {\n fit();\n frame = performance.now() < until ? requestAnimationFrame(follow) : 0;\n };\n\n // The viewport reports where it has got to, not where it is going. Each\n // report is taken as a sign it is still moving, and the panel measures for\n // itself until the reports stop coming.\n const track = () => {\n until = performance.now() + SETTLE_MS;\n if (frame === 0) frame = requestAnimationFrame(follow);\n };\n\n fit();\n viewport.addEventListener(\"resize\", track);\n viewport.addEventListener(\"scroll\", track);\n // A tap on the composer is the first anybody knows about a keyboard: the\n // viewport says nothing until it has already started moving.\n panel.addEventListener(\"focusin\", track);\n\n return () => {\n if (frame !== 0) cancelAnimationFrame(frame);\n viewport.removeEventListener(\"resize\", track);\n viewport.removeEventListener(\"scroll\", track);\n panel.removeEventListener(\"focusin\", track);\n // Back to the classes' `inset-0`, for the floating panel these would\n // otherwise misplace.\n panel.style.top = \"\";\n panel.style.height = \"\";\n panel.style.bottom = \"\";\n delete panel.dataset.keyboard;\n };\n }, [panelRef, isUp]);\n\n usePageLock(isUp);\n\n return isSheet;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\n\n/**\n * Holds the host's page still underneath a full screen sheet.\n *\n * `overflow: hidden` is not a lock on a phone. Tapping a field inside a fixed\n * panel makes the browser scroll the page to bring the field above the\n * keyboard, and it scrolls a page that only said it had no overflow: the sheet\n * stays where it is, the page slides about behind it, and everything pinned to\n * the visual viewport chases that a frame late. That is the shudder.\n *\n * So the page is pinned instead, fixed at the offset it is already scrolled to.\n * It looks exactly the same and there is nothing left to scroll, which is the\n * only answer the keyboard takes. Letting go puts the offset back first, so the\n * page never flashes at the top on the way out.\n *\n * Width is deliberately not set. A fixed box with both edges pinned already\n * works out to the width the page had, margins and all, and saying `100%` on\n * top of that hangs the host's own margin off the right hand side.\n *\n * Everything it touches is written down first and put back after. This is\n * somebody else's body, and they may have had an opinion about all of it.\n */\nexport function usePageLock(isLocked: boolean) {\n useEffect(() => {\n if (!isLocked) return;\n\n const { style } = document.body;\n const held = {\n position: style.position,\n top: style.top,\n left: style.left,\n right: style.right,\n overflow: style.overflow,\n };\n const scrollY = window.scrollY;\n\n style.position = \"fixed\";\n style.top = `${-scrollY}px`;\n style.left = \"0\";\n style.right = \"0\";\n style.overflow = \"hidden\";\n\n return () => {\n style.position = held.position;\n style.top = held.top;\n style.left = held.left;\n style.right = held.right;\n style.overflow = held.overflow;\n // Instant, or a host who asked for smooth scrolling watches their page\n // sail back down from the top while the sheet is still coming off it.\n window.scrollTo({ top: scrollY, behavior: \"instant\" });\n };\n }, [isLocked]);\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { X } from \"@/components/icons\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { cn } from \"@/lib/utils\";\nimport type { LauncherSide } from \"./launcher-position\";\nimport { plainTextOf } from \"./plain-text\";\nimport type { TeaserPlacement } from \"./use-teaser-placement\";\nimport { WidgetAvatar } from \"./widget-avatar\";\nimport type { SupportMessage } from \"./types\";\n\n/**\n * The card's own width. Narrower than the panel it stands in for, so it\n * reads as a note left on the button rather than the panel half open. Never\n * wider than the box, which on a phone is the box saying so.\n */\nconst WIDTH = \"min(18rem, 100%)\";\n\n/** The gap between the card and the button it belongs to. */\nconst GAP = \"0.5rem\";\n\n/**\n * A reply, shown on the closed button so somebody sees what came in without\n * opening anything.\n *\n * The count on the button says something arrived; this says what. One card,\n * for the newest unread reply, with the sender's name and face over the\n * first couple of lines. Pressing it opens the panel, and the cross in the\n * corner waves it away without opening anything.\n *\n * Two buttons rather than one with a cross inside it, because a button\n * inside a button is not a thing a browser will let you have. The cross is\n * a sibling, sat over the corner of the card it dismisses.\n *\n * Kept mounted while it leaves rather than unmounted on the spot, so the\n * dismissal is the card fading rather than vanishing. The last message is\n * held for that, since by then the caller has stopped passing one.\n */\nexport function WidgetTeaser({\n message,\n isShown,\n side,\n placement,\n buttonY,\n buttonSize,\n onOpen,\n onDismiss,\n}: {\n /** The reply to show, or null once there is none. */\n message: SupportMessage | null;\n /** Whether it is on screen. False leaves it fading out in place. */\n isShown: boolean;\n /** Which edge the button is parked against. The card lines up with it. */\n side: LauncherSide;\n placement: TeaserPlacement;\n /** The button's top inside the box, as a CSS length. */\n buttonY: string;\n buttonSize: string;\n onOpen: () => void;\n onDismiss: () => void;\n}) {\n // What was last shown, for the fade out after the caller lets go of it.\n // Settled during render rather than in an effect, so the frame the caller\n // drops the message is the frame the card starts leaving.\n const [held, setHeld] = useState(message);\n if (message !== null && message !== held) setHeld(message);\n const shown = message ?? held;\n if (shown === null) return null;\n\n const agent = shown.agent;\n const text = plainTextOf(shown.body);\n\n return (\n <div\n key={shown.id}\n inert={!isShown}\n // Announced as it lands, so a screen reader hears that a reply came\n // in without having to find the corner of the page it landed in.\n role=\"status\"\n aria-live=\"polite\"\n style={{\n width: WIDTH,\n [side]: 0,\n ...(placement === \"above\"\n ? { bottom: `calc(100% - ${buttonY} + ${GAP})` }\n : { top: `calc(${buttonY} + ${buttonSize} + ${GAP})` }),\n }}\n className={cn(\n \"absolute\",\n // Grows out of the corner nearest the button, so it reads as coming\n // from it rather than landing beside it.\n placement === \"above\"\n ? side === \"right\"\n ? \"origin-bottom-right\"\n : \"origin-bottom-left\"\n : side === \"right\"\n ? \"origin-top-right\"\n : \"origin-top-left\",\n \"transition-[opacity,translate,scale] motion-reduce:transition-none\",\n isShown\n ? [\n \"pointer-events-auto opacity-100 duration-300 ease-spring\",\n // The arrival, once. The transition above takes over after.\n \"animate-in fade-in-0 zoom-in-95 duration-300 ease-spring motion-reduce:animate-none\",\n placement === \"above\"\n ? \"slide-in-from-bottom-2\"\n : \"slide-in-from-top-2\",\n ]\n : \"pointer-events-none scale-95 opacity-0 duration-150 ease-out-quint\",\n )}\n >\n <button\n type=\"button\"\n onClick={onOpen}\n aria-label={\n agent ? `Read the reply from ${agent.name}` : \"Read the reply\"\n }\n className={cn(\n // Its own radius scale, like the panel, so the app's token cannot\n // reshape a card that sits on somebody else's site.\n \"block w-full rounded-xl border bg-card p-3 pr-9 text-left text-card-foreground shadow-lg [--radius:0.625rem]\",\n \"transition-[background-color,box-shadow] outline-none\",\n \"hover:bg-muted/50 focus-visible:ring-3 focus-visible:ring-ring/50\",\n \"cursor-pointer select-none\",\n )}\n >\n <span className=\"flex items-center gap-1.5\">\n {agent && (\n <>\n <WidgetAvatar agent={agent} className=\"size-5 rounded-md\" />\n <span className=\"truncate text-xs font-medium\">\n {agent.name}\n </span>\n {agent.kind === \"ai\" && (\n <Badge variant=\"muted\" className=\"shrink-0 rounded-md px-1\">\n AI\n </Badge>\n )}\n </>\n )}\n <span className=\"ml-auto shrink-0 text-xs text-muted-foreground tabular-nums\">\n {shown.time}\n </span>\n </span>\n\n <span className=\"mt-1 line-clamp-2 block text-sm leading-snug\">\n {text.length > 0 ? text : \"Sent a file\"}\n </span>\n </button>\n\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className={cn(\n \"absolute top-2 right-2 grid size-6 place-items-center rounded-md\",\n \"text-muted-foreground transition-colors outline-none\",\n \"hover:bg-muted hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50\",\n \"cursor-pointer\",\n )}\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n );\n}\n","/**\n * A message read aloud rather than rendered: what a reply says, with the\n * markdown taken off it, for the one line a teaser has room for.\n *\n * Light-handed on purpose, and the same reading the inbox's own preview\n * uses. A fence line goes entirely and the code between stays, a link reads\n * as its text, and emphasis marks come off. Anything this misses is shown\n * as typed, which is a fair result for a preview.\n */\nexport function plainTextOf(markdown: string): string {\n return (\n markdown\n .replace(/^\\s*(?:```|~~~).*$/gm, \"\")\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, \"$1\")\n .replace(/[*`_~]/g, \"\")\n .replace(/^\\s*#{1,6}\\s+/gm, \"\")\n .replace(/^\\s*[-+]\\s+/gm, \"\")\n .replace(/^\\s*>\\s?/gm, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\n/**\n * How long to keep looking for something that may not be on the page yet.\n * A navigation is usually still resolving when the instruction lands, so the\n * element the tool means is often a route change away.\n */\nconst FIND_TIMEOUT_MS = 4_000;\n\n/** How long the ring stays once it has found something. */\nconst HOLD_MS = 2_600;\n\n/** The fade at the end, which is also how long the node outlives the hold. */\nconst FADE_MS = 300;\n\n/** Above the host's own chrome. Their z-indexes are not ours to guess at. */\nconst LAYER = 2_147_483_000;\n\nfunction prefersReducedMotion(): boolean {\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/**\n * A ring drawn over something on the host's page, because one of their tools\n * asked for it to be pointed at.\n *\n * Nothing on their page is touched. The ring is a box of our own, positioned\n * over the element's rectangle and following it every frame, so a page that\n * scrolls, resizes or animates underneath keeps the ring where the thing is,\n * and there is no style of theirs to put back afterwards.\n *\n * It also waits. The instruction rides the same reply that moves the page, so\n * the element it names is usually a route change away and not in the document\n * yet; this keeps looking for a few seconds and gives up quietly rather than\n * ringing the wrong thing or nothing at all.\n *\n * In `document.body` rather than where the widget sits, since a `fixed` box\n * inside a host container that happens to carry a transform is fixed to that\n * container instead of to the window, and this one has to line up with an\n * element anywhere on their page.\n */\nexport function WidgetSpotlight({ selector }: { selector: string }) {\n const [isShown, setIsShown] = useState(false);\n const [isLeaving, setIsLeaving] = useState(false);\n const ring = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n let target: Element | null = null;\n let frame = 0;\n let startedAt = 0;\n let foundAt = 0;\n let stopped = false;\n let leaveTimer: ReturnType<typeof setTimeout> | undefined;\n\n function find(): Element | null {\n try {\n return document.querySelector(selector);\n } catch {\n // Not a selector at all. Median checks the shape of one before it is\n // stored, but only a browser can say whether it parses.\n console.error(\n `Median: a tool asked to highlight ${selector}, which is not a valid CSS selector.`,\n );\n stopped = true;\n return null;\n }\n }\n\n function tick(now: number) {\n if (stopped) return;\n if (startedAt === 0) startedAt = now;\n\n if (target === null) {\n target = find();\n if (stopped) return;\n\n if (target === null) {\n // Still not there. It may be one route change behind us.\n if (now - startedAt > FIND_TIMEOUT_MS) return;\n frame = requestAnimationFrame(tick);\n return;\n }\n\n foundAt = now;\n target.scrollIntoView({\n behavior: prefersReducedMotion() ? \"auto\" : \"smooth\",\n block: \"center\",\n });\n setIsShown(true);\n }\n\n // Written straight onto the node rather than held in state: this runs\n // every frame for a couple of seconds, and a re-render per frame to\n // move one box is a cost the host's page would pay for nothing.\n const node = ring.current;\n if (node !== null) {\n const rect = target.getBoundingClientRect();\n node.style.transform = `translate(${rect.left}px, ${rect.top}px)`;\n node.style.width = `${rect.width}px`;\n node.style.height = `${rect.height}px`;\n }\n\n if (now - foundAt > HOLD_MS) {\n setIsLeaving(true);\n leaveTimer = setTimeout(() => setIsShown(false), FADE_MS);\n return;\n }\n frame = requestAnimationFrame(tick);\n }\n\n frame = requestAnimationFrame(tick);\n return () => {\n stopped = true;\n cancelAnimationFrame(frame);\n clearTimeout(leaveTimer);\n };\n }, [selector]);\n\n if (!isShown || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n ref={ring}\n aria-hidden\n // Portalled to the body, outside the launcher's box, so it carries the\n // published stylesheet's scope hook itself.\n data-median-widget=\"\"\n style={{ zIndex: LAYER, top: 0, left: 0 }}\n className=\"pointer-events-none fixed\"\n >\n {/* Two layers of the same box: one that holds the outline, and one\n that swells out of it and fades, which is the part the eye catches\n on a page somebody is already looking at. */}\n <span\n className={[\n \"absolute -inset-1 rounded-lg outline-2 outline-offset-0 outline-primary\",\n \"shadow-[0_0_0_6px_color-mix(in_oklch,var(--primary)_20%,transparent)]\",\n \"transition-opacity duration-300 ease-out motion-reduce:transition-none\",\n isLeaving ? \"opacity-0\" : \"opacity-100\",\n ].join(\" \")}\n />\n <span\n className={[\n \"absolute -inset-1 rounded-lg outline-2 outline-primary\",\n \"animate-ping opacity-60 motion-reduce:animate-none\",\n isLeaving ? \"hidden\" : \"\",\n ].join(\" \")}\n />\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"@/lib/utils\";\nimport { WidgetAvatar } from \"./widget-avatar\";\nimport type { SupportAgent } from \"./types\";\n\n/** How long it stays. Long enough to read twice, short enough to forgive. */\nconst STAY_MS = 5_000;\n\n/** The travel at either end. */\nconst MOVE_MS = 250;\n\n/** Above the host's own chrome, and above the ring it explains. */\nconst LAYER = 2_147_483_001;\n\n/**\n * A line at the foot of the page saying who moved it.\n *\n * A page changing under somebody who did not touch anything is the one thing\n * a widget can do that feels like it has been let loose, so it says so, by\n * name, where a browser already puts its own status line.\n *\n * Nothing to click: it cannot be in the way of whatever they came to do, and\n * it takes itself off. In `document.body` for the same reason the ring is: a\n * host container with a transform on it would otherwise capture the fixed\n * position and put this somewhere that is not the bottom of the window.\n */\nexport function WidgetToast({\n agent,\n children,\n}: {\n /** Who did it, so the line can say so with their own face on it. */\n agent: SupportAgent;\n children: React.ReactNode;\n}) {\n const [isShown, setIsShown] = useState(false);\n\n useEffect(() => {\n // Up on the frame after it mounts, so it rises into place rather than\n // being there suddenly.\n const frame = requestAnimationFrame(() => setIsShown(true));\n const timer = setTimeout(() => setIsShown(false), STAY_MS);\n return () => {\n cancelAnimationFrame(frame);\n clearTimeout(timer);\n };\n }, []);\n\n if (typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n // Portalled to the body, outside the launcher's box, so it carries the\n // published stylesheet's scope hook itself.\n data-median-widget=\"\"\n style={{ zIndex: LAYER, transitionDuration: `${MOVE_MS}ms` }}\n // A live region rather than a thing to find: somebody using a screen\n // reader is told the page moved without having to go looking for the\n // line that says so.\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n \"pointer-events-none fixed bottom-4 left-1/2 flex max-w-[calc(100vw-2rem)] items-center gap-2\",\n \"-translate-x-1/2 rounded-full border bg-card py-1.5 pr-4 pl-1.5 shadow-lg\",\n \"text-sm text-card-foreground\",\n // `translate`, which is the property `translate-y-*` sets. Under\n // `transform` the line used to arrive in one frame with only its\n // opacity easing.\n \"transition-[opacity,translate] ease-out motion-reduce:transition-none\",\n isShown\n ? \"translate-y-0 opacity-100\"\n : \"pointer-events-none translate-y-2 opacity-0\",\n )}\n >\n <WidgetAvatar agent={agent} className=\"size-6 rounded-full\" />\n <span className=\"truncate\">{children}</span>\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport { queueCustomData } from \"./custom-data\";\nimport {\n createOpenStore,\n isDevelopment,\n useOpenState,\n useRegister,\n} from \"./open-store\";\nimport {\n reportError,\n type MedianErrorReportOptions,\n type MedianErrorReportOutcome,\n} from \"./report-error\";\nimport { resetSessions } from \"./session\";\nimport { resetVisitorEmails } from \"./visitor-email\";\n\n/**\n * Driving the support panel from anywhere on the page. The open state lives\n * in `open-store.ts`, which the feedback panel keeps its own copy of; this\n * file is the three things that are the support widget's alone, `attach`,\n * `reportError` and `reset`, and the shape a host reaches for them through.\n */\nconst store = createOpenStore(\"MedianSupport\");\n\n/**\n * The widget from anywhere, React or not: the same shape the hook hands\n * back, for a plain `onclick` or a shortcut listener that never sees a\n * component. `isOpen` reads live but does not re-render anything; the hook\n * is for that.\n */\nexport const medianSupport = {\n /** What the panel is doing right now. */\n get isOpen() {\n return store.readEffective();\n },\n open() {\n store.request(true);\n store.warnIfNothingIsMounted(\"the widget was asked to open\");\n },\n close() {\n store.request(false);\n },\n toggle() {\n const next = !store.readEffective();\n store.request(next);\n if (next) store.warnIfNothingIsMounted(\"the widget was asked to open\");\n },\n /**\n * Put your own data on the next bug report: a crash trace from your error\n * handler, a request id, the state of a store. Objects are written out as\n * JSON. Entries ride the visitor's next message and land on the report,\n * whether or not diagnostics are on.\n */\n attach(label: string, value: unknown) {\n if (!queueCustomData(label, value)) {\n if (isDevelopment) {\n console.warn(\n \"Median: attach() needs a label and a value, and nothing was queued. Pass a short label naming the data, and the data itself.\",\n );\n }\n return;\n }\n store.warnIfNothingIsMounted(\"data was attached\");\n },\n /**\n * File the crash your error screen is showing, with everything the browser\n * was doing when it happened. One press from a \"Report error\" button:\n *\n * const outcome = await medianSupport.reportError(error);\n *\n * It answers rather than throws, so the screen can say whether it landed.\n * It works from a boundary with no widget left under it, which is most of\n * them.\n */\n reportError(error: unknown, options?: MedianErrorReportOptions) {\n return reportError(error, options);\n },\n /**\n * Forget this browser's conversation, so the next one starts fresh and\n * anonymous. Call it when your user signs out: whoever sits down next\n * should not find somebody else's thread waiting.\n */\n reset() {\n resetSessions();\n resetVisitorEmails();\n },\n} satisfies MedianSupportControl;\n\n/** The shape of {@link medianSupport}, and of what the hook returns. */\nexport type MedianSupportControl = {\n /** Whether the panel is open. */\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n /** Put your own data on the next bug report: a crash trace, an id. */\n attach: (label: string, value: unknown) => void;\n /** File the crash your error screen is showing. For a report button. */\n reportError: (\n error: unknown,\n options?: MedianErrorReportOptions,\n ) => Promise<MedianErrorReportOutcome>;\n /** Forget this browser's conversation. For sign out. */\n reset: () => void;\n};\n\n/**\n * The widget, from anywhere else on the page:\n *\n * const support = useMedianSupport();\n *\n * <button onClick={support.open}>Contact us</button>\n *\n * `isOpen` follows the panel however it was opened, so a trigger can render\n * itself as pressed, or step out of the way while the panel is up.\n */\nexport function useMedianSupport(): MedianSupportControl {\n const isOpen = useSyncExternalStore(\n store.subscribe,\n store.readEffective,\n store.readServerEffective,\n );\n\n return {\n isOpen,\n open: medianSupport.open,\n close: medianSupport.close,\n toggle: medianSupport.toggle,\n attach: medianSupport.attach,\n reportError: medianSupport.reportError,\n reset: medianSupport.reset,\n };\n}\n\n/** The panel's own settled open state. See {@link useOpenState}. */\nexport function useMedianOpenState(options: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): [boolean, (next: boolean) => void] {\n return useOpenState(store, options);\n}\n\n/** One widget per page, and a word in the console when there are two. */\nexport function useRegisterMedianSupport() {\n useRegister(store);\n}\n","/**\n * Data somebody chose to put on a bug report: a crash trace, a request id,\n * the state of a store when it fell over.\n *\n * The deliberate third of the telemetry. Context is what the browser knows,\n * diagnostics are what the widget caught on its own; this is what the host's\n * code or the agent decided the team should see, word for word. Because it is\n * handed over on purpose, it does not wait behind the diagnostics switch.\n *\n * Pure on purpose, like `diagnostics.ts` next door: the SDK cleans what it\n * queues with this file before it sends, and the backend cleans it again with\n * the same file before it stores, so neither side is trusting the other's\n * arithmetic.\n */\n\nexport type CustomDataEntry = {\n /** What the value is, in a few words. The entry's heading on the report. */\n label: string;\n /** The thing itself, kept exactly as written, up to the cap. */\n value: string;\n};\n\n/** The most entries one report carries. Newest kept, oldest dropped. */\nexport const MAX_CUSTOM_ENTRIES = 8;\n\nexport const CUSTOM_LABEL_MAX_LENGTH = 60;\n\n/** Room for a real stack trace, not just its first line. */\nexport const CUSTOM_VALUE_MAX_LENGTH = 4_000;\n\nfunction cleanLabel(input: unknown): string | undefined {\n if (typeof input !== \"string\") return undefined;\n const label = input.trim().slice(0, CUSTOM_LABEL_MAX_LENGTH);\n return label.length > 0 ? label : undefined;\n}\n\n/**\n * Whatever was handed over, written out as text. Objects become readable\n * JSON, because \"the state of the store\" arrives as an object, and making the\n * caller serialize it first is exactly the chore this exists to remove.\n */\nfunction cleanValue(input: unknown): string | undefined {\n let written: string | undefined;\n if (typeof input === \"string\") {\n written = input.trim();\n } else if (typeof input === \"number\" || typeof input === \"boolean\") {\n written = String(input);\n } else {\n try {\n written = JSON.stringify(input, null, 2);\n } catch {\n written = undefined;\n }\n }\n\n if (written === undefined || written.length === 0) return undefined;\n return written.length > CUSTOM_VALUE_MAX_LENGTH\n ? `${written.slice(0, CUSTOM_VALUE_MAX_LENGTH)}…`\n : written;\n}\n\n/**\n * Whatever arrived, cut down to what may be stored. Undefined when nothing\n * survived, so an empty list never lands on a row and reads later as \"they\n * attached something and it was blank\".\n *\n * One entry per label, the newest one winning: attaching a second crash\n * trace means the first one is no longer the crash.\n */\nexport function cleanCustomData(input: unknown): CustomDataEntry[] | undefined {\n if (!Array.isArray(input)) return undefined;\n\n const byLabel = new Map<string, string>();\n for (const raw of input) {\n if (typeof raw !== \"object\" || raw === null) continue;\n const entry = raw as Record<string, unknown>;\n const label = cleanLabel(entry.label);\n const value = cleanValue(entry.value);\n if (label === undefined || value === undefined) continue;\n // Re-set so a replaced label moves to the end, where the newest live.\n byLabel.delete(label);\n byLabel.set(label, value);\n }\n\n const entries = [...byLabel].map(([label, value]) => ({ label, value }));\n return entries.length > 0 ? entries.slice(-MAX_CUSTOM_ENTRIES) : undefined;\n}\n\n/**\n * Several sources of entries, oldest source first, folded into one list. The\n * same rules as cleaning: one entry per label, later wins, newest kept when\n * the cap says something has to go.\n */\nexport function mergeCustomData(\n ...sources: (CustomDataEntry[] | undefined)[]\n): CustomDataEntry[] | undefined {\n return cleanCustomData(sources.flatMap((entries) => entries ?? []));\n}\n","\"use client\";\n\nimport {\n cleanCustomData,\n mergeCustomData,\n type CustomDataEntry,\n} from \"@median/backend/customData\";\n\n/**\n * Data the host hands over on purpose, waiting to ride the next message: a\n * crash trace from their error handler, a request id, the state of a store.\n *\n * The deliberate cousin of the diagnostics ring buffer next door, and module\n * level for the same reason: a crash handler runs wherever the crash was,\n * usually nowhere near React, and sometimes before the widget has mounted.\n * Unlike diagnostics it does not wait behind a switch, because calling\n * `attach` is the host offering it.\n *\n * Nothing is sent on its own. Entries ride the next message the visitor\n * sends, land on the conversation, and are copied onto a bug report the\n * moment one is filed.\n */\n\nlet queued: CustomDataEntry[] = [];\n\n/** True when the entry survived cleaning and is waiting for a send. */\nexport function queueCustomData(label: unknown, value: unknown): boolean {\n const cleaned = cleanCustomData([{ label, value }]);\n if (cleaned === undefined) return false;\n\n queued = mergeCustomData(queued, cleaned) ?? [];\n return true;\n}\n\n/**\n * What a send takes with it: everything attached since the last one, or\n * nothing, so a quiet page costs nothing. Drained rather than copied; a send\n * that fails hands its entries back through {@link restoreCustomData}.\n */\nexport function takeCustomData(): CustomDataEntry[] | undefined {\n if (queued.length === 0) return undefined;\n const taken = queued;\n queued = [];\n return taken;\n}\n\n/** A failed send's entries, back in the queue so the retry still has them. */\nexport function restoreCustomData(entries: CustomDataEntry[]): void {\n // The failed send's entries are the older side: anything attached since\n // the failure wins a collision.\n queued = mergeCustomData(entries, queued) ?? [];\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useSyncExternalStore } from \"react\";\n\n/**\n * Whether a panel is open, kept outside React.\n *\n * The widget is mounted once, usually in a root layout. The thing that opens\n * it is usually somewhere else entirely: a \"Contact us\" item in a nav, a\n * \"Share feedback\" row in a menu, a keyboard shortcut. Holding this in a\n * module rather than in the panel's own state is what lets those reach it\n * without a host threading state through their whole tree, or wrapping their\n * app in a provider of ours.\n *\n * Two values rather than one, because the host has the last word:\n *\n * - `requested` is what the page last asked for, including the widget's own\n * controls. Null until something asks, so `defaultOpen` still means\n * something on first paint.\n * - `effective` is what the panel is actually doing. A host driving it with\n * the `open` prop can ignore a request, so anything reading the state back\n * reads this one.\n *\n * One store per panel: the support widget and the feedback panel are two\n * things a page can open, and opening one must never open the other.\n */\n\n// The `typeof` guard is for the published bundle, where no framework has\n// promised that `process` exists. A bundler that defines it leaves this line\n// statically true or false; a page without one gets production behavior.\nexport const isDevelopment =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"development\";\n\nexport type OpenStore = ReturnType<typeof createOpenStore>;\n\nexport function createOpenStore(component: string) {\n let requested: boolean | null = null;\n let effective = false;\n let mounted = 0;\n const listeners = new Set<() => void>();\n\n function emit() {\n for (const listener of listeners) listener();\n }\n\n return {\n /** The component a warning should name, so it reads like the host's code. */\n component,\n\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n\n readRequested: () => requested,\n readEffective: () => effective,\n\n /**\n * The server has no page to open a panel on, and neither does the first\n * client paint, which is what keeps hydration quiet.\n */\n readServerRequested: () => null as boolean | null,\n readServerEffective: () => false,\n\n request(next: boolean) {\n requested = next;\n emit();\n },\n\n /** Told, not asked: the panel saying what it settled on. */\n settle(next: boolean) {\n if (effective === next) return;\n effective = next;\n emit();\n },\n\n countMounted() {\n mounted += 1;\n return mounted;\n },\n\n countUnmounted() {\n mounted -= 1;\n // With nothing on the page, nothing is open, whatever the last one to\n // leave was doing. What was asked for is kept, so a widget that comes\n // back on the next route comes back the way it went.\n if (mounted === 0 && effective) {\n effective = false;\n emit();\n }\n },\n\n /**\n * The likeliest way to spend an afternoon on this: call `open()`, watch\n * nothing happen, and never find out that the component is not on the\n * page. So it says so, in the console, where that afternoon is being\n * spent.\n *\n * Asked a second later rather than now, because a static button wired up\n * before React has hydrated is early, not wrong. The request is kept\n * either way, so a panel that mounts afterwards picks it up.\n */\n warnIfNothingIsMounted(did: string) {\n if (!isDevelopment || mounted > 0) return;\n\n setTimeout(() => {\n if (mounted > 0) return;\n console.warn(\n `Median: ${did}, but no <${component}> is on the page. Mount it once, near the root of your app.`,\n );\n }, 1000);\n },\n };\n}\n\n/**\n * The state a panel actually renders with, and the one place the three ways\n * of driving it are settled:\n *\n * 1. `open`, if the host passed it. Controlled wins, always.\n * 2. Whatever the page last asked for, through a trigger or the hook.\n * 3. `defaultOpen`, until anything at all has happened.\n *\n * A request is reported to `onOpenChange` either way, so a controlled host\n * hears about their own nav item pressing open just as they hear about ours.\n */\nexport function useOpenState(\n store: OpenStore,\n {\n open,\n defaultOpen = false,\n onOpenChange,\n }: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n },\n): [boolean, (next: boolean) => void] {\n const asked = useSyncExternalStore(\n store.subscribe,\n store.readRequested,\n store.readServerRequested,\n );\n const isOpen = open ?? asked ?? defaultOpen;\n\n // So a trigger reading `isOpen` back is never a frame behind the panel it\n // opened.\n useEffect(() => {\n store.settle(isOpen);\n }, [store, isOpen]);\n\n const setOpen = useCallback(\n (next: boolean) => {\n store.request(next);\n onOpenChange?.(next);\n },\n [store, onOpenChange],\n );\n\n return [isOpen, setOpen];\n}\n\n/**\n * One of each per page. Two would share the state above and open together,\n * which is never what anyone meant, so it says so where it will be read.\n */\nexport function useRegister(store: OpenStore) {\n useEffect(() => {\n if (store.countMounted() > 1 && isDevelopment) {\n console.warn(\n `Median: more than one <${store.component}> is mounted. They share one open state and open together. Mount it once, near the root of your app.`,\n );\n }\n return () => store.countUnmounted();\n }, [store]);\n}\n","/* eslint-disable */\n/**\n * Generated `api` utility.\n *\n * THIS CODE IS AUTOMATICALLY GENERATED.\n *\n * To regenerate, run `npx convex dev`.\n * @module\n */\n\nimport { anyApi, componentsGeneric } from \"convex/server\";\n\n/**\n * A utility for referencing Convex functions in your app's API.\n *\n * Usage:\n * ```js\n * const myFunctionReference = api.myModule.myFunction;\n * ```\n */\nexport const api = anyApi;\nexport const internal = anyApi;\nexport const components = componentsGeneric();\n","import { cleanTitle } from \"./signals\";\n\n/**\n * A crash, in the vocabulary both sides share.\n *\n * A page that has fallen over is the one report nobody types: whoever was\n * using it can see that it broke and has nothing to add about why. So the\n * error describes itself, and this file is what it turns into on the Signal\n * tab.\n *\n * Deliberately pure, like `signals.ts` and `feedback.ts` next door. The SDK\n * trims a crash with this file before it sends and the mutation trims it\n * again on arrival, so neither side is trusting the other's arithmetic.\n *\n * Nothing here asks a model. A report somebody pressed a button for has to\n * land, and it has to land under the same title as the last twenty copies of\n * the same crash, which is what makes the list one row rather than twenty.\n */\n\n/** What the boundary saw, as it hands it over. */\nexport type Crash = {\n /** The error's own line, without its stack. */\n message: string;\n /** \"TypeError\", when the thrown thing had a name worth keeping. */\n name?: string;\n stack?: string;\n /** The framework's id for an error that happened on the server. */\n digest?: string;\n /** The component stack, when the boundary was handed one. */\n componentStack?: string;\n /** The route it happened on, as the app's own router writes it. */\n route?: string;\n};\n\n/** One line of error, the same cap a diagnostic message gets. */\nexport const CRASH_MESSAGE_MAX_LENGTH = 300;\n\n/** Room for a real stack, matching what one attachment may hold. */\nexport const CRASH_STACK_MAX_LENGTH = 4_000;\n\nexport const CRASH_NAME_MAX_LENGTH = 60;\nexport const CRASH_ROUTE_MAX_LENGTH = 200;\n\n/** When the thrown thing said nothing for itself. */\nconst UNNAMED = \"Unnamed error\";\n\n/**\n * Names that add nothing to a title. Every thrown thing in a browser is an\n * error, so saying so twice only costs room the message wanted.\n */\nconst GENERIC_NAMES = [\"error\", \"exception\"];\n\nfunction trim(value: unknown, limit: number): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const clean = value.trim().slice(0, limit);\n return clean.length > 0 ? clean : undefined;\n}\n\n/** Whatever arrived, cut down to what may be stored. */\nexport function cleanCrash(input: unknown): Crash {\n const raw =\n typeof input === \"object\" && input !== null\n ? (input as Record<string, unknown>)\n : {};\n\n const name = trim(raw.name, CRASH_NAME_MAX_LENGTH);\n const stack = trim(raw.stack, CRASH_STACK_MAX_LENGTH);\n const digest = trim(raw.digest, CRASH_NAME_MAX_LENGTH);\n const componentStack = trim(raw.componentStack, CRASH_STACK_MAX_LENGTH);\n const route = trim(raw.route, CRASH_ROUTE_MAX_LENGTH);\n\n return {\n message: trim(raw.message, CRASH_MESSAGE_MAX_LENGTH) ?? UNNAMED,\n ...(name !== undefined ? { name } : {}),\n ...(stack !== undefined ? { stack } : {}),\n ...(digest !== undefined ? { digest } : {}),\n ...(componentStack !== undefined ? { componentStack } : {}),\n ...(route !== undefined ? { route } : {}),\n };\n}\n\n/**\n * The error on one line: \"TypeError: user.plan is not a function\".\n *\n * The name is dropped when the message already opens with it, which is what\n * a stack's first line looks like when a host passes one straight through.\n */\nexport function crashLabel(crash: Crash): string {\n const name = crash.name;\n if (name === undefined) return crash.message;\n if (GENERIC_NAMES.includes(name.toLowerCase())) return crash.message;\n if (crash.message.toLowerCase().startsWith(name.toLowerCase())) {\n return crash.message;\n }\n return `${name}: ${crash.message}`;\n}\n\n/**\n * How the row reads in the bug list.\n *\n * The route leads, because it is what makes two crashes the same crash: the\n * error's own line can run long and be cut, and what survives the cut should\n * still be the thing that groups them. The exact words matter more here than\n * anywhere else, since the filing mutation dedupes on them.\n */\nexport function crashTitle(crash: Crash): string {\n const label = crashLabel(crash);\n return cleanTitle(\n crash.route === undefined\n ? `Crash: ${label}`\n : `Crash on ${crash.route}: ${label}`,\n );\n}\n\n/** What the team reads first: what broke, and where. */\nexport function crashBody(crash: Crash): string {\n return [\n `The page stopped working${\n crash.route === undefined ? \"\" : ` on ${crash.route}`\n } and somebody reported it from the error screen.`,\n \"\",\n `**Error**: ${crashLabel(crash)}`,\n ...(crash.digest === undefined ? [] : [`**Digest**: ${crash.digest}`]),\n ].join(\"\\n\");\n}\n\n/**\n * The reporter's own line on the report. They pressed a button rather than\n * writing a sentence, so it says what the button did and what it saw.\n */\nexport function crashQuote(crash: Crash): string {\n return `Reported from the error screen: ${crashLabel(crash)}`;\n}\n\n/**\n * The long parts, as attachments rather than as body text: the stack belongs\n * to this one crash, and the body is shared with every other report of it.\n */\nexport function crashAttachments(crash: Crash): { label: string; value: string }[] {\n return [\n ...(crash.stack === undefined\n ? []\n : [{ label: \"Crash trace\", value: crash.stack }]),\n ...(crash.componentStack === undefined\n ? []\n : [{ label: \"Component stack\", value: crash.componentStack }]),\n ];\n}\n","\"use client\";\n\nimport { api } from \"@median/backend\";\nimport { cleanCrash, type Crash } from \"@median/backend/crashes\";\nimport { mergeCustomData } from \"@median/backend/customData\";\nimport { ConvexHttpClient } from \"convex/browser\";\nimport { useSyncExternalStore } from \"react\";\nimport { collectContext, collectPage } from \"./context\";\nimport { restoreCustomData, takeCustomData } from \"./custom-data\";\nimport { MEDIAN_DEPLOYMENT_URL } from \"./deployment\";\nimport { snapshotNow } from \"./diagnostics\";\nimport { hasInstall, readInstall, subscribeInstall } from \"./install\";\nimport { getOrCreateSessionId } from \"./session\";\nimport { splitIdentity, type MedianUser } from \"./use-median-thread\";\n\n/**\n * Filing the crash the visitor is looking at.\n *\n * Every other send in the SDK starts with somebody typing. This one starts\n * with a page that has stopped working, which is the report nobody writes:\n * whoever was using it can see that it broke and has nothing to add about\n * why. So the error describes itself, the browser hands over what it was\n * doing, and one press files it.\n *\n * It brings its own connection and reads its key from the last widget that\n * mounted, because by the time this runs the tree that widget lived in has\n * usually been replaced by the error screen calling it. Nothing here needs a\n * component, a provider, or a panel on the page.\n *\n * It never throws. A crash screen that crashes reporting a crash is a poor\n * apology, so everything that can go wrong comes back as a reason instead.\n */\n\nexport type MedianErrorReportOptions = {\n /**\n * The key, when no widget has mounted on this page to remember it. Both\n * panels write theirs down as they mount, so an app with either one\n * installed can leave this alone.\n */\n apiKey?: string;\n /** Who is in the chair. Defaults to whoever the mounted widget was given. */\n user?: MedianUser;\n /**\n * Where it happened, when your router names the page better than its URL\n * does: \"/orders/[id]\" rather than \"/orders/8912\". It leads the title, so\n * the same crash on the same route is one row on the list however many\n * people hit it. Defaults to the path in the address bar.\n */\n route?: string;\n /** React's component stack, when your boundary was handed one. */\n componentStack?: string;\n /** Facts to put on the report, the same shape as `appState`. */\n state?: Record<string, string | number | boolean>;\n /** Blocks to attach, the same shape and limits as `attach`. */\n attach?: Record<string, unknown>;\n /** Whether the report carries what the browser knows. On by default. */\n telemetry?: boolean;\n};\n\n/** Where the report went, or why it did not go. */\nexport type MedianErrorReportOutcome =\n | {\n reported: true;\n /** True when somebody had already reported this one. */\n joined: boolean;\n }\n | { reported: false; reason: string };\n\n/** Why a report did not land, in words the host can act on. */\nconst REASONS = {\n noKey:\n \"Median has no API key on this page, so the crash could not be reported. Mount <MedianSupport> or pass apiKey to reportError.\",\n noDeployment:\n \"The Median widget was built without a deployment URL, so the crash could not be reported.\",\n noBrowser: \"reportError only runs in a browser.\",\n off: \"This site is not taking reports right now.\",\n failed: \"The report could not be sent. Check the connection and try again.\",\n} as const;\n\nlet client: ConvexHttpClient | null = null;\n\n/**\n * Anything thrown, as the fields a report is made of.\n *\n * Hosts throw all sorts. An Error is the common case, a string is the lazy\n * one, and a framework error is an Error with an id stapled to it. All three\n * arrive here and none of them should cost the report.\n */\nfunction crashFrom(error: unknown, options: MedianErrorReportOptions): Crash {\n const raw = (\n typeof error === \"object\" && error !== null ? error : {}\n ) as Record<string, unknown>;\n\n const message =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : typeof raw.message === \"string\"\n ? raw.message\n : String(error);\n\n return cleanCrash({\n message,\n name: error instanceof Error ? error.name : raw.name,\n stack: raw.stack,\n // Next puts one on every error that came from the server, and it is the\n // id in that server's own log line.\n digest: raw.digest,\n componentStack: options.componentStack ?? raw.componentStack,\n route: options.route ?? currentRoute(),\n });\n}\n\n/** The page it happened on, minus anything after the path. */\nfunction currentRoute(): string | undefined {\n if (typeof window === \"undefined\") return undefined;\n return window.location.pathname || undefined;\n}\n\n/**\n * The facts that belong beside the browser's, rather than inside the write-up.\n * Both of these read as a row on the report next to the viewport and the page.\n */\nfunction factsOf(crash: Crash): Record<string, string> {\n return {\n ...(crash.route !== undefined ? { route: crash.route } : {}),\n ...(crash.digest !== undefined ? { digest: crash.digest } : {}),\n };\n}\n\nexport async function reportError(\n error: unknown,\n options: MedianErrorReportOptions = {},\n): Promise<MedianErrorReportOutcome> {\n if (typeof window === \"undefined\") {\n return { reported: false, reason: REASONS.noBrowser };\n }\n\n const apiKey = options.apiKey ?? readInstall()?.apiKey;\n if (!apiKey) {\n console.error(REASONS.noKey);\n return { reported: false, reason: REASONS.noKey };\n }\n if (!MEDIAN_DEPLOYMENT_URL) {\n console.error(REASONS.noDeployment);\n return { reported: false, reason: REASONS.noDeployment };\n }\n\n const sessionId = getOrCreateSessionId(apiKey);\n if (sessionId === null) {\n return { reported: false, reason: REASONS.failed };\n }\n\n const crash = crashFrom(error, options);\n const telemetry = options.telemetry ?? true;\n const user = options.user ?? readInstall()?.user;\n const { facts, claim } = splitIdentity(user ?? null);\n\n // Whatever the host attached since the last send, plus whatever they handed\n // this call, drained the way a message drains it so nothing is sent twice.\n const custom = mergeCustomData(\n takeCustomData(),\n Object.entries(options.attach ?? {}).map(([label, value]) => ({\n label,\n value: typeof value === \"string\" ? value : JSON.stringify(value),\n })),\n );\n\n // Read here rather than on mount, like every other send: all of it is\n // wanted as \"what was true when it broke\".\n const context = telemetry ? collectContext() : undefined;\n const page = telemetry ? collectPage() : undefined;\n const diagnostics = snapshotNow({ ...factsOf(crash), ...options.state });\n\n try {\n client ??= new ConvexHttpClient(MEDIAN_DEPLOYMENT_URL);\n const outcome = await client.mutation(api.feedback.reportError, {\n apiKey,\n sessionId,\n error: crash,\n ...(user ? { user: facts } : {}),\n ...(claim ? { identity: claim } : {}),\n ...(context ? { context } : {}),\n ...(page ? { page } : {}),\n ...(diagnostics ? { diagnostics } : {}),\n ...(custom ? { customData: custom } : {}),\n });\n\n if (outcome === \"off\") {\n if (custom) restoreCustomData(custom);\n return { reported: false, reason: REASONS.off };\n }\n return { reported: true, joined: outcome === \"joined\" };\n } catch (caught) {\n // Back in the queue, so a second press still carries them.\n if (custom) restoreCustomData(custom);\n console.error(\"Median: sending the crash report failed\", caught);\n return { reported: false, reason: REASONS.failed };\n }\n}\n\n/**\n * Whether a report has anywhere to go: a widget has mounted on this page and\n * left its key, and this build knows which Median to send to.\n *\n * For a \"Report error\" button, which should not be on the screen at all if\n * pressing it could only ever fail. It follows the install rather than\n * reading it once, since an error screen can render before the widget does.\n */\nexport function useCanReportError(): boolean {\n const isInstalled = useSyncExternalStore(\n subscribeInstall,\n hasInstall,\n // The server renders nothing installed: it has no page to have mounted\n // on, and a button that flickered away on hydration is worse than one\n // that arrives a moment late.\n () => false,\n );\n\n return isInstalled && Boolean(MEDIAN_DEPLOYMENT_URL);\n}\n","import type {\n ConversationPage,\n DeviceKind,\n VisitorContext,\n} from \"@median/backend/telemetry\";\n\n/**\n * The handful of things the browser already knows that a support reply needs.\n *\n * Read at send time rather than watched, because all of it is only ever wanted\n * as \"what was true when they wrote\". Nothing is stored, nothing is polled,\n * and nothing leaves the page unless somebody actually gets in touch.\n *\n * The user agent is parsed here rather than sent up raw. A name and a major\n * version is what the inbox shows and all it can act on; the full string is a\n * fingerprint we would then be keeping on somebody else's customers.\n */\n\n/**\n * Browser names in the order they have to be tested.\n *\n * Every one of these lies about being the others. Chrome's string contains\n * Safari, Edge's contains Chrome and Safari, Opera's contains all three, so\n * the only thing that works is checking the most specific claim first and\n * taking the first hit.\n */\nconst BROWSERS: { name: string; token: RegExp }[] = [\n { name: \"Edge\", token: /Edg(?:e|A|iOS)?\\/(\\d+)/ },\n { name: \"Opera\", token: /OPR\\/(\\d+)/ },\n { name: \"Samsung Internet\", token: /SamsungBrowser\\/(\\d+)/ },\n { name: \"Firefox\", token: /(?:Firefox|FxiOS)\\/(\\d+)/ },\n { name: \"Chrome\", token: /(?:Chrome|CriOS)\\/(\\d+)/ },\n { name: \"Safari\", token: /Version\\/(\\d+).*Safari/ },\n];\n\nconst OPERATING_SYSTEMS: { name: string; token: RegExp }[] = [\n // Before Android, whose string also says Linux.\n { name: \"Android\", token: /Android/ },\n { name: \"iOS\", token: /iPhone|iPad|iPod/ },\n { name: \"macOS\", token: /Mac OS X|Macintosh/ },\n { name: \"Windows\", token: /Windows NT/ },\n { name: \"ChromeOS\", token: /CrOS/ },\n { name: \"Linux\", token: /Linux/ },\n];\n\nfunction browserOf(ua: string): string | undefined {\n for (const { name, token } of BROWSERS) {\n const match = ua.match(token);\n if (match) return match[1] ? `${name} ${match[1]}` : name;\n }\n return undefined;\n}\n\nfunction osOf(ua: string): string | undefined {\n return OPERATING_SYSTEMS.find(({ token }) => token.test(ua))?.name;\n}\n\n/**\n * Desktop, tablet, or phone.\n *\n * An iPad reports itself as a Mac and has done for years, so the touch check\n * is what tells the two apart. Everything else is honest enough about it.\n */\nfunction deviceOf(ua: string): DeviceKind {\n const isTouchMac =\n /Macintosh/.test(ua) && navigator.maxTouchPoints > 1;\n\n if (/iPad|Tablet/.test(ua) || isTouchMac) return \"tablet\";\n if (/Mobi|iPhone|iPod|Android.*Mobile/.test(ua)) return \"mobile\";\n if (/Android/.test(ua)) return \"tablet\";\n return \"desktop\";\n}\n\n/** What the browser will admit to, or nothing if it is not a browser at all. */\nexport function collectContext(): VisitorContext | undefined {\n if (typeof navigator === \"undefined\" || typeof window === \"undefined\") {\n return undefined;\n }\n\n const ua = navigator.userAgent ?? \"\";\n const { width, height } = window.screen ?? { width: 0, height: 0 };\n\n const context: VisitorContext = {\n // Wrapped: a browser with a broken or absent Intl is rare but real, and\n // failing to work out a time zone should not stop a message sending.\n timeZone: safely(() => Intl.DateTimeFormat().resolvedOptions().timeZone),\n locale: navigator.language || undefined,\n browser: browserOf(ua),\n os: osOf(ua),\n device: deviceOf(ua),\n // The multiplication sign rather than an x, since this is being read as a\n // measurement rather than run as one.\n screen: width && height ? `${width} × ${height}` : undefined,\n };\n\n return Object.values(context).some((one) => one !== undefined)\n ? context\n : undefined;\n}\n\n/**\n * The page they are writing from.\n *\n * The query string is dropped on the way out, before it is ever sent, and\n * again on the way in. A support agent needs to know somebody was on the\n * checkout page; the password reset token that got them there is not ours to\n * put in somebody's inbox.\n */\nexport function collectPage(): ConversationPage | undefined {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return undefined;\n }\n\n const url = withoutQuery(window.location.href);\n if (url === undefined) return undefined;\n\n return {\n url,\n title: document.title || undefined,\n referrer: withoutQuery(document.referrer),\n };\n}\n\nfunction withoutQuery(href: string): string | undefined {\n if (!href) return undefined;\n try {\n const url = new URL(href);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") return undefined;\n return `${url.origin}${url.pathname}`;\n } catch {\n return undefined;\n }\n}\n\nfunction safely<T>(read: () => T): T | undefined {\n try {\n return read();\n } catch {\n return undefined;\n }\n}\n","/**\n * Which Median the widget talks to.\n *\n * Deliberately not a prop. A host plugs in their API key and that is the whole\n * install; our address is our business, not something they should have to know\n * or keep in sync. It reads from the env while the widget ships inside this\n * app, and the published package bakes it in at build time.\n */\nexport const MEDIAN_DEPLOYMENT_URL = process.env.NEXT_PUBLIC_CONVEX_URL;\n","/**\n * What was going wrong around a bug report, from both ends.\n *\n * The client half is collected by the widget SDK: uncaught errors, rejected\n * promises, failed requests, and whatever the host chose to tell us about\n * their own app. The server half is asked for at report time, from the same\n * endpoint the agent's tools live at, so a team that has already wired up\n * tools gets it for nothing.\n *\n * Pure on purpose. The widget cleans what it collects with this file before\n * it sends, and the backend cleans it again with the same file before it\n * stores, so neither side is trusting the other's arithmetic.\n *\n * The rule everywhere here is the one the rest of the telemetry follows: a\n * fact about a program, never a fact about a person. Nothing reads cookies,\n * nothing reads storage, and every URL loses its query string on the way.\n */\n\n/**\n * Where one entry came from. `error` is an uncaught exception, `rejection`\n * is a promise nobody caught, `console` is a console.error, and `network` is\n * a request that failed or came back unhappy.\n */\nexport const DIAGNOSTIC_KINDS = [\n \"error\",\n \"rejection\",\n \"console\",\n \"network\",\n] as const;\n\nexport type DiagnosticKind = (typeof DIAGNOSTIC_KINDS)[number];\n\nexport type DiagnosticEvent = {\n at: number;\n kind: DiagnosticKind;\n message: string;\n /** The file, or the request's method and path. Never a query string. */\n source?: string;\n /** The first frames, for an exception. */\n stack?: string;\n /** The HTTP status, on a network entry that got one. */\n status?: number;\n};\n\nexport type ClientDiagnostics = {\n /** When the snapshot was taken, by the browser's own clock. */\n at: number;\n /** The page they were on. Query string already dropped. */\n url?: string;\n /** \"1512 × 982\", already formatted, like the rest of the telemetry. */\n viewport?: string;\n /** Whatever the host declared about their own app: version, route, flags. */\n state?: Record<string, string>;\n events: DiagnosticEvent[];\n};\n\n/** One tool endpoint's answer to \"how are you\". */\nexport type ServerDiagnostics = {\n /** Which endpoint answered, so a team with two can tell them apart. */\n url: string;\n ok: boolean;\n /** What it said, as JSON text, or why it could not be asked. */\n detail: string;\n};\n\n/** The most entries one snapshot carries. Newest kept, oldest dropped. */\nexport const MAX_EVENTS = 12;\n\nexport const MESSAGE_MAX_LENGTH = 300;\nexport const SOURCE_MAX_LENGTH = 200;\nexport const STACK_MAX_LENGTH = 800;\n\n/** The host's own state, bounded the same way visitor metadata is. */\nexport const MAX_STATE_ENTRIES = 20;\nexport const STATE_KEY_MAX_LENGTH = 60;\nexport const STATE_VALUE_MAX_LENGTH = 200;\n\n/** What one endpoint may say for itself. Enough to hold a health payload. */\nexport const SERVER_DETAIL_MAX_LENGTH = 2_000;\n\n/** How long the widget waits before deciding an endpoint is not answering. */\nexport const SERVER_TIMEOUT_MS = 8_000;\n\nfunction trim(value: unknown, limit: number): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const clean = value.trim().slice(0, limit);\n return clean.length > 0 ? clean : undefined;\n}\n\n/** A URL with its query string taken off, or nothing if it is not one. */\nexport function withoutQuery(href: unknown): string | undefined {\n if (typeof href !== \"string\" || href.length === 0) return undefined;\n try {\n const url = new URL(href);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") return undefined;\n return `${url.origin}${url.pathname}`.slice(0, SOURCE_MAX_LENGTH);\n } catch {\n // Relative paths and the like arrive here. The path is the useful half\n // anyway, so it is kept as written, minus anything after a \"?\".\n return trim(href.split(\"?\")[0], SOURCE_MAX_LENGTH);\n }\n}\n\nfunction cleanEvent(input: unknown): DiagnosticEvent | null {\n if (typeof input !== \"object\" || input === null) return null;\n const raw = input as Record<string, unknown>;\n\n const kind = DIAGNOSTIC_KINDS.find((one) => one === raw.kind);\n const message = trim(raw.message, MESSAGE_MAX_LENGTH);\n if (kind === undefined || message === undefined) return null;\n\n const status =\n typeof raw.status === \"number\" && Number.isFinite(raw.status)\n ? Math.trunc(raw.status)\n : undefined;\n\n return {\n at: typeof raw.at === \"number\" && Number.isFinite(raw.at) ? raw.at : 0,\n kind,\n message,\n ...(trim(raw.source, SOURCE_MAX_LENGTH) !== undefined\n ? { source: trim(raw.source, SOURCE_MAX_LENGTH)! }\n : {}),\n ...(trim(raw.stack, STACK_MAX_LENGTH) !== undefined\n ? { stack: trim(raw.stack, STACK_MAX_LENGTH)! }\n : {}),\n ...(status !== undefined ? { status } : {}),\n };\n}\n\nfunction cleanState(input: unknown): Record<string, string> | undefined {\n if (typeof input !== \"object\" || input === null) return undefined;\n\n const state: Record<string, string> = {};\n for (const [key, value] of Object.entries(input).slice(0, MAX_STATE_ENTRIES)) {\n if (value === null || value === undefined) continue;\n const label = trim(key, STATE_KEY_MAX_LENGTH);\n // Numbers and booleans are the other two things anybody puts in here, so\n // they are written out rather than refused.\n const written =\n typeof value === \"string\"\n ? trim(value, STATE_VALUE_MAX_LENGTH)\n : typeof value === \"number\" || typeof value === \"boolean\"\n ? String(value).slice(0, STATE_VALUE_MAX_LENGTH)\n : undefined;\n if (label === undefined || written === undefined) continue;\n state[label] = written;\n }\n\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\n/**\n * Whatever arrived, cut down to what may be stored. Undefined when there was\n * nothing worth keeping, so an empty snapshot never lands on a row and reads\n * later as \"we looked and the page was fine\".\n */\nexport function cleanClientDiagnostics(\n input: unknown,\n): ClientDiagnostics | undefined {\n if (typeof input !== \"object\" || input === null) return undefined;\n const raw = input as Record<string, unknown>;\n\n const events = Array.isArray(raw.events)\n ? raw.events\n .map(cleanEvent)\n .filter((one): one is DiagnosticEvent => one !== null)\n .slice(-MAX_EVENTS)\n : [];\n\n const url = withoutQuery(raw.url);\n const viewport = trim(raw.viewport, 40);\n const state = cleanState(raw.state);\n\n if (events.length === 0 && state === undefined && url === undefined) {\n return undefined;\n }\n\n return {\n at: typeof raw.at === \"number\" && Number.isFinite(raw.at) ? raw.at : 0,\n ...(url !== undefined ? { url } : {}),\n ...(viewport !== undefined ? { viewport } : {}),\n ...(state !== undefined ? { state } : {}),\n events,\n };\n}\n\n/** Put browser events on the receipt clock while preserving their relative ages. */\nexport function diagnosticEventsAtReceipt(\n snapshot: ClientDiagnostics,\n receivedAt: number,\n): DiagnosticEvent[] {\n if (!Number.isFinite(snapshot.at) || !Number.isFinite(receivedAt)) return [];\n return snapshot.events\n .filter((event) => Number.isFinite(event.at) && event.at <= snapshot.at + 60_000)\n .map((event) => ({\n ...event,\n at: receivedAt - Math.max(0, snapshot.at - event.at),\n }));\n}\n\n/** One endpoint's answer, trimmed to something a card can show. */\nexport function cleanServerDetail(text: string): string {\n return text.length > SERVER_DETAIL_MAX_LENGTH\n ? `${text.slice(0, SERVER_DETAIL_MAX_LENGTH)}…`\n : text;\n}\n","\"use client\";\n\nimport {\n cleanClientDiagnostics,\n MAX_EVENTS,\n MESSAGE_MAX_LENGTH,\n SOURCE_MAX_LENGTH,\n STACK_MAX_LENGTH,\n withoutQuery,\n type ClientDiagnostics,\n type DiagnosticEvent,\n} from \"@median/backend/diagnostics\";\nimport { useCallback, useEffect, useRef } from \"react\";\n\n/**\n * What has been going wrong on the page, kept ready in case somebody asks\n * for help about it.\n *\n * A support agent's first three questions are always the same: what were you\n * doing, what did it say, and what does the console show. The customer can\n * answer the first one. This answers the other two, so a bug report arrives\n * with the error already attached rather than after four messages of asking.\n *\n * Off unless a host switches it on. Everything here reads their program's\n * error stream, which is theirs to offer rather than ours to take.\n *\n * A bounded ring buffer and nothing else. Nothing is sent on its own, nothing\n * is stored, and nothing is polled: the newest snapshot rides the next message\n * the customer sends, and only when there is something new in it.\n */\n\n/** What a host can switch on. `true` is the passive half. */\nexport type MedianDiagnostics =\n | boolean\n | {\n /** Uncaught errors and rejected promises. On whenever diagnostics are. */\n errors?: boolean;\n /** Requests that failed or came back unhappy. Wraps window.fetch. */\n network?: boolean;\n /** console.error calls. Wraps console.error. */\n console?: boolean;\n };\n\ntype Settings = { errors: boolean; network: boolean; console: boolean };\n\nfunction settingsOf(option: MedianDiagnostics | undefined): Settings | null {\n if (option === undefined || option === false) return null;\n if (option === true) return { errors: true, network: false, console: false };\n return {\n errors: option.errors ?? true,\n network: option.network ?? false,\n console: option.console ?? false,\n };\n}\n\n/**\n * The buffer, and how many things have gone into it.\n *\n * Module level rather than per component: a page has one widget, and an\n * error that happened before React mounted it is exactly the kind worth\n * keeping. The count is what lets a sender ask \"anything new since last\n * time\" without comparing arrays.\n */\nconst events: DiagnosticEvent[] = [];\nlet recorded = 0;\n\n/**\n * The host's own state, as the last mounted widget was given it. Here rather\n * than only in the hook's ref because a crash report is sent from a tree\n * where that hook no longer exists, and the route a page fell over on is\n * exactly the sort of thing hosts put in `appState`.\n */\nlet latestState: Record<string, string | number | boolean> | undefined;\n\nfunction record(event: DiagnosticEvent): void {\n events.push(event);\n if (events.length > MAX_EVENTS) events.shift();\n recorded += 1;\n}\n\nfunction messageOf(value: unknown): string {\n if (value instanceof Error) return value.message.slice(0, MESSAGE_MAX_LENGTH);\n if (typeof value === \"string\") return value.slice(0, MESSAGE_MAX_LENGTH);\n try {\n return JSON.stringify(value).slice(0, MESSAGE_MAX_LENGTH);\n } catch {\n return String(value).slice(0, MESSAGE_MAX_LENGTH);\n }\n}\n\nfunction stackOf(value: unknown): string | undefined {\n return value instanceof Error && typeof value.stack === \"string\"\n ? value.stack.slice(0, STACK_MAX_LENGTH)\n : undefined;\n}\n\n/**\n * Installs whatever the host asked for, and gives back the way to take it all\n * off again. Every wrapper calls through to what it replaced first, so a page\n * behaves exactly as it did before the widget arrived.\n */\nfunction collect(settings: Settings): () => void {\n const undo: (() => void)[] = [];\n\n if (settings.errors) {\n const onError = (event: ErrorEvent) => {\n // A failed image or script fires here too, with no error on it. Those\n // are the browser's business, not a bug report's.\n if (!event.error && !event.message) return;\n record({\n at: Date.now(),\n kind: \"error\",\n message: messageOf(event.error ?? event.message),\n ...(event.filename\n ? {\n source: `${withoutQuery(event.filename) ?? \"\"}:${event.lineno}`.slice(\n 0,\n SOURCE_MAX_LENGTH,\n ),\n }\n : {}),\n ...(stackOf(event.error) !== undefined\n ? { stack: stackOf(event.error)! }\n : {}),\n });\n };\n const onRejection = (event: PromiseRejectionEvent) => {\n record({\n at: Date.now(),\n kind: \"rejection\",\n message: messageOf(event.reason),\n ...(stackOf(event.reason) !== undefined\n ? { stack: stackOf(event.reason)! }\n : {}),\n });\n };\n\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n undo.push(() => {\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n });\n }\n\n if (settings.network && typeof window.fetch === \"function\") {\n const original = window.fetch;\n window.fetch = async function medianFetch(this: unknown, ...args) {\n const [input, init] = args;\n const method = (init?.method ?? \"GET\").toUpperCase();\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n\n try {\n const response = await original.apply(this as never, args);\n if (!response.ok) {\n record({\n at: Date.now(),\n kind: \"network\",\n message: `${method} ${response.status}`,\n source: `${method} ${withoutQuery(url) ?? \"\"}`.slice(\n 0,\n SOURCE_MAX_LENGTH,\n ),\n status: response.status,\n });\n }\n return response;\n } catch (thrown) {\n record({\n at: Date.now(),\n kind: \"network\",\n message: messageOf(thrown),\n source: `${method} ${withoutQuery(url) ?? \"\"}`.slice(\n 0,\n SOURCE_MAX_LENGTH,\n ),\n });\n // Rethrown untouched. Watching a request is not catching it.\n throw thrown;\n }\n } as typeof window.fetch;\n\n undo.push(() => {\n window.fetch = original;\n });\n }\n\n if (settings.console) {\n const original = console.error;\n console.error = function medianConsoleError(...args: unknown[]) {\n record({\n at: Date.now(),\n kind: \"console\",\n message: args.map(messageOf).join(\" \").slice(0, MESSAGE_MAX_LENGTH),\n ...(stackOf(args.find((one) => one instanceof Error)) !== undefined\n ? { stack: stackOf(args.find((one) => one instanceof Error))! }\n : {}),\n });\n original.apply(console, args);\n };\n\n undo.push(() => {\n console.error = original;\n });\n }\n\n return () => {\n for (const off of undo) off();\n };\n}\n\n/** Everything worth saying about the page right now, or nothing. */\nfunction snapshot(\n state: Record<string, string | number | boolean> | undefined,\n): ClientDiagnostics | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n return cleanClientDiagnostics({\n at: Date.now(),\n url: window.location.href,\n viewport: `${window.innerWidth} × ${window.innerHeight}`,\n state,\n events,\n });\n}\n\n/**\n * Everything the page can say for itself right now, for a send that cannot\n * wait to be asked twice.\n *\n * The hook's `take` answers with nothing when nothing has been recorded since\n * the last send, which is right for a chat message and wrong for a crash\n * report: the viewport and the route are worth having whether or not the ring\n * buffer moved. So this one always answers, and takes anything the caller\n * knows that the host's own state does not.\n */\nexport function snapshotNow(\n extraState?: Record<string, string | number | boolean>,\n): ClientDiagnostics | undefined {\n return snapshot({ ...latestState, ...extraState });\n}\n\n/**\n * The collector, as a component uses it: on while the host wants it, off\n * again when they change their mind or the widget leaves the page.\n *\n * `take` is what a send calls. It answers with a snapshot the first time and\n * whenever something new has been recorded since, and with nothing the rest\n * of the time, so a long conversation on a healthy page sends the state once\n * rather than on every line.\n */\nexport function useDiagnostics(\n option: MedianDiagnostics | undefined,\n appState: Record<string, string | number | boolean> | undefined,\n) {\n const settings = settingsOf(option);\n // Serialised so a host building the object inline does not reinstall the\n // wrappers on every render. The same trick `user` gets in the thread hook.\n const key = settings === null ? null : JSON.stringify(settings);\n\n // Read at send time rather than closed over, since a route or a flag can\n // change between the widget mounting and somebody typing. Written after\n // the render rather than during it: nothing on screen depends on it, and a\n // ref written mid-render is a render that cannot be replayed.\n const stateRef = useRef(appState);\n useEffect(() => {\n stateRef.current = appState;\n latestState = appState;\n });\n\n const sentAt = useRef<number | null>(null);\n\n useEffect(() => {\n if (key === null) return;\n return collect(JSON.parse(key) as Settings);\n }, [key]);\n\n const take = useCallback((): ClientDiagnostics | undefined => {\n if (key === null) return undefined;\n if (sentAt.current !== null && sentAt.current === recorded) return undefined;\n\n sentAt.current = recorded;\n return snapshot(stateRef.current);\n }, [key]);\n\n return take;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport type { MedianUser } from \"./use-median-thread\";\n\n/**\n * What the install on this page said, kept where a crash can still reach it.\n *\n * Everything else in the SDK reads its API key and its visitor from props,\n * which is fine while there is a widget on the page to hold them. A crash is\n * the case where there is not: the boundary that catches it has replaced the\n * tree the widget was mounted in, and in the worst of them, the root layout,\n * there is nothing of the app left at all.\n *\n * Module level for the same reason the diagnostics buffer is: it outlives\n * every React tree on the page. A panel writes here as it mounts, and\n * `reportError` reads it long after that panel has been unmounted by the\n * error it is reporting.\n */\n\ntype Install = { apiKey: string; user?: MedianUser };\n\nlet install: Install | null = null;\n\nconst listeners = new Set<() => void>();\n\n/** Called by whichever widget mounted. The newest one wins. */\nexport function rememberInstall(next: Install): void {\n // Only a new key is news. The panels write here after every render, and a\n // report button that re-rendered on each of them would be a waste of a\n // subscription.\n const isNews = install?.apiKey !== next.apiKey;\n install = { apiKey: next.apiKey, ...(next.user ? { user: next.user } : {}) };\n if (!isNews) return;\n for (const listener of listeners) listener();\n}\n\n/** What the last mounted widget was given, or nothing if none ever was. */\nexport function readInstall(): Install | null {\n return install;\n}\n\n/**\n * Whether anything has been installed yet, as an external store.\n *\n * A report button rendered by an error screen can easily be on the page one\n * commit before the widget whose key it needs: a page that failed on the\n * server paints its error boundary and its layout together. Reading this\n * live is what lets that button appear the moment reporting becomes\n * possible, rather than sitting hidden until something else re-renders.\n */\nexport function subscribeInstall(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function hasInstall(): boolean {\n return install !== null;\n}\n\n/**\n * Both panels call this as they mount, and again whenever the host changes\n * its mind about who is in the chair.\n *\n * Written after the render rather than during it, and on every one rather\n * than behind a dependency list, because `user` is an object a host builds\n * inline and the write is one assignment.\n */\nexport function useRememberInstall(apiKey: string, user?: MedianUser): void {\n useEffect(() => {\n rememberInstall({ apiKey, ...(user ? { user } : {}) });\n });\n}\n","/**\n * Who this browser is, as far as the widget cares: a random token minted on\n * first visit and kept in localStorage, one per API key, so coming back\n * reopens the same conversation without anyone signing in.\n *\n * A small store rather than a bare read, so `resetSessions` can tell a\n * mounted widget its token is gone and the thread re-reads through\n * `useSyncExternalStore`.\n */\n\nconst STORAGE_PREFIX = \"median:session:\";\n\n/**\n * When localStorage is blocked, the token lives here instead: gone on\n * reload, but stable within the page, which is what the reads below need.\n */\nconst inMemorySessions = new Map<string, string>();\n\nconst listeners = new Set<() => void>();\n\nexport function subscribeSession(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n/**\n * Stable across calls on purpose: this is read as an external-store snapshot,\n * so two calls in a row must agree.\n */\nexport function getOrCreateSessionId(apiKey: string): string | null {\n if (typeof window === \"undefined\") return null;\n\n const storageKey = `${STORAGE_PREFIX}${apiKey}`;\n try {\n const existing = window.localStorage.getItem(storageKey);\n if (existing && existing.length >= 8) return existing;\n\n const created = crypto.randomUUID();\n window.localStorage.setItem(storageKey, created);\n return created;\n } catch {\n // Storage can be blocked entirely. A session that lasts one page load\n // still beats no support at all.\n const remembered = inMemorySessions.get(apiKey) ?? crypto.randomUUID();\n inMemorySessions.set(apiKey, remembered);\n return remembered;\n }\n}\n\n/**\n * Forget every token this browser holds. The next read mints a fresh one, so\n * the next message starts a conversation with nothing behind it.\n *\n * This is for sign out: the conversation belongs to the person who was in the\n * chair, not to the chair. The old thread stays in the team's inbox; it just\n * stops being reachable from this browser.\n */\nexport function resetSessions() {\n inMemorySessions.clear();\n\n if (typeof window !== \"undefined\") {\n try {\n const stale: string[] = [];\n for (let i = 0; i < window.localStorage.length; i += 1) {\n const key = window.localStorage.key(i);\n if (key !== null && key.startsWith(STORAGE_PREFIX)) stale.push(key);\n }\n for (const key of stale) window.localStorage.removeItem(key);\n } catch {\n // Storage was blocked, so there was nothing durable to forget.\n }\n }\n\n for (const listener of listeners) listener();\n}\n","\"use client\";\n\nimport { api } from \"@median/backend\";\nimport { TYPING_TTL_MS } from \"@median/backend/support\";\nimport { useMutation, useQuery } from \"convex/react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { attachmentKindOf, formatFileSize } from \"@/components/attachments\";\nimport { useNow } from \"@/hooks/use-now\";\nimport { errorMessage } from \"@/lib/errors\";\nimport { formatClockTime, formatDayLabel, isNewDay } from \"@/lib/time\";\nimport { uploadAttachments } from \"@/lib/upload\";\nimport type {\n SupportAgent,\n SupportAsk,\n SupportMessage,\n SupportPresence,\n SupportRating,\n} from \"../types\";\nimport { collectContext, collectPage } from \"./context\";\nimport { restoreCustomData, takeCustomData } from \"./custom-data\";\nimport { useDiagnostics, type MedianDiagnostics } from \"./diagnostics\";\nimport { readSkippedRatings, writeSkippedRating } from \"./rating-skips\";\nimport { readLastSeenAt, writeLastSeenAt } from \"./read-state\";\nimport { getOrCreateSessionId, subscribeSession } from \"./session\";\nimport { useVisitorEmail } from \"./visitor-email\";\n\n/** What a host can tell us about who is in the widget. All of it optional. */\nexport type MedianUser = {\n /**\n * Your own id for this person, and that id signed from MEDIAN_KEY.\n *\n * The pair is what makes a conversation follow somebody rather than a\n * browser: sign in on a phone and the thread from the laptop is already\n * there. Both or neither, and the signing belongs on your server, because\n * whoever holds the key can claim to be any of your customers.\n *\n * Without them the widget still works. It is just this browser's thread,\n * which is what it has always been.\n */\n id?: string;\n hash?: string;\n name?: string;\n email?: string;\n /**\n * Their profile picture, so the team sees who they are talking to rather\n * than a letter. Has to be an https URL; anything else is ignored.\n */\n avatarUrl?: string;\n /** Anything else worth showing the team: plan, company, whatever. */\n metadata?: Record<string, string>;\n};\n\n/**\n * Whether the host has told us somebody is in the chair.\n *\n * Anything they say about the person counts, because only they can know it: a\n * host who passes a name and an email for whoever is signed in is as sure as\n * one who passes a signed id. An empty object is not an answer, so a session\n * that is still loading does not open the door on its way past.\n */\nexport function isSignedIn(user: MedianUser | undefined): boolean {\n if (user === undefined) return false;\n\n // Every field checked as it arrives rather than as it is typed: a host\n // spreading a session that is not there yet passes `{ name: undefined }`,\n // and a widget that threw on that would be a page broken by signing out.\n const { metadata, ...facts } = user;\n return (\n Object.values(facts).some(\n (value) => typeof value === \"string\" && value.trim().length > 0,\n ) || Object.keys(metadata ?? {}).length > 0\n );\n}\n\n/**\n * The claim, split from the rest.\n *\n * Two things go up rather than one, and the difference between them is the\n * whole of the security. A name is decoration and is taken at its word; an id\n * decides whose history the widget can reach, so it travels with its signature\n * and is believed only if that checks out. Sending them as one object would\n * blur a line the backend needs to keep sharp.\n */\nexport function splitIdentity(user: MedianUser | null): {\n facts: Omit<MedianUser, \"id\" | \"hash\">;\n claim: { userId: string; userHash: string } | undefined;\n} {\n if (user === null) return { facts: {}, claim: undefined };\n\n const { id, hash, ...facts } = user;\n return {\n facts,\n claim: id && hash ? { userId: id, userHash: hash } : undefined,\n };\n}\n\n/** What the backend made of a claim, and what to say about it. */\nconst IDENTITY_COMPLAINTS: Record<string, string> = {\n unverified:\n \"Median: the user hash passed to <MedianSupport> did not match. Sign the same string you pass as `user.id` with the Median key that produced this widget id. Until it matches, this visitor gets a conversation of their own on every device.\",\n unconfigured:\n \"Median: a user hash was passed to <MedianSupport>, but its widget id and hash came from different Median keys. Derive both from the same key.\",\n};\n\n/**\n * The live conversation behind the widget: a session token for this browser,\n * the thread as Convex sees it, and a send that uploads files first. The\n * widget itself stays dumb; this is the seam the SDK promised it.\n */\nexport function useMedianThread(\n apiKey: string,\n user?: MedianUser,\n /** Whether to read the browser's own answers along with a message. */\n telemetry = true,\n /**\n * Nobody may write yet, so nothing is read either: a visitor who has to\n * sign in first is not shown a thread they cannot answer, and the widget\n * holds no conversation open behind the invitation to sign in.\n */\n isLocked = false,\n /** What to watch going wrong on the page, if the host wants any of it. */\n diagnostics?: MedianDiagnostics,\n /** The host's own state, read at send time. */\n appState?: Record<string, string | number | boolean>,\n /**\n * Whether this page asks for an email before a visitor's first message.\n * The team answers through `config.requireEmail`, and both have to agree:\n * either side can waive the question.\n */\n requireEmail = true,\n /**\n * Whether this page lets an unread reply be previewed on the closed\n * button. The team answers through `config.messagePreview`, and both have\n * to agree, exactly as the email question is settled: either side can keep\n * the corner quiet.\n */\n messagePreview = true,\n) {\n // The session token is external state (localStorage), read as a store: the\n // server snapshot is null, so SSR and the first client paint agree, and the\n // browser's token takes over from there. Subscribed so `reset()` lands\n // here, mints a new token, and the thread starts over.\n const sessionId = useSyncExternalStore(\n subscribeSession,\n useCallback(() => getOrCreateSessionId(apiKey), [apiKey]),\n () => null,\n );\n\n const config = useQuery(api.widget.config, { apiKey });\n\n // The answer to the composer's question, if this browser has given one.\n const [visitorEmail, setVisitorEmail] = useVisitorEmail(apiKey);\n\n /**\n * Whether the composer asks who they are before it takes a message. All\n * three have to say so: the page's own rule, the team's switch, and the\n * fact that nobody here knows an address already. A host who passes\n * `user.email` has answered on their visitor's behalf; the question never\n * comes up. Before the config lands there is no team answer yet, and the\n * panel is still shimmering besides, so the default holds.\n */\n const askForEmail =\n requireEmail &&\n (config?.requireEmail ?? true) &&\n !visitorEmail &&\n !(typeof user?.email === \"string\" && user.email.trim().length > 0);\n\n const thread = useQuery(\n api.widget.thread,\n sessionId === null || isLocked ? \"skip\" : { apiKey, sessionId },\n );\n const send = useMutation(api.widget.send);\n const sendTyping = useMutation(api.widget.setTyping);\n const sendPresence = useMutation(api.widget.presence);\n const rateConversation = useMutation(api.widget.rate);\n const identify = useMutation(api.widget.identify);\n const generateUploadUrl = useMutation(api.widget.generateUploadUrl);\n\n // Who they are can change without them saying a word: they sign in on the\n // host's page while the thread a teammate is reading still says nobody.\n //\n // Serialised and parsed back, which looks like a detour and is the point.\n // A host almost always builds this object inline, so it is a new one on\n // every render and a new identity to any effect watching it; the string is\n // the same until the facts in it are not.\n const identityKey = user ? JSON.stringify(user) : null;\n const identity = useMemo(\n () => (identityKey === null ? null : (JSON.parse(identityKey) as MedianUser)),\n [identityKey],\n );\n\n useEffect(() => {\n if (sessionId === null || identity === null) return;\n const { facts, claim } = splitIdentity(identity);\n\n // Best effort on the facts: they ride along with the next message anyway,\n // which is exactly where they were before this existed. A signature that\n // was offered and refused is worth saying out loud though, because the\n // host is the only one who can fix it and nothing visibly breaks.\n identify({\n apiKey,\n sessionId,\n user: facts,\n ...(claim ? { identity: claim } : {}),\n })\n .then((status) => {\n const complaint = IDENTITY_COMPLAINTS[status];\n if (complaint) console.error(complaint);\n })\n .catch(() => {});\n }, [apiKey, sessionId, identity, identify]);\n\n // A fast clock only while a teammate's dots are on screen, so they expire\n // on time without the widget re-rendering every second forever.\n const hasLiveDots =\n thread?.messages.some(\n (message) => message.pending && message.typingAt !== null,\n ) ?? false;\n const now = useNow(hasLiveDots ? 1000 : 60_000);\n\n const takeDiagnostics = useDiagnostics(diagnostics, appState);\n\n const [isSending, setIsSending] = useState(false);\n const [sendError, setSendError] = useState<string | null>(null);\n\n const agent: SupportAgent | null = useMemo(\n () =>\n config === undefined\n ? null\n : {\n id: \"median-agent\",\n name: config.agent.name,\n kind: \"ai\",\n avatarUrl: config.agent.avatarUrl,\n },\n [config],\n );\n\n const messages: SupportMessage[] = useMemo(() => {\n if (!thread || agent === null) return [];\n\n const out: SupportMessage[] = [];\n let previousAt: number | undefined;\n let previousConversationId: string | undefined;\n\n for (const message of thread.messages) {\n // A typing bubble whose teammate stopped refreshing it: the browser on\n // the other end went away, so the dots go too.\n if (\n message.pending &&\n message.typingAt !== null &&\n now - message.typingAt > TYPING_TTL_MS\n ) {\n continue;\n }\n\n out.push({\n id: message._id,\n sender: message.sender,\n body: message.body,\n time: formatClockTime(message.createdAt),\n sentAt: message.createdAt,\n dayLabel: isNewDay(previousAt, message.createdAt)\n ? formatDayLabel(message.createdAt, now)\n : undefined,\n // Not on the very first message: the history has to start somewhere,\n // and a line above the only conversation there has ever been would be\n // marking a boundary that does not exist.\n startsConversation:\n previousConversationId !== undefined &&\n previousConversationId !== message.conversationId\n ? true\n : undefined,\n agent:\n message.agent === null\n ? undefined\n : message.agent.kind === \"ai\"\n ? agent\n : {\n id: `human-${message.agent.name}`,\n name: message.agent.name,\n kind: \"human\",\n avatarUrl: message.agent.avatarUrl,\n },\n pending: message.pending || undefined,\n attachments:\n message.attachments.length > 0\n ? message.attachments.map((attachment) => {\n const kind = attachmentKindOf(attachment.type);\n return {\n id: attachment.id,\n kind,\n name: attachment.name,\n size: formatFileSize(attachment.size),\n // Only what can actually be shown small. A text file had\n // one of these too, which read as \"there is a thumbnail\n // here\" everywhere it was checked.\n previewUrl:\n kind === \"file\" ? undefined : (attachment.url ?? undefined),\n url: attachment.url ?? undefined,\n };\n })\n : undefined,\n navigateTo: message.navigateTo ?? undefined,\n highlight: message.highlight ?? undefined,\n });\n previousAt = message.createdAt;\n previousConversationId = message.conversationId;\n }\n\n return out;\n }, [thread, agent, now]);\n\n // The faces in the corner: the AI, then anyone human who has spoken.\n const presence: SupportPresence | null = useMemo(() => {\n if (config === undefined || agent === null) return null;\n\n const humans = new Map<string, SupportAgent>();\n for (const message of messages) {\n if (message.agent && message.agent.kind === \"human\") {\n humans.set(message.agent.id, message.agent);\n }\n }\n\n return {\n name: config.orgName,\n status: \"Support online\",\n team: [...[...humans.values()].slice(-2), agent],\n };\n }, [config, agent, messages]);\n\n // What they had seen last time the panel was open. Read once, from storage,\n // so a reply that landed while it was closed survives them clicking through\n // to another page on the host's site.\n const [lastSeenAt, setLastSeenAt] = useState(() => readLastSeenAt(apiKey));\n\n /**\n * Replies they have not looked at. Only the other side's, and only ones\n * that have actually been written: a bubble still holding dots is not news.\n */\n const unread = useMemo(\n () =>\n messages.filter(\n (message) =>\n message.sender === \"agent\" &&\n !message.pending &&\n (message.sentAt ?? 0) > lastSeenAt,\n ),\n [messages, lastSeenAt],\n );\n const unreadCount = unread.length;\n\n /**\n * The newest of those, for the card on the closed button, or null when\n * either side has turned the card off. The count on the button is not\n * affected: this decides whether the words are shown, not whether the\n * reply is announced.\n *\n * Before the config lands there is no team answer, and nothing has been\n * read yet either, so the default holds and nothing is shown regardless.\n */\n const latestUnread =\n messagePreview && (config?.messagePreview ?? true)\n ? (unread[unread.length - 1] ?? null)\n : null;\n\n // Asking how it went, once, on a conversation that is over.\n //\n // Three things decide whether the card is up, and all three are read\n // rather than remembered: the thread is resolved, nobody has answered yet,\n // and they have not waved it away. Pressing a star writes a rating, which\n // would otherwise take the card off screen mid-sentence, so a pick made\n // here keeps it open until they are finished with it.\n const [picked, setPicked] = useState<{\n conversationId: string;\n stars: number;\n } | null>(null);\n // Read from storage rather than started empty: a skip has to outlive the\n // remount that clicking a link on the host's site costs us.\n const [skipped, setSkipped] = useState<ReadonlySet<string>>(() =>\n readSkippedRatings(apiKey),\n );\n\n const conversationId = thread?.conversationId ?? null;\n const savedRating = thread?.rating ?? null;\n const isMine = picked?.conversationId === conversationId;\n\n const rating: SupportRating | null =\n thread?.status === \"resolved\" &&\n conversationId !== null &&\n !skipped.has(conversationId) &&\n (savedRating === null || isMine)\n ? {\n stars: isMine ? picked.stars : (savedRating?.stars ?? null),\n submit: async (stars, feedback) => {\n // Never null by the time a thread has been read, and a quiet\n // return here would read on screen as a rating that landed.\n if (sessionId === null) throw new Error(\"No session yet.\");\n setPicked({ conversationId, stars });\n await rateConversation({\n apiKey,\n sessionId,\n conversationId,\n stars,\n ...(feedback ? { feedback } : {}),\n });\n },\n skip: () => {\n writeSkippedRating(apiKey, conversationId);\n setSkipped((current) => new Set(current).add(conversationId));\n },\n }\n : null;\n\n /** They are looking at it, so the newest thing in it has been seen. */\n const markSeen = useCallback(() => {\n const newest = messages.reduce(\n (latest, message) => Math.max(latest, message.sentAt ?? 0),\n 0,\n );\n if (newest <= lastSeenAt) return;\n\n writeLastSeenAt(apiKey, newest);\n setLastSeenAt(newest);\n }, [apiKey, messages, lastSeenAt]);\n\n async function handleSend(body: string, files: File[]) {\n if (sessionId === null || isSending) return;\n\n setSendError(null);\n setIsSending(true);\n // Whatever the host attached since the last send rides this message.\n // Taken outside the try so a failed upload hands it back too.\n const custom = takeCustomData();\n try {\n const attachments = await uploadAttachments(\n () => generateUploadUrl({ apiKey, sessionId }),\n files,\n );\n\n // Read now rather than on mount: all of it is wanted as \"what was true\n // when they wrote\", and a widget can sit closed on a page for an hour\n // before anybody says anything.\n const context = telemetry ? collectContext() : undefined;\n const page = telemetry ? collectPage() : undefined;\n\n // Nothing the first time a healthy page sends twice in a row: the\n // snapshot only travels when something new has gone wrong since.\n const collected = takeDiagnostics();\n\n // The same split as above, and this is the call that needs it most: a\n // visitor's first message is what creates them, so it is the only chance\n // to put them straight onto the account they are already signed in to.\n const { facts, claim } = splitIdentity(user ?? null);\n\n // The address typed at the composer's question rides along the same way\n // a host's facts do, but never over one the host already knows.\n const withEmail =\n facts.email || !visitorEmail ? facts : { ...facts, email: visitorEmail };\n\n await send({\n apiKey,\n sessionId,\n body,\n ...(Object.keys(withEmail).length > 0 ? { user: withEmail } : {}),\n ...(claim ? { identity: claim } : {}),\n ...(context ? { context } : {}),\n ...(page ? { page } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n ...(collected ? { diagnostics: collected } : {}),\n ...(custom ? { customData: custom } : {}),\n });\n } catch (caught) {\n // Back in the queue, so the retry carries them like it keeps the draft.\n if (custom) restoreCustomData(custom);\n console.error(\"Sending from the support widget failed\", caught);\n setSendError(errorMessage(caught));\n // Rethrown so the composer keeps the draft: a failed send should cost\n // a retry, never a retype.\n throw caught;\n } finally {\n setIsSending(false);\n }\n }\n\n function handleTypingChange(isTyping: boolean) {\n if (sessionId === null) return;\n // Best effort: dots that fail to show are not worth an error.\n sendTyping({ apiKey, sessionId, isTyping }).catch(() => {});\n }\n\n /**\n * The panel is visible right now. Whatever renders the thread calls this\n * on open and every so often after, and it is what stands between a\n * customer and an email copy of a reply they are already reading.\n */\n const reportPresence = useCallback(() => {\n if (sessionId === null || isLocked) return;\n // Best effort, like typing: a missed heartbeat costs one stray email at\n // worst, and an error here has nobody to be shown to.\n sendPresence({ apiKey, sessionId }).catch(() => {});\n }, [apiKey, sessionId, isLocked, sendPresence]);\n\n // Nearly always null. Its own value rather than a message in the list,\n // because it belongs to a tool run and not to anything anybody said.\n const ask: SupportAsk | null = thread?.direction ?? null;\n\n return {\n presence,\n messages,\n /** Something a tool run asked of this page, with no message to ride on. */\n ask,\n /**\n * The live thread, or null before there is one. Read by whatever has to\n * tell \"the next thing in this conversation\" from \"a different\n * conversation altogether\", which is what signing in produces.\n */\n conversationId,\n /**\n * Still finding out whether this browser has a conversation already.\n * Locked, there is only the host's name to wait for, and the invitation\n * to sign in names them.\n */\n isLoading:\n config === undefined ||\n (!isLocked && (sessionId === null || thread === undefined)),\n isSending,\n /**\n * Whether the composer asks for an email before a first message. The\n * page's rule and the team's switch both have to want it, and nobody\n * here may know an address already.\n */\n askForEmail,\n /** What the composer's question does with a good answer. */\n setVisitorEmail,\n /** The agent asked for a person, and nobody has answered yet. */\n awaitingHuman: thread?.awaitingHuman ?? false,\n /** The question a finished conversation asks, while it is worth asking. */\n rating,\n /** Replies that arrived while they were not looking. */\n unreadCount,\n /** The newest of those, for the card on the closed button. */\n latestUnread,\n markSeen,\n /** Say the panel is on screen, so replies are not also emailed. */\n reportPresence,\n sendError,\n send: handleSend,\n setTyping: handleTypingChange,\n };\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * The current time, refreshed on an interval, so relative timestamps (\"2m\")\n * drift forward without anyone touching the page. One state per caller keeps\n * this dumb; the inbox only needs it once.\n */\nexport function useNow(intervalMs = 30_000): number {\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), intervalMs);\n return () => clearInterval(timer);\n }, [intervalMs]);\n\n return now;\n}\n","import { ConvexError } from \"convex/values\";\n\nconst FALLBACK = \"Something went wrong on our end. Please try again.\";\n\ntype ErrorPayload = { code: string; message: string };\n\nfunction isErrorPayload(data: unknown): data is ErrorPayload {\n return (\n typeof data === \"object\" &&\n data !== null &&\n \"message\" in data &&\n typeof (data as ErrorPayload).message === \"string\"\n );\n}\n\n/**\n * Turns anything thrown by a Convex call into a sentence worth showing.\n * Only errors we raised on purpose are surfaced; everything else falls back so\n * we never paste a stack trace into the UI.\n */\nexport function errorMessage(error: unknown): string {\n if (error instanceof ConvexError) {\n if (typeof error.data === \"string\") return error.data;\n if (isErrorPayload(error.data)) return error.data.message;\n }\n return FALLBACK;\n}\n","/**\n * Timestamps, written the way the inbox and the widget say them. All of it\n * runs on the client with a real clock, so the backend only ever stores\n * numbers.\n */\n\nconst MINUTE = 60_000;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\n/**\n * A time of day, wherever one is printed: beside a message, and under a\n * visitor's name for the clock where they are.\n *\n * Twelve hour on purpose rather than by the reader's locale. Two clocks can\n * sit on one screen here, one for the message and one for the customer, and\n * they came from different formatters; leaving the shape to the locale meant\n * they agreed only by luck, and a reader in a country that counts to\n * twenty-four saw a screen that could not decide.\n *\n * The rest is still the reader's. Which characters mark the afternoon is a\n * question their locale answers better than we can.\n */\nexport const CLOCK_FORMAT = {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n} as const satisfies Intl.DateTimeFormatOptions;\n\n/** \"3:58 PM\", for the line beside a message. */\nexport function formatClockTime(timestamp: number): string {\n return new Date(timestamp).toLocaleTimeString([], CLOCK_FORMAT);\n}\n\n/** \"now\", \"2m\", \"3h\", \"2d\", then a date, for a queue row. */\nexport function formatTimeAgo(timestamp: number, now: number): string {\n const elapsed = now - timestamp;\n if (elapsed < MINUTE) return \"now\";\n if (elapsed < HOUR) return `${Math.floor(elapsed / MINUTE)}m`;\n if (elapsed < DAY) return `${Math.floor(elapsed / HOUR)}h`;\n if (elapsed < 7 * DAY) return `${Math.floor(elapsed / DAY)}d`;\n return new Date(timestamp).toLocaleDateString([], {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/**\n * \"just now\", \"2m ago\", \"Mar 3\", for a line about when something last ran.\n *\n * The queue's own shorthand reads as a column of times, which is right beside\n * a conversation and wrong in a sentence: \"synced 2m\" is not a thing anybody\n * says. Same clock, said out loud.\n */\nexport function formatSyncedAgo(timestamp: number, now: number): string {\n const ago = formatTimeAgo(timestamp, now);\n if (ago === \"now\") return \"just now\";\n return /^\\d/.test(ago) ? `${ago} ago` : ago;\n}\n\n/** Minutes since, for sorting rows the way the demo data did. */\nexport function minutesSince(timestamp: number, now: number): number {\n return Math.max(0, Math.floor((now - timestamp) / MINUTE));\n}\n\n/** \"March 2023\", for the customer since row and past conversations. */\nexport function formatMonthYear(timestamp: number): string {\n return new Date(timestamp).toLocaleDateString([], {\n month: \"long\",\n year: \"numeric\",\n });\n}\n\nfunction startOfDay(timestamp: number): number {\n const date = new Date(timestamp);\n date.setHours(0, 0, 0, 0);\n return date.getTime();\n}\n\n/** \"Today\", \"Yesterday\", \"Monday\", then a date, for a thread divider. */\nexport function formatDayLabel(timestamp: number, now: number): string {\n const days = Math.round((startOfDay(now) - startOfDay(timestamp)) / DAY);\n if (days <= 0) return \"Today\";\n if (days === 1) return \"Yesterday\";\n if (days < 7) {\n return new Date(timestamp).toLocaleDateString([], { weekday: \"long\" });\n }\n return new Date(timestamp).toLocaleDateString([], {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** How many whole days apart two timestamps land, by the calendar. */\nfunction daysApart(from: number, to: number): number {\n return Math.round((startOfDay(to) - startOfDay(from)) / DAY);\n}\n\n/**\n * \"9:00 AM\", \"tomorrow, 9:00 AM\", \"Mon, 9:00 AM\", \"Mar 4\": when a snooze is\n * up, as short as it can be said without leaving anyone guessing which day.\n */\nexport function formatSnoozeAt(until: number, now: number): string {\n const days = daysApart(now, until);\n if (days >= 7) {\n return new Date(until).toLocaleDateString([], {\n month: \"short\",\n day: \"numeric\",\n });\n }\n\n const time = formatClockTime(until);\n if (days <= 0) return time;\n if (days === 1) return `tomorrow, ${time}`;\n return `${new Date(until).toLocaleDateString([], { weekday: \"short\" })}, ${time}`;\n}\n\n/** Whether two timestamps land on different days, so a thread can divide. */\nexport function isNewDay(previous: number | undefined, next: number): boolean {\n if (previous === undefined) return true;\n return startOfDay(previous) !== startOfDay(next);\n}\n","import type { Id } from \"@median/backend/dataModel\";\n\n/**\n * POSTs one file to a one shot Convex upload URL and hands back its storage\n * id. The URL comes from whichever mutation guards the caller, so the same\n * helper serves the inbox, the widget, and the settings page.\n */\nexport async function uploadFile(\n getUploadUrl: () => Promise<string>,\n file: File,\n): Promise<Id<\"_storage\">> {\n const url = await getUploadUrl();\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": file.type || \"application/octet-stream\" },\n body: file,\n });\n if (!response.ok) {\n throw new Error(`Uploading ${file.name} failed with ${response.status}`);\n }\n\n const { storageId } = (await response.json()) as {\n storageId: Id<\"_storage\">;\n };\n return storageId;\n}\n\n/** The shape a message mutation wants a sent file described in. */\nexport type SentAttachment = {\n storageId: Id<\"_storage\">;\n name: string;\n size: number;\n type: string;\n};\n\n/** Uploads a batch in order and describes each one for the send mutation. */\nexport async function uploadAttachments(\n getUploadUrl: () => Promise<string>,\n files: File[],\n): Promise<SentAttachment[]> {\n const attachments: SentAttachment[] = [];\n for (const file of files) {\n attachments.push({\n storageId: await uploadFile(getUploadUrl, file),\n name: file.name,\n size: file.size,\n type: file.type || \"application/octet-stream\",\n });\n }\n return attachments;\n}\n","/**\n * Which finished conversations somebody has already waved the rating card\n * away on.\n *\n * Beside the session token and the read marker, and kept for the same\n * reason: a host's site is several pages, so the widget is remounted every\n * time somebody clicks a link. Held in memory, a skip would last until the\n * next click and the card would be back. Skipping is a no thanks, and asking\n * again is how a no thanks turns into a nuisance.\n *\n * One entry per API key, like the others, and capped: a browser that has\n * skipped a hundred conversations has no reason to carry all hundred ids\n * around, and the oldest of them are threads nobody will see again anyway.\n */\n\nconst STORAGE_PREFIX = \"median:rating-skips:\";\n\n/** How many are worth remembering. Past this, the oldest fall off. */\nconst MAX_REMEMBERED = 20;\n\n/** Where they live when localStorage is blocked. Lasts the page load. */\nconst inMemory = new Map<string, string[]>();\n\nfunction read(apiKey: string): string[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const stored = window.localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`);\n if (stored === null) return [];\n const parsed: unknown = JSON.parse(stored);\n return Array.isArray(parsed)\n ? parsed.filter((one): one is string => typeof one === \"string\")\n : [];\n } catch {\n // Blocked, or somebody put something else under our key.\n return inMemory.get(apiKey) ?? [];\n }\n}\n\n/** The conversations this browser has already said no thanks to. */\nexport function readSkippedRatings(apiKey: string): ReadonlySet<string> {\n return new Set(read(apiKey));\n}\n\n/** One more no thanks, remembered across the pages of a host's site. */\nexport function writeSkippedRating(\n apiKey: string,\n conversationId: string,\n): void {\n if (typeof window === \"undefined\") return;\n\n const next = [\n ...read(apiKey).filter((one) => one !== conversationId),\n conversationId,\n ].slice(-MAX_REMEMBERED);\n\n inMemory.set(apiKey, next);\n try {\n window.localStorage.setItem(\n `${STORAGE_PREFIX}${apiKey}`,\n JSON.stringify(next),\n );\n } catch {\n // Blocked, so the in-memory copy above is all there is. It still holds\n // for as long as they are on the page they skipped it from.\n }\n}\n","/**\n * A timestamp this browser remembers, per widget.\n *\n * Kept beside the session token and for the same reason: a host's site is\n * usually several pages, so the widget is remounted every time somebody\n * clicks a link. Held in memory, anything decided while the panel was\n * closed would be forgotten the moment they wandered to another page.\n *\n * One entry per API key, like the session, so two widgets on one browser\n * cannot read each other's marks. The read state and the dismissed teaser\n * are both one of these.\n */\n\n/** Where it lives when localStorage is blocked. Lasts the page load. */\nconst inMemory = new Map<string, number>();\n\nfunction keyOf(name: string, apiKey: string): string {\n return `median:${name}:${apiKey}`;\n}\n\n/** The stamp, or 0 when this browser has never written one. */\nexport function readStamp(name: string, apiKey: string): number {\n if (typeof window === \"undefined\") return 0;\n\n const key = keyOf(name, apiKey);\n try {\n const stored = window.localStorage.getItem(key);\n const at = stored === null ? Number.NaN : Number(stored);\n return Number.isFinite(at) ? at : 0;\n } catch {\n return inMemory.get(key) ?? 0;\n }\n}\n\nexport function writeStamp(name: string, apiKey: string, at: number): void {\n if (typeof window === \"undefined\") return;\n\n const key = keyOf(name, apiKey);\n inMemory.set(key, at);\n try {\n window.localStorage.setItem(key, String(at));\n } catch {\n // Blocked, so the in-memory copy above is all there is. It still holds\n // for as long as this page does, which is the part anybody would notice.\n }\n}\n","import { readStamp, writeStamp } from \"./stamps\";\n\n/**\n * How much of the conversation this browser has already seen. One of the\n * stamps in `stamps.ts`, kept under its old name because nothing about it\n * changed when the teaser arrived to share the store.\n */\n\nconst READ = \"read\";\n\n/** When they last had the panel open, or 0 if they never have. */\nexport function readLastSeenAt(apiKey: string): number {\n return readStamp(READ, apiKey);\n}\n\nexport function writeLastSeenAt(apiKey: string, at: number): void {\n writeStamp(READ, apiKey, at);\n}\n","\"use client\";\n\n/**\n * The address a visitor typed at the composer's question, kept beside the\n * session token and for the same reason: a host's site is usually several\n * pages, so the widget is remounted every time somebody clicks a link, and\n * asking all over again on each one is not a question, it is a wall.\n *\n * It rides the visitor's first message like any other fact the host passes,\n * which is what puts it on their row in the team's inbox.\n */\n\nimport { useCallback, useSyncExternalStore } from \"react\";\n\nconst STORAGE_PREFIX = \"median:email:\";\n\n/** Where it lives when localStorage is blocked. Lasts the page load. */\nconst inMemory = new Map<string, string>();\n\nconst listeners = new Set<() => void>();\n\nexport function subscribeVisitorEmail(listener: () => void) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n/** The address this browser gave, or null before it has. */\nexport function readVisitorEmail(apiKey: string): string | null {\n if (typeof window === \"undefined\") return null;\n\n try {\n const stored = window.localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`);\n return stored && stored.length > 0 ? stored : null;\n } catch {\n return inMemory.get(apiKey) ?? null;\n }\n}\n\nfunction writeVisitorEmail(apiKey: string, email: string): void {\n inMemory.set(apiKey, email);\n try {\n window.localStorage.setItem(`${STORAGE_PREFIX}${apiKey}`, email);\n } catch {\n // Blocked, so the in-memory copy above is all there is. It still gets\n // them through this page, where the message that carries it goes out.\n }\n\n for (const listener of listeners) listener();\n}\n\n/**\n * Forget every address this browser holds. Part of `medianSupport.reset()`,\n * which has to detach a browser from its conversation completely: an email\n * that survived a sign out would greet the next person at the keyboard with\n * somebody else's name.\n */\nexport function resetVisitorEmails() {\n inMemory.clear();\n\n if (typeof window !== \"undefined\") {\n try {\n const stale: string[] = [];\n for (let i = 0; i < window.localStorage.length; i += 1) {\n const key = window.localStorage.key(i);\n if (key !== null && key.startsWith(STORAGE_PREFIX)) stale.push(key);\n }\n for (const key of stale) window.localStorage.removeItem(key);\n } catch {\n // Storage was blocked, so there was nothing durable to forget.\n }\n }\n\n for (const listener of listeners) listener();\n}\n\n/**\n * The address, live: subscribed, so a reset while the widget is mounted asks\n * again rather than trusting state that outlived its storage. The setter is\n * what the composer's question calls once the answer checks out.\n */\nexport function useVisitorEmail(\n apiKey: string,\n): [string | null, (email: string) => void] {\n const email = useSyncExternalStore(\n subscribeVisitorEmail,\n useCallback(() => readVisitorEmail(apiKey), [apiKey]),\n () => null,\n );\n\n const setEmail = useCallback(\n (next: string) => writeVisitorEmail(apiKey, next),\n [apiKey],\n );\n\n return [email, setEmail];\n}\n","\"use client\";\n\nimport { ConvexError } from \"convex/values\";\nimport { Component, type ReactNode } from \"react\";\n\n/**\n * The widget runs on somebody else's page, so whatever goes wrong in here must\n * never take the host's site down with it. The widget quietly steps off the\n * page and says why in the console, where the person installing it is already\n * looking.\n */\n\n/**\n * Name the actual problem when we can. \"Check the apiKey\" is the right advice\n * for a rejected key and a wild goose chase for everything else.\n */\nfunction adviceFor(error: unknown): string {\n if (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n (error.data as { code?: string }).code === \"invalid_api_key\"\n ) {\n return \"Median did not recognize the apiKey passed to <MedianSupport>, so the widget has been hidden. Derive it from an active MEDIAN_KEY with publicKeyFromMedianKey.\";\n }\n return \"The Median support widget hit an error and has been hidden. Your page is unaffected.\";\n}\n\nexport class MedianErrorBoundary extends Component<\n { children: ReactNode },\n { hasFailed: boolean }\n> {\n state = { hasFailed: false };\n\n static getDerivedStateFromError() {\n return { hasFailed: true };\n }\n\n componentDidCatch(error: unknown) {\n console.error(adviceFor(error), error);\n }\n\n render() {\n return this.state.hasFailed ? null : this.props.children;\n }\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { MedianUser } from \"./use-median-thread\";\n\n/**\n * Who is signed in, fetched from the host's own route rather than passed down\n * their tree.\n *\n * The widget is a client component and the signature can only be made on a\n * server, so on an app with a server rendered root layout there is nowhere\n * that has both the session and this component. The route in the middle is\n * always the same one, so `medianIdentity` in @mediansh/agent-tools ships it\n * and this reads it.\n *\n * The publishable key comes down the same way. A host who points at a route\n * has one Median value in their app instead of two, and the browser safe half\n * of the key never has to be plumbed into a client environment by hand.\n */\n\n/** What `medianIdentity` answers with. Both fields absent is a valid answer. */\ntype IdentityResponse = {\n apiKey?: string;\n user?: MedianUser;\n};\n\nexport type ResolvedIdentity = {\n apiKey: string | undefined;\n user: MedianUser | undefined;\n /**\n * The answer is still on its way. True only while a route is actually being\n * read: a widget given no route is never waiting for one.\n *\n * The panel holds its loading state on this rather than showing the sign in\n * invitation, because \"we have not asked yet\" and \"they are not signed in\"\n * look identical from here and only one of them is worth telling somebody.\n */\n isLoading: boolean;\n};\n\nconst NOTHING: ResolvedIdentity = {\n apiKey: undefined,\n user: undefined,\n isLoading: false,\n};\n\n/** A route has been named and has not answered yet. */\nconst WAITING: ResolvedIdentity = { ...NOTHING, isLoading: true };\n\n/**\n * The request, while it is in the air, shared by everything waiting on it.\n *\n * A page with the support panel and the feedback panel on it mounts two\n * components that both want the same answer from the same route. One asks and\n * the other joins, rather than the host's server signing the same person\n * twice.\n *\n * Dropped the moment it settles, so nothing here outlives the answer. Signing\n * out and back in re-reads the route rather than being handed the last\n * person's signature out of a cache.\n */\nconst inFlight = new Map<string, Promise<IdentityResponse>>();\n\nfunction read(endpoint: string): Promise<IdentityResponse> {\n const existing = inFlight.get(endpoint);\n if (existing !== undefined) return existing;\n\n const request = (async () => {\n const response = await fetch(endpoint, {\n // The session lives in a cookie, and a cross origin route only sees it\n // if the request asks. Same origin routes are unaffected.\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n });\n if (!response.ok) {\n throw new Error(\n `${endpoint} answered ${response.status}. It should return { apiKey, user } from medianIdentity().`,\n );\n }\n return (await response.json()) as IdentityResponse;\n })().finally(() => inFlight.delete(endpoint));\n\n inFlight.set(endpoint, request);\n return request;\n}\n\n/**\n * Neither half was passed, so there is nothing to connect to and nothing on\n * the page. Silence here is the worst outcome: the install looks done, the\n * corner is empty, and there is no error anywhere to explain it.\n *\n * Said from the browser rather than checked by the types alone, because a\n * host on plain JavaScript, or one building options up across an `update()`\n * call, never sees the types.\n */\nexport function useMissingCredentials(\n component: string,\n apiKey: string | undefined,\n endpoint: string | undefined,\n): void {\n useEffect(() => {\n if (apiKey !== undefined || endpoint !== undefined) return;\n console.error(\n `Median: <${component}> was given neither apiKey nor identity, so nothing is on the page. Pass the median_pk_ id from publicKeyFromMedianKey(MEDIAN_KEY), or the path of a route built with medianIdentity().`,\n );\n }, [component, apiKey, endpoint]);\n}\n\nexport function useMedianIdentity(\n endpoint: string | undefined,\n): ResolvedIdentity {\n // The answer, with the route it is an answer to.\n //\n // Kept as a pair, and read back below only when the two still agree,\n // because that is what makes \"we are waiting\" a fact about the current\n // route rather than a flag something has to remember to set. Nothing here\n // writes state on the way in, and a route that changes is one comparison\n // rather than a reset.\n const [answered, setAnswered] = useState<{\n endpoint: string;\n identity: ResolvedIdentity;\n } | null>(null);\n\n useEffect(() => {\n if (endpoint === undefined) return;\n\n // A flag rather than an AbortController: the request can be shared with\n // the other panel on the page, and one of them unmounting must not cancel\n // the answer the other is still waiting for.\n let listening = true;\n\n void (async () => {\n try {\n const body = await read(endpoint);\n if (!listening) return;\n setAnswered({\n endpoint,\n identity: {\n apiKey: body.apiKey,\n // An id without its signature is ignored by the backend anyway,\n // so it is dropped here rather than sent up to be refused.\n user: body.user?.hash ? body.user : undefined,\n isLoading: false,\n },\n });\n } catch (caught) {\n if (!listening) return;\n // Support stays on the page. Without a key from anywhere the widget\n // has nothing to talk to and says so through its own boundary; with\n // one, this is a visitor whose thread belongs to their browser, which\n // is where every anonymous visitor already is.\n console.error(\n \"Median: could not read the identity route.\",\n caught instanceof Error ? caught.message : caught,\n );\n setAnswered({ endpoint, identity: NOTHING });\n }\n })();\n\n return () => {\n listening = false;\n };\n }, [endpoint]);\n\n if (endpoint === undefined) return NOTHING;\n if (answered?.endpoint === endpoint) return answered.identity;\n return WAITING;\n}\n","/**\n * The sound palette — layer/recipe types plus the seventeen built-in recipes.\n * Each sound has its own distinct shape — a chime, an arpeggio, a pitch\n * glide, a warm pad, a breath — rather than being a volume/EQ tweak on\n * the same click. Add a new one here without touching any audio graph code.\n */\nexport const RECIPES = {\n /** A soft two-note ascending bell, like an iOS/macOS confirmation tink. */\n chime: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 1046.5, attack: 0.006, decay: 0.22, peak: 0.09 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1568, offset: 0.09, attack: 0.006, decay: 0.26, peak: 0.08 },\n ],\n shimmer: { delay: 0.12, feedback: 0.25, wet: 0.18, lowpass: 4000 },\n },\n /** A quick ascending twinkle of four notes — bright and playful. */\n sparkle: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 1760, offset: 0, attack: 0.003, decay: 0.09, peak: 0.045 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2217, offset: 0.045, attack: 0.003, decay: 0.09, peak: 0.04 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2637, offset: 0.09, attack: 0.003, decay: 0.1, peak: 0.038 },\n { kind: \"tone\", waveform: \"sine\", frequency: 3520, offset: 0.135, attack: 0.003, decay: 0.12, peak: 0.032 },\n ],\n shimmer: { delay: 0.07, feedback: 0.35, wet: 0.22, lowpass: 6000 },\n },\n /** A single note gliding smoothly downward, like a drop of water. */\n droplet: {\n masterGain: 0.55,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 1200, glideTo: 550, glideTime: 0.14, attack: 0.004, decay: 0.2, peak: 0.075 },\n ],\n shimmer: { delay: 0.09, feedback: 0.2, wet: 0.15, lowpass: 3000 },\n },\n /** A warm, slow-swelling pad from two gently detuned sines. */\n bloom: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 528, attack: 0.06, decay: 0.32, peak: 0.06 },\n { kind: \"tone\", waveform: \"sine\", frequency: 528, detune: 12, attack: 0.06, decay: 0.34, peak: 0.05 },\n ],\n shimmer: { delay: 0.15, feedback: 0.2, wet: 0.12, lowpass: 2500 },\n },\n /** A soft hush with a falling tone — for tooltips and low-priority previews. */\n whisper: {\n masterGain: 0.48,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 1600, filterQ: 0.7, attack: 0.025, decay: 0.13, peak: 0.04 },\n { kind: \"tone\", waveform: \"sine\", frequency: 880, glideTo: 660, glideTime: 0.14, offset: 0.01, attack: 0.012, decay: 0.14, peak: 0.025 },\n ],\n },\n /** A focused, bandpass-filtered tick with a bright sine ping on top — crisp and instant. */\n tick: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 5400, filterQ: 1.8, attack: 0.001, decay: 0.018, peak: 0.14 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2600, attack: 0.001, decay: 0.012, peak: 0.018 },\n ],\n },\n /** A dull, muted knock — the \"down\" half of a press/release pair, like a key bottoming out. */\n press: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 1700, filterQ: 1.4, attack: 0.001, decay: 0.02, peak: 0.13 },\n ],\n },\n /** A brighter, springier tick — the \"up\" half of a press/release pair, like a key returning. */\n release: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 4600, filterQ: 1.8, attack: 0.001, decay: 0.016, peak: 0.12 },\n { kind: \"tone\", waveform: \"sine\", frequency: 3200, offset: 0.006, attack: 0.001, decay: 0.05, peak: 0.02 },\n ],\n },\n /** A two-part click-clack, like a mechanical switch flipping between states. */\n toggle: {\n masterGain: 0.4,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 2200, filterQ: 1.6, attack: 0.001, decay: 0.016, peak: 0.12 },\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 3800, filterQ: 1.6, offset: 0.024, attack: 0.001, decay: 0.02, peak: 0.1 },\n ],\n },\n /** A short, warm three-note ascending confirmation — \"done\", not a fanfare. */\n success: {\n masterGain: 0.5,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 880, attack: 0.004, decay: 0.09, peak: 0.06 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1108.73, offset: 0.06, attack: 0.004, decay: 0.1, peak: 0.06 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1318.51, offset: 0.12, attack: 0.004, decay: 0.18, peak: 0.07 },\n ],\n shimmer: { delay: 0.1, feedback: 0.22, wet: 0.16, lowpass: 4500 },\n },\n /** A muted knock followed by two descending tones — a calm, recoverable refusal. */\n error: {\n masterGain: 0.42,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 850, filterQ: 1.1, attack: 0.001, decay: 0.035, peak: 0.13 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 440, offset: 0.025, attack: 0.004, decay: 0.09, peak: 0.045 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 349.23, offset: 0.1, attack: 0.004, decay: 0.14, peak: 0.04 },\n ],\n },\n /** A papery filtered flick with a tiny glass tick — for pages, galleries, and carousels. */\n page: {\n masterGain: 0.38,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 1800, filterQ: 0.7, attack: 0.006, decay: 0.08, peak: 0.11 },\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 4200, filterQ: 1.2, offset: 0.04, attack: 0.004, decay: 0.065, peak: 0.08 },\n { kind: \"tone\", waveform: \"sine\", frequency: 2400, offset: 0.075, attack: 0.002, decay: 0.045, peak: 0.02 },\n ],\n },\n /** A brief unresolved lift — signals that user-initiated work has started. */\n loading: {\n masterGain: 0.42,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 1400, filterQ: 0.6, attack: 0.035, decay: 0.14, peak: 0.035 },\n { kind: \"tone\", waveform: \"sine\", frequency: 420, glideTo: 630, glideTime: 0.18, attack: 0.025, decay: 0.18, peak: 0.05 },\n ],\n shimmer: { delay: 0.11, feedback: 0.18, wet: 0.12, lowpass: 2800 },\n },\n /** A quick lock-on sweep resolving to a clear tone — the system is ready. */\n ready: {\n masterGain: 0.48,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 3600, filterQ: 1.8, attack: 0.001, decay: 0.02, peak: 0.11 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 330, glideTo: 660, glideTime: 0.12, offset: 0.012, attack: 0.004, decay: 0.16, peak: 0.055 },\n { kind: \"tone\", waveform: \"sine\", frequency: 990, offset: 0.13, attack: 0.004, decay: 0.22, peak: 0.06 },\n ],\n shimmer: { delay: 0.1, feedback: 0.16, wet: 0.1, lowpass: 4200 },\n },\n /** A compact synthetic chirp — crisp feedback for primary buttons and controls. */\n pulse: {\n masterGain: 0.42,\n layers: [\n { kind: \"noise\", filterType: \"bandpass\", filterFrequency: 2600, filterQ: 2.4, attack: 0.001, decay: 0.022, peak: 0.08 },\n { kind: \"tone\", waveform: \"triangle\", frequency: 620, glideTo: 1240, glideTime: 0.07, attack: 0.002, decay: 0.085, peak: 0.055 },\n ],\n },\n /** A fast three-step locator signal — playful feedback for menus and secondary buttons. */\n scan: {\n masterGain: 0.4,\n layers: [\n { kind: \"tone\", waveform: \"sine\", frequency: 740, attack: 0.002, decay: 0.055, peak: 0.05 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1110, offset: 0.045, attack: 0.002, decay: 0.055, peak: 0.045 },\n { kind: \"tone\", waveform: \"sine\", frequency: 1665, offset: 0.09, attack: 0.002, decay: 0.07, peak: 0.04 },\n ],\n shimmer: { delay: 0.065, feedback: 0.16, wet: 0.1, lowpass: 4200 },\n },\n /** A rising harmonic portal with a soft tail — for client-side page arrivals. */\n arrival: {\n masterGain: 0.44,\n layers: [\n { kind: \"noise\", filterType: \"lowpass\", filterFrequency: 900, filterQ: 0.8, attack: 0.05, decay: 0.24, peak: 0.035 },\n { kind: \"tone\", waveform: \"sine\", frequency: 220, glideTo: 440, glideTime: 0.32, attack: 0.04, decay: 0.34, peak: 0.055 },\n { kind: \"tone\", waveform: \"sine\", frequency: 659.25, offset: 0.12, attack: 0.045, decay: 0.32, peak: 0.04 },\n { kind: \"tone\", waveform: \"sine\", frequency: 987.77, offset: 0.19, attack: 0.045, decay: 0.34, peak: 0.032 },\n ],\n shimmer: { delay: 0.16, feedback: 0.28, wet: 0.18, lowpass: 3200 },\n },\n};\nexport function isSoundName(value) {\n return typeof value === \"string\" && Object.prototype.hasOwnProperty.call(RECIPES, value);\n}\n/** All available sound names, derived from the recipe palette. */\nexport const sounds = Object.keys(RECIPES);\n","/**\n * The audio engine — synthesizes each sound live via the Web Audio API\n * on one shared, lazily created `AudioContext`. No audio files, no\n * dependencies. Every sound carries a gentle envelope (and often a soft\n * shimmer tail) instead of a hard transient, so nothing feels harsh.\n */\nimport { RECIPES, isSoundName, } from \"../sounds/recipes.js\";\nconst SOURCE_STOP_PADDING = 0.05;\nconst CLEANUP_MARGIN = 0.05;\nconst INAUDIBLE_GAIN = 0.001;\nconst OUTPUT_GAIN = 4;\nfunction renderTone(context, destination, layer, startTime) {\n const oscillator = context.createOscillator();\n oscillator.type = layer.waveform;\n oscillator.frequency.setValueAtTime(layer.frequency, startTime);\n if (layer.detune)\n oscillator.detune.value = layer.detune;\n if (layer.glideTo !== undefined) {\n const glideTime = layer.glideTime ?? layer.attack + layer.decay;\n oscillator.frequency.exponentialRampToValueAtTime(layer.glideTo, startTime + glideTime);\n }\n const gain = context.createGain();\n gain.gain.setValueAtTime(0.0001, startTime);\n gain.gain.exponentialRampToValueAtTime(layer.peak, startTime + layer.attack);\n gain.gain.exponentialRampToValueAtTime(0.0001, startTime + layer.attack + layer.decay);\n oscillator.connect(gain).connect(destination);\n oscillator.start(startTime);\n oscillator.stop(startTime + layer.attack + layer.decay + SOURCE_STOP_PADDING);\n}\nfunction renderNoise(context, destination, layer, startTime) {\n const duration = layer.attack + layer.decay + SOURCE_STOP_PADDING;\n const length = Math.max(1, Math.floor(duration * context.sampleRate));\n const buffer = context.createBuffer(1, length, context.sampleRate);\n const data = buffer.getChannelData(0);\n for (let i = 0; i < length; i++)\n data[i] = 2 * Math.random() - 1;\n const source = context.createBufferSource();\n source.buffer = buffer;\n const filter = context.createBiquadFilter();\n filter.type = layer.filterType;\n filter.frequency.value = layer.filterFrequency;\n if (layer.filterQ !== undefined)\n filter.Q.value = layer.filterQ;\n const gain = context.createGain();\n gain.gain.setValueAtTime(0.0001, startTime);\n gain.gain.exponentialRampToValueAtTime(layer.peak, startTime + layer.attack);\n gain.gain.exponentialRampToValueAtTime(0.0001, startTime + layer.attack + layer.decay);\n source.connect(filter).connect(gain).connect(destination);\n source.start(startTime);\n source.stop(startTime + duration);\n}\n/** Wires a soft echo/shimmer send off `source`, feeding back into `destination`. */\nfunction attachShimmer(context, source, destination, shimmer) {\n const delay = context.createDelay(1);\n delay.delayTime.value = shimmer.delay;\n const feedbackFilter = context.createBiquadFilter();\n feedbackFilter.type = \"lowpass\";\n feedbackFilter.frequency.value = shimmer.lowpass;\n const feedbackGain = context.createGain();\n feedbackGain.gain.value = shimmer.feedback;\n const wetGain = context.createGain();\n wetGain.gain.value = shimmer.wet;\n source.connect(delay);\n delay.connect(feedbackFilter);\n feedbackFilter.connect(feedbackGain);\n feedbackGain.connect(delay);\n feedbackFilter.connect(wetGain);\n wetGain.connect(destination);\n return [delay, feedbackFilter, feedbackGain, wetGain];\n}\nfunction sourceEnd(recipe) {\n return Math.max(...recipe.layers.map((layer) => (layer.offset ?? 0) + layer.attack + layer.decay + SOURCE_STOP_PADDING));\n}\nfunction shimmerTail(shimmer) {\n if (!shimmer || shimmer.feedback <= 0)\n return 0;\n if (shimmer.feedback >= 1)\n return shimmer.delay;\n return shimmer.delay * (1 + Math.ceil(Math.log(INAUDIBLE_GAIN) / Math.log(shimmer.feedback)));\n}\nlet sharedOutput = null;\nfunction getOutput(context) {\n if (sharedOutput)\n return sharedOutput;\n const output = context.createGain();\n output.gain.value = OUTPUT_GAIN;\n const limiter = context.createDynamicsCompressor();\n limiter.threshold.value = -8;\n limiter.knee.value = 6;\n limiter.ratio.value = 12;\n limiter.attack.value = 0.002;\n limiter.release.value = 0.08;\n output.connect(limiter).connect(context.destination);\n sharedOutput = output;\n return output;\n}\nfunction renderRecipe(context, recipe, volume) {\n const now = context.currentTime;\n const output = getOutput(context);\n const master = context.createGain();\n master.gain.value = recipe.masterGain * volume;\n master.connect(output);\n const shimmerNodes = recipe.shimmer\n ? attachShimmer(context, master, output, recipe.shimmer)\n : [];\n for (const layer of recipe.layers) {\n const startTime = now + (layer.offset ?? 0);\n if (layer.kind === \"tone\")\n renderTone(context, master, layer, startTime);\n else\n renderNoise(context, master, layer, startTime);\n }\n const cleanupAfterMs = (sourceEnd(recipe) + shimmerTail(recipe.shimmer) + CLEANUP_MARGIN) * 1000;\n setTimeout(() => {\n master.disconnect();\n for (const node of shimmerNodes)\n node.disconnect();\n }, cleanupAfterMs);\n}\nlet sharedContext = null;\nlet enabled = true;\nlet globalVolume = 1;\nfunction normalizeVolume(value, fallback) {\n return typeof value === \"number\" && Number.isFinite(value)\n ? Math.min(1, Math.max(0, value))\n : fallback;\n}\n/** Enables or disables future playback. Preference storage stays with the app. */\nexport function setEnabled(value) {\n if (typeof value === \"boolean\")\n enabled = value;\n}\n/** Sets the volume multiplier for future playback. Preference storage stays with the app. */\nexport function setVolume(value) {\n globalVolume = normalizeVolume(value, globalVolume);\n}\nfunction getAudioContext() {\n if (sharedContext)\n return sharedContext;\n if (typeof window === \"undefined\")\n return null;\n const Ctor = window.AudioContext ??\n window.webkitAudioContext;\n if (!Ctor)\n return null;\n try {\n sharedContext = new Ctor();\n }\n catch {\n return null;\n }\n return sharedContext;\n}\n/**\n * Plays a sound immediately. Safe to call from anywhere — lazily creates\n * the shared `AudioContext` on first use, resumes it if the browser\n * started it suspended (e.g. before any user gesture), and is a no-op\n * when Web Audio is unavailable (SSR, old browsers).\n */\nexport function play(sound = \"chime\", options) {\n if (!enabled || !isSoundName(sound))\n return;\n if (typeof navigator !== \"undefined\" && navigator.userActivation?.hasBeenActive === false)\n return;\n const playVolume = globalVolume * normalizeVolume(options?.volume, 1);\n if (playVolume === 0)\n return;\n const context = getAudioContext();\n if (!context)\n return;\n const recipe = RECIPES[sound];\n if (context.state === \"running\") {\n renderRecipe(context, recipe, playVolume);\n }\n else {\n try {\n void context.resume().then(() => {\n if (enabled && context.state === \"running\")\n renderRecipe(context, recipe, playVolume);\n }, () => { });\n }\n catch {\n // Some browsers throw synchronously when audio is blocked.\n }\n }\n}\n","\"use client\";\n\nimport { play } from \"cuelume\";\nimport { useEffect, useRef } from \"react\";\nimport type { SupportMessage } from \"../types\";\n\n/**\n * Under the default, because this plays on somebody else's site while they are\n * reading it. Loud enough to catch with the panel closed, quiet enough to sit\n * behind whatever else they have on.\n */\nconst ARRIVAL_VOLUME = 0.45;\n\n/**\n * The twinkle a reply lands on, whether the panel is open or not. Closed is\n * where it earns its keep: the count on the launcher is the only other thing\n * saying anything came in, and nobody is looking at the corner.\n *\n * The same rule the ring and the navigation follow, for the same reason: the\n * first snapshot is history, however recent, and history does not ring. Without\n * it, every page of a host's site would open on a sparkle for a conversation\n * from last week. A thread being fetched again is a thread this page has not\n * read either, so whatever lands after that is history too.\n *\n * And a change of thread is a first snapshot of its own. Somebody signing in\n * hands this page an account's whole history at once, which is a great many\n * replies it has never heard and not one of them worth a sound.\n *\n * Only the other side's messages, and only once they are written. A bubble\n * holding dots keeps its id and fills in later, so waiting for the words means\n * the sound arrives with them rather than with the promise of them.\n *\n * `play` neither throws nor asks: it is a no-op without Web Audio, and stays\n * quiet until the visitor has interacted with the page at all. That last one is\n * the browser's rule about autoplay, and it is a rule worth keeping.\n */\nexport function useMessageSound({\n messages,\n conversationId = null,\n isLoading,\n}: {\n messages: SupportMessage[];\n /** The thread being watched. A different one starts the listening over. */\n conversationId?: string | null;\n /** Nothing is history until the first answer has arrived. */\n isLoading: boolean;\n}) {\n /** Every written reply this page has already heard. */\n const heard = useRef<Set<string> | null>(null);\n /** Which thread that set is about. */\n const watching = useRef<string | null>(null);\n\n useEffect(() => {\n if (isLoading) {\n heard.current = null;\n return;\n }\n\n const written = messages.filter(\n (message) => message.sender === \"agent\" && !message.pending,\n );\n\n if (heard.current === null || watching.current !== conversationId) {\n heard.current = new Set(written.map((message) => message.id));\n watching.current = conversationId;\n return;\n }\n\n // One sparkle however many arrived together: a person taking over and\n // answering in the same breath is still one thing to look up at.\n let hasArrived = false;\n for (const message of written) {\n if (heard.current.has(message.id)) continue;\n heard.current.add(message.id);\n hasArrived = true;\n }\n\n if (hasArrived) play(\"sparkle\", { volume: ARRIVAL_VOLUME });\n }, [messages, conversationId, isLoading]);\n}\n","\"use client\";\n\nimport { useLayoutEffect, useRef, useState } from \"react\";\nimport type { SupportAsk, SupportMessage } from \"../types\";\n\n/**\n * Doing what one of the team's own tools asked to be done to the page: taking\n * the reader somewhere, pointing at something there, or both.\n *\n * The instruction rides on the message that explains it, but a layout effect\n * acts before those words are painted. Everything here is about making sure\n * that ordering happens exactly once.\n *\n * The thread is a live query and the message stays in it forever, so \"act on\n * what I can see\" would move somebody every time the query re-ran, and again\n * every time they came back to the page. What actually counts as new is what\n * arrived after the widget started watching: the first snapshot is history,\n * however recent, and history is not an instruction. That also covers the\n * loop this would otherwise be, where a host who navigates with a full page\n * load remounts the widget onto the message that moved it.\n *\n * A thread can also change under a page that never stopped watching it.\n * Somebody signs in, the widget says who they are, and a query that answered\n * \"no conversation\" a second ago answers with the account's whole history\n * instead. Every word of it is new to this page and none of it is news, so a\n * change of thread starts the first look over, and an instruction has to be\n * recent as well as unseen before anything is done about it.\n *\n * Nothing navigates at all without `onNavigate`. Moving a host's page because\n * their server answered with a field is not a thing to do by default, and a\n * host who wired the tool but not the handler hears about it in the console\n * rather than by watching nothing happen. Pointing at something needs no\n * handler: the ring is ours, drawn over their page and taken away again.\n */\n\n// Guarded as in control.ts: the published bundle cannot assume `process`.\nconst isDevelopment =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"development\";\n\n/**\n * How recently an instruction has to have been asked for to be worth acting\n * on.\n *\n * Long enough that a slow network, a reconnect, or a tab coming back from\n * sleep still lands the one that just happened. Short enough that a\n * conversation from last week cannot move anybody, whatever route it takes\n * into the query: the person reading this page did not ask for it, and\n * whoever did is long gone.\n *\n * Generous because the two ends of the comparison are two different clocks.\n * The instruction is stamped by the server and the age is worked out on a\n * machine that may be a minute out either way, so the window is minutes\n * rather than seconds. Nothing about a live exchange needs it tighter.\n */\nconst STALE_AFTER_MS = 5 * 60 * 1000;\n\n/** What a message asked for, once it is this page's business to do it. */\nexport type SupportDirection = {\n /** The message that asked, so a second ask is a new one. */\n key: string;\n /** Whether the page was actually moved, which is the only thing worth\n * announcing: a destination nobody could act on moved nothing. */\n didNavigate: boolean;\n /** What to point at once they are looking at the right page, if anything. */\n selector: string | null;\n};\n\n/**\n * The destination as somewhere on this site, or null.\n *\n * Median checks the path when the tool answers and again before it is stored,\n * and neither of those is on the machine that navigates. This one is. `//host`\n * and `/\\host` resolve to another origin rather than a path, which is the\n * whole reason this asks the URL parser instead of reading the string.\n */\nfunction pathOnThisSite(destination: string): string | null {\n if (typeof window === \"undefined\") return null;\n if (!destination.startsWith(\"/\")) return null;\n\n let url: URL;\n try {\n url = new URL(destination, window.location.origin);\n } catch {\n return null;\n }\n if (url.origin !== window.location.origin) return null;\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\n/**\n * Everything asking for something to be done rather than only said, oldest\n * first.\n *\n * Two carriers, one list. A message carries the instruction the agent's own\n * turn produced; a standalone ask carries one from a run that never produced\n * a message, which is a teammate running a tool themselves. The loose one\n * goes last because it is the newer of the two whenever both land together:\n * a teammate reaches for a tool in a thread the agent has already answered.\n */\nfunction directed(\n messages: SupportMessage[],\n ask: SupportAsk | null,\n): SupportAsk[] {\n const asked: SupportAsk[] = messages\n .filter(\n (message) =>\n message.navigateTo !== undefined || message.highlight !== undefined,\n )\n .map((message) => ({\n key: message.id,\n // Canned content may leave the clock off, and a message with no time on\n // it reads as old here rather than as now. Nothing that moves a page\n // should be doing it on a guess.\n at: message.sentAt ?? 0,\n navigateTo: message.navigateTo ?? null,\n highlight: message.highlight ?? null,\n }));\n\n if (ask !== null) asked.push(ask);\n return asked;\n}\n\nexport function useSupportNavigation({\n messages,\n ask = null,\n conversationId = null,\n isLoading,\n onNavigate,\n}: {\n messages: SupportMessage[];\n /** The one not riding a message, when a run produced one. */\n ask?: SupportAsk | null;\n /**\n * The thread being watched. When it changes, what is on screen is somebody\n * else's history rather than this page's next line, so the first look\n * starts again.\n */\n conversationId?: string | null;\n /** Nothing is history until the first answer has arrived. */\n isLoading: boolean;\n onNavigate?: (path: string) => void;\n}): SupportDirection | null {\n /** Every message carrying an instruction that this page has already seen. */\n const seen = useRef<Set<string> | null>(null);\n /** Which thread that set is about. */\n const watching = useRef<string | null>(null);\n const [direction, setDirection] = useState<SupportDirection | null>(null);\n\n // A layout effect is deliberate: the direction and its message arrive in\n // one live-query update, so the host gets to move before the browser paints\n // a confirmation claiming that it already did.\n useLayoutEffect(() => {\n if (isLoading) return;\n\n const asked = directed(messages, ask);\n\n // The first look is the thread as it already was. Remembered, never\n // acted on: whatever is in it happened before this page existed.\n //\n // A different thread than the one this set was built for is a first look\n // as well. That is signing in: the account's history arrives whole, into\n // a page that has been watching an empty query, and none of it happened\n // here.\n if (seen.current === null || watching.current !== conversationId) {\n seen.current = new Set(asked.map((one) => one.key));\n watching.current = conversationId;\n return;\n }\n\n // Only the newest is worth showing afterwards. Two in one turn is a turn\n // that has already gone wrong, and the later of them is the one the words\n // underneath are about.\n let latest: SupportDirection | null = null;\n\n for (const one of asked) {\n if (seen.current.has(one.key)) continue;\n // Marked before it is acted on, so a handler that throws, or one that\n // navigates without unmounting, cannot be asked twice.\n seen.current.add(one.key);\n\n // Unseen and still not news. An instruction is a thing somebody is\n // doing to a page in front of a reader, so one that has been sitting in\n // a thread since yesterday is not carried out late: not the navigation,\n // and not the ring either.\n //\n // An instruction with no time on it moves nobody either. That is a\n // deployment answering from before any of this, and the safe reading of\n // \"I cannot tell how old this is\" is to leave the page alone.\n const age = Date.now() - one.at;\n if (!Number.isFinite(age) || age > STALE_AFTER_MS) continue;\n\n let didNavigate = false;\n const destination = one.navigateTo;\n\n if (destination !== null) {\n const path = pathOnThisSite(destination);\n if (onNavigate === undefined) {\n if (isDevelopment) {\n console.warn(\n `Median: a tool asked to take this visitor to ${destination}, but <MedianSupport> has no onNavigate. Pass one, such as onNavigate={router.push}, or the tool cannot move anybody.`,\n );\n }\n } else if (path === null) {\n console.error(\n `Median: refused to navigate to ${destination}, which is not a path on this site.`,\n );\n } else {\n onNavigate(path);\n didNavigate = true;\n }\n }\n\n latest = { key: one.key, didNavigate, selector: one.highlight };\n }\n\n // Said on the next frame rather than in the middle of this one. What the\n // ring and the line are is settled here, where what actually happened is\n // known; showing them is the render after, like any other arrival.\n let frame = 0;\n if (latest !== null) {\n const announced = latest;\n frame = requestAnimationFrame(() => setDirection(announced));\n }\n return () => cancelAnimationFrame(frame);\n }, [messages, ask, conversationId, isLoading, onNavigate]);\n\n return direction;\n}\n","\"use client\";\n\nimport { useCallback, useState } from \"react\";\nimport type { SupportMessage } from \"../types\";\nimport { readTeaserDismissedAt, writeTeaserDismissedAt } from \"./teaser-state\";\n\n/**\n * Which reply, if any, gets the card over the closed button.\n *\n * The newest unread reply, unless this browser already waved it away. A\n * reply that lands after a dismissal is news again and gets a card of its\n * own, which is the whole reason the dismissal is a time rather than a flag.\n *\n * Opening the panel is handled elsewhere: it marks everything seen, the\n * unread list empties, and there is nothing left here to show.\n */\nexport function useTeaser(\n apiKey: string,\n /** The newest reply they have not looked at, or null. */\n latestUnread: SupportMessage | null,\n): { teaser: SupportMessage | null; dismiss: () => void } {\n const [dismissedAt, setDismissedAt] = useState(() =>\n readTeaserDismissedAt(apiKey),\n );\n\n const teaser =\n latestUnread !== null && (latestUnread.sentAt ?? 0) > dismissedAt\n ? latestUnread\n : null;\n\n const dismiss = useCallback(() => {\n if (teaser === null) return;\n // Stamped with when the reply was sent rather than with now, so a reply\n // that has been sitting on the server since before the click still\n // counts as dismissed, and one that arrives a second later does not.\n const at = teaser.sentAt ?? Date.now();\n writeTeaserDismissedAt(apiKey, at);\n setDismissedAt(at);\n }, [apiKey, teaser]);\n\n return { teaser, dismiss };\n}\n","import { readStamp, writeStamp } from \"./stamps\";\n\n/**\n * The newest reply whose teaser this browser waved away.\n *\n * Its own stamp rather than the read one, because the two mean different\n * things. Dismissing the card says \"not now\", and the count stays on the\n * button until the panel is actually opened; marking a reply read would\n * take the count with it, and a visitor who closed a card has not read the\n * three replies behind it.\n */\n\nconst TEASER = \"teaser\";\n\n/** When the last dismissed reply was sent, or 0 if none ever was. */\nexport function readTeaserDismissedAt(apiKey: string): number {\n return readStamp(TEASER, apiKey);\n}\n\nexport function writeTeaserDismissedAt(apiKey: string, at: number): void {\n writeStamp(TEASER, apiKey, at);\n}\n","\"use client\";\n\nimport { createRoot } from \"react-dom/client\";\nimport { MedianSupport, type MedianSupportProps } from \"./median-support\";\n\n/**\n * What a mounted widget hands back: the two things a host without React has\n * no re-render to do for them. Everything else goes through `medianSupport`,\n * same as anywhere.\n */\nexport type MedianSupportInstance = {\n /**\n * Change any option after mount. Only the keys passed change, so\n * `update({ user })` when somebody signs in leaves the rest alone.\n */\n update: (options: Partial<MedianSupportProps>) => void;\n /** Take the widget off the page: panel, launcher, connection, all of it. */\n unmount: () => void;\n};\n\n// Guarded as in control.ts: the published bundle cannot assume `process`.\nconst isDevelopment =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"development\";\n\n/**\n * The same widget, for a page that has never heard of React: Vue, Svelte,\n * Rails, a script on plain HTML. One call puts the launcher in the corner,\n * wired to the same panel, thread and inbox as the component:\n *\n * const support = mountMedianSupport({ apiKey: \"median_pk_...\" });\n *\n * It takes the component's props, as one options object, and the rest of the\n * SDK does not know the difference: `medianSupport.open()` opens this widget\n * exactly as it opens the component.\n *\n * What would have been new props on a re-render is `update`:\n *\n * support.update({ user: { name: \"Ada\", email: \"ada@example.com\" } });\n *\n * It renders into a container of its own, appended to `<body>`, with the\n * package's copy of React. The host's page needs none and never sees it.\n */\nexport function mountMedianSupport(\n options: MedianSupportProps,\n): MedianSupportInstance {\n // A server rendering the page has nowhere to put a widget. Say so where\n // the installer is looking, and hand back an instance that is safe to\n // hold, because a broken widget must never take the page down with it.\n if (typeof document === \"undefined\") {\n console.error(\n \"Median: mountMedianSupport() was called where there is no document, so nothing was mounted. Call it in the browser, after the page exists.\",\n );\n return { update: () => {}, unmount: () => {} };\n }\n\n const container = document.createElement(\"div\");\n container.dataset.medianSupport = \"\";\n document.body.appendChild(container);\n\n const root = createRoot(container);\n let current = options;\n let mounted = true;\n\n const render = () => {\n root.render(<MedianSupport {...current} />);\n };\n render();\n\n return {\n update(next) {\n if (!mounted) {\n if (isDevelopment) {\n console.warn(\n \"Median: update() was called after unmount(), so nothing changed. Mount again with mountMedianSupport() if the widget should come back.\",\n );\n }\n return;\n }\n current = { ...current, ...next };\n render();\n },\n unmount() {\n if (!mounted) return;\n mounted = false;\n root.unmount();\n container.remove();\n },\n };\n}\n","\"use client\";\n\nimport { API_KEY_PREFIX, hasPrefix } from \"@median/backend/support\";\nimport { ConvexProvider, ConvexReactClient } from \"convex/react\";\nimport { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { FeedbackPanel } from \"../feedback/feedback-panel\";\nimport { FeedbackPopover } from \"../feedback/feedback-popover\";\nimport { MEDIAN_DEPLOYMENT_URL } from \"./deployment\";\nimport type { MedianDiagnostics } from \"./diagnostics\";\nimport { MedianErrorBoundary } from \"./error-boundary\";\nimport {\n useMedianFeedbackOpenState,\n useRegisterMedianFeedback,\n} from \"./feedback-control\";\nimport { useRememberInstall } from \"./install\";\nimport { useMedianIdentity, useMissingCredentials } from \"./use-identity\";\nimport { useFeedbackNote } from \"./use-feedback-note\";\nimport type { MedianUser } from \"./use-median-thread\";\n\n/** Wide enough for a paragraph, narrow enough to hang off a menu item. */\nconst DEFAULT_WIDTH = \"20rem\";\n\ntype MedianFeedbackOptions = {\n /**\n * Your own trigger. Whatever you pass is rendered where you put it and the\n * panel hangs off it, the way a dropdown hangs off the thing that opens\n * it:\n *\n * <MedianFeedback apiKey=\"median_pk_...\">\n * <button>Share feedback</button>\n * </MedianFeedback>\n *\n * It is wrapped in an inline span that takes the click, so your button\n * keeps its own styles and needs to know nothing about any of this.\n *\n * Without children the panel sits in the bottom right corner instead, for\n * a host opening it from somewhere else entirely with\n * `useMedianFeedback()`.\n */\n children?: ReactNode;\n /**\n * Something already on your page for the panel to hang off, as a CSS\n * selector. For the case children cannot cover: a row inside a dropdown,\n * which closes itself opening this and takes the trigger with it.\n *\n * <MedianFeedback apiKey=\"median_pk_...\" anchor=\"#account-button\" />\n *\n * Looked up each time the panel is placed, so it works for anything that\n * comes and goes. Unlike a trigger it is only a position: pressing it does\n * not open or close the panel, and a press on it dismisses the panel like\n * a press anywhere else. Ignored when `children` are passed.\n */\n anchor?: string;\n /** Who is signed in on your site, if anyone. Shown to your team. */\n user?: MedianUser;\n /**\n * Whether a note carries what the browser already knows: time zone,\n * language, browser, OS, device, screen, and the page it was written on.\n * On by default, because the page is most of what makes a note actionable,\n * which is what the panel says out loud. Pass `false` and none of it is\n * read at all.\n */\n telemetry?: boolean;\n /**\n * Watch what goes wrong on the page, so a bug filed from a note arrives\n * with the error already attached. The same switch `<MedianSupport>`\n * takes, and the same buffer behind it: mount either one with it on.\n */\n diagnostics?: MedianDiagnostics;\n /**\n * Anything about your own app worth having next to a bug report: a build,\n * a route, a flag. Read when a note is sent.\n */\n appState?: Record<string, string | number | boolean>;\n /** Pass it, with `onOpenChange`, to hold the open state yourself. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Any CSS length. The panel never grows past the viewport whatever this says. */\n width?: string;\n /** The heading, for a host whose product calls this something else. */\n title?: string;\n /** The line under it. */\n description?: string;\n placeholder?: string;\n};\n\n/**\n * Two ways in, the same two `<MedianSupport>` takes.\n *\n * `apiKey` is the publishable id on its own. `identity` is the path to a\n * route built with `medianIdentity`, which answers with the key and with\n * whoever is signed in, already signed. Pass both and the panel is usable on\n * the key from the prop while the route is still answering.\n */\nexport type MedianFeedbackProps = MedianFeedbackOptions &\n (\n | { apiKey: string; identity?: string }\n | { apiKey?: string; identity: string }\n );\n\n/** The same, once the gate below has settled which key and which person. */\ntype ConnectedFeedbackProps = MedianFeedbackOptions & { apiKey: string };\n\n/**\n * The same two ways in, for a host without JSX. Spelled out rather than\n * `Omit`ped off the props above, because omitting a key from a union of two\n * shapes flattens it into one and loses the \"either, but not neither\" the\n * union is there to say.\n */\nexport type MedianFeedbackMountOptions = Omit<MedianFeedbackOptions, \"children\"> &\n (\n | { apiKey: string; identity?: string }\n | { apiKey?: string; identity: string }\n );\n\n/**\n * A feedback panel, hung off a trigger of your own.\n *\n * One box and one button. Whoever is on the page types a sentence, and a\n * fast model reads it: a bug goes on the bug list, an idea goes on the\n * suggestions list, and an advert goes nowhere. Nobody has to pick a\n * category, rank anything, or write a title, which is the point, because a\n * form that asks for those is a form nobody fills in.\n *\n * <MedianFeedback apiKey=\"median_pk_...\">\n * <MenuItem>Share feedback</MenuItem>\n * </MedianFeedback>\n *\n * The page they were on rides along on its own, which the line under the\n * title says plainly.\n *\n * It brings its own connection, so it works on pages that have never heard\n * of Convex, and it is independent of `<MedianSupport>`: mount either, both,\n * or neither. Mounted together they share a visitor, so the same person\n * writing in and leaving a note is one customer with both to their name.\n */\nexport function MedianFeedback(props: MedianFeedbackProps) {\n return (\n <MedianErrorBoundary>\n <FeedbackIdentity {...props} />\n </MedianErrorBoundary>\n );\n}\n\n/**\n * The same gate `<MedianSupport>` has, for the same reason: the signature can\n * only be made on a server and this is a client component. Both panels on one\n * page read the one route between them. See `use-identity.ts`.\n */\nfunction FeedbackIdentity({\n apiKey,\n identity,\n user,\n ...rest\n}: MedianFeedbackOptions & { apiKey?: string; identity?: string }) {\n const resolved = useMedianIdentity(identity);\n useMissingCredentials(\"MedianFeedback\", apiKey, identity);\n const key = apiKey ?? resolved.apiKey;\n const person = user ?? resolved.user;\n\n if (key === undefined) return null;\n\n return (\n <FeedbackConnection\n {...rest}\n apiKey={key}\n {...(person ? { user: person } : {})}\n />\n );\n}\n\n/**\n * A key with the wrong shape would only ever fail later, quietly, as a panel\n * that never sends. Say so now, in the console, while the person who pasted\n * it is still looking at this page.\n */\nfunction useApiKeyShapeWarning(apiKey: string) {\n useEffect(() => {\n if (hasPrefix(apiKey, API_KEY_PREFIX)) return;\n\n const shown =\n apiKey === \"\"\n ? \"an empty string\"\n : `\"${apiKey.length > 16 ? `${apiKey.slice(0, 16)}…` : apiKey}\"`;\n console.error(\n `Median: the apiKey passed to <MedianFeedback> is ${shown}, which does not look like the browser-safe id from publicKeyFromMedianKey(MEDIAN_KEY). It should start with ${API_KEY_PREFIX}.`,\n );\n }, [apiKey]);\n}\n\nfunction FeedbackConnection(props: ConnectedFeedbackProps) {\n // Its own client rather than the app's, so the panel is self contained on\n // a host site. Lazy so a missing URL fails at render, into the boundary.\n const [client] = useState(() => {\n if (!MEDIAN_DEPLOYMENT_URL) {\n throw new Error(\n \"The Median feedback panel was built without a deployment URL. Set NEXT_PUBLIC_CONVEX_URL.\",\n );\n }\n return new ConvexReactClient(MEDIAN_DEPLOYMENT_URL);\n });\n\n return (\n <ConvexProvider client={client}>\n <Feedback {...props} />\n </ConvexProvider>\n );\n}\n\nfunction Feedback({\n apiKey,\n children,\n anchor,\n user,\n telemetry,\n diagnostics,\n appState,\n open,\n onOpenChange,\n width = DEFAULT_WIDTH,\n title,\n description,\n placeholder,\n}: ConnectedFeedbackProps) {\n useRegisterMedianFeedback();\n useApiKeyShapeWarning(apiKey);\n // The support panel writes the same thing down. Either one is enough for a\n // crash screen to have a key to report with.\n useRememberInstall(apiKey, user);\n\n const triggerRef = useRef<HTMLSpanElement>(null);\n const [isOpen, setOpen] = useMedianFeedbackOpenState({\n ...(open !== undefined ? { open } : {}),\n ...(onOpenChange ? { onOpenChange } : {}),\n });\n\n const note = useFeedbackNote({\n apiKey,\n ...(user ? { user } : {}),\n ...(telemetry !== undefined ? { telemetry } : {}),\n ...(diagnostics !== undefined ? { diagnostics } : {}),\n ...(appState ? { appState } : {}),\n });\n\n const close = useCallback(() => setOpen(false), [setOpen]);\n\n // A fresh box for the next note, but not until this one is out of sight:\n // resetting as the panel closes would swap the thank-you back to an empty\n // form halfway through the fade. So the panel is remounted on the way\n // back in, and only when there is something to clear. A draft somebody\n // closed without sending is theirs, and survives.\n const [attempt, setAttempt] = useState(0);\n const hasSent = useRef(false);\n useEffect(() => {\n if (!isOpen || !hasSent.current) return;\n hasSent.current = false;\n setAttempt((count) => count + 1);\n }, [isOpen]);\n\n return (\n <>\n {children !== undefined && (\n // An inline span rather than a clone of whatever was passed: the\n // host's trigger keeps its own props, its own ref and its own\n // styles, and the click is caught on the way past. `display:\n // contents` would lose the rectangle the panel is measured against.\n <span\n ref={triggerRef}\n onClick={() => setOpen(!isOpen)}\n className=\"inline-flex\"\n >\n {children}\n </span>\n )}\n\n <FeedbackPopover\n isOpen={isOpen}\n onClose={close}\n triggerRef={triggerRef}\n {...(anchor !== undefined ? { anchor } : {})}\n width={width}\n >\n <FeedbackPanel\n key={attempt}\n onSubmit={note.submit}\n onClose={close}\n onSent={() => {\n hasSent.current = true;\n close();\n }}\n notice={note.notice}\n {...(title !== undefined ? { title } : {})}\n {...(description !== undefined ? { description } : {})}\n {...(placeholder !== undefined ? { placeholder } : {})}\n />\n </FeedbackPopover>\n </>\n );\n}\n","/**\n * The feedback panel's vocabulary: what a note may be, what it may point at,\n * and the three answers a reader can give about one.\n *\n * Deliberately pure, like `shared/signals.ts`: no Convex imports, nothing\n * that touches a database. The widget reads these limits before it sends and\n * the mutation enforces them on arrival, so neither side can drift.\n */\n\n/**\n * How much one note may be. Longer than a chat message would be worth\n * reading in a bubble and shorter than the write-up it turns into, because\n * this is a box somebody types a paragraph into, not a document.\n */\nexport const NOTE_MAX_LENGTH = 2_000;\n\n/**\n * Where a note goes.\n *\n * The first two are the Signal tab's own kinds, so a note that survives\n * reading lands on the list the team already triages. The third is the one\n * that goes nowhere: a page open to the internet collects adverts, keyboard\n * mashing, and people testing whether the box works, and none of that is\n * worth a row somebody has to close.\n */\nexport const FEEDBACK_VERDICTS = [\"bug\", \"suggestion\", \"spam\"] as const;\n\nexport type FeedbackVerdict = (typeof FEEDBACK_VERDICTS)[number];\n\n/** Trims a note, keeping its line breaks: somebody wrote it in a textarea. */\nexport function cleanNote(input: string): string {\n return input.trim().slice(0, NOTE_MAX_LENGTH);\n}\n\n/** What is wrong with this note, in a sentence, or null if nothing is. */\nexport function noteIssue(note: string): string | null {\n if (note.trim().length === 0) return \"Write something first.\";\n if (note.length > NOTE_MAX_LENGTH) {\n return `Feedback has to be ${NOTE_MAX_LENGTH} characters or fewer.`;\n }\n return null;\n}\n","import { isUnsafeAttachmentType } from \"./support\";\n\n/**\n * The pictures on a bug report: what a customer sent, what the agent found a\n * link to, and what a host handed over on purpose.\n *\n * A screenshot is the fastest thing on a report to read. Everything else on\n * one is a description of what went wrong; a picture is the thing itself. So\n * they are lifted out of wherever they arrived and kept on the report, where\n * a developer meets them without opening the conversation they came from.\n *\n * Two ways a picture can be here, and the difference is who is holding it.\n * `stored` is a file that came through us and lives in our storage, which is\n * what an upload from the widget or the feedback panel becomes. `linked` is\n * an address on somebody else's machine, which is what an agent or an API\n * caller can offer, since neither has a file to hand over.\n *\n * Deliberately pure, like `signals.ts` and `customData.ts` next door: the SDK\n * trims what it sends with this file and the mutation trims it again on\n * arrival, so neither side is trusting the other's arithmetic.\n */\n\n/**\n * The storage id is a plain string here so this file stays free of Convex.\n * The schema's validator is what pins it to `_storage`, and the model layer\n * hands these functions rows that already carry the real id.\n */\nexport type ReportImage<StorageId extends string = string> =\n | {\n kind: \"stored\";\n storageId: StorageId;\n name: string;\n type: string;\n size: number;\n }\n | { kind: \"linked\"; url: string; name: string };\n\n/** What an image link looks like as it arrives, before it is cleaned. */\nexport type ImageLink = { url: string; name?: string };\n\n/**\n * The most one report holds. Past a handful nobody is looking at the sixth\n * screenshot, and a thread that ran long would otherwise push the write-up\n * off the top of the card.\n */\nexport const MAX_REPORT_IMAGES = 6;\n\n/** Enough to say what a picture is without wrapping the row it sits in. */\nexport const IMAGE_NAME_MAX_LENGTH = 80;\n\n/** Long enough for a signed link with its query string still on it. */\nexport const IMAGE_URL_MAX_LENGTH = 2_000;\n\n/** When the address gave nothing worth calling it. */\nconst UNNAMED = \"Screenshot\";\n\n/**\n * Extensions a lone URL has to end in before we will treat it as a picture.\n *\n * Only used for guessing, never for something a caller explicitly called an\n * image. SVG is missing on purpose: a browser runs one, which is the same\n * reason `UNSAFE_ATTACHMENT_TYPES` turns them away as uploads.\n */\nconst IMAGE_EXTENSIONS = [\"png\", \"jpg\", \"jpeg\", \"gif\", \"webp\", \"avif\", \"bmp\"];\n\n/** Whether a content type is a picture we are willing to show. */\nexport function isImageContentType(type: string): boolean {\n const bare = type.split(\";\")[0].trim().toLowerCase();\n return bare.startsWith(\"image/\") && !isUnsafeAttachmentType(bare);\n}\n\n/**\n * An address a browser may be pointed at, or null.\n *\n * Only http and https: a `javascript:` or `data:` value in an `src` is the\n * whole of how a pasted link becomes somebody else's code running on the\n * dashboard, and neither is ever what a screenshot arrives as.\n */\nfunction cleanUrl(input: unknown): string | null {\n if (typeof input !== \"string\") return null;\n const url = input.trim();\n if (url.length === 0 || url.length > IMAGE_URL_MAX_LENGTH) return null;\n return /^https?:\\/\\/\\S+$/i.test(url) ? url : null;\n}\n\n/** The last part of the path, which is usually what the file is called. */\nfunction nameFromUrl(url: string): string {\n // Past the host as well as the query string: an address with nothing after\n // the domain has no name in it, and \"acme.com\" is not what a picture is\n // called.\n const path = url.split(/[?#]/)[0].replace(/^https?:\\/\\/[^/]*/i, \"\");\n const last = path.split(\"/\").filter(Boolean).pop();\n if (last === undefined) return UNNAMED;\n const name = decodeURIComponent(last).slice(0, IMAGE_NAME_MAX_LENGTH);\n return name.length > 0 ? name : UNNAMED;\n}\n\n/** Whatever it was called, trimmed to something a caption can hold. */\nfunction trimName(input: unknown): string | null {\n if (typeof input !== \"string\") return null;\n const name = input.trim().replace(/\\s+/g, \" \").slice(0, IMAGE_NAME_MAX_LENGTH);\n return name.length > 0 ? name : null;\n}\n\n/**\n * Whether an address looks like a picture from the outside.\n *\n * A guess, and only ever used where guessing is the point: a host attaching\n * `{ label: \"Screenshot\", value: \"https://…/broken.png\" }` through the\n * ordinary custom data door meant a picture, and asking them to learn a\n * second API to say so would be a worse product than reading the extension.\n * Anything that does not end in one stays a link, which is what it was.\n */\nexport function looksLikeImageUrl(value: unknown): string | null {\n const url = cleanUrl(value);\n if (url === null) return null;\n\n const path = url.split(/[?#]/)[0].toLowerCase();\n const dot = path.lastIndexOf(\".\");\n if (dot === -1) return null;\n return IMAGE_EXTENSIONS.includes(path.slice(dot + 1)) ? url : null;\n}\n\n/**\n * Whatever arrived, cut down to the links that may be stored. Undefined when\n * nothing survived, so an empty list never lands on a row and reads later as\n * \"they attached something and it was blank\".\n *\n * No extension check here: a caller passing this has said it is a picture,\n * and plenty of real ones are served from an address that ends in an id.\n */\nexport function cleanImageLinks(\n input: unknown,\n): Extract<ReportImage, { kind: \"linked\" }>[] | undefined {\n if (!Array.isArray(input)) return undefined;\n\n const byUrl = new Map<string, string>();\n for (const raw of input) {\n const source =\n typeof raw === \"string\" ? { url: raw } : (raw as ImageLink | null);\n if (typeof source !== \"object\" || source === null) continue;\n\n const url = cleanUrl(source.url);\n if (url === null) continue;\n // Re-set so a repeated address takes the newer name for it.\n byUrl.delete(url);\n byUrl.set(url, trimName(source.name) ?? nameFromUrl(url));\n }\n\n const links = [...byUrl].map(([url, name]) => ({\n kind: \"linked\" as const,\n url,\n name,\n }));\n return links.length > 0 ? links.slice(-MAX_REPORT_IMAGES) : undefined;\n}\n\n/**\n * Whatever arrived describing files already in our storage, cut down the\n * same way. The ids themselves are checked by the validator on the way in;\n * what this decides is whether the thing is a picture worth showing.\n */\nexport function cleanStoredImages<StorageId extends string>(\n input: readonly {\n storageId: StorageId;\n name: string;\n type: string;\n size: number;\n }[],\n): Extract<ReportImage<StorageId>, { kind: \"stored\" }>[] | undefined {\n const kept = input\n .filter((file) => isImageContentType(file.type))\n .map((file) => ({\n kind: \"stored\" as const,\n storageId: file.storageId,\n name: trimName(file.name) ?? UNNAMED,\n type: file.type,\n size: file.size,\n }));\n return kept.length > 0 ? kept.slice(-MAX_REPORT_IMAGES) : undefined;\n}\n\n/** What makes two pictures the same picture: the thing they point at. */\nfunction keyOf(image: ReportImage): string {\n return image.kind === \"stored\"\n ? `stored:${image.storageId}`\n : `linked:${image.url}`;\n}\n\n/**\n * Several sources of pictures, oldest source first, folded into one list.\n * The same rules as cleaning: one entry per picture, later wins, newest kept\n * when the cap says something has to go.\n */\nexport function mergeReportImages<StorageId extends string>(\n ...sources: (readonly ReportImage<StorageId>[] | undefined)[]\n): ReportImage<StorageId>[] | undefined {\n const byKey = new Map<string, ReportImage<StorageId>>();\n for (const image of sources.flatMap((list) => list ?? [])) {\n byKey.delete(keyOf(image));\n byKey.set(keyOf(image), image);\n }\n\n const images = [...byKey.values()];\n return images.length > 0 ? images.slice(-MAX_REPORT_IMAGES) : undefined;\n}\n","\"use client\";\n\nimport { NOTE_MAX_LENGTH } from \"@median/backend/feedback\";\nimport { MAX_REPORT_IMAGES } from \"@median/backend/reportImages\";\nimport {\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type KeyboardEvent,\n} from \"react\";\nimport {\n AttachmentDraftChip,\n useAttachmentDrafts,\n useAttachmentTarget,\n} from \"@/components/attachments\";\nimport { ArrowsClockwise, Check, ImageSquare, X } from \"@/components/icons\";\nimport { Collapse } from \"@/components/ui/collapse\";\nimport { TEXT_FIELD_SHELL } from \"@/components/ui/text-field\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { cn } from \"@/lib/utils\";\nimport { PoweredByMedian } from \"../widget-badge\";\nimport { WidgetButton } from \"../widget-button\";\nimport { AUTOFOCUS_ATTRIBUTE } from \"./feedback-popover\";\n\n/** How long the thank-you sits there before whoever owns the panel closes it. */\nconst THANKS_MS = 1_600;\n\n/**\n * The feedback panel: one box, one button, and no questions in front of them.\n *\n * A visitor with something to say should not first have to decide whether it\n * is a bug or an idea, rank it, or write a title. So the panel asks for a\n * sentence and nothing else, and the reader on the other side does the rest.\n * The page rides along on its own, which the line under the title says\n * plainly, because collecting it quietly would be somebody else's business\n * to be told about rather than ours to assume.\n *\n * One surface, not two. The box sits straight on the card rather than inside\n * a tray of its own: a panel this small has no room for a container that\n * contains one thing, and the extra edge only made it look like there was\n * more here than there is.\n *\n * Presentational, like `SupportWidget`: a note goes out through `onSubmit`\n * and nothing is held here but the draft.\n */\nexport function FeedbackPanel({\n onSubmit,\n onClose,\n onSent,\n notice,\n showBadge = true,\n title = \"Share feedback\",\n description = \"This page is included automatically.\",\n placeholder = \"What should change?\",\n className,\n}: {\n /**\n * Awaited. A rejection keeps the draft and the pictures, so a send that\n * fails costs a retry rather than a retype.\n */\n onSubmit?: (note: string, images: File[]) => unknown;\n /** Omit to hide the close button, for a panel that is always on the page. */\n onClose?: () => void;\n /** The thank-you has been read. Whoever opened the panel closes it. */\n onSent?: () => void;\n /** One line under the box, for a send that went wrong. */\n notice?: string | null;\n /** The \"Powered by Median\" line. Hosts on a paid plan can turn it off. */\n showBadge?: boolean;\n title?: string;\n description?: string;\n placeholder?: string;\n className?: string;\n}) {\n const [draft, setDraft] = useState(\"\");\n const [isSending, setSending] = useState(false);\n const [isSent, setSent] = useState(false);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n // Pictures only. Everything else on a report is words, and a note is not a\n // place to hand over a database dump.\n const images = useAttachmentDrafts({\n accept: \"image\",\n max: MAX_REPORT_IMAGES,\n });\n const target = useAttachmentTarget({ onFiles: images.add });\n\n const canSend =\n draft.trim().length > 0 && !images.hasBlocker && !isSending && !isSent;\n\n // The thank-you is read, then the panel is somebody else's problem. In an\n // effect rather than in the handler so a panel unmounted in between never\n // calls back into a host that has moved on.\n useEffect(() => {\n if (!isSent) return;\n const timer = setTimeout(() => onSent?.(), THANKS_MS);\n return () => clearTimeout(timer);\n }, [isSent, onSent]);\n\n async function send() {\n if (!canSend) return;\n setSending(true);\n try {\n await onSubmit?.(draft.trim(), images.files);\n } catch {\n // The notice under the box says why. The draft and its pictures stay put.\n return;\n } finally {\n setSending(false);\n }\n images.clear();\n setSent(true);\n }\n\n function handlePick(event: ChangeEvent<HTMLInputElement>) {\n if (event.target.files?.length) images.add(event.target.files);\n // Cleared so picking the same file twice in a row still fires a change.\n event.target.value = \"\";\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {\n // Enter is a new line here, not a send: this is a paragraph box rather\n // than a chat composer, and the button is right there. Meta and enter\n // still sends, which is what anybody who tries it expects.\n if (event.key !== \"Enter\") return;\n if (!event.metaKey && !event.ctrlKey) return;\n event.preventDefault();\n void send();\n }\n\n return (\n <section\n aria-label={title}\n {...target.targetProps}\n className={cn(\n // The widget's own radius scale, so the app's token can climb as the\n // chrome gets rounder without this changing shape under its hosts.\n \"flex w-full flex-col gap-2 overflow-hidden rounded-xl border bg-card p-3 text-card-foreground [--radius:0.625rem]\",\n className,\n )}\n >\n <header className=\"flex items-start gap-2\">\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <h2 className=\"truncate text-sm font-semibold tracking-tight\">\n {title}\n </h2>\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n </div>\n\n {onClose && (\n <WidgetButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n onClick={onClose}\n aria-label=\"Close feedback\"\n className=\"-mt-0.5 -mr-1 shrink-0 text-muted-foreground\"\n >\n <X />\n </WidgetButton>\n )}\n </header>\n\n {/* Two rows of one grid, one opening as the other closes, so the swap\n is the panel changing height rather than two panels. */}\n <div className=\"grid\">\n <Collapse isOpen={!isSent}>\n <div className=\"flex flex-col gap-1.5\">\n <Textarea\n rows={3}\n value={draft}\n maxLength={NOTE_MAX_LENGTH}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={target.isDropTarget ? \"Drop to attach\" : placeholder}\n aria-label={title}\n {...{ [AUTOFOCUS_ATTRIBUTE]: \"\" }}\n className={cn(\n TEXT_FIELD_SHELL,\n \"max-h-40 min-h-18 px-2.5 py-2\",\n // 16px on phones, in pixels: any focused field smaller than\n // that makes iOS zoom the host's whole page in.\n \"max-sm:text-[16px]\",\n )}\n />\n\n {images.drafts.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {images.drafts.map((draft) => (\n <AttachmentDraftChip\n key={draft.id}\n draft={draft}\n onRemove={() => images.remove(draft.id)}\n />\n ))}\n </div>\n )}\n\n {notice && (\n <p className=\"animate-in px-0.5 text-xs text-destructive fade-in duration-150\">\n {notice}\n </p>\n )}\n </div>\n </Collapse>\n\n <Collapse isOpen={isSent}>\n <div className=\"flex items-center justify-center gap-2 py-4 text-sm font-medium\">\n <span className=\"grid size-5 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground\">\n <Check className=\"size-3\" />\n </span>\n Thanks, we got it.\n </div>\n </Collapse>\n </div>\n\n {/* Our name and the one action, on the same line: the foot of a panel\n this small is a row rather than two.\n\n The height is held whether or not the button is in it, so the row\n does not shrink under the thank-you while the panel above it is\n already animating. */}\n <div className=\"flex min-h-8 items-center gap-2\">\n {showBadge && <PoweredByMedian className=\"justify-start\" />}\n\n {!isSent && (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n multiple\n tabIndex={-1}\n onChange={handlePick}\n className=\"sr-only\"\n />\n <WidgetButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={images.isFull}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Add a picture\"\n className=\"ml-auto shrink-0 rounded-full text-muted-foreground\"\n >\n <ImageSquare />\n </WidgetButton>\n\n <WidgetButton\n type=\"button\"\n disabled={!canSend}\n aria-busy={isSending}\n onClick={() => void send()}\n className=\"relative shrink-0 rounded-full px-3\"\n >\n {/* The label stays in the box while the spinner is over it, so\n it goes on setting the width and a send never moves the\n button it is happening in. */}\n <span\n className={cn(\n \"transition-opacity duration-150 motion-reduce:transition-none\",\n isSending && \"opacity-0\",\n )}\n >\n Submit feedback\n </span>\n\n {isSending && (\n <ArrowsClockwise\n aria-hidden\n className=\"absolute inset-0 m-auto animate-spin motion-reduce:animate-none\"\n />\n )}\n </WidgetButton>\n </>\n )}\n </div>\n </section>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"@/lib/utils\";\nimport { useHydrated } from \"../use-hydrated\";\nimport { useAnchor } from \"./use-anchor\";\n\n/** Above the host's own chrome. Their z-indexes are not ours to guess at. */\nconst LAYER = 2_147_483_000;\n\n/**\n * What inside the panel takes focus when it opens. The panel says which,\n * because which field is the one somebody came to fill in is the panel's\n * business rather than the box it is drawn in.\n */\nexport const AUTOFOCUS_ATTRIBUTE = \"data-median-autofocus\";\n\n/**\n * How the panel arrives and leaves.\n *\n * A dropdown, so it comes out of the thing that opened it: a little smaller\n * and a little towards its trigger, growing into place. The spring is the\n * same one the support panel opens with, and it overshoots by a hair, which\n * is the difference between a panel that appears and one that pops.\n *\n * Leaving is quicker and has no spring. An overshoot on the way out is a\n * panel arguing about being closed.\n */\n// `scale` and `translate` by name: those are the properties Tailwind's\n// `scale-*` and `translate-y-*` set. Listed as `transform` the panel had\n// neither, and popped open on opacity alone.\nconst MOTION =\n \"transition-[opacity,scale,translate] motion-reduce:transition-none\";\nconst OPEN = \"duration-250 ease-spring\";\nconst SHUT = \"duration-150 ease-out-quint\";\n\n/**\n * The panel, in a layer of its own, under whatever opened it.\n *\n * Portalled to the body rather than rendered where the trigger is. A host's\n * trigger lives inside their layout, and a panel rendered there inherits\n * every `overflow: hidden`, stacking context and transform between it and\n * the page. Out here it answers to the window and to nothing else.\n *\n * Closed, it stays mounted and goes `inert`: the draft somebody was halfway\n * through survives a close, and nothing behind the fade can be tabbed into.\n */\nexport function FeedbackPopover({\n isOpen,\n onClose,\n triggerRef,\n anchor,\n width,\n children,\n}: {\n isOpen: boolean;\n onClose: () => void;\n /** The host's own trigger, when they wrapped one. */\n triggerRef: RefObject<HTMLElement | null>;\n /**\n * Something else on their page to hang off, as a selector. Unlike the\n * trigger it is only a position: a press on it closes the panel like a\n * press anywhere else, because it is not the thing doing the opening.\n */\n anchor?: string;\n /** Any CSS length. Never wider than the window, whatever this says. */\n width: string;\n children: ReactNode;\n}) {\n const panelRef = useRef<HTMLDivElement>(null);\n const side = useAnchor({ triggerRef, anchor, panelRef, isOpen });\n // The panel is medianled into `document.body`, which does not exist until\n // there is one. Nothing at all until then, on the server and through\n // hydration alike, so both passes agree.\n const isHydrated = useHydrated();\n\n // Whatever had focus when the panel came up, so closing can hand it back.\n const opener = useRef<HTMLElement | null>(null);\n // Focus only moves once the panel has actually changed state, or a panel\n // that started open would steal focus on page load.\n const wasOpen = useRef(isOpen);\n\n // Escape closes, wherever focus is inside the panel. The element picker\n // takes its own Escape first, in the capture phase, so backing out of\n // pointing at something never closes the whole panel with it.\n useEffect(() => {\n if (!isOpen) return;\n\n function handleKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") onClose();\n }\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onClose]);\n\n // A press anywhere else closes it, the way every dropdown does. On\n // pointerdown rather than click, so it closes as the press lands rather\n // than when it is let go, and the trigger is left out: it does its own\n // toggling, and closing here first would make a second press reopen.\n useEffect(() => {\n if (!isOpen) return;\n\n function handlePointerDown(event: PointerEvent) {\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (panelRef.current?.contains(target)) return;\n if (triggerRef.current?.contains(target)) return;\n onClose();\n }\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [isOpen, onClose, triggerRef]);\n\n useEffect(() => {\n if (wasOpen.current === isOpen) return;\n wasOpen.current = isOpen;\n\n if (isOpen) {\n const active = document.activeElement;\n opener.current = active instanceof HTMLElement ? active : null;\n // Straight into whatever the panel says takes focus, which is the box\n // they are here to type in. Unlike the support widget's launcher this\n // is never opened by accident: somebody chose it from a menu or a\n // button, and landing anywhere but the field would cost them a Tab.\n const field = panelRef.current?.querySelector<HTMLElement>(\n `[${AUTOFOCUS_ATTRIBUTE}]`,\n );\n (field ?? panelRef.current)?.focus();\n return;\n }\n\n const back = triggerRef.current ?? opener.current;\n opener.current = null;\n // Only somewhere focus can actually land, and only if it is still on the\n // page: a menu that closed behind the panel is not there to take it back.\n if (back && back !== document.body && back.isConnected) back.focus();\n }, [isOpen, triggerRef]);\n\n if (!isHydrated) return null;\n\n return createPortal(\n <div\n ref={panelRef}\n tabIndex={-1}\n inert={!isOpen}\n // The hook the published stylesheet scopes its resets to. On a page\n // without Tailwind there is no preflight, so the package ships one\n // that reaches no further than this box.\n data-median-widget=\"\"\n style={{\n zIndex: LAYER,\n width,\n top: 0,\n left: 0,\n // Grows out of the edge nearest its trigger rather than out of its\n // own middle, which is what makes it read as the trigger opening.\n transformOrigin: side === \"top\" ? \"bottom center\" : \"top center\",\n }}\n className={cn(\n \"fixed max-w-[calc(100vw-2rem)] outline-none\",\n // The shadow is on the box rather than inside the panel: a filter on\n // a parent of anything that scrolls makes the browser repaint it on\n // every frame, and there is nothing scrolling in here to protect.\n \"drop-shadow-xl\",\n MOTION,\n isOpen\n ? [OPEN, \"pointer-events-auto scale-100 opacity-100 translate-y-0\"]\n : [\n SHUT,\n \"pointer-events-none scale-[0.97] opacity-0\",\n // Towards its trigger, which is above it or below it.\n side === \"top\" ? \"translate-y-1\" : \"-translate-y-1\",\n ],\n )}\n >\n {children}\n </div>,\n document.body,\n );\n}\n","\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\n\n/**\n * Whether this is running in a browser that has finished hydrating.\n *\n * For the things that cannot exist until there is a document: a median has to\n * be handed a node, and there is no `document.body` on a server. Returning\n * null for those and the real thing once mounted is a server/client branch,\n * which is the first thing React names when it reports a hydration mismatch:\n * the server sends nothing, the client's first pass renders a panel, and the\n * whole tree is thrown away and built again.\n *\n * So it is read as an external store rather than as a mounted flag. React\n * takes the server snapshot both on the server and through hydration, so both\n * passes agree on nothing, and only the commit after it moves. Same trick the\n * session token is read with, for the same reason.\n *\n * The store never changes, so nothing ever subscribes to anything.\n */\nconst subscribe = () => () => {};\nconst onClient = () => true;\nconst onServer = () => false;\n\nexport function useHydrated(): boolean {\n return useSyncExternalStore(subscribe, onClient, onServer);\n}\n","\"use client\";\n\nimport { useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * Keeping the panel under whatever opened it.\n *\n * The host owns the trigger: it is a nav item, a menu row, a button in a\n * toolbar, and it can be anywhere on their page. So the panel is measured\n * against it rather than pinned to a corner, and it follows it: a page that\n * scrolls or resizes under an open panel keeps the two together.\n *\n * The edges are written straight onto the node rather than held in state,\n * because scrolling fires far more often than anything worth re-rendering\n * for, and the panel's own opening animation is a transform. Position and\n * motion on two different properties is what keeps them from fighting.\n */\n\n/** Between the trigger and the panel. */\nconst GAP = 8;\n\n/** How close to the edge of the window the panel is allowed to sit. */\nconst MARGIN = 16;\n\n/** Which side of the trigger the panel ended up on, for the motion. */\nexport type AnchorSide = \"top\" | \"bottom\";\n\n/**\n * Whatever the selector finds, or nothing.\n *\n * Read every time it is placed rather than once, because the point of taking\n * a selector at all is that the thing it names may not have been on the page\n * when the panel opened. A menu item that opens this closes itself doing it;\n * the button the menu hangs off is still there, and that is what a selector\n * is for.\n */\nfunction findAnchor(selector: string | undefined): HTMLElement | null {\n if (selector === undefined || typeof document === \"undefined\") return null;\n try {\n return document.querySelector<HTMLElement>(selector);\n } catch {\n console.error(\n `Median: the anchor passed to <MedianFeedback> is ${selector}, which is not a valid CSS selector.`,\n );\n return null;\n }\n}\n\nexport function useAnchor({\n triggerRef,\n anchor,\n panelRef,\n isOpen,\n}: {\n /** The host's own trigger, when they wrapped one. */\n triggerRef: RefObject<HTMLElement | null>;\n /** Something on their page to hang off instead. Both absent is the corner. */\n anchor?: string;\n panelRef: RefObject<HTMLDivElement | null>;\n isOpen: boolean;\n}): AnchorSide {\n const [side, setSide] = useState<AnchorSide>(\"bottom\");\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let frame = 0;\n\n function place() {\n const panel = panelRef.current;\n const trigger = triggerRef.current ?? findAnchor(anchor);\n if (panel === null) return;\n\n const width = panel.offsetWidth;\n const height = panel.offsetHeight;\n const room = {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n\n // Nothing to hang off, so it sits in the corner every widget sits in.\n if (trigger === null) {\n panel.style.left = `${Math.max(MARGIN, room.width - width - MARGIN)}px`;\n panel.style.top = `${Math.max(MARGIN, room.height - height - MARGIN)}px`;\n setSide(\"bottom\");\n return;\n }\n\n const rect = trigger.getBoundingClientRect();\n\n // Under the trigger, unless the panel would not fit and there is more\n // room above it. Flipping only when it actually helps: a panel that\n // jumped over its trigger the moment the page got short would move\n // for nothing most of the time.\n const below = room.height - rect.bottom - GAP - MARGIN;\n const above = rect.top - GAP - MARGIN;\n const onTop = height > below && above > below;\n setSide(onTop ? \"top\" : \"bottom\");\n\n const top = onTop ? rect.top - GAP - height : rect.bottom + GAP;\n\n // Aligned to whichever edge of the trigger keeps the panel on screen:\n // its left edge normally, its right edge when the trigger is over\n // towards the right, which is where a nav item usually is.\n const fromStart = rect.left;\n const fromEnd = rect.right - width;\n const left =\n fromStart + width + MARGIN <= room.width ? fromStart : fromEnd;\n\n panel.style.left = `${clamp(left, MARGIN, room.width - width - MARGIN)}px`;\n panel.style.top = `${clamp(top, MARGIN, room.height - height - MARGIN)}px`;\n }\n\n /** One placement per frame at most, however hard the page is scrolling. */\n function schedule() {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(place);\n }\n\n place();\n window.addEventListener(\"scroll\", schedule, true);\n window.addEventListener(\"resize\", schedule);\n\n // The panel changes height as the box grows and as the thank-you takes\n // over, and a panel flipped above its trigger has to move when it does.\n const observer = new ResizeObserver(schedule);\n if (panelRef.current !== null) observer.observe(panelRef.current);\n\n return () => {\n cancelAnimationFrame(frame);\n window.removeEventListener(\"scroll\", schedule, true);\n window.removeEventListener(\"resize\", schedule);\n observer.disconnect();\n };\n }, [isOpen, anchor, panelRef, triggerRef]);\n\n return side;\n}\n\nfunction clamp(value: number, low: number, high: number): number {\n // High can be below low on a window shorter than the panel, and then the\n // top edge wins: the way out is up there.\n return Math.max(low, Math.min(value, Math.max(low, high)));\n}\n","\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport {\n createOpenStore,\n useOpenState,\n useRegister,\n} from \"./open-store\";\n\n/**\n * Driving the feedback panel from anywhere on the page.\n *\n * The panel usually hangs off a trigger the host wrapped it around, and for\n * that this is not needed at all. It is here for the other way of putting\n * feedback on a page: a row in a menu somewhere else entirely, a keyboard\n * shortcut, a link at the foot of an error screen. Same shape as\n * `medianSupport`, and a store of its own, so opening one never opens the\n * other.\n */\nconst store = createOpenStore(\"MedianFeedback\");\n\nexport const medianFeedback = {\n /** What the panel is doing right now. */\n get isOpen() {\n return store.readEffective();\n },\n open() {\n store.request(true);\n store.warnIfNothingIsMounted(\"the feedback panel was asked to open\");\n },\n close() {\n store.request(false);\n },\n toggle() {\n const next = !store.readEffective();\n store.request(next);\n if (next) {\n store.warnIfNothingIsMounted(\"the feedback panel was asked to open\");\n }\n },\n} satisfies MedianFeedbackControl;\n\n/** The shape of {@link medianFeedback}, and of what the hook returns. */\nexport type MedianFeedbackControl = {\n /** Whether the panel is open. */\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n};\n\n/**\n * The feedback panel, from anywhere else on the page:\n *\n * const feedback = useMedianFeedback();\n *\n * <button onClick={feedback.open}>Share feedback</button>\n *\n * `isOpen` follows the panel however it was opened, so a menu row can render\n * itself as pressed while it is up.\n */\nexport function useMedianFeedback(): MedianFeedbackControl {\n const isOpen = useSyncExternalStore(\n store.subscribe,\n store.readEffective,\n store.readServerEffective,\n );\n\n return {\n isOpen,\n open: medianFeedback.open,\n close: medianFeedback.close,\n toggle: medianFeedback.toggle,\n };\n}\n\n/** The panel's own settled open state. See {@link useOpenState}. */\nexport function useMedianFeedbackOpenState(options: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): [boolean, (next: boolean) => void] {\n return useOpenState(store, options);\n}\n\n/** One panel per page, and a word in the console when there are two. */\nexport function useRegisterMedianFeedback() {\n useRegister(store);\n}\n","\"use client\";\n\nimport { api } from \"@median/backend\";\nimport { useMutation } from \"convex/react\";\nimport { useCallback, useState, useSyncExternalStore } from \"react\";\nimport { errorMessage } from \"@/lib/errors\";\nimport { uploadAttachments } from \"@/lib/upload\";\nimport { collectContext, collectPage } from \"./context\";\nimport { restoreCustomData, takeCustomData } from \"./custom-data\";\nimport { useDiagnostics, type MedianDiagnostics } from \"./diagnostics\";\nimport { getOrCreateSessionId, subscribeSession } from \"./session\";\nimport { splitIdentity, type MedianUser } from \"./use-median-thread\";\n\n/**\n * Sending one note, and everything that rides along with it.\n *\n * The same session token the support widget uses, so a person who has\n * written in and then left feedback is one customer with both to their name\n * rather than two strangers who happen to share a browser. The same\n * telemetry, the same diagnostics ring buffer, and the same attached data\n * too: a bug report filed off a note deserves what a bug report filed off a\n * conversation gets.\n *\n * Nothing is read here. A note is a thing you hand over, not a thread you\n * watch, so there is no subscription and nothing to keep in step.\n */\n\n/** What the panel is told about a note that could not be taken. */\nconst REFUSALS: Record<string, string> = {\n off: \"This site is not taking feedback right now.\",\n empty: \"Write something first.\",\n};\n\nexport function useFeedbackNote({\n apiKey,\n user,\n telemetry = true,\n diagnostics,\n appState,\n}: {\n apiKey: string;\n user?: MedianUser;\n telemetry?: boolean;\n diagnostics?: MedianDiagnostics;\n appState?: Record<string, string | number | boolean>;\n}) {\n // The session token is external state (localStorage), read as a store: the\n // server snapshot is null, so SSR and the first client paint agree, and\n // `reset()` on sign out lands here like it lands on the thread.\n const sessionId = useSyncExternalStore(\n subscribeSession,\n useCallback(() => getOrCreateSessionId(apiKey), [apiKey]),\n () => null,\n );\n\n const submitNote = useMutation(api.feedback.submit);\n // The widget's own upload door, which the panel may use whether or not the\n // support widget is mounted: it is guarded by the same key and the same\n // toll, and a screenshot is a screenshot either way.\n const getUploadUrl = useMutation(api.widget.generateUploadUrl);\n const takeDiagnostics = useDiagnostics(diagnostics, appState);\n const [notice, setNotice] = useState<string | null>(null);\n\n /**\n * Rejects when the note did not land, which is what keeps the draft in the\n * box. The reason is in `notice` by then, where the panel shows it.\n */\n const submit = useCallback(\n async (body: string, images: File[] = []) => {\n setNotice(null);\n if (sessionId === null) {\n setNotice(\"This browser is still waking up. Try again in a moment.\");\n throw new Error(\"No session yet.\");\n }\n\n // Whatever the host attached since the last send rides this note.\n // Taken outside the try so a failed send hands it back too.\n const custom = takeCustomData();\n // Whether a refusal has already said its own piece. State cannot\n // answer that here: it is set and read inside one tick.\n let explained = false;\n try {\n // Read now rather than on mount: all of it is wanted as \"what was\n // true when they wrote\", and a panel can sit closed on a page for an\n // hour before anybody opens it.\n const context = telemetry ? collectContext() : undefined;\n const page = telemetry ? collectPage() : undefined;\n const collected = takeDiagnostics();\n const { facts, claim } = splitIdentity(user ?? null);\n // Before the note, so a picture that will not upload stops the send\n // rather than landing as a report with a missing screenshot.\n const attached = await uploadAttachments(\n () => getUploadUrl({ apiKey, sessionId }),\n images,\n );\n\n const outcome = await submitNote({\n apiKey,\n sessionId,\n body,\n ...(user ? { user: facts } : {}),\n ...(claim ? { identity: claim } : {}),\n ...(context ? { context } : {}),\n ...(page ? { page } : {}),\n ...(collected ? { diagnostics: collected } : {}),\n ...(custom ? { customData: custom } : {}),\n ...(attached.length > 0 ? { images: attached } : {}),\n });\n\n if (outcome !== \"taken\") {\n explained = true;\n setNotice(REFUSALS[outcome] ?? \"That did not send.\");\n throw new Error(outcome);\n }\n } catch (caught) {\n // Back in the queue, so the retry carries them like it keeps the draft.\n if (custom) restoreCustomData(custom);\n if (!explained) {\n console.error(\"Sending feedback from the Median panel failed\", caught);\n setNotice(errorMessage(caught));\n }\n // Rethrown so the panel keeps the draft: a failed send should cost a\n // retry, never a retype.\n throw caught;\n }\n },\n [\n apiKey,\n sessionId,\n user,\n telemetry,\n takeDiagnostics,\n submitNote,\n getUploadUrl,\n ],\n );\n\n return { submit, notice, clearNotice: () => setNotice(null) };\n}\n","\"use client\";\n\nimport { createRoot } from \"react-dom/client\";\nimport { isDevelopment } from \"./open-store\";\nimport {\n MedianFeedback,\n type MedianFeedbackMountOptions,\n type MedianFeedbackProps,\n} from \"./median-feedback\";\n\n/**\n * What a mounted panel hands back: the two things a host without React has\n * no re-render to do for them. Opening and closing go through\n * `medianFeedback`, same as anywhere.\n */\nexport type MedianFeedbackInstance = {\n /**\n * Change any option after mount. Only the keys passed change, so\n * `update({ user })` when somebody signs in leaves the rest alone.\n */\n update: (options: Partial<MedianFeedbackProps>) => void;\n /** Take the panel off the page. */\n unmount: () => void;\n};\n\n/**\n * The same panel, for a page that has never heard of React: Vue, Svelte,\n * Rails, a script on plain HTML.\n *\n * const feedback = mountMedianFeedback({ apiKey: \"median_pk_...\" });\n *\n * document.querySelector(\"#feedback\").onclick = () => medianFeedback.open();\n *\n * There is no trigger to wrap out here, so the panel opens in the bottom\n * right corner and your own button says when. Everything else is the\n * component's, unchanged.\n */\nexport function mountMedianFeedback(\n options: MedianFeedbackMountOptions,\n): MedianFeedbackInstance {\n // A server rendering the page has nowhere to put a panel. Say so where the\n // installer is looking, and hand back an instance that is safe to hold,\n // because a broken panel must never take the page down with it.\n if (typeof document === \"undefined\") {\n console.error(\n \"Median: mountMedianFeedback() was called where there is no document, so nothing was mounted. Call it in the browser, after the page exists.\",\n );\n return { update: () => {}, unmount: () => {} };\n }\n\n const container = document.createElement(\"div\");\n container.dataset.medianFeedback = \"\";\n document.body.appendChild(container);\n\n const root = createRoot(container);\n let current = options;\n let mounted = true;\n\n const render = () => {\n root.render(<MedianFeedback {...current} />);\n };\n render();\n\n return {\n update(next) {\n if (!mounted) {\n if (isDevelopment) {\n console.warn(\n \"Median: update() was called after unmount(), so nothing changed. Mount again with mountMedianFeedback() if the panel should come back.\",\n );\n }\n return;\n }\n current = { ...current, ...next };\n render();\n },\n unmount() {\n if (!mounted) return;\n mounted = false;\n root.unmount();\n container.remove();\n },\n };\n}\n"],"mappings":"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","names":["useEffect","useState","useCallback","useEffect","useRef","useState","l","s","r","a","t","o","i","c","m","e","e","t","r","e","a","o","e","t","a","o","a","e","r","e","s","r","a","e","o","e","s","r","a","e","o","t","e","o","a","e","e","r","t","t","e","e","r","o","t","a","e","o","e","r","e","e","a","o","r","t","a","e","e","a","o","m","p","a","e","e","a","o","r","t","a","e","a","e","a","r","o","e","t","a","e","o","e","r","o","a","e","e","m","r","o","e","a","a","e","r","o","e","a","e","r","s","a","e","a","r","o","a","r","a","l","t","o","a","l","e","e","a","r","o","s","a","r","e","a","e","o","a","o","e","a","e","r","t","a","e","o","o","a","o","e","a","r","t","r","e","o","r","o","e","o","e","at","buttonY","listeners","React","i","a","r","t","e","o","s","f","l","p","c","jsx","e","t","r","o","i","S","l","d","b","p","m","c","f","s","a","w","I","X","e","t","r","o","i","S","l","jsx","X","d","b","p","m","f","param","React","i","Slot","__name","Slottable","child","React","jsx","useEffect","Fragment","jsx","jsxs","useCallback","useLayoutEffect","useRef","useRef","useCallback","useLayoutEffect","useEffect","useRef","useState","forwardRef","jsx","Image","jsx","jsx","jsxs","useEffect","useRef","useState","useRef","useState","jsx","jsx","useCallback","useEffect","useRef","d","jsx","d","jsx","jsxs","jsx","jsxs","useState","useRef","useEffect","useState","jsx","jsx","useState","shape","jsx","shape","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs","jsx","useState","Fragment","jsx","jsxs","useState","useLayoutEffect","useRef","jsx","prefersReducedMotion","release","useRef","useLayoutEffect","jsx","jsx","jsx","jsxs","Fragment","jsx","jsxs","useEffect","useRef","useState","jsx","jsx","jsxs","useState","useRef","useEffect","jsx","jsxs","jsx","jsxs","useCallback","useEffect","useLayoutEffect","useRef","useState","useSyncExternalStore","enabled","useSyncExternalStore","useState","useRef","useCallback","useLayoutEffect","useEffect","clamp","useLayoutEffect","useState","enabled","useLayoutEffect","useState","useSyncExternalStore","useEffect","SETTLE_MS","useSyncExternalStore","useState","useLayoutEffect","useState","Fragment","jsx","jsxs","buttonY","useState","jsx","jsxs","useState","useRef","useCallback","useEffect","current","useEffect","useRef","useState","jsx","jsxs","prefersReducedMotion","useEffect","useState","createPortal","jsx","jsxs","LAYER","useState","useEffect","createPortal","useSyncExternalStore","useCallback","useEffect","useSyncExternalStore","listeners","store","useSyncExternalStore","read","trim","withoutQuery","events","useCallback","useEffect","useRef","withoutQuery","useEffect","listeners","listeners","i","useCallback","useEffect","useMemo","useState","useSyncExternalStore","useEffect","useState","STORAGE_PREFIX","read","inMemory","at","at","useCallback","useSyncExternalStore","STORAGE_PREFIX","inMemory","listeners","i","useSyncExternalStore","useCallback","useMemo","useEffect","useState","current","useSyncExternalStore","useSyncExternalStore","ConvexError","useEffect","useState","inFlight","read","i","useEffect","useRef","useLayoutEffect","useRef","useState","isDevelopment","useCallback","useState","at","useState","useCallback","at","Fragment","jsx","jsxs","useEffect","client","useState","jsx","isDevelopment","current","ConvexProvider","ConvexReactClient","useCallback","useEffect","useRef","useState","useEffect","useRef","useState","useEffect","useRef","createPortal","useSyncExternalStore","subscribe","onServer","useLayoutEffect","useState","GAP","MARGIN","clamp","jsx","LAYER","useRef","useEffect","createPortal","Fragment","jsx","jsxs","THANKS_MS","useState","useRef","useEffect","draft","useSyncExternalStore","store","useSyncExternalStore","useMutation","useCallback","useState","useSyncExternalStore","useSyncExternalStore","useCallback","useMutation","useState","Fragment","jsx","jsxs","DEFAULT_WIDTH","useApiKeyShapeWarning","useEffect","client","useState","ConvexReactClient","ConvexProvider","useRef","useCallback","createRoot","jsx","createRoot","current"]}
|