feedbackkit-web 1.0.50 → 1.0.51

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.
@@ -1 +1 @@
1
- {"version":3,"file":"feedbackkit.js","sources":["../src/capture.ts","../src/environment.ts","../src/logs.ts","../src/submit.ts","../src/fixes.ts","../src/ui/icons.ts","../src/ui/fixCard.ts","../src/renderer.ts","../src/ui/editor.ts","../src/ui/styles.ts","../src/ui/widget.ts","../src/index.ts"],"sourcesContent":["import type { CaptureMode } from \"./types\";\n\n/**\n * Viewport screenshot capture.\n *\n * Default (`\"dom\"`) re-renders the page's own DOM into an image with\n * `modern-screenshot` (SVG `foreignObject`, so the browser itself lays out\n * every modern CSS feature — no hand-written CSS engine like html2canvas,\n * which can't even parse Tailwind v4's `oklch()` colors). Same idea as the\n * native SDKs' window-level capture: render our own view hierarchy rather\n * than read the screen buffer, so no permission prompt is ever shown.\n *\n * What the user saw is the *viewport*, not the whole document, so the root\n * is clipped to `innerWidth × innerHeight` and shifted by the scroll offset\n * (`restoreScrollPosition`). Shifting the document puts a transform on\n * `<body>`, which silently turns it into the containing block for every\n * `position: fixed` descendant — so fixed and sticky elements (headers,\n * toasts, floating buttons) are re-pinned in the clone at the exact spot\n * they occupied on screen. See `pinFixedAndSticky`.\n */\n\nexport interface CapturedScreenshot {\n canvas: HTMLCanvasElement;\n /** Viewport size in CSS pixels — the space annotations are normalized against. */\n width: number;\n height: number;\n pixelRatio: number;\n}\n\nexport interface CaptureInternalOptions {\n mode?: CaptureMode;\n maxPixelRatio?: number;\n /** Elements to leave out of the image (the widget itself). */\n exclude?: (node: Node) => boolean;\n}\n\nexport async function captureViewport(options: CaptureInternalOptions = {}): Promise<CapturedScreenshot> {\n const pixelRatio = Math.min(window.devicePixelRatio || 1, options.maxPixelRatio ?? 2);\n if (options.mode === \"display\") {\n try {\n const display = await captureDisplay(pixelRatio);\n if (display) return display;\n } catch {\n // Declined picker / unsupported → fall back to DOM rendering below.\n }\n }\n return captureDom(pixelRatio, options.exclude);\n}\n\nconst PIN_ATTR = \"data-feedbackkit-pin\";\n\ninterface PinInfo {\n kind: \"fixed\" | \"sticky\";\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\nasync function captureDom(pixelRatio: number, exclude?: (node: Node) => boolean): Promise<CapturedScreenshot> {\n const width = window.innerWidth;\n const height = window.innerHeight;\n const pins = pinFixedAndSticky(exclude);\n const root = document.documentElement;\n const bodyBackground = getComputedStyle(document.body).backgroundColor;\n const rootBackground = getComputedStyle(root).backgroundColor;\n const background = isTransparent(rootBackground)\n ? isTransparent(bodyBackground)\n ? \"#ffffff\"\n : bodyBackground\n : rootBackground;\n\n try {\n // Loaded on first capture, so pages that only ever show the trigger\n // button don't pay for the DOM renderer up front.\n const { domToCanvas } = await import(\"modern-screenshot\");\n const canvas = await domToCanvas(root, {\n width,\n height,\n scale: pixelRatio,\n backgroundColor: background,\n filter: exclude ? (node) => !exclude(node) : null,\n features: { restoreScrollPosition: true },\n timeout: 8000,\n onCloneEachNode: (cloned) => {\n if (!(cloned instanceof HTMLElement)) return;\n // Keep <body> transformed even when the page isn't scrolled, so it's\n // the containing block for pinned fixed elements either way.\n if (cloned.tagName === \"BODY\" && !cloned.style.transform) cloned.style.transform = \"translate(0px, 0px)\";\n const id = cloned.getAttribute(PIN_ATTR);\n if (id === null) return;\n cloned.removeAttribute(PIN_ATTR);\n const pin = pins.info.get(id);\n if (!pin) return;\n const s = cloned.style;\n if (pin.kind === \"sticky\") {\n s.setProperty(\"position\", \"relative\", \"important\");\n s.setProperty(\"inset\", \"auto\", \"important\");\n s.setProperty(\"top\", `${pin.top}px`, \"important\");\n s.setProperty(\"left\", `${pin.left}px`, \"important\");\n } else {\n s.setProperty(\"position\", \"fixed\", \"important\");\n s.setProperty(\"inset\", \"auto\", \"important\");\n s.setProperty(\"top\", `${pin.top}px`, \"important\");\n s.setProperty(\"left\", `${pin.left}px`, \"important\");\n s.setProperty(\"width\", `${pin.width}px`, \"important\");\n s.setProperty(\"height\", `${pin.height}px`, \"important\");\n s.setProperty(\"margin\", \"0\", \"important\");\n s.setProperty(\"box-sizing\", \"border-box\", \"important\");\n s.setProperty(\"transform\", \"none\", \"important\");\n s.setProperty(\"translate\", \"none\", \"important\");\n }\n },\n });\n return { canvas, width, height, pixelRatio };\n } finally {\n pins.cleanup();\n }\n}\n\n/**\n * Tags every fixed/sticky element with its on-screen geometry, expressed\n * relative to the containing block it will have in the shifted clone.\n * Only attributes are touched on the live page (and removed right after);\n * styles are rewritten on the clone only.\n */\nfunction pinFixedAndSticky(exclude?: (node: Node) => boolean): { info: Map<string, PinInfo>; cleanup: () => void } {\n const info = new Map<string, PinInfo>();\n const tagged: Element[] = [];\n const body = document.body;\n if (!body) return { info, cleanup: () => {} };\n\n const walker = document.createTreeWalker(body, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node) => (exclude?.(node) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT),\n });\n let counter = 0;\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n const el = node as HTMLElement;\n const style = getComputedStyle(el);\n if (style.position !== \"fixed\" && style.position !== \"sticky\") continue;\n if (style.display === \"none\") continue;\n const rect = el.getBoundingClientRect();\n const id = String(counter++);\n\n if (style.position === \"sticky\") {\n // Where it would sit if it weren't stuck: measure once with sticky off.\n // Synchronous (no frame is painted in between), so nothing flickers.\n const previous = el.style.getPropertyValue(\"position\");\n const previousPriority = el.style.getPropertyPriority(\"position\");\n el.style.setProperty(\"position\", \"static\", \"important\");\n const natural = el.getBoundingClientRect();\n el.style.setProperty(\"position\", previous, previousPriority);\n if (!previous) el.style.removeProperty(\"position\");\n const dy = rect.top - natural.top;\n const dx = rect.left - natural.left;\n if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5) continue;\n // `relative` offsets are relative to its *own* normal position, and\n // its sticky `top`/`left` are dropped, so the delta alone is enough.\n info.set(id, { kind: \"sticky\", top: dy, left: dx, width: rect.width, height: rect.height });\n } else {\n const block = containingBlockInClone(el);\n const blockRect = block.getBoundingClientRect();\n info.set(id, {\n kind: \"fixed\",\n top: rect.top - (blockRect.top + block.clientTop),\n left: rect.left - (blockRect.left + block.clientLeft),\n width: rect.width,\n height: rect.height,\n });\n }\n el.setAttribute(PIN_ATTR, id);\n tagged.push(el);\n }\n return {\n info,\n cleanup: () => {\n for (const el of tagged) el.removeAttribute(PIN_ATTR);\n },\n };\n}\n\n/**\n * The element a fixed-position node will be positioned against in the\n * clone: the nearest ancestor that already creates a containing block for\n * fixed descendants (transform/filter/etc.), or one the scroll-shift will\n * transform (a direct child of a scrolled element), falling back to <body>.\n */\nfunction containingBlockInClone(el: HTMLElement): HTMLElement {\n for (let node = el.parentElement; node && node !== document.body; node = node.parentElement) {\n const s = getComputedStyle(node);\n if (\n s.transform !== \"none\" ||\n s.filter !== \"none\" ||\n s.perspective !== \"none\" ||\n (s as CSSStyleDeclaration & { backdropFilter?: string }).backdropFilter !== undefined &&\n (s as CSSStyleDeclaration & { backdropFilter?: string }).backdropFilter !== \"none\" ||\n /paint|layout|strict|content/.test(s.contain) ||\n /transform|filter|perspective/.test(s.willChange)\n ) {\n return node;\n }\n const parent = node.parentElement;\n if (parent && (parent.scrollTop !== 0 || parent.scrollLeft !== 0)) return node;\n }\n return document.body;\n}\n\nfunction isTransparent(color: string): boolean {\n return !color || color === \"transparent\" || /rgba\\(\\s*0,\\s*0,\\s*0,\\s*0\\s*\\)/.test(color);\n}\n\ninterface DisplayMediaOptionsWithCurrentTab extends DisplayMediaStreamOptions {\n preferCurrentTab?: boolean;\n selfBrowserSurface?: \"include\" | \"exclude\";\n}\n\n/**\n * Pixel-exact capture via the Screen Capture API. Shows the browser's own\n * picker (Chromium preselects this tab with `preferCurrentTab`). Grabs a\n * single frame, then stops the stream immediately.\n */\nasync function captureDisplay(pixelRatio: number): Promise<CapturedScreenshot | null> {\n if (!navigator.mediaDevices?.getDisplayMedia) return null;\n const options: DisplayMediaOptionsWithCurrentTab = {\n video: { displaySurface: \"browser\" } as MediaTrackConstraints,\n audio: false,\n preferCurrentTab: true,\n selfBrowserSurface: \"include\",\n };\n const stream = await navigator.mediaDevices.getDisplayMedia(options);\n try {\n const video = document.createElement(\"video\");\n video.muted = true;\n video.playsInline = true;\n video.srcObject = stream;\n await video.play();\n // Give the picker's own UI a moment to disappear from the captured tab.\n await new Promise((r) => setTimeout(r, 250));\n const width = window.innerWidth;\n const height = window.innerHeight;\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.round(width * pixelRatio);\n canvas.height = Math.round(height * pixelRatio);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return null;\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n return { canvas, width, height, pixelRatio };\n } finally {\n for (const track of stream.getTracks()) track.stop();\n }\n}\n\nexport function canvasToPngBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => (blob ? resolve(blob) : reject(new Error(\"Failed to encode screenshot\"))), \"image/png\");\n });\n}\n","import type { FeedbackEnvironment } from \"./types\";\n\nexport interface ParsedUserAgent {\n osName: string;\n osVersion: string;\n browserName: string;\n browserVersion: string;\n}\n\n/**\n * Best-effort user-agent parsing. Deliberately small (a handful of ordered\n * regexes) rather than a UA-parsing dependency — the goal is a readable\n * \"macOS 15.2 / Chrome 141\" for a human or coding agent, not device\n * fingerprinting. `collectEnvironment` upgrades these with User-Agent Client\n * Hints where the browser offers them (Chromium), since UA strings freeze\n * or lie about OS versions there.\n */\nexport function parseUserAgent(ua: string): ParsedUserAgent {\n let osName = \"Unknown\";\n let osVersion = \"\";\n let m: RegExpMatchArray | null;\n\n if ((m = ua.match(/(?:iPhone|iPad|iPod).*?OS (\\d+[_.\\d]*)/))) {\n osName = /iPad/.test(ua) ? \"iPadOS\" : \"iOS\";\n osVersion = m[1].replace(/_/g, \".\");\n } else if ((m = ua.match(/Android (\\d+(?:\\.\\d+)*)/))) {\n osName = \"Android\";\n osVersion = m[1];\n } else if ((m = ua.match(/Windows NT (\\d+\\.\\d+)/))) {\n osName = \"Windows\";\n osVersion = ({ \"10.0\": \"10\", \"6.3\": \"8.1\", \"6.2\": \"8\", \"6.1\": \"7\" } as Record<string, string>)[m[1]] ?? m[1];\n } else if ((m = ua.match(/Mac OS X (\\d+[_.\\d]*)/))) {\n osName = \"macOS\";\n osVersion = m[1].replace(/_/g, \".\");\n } else if (/CrOS/.test(ua)) {\n osName = \"ChromeOS\";\n } else if (/Linux/.test(ua)) {\n osName = \"Linux\";\n }\n\n let browserName = \"Unknown\";\n let browserVersion = \"\";\n const browsers: [string, RegExp][] = [\n [\"Edge\", /Edg(?:e|A|iOS)?\\/([\\d.]+)/],\n [\"Opera\", /(?:OPR|Opera)\\/([\\d.]+)/],\n [\"Samsung Internet\", /SamsungBrowser\\/([\\d.]+)/],\n [\"Firefox\", /(?:Firefox|FxiOS)\\/([\\d.]+)/],\n [\"Chrome\", /(?:Chrome|CriOS)\\/([\\d.]+)/],\n [\"Safari\", /Version\\/([\\d.]+).*Safari/],\n ];\n for (const [name, re] of browsers) {\n const match = ua.match(re);\n if (match) {\n browserName = name;\n browserVersion = match[1];\n break;\n }\n }\n return { osName, osVersion, browserName, browserVersion };\n}\n\n/** Query parameter names whose values are replaced before a page URL leaves the browser. */\nconst SENSITIVE_PARAM = /token|secret|password|passwd|pwd|auth|session|key|code|signature|sig|jwt|otp|email/i;\n\nexport function redactUrl(href: string): string {\n try {\n const url = new URL(href);\n for (const name of [...url.searchParams.keys()]) {\n if (SENSITIVE_PARAM.test(name)) url.searchParams.set(name, \"[redacted]\");\n }\n // OAuth implicit-flow fragments (#access_token=...) are the classic leak.\n if (url.hash && SENSITIVE_PARAM.test(url.hash)) url.hash = \"#[redacted]\";\n return url.toString();\n } catch {\n return href;\n }\n}\n\ninterface UADataValues {\n platform?: string;\n platformVersion?: string;\n fullVersionList?: { brand: string; version: string }[];\n}\n\ninterface NavigatorWithUAData extends Navigator {\n userAgentData?: {\n getHighEntropyValues(hints: string[]): Promise<UADataValues>;\n };\n}\n\n/**\n * Real OS/version from User-Agent Client Hints where available — Chromium\n * freezes the UA string's OS version (e.g. macOS always reads \"10_15_7\").\n * Never throws; resolves to `null` when hints are unavailable or slow.\n */\nasync function clientHints(): Promise<UADataValues | null> {\n const uaData = (navigator as NavigatorWithUAData).userAgentData;\n if (!uaData?.getHighEntropyValues) return null;\n try {\n return await Promise.race([\n uaData.getHighEntropyValues([\"platform\", \"platformVersion\", \"fullVersionList\"]),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 300)),\n ]);\n } catch {\n return null;\n }\n}\n\nfunction osFromHints(hints: UADataValues, fallback: ParsedUserAgent): { osName: string; osVersion: string } {\n const platform = hints.platform;\n const version = hints.platformVersion ?? \"\";\n if (!platform) return fallback;\n if (platform === \"macOS\") return { osName: \"macOS\", osVersion: trimVersion(version) };\n if (platform === \"Windows\") {\n // platformVersion 13+ means Windows 11; 1–10 means Windows 10.\n const major = parseInt(version, 10);\n return { osName: \"Windows\", osVersion: major >= 13 ? \"11\" : major > 0 ? \"10\" : fallback.osVersion };\n }\n if (platform === \"Android\") return { osName: \"Android\", osVersion: trimVersion(version) || fallback.osVersion };\n if (platform === \"Chrome OS\" || platform === \"ChromeOS\") return { osName: \"ChromeOS\", osVersion: trimVersion(version) };\n return { osName: platform, osVersion: trimVersion(version) || fallback.osVersion };\n}\n\nfunction trimVersion(v: string): string {\n return v.replace(/(\\.0)+$/, \"\");\n}\n\nfunction browserFromHints(hints: UADataValues): { name: string; version: string } | null {\n const list = hints.fullVersionList ?? [];\n const known = [\"Microsoft Edge\", \"Opera\", \"Google Chrome\", \"Chromium\"];\n for (const brand of known) {\n const hit = list.find((b) => b.brand === brand);\n if (hit) {\n const name = brand === \"Microsoft Edge\" ? \"Edge\" : brand === \"Google Chrome\" ? \"Chrome\" : brand;\n return { name, version: hit.version };\n }\n }\n return null;\n}\n\nexport interface EnvironmentInputs {\n screenName?: string | null;\n appVersion?: string;\n appBuild?: string;\n}\n\nexport async function collectEnvironment(inputs: EnvironmentInputs = {}): Promise<FeedbackEnvironment> {\n const ua = navigator.userAgent;\n const parsed = parseUserAgent(ua);\n const hints = await clientHints();\n const os = hints ? osFromHints(hints, parsed) : parsed;\n const browser = (hints && browserFromHints(hints)) || { name: parsed.browserName, version: parsed.browserVersion };\n const major = browser.version.split(\".\")[0];\n\n return {\n osName: os.osName,\n osVersion: os.osVersion,\n deviceModel: major ? `${browser.name} ${major}` : browser.name,\n appVersion: inputs.appVersion ?? \"\",\n appBuild: inputs.appBuild ?? \"\",\n bundleIdentifier: location.host,\n screenName: inputs.screenName || location.pathname || null,\n locale: navigator.language || \"en\",\n screenWidthPoints: window.innerWidth,\n screenHeightPoints: window.innerHeight,\n screenScale: window.devicePixelRatio || 1,\n platform: \"web\",\n pageUrl: redactUrl(location.href),\n userAgent: ua,\n browserName: browser.name,\n browserVersion: browser.version,\n };\n}\n","import type { FeedbackLogEntry, LogLevel } from \"./types\";\nimport { redactUrl } from \"./environment\";\n\n/**\n * Keeps a small ring buffer of recent console output, uncaught errors, and\n * failed network requests, so a report can carry \"what the page was\n * complaining about\" alongside the screenshot. This is the one kind of\n * context a browser has that native reports don't, and it's exactly what a\n * coding agent needs to go from \"the button does nothing\" to a root cause.\n *\n * Privacy: messages are truncated, obvious credentials (bearer tokens, JWTs,\n * sensitive query params) are redacted, request/response *bodies* are never\n * recorded, and `console.log`/`debug` are excluded unless opted in.\n */\n\nexport interface LogCaptureOptions {\n /** Max entries kept (oldest dropped first). Default 50. */\n maxEntries?: number;\n /** Also record `console.log`/`console.info`/`console.debug`. Default false — warn/error only. */\n includeVerbose?: boolean;\n /** Record fetch/XHR requests that fail or return HTTP >= 400. Default true. */\n network?: boolean;\n}\n\nconst MAX_MESSAGE_LENGTH = 1000;\n\nexport function redactMessage(message: string): string {\n return message\n .replace(/\\b(Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]+/gi, \"$1 [redacted]\")\n .replace(/\\beyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}/g, \"[redacted-jwt]\")\n .replace(/https?:\\/\\/[^\\s\"'<>)]+/g, (url) => redactUrl(url))\n .replace(/(\"?(?:password|passwd|secret|token|api[_-]?key|access[_-]?token|refresh[_-]?token)\"?\\s*[:=]\\s*)(\"[^\"]*\"|'[^']*'|[^\\s,}&]+)/gi, \"$1[redacted]\");\n}\n\nexport function stringifyArg(arg: unknown): string {\n if (typeof arg === \"string\") return arg;\n if (arg instanceof Error) return arg.stack || `${arg.name}: ${arg.message}`;\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"function\") return `[function ${arg.name || \"anonymous\"}]`;\n if (typeof Element !== \"undefined\" && arg instanceof Element) return `<${arg.tagName.toLowerCase()}>`;\n try {\n const seen = new WeakSet<object>();\n return JSON.stringify(arg, (_k, v: unknown) => {\n if (typeof v === \"object\" && v !== null) {\n if (seen.has(v)) return \"[circular]\";\n seen.add(v);\n }\n return typeof v === \"bigint\" ? v.toString() : v;\n });\n } catch {\n return String(arg);\n }\n}\n\nexport class LogBuffer {\n private entries: FeedbackLogEntry[] = [];\n constructor(private maxEntries = 50) {}\n\n push(level: LogLevel, message: string): void {\n let text = redactMessage(message);\n if (text.length > MAX_MESSAGE_LENGTH) text = `${text.slice(0, MAX_MESSAGE_LENGTH)}… [truncated]`;\n this.entries.push({ level, message: text, timestamp: new Date().toISOString() });\n if (this.entries.length > this.maxEntries) this.entries.splice(0, this.entries.length - this.maxEntries);\n }\n\n snapshot(): FeedbackLogEntry[] {\n return this.entries.slice();\n }\n\n clear(): void {\n this.entries = [];\n }\n}\n\ntype ConsoleMethod = \"log\" | \"info\" | \"warn\" | \"error\" | \"debug\";\n\n/** Installs the hooks; returns the buffer plus an uninstall function restoring every patched global. */\nexport function installLogCapture(options: LogCaptureOptions = {}): { buffer: LogBuffer; uninstall: () => void } {\n const buffer = new LogBuffer(options.maxEntries ?? 50);\n const restores: (() => void)[] = [];\n\n const methods: ConsoleMethod[] = options.includeVerbose ? [\"log\", \"info\", \"warn\", \"error\", \"debug\"] : [\"warn\", \"error\"];\n for (const method of methods) {\n const original = console[method];\n console[method] = function (this: Console, ...args: unknown[]) {\n try {\n buffer.push(method, args.map(stringifyArg).join(\" \"));\n } catch {\n // Never let log capture break the host page's own logging.\n }\n return original.apply(this, args);\n };\n restores.push(() => {\n console[method] = original;\n });\n }\n\n const onError = (event: ErrorEvent) => {\n const where = event.filename ? ` (${event.filename}:${event.lineno}:${event.colno})` : \"\";\n buffer.push(\"error\", `Uncaught ${event.error ? stringifyArg(event.error) : event.message}${where}`);\n };\n const onRejection = (event: PromiseRejectionEvent) => {\n buffer.push(\"error\", `Unhandled promise rejection: ${stringifyArg(event.reason)}`);\n };\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n restores.push(() => {\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n });\n\n if (options.network !== false) {\n restores.push(patchFetch(buffer), patchXHR(buffer));\n }\n\n return {\n buffer,\n uninstall: () => {\n for (const restore of restores.reverse()) restore();\n },\n };\n}\n\n/** Requests to FeedbackKit's own endpoint are skipped so a failed submit doesn't log itself. */\nlet ignoredUrlPrefix: string | null = null;\nexport function setIgnoredUrlPrefix(prefix: string | null): void {\n ignoredUrlPrefix = prefix;\n}\n\nfunction isIgnored(url: string): boolean {\n return !!ignoredUrlPrefix && url.startsWith(ignoredUrlPrefix);\n}\n\nfunction patchFetch(buffer: LogBuffer): () => void {\n if (typeof window.fetch !== \"function\") return () => {};\n const original = window.fetch;\n window.fetch = async function (input: RequestInfo | URL, init?: RequestInit) {\n const method = (init?.method || (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n const url = input instanceof Request ? input.url : String(input);\n try {\n const response = await original.call(window, input, init);\n if (response.status >= 400 && !isIgnored(url)) {\n buffer.push(\"network\", `${method} ${url} → ${response.status} ${response.statusText}`.trim());\n }\n return response;\n } catch (error) {\n if (!isIgnored(url) && !(error instanceof DOMException && error.name === \"AbortError\")) {\n buffer.push(\"network\", `${method} ${url} → failed: ${stringifyArg(error)}`);\n }\n throw error;\n }\n };\n return () => {\n window.fetch = original;\n };\n}\n\nfunction patchXHR(buffer: LogBuffer): () => void {\n if (typeof XMLHttpRequest === \"undefined\") return () => {};\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n const meta = new WeakMap<XMLHttpRequest, { method: string; url: string }>();\n\n proto.open = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n meta.set(this, { method: String(method).toUpperCase(), url: String(url) });\n return (originalOpen as (...a: unknown[]) => void).call(this, method, url, ...rest);\n } as typeof proto.open;\n\n proto.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n this.addEventListener(\"loadend\", () => {\n const info = meta.get(this);\n if (!info || isIgnored(info.url)) return;\n if (this.status === 0) buffer.push(\"network\", `${info.method} ${info.url} → failed (network error)`);\n else if (this.status >= 400) buffer.push(\"network\", `${info.method} ${info.url} → ${this.status} ${this.statusText}`.trim());\n });\n return originalSend.call(this, body);\n };\n\n return () => {\n proto.open = originalOpen;\n proto.send = originalSend;\n };\n}\n","import type { FeedbackKitConfiguration, FeedbackProduct, FeedbackReport, FeedbackUser } from \"./types\";\n\n/** The hosted FeedbackKit dashboard's ingestion endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://gpucoladcyvijefdjudf.supabase.co/functions/v1/ingest-feedback\";\n\nexport class FeedbackSubmissionError extends Error {\n constructor(\n message: string,\n readonly kind: \"not_configured\" | \"network\" | \"server\",\n readonly status?: number,\n ) {\n super(message);\n this.name = \"FeedbackSubmissionError\";\n }\n}\n\n/**\n * Wire format sent to the ingestion endpoint — the exact shape the Swift\n * SDK's private `IngestPayload` produces (Sources/FeedbackKit/Networking/FeedbackSubmitter.swift)\n * and `supabase/functions/ingest-feedback` accepts. snake_case at the top\n * level; `environment`/`annotations`/`logs` pass through untouched (camelCase\n * JSONB). Optional fields are omitted rather than sent as null, matching\n * Swift's `encodeIfPresent`.\n */\nexport interface IngestPayload {\n project_key: string;\n id: string;\n created_at: string;\n text: string;\n screenshot_raw_png_base64?: string;\n screenshot_annotated_png_base64?: string;\n annotations: FeedbackReport[\"annotations\"];\n environment: FeedbackReport[\"environment\"];\n attachment_filename?: string;\n attachment_mime_type?: string;\n attachment_data_base64?: string;\n product_keys?: string[];\n products?: { key: string; name: string; description: string; is_default: boolean }[];\n logs?: FeedbackReport[\"logs\"];\n /** Anonymous per-browser id — see fixes.ts `reporterId`. */\n reporter_id?: string;\n /** `FeedbackKit.setUser(...)`, camelCase JSONB like `environment`. */\n reporter?: FeedbackUser;\n /** \"Notify me when it's fixed\"; always sent, false unless the reporter opted in. */\n notify_reporter: boolean;\n}\n\nexport async function blobToBase64(blob: Blob): Promise<string> {\n const bytes = new Uint8Array(await blob.arrayBuffer());\n let binary = \"\";\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n\nexport async function encodePayload(\n report: FeedbackReport,\n projectKey: string,\n identity: { reporterId?: string; user?: FeedbackUser | null } = {},\n): Promise<IngestPayload> {\n const payload: IngestPayload = {\n project_key: projectKey,\n id: report.id,\n created_at: report.createdAt.toISOString(),\n text: report.text,\n annotations: report.annotations,\n environment: report.environment,\n notify_reporter: report.notifyReporter ?? false,\n };\n if (report.screenshotRaw && report.screenshotAnnotated) {\n const [raw, annotated] = await Promise.all([\n blobToBase64(report.screenshotRaw),\n blobToBase64(report.screenshotAnnotated),\n ]);\n payload.screenshot_raw_png_base64 = raw;\n payload.screenshot_annotated_png_base64 = annotated;\n }\n if (report.attachment) {\n payload.attachment_filename = report.attachment.filename;\n payload.attachment_mime_type = report.attachment.mimeType;\n payload.attachment_data_base64 = await blobToBase64(report.attachment.data);\n }\n if (report.products.length > 0) {\n payload.product_keys = report.products.map((p) => p.key);\n payload.products = report.products.map((p) => ({\n key: p.key,\n name: p.name,\n description: p.description ?? \"\",\n is_default: p.isDefault ?? false,\n }));\n }\n if (report.logs.length > 0) payload.logs = report.logs;\n if (identity.reporterId) payload.reporter_id = identity.reporterId;\n if (identity.user) payload.reporter = identity.user;\n return payload;\n}\n\nexport async function submitReport(\n report: FeedbackReport,\n configuration: FeedbackKitConfiguration,\n identity: { reporterId?: string; user?: FeedbackUser | null } = {},\n): Promise<void> {\n if (!configuration.projectKey) {\n throw new FeedbackSubmissionError(\"FeedbackKit is not configured with a project key.\", \"not_configured\");\n }\n const body = JSON.stringify(await encodePayload(report, configuration.projectKey, identity));\n let response: Response;\n try {\n response = await fetch(configuration.endpoint ?? DEFAULT_ENDPOINT, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n } catch (error) {\n throw new FeedbackSubmissionError(\n `Network error: ${error instanceof Error ? error.message : String(error)}`,\n \"network\",\n );\n }\n if (!response.ok) {\n let code = \"\";\n try {\n const json = (await response.json()) as { error?: string };\n code = json.error ?? \"\";\n } catch {\n // Non-JSON error body; the status alone is enough.\n }\n const detail = code ? ` (${code})` : \"\";\n const message =\n code === \"origin_not_allowed\"\n ? `This site (${location.origin}) isn't in the project's allowed origins.`\n : response.status === 401 || response.status === 403\n ? `Server rejected the project key or origin (HTTP ${response.status})${detail}.`\n : response.status === 429\n ? \"Too many reports right now — please try again in a minute.\"\n : response.status === 402\n ? \"Feedback for this site is paused this month. Please try again later.\"\n : `Server returned HTTP ${response.status}${detail}.`;\n throw new FeedbackSubmissionError(message, \"server\", response.status);\n }\n}\n\n/** `GET <endpoint>?project_key=…` — the products configured for the project in the dashboard. */\nexport async function fetchProducts(configuration: FeedbackKitConfiguration): Promise<FeedbackProduct[]> {\n const url = new URL(configuration.endpoint ?? DEFAULT_ENDPOINT);\n url.searchParams.set(\"project_key\", configuration.projectKey);\n const response = await fetch(url.toString());\n if (!response.ok) throw new FeedbackSubmissionError(`HTTP ${response.status}`, \"server\", response.status);\n const json = (await response.json()) as {\n products?: { key: string; name: string; description?: string; is_default?: boolean }[];\n };\n return (json.products ?? []).map((p) => ({\n key: p.key,\n name: p.name,\n description: p.description ?? \"\",\n isDefault: p.is_default ?? false,\n }));\n}\n","import { blobToBase64, DEFAULT_ENDPOINT, FeedbackSubmissionError } from \"./submit\";\nimport type { FeedbackKitConfiguration, FeedbackReport, FeedbackUser, FixUpdate } from \"./types\";\n\n/**\n * The reporter's half of the closed loop — web counterpart of the Swift\n * SDK's `FixUpdatesClient` / `FeedbackReporterIdentity`. Talks to the\n * `reporter-updates` Edge Function (supabase/functions/reporter-updates);\n * keep the wire format in sync with it and with\n * Sources/FeedbackKit/Networking/FixUpdatesClient.swift.\n */\n\n// ------------------------------------------------------------ build order\n\n/**\n * Mirrors `compare_builds` (0014_closed_loop.sql) and every other copy:\n * dotted numeric builds compare numerically; anything else is only equal (0)\n * or incomparable (null).\n */\nexport function compareBuilds(a: string | null | undefined, b: string | null | undefined): -1 | 0 | 1 | null {\n if (a == null || b == null || a === \"\" || b === \"\") return null;\n if (a === b) return 0;\n const numeric = /^[0-9]+(\\.[0-9]+)*$/;\n if (!numeric.test(a) || !numeric.test(b)) return null;\n const pa = a.split(\".\");\n const pb = b.split(\".\");\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const na = BigInt(pa[i] ?? \"0\");\n const nb = BigInt(pb[i] ?? \"0\");\n if (na < nb) return -1;\n if (na > nb) return 1;\n }\n return 0;\n}\n\n// -------------------------------------------------------- reporter identity\n\nconst STORAGE_KEY = \"feedbackkit.reporterId\";\nconst VALID_ID = /^[A-Za-z0-9_-]{16,128}$/;\nlet memoryId: string | null = null;\nlet currentUser: FeedbackUser | null = null;\n\nfunction freshId(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * The anonymous, random id attached to reports from this browser — what lets\n * a fix get back to the person who reported the bug. Kept in localStorage\n * (per origin); where storage is unavailable (private mode, blocked site\n * data) it lasts for the page's lifetime instead, which just means that\n * browser won't be asked to verify fixes later.\n */\nexport function reporterId(): string {\n if (memoryId) return memoryId;\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored && VALID_ID.test(stored)) return (memoryId = stored);\n const id = freshId();\n localStorage.setItem(STORAGE_KEY, id);\n return (memoryId = id);\n } catch {\n return (memoryId = freshId());\n }\n}\n\nexport function setUser(user: FeedbackUser | null): void {\n currentUser = user && (user.id || user.email || user.name) ? { ...user } : null;\n}\n\nexport function getUser(): FeedbackUser | null {\n return currentUser;\n}\n\n// ------------------------------------------------------------- transport\n\n/** `…/functions/v1/ingest-feedback` → `…/functions/v1/reporter-updates`, unless overridden. */\nexport function reporterUpdatesEndpoint(configuration: FeedbackKitConfiguration): string {\n if (configuration.reporterUpdatesEndpoint) return configuration.reporterUpdatesEndpoint;\n const url = new URL(configuration.endpoint ?? DEFAULT_ENDPOINT);\n url.pathname = url.pathname.replace(/\\/[^/]*\\/?$/, \"/reporter-updates\");\n url.search = \"\";\n return url.toString();\n}\n\ninterface WireUpdate {\n feedback_id: string;\n text?: string;\n created_at?: string;\n screen_name?: string | null;\n fix_stage?: string | null;\n fixed_in_build?: string | null;\n fix_summary?: string | null;\n needs_verification?: boolean;\n open_question?: { id: string; body: string; created_at: string } | null;\n screenshot_url?: string | null;\n messages?: { id: string; kind: string; body: string; author: string; created_at: string }[];\n}\n\nexport function decodeUpdate(w: WireUpdate): FixUpdate {\n return {\n feedbackId: w.feedback_id,\n text: w.text ?? \"\",\n createdAt: w.created_at ?? \"\",\n screenName: w.screen_name ?? null,\n fixStage: w.fix_stage ?? null,\n fixedInBuild: w.fixed_in_build ?? null,\n fixSummary: w.fix_summary ?? null,\n needsVerification: w.needs_verification ?? false,\n openQuestion: w.open_question ? { id: w.open_question.id, body: w.open_question.body, createdAt: w.open_question.created_at } : null,\n screenshotUrl: w.screenshot_url ?? null,\n messages: (w.messages ?? []).map((m) => ({ id: m.id, kind: m.kind, body: m.body, author: m.author, createdAt: m.created_at })),\n };\n}\n\nexport async function fetchFixUpdates(configuration: FeedbackKitConfiguration): Promise<FixUpdate[]> {\n const url = new URL(reporterUpdatesEndpoint(configuration));\n url.searchParams.set(\"project_key\", configuration.projectKey);\n url.searchParams.set(\"reporter_id\", reporterId());\n if (configuration.appBuild) url.searchParams.set(\"build\", configuration.appBuild);\n let response: Response;\n try {\n response = await fetch(url.toString());\n } catch (error) {\n throw new FeedbackSubmissionError(`Network error: ${error instanceof Error ? error.message : String(error)}`, \"network\");\n }\n if (!response.ok) throw new FeedbackSubmissionError(`HTTP ${response.status}`, \"server\", response.status);\n const json = (await response.json()) as { updates?: WireUpdate[] };\n return (json.updates ?? []).map(decodeUpdate);\n}\n\nexport type FixAction =\n | { type: \"verify\" }\n /** Still broken — optionally with a fresh report (text + annotated screenshot). */\n | { type: \"reopen\"; report?: FeedbackReport | null; text?: string }\n | { type: \"reply\"; text: string };\n\nexport async function encodeFixAction(\n configuration: FeedbackKitConfiguration,\n feedbackId: string,\n action: FixAction,\n): Promise<Record<string, unknown>> {\n const body: Record<string, unknown> = {\n project_key: configuration.projectKey,\n reporter_id: reporterId(),\n feedback_id: feedbackId,\n action: action.type,\n };\n if (configuration.appBuild) body.build = configuration.appBuild;\n if (action.type === \"reply\") body.text = action.text;\n if (action.type === \"reopen\") {\n const report = action.report;\n const text = report?.text ?? action.text;\n if (text) body.text = text;\n if (report?.screenshotAnnotated) {\n body.screenshot_annotated_png_base64 = await blobToBase64(report.screenshotAnnotated);\n if (report.screenshotRaw) body.screenshot_raw_png_base64 = await blobToBase64(report.screenshotRaw);\n body.annotations = report.annotations;\n }\n }\n return body;\n}\n\nexport async function sendFixAction(configuration: FeedbackKitConfiguration, feedbackId: string, action: FixAction): Promise<void> {\n const body = JSON.stringify(await encodeFixAction(configuration, feedbackId, action));\n let response: Response;\n try {\n response = await fetch(reporterUpdatesEndpoint(configuration), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n } catch (error) {\n throw new FeedbackSubmissionError(`Network error: ${error instanceof Error ? error.message : String(error)}`, \"network\");\n }\n if (!response.ok) throw new FeedbackSubmissionError(`HTTP ${response.status}`, \"server\", response.status);\n}\n","// Inline stroke icons (24×24, currentColor) so the widget has no asset requests.\nconst svg = (body: string) =>\n `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${body}</svg>`;\n\nexport const icons = {\n feedback: svg(\n '<path d=\"M21 12a8 8 0 0 1-11.6 7.1L4 20l1-4.6A8 8 0 1 1 21 12Z\"/><path d=\"M8.5 10.5h7M8.5 14h4.5\"/>',\n ),\n pen: svg('<path d=\"M4 20l4-1L19 8a2.1 2.1 0 0 0-3-3L5 16l-1 4Z\"/><path d=\"M14.5 6.5l3 3\"/>'),\n rectangle: svg('<rect x=\"4\" y=\"6\" width=\"16\" height=\"12\" rx=\"1.5\"/>'),\n arrow: svg('<path d=\"M6 18L18 6\"/><path d=\"M9 6h9v9\"/>'),\n text: svg('<path d=\"M5 6V5h14v1\"/><path d=\"M12 5v14\"/><path d=\"M9 19h6\"/>'),\n move: svg(\n '<path d=\"M12 3v18M3 12h18\"/><path d=\"M9 6l3-3 3 3M9 18l3 3 3-3M6 9l-3 3 3 3M18 9l3 3-3 3\"/>',\n ),\n undo: svg('<path d=\"M9 14L4 9l5-5\"/><path d=\"M4 9h10.5a5.5 5.5 0 0 1 0 11H11\"/>'),\n trash: svg('<path d=\"M4 7h16\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M6 7l1 13h10l1-13\"/><path d=\"M9 7V4h6v3\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n plus: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n paperclip: svg(\n '<path d=\"M21 11.5l-8.6 8.6a5.5 5.5 0 0 1-7.8-7.8l8.6-8.6a3.7 3.7 0 0 1 5.2 5.2l-8.6 8.6a1.8 1.8 0 0 1-2.6-2.6l7.9-7.9\"/>',\n ),\n send: svg('<path d=\"M4 12l16-8-6 16-3-7-7-1Z\"/>'),\n check: svg('<path d=\"M5 12.5l4.5 4.5L19 7.5\"/>'),\n};\n","import type { FixUpdate } from \"../types\";\nimport { icons } from \"./icons\";\n\nexport type FixCardOutcome =\n | { type: \"verified\" }\n /** The widget then opens the capture flow in \"still broken\" mode. */\n | { type: \"stillBroken\" }\n | { type: \"replied\"; text: string }\n | { type: \"later\" };\n\n/**\n * \"We fixed something you reported — is it fixed?\" A small non-modal card in\n * the page's bottom corner (above the trigger), inside the widget's Shadow\n * DOM. Web counterpart of Swift's `FixVerificationView`; same copy on purpose.\n */\nexport class FixCard {\n private root: HTMLElement | null = null;\n private settled = false;\n\n constructor(\n private readonly shadow: ShadowRoot,\n private readonly update: FixUpdate,\n private readonly onOutcome: (outcome: FixCardOutcome) => void,\n ) {}\n\n show(position: \"bottom-right\" | \"bottom-left\"): void {\n const u = this.update;\n const card = el(\"section\", \"fk-fixcard\");\n card.dataset.position = position;\n card.setAttribute(\"role\", \"dialog\");\n card.setAttribute(\"aria-labelledby\", \"fk-fixcard-title\");\n\n const header = el(\"div\", \"fk-fixcard-header\");\n const title = el(\"h2\", \"fk-title\");\n title.id = \"fk-fixcard-title\";\n title.textContent = u.needsVerification ? \"We fixed something you reported\" : \"A question about your report\";\n const close = document.createElement(\"button\");\n close.type = \"button\";\n close.className = \"fk-close\";\n close.innerHTML = icons.close;\n close.setAttribute(\"aria-label\", \"Remind me later\");\n close.title = \"Remind me later\";\n close.addEventListener(\"click\", () => this.settle({ type: \"later\" }));\n header.append(title, close);\n card.append(header);\n\n if (u.needsVerification && u.fixedInBuild) {\n card.append(text(\"p\", \"fk-meta\", `Fixed in build ${u.fixedInBuild}.`));\n }\n\n if (u.screenshotUrl) {\n const img = document.createElement(\"img\");\n img.className = \"fk-fixcard-shot\";\n img.alt = \"Your screenshot from the original report\";\n img.src = u.screenshotUrl;\n img.addEventListener(\"error\", () => img.remove());\n card.append(img);\n }\n\n card.append(text(\"p\", \"fk-meta\", \"You reported\"));\n card.append(text(\"p\", \"fk-fixcard-quote\", u.text ? `“${u.text}”` : \"(no description)\"));\n if (u.needsVerification && u.fixSummary) {\n card.append(text(\"p\", \"fk-fixcard-summary\", `What changed: ${u.fixSummary}`));\n }\n for (const m of u.messages.filter((m) => m.kind === \"comment\")) {\n const msg = el(\"div\", \"fk-fixcard-message\");\n msg.append(text(\"span\", \"fk-meta\", m.author), text(\"p\", \"\", m.body));\n card.append(msg);\n }\n\n const actions = el(\"div\", \"fk-fixcard-actions\");\n if (u.needsVerification) {\n const yes = button(\"fk-btn fk-btn-primary\", \"Yes, it's fixed\");\n yes.addEventListener(\"click\", () => this.settle({ type: \"verified\" }));\n const no = button(\"fk-btn fk-btn-secondary\", \"No, still broken\");\n no.addEventListener(\"click\", () => this.settle({ type: \"stillBroken\" }));\n actions.append(yes, no);\n } else if (u.openQuestion) {\n actions.append(text(\"p\", \"fk-fixcard-question\", u.openQuestion.body));\n const input = document.createElement(\"textarea\");\n input.className = \"fk-textarea\";\n input.placeholder = \"Your answer\";\n input.setAttribute(\"aria-label\", \"Your answer\");\n const send = button(\"fk-btn fk-btn-primary\", \"Send\");\n send.disabled = true;\n input.addEventListener(\"input\", () => (send.disabled = input.value.trim() === \"\"));\n send.addEventListener(\"click\", () => this.settle({ type: \"replied\", text: input.value.trim() }));\n actions.append(input, send);\n }\n card.append(actions);\n\n this.root = card;\n this.shadow.append(card);\n }\n\n /** Close as \"later\" (e.g. `FeedbackKit.disableFixVerification()`). */\n dismiss(): void {\n this.settle({ type: \"later\" });\n }\n\n /** Remove without reporting an outcome (the widget is being destroyed). */\n remove(): void {\n this.settled = true;\n this.root?.remove();\n this.root = null;\n }\n\n private settle(outcome: FixCardOutcome): void {\n if (this.settled) return;\n this.settled = true;\n this.root?.remove();\n this.root = null;\n this.onOutcome(outcome);\n }\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(tag: K, className: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction text<K extends keyof HTMLElementTagNameMap>(tag: K, className: string, content: string): HTMLElementTagNameMap[K] {\n const node = el(tag, className);\n node.textContent = content;\n return node;\n}\n\nfunction button(className: string, label: string): HTMLButtonElement {\n const b = el(\"button\", className);\n b.type = \"button\";\n b.textContent = label;\n return b;\n}\n","import type { FeedbackAnnotation, NormalizedPoint } from \"./types\";\n\n/**\n * Canvas port of the Swift SDK's `AnnotationRenderer`\n * (Sources/FeedbackKit/Annotation/AnnotationRenderer.swift). Same stroke\n * width, arrowhead geometry, text-bubble metrics, scale/rotation math and\n * hit-testing, so a report annotated in a browser renders the same way a\n * native one does — and the dashboard can use this one file to redraw\n * annotations from any platform on top of the raw screenshot.\n *\n * All sizes are in the *target's* coordinate space (CSS pixels on the web,\n * points on iOS/macOS); callers scale the context for device pixels.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** Anything with `measureText` — lets hit-testing run without a real canvas in tests. */\nexport interface TextMeasurer {\n font: string;\n measureText(text: string): { width: number };\n}\n\nexport const STROKE_WIDTH = 4;\nexport const HIT_TEST_TOLERANCE = 16;\nconst HEAD_LENGTH = 18;\nconst HEAD_ANGLE = Math.PI / 7;\nconst BASE_FONT_SIZE = 16;\nconst TEXT_PADDING = 8;\n/** UIFont.boldSystemFont's line height is ~1.19× its point size; match it so bubbles are the same height. */\nconst LINE_HEIGHT_RATIO = 1.19;\nconst FALLBACK_COLOR = \"#FF0000\";\n\nexport function textFont(scale = 1): string {\n return `bold ${BASE_FONT_SIZE * scale}px -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif`;\n}\n\n/** Accepts both the `[x, y]` wire shape and a legacy/defensive `{x, y}` object. */\nexport function readPoint(p: NormalizedPoint | Point | unknown): Point {\n if (Array.isArray(p)) return { x: Number(p[0]) || 0, y: Number(p[1]) || 0 };\n if (p && typeof p === \"object\") {\n const o = p as Record<string, unknown>;\n return { x: Number(o.x) || 0, y: Number(o.y) || 0 };\n }\n return { x: 0, y: 0 };\n}\n\nexport function denormalize(annotation: FeedbackAnnotation, size: Size): Point[] {\n return (annotation.points ?? []).map((p) => {\n const { x, y } = readPoint(p);\n return { x: x * size.width, y: y * size.height };\n });\n}\n\nexport function normalizeColor(hex: string | undefined): string {\n if (!hex) return FALLBACK_COLOR;\n const cleaned = hex.trim().replace(/^#/, \"\");\n if (/^[0-9a-fA-F]{6}$/.test(cleaned) || /^[0-9a-fA-F]{8}$/.test(cleaned)) return `#${cleaned}`;\n return FALLBACK_COLOR;\n}\n\nexport function drawAnnotations(\n ctx: CanvasRenderingContext2D,\n annotations: readonly FeedbackAnnotation[],\n size: Size,\n): void {\n for (const annotation of annotations) drawAnnotation(ctx, annotation, size);\n}\n\nexport function drawAnnotation(ctx: CanvasRenderingContext2D, annotation: FeedbackAnnotation, size: Size): void {\n const color = normalizeColor(annotation.colorHex);\n const points = denormalize(annotation, size);\n const scale = annotation.scale ?? 1;\n const rotation = annotation.rotation ?? 0;\n\n switch (annotation.kind) {\n case \"freehand\":\n drawFreehand(ctx, points, color);\n break;\n case \"rectangle\":\n if (points.length === 2) drawRectangle(ctx, points[0], points[1], color, scale, rotation);\n break;\n case \"arrow\":\n if (points.length === 2) drawArrow(ctx, points[0], points[1], color, scale, rotation);\n break;\n case \"text\":\n if (points.length >= 1 && annotation.label) drawText(ctx, annotation.label, points[0], color, scale);\n break;\n }\n}\n\nfunction drawFreehand(ctx: CanvasRenderingContext2D, points: Point[], color: string): void {\n if (points.length === 0) return;\n ctx.save();\n ctx.lineWidth = STROKE_WIDTH;\n ctx.lineJoin = \"round\";\n ctx.lineCap = \"round\";\n ctx.strokeStyle = color;\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n // A single tap still leaves a visible dot, like a zero-length CGPath stroke with round caps.\n if (points.length === 1) ctx.lineTo(points[0].x + 0.01, points[0].y);\n for (const p of points.slice(1)) ctx.lineTo(p.x, p.y);\n ctx.stroke();\n ctx.restore();\n}\n\nfunction drawRectangle(\n ctx: CanvasRenderingContext2D,\n start: Point,\n end: Point,\n color: string,\n scale: number,\n rotation: number,\n): void {\n const center = midpoint(start, end);\n const corners = rectangleCorners(\n center,\n (Math.abs(end.x - start.x) / 2) * scale,\n (Math.abs(end.y - start.y) / 2) * scale,\n rotation,\n );\n ctx.save();\n ctx.lineWidth = STROKE_WIDTH;\n ctx.lineJoin = \"miter\";\n ctx.strokeStyle = color;\n ctx.beginPath();\n ctx.moveTo(corners[0].x, corners[0].y);\n for (const c of corners.slice(1)) ctx.lineTo(c.x, c.y);\n ctx.closePath();\n ctx.stroke();\n ctx.restore();\n}\n\nfunction drawArrow(\n ctx: CanvasRenderingContext2D,\n rawStart: Point,\n rawEnd: Point,\n color: string,\n scale: number,\n rotation: number,\n): void {\n const { start, end, left, right } = arrowGeometry(rawStart, rawEnd, scale, rotation);\n ctx.save();\n ctx.lineWidth = STROKE_WIDTH;\n ctx.lineJoin = \"round\";\n ctx.lineCap = \"round\";\n ctx.strokeStyle = color;\n ctx.beginPath();\n ctx.moveTo(start.x, start.y);\n ctx.lineTo(end.x, end.y);\n ctx.lineTo(left.x, left.y);\n ctx.moveTo(end.x, end.y);\n ctx.lineTo(right.x, right.y);\n ctx.stroke();\n ctx.restore();\n}\n\nexport function arrowGeometry(rawStart: Point, rawEnd: Point, scale = 1, rotation = 0) {\n const center = midpoint(rawStart, rawEnd);\n const start = rotate(scaled(rawStart, scale, center), rotation, center);\n const end = rotate(scaled(rawEnd, scale, center), rotation, center);\n const angle = Math.atan2(end.y - start.y, end.x - start.x);\n const left = {\n x: end.x - HEAD_LENGTH * Math.cos(angle - HEAD_ANGLE),\n y: end.y - HEAD_LENGTH * Math.sin(angle - HEAD_ANGLE),\n };\n const right = {\n x: end.x - HEAD_LENGTH * Math.cos(angle + HEAD_ANGLE),\n y: end.y - HEAD_LENGTH * Math.sin(angle + HEAD_ANGLE),\n };\n return { start, end, left, right };\n}\n\nfunction drawText(ctx: CanvasRenderingContext2D, text: string, point: Point, color: string, scale: number): void {\n const rect = textBubbleRect(ctx, text, point, scale);\n ctx.save();\n ctx.fillStyle = color;\n ctx.beginPath();\n roundedRectPath(ctx, rect.x, rect.y, rect.width, rect.height, 8);\n ctx.fill();\n ctx.font = textFont(scale);\n ctx.fillStyle = \"#FFFFFF\";\n ctx.textBaseline = \"top\";\n // Matches Swift, which insets by the *unscaled* padding when drawing but\n // sizes the bubble with the scaled one.\n ctx.fillText(text, rect.x + TEXT_PADDING, rect.y + TEXT_PADDING + (BASE_FONT_SIZE * scale * (LINE_HEIGHT_RATIO - 1)) / 2);\n ctx.restore();\n}\n\nfunction roundedRectPath(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number): void {\n const radius = Math.min(r, w / 2, h / 2);\n ctx.moveTo(x + radius, y);\n ctx.arcTo(x + w, y, x + w, y + h, radius);\n ctx.arcTo(x + w, y + h, x, y + h, radius);\n ctx.arcTo(x, y + h, x, y, radius);\n ctx.arcTo(x, y, x + w, y, radius);\n ctx.closePath();\n}\n\nexport function textBubbleRect(measurer: TextMeasurer, text: string, point: Point, scale = 1) {\n const previous = measurer.font;\n measurer.font = textFont(scale);\n const width = measurer.measureText(text).width;\n measurer.font = previous;\n const height = BASE_FONT_SIZE * scale * LINE_HEIGHT_RATIO;\n const padding = TEXT_PADDING * scale;\n return { x: point.x, y: point.y, width: width + padding * 2, height: height + padding * 2 };\n}\n\nexport function rectangleCorners(center: Point, halfWidth: number, halfHeight: number, rotation: number): Point[] {\n return [\n { x: center.x - halfWidth, y: center.y - halfHeight },\n { x: center.x + halfWidth, y: center.y - halfHeight },\n { x: center.x + halfWidth, y: center.y + halfHeight },\n { x: center.x - halfWidth, y: center.y + halfHeight },\n ].map((p) => rotate(p, rotation, center));\n}\n\n/**\n * Whether a pointer at `point` grabs `annotation` for a drag. Freehand\n * strokes are intentionally not draggable, same as native.\n */\nexport function hitTest(\n annotation: FeedbackAnnotation,\n point: Point,\n size: Size,\n measurer: TextMeasurer,\n): boolean {\n const points = denormalize(annotation, size);\n const scale = annotation.scale ?? 1;\n switch (annotation.kind) {\n case \"rectangle\": {\n if (points.length !== 2) return false;\n // Scaled-but-unrotated bounding box, same approximation as native.\n const center = midpoint(points[0], points[1]);\n const hw = (Math.abs(points[1].x - points[0].x) / 2) * scale + HIT_TEST_TOLERANCE;\n const hh = (Math.abs(points[1].y - points[0].y) / 2) * scale + HIT_TEST_TOLERANCE;\n return Math.abs(point.x - center.x) <= hw && Math.abs(point.y - center.y) <= hh;\n }\n case \"arrow\": {\n if (points.length !== 2) return false;\n const center = midpoint(points[0], points[1]);\n return (\n distanceToSegment(point, scaled(points[0], scale, center), scaled(points[1], scale, center)) <=\n HIT_TEST_TOLERANCE\n );\n }\n case \"text\": {\n if (points.length < 1 || !annotation.label) return false;\n const rect = textBubbleRect(measurer, annotation.label, points[0], scale);\n const t = HIT_TEST_TOLERANCE / 2;\n return (\n point.x >= rect.x - t &&\n point.x <= rect.x + rect.width + t &&\n point.y >= rect.y - t &&\n point.y <= rect.y + rect.height + t\n );\n }\n case \"freehand\":\n return false;\n }\n}\n\nexport function midpoint(a: Point, b: Point): Point {\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n}\n\nexport function rotate(p: Point, angle: number, center: Point): Point {\n const dx = p.x - center.x;\n const dy = p.y - center.y;\n return {\n x: center.x + dx * Math.cos(angle) - dy * Math.sin(angle),\n y: center.y + dx * Math.sin(angle) + dy * Math.cos(angle),\n };\n}\n\nexport function scaled(p: Point, scale: number, center: Point): Point {\n return { x: center.x + (p.x - center.x) * scale, y: center.y + (p.y - center.y) * scale };\n}\n\nexport function distanceToSegment(p: Point, a: Point, b: Point): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lengthSquared = dx * dx + dy * dy;\n if (lengthSquared === 0) return Math.hypot(p.x - a.x, p.y - a.y);\n const t = Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared));\n return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));\n}\n","import type { CapturedScreenshot } from \"../capture\";\nimport { drawAnnotation, drawAnnotations, hitTest, type Point } from \"../renderer\";\nimport type { FeedbackAnnotation, NormalizedPoint } from \"../types\";\n\nexport type Tool = \"pen\" | \"rectangle\" | \"arrow\" | \"text\" | \"move\";\n\n/** Same palette as the native toolbar: systemRed, systemYellow, systemGreen, systemBlue, label. */\nexport const COLORS = [\"#FF3B30\", \"#FFCC00\", \"#34C759\", \"#007AFF\", \"#000000\"] as const;\n\nconst MIN_SCALE = 0.3;\nconst MAX_SCALE = 5;\n\ninterface Gesture {\n index: number;\n startDistance: number;\n startAngle: number;\n startScale: number;\n startRotation: number;\n}\n\ninterface Drag {\n index: number;\n last: Point;\n moved: boolean;\n}\n\n/**\n * The annotation canvas: the screenshot, plus an \"ink\" canvas on top that\n * the user draws on. Everything is stored in the capture's own coordinate\n * space (viewport CSS pixels) and normalized to 0...1 on the way out, so the\n * on-screen display size never leaks into the report — same contract as\n * the native `AnnotationCanvasView`.\n */\nexport class AnnotationEditor {\n readonly element: HTMLDivElement;\n annotations: FeedbackAnnotation[] = [];\n tool: Tool = \"pen\";\n color: string = COLORS[0];\n onChange: () => void = () => {};\n\n private readonly base: HTMLCanvasElement;\n private readonly ink: HTMLCanvasElement;\n private readonly inkCtx: CanvasRenderingContext2D;\n private history: FeedbackAnnotation[][] = [];\n private draft: FeedbackAnnotation | null = null;\n private draftStart: Point | null = null;\n private pointers = new Map<number, Point>();\n private drag: Drag | null = null;\n private gesture: Gesture | null = null;\n private selected: number | null = null;\n private textInput: HTMLInputElement | null = null;\n private displayScale = 1;\n\n constructor(private readonly shot: CapturedScreenshot) {\n this.element = document.createElement(\"div\");\n this.element.className = \"fk-canvas-box\";\n this.base = document.createElement(\"canvas\");\n this.ink = document.createElement(\"canvas\");\n this.ink.className = \"fk-ink\";\n this.ink.setAttribute(\"role\", \"img\");\n this.ink.setAttribute(\"aria-label\", \"Screenshot — draw on it to highlight the problem\");\n this.element.append(this.base, this.ink);\n const ctx = this.ink.getContext(\"2d\");\n if (!ctx) throw new Error(\"Canvas 2D is unavailable\");\n this.inkCtx = ctx;\n\n this.ink.addEventListener(\"pointerdown\", (e) => this.onPointerDown(e));\n this.ink.addEventListener(\"pointermove\", (e) => this.onPointerMove(e));\n this.ink.addEventListener(\"pointerup\", (e) => this.onPointerUp(e));\n this.ink.addEventListener(\"pointercancel\", (e) => this.onPointerUp(e));\n this.ink.addEventListener(\"wheel\", (e) => this.onWheel(e), { passive: false });\n }\n\n /** Fits the screenshot inside `maxWidth × maxHeight` (CSS px) keeping its aspect ratio. */\n layout(maxWidth: number, maxHeight: number): void {\n const scale = Math.max(0.05, Math.min(maxWidth / this.shot.width, maxHeight / this.shot.height, 1));\n this.displayScale = scale;\n const w = Math.round(this.shot.width * scale);\n const h = Math.round(this.shot.height * scale);\n const dpr = window.devicePixelRatio || 1;\n for (const canvas of [this.base, this.ink]) {\n canvas.style.width = `${w}px`;\n canvas.style.height = `${h}px`;\n canvas.width = Math.round(w * dpr);\n canvas.height = Math.round(h * dpr);\n }\n const baseCtx = this.base.getContext(\"2d\");\n if (baseCtx) {\n baseCtx.imageSmoothingQuality = \"high\";\n baseCtx.drawImage(this.shot.canvas, 0, 0, this.base.width, this.base.height);\n }\n this.cancelTextInput();\n this.render();\n }\n\n setTool(tool: Tool): void {\n this.commitTextInput();\n this.tool = tool;\n this.selected = null;\n this.ink.style.cursor = tool === \"move\" ? \"grab\" : tool === \"text\" ? \"text\" : \"crosshair\";\n this.render();\n }\n\n undo(): void {\n this.commitTextInput();\n const previous = this.history.pop();\n if (!previous) return;\n this.annotations = previous;\n this.selected = null;\n this.changed();\n }\n\n clear(): void {\n if (this.annotations.length === 0) return;\n this.snapshot();\n this.annotations = [];\n this.selected = null;\n this.changed();\n }\n\n get canUndo(): boolean {\n return this.history.length > 0;\n }\n\n /** Deletes the annotation last moved/selected with the move tool. */\n deleteSelected(): boolean {\n if (this.selected === null || !this.annotations[this.selected]) return false;\n this.snapshot();\n this.annotations.splice(this.selected, 1);\n this.selected = null;\n this.changed();\n return true;\n }\n\n /** The screenshot at full capture resolution with every annotation burned in. */\n flatten(): HTMLCanvasElement {\n this.commitTextInput();\n const out = document.createElement(\"canvas\");\n out.width = this.shot.canvas.width;\n out.height = this.shot.canvas.height;\n const ctx = out.getContext(\"2d\");\n if (!ctx) throw new Error(\"Canvas 2D is unavailable\");\n ctx.drawImage(this.shot.canvas, 0, 0);\n ctx.scale(out.width / this.shot.width, out.height / this.shot.height);\n drawAnnotations(ctx, this.annotations, { width: this.shot.width, height: this.shot.height });\n return out;\n }\n\n commitTextInput(): void {\n const input = this.textInput;\n if (!input) return;\n this.textInput = null;\n const label = input.value.trim();\n const origin = JSON.parse(input.dataset.origin ?? \"[0,0]\") as NormalizedPoint;\n input.remove();\n if (!label) return;\n this.snapshot();\n this.annotations.push({ kind: \"text\", points: [origin], colorHex: this.color, label, scale: 1, rotation: 0 });\n this.changed();\n }\n\n cancelTextInput(): void {\n this.textInput?.remove();\n this.textInput = null;\n }\n\n // ---------------------------------------------------------------- drawing\n\n render(): void {\n const ctx = this.inkCtx;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, this.ink.width, this.ink.height);\n const k = this.ink.width / this.shot.width;\n ctx.setTransform(k, 0, 0, k, 0, 0);\n const size = { width: this.shot.width, height: this.shot.height };\n drawAnnotations(ctx, this.annotations, size);\n if (this.draft) drawAnnotation(ctx, this.draft, size);\n }\n\n private changed(): void {\n this.render();\n this.onChange();\n }\n\n private snapshot(): void {\n this.history.push(this.annotations.map((a) => ({ ...a, points: a.points.map((p) => [p[0], p[1]] as NormalizedPoint) })));\n if (this.history.length > 100) this.history.shift();\n }\n\n // ---------------------------------------------------------------- input\n\n /** Pointer position in capture coordinates (viewport CSS px of the original page). */\n private toCapture(e: PointerEvent | WheelEvent): Point {\n const rect = this.ink.getBoundingClientRect();\n return {\n x: Math.max(0, Math.min(this.shot.width, (e.clientX - rect.left) / this.displayScale)),\n y: Math.max(0, Math.min(this.shot.height, (e.clientY - rect.top) / this.displayScale)),\n };\n }\n\n private normalize(p: Point): NormalizedPoint {\n return [round4(p.x / this.shot.width), round4(p.y / this.shot.height)];\n }\n\n private hitIndex(p: Point): number | null {\n const size = { width: this.shot.width, height: this.shot.height };\n for (let i = this.annotations.length - 1; i >= 0; i--) {\n if (hitTest(this.annotations[i], p, size, this.inkCtx)) return i;\n }\n return null;\n }\n\n private onPointerDown(e: PointerEvent): void {\n if (e.button !== 0 && e.pointerType === \"mouse\") return;\n e.preventDefault();\n const p = this.toCapture(e);\n this.ink.setPointerCapture(e.pointerId);\n this.pointers.set(e.pointerId, p);\n\n if (this.tool === \"move\") {\n if (this.pointers.size === 2 && this.selected !== null) {\n this.drag = null;\n this.startGesture();\n return;\n }\n const index = this.hitIndex(p);\n this.selected = index;\n if (index !== null) {\n this.snapshot();\n this.drag = { index, last: p, moved: false };\n this.ink.style.cursor = \"grabbing\";\n }\n return;\n }\n\n if (this.pointers.size > 1) return;\n\n if (this.tool === \"text\") {\n this.commitTextInput();\n this.openTextInput(p);\n return;\n }\n\n this.draftStart = p;\n const n = this.normalize(p);\n this.draft = {\n kind: this.tool === \"pen\" ? \"freehand\" : this.tool,\n points: this.tool === \"pen\" ? [n] : [n, n],\n colorHex: this.color,\n scale: 1,\n rotation: 0,\n };\n this.render();\n }\n\n private onPointerMove(e: PointerEvent): void {\n if (!this.pointers.has(e.pointerId)) {\n if (this.tool === \"move\" && e.pointerType === \"mouse\") {\n this.ink.style.cursor = this.hitIndex(this.toCapture(e)) !== null ? \"grab\" : \"default\";\n }\n return;\n }\n const p = this.toCapture(e);\n this.pointers.set(e.pointerId, p);\n\n if (this.gesture) {\n this.updateGesture();\n return;\n }\n if (this.drag) {\n const dx = (p.x - this.drag.last.x) / this.shot.width;\n const dy = (p.y - this.drag.last.y) / this.shot.height;\n this.drag.last = p;\n this.drag.moved = true;\n const a = this.annotations[this.drag.index];\n a.points = a.points.map(([x, y]) => [round4(x + dx), round4(y + dy)] as NormalizedPoint);\n this.render();\n return;\n }\n if (!this.draft || !this.draftStart) return;\n const n = this.normalize(p);\n if (this.draft.kind === \"freehand\") {\n const last = this.draft.points[this.draft.points.length - 1];\n // Skip sub-pixel jitter so long strokes stay compact in the JSON.\n if (Math.hypot((n[0] - last[0]) * this.shot.width, (n[1] - last[1]) * this.shot.height) >= 1.5) {\n this.draft.points.push(n);\n }\n } else {\n this.draft.points = [this.draft.points[0], n];\n }\n this.render();\n }\n\n private onPointerUp(e: PointerEvent): void {\n if (!this.pointers.has(e.pointerId)) return;\n this.pointers.delete(e.pointerId);\n if (this.ink.hasPointerCapture(e.pointerId)) this.ink.releasePointerCapture(e.pointerId);\n\n if (this.gesture) {\n if (this.pointers.size < 2) {\n this.gesture = null;\n this.onChange();\n }\n return;\n }\n if (this.drag) {\n if (!this.drag.moved) this.history.pop(); // A click without movement isn't an edit.\n this.drag = null;\n this.ink.style.cursor = \"grab\";\n this.onChange();\n return;\n }\n const draft = this.draft;\n this.draft = null;\n const start = this.draftStart;\n this.draftStart = null;\n if (!draft || !start) return;\n if (draft.kind !== \"freehand\") {\n const [a, b] = draft.points;\n const tiny = Math.hypot((b[0] - a[0]) * this.shot.width, (b[1] - a[1]) * this.shot.height) < 6;\n if (tiny) {\n this.render();\n return;\n }\n }\n this.snapshot();\n this.annotations.push(draft);\n this.changed();\n }\n\n /** Mouse/trackpad stand-in for pinch/twist: wheel scales, Shift/Alt+wheel rotates. */\n private onWheel(e: WheelEvent): void {\n if (this.tool !== \"move\") return;\n const p = this.toCapture(e);\n const index = this.hitIndex(p) ?? this.selected;\n if (index === null || !this.annotations[index]) return;\n e.preventDefault();\n const a = this.annotations[index];\n if (a.kind === \"freehand\") return;\n this.selected = index;\n if (e.shiftKey || e.altKey) {\n if (a.kind === \"text\") return;\n const delta = e.deltaY !== 0 ? e.deltaY : e.deltaX;\n a.rotation = round4(a.rotation + delta * 0.004);\n } else {\n // ctrlKey is set for trackpad pinch gestures in Chromium/Firefox — same axis, finer steps.\n a.scale = round4(clamp(a.scale * Math.exp(-e.deltaY * (e.ctrlKey ? 0.01 : 0.0015)), MIN_SCALE, MAX_SCALE));\n }\n this.render();\n this.onChange();\n }\n\n private startGesture(): void {\n if (this.selected === null) return;\n const [a, b] = [...this.pointers.values()];\n const annotation = this.annotations[this.selected];\n this.snapshot();\n this.gesture = {\n index: this.selected,\n startDistance: Math.max(1, Math.hypot(b.x - a.x, b.y - a.y)),\n startAngle: Math.atan2(b.y - a.y, b.x - a.x),\n startScale: annotation.scale,\n startRotation: annotation.rotation,\n };\n }\n\n private updateGesture(): void {\n const g = this.gesture;\n if (!g || this.pointers.size < 2) return;\n const [a, b] = [...this.pointers.values()];\n const annotation = this.annotations[g.index];\n if (!annotation || annotation.kind === \"freehand\") return;\n const distance = Math.hypot(b.x - a.x, b.y - a.y);\n annotation.scale = round4(clamp(g.startScale * (distance / g.startDistance), MIN_SCALE, MAX_SCALE));\n if (annotation.kind !== \"text\") {\n annotation.rotation = round4(g.startRotation + (Math.atan2(b.y - a.y, b.x - a.x) - g.startAngle));\n }\n this.render();\n }\n\n private openTextInput(p: Point): void {\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.className = \"fk-text-input\";\n input.placeholder = \"Add a note…\";\n input.setAttribute(\"aria-label\", \"Annotation text\");\n input.dataset.origin = JSON.stringify(this.normalize(p));\n input.style.left = `${Math.min(p.x * this.displayScale, this.shot.width * this.displayScale - 130)}px`;\n input.style.top = `${Math.min(p.y * this.displayScale, this.shot.height * this.displayScale - 36)}px`;\n input.style.borderColor = this.color;\n input.addEventListener(\"keydown\", (e) => {\n e.stopPropagation();\n if (e.key === \"Enter\") this.commitTextInput();\n else if (e.key === \"Escape\") this.cancelTextInput();\n });\n input.addEventListener(\"blur\", () => this.commitTextInput());\n this.element.append(input);\n this.textInput = input;\n requestAnimationFrame(() => input.focus());\n }\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, v));\n}\n\nfunction round4(v: number): number {\n return Math.round(v * 10000) / 10000;\n}\n\n","/**\n * Widget CSS, scoped inside the host's Shadow DOM so neither the page's\n * styles nor ours leak across. `:host { all: initial }` also blocks inherited\n * properties (font, color, line-height) from the page.\n */\nexport const styles = /* css */ `\n:host {\n all: initial;\n --fk-primary: #007aff;\n --fk-secondary: #6b7280;\n --fk-bg: #ffffff;\n --fk-surface: #f5f5f7;\n --fk-border: rgba(0, 0, 0, 0.1);\n --fk-text: #111114;\n --fk-muted: #6b6b73;\n --fk-danger: #d92d20;\n --fk-backdrop: rgba(10, 10, 14, 0.55);\n --fk-shadow: 0 24px 64px rgba(0, 0, 0, 0.28), 0 2px 8px rgba(0, 0, 0, 0.12);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n font-size: 14px;\n line-height: 1.4;\n color: var(--fk-text);\n}\n@media (prefers-color-scheme: dark) {\n :host(:not([data-color-scheme=\"light\"])) {\n --fk-bg: #1c1c1f;\n --fk-surface: #26262a;\n --fk-border: rgba(255, 255, 255, 0.12);\n --fk-text: #f2f2f5;\n --fk-muted: #a0a0a8;\n --fk-backdrop: rgba(0, 0, 0, 0.65);\n }\n}\n:host([data-color-scheme=\"dark\"]) {\n --fk-bg: #1c1c1f;\n --fk-surface: #26262a;\n --fk-border: rgba(255, 255, 255, 0.12);\n --fk-text: #f2f2f5;\n --fk-muted: #a0a0a8;\n --fk-backdrop: rgba(0, 0, 0, 0.65);\n}\n*, *::before, *::after { box-sizing: border-box; }\nbutton { font: inherit; color: inherit; cursor: pointer; }\nbutton:disabled { cursor: not-allowed; opacity: 0.45; }\n:focus-visible { outline: 2px solid var(--fk-primary); outline-offset: 2px; }\n\n/* ---------- floating trigger ---------- */\n.fk-trigger {\n position: fixed;\n z-index: 2147483000;\n bottom: 20px;\n right: 20px;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 44px;\n padding: 0 16px 0 14px;\n border: 0;\n border-radius: 22px;\n background: var(--fk-primary);\n color: #fff;\n font-weight: 600;\n font-size: 14px;\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);\n transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;\n}\n.fk-trigger[data-position=\"bottom-left\"] { right: auto; left: 20px; }\n.fk-trigger:hover { transform: translateY(-1px); box-shadow: 0 10px 26px rgba(0, 0, 0, 0.26); }\n.fk-trigger[data-compact=\"true\"] { width: 48px; height: 48px; padding: 0; justify-content: center; border-radius: 24px; }\n.fk-trigger[data-compact=\"true\"] .fk-trigger-label { display: none; }\n.fk-trigger[aria-busy=\"true\"] { opacity: 0.6; pointer-events: none; }\n\n/* ---------- overlay ---------- */\n.fk-overlay {\n position: fixed;\n inset: 0;\n z-index: 2147483001;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: var(--fk-backdrop);\n animation: fk-fade 0.16s ease-out;\n}\n@keyframes fk-fade { from { opacity: 0; } to { opacity: 1; } }\n@keyframes fk-rise { from { opacity: 0; transform: translateY(8px) scale(0.99); } to { opacity: 1; transform: none; } }\n.fk-dialog {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 340px;\n width: min(1180px, 100%);\n height: min(780px, 100%);\n overflow: hidden;\n border-radius: 16px;\n background: var(--fk-bg);\n box-shadow: var(--fk-shadow);\n animation: fk-rise 0.2s ease-out;\n}\n.fk-stage {\n display: flex;\n flex-direction: column;\n min-width: 0;\n min-height: 0;\n background: var(--fk-surface);\n border-right: 1px solid var(--fk-border);\n}\n.fk-toolbar {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n padding: 10px 12px;\n border-bottom: 1px solid var(--fk-border);\n}\n.fk-toolbar-sep { width: 1px; height: 22px; margin: 0 6px; background: var(--fk-border); }\n.fk-tool {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n height: 34px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: var(--fk-muted);\n}\n.fk-tool:hover:not(:disabled) { background: var(--fk-border); color: var(--fk-text); }\n.fk-tool[aria-pressed=\"true\"] { background: var(--fk-primary); color: #fff; }\n.fk-swatch {\n width: 22px;\n height: 22px;\n margin: 0 2px;\n padding: 0;\n border-radius: 11px;\n border: 2px solid var(--fk-bg);\n box-shadow: 0 0 0 1px var(--fk-border);\n}\n.fk-swatch[aria-pressed=\"true\"] { box-shadow: 0 0 0 2px var(--fk-text); }\n/* Shrinks (with an ellipsis) instead of wrapping onto its own line: hints\n differ in length per tool, and a toolbar that changed height on every tool\n switch would make the screenshot below jump mid-annotation. */\n.fk-hint { flex: 1 1 0; min-width: 0; margin-left: auto; text-align: right; font-size: 12px; color: var(--fk-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.fk-canvas-wrap {\n position: relative;\n flex: 1;\n min-height: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n overflow: hidden;\n}\n.fk-canvas-box { position: relative; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18); border-radius: 6px; overflow: hidden; }\n.fk-canvas-box canvas { display: block; }\n.fk-canvas-box .fk-ink { position: absolute; inset: 0; touch-action: none; }\n.fk-stage[data-screenshot=\"off\"] .fk-canvas-box { opacity: 0.25; filter: grayscale(1); }\n.fk-stage[data-screenshot=\"off\"] .fk-toolbar button { pointer-events: none; opacity: 0.35; }\n.fk-off-note {\n position: absolute;\n inset: 0;\n display: none;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n color: var(--fk-muted);\n pointer-events: none;\n}\n.fk-stage[data-screenshot=\"off\"] .fk-off-note { display: flex; }\n.fk-text-input {\n position: absolute;\n z-index: 2;\n min-width: 120px;\n padding: 6px 8px;\n border: 2px solid var(--fk-primary);\n border-radius: 8px;\n background: var(--fk-bg);\n color: var(--fk-text);\n font: bold 14px -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n outline: none;\n}\n\n/* ---------- composer ---------- */\n.fk-composer { display: flex; flex-direction: column; min-height: 0; padding: 18px; gap: 14px; overflow-y: auto; }\n.fk-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n.fk-title { margin: 0; font-size: 17px; font-weight: 650; letter-spacing: -0.01em; }\n.fk-close { display: inline-flex; width: 30px; height: 30px; align-items: center; justify-content: center; border: 0; border-radius: 15px; background: var(--fk-surface); color: var(--fk-muted); }\n.fk-close:hover { color: var(--fk-text); }\n.fk-label { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 600; color: var(--fk-muted); text-transform: uppercase; letter-spacing: 0.04em; }\n.fk-textarea {\n width: 100%;\n min-height: 140px;\n resize: vertical;\n padding: 10px 12px;\n border: 1px solid var(--fk-border);\n border-radius: 10px;\n background: var(--fk-bg);\n color: var(--fk-text);\n font: inherit;\n line-height: 1.45;\n}\n.fk-textarea:focus { outline: none; border-color: var(--fk-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--fk-primary) 22%, transparent); }\n.fk-chips { display: flex; flex-wrap: wrap; gap: 6px; }\n.fk-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 28px;\n padding: 0 11px;\n border: 1px solid var(--fk-border);\n border-radius: 14px;\n background: var(--fk-bg);\n font-size: 13px;\n}\n.fk-chip[aria-pressed=\"true\"] { border-color: var(--fk-primary); background: color-mix(in srgb, var(--fk-primary) 12%, transparent); color: var(--fk-primary); font-weight: 600; }\n.fk-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n.fk-switch { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; user-select: none; }\n.fk-switch input { position: absolute; opacity: 0; width: 0; height: 0; }\n.fk-switch-track { position: relative; width: 36px; height: 22px; border-radius: 11px; background: var(--fk-border); transition: background 0.15s; }\n.fk-switch-track::after { content: \"\"; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 9px; background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); transition: transform 0.15s; }\n.fk-switch input:checked + .fk-switch-track { background: var(--fk-primary); }\n.fk-switch input:checked + .fk-switch-track::after { transform: translateX(14px); }\n.fk-switch input:focus-visible + .fk-switch-track { outline: 2px solid var(--fk-primary); outline-offset: 2px; }\n.fk-attach {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 32px;\n padding: 0 12px;\n border: 1px dashed var(--fk-secondary);\n border-radius: 8px;\n background: transparent;\n color: var(--fk-secondary);\n font-size: 13px;\n}\n.fk-options-left { display: flex; align-items: center; gap: 8px; min-width: 0; }\n.fk-menu-anchor { position: relative; display: inline-flex; }\n.fk-plus { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 1px dashed var(--fk-secondary); border-radius: 8px; background: transparent; color: var(--fk-secondary); cursor: pointer; }\n.fk-options-summary { font-size: 12px; color: var(--fk-muted); white-space: nowrap; }\n.fk-menu { position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 5; min-width: 230px; padding: 4px; border: 1px solid var(--fk-border); border-radius: 10px; background: var(--fk-bg); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); }\n.fk-menu-item { display: flex; align-items: center; gap: 6px; width: 100%; padding: 7px 10px 7px 6px; border: 0; border-radius: 6px; background: transparent; color: var(--fk-text); font-size: 13px; text-align: left; cursor: pointer; }\n.fk-menu-item:hover, .fk-menu-item:focus-visible { background: var(--fk-surface); outline: none; }\n.fk-menu-check { display: inline-flex; width: 16px; height: 16px; color: var(--fk-primary); }\n.fk-menu-check svg { width: 16px; height: 16px; }\n.fk-menu-sep { margin: 4px 0; border: 0; border-top: 1px solid var(--fk-border); }\n.fk-file { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 4px 6px 4px 10px; border-radius: 8px; background: var(--fk-surface); font-size: 12px; }\n.fk-file span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.fk-file button { display: inline-flex; border: 0; background: transparent; color: var(--fk-muted); padding: 2px; }\n.fk-meta { font-size: 12px; color: var(--fk-muted); }\n.fk-meta details summary { cursor: pointer; }\n.fk-meta pre { max-height: 140px; overflow: auto; margin: 6px 0 0; padding: 8px; border-radius: 8px; background: var(--fk-surface); font-size: 11px; white-space: pre-wrap; word-break: break-word; }\n.fk-spacer { flex: 1; }\n.fk-actions { display: flex; gap: 8px; }\n.fk-btn {\n display: inline-flex;\n flex: 1;\n align-items: center;\n justify-content: center;\n gap: 7px;\n height: 40px;\n border-radius: 10px;\n font-weight: 600;\n}\n.fk-btn-secondary { border: 1px solid var(--fk-border); background: transparent; color: var(--fk-secondary); }\n.fk-btn-primary { border: 0; background: var(--fk-primary); color: #fff; }\n.fk-btn-primary:hover:not(:disabled) { filter: brightness(1.06); }\n.fk-error { margin: 0; padding: 8px 10px; border-radius: 8px; background: color-mix(in srgb, var(--fk-danger) 12%, transparent); color: var(--fk-danger); font-size: 13px; }\n.fk-spinner { width: 16px; height: 16px; border: 2px solid rgba(255, 255, 255, 0.45); border-top-color: #fff; border-radius: 50%; animation: fk-spin 0.7s linear infinite; }\n@keyframes fk-spin { to { transform: rotate(360deg); } }\n.fk-done { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; flex: 1; text-align: center; }\n.fk-done-icon { display: inline-flex; width: 48px; height: 48px; align-items: center; justify-content: center; border-radius: 24px; background: var(--fk-primary); color: #fff; }\n.fk-done-icon svg { width: 26px; height: 26px; }\n.fk-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }\n\n/* ---------- \"is it fixed?\" card (fixCard.ts) ---------- */\n.fk-fixcard {\n position: fixed;\n z-index: 2147483000;\n right: 20px;\n bottom: 76px;\n width: min(360px, calc(100vw - 32px));\n max-height: min(640px, calc(100vh - 96px));\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 16px;\n border: 1px solid var(--fk-border);\n border-radius: 16px;\n background: var(--fk-bg);\n box-shadow: var(--fk-shadow);\n animation: fk-rise 0.2s ease-out;\n}\n.fk-fixcard[data-position=\"bottom-left\"] { right: auto; left: 20px; }\n.fk-fixcard > *, .fk-fixcard-actions > * { flex-shrink: 0; }\n.fk-fixcard p { margin: 0; }\n.fk-fixcard-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }\n.fk-fixcard-shot { display: block; width: 100%; max-height: 220px; object-fit: contain; border-radius: 10px; background: var(--fk-surface); }\n.fk-fixcard-quote { font-size: 14px; }\n.fk-fixcard-summary { font-size: 13px; padding: 8px 10px; border-radius: 8px; background: var(--fk-surface); }\n.fk-fixcard-message p { font-size: 13px; }\n.fk-fixcard-question { font-weight: 600; }\n.fk-fixcard-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }\n.fk-fixcard-actions .fk-btn { flex: none; width: 100%; }\n.fk-fixcard-actions .fk-textarea { min-height: 64px; }\n@keyframes fk-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }\n\n/* ---------- narrow screens: stack stage over composer ---------- */\n@media (max-width: 760px) {\n .fk-overlay { padding: 0; }\n .fk-dialog { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) auto; width: 100%; height: 100%; border-radius: 0; }\n .fk-stage { border-right: 0; border-bottom: 1px solid var(--fk-border); }\n .fk-hint { display: none; }\n .fk-canvas-wrap { padding: 10px; }\n .fk-composer { max-height: 55vh; padding: 14px; gap: 10px; }\n .fk-textarea { min-height: 84px; }\n .fk-fixcard, .fk-fixcard[data-position] { right: 16px; left: 16px; width: auto; bottom: 16px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .fk-overlay, .fk-dialog, .fk-fixcard { animation: none; }\n}\n`;\n","import { canvasToPngBlob, captureViewport, type CapturedScreenshot } from \"../capture\";\nimport { collectEnvironment } from \"../environment\";\nimport { submitReport } from \"../submit\";\nimport type {\n CaptureOptions,\n FeedbackAttachment,\n FeedbackEnvironment,\n FeedbackKitConfiguration,\n FeedbackLogEntry,\n FeedbackProduct,\n FeedbackReport,\n FeedbackTheme,\n FeedbackUser,\n FixUpdate,\n} from \"../types\";\nimport { FixCard, type FixCardOutcome } from \"./fixCard\";\nimport { AnnotationEditor, COLORS, type Tool } from \"./editor\";\nimport { icons } from \"./icons\";\nimport { styles } from \"./styles\";\n\nexport interface WidgetDeps {\n configuration(): FeedbackKitConfiguration | null;\n theme(): FeedbackTheme | null;\n products(): Promise<FeedbackProduct[]>;\n defaultProductKey(): string | undefined;\n logs(): FeedbackLogEntry[];\n captureOptions(): CaptureOptions;\n includeScreenshot?(): boolean;\n currentScreen(): string | null;\n /** Reporter identity attached to submitted reports (fixes.ts). */\n identity(): { reporterId: string; user: FeedbackUser | null };\n}\n\nexport interface OpenOptions {\n /** POST the report to the configured endpoint before resolving. */\n submit: boolean;\n /** Called with the finished report (after a successful submit, when `submit` is true). */\n onReport?: (report: FeedbackReport) => void | Promise<void>;\n /** Called if submitting fails. The dialog stays open so the user can retry. */\n onError?: (error: unknown) => void;\n /**\n * Deliver the report somewhere other than the ingestion endpoint — used by\n * \"still broken\", which sends it as a reopen of the original report.\n * Takes precedence over `submit`. Shows the thank-you state like `submit`.\n */\n deliver?: (report: FeedbackReport) => Promise<void>;\n /** Dialog wording overrides (e.g. \"What's still wrong?\" for a reopen). */\n copy?: DialogCopy;\n /** Whether to capture a screenshot for this report. Overrides global settings. */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n}\n\nexport interface DialogCopy {\n title?: string;\n label?: string;\n placeholder?: string;\n thanksTitle?: string;\n thanksBody?: string;\n}\n\nexport interface TriggerOptions {\n position?: \"bottom-right\" | \"bottom-left\";\n /** Button text. Default \"Feedback\". */\n label?: string;\n /** Icon-only round button. */\n compact?: boolean;\n /** Whether to capture a screenshot when triggered. */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n /**\n * Keyboard shortcut to trigger feedback (defaults to true: ⌘⇧F on macOS, Ctrl+Shift+F elsewhere).\n * Pass options to customize the key, or false to disable.\n */\n keyboardShortcut?: boolean | { key?: string };\n /** Alias for `keyboardShortcut`. */\n enableKeyboardShortcut?: boolean;\n}\n\n/** Max attachment size accepted by the composer (base64 in a JSON body grows it by a third). */\nconst MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;\n\nconst TOOLS: { tool: Tool; label: string; icon: string }[] = [\n { tool: \"pen\", label: \"Draw\", icon: icons.pen },\n { tool: \"rectangle\", label: \"Rectangle\", icon: icons.rectangle },\n { tool: \"arrow\", label: \"Arrow\", icon: icons.arrow },\n { tool: \"text\", label: \"Text\", icon: icons.text },\n { tool: \"move\", label: \"Move / resize\", icon: icons.move },\n];\n\nconst HINTS: Record<Tool, string> = {\n pen: \"Draw on the screenshot to highlight the problem\",\n rectangle: \"Drag to box an area\",\n arrow: \"Drag to point at something\",\n text: \"Click to add a note\",\n move: \"Drag to move · scroll to resize · Shift+scroll to rotate · Delete to remove\",\n};\n\n/**\n * Owns the widget's Shadow DOM host: the floating trigger button and the\n * capture → annotate → describe → send dialog. One per page.\n */\nexport class Widget {\n private host: HTMLElement | null = null;\n private shadow: ShadowRoot | null = null;\n private trigger: HTMLButtonElement | null = null;\n private pending: Promise<FeedbackReport | null> | null = null;\n private fixCard: FixCard | null = null;\n\n constructor(private readonly deps: WidgetDeps) {}\n\n get isShowingFixCard(): boolean {\n return this.fixCard !== null;\n }\n\n /**\n * The non-modal \"is it fixed?\" card (bottom corner). Resolves with what\n * the reporter chose; the card removes itself.\n */\n showFixCard(update: FixUpdate): Promise<FixCardOutcome> {\n this.fixCard?.remove();\n const shadow = this.mount();\n return new Promise((resolve) => {\n this.fixCard = new FixCard(shadow, update, (outcome) => {\n this.fixCard = null;\n resolve(outcome);\n });\n this.fixCard.show(this.trigger?.dataset.position === \"bottom-left\" ? \"bottom-left\" : \"bottom-right\");\n });\n }\n\n hideFixCard(): void {\n this.fixCard?.dismiss();\n }\n\n /** True for the widget's own host element — used to keep it out of screenshots. */\n isOwnNode = (node: Node): boolean => node === this.host;\n\n get isOpen(): boolean {\n return this.pending !== null;\n }\n\n showTrigger(options: TriggerOptions, onClick: () => void): void {\n const shadow = this.mount();\n this.trigger?.remove();\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"fk-trigger\";\n button.dataset.position = options.position ?? \"bottom-right\";\n button.dataset.compact = String(!!options.compact);\n const label = options.label ?? \"Feedback\";\n const isMac = typeof navigator !== \"undefined\" && /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);\n const shortcutLabel = isMac ? \"⌘⇧F\" : \"Ctrl+Shift+F\";\n button.title = `${label} (${shortcutLabel})`;\n button.setAttribute(\"aria-label\", `${label} (${shortcutLabel})`);\n button.setAttribute(\"aria-keyshortcuts\", isMac ? \"Meta+Shift+F\" : \"Control+Shift+F\");\n button.innerHTML = `${icons.feedback}<span class=\"fk-trigger-label\"></span>`;\n (button.querySelector(\".fk-trigger-label\") as HTMLElement).textContent = label;\n button.addEventListener(\"click\", onClick);\n shadow.append(button);\n this.trigger = button;\n this.applyTheme();\n }\n\n hideTrigger(): void {\n this.trigger?.remove();\n this.trigger = null;\n }\n\n destroy(): void {\n this.hideTrigger();\n this.fixCard?.remove();\n this.fixCard = null;\n this.host?.remove();\n this.host = null;\n this.shadow = null;\n }\n\n open(options: OpenOptions): Promise<FeedbackReport | null> {\n if (this.pending) return this.pending;\n this.pending = this.run(options).finally(() => {\n this.pending = null;\n });\n return this.pending;\n }\n\n private mount(): ShadowRoot {\n if (this.shadow && this.host?.isConnected) return this.shadow;\n const host = document.createElement(\"div\");\n host.setAttribute(\"data-feedbackkit-root\", \"\");\n // The host itself takes no space; everything inside is position: fixed.\n host.style.cssText = \"position:static!important;display:contents!important;\";\n const shadow = host.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = styles;\n shadow.append(style);\n document.body.append(host);\n this.host = host;\n this.shadow = shadow;\n this.applyTheme();\n return shadow;\n }\n\n private applyTheme(): void {\n const theme = this.deps.theme();\n const host = this.host;\n if (!host) return;\n const primary = validHex(theme?.primaryColorHex);\n const secondary = validHex(theme?.secondaryColorHex);\n if (primary) host.style.setProperty(\"--fk-primary\", primary);\n else host.style.removeProperty(\"--fk-primary\");\n if (secondary) host.style.setProperty(\"--fk-secondary\", secondary);\n else host.style.removeProperty(\"--fk-secondary\");\n }\n\n private shouldCaptureScreenshot(options: OpenOptions, captureOptions: CaptureOptions): boolean {\n if (options.captureScreenshot !== undefined) return options.captureScreenshot;\n if (options.includeScreenshot !== undefined) return options.includeScreenshot;\n if (captureOptions.enabled !== undefined) return captureOptions.enabled;\n if (captureOptions.includeScreenshot !== undefined) return captureOptions.includeScreenshot;\n if (captureOptions.mode === \"off\") return false;\n if (this.deps.includeScreenshot && !this.deps.includeScreenshot()) return false;\n const config = this.deps.configuration();\n if (config) {\n if (typeof config.captureScreenshot === \"boolean\") return config.captureScreenshot;\n if (typeof config.captureScreenshot === \"object\" && config.captureScreenshot !== null) {\n if (config.captureScreenshot.enabled !== undefined) return config.captureScreenshot.enabled;\n if (config.captureScreenshot.includeScreenshot !== undefined) return config.captureScreenshot.includeScreenshot;\n if (config.captureScreenshot.mode === \"off\") return false;\n }\n if (config.includeScreenshot !== undefined) return config.includeScreenshot;\n }\n return true;\n }\n\n private async run(options: OpenOptions): Promise<FeedbackReport | null> {\n const shadow = this.mount();\n this.applyTheme();\n\n const captureOptions = this.deps.captureOptions();\n const shouldCapture = this.shouldCaptureScreenshot(options, captureOptions);\n if (shouldCapture) {\n this.trigger?.setAttribute(\"aria-busy\", \"true\");\n }\n\n // Everything describing \"the moment of the problem\" is taken *before*\n // the dialog covers the page.\n const [shot, environment] = await Promise.all([\n shouldCapture\n ? captureViewport({ ...captureOptions, exclude: this.isOwnNode }).catch((error: unknown) => {\n console.warn(\"[FeedbackKit] Screenshot capture failed; continuing without one.\", error);\n return null;\n })\n : Promise.resolve(null),\n collectEnvironment({\n screenName: this.deps.currentScreen(),\n appVersion: this.deps.configuration()?.appVersion,\n appBuild: this.deps.configuration()?.appBuild,\n }),\n ]);\n const logs = this.deps.logs();\n this.trigger?.removeAttribute(\"aria-busy\");\n\n return new Promise<FeedbackReport | null>((resolve) => {\n const dialog = new Dialog(\n shadow,\n shot,\n environment,\n logs,\n this.deps,\n options,\n !shouldCapture,\n (result) => {\n resolve(result);\n },\n );\n dialog.show();\n });\n }\n}\n\n/** One open feedback dialog. Resolves exactly once via `done`. */\nclass Dialog {\n private overlay!: HTMLDivElement;\n private editor: AnnotationEditor | null = null;\n private textarea!: HTMLTextAreaElement;\n private sendButton!: HTMLButtonElement;\n private errorBox!: HTMLParagraphElement;\n private stage!: HTMLDivElement;\n private includeScreenshot: boolean;\n private includeLogs = true;\n /** \"Notify me when it's fixed\" — off by default, like the native composers. */\n private notifyReporter = false;\n private optionsMenu: HTMLDivElement | null = null;\n private readonly onPointerDownOutsideMenu = (e: PointerEvent) => {\n const anchor = this.optionsMenu?.parentElement;\n if (anchor && !e.composedPath().includes(anchor)) this.closeOptionsMenu();\n };\n private attachment: FeedbackAttachment | null = null;\n private selectedProducts = new Set<string>();\n private products: FeedbackProduct[] = [];\n private sending = false;\n private finished = false;\n private resizeObserver: ResizeObserver | null = null;\n private previousFocus: Element | null = null;\n private previousOverflow = \"\";\n private toolButtons = new Map<Tool, HTMLButtonElement>();\n private swatches: HTMLButtonElement[] = [];\n private undoButton!: HTMLButtonElement;\n private clearButton!: HTMLButtonElement;\n private hint!: HTMLSpanElement;\n private readonly onKeyDown = (e: KeyboardEvent) => this.handleKey(e);\n\n constructor(\n private readonly shadow: ShadowRoot,\n private readonly shot: CapturedScreenshot | null,\n private readonly environment: FeedbackEnvironment,\n private readonly logs: FeedbackLogEntry[],\n private readonly deps: WidgetDeps,\n private readonly options: OpenOptions,\n private readonly screenshotDisabled: boolean,\n private readonly done: (report: FeedbackReport | null) => void,\n ) {\n if (this.screenshotDisabled || !shot) {\n this.includeScreenshot = false;\n } else if (options.includeScreenshot !== undefined) {\n this.includeScreenshot = options.includeScreenshot;\n } else {\n this.includeScreenshot = true;\n }\n }\n\n show(): void {\n this.previousFocus = document.activeElement;\n this.previousOverflow = document.documentElement.style.overflow;\n document.documentElement.style.overflow = \"hidden\";\n\n const overlay = el(\"div\", \"fk-overlay\");\n const dialog = el(\"div\", \"fk-dialog\");\n dialog.setAttribute(\"role\", \"dialog\");\n dialog.setAttribute(\"aria-modal\", \"true\");\n dialog.setAttribute(\"aria-labelledby\", \"fk-title\");\n dialog.append(this.buildStage(), this.buildComposer());\n overlay.append(dialog);\n overlay.addEventListener(\"mousedown\", (e) => {\n if (e.target === overlay) this.cancel();\n });\n this.overlay = overlay;\n this.shadow.append(overlay);\n // One capture-phase listener on the document sees keys from inside the\n // shadow root too (they're retargeted, not stopped), so the dialog\n // behaves modally without double-handling.\n document.addEventListener(\"keydown\", this.onKeyDown, true);\n\n this.layoutEditor();\n requestAnimationFrame(() => this.textarea.focus());\n void this.loadProducts();\n }\n\n // ---------------------------------------------------------------- stage\n\n private buildStage(): HTMLElement {\n const stage = el(\"div\", \"fk-stage\");\n this.stage = stage;\n stage.dataset.screenshot = this.includeScreenshot ? \"on\" : \"off\";\n\n const toolbar = el(\"div\", \"fk-toolbar\");\n toolbar.setAttribute(\"role\", \"toolbar\");\n toolbar.setAttribute(\"aria-label\", \"Annotation tools\");\n for (const { tool, label, icon } of TOOLS) {\n const b = iconButton(\"fk-tool\", icon, label);\n b.setAttribute(\"aria-pressed\", String(tool === \"pen\"));\n b.addEventListener(\"click\", () => this.selectTool(tool));\n this.toolButtons.set(tool, b);\n toolbar.append(b);\n }\n toolbar.append(el(\"span\", \"fk-toolbar-sep\"));\n COLORS.forEach((color, i) => {\n const b = document.createElement(\"button\");\n b.type = \"button\";\n b.className = \"fk-swatch\";\n b.style.background = color;\n b.setAttribute(\"aria-label\", `Color ${[\"red\", \"yellow\", \"green\", \"blue\", \"black\"][i]}`);\n b.setAttribute(\"aria-pressed\", String(i === 0));\n b.addEventListener(\"click\", () => {\n if (this.editor) this.editor.color = color;\n this.swatches.forEach((s) => s.setAttribute(\"aria-pressed\", String(s === b)));\n });\n this.swatches.push(b);\n toolbar.append(b);\n });\n toolbar.append(el(\"span\", \"fk-toolbar-sep\"));\n this.undoButton = iconButton(\"fk-tool\", icons.undo, \"Undo\");\n this.undoButton.addEventListener(\"click\", () => this.editor?.undo());\n this.clearButton = iconButton(\"fk-tool\", icons.trash, \"Clear all annotations\");\n this.clearButton.addEventListener(\"click\", () => this.editor?.clear());\n toolbar.append(this.undoButton, this.clearButton);\n this.hint = el(\"span\", \"fk-hint\");\n this.hint.textContent = HINTS.pen;\n this.hint.title = HINTS.pen;\n toolbar.append(this.hint);\n\n const wrap = el(\"div\", \"fk-canvas-wrap\");\n if (this.shot) {\n const editor = new AnnotationEditor(this.shot);\n editor.onChange = () => this.refreshState();\n editor.setTool(\"pen\");\n this.editor = editor;\n wrap.append(editor.element);\n this.resizeObserver = new ResizeObserver(() => this.layoutEditor());\n this.resizeObserver.observe(wrap);\n }\n const note = el(\"div\", \"fk-off-note\");\n note.textContent = this.shot || this.screenshotDisabled\n ? \"Screenshot won't be included\"\n : \"Screenshot unavailable on this page\";\n wrap.append(note);\n stage.append(toolbar, wrap);\n return stage;\n }\n\n private layoutEditor(): void {\n if (!this.editor) return;\n const wrap = this.editor.element.parentElement;\n if (!wrap) return;\n const styles = getComputedStyle(wrap);\n const padX = parseFloat(styles.paddingLeft) + parseFloat(styles.paddingRight);\n const padY = parseFloat(styles.paddingTop) + parseFloat(styles.paddingBottom);\n this.editor.layout(Math.max(40, wrap.clientWidth - padX), Math.max(40, wrap.clientHeight - padY));\n }\n\n private selectTool(tool: Tool): void {\n this.editor?.setTool(tool);\n this.toolButtons.forEach((b, t) => b.setAttribute(\"aria-pressed\", String(t === tool)));\n this.hint.textContent = HINTS[tool];\n this.hint.title = HINTS[tool];\n }\n\n // ---------------------------------------------------------------- composer\n\n private buildComposer(): HTMLElement {\n const composer = el(\"div\", \"fk-composer\");\n\n const header = el(\"div\", \"fk-header\");\n const title = el(\"h2\", \"fk-title\");\n title.id = \"fk-title\";\n title.textContent = this.options.copy?.title ?? \"Send feedback\";\n const close = iconButton(\"fk-close\", icons.close, \"Close\");\n close.addEventListener(\"click\", () => this.cancel());\n header.append(title, close);\n\n let renderAttachment = () => {};\n const attachFile = (file: File) => {\n if (file.size > MAX_ATTACHMENT_BYTES) {\n this.showError(`\"${file.name}\" is larger than 10 MB.`);\n return;\n }\n this.attachment = { filename: file.name, mimeType: file.type || \"application/octet-stream\", data: file };\n renderAttachment();\n };\n\n const textLabel = el(\"label\", \"fk-label\");\n textLabel.textContent = this.options.copy?.label ?? \"What's the problem?\";\n textLabel.setAttribute(\"for\", \"fk-text\");\n this.textarea = document.createElement(\"textarea\");\n this.textarea.id = \"fk-text\";\n this.textarea.className = \"fk-textarea\";\n this.textarea.placeholder = this.options.copy?.placeholder ?? \"Describe what happened and what you expected instead…\";\n this.textarea.addEventListener(\"input\", () => this.refreshState());\n this.textarea.addEventListener(\"paste\", (e: ClipboardEvent) => {\n const items = e.clipboardData?.items;\n if (!items || items.length === 0) return;\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n let filename = file.name;\n if (!filename || filename === \"image.png\") {\n const ext = file.type.startsWith(\"image/\") ? file.type.split(\"/\")[1] || \"png\" : \"bin\";\n filename = `clipboard-${Date.now()}.${ext}`;\n }\n const attached = new File([file], filename, { type: file.type || \"application/octet-stream\" });\n attachFile(attached);\n e.preventDefault();\n break;\n }\n }\n }\n });\n const textGroup = el(\"div\");\n textGroup.append(textLabel, this.textarea);\n\n const productsGroup = el(\"div\");\n productsGroup.dataset.role = \"products\";\n productsGroup.hidden = true;\n\n // One \"+\" button opens a menu with the ways to attach and \"notify me\".\n // The screenshot switch sits in the composer itself rather than in that\n // menu (unlike the iOS/macOS composers): the web panel has the room, and\n // reporters didn't find it behind the \"+\".\n const optionsRow = el(\"div\", \"fk-row\");\n const fileInput = document.createElement(\"input\");\n fileInput.type = \"file\";\n fileInput.hidden = true;\n // `capture` opens the camera on phones and tablets; desktop browsers ignore it.\n const cameraInput = document.createElement(\"input\");\n cameraInput.type = \"file\";\n cameraInput.accept = \"image/*\";\n cameraInput.setAttribute(\"capture\", \"environment\");\n cameraInput.hidden = true;\n const onFile = (input: HTMLInputElement) => {\n const file = input.files?.[0];\n input.value = \"\";\n if (!file) return;\n attachFile(file);\n };\n fileInput.addEventListener(\"change\", () => onFile(fileInput));\n cameraInput.addEventListener(\"change\", () => onFile(cameraInput));\n\n const menuAnchor = el(\"div\", \"fk-menu-anchor\");\n const menuButton = iconButton(\"fk-plus\", icons.plus, \"Options and attachments\");\n menuButton.setAttribute(\"aria-haspopup\", \"menu\");\n menuButton.setAttribute(\"aria-expanded\", \"false\");\n menuButton.addEventListener(\"click\", () => (this.optionsMenu ? this.closeOptionsMenu() : openMenu()));\n const summary = el(\"span\", \"fk-options-summary\");\n const renderSummary = () => {\n const parts: string[] = [];\n if (!this.shot) parts.push(\"No screenshot\");\n if (this.notifyReporter) parts.push(\"Notify me\");\n summary.textContent = parts.join(\" · \");\n };\n\n const openMenu = () => {\n const menu = el(\"div\", \"fk-menu\");\n menu.setAttribute(\"role\", \"menu\");\n const item = (label: string, onSelect: () => void, checked?: boolean) => {\n const b = document.createElement(\"button\");\n b.type = \"button\";\n b.className = \"fk-menu-item\";\n b.setAttribute(\"role\", checked === undefined ? \"menuitem\" : \"menuitemcheckbox\");\n if (checked !== undefined) b.setAttribute(\"aria-checked\", String(checked));\n b.innerHTML = `<span class=\"fk-menu-check\">${checked ? icons.check : \"\"}</span><span></span>`;\n b.lastElementChild!.textContent = label;\n b.addEventListener(\"click\", () => {\n this.closeOptionsMenu();\n onSelect();\n });\n return b;\n };\n menu.append(item(\"Attach file…\", () => fileInput.click()));\n if (window.matchMedia?.(\"(pointer: coarse)\").matches) menu.append(item(\"Take photo\", () => cameraInput.click()));\n menu.append(el(\"hr\", \"fk-menu-sep\"));\n menu.append(\n item(\"Notify me when it's fixed\", () => {\n this.notifyReporter = !this.notifyReporter;\n renderSummary();\n }, this.notifyReporter),\n );\n menuAnchor.append(menu);\n menuButton.setAttribute(\"aria-expanded\", \"true\");\n this.optionsMenu = menu;\n this.overlay.addEventListener(\"pointerdown\", this.onPointerDownOutsideMenu, true);\n (menu.querySelector(\".fk-menu-item\") as HTMLButtonElement | null)?.focus();\n };\n\n const attachGroup = el(\"div\", \"fk-attach-group\");\n renderAttachment = () => {\n attachGroup.replaceChildren();\n if (!this.attachment) return;\n const chip = el(\"span\", \"fk-file\");\n const name = el(\"span\");\n name.textContent = this.attachment.filename;\n const remove = iconButton(\"\", icons.close, `Remove ${this.attachment.filename}`);\n remove.addEventListener(\"click\", () => {\n this.attachment = null;\n renderAttachment();\n });\n chip.append(name, remove);\n attachGroup.append(chip);\n };\n renderAttachment();\n renderSummary();\n menuAnchor.append(menuButton, fileInput, cameraInput);\n const left = el(\"div\", \"fk-options-left\");\n left.append(menuAnchor, attachGroup);\n optionsRow.append(left, summary);\n\n const meta = this.buildDiagnostics();\n\n this.errorBox = el(\"p\", \"fk-error\");\n this.errorBox.setAttribute(\"role\", \"alert\");\n this.errorBox.hidden = true;\n\n const actions = el(\"div\", \"fk-actions\");\n const cancel = document.createElement(\"button\");\n cancel.type = \"button\";\n cancel.className = \"fk-btn fk-btn-secondary\";\n cancel.textContent = \"Cancel\";\n cancel.addEventListener(\"click\", () => this.cancel());\n this.sendButton = document.createElement(\"button\");\n this.sendButton.type = \"button\";\n this.sendButton.className = \"fk-btn fk-btn-primary\";\n this.sendButton.innerHTML = `${icons.send}<span>Send</span>`;\n this.sendButton.title = \"Send (⌘/Ctrl + Enter)\";\n this.sendButton.addEventListener(\"click\", () => void this.send());\n actions.append(cancel, this.sendButton);\n\n composer.append(header, textGroup, productsGroup);\n if (this.shot) {\n composer.append(\n switchControl(\"Include screenshot\", this.includeScreenshot, (on) => {\n this.includeScreenshot = on;\n this.stage.dataset.screenshot = on ? \"on\" : \"off\";\n this.refreshState();\n }),\n );\n }\n composer.append(optionsRow);\n if (meta) composer.append(meta);\n composer.append(el(\"div\", \"fk-spacer\"), this.errorBox, actions);\n this.refreshState();\n return composer;\n }\n\n /** Shows the user exactly what page context will be sent, with an opt-out for logs. */\n private buildDiagnostics(): HTMLElement | null {\n const box = el(\"div\", \"fk-meta\");\n const env = this.environment;\n const summary = `${env.deviceModel} · ${env.osName} ${env.osVersion}`.trim();\n const details = document.createElement(\"details\");\n const s = document.createElement(\"summary\");\n s.textContent = `Included: page URL, ${summary}${this.logs.length ? `, ${this.logs.length} log entr${this.logs.length === 1 ? \"y\" : \"ies\"}` : \"\"}`;\n const pre = document.createElement(\"pre\");\n const lines = [`URL: ${env.pageUrl ?? \"\"}`, `Viewport: ${env.screenWidthPoints}×${env.screenHeightPoints} @${env.screenScale}x`];\n if (this.logs.length) {\n lines.push(\"\", ...this.logs.map((l) => `[${l.level}] ${l.message}`));\n }\n pre.textContent = lines.join(\"\\n\");\n details.append(s, pre);\n box.append(details);\n if (this.logs.length) {\n const logsToggle = switchControl(\"Include console & network logs\", true, (on) => {\n this.includeLogs = on;\n });\n logsToggle.style.marginTop = \"8px\";\n box.append(logsToggle);\n }\n return box;\n }\n\n private async loadProducts(): Promise<void> {\n let products: FeedbackProduct[] = [];\n try {\n products = await this.deps.products();\n } catch {\n return; // Products are optional; the composer works without them.\n }\n if (this.finished || products.length === 0) return;\n this.products = products;\n const preferred = this.deps.defaultProductKey();\n const initial =\n (preferred && products.find((p) => p.key === preferred)) || products.find((p) => p.isDefault) || null;\n if (initial) this.selectedProducts.add(initial.key);\n\n const group = this.overlay.querySelector('[data-role=\"products\"]') as HTMLElement | null;\n if (!group) return;\n const label = el(\"span\", \"fk-label\");\n label.textContent = \"Affected product\";\n const chips = el(\"div\", \"fk-chips\");\n chips.setAttribute(\"role\", \"group\");\n chips.setAttribute(\"aria-label\", \"Affected products\");\n for (const product of products) {\n const chip = document.createElement(\"button\");\n chip.type = \"button\";\n chip.className = \"fk-chip\";\n chip.textContent = product.name || product.key;\n if (product.description) chip.title = product.description;\n chip.setAttribute(\"aria-pressed\", String(this.selectedProducts.has(product.key)));\n chip.addEventListener(\"click\", () => {\n if (this.selectedProducts.has(product.key)) this.selectedProducts.delete(product.key);\n else this.selectedProducts.add(product.key);\n chip.setAttribute(\"aria-pressed\", String(this.selectedProducts.has(product.key)));\n });\n chips.append(chip);\n }\n group.replaceChildren(label, chips);\n group.hidden = false;\n }\n\n private refreshState(): void {\n const hasText = this.textarea?.value.trim().length > 0;\n const hasMarks = this.includeScreenshot && (this.editor?.annotations.length ?? 0) > 0;\n if (this.sendButton) this.sendButton.disabled = this.sending || (!hasText && !hasMarks);\n if (this.undoButton) this.undoButton.disabled = !this.editor?.canUndo;\n if (this.clearButton) this.clearButton.disabled = !(this.editor && this.editor.annotations.length > 0);\n }\n\n private closeOptionsMenu(): void {\n this.optionsMenu?.remove();\n this.optionsMenu = null;\n this.overlay?.removeEventListener(\"pointerdown\", this.onPointerDownOutsideMenu, true);\n this.overlay?.querySelector(\".fk-plus\")?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n // ---------------------------------------------------------------- keyboard\n\n private handleKey(e: KeyboardEvent): void {\n if (this.finished) return;\n const mod = e.metaKey || e.ctrlKey;\n const active = this.shadow.activeElement;\n const typing = active instanceof HTMLTextAreaElement || active instanceof HTMLInputElement;\n // The on-canvas note input handles its own Enter/Escape (commit/cancel the note).\n if (active instanceof HTMLInputElement && active.classList.contains(\"fk-text-input\")) return;\n\n if (e.key === \"Escape\" && this.optionsMenu) {\n e.preventDefault();\n e.stopPropagation();\n this.closeOptionsMenu();\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n this.cancel();\n } else if (mod && e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n void this.send();\n } else if (mod && !e.shiftKey && e.key.toLowerCase() === \"z\" && !typing) {\n e.preventDefault();\n e.stopPropagation();\n this.editor?.undo();\n } else if ((e.key === \"Backspace\" || e.key === \"Delete\") && !typing) {\n if (this.editor?.deleteSelected()) {\n e.preventDefault();\n e.stopPropagation();\n }\n } else if (e.key === \"Tab\") {\n this.trapFocus(e);\n }\n }\n\n private trapFocus(e: KeyboardEvent): void {\n const focusable = [\n ...this.overlay.querySelectorAll<HTMLElement>(\"button:not(:disabled), textarea, input:not([type=file]):not(:disabled), summary\"),\n ].filter((n) => n.offsetParent !== null || n.tagName === \"INPUT\");\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = this.shadow.activeElement;\n if (e.shiftKey && (active === first || !active)) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n }\n\n // ---------------------------------------------------------------- results\n\n private showError(message: string | null): void {\n this.errorBox.hidden = !message;\n this.errorBox.textContent = message ?? \"\";\n }\n\n private async buildReport(): Promise<FeedbackReport> {\n let screenshotRaw: Blob | null = null;\n let screenshotAnnotated: Blob | null = null;\n let annotations: FeedbackReport[\"annotations\"] = [];\n if (this.includeScreenshot && this.shot && this.editor) {\n const flattened = this.editor.flatten();\n [screenshotRaw, screenshotAnnotated] = await Promise.all([\n canvasToPngBlob(this.shot.canvas),\n canvasToPngBlob(flattened),\n ]);\n annotations = this.editor.annotations.map((a) => ({ ...a }));\n }\n return {\n id: uuid(),\n createdAt: new Date(),\n text: this.textarea.value.trim(),\n screenshotRaw,\n screenshotAnnotated,\n annotations,\n environment: this.environment,\n attachment: this.attachment,\n products: this.products.filter((p) => this.selectedProducts.has(p.key)),\n logs: this.includeLogs ? this.logs : [],\n notifyReporter: this.notifyReporter,\n };\n }\n\n private async send(): Promise<void> {\n if (this.sending || this.sendButton.disabled) return;\n this.sending = true;\n this.showError(null);\n this.refreshState();\n this.sendButton.innerHTML = `<span class=\"fk-spinner\" aria-hidden=\"true\"></span><span>Sending…</span>`;\n try {\n const report = await this.buildReport();\n if (this.options.deliver) {\n await this.options.deliver(report);\n } else if (this.options.submit) {\n const configuration = this.deps.configuration();\n if (!configuration) throw new Error(\"FeedbackKit.configure() hasn't been called.\");\n await submitReport(report, configuration, this.deps.identity());\n }\n await this.options.onReport?.(report);\n this.showThanks();\n setTimeout(() => this.finish(report), this.delivers ? 1300 : 0);\n } catch (error) {\n this.sending = false;\n this.sendButton.innerHTML = `${icons.send}<span>Retry</span>`;\n this.showError(error instanceof Error ? error.message : \"Something went wrong sending your feedback.\");\n this.refreshState();\n this.options.onError?.(error);\n }\n }\n\n private get delivers(): boolean {\n return this.options.submit || !!this.options.deliver;\n }\n\n private showThanks(): void {\n if (!this.delivers) return;\n const composer = this.overlay.querySelector(\".fk-composer\");\n if (!composer) return;\n const done = el(\"div\", \"fk-done\");\n done.setAttribute(\"role\", \"status\");\n const icon = el(\"span\", \"fk-done-icon\");\n icon.innerHTML = icons.check;\n const title = el(\"h2\", \"fk-title\");\n title.textContent = this.options.copy?.thanksTitle ?? \"Thanks for the feedback!\";\n const sub = el(\"p\", \"fk-meta\");\n sub.textContent = this.options.copy?.thanksBody ?? \"It's on its way to the team.\";\n done.append(icon, title, sub);\n composer.replaceChildren(done);\n }\n\n private cancel(): void {\n if (this.sending) return;\n this.finish(null);\n }\n\n private finish(result: FeedbackReport | null): void {\n if (this.finished) return;\n this.finished = true;\n this.resizeObserver?.disconnect();\n document.removeEventListener(\"keydown\", this.onKeyDown, true);\n this.overlay.remove();\n document.documentElement.style.overflow = this.previousOverflow;\n if (this.previousFocus instanceof HTMLElement) this.previousFocus.focus({ preventScroll: true });\n this.done(result);\n }\n}\n\n// ------------------------------------------------------------------ helpers\n\nfunction el<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction iconButton(className: string, icon: string, label: string): HTMLButtonElement {\n const b = document.createElement(\"button\");\n b.type = \"button\";\n if (className) b.className = className;\n b.innerHTML = icon;\n b.setAttribute(\"aria-label\", label);\n b.title = label;\n return b;\n}\n\nfunction switchControl(label: string, checked: boolean, onChange: (on: boolean) => void): HTMLLabelElement {\n const wrap = el(\"label\", \"fk-switch\");\n const input = document.createElement(\"input\");\n input.type = \"checkbox\";\n input.checked = checked;\n input.setAttribute(\"role\", \"switch\");\n input.addEventListener(\"change\", () => onChange(input.checked));\n const track = el(\"span\", \"fk-switch-track\");\n const text = el(\"span\");\n text.textContent = label;\n wrap.append(input, track, text);\n return wrap;\n}\n\nfunction validHex(hex: string | undefined): string | null {\n if (!hex) return null;\n const cleaned = hex.trim().replace(/^#/, \"\");\n return /^[0-9a-fA-F]{6}$/.test(cleaned) ? `#${cleaned}` : null;\n}\n\nexport function uuid(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","import { canvasToPngBlob, captureViewport } from \"./capture\";\nimport { installLogCapture, setIgnoredUrlPrefix, type LogBuffer, type LogCaptureOptions } from \"./logs\";\nimport { DEFAULT_ENDPOINT, fetchProducts, submitReport } from \"./submit\";\nimport { fetchFixUpdates, getUser, reporterId, sendFixAction, setUser, type FixAction } from \"./fixes\";\nimport type {\n CaptureOptions,\n FeedbackKitConfiguration,\n FeedbackProduct,\n FeedbackReport,\n FeedbackTheme,\n FeedbackUser,\n FixUpdate,\n} from \"./types\";\nimport { Widget, type TriggerOptions } from \"./ui/widget\";\n\nexport type * from \"./types\";\nexport type { TriggerOptions } from \"./ui/widget\";\nexport type { LogCaptureOptions } from \"./logs\";\nexport { FeedbackSubmissionError, DEFAULT_ENDPOINT, encodePayload, type IngestPayload } from \"./submit\";\nexport { parseUserAgent, redactUrl } from \"./environment\";\nexport { compareBuilds, reporterUpdatesEndpoint, type FixAction } from \"./fixes\";\nexport {\n drawAnnotation,\n drawAnnotations,\n hitTest,\n readPoint,\n textBubbleRect,\n STROKE_WIDTH,\n type Point,\n type Size,\n} from \"./renderer\";\n\nexport interface PresentOptions {\n /** Called with the finished report when the user taps Send. */\n onReport?: (report: FeedbackReport) => void | Promise<void>;\n /**\n * Whether to capture and include a screenshot for this report.\n * Set to `false` to open the feedback dialog without a screenshot.\n */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n}\n\nexport interface PresentAndSubmitOptions {\n /** Called after the report has been accepted by the ingestion endpoint. */\n onSubmitted?: (report: FeedbackReport) => void;\n /** Called when a submit attempt fails (the dialog stays open for a retry). */\n onError?: (error: unknown) => void;\n /**\n * Whether to capture and include a screenshot for this report.\n * Set to `false` to open the feedback dialog without a screenshot.\n */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n}\n\nexport interface ShortcutOptions {\n /** Key to combine with ⌘ (macOS) / Ctrl (elsewhere) + Shift. Default \"F\" — e.g. ⌘⇧F. */\n key?: string;\n}\n\nlet configuration: FeedbackKitConfiguration | null = null;\nlet products: FeedbackProduct[] = [];\nlet productsPromise: Promise<FeedbackProduct[]> | null = null;\nlet logCapture: { buffer: LogBuffer; uninstall: () => void } | null = null;\nlet shortcutHandler: ((e: KeyboardEvent) => void) | null = null;\n\nconst widget = new Widget({\n configuration: () => configuration,\n theme: () => FeedbackKit.theme,\n products: () => resolveProducts(),\n defaultProductKey: () => configuration?.defaultProductKey,\n logs: () => logCapture?.buffer.snapshot() ?? [],\n captureOptions: () => FeedbackKit.captureOptions,\n includeScreenshot: () => FeedbackKit.includeScreenshot,\n currentScreen: () => FeedbackKit.currentScreen,\n identity: () => ({ reporterId: reporterId(), user: getUser() }),\n});\n\n// ---- \"Is it fixed?\" loop (see fixes.ts) --------------------------------\n\n/** Don't hit the network more than this often from page-visibility checks. */\nconst FIX_CHECK_INTERVAL_MS = 60_000;\nlet fixVerificationEnabled = false;\nlet lastFixCheck = 0;\nlet fixCheckInFlight = false;\nconst handledThisPage = new Set<string>();\n\nfunction onVisibilityChange(): void {\n if (document.visibilityState === \"visible\") void checkAndShowFix(false);\n}\n\nasync function checkAndShowFix(force: boolean): Promise<void> {\n const config = configuration;\n if (!fixVerificationEnabled || !config || fixCheckInFlight || widget.isOpen || widget.isShowingFixCard) return;\n if (!force && Date.now() - lastFixCheck < FIX_CHECK_INTERVAL_MS) return;\n fixCheckInFlight = true;\n lastFixCheck = Date.now();\n let next: FixUpdate | undefined;\n try {\n next = (await fetchFixUpdates(config)).find((u) => !handledThisPage.has(u.feedbackId));\n } catch {\n return;\n } finally {\n fixCheckInFlight = false;\n }\n if (!next || !fixVerificationEnabled) return;\n // Resolve once the card is up; the reporter answers in their own time.\n void handleFixCard(config, next);\n}\n\nasync function handleFixCard(config: FeedbackKitConfiguration, update: FixUpdate): Promise<void> {\n const outcome = await widget.showFixCard(update);\n handledThisPage.add(update.feedbackId);\n const send = (action: FixAction) =>\n sendFixAction(config, update.feedbackId, action).catch((error: unknown) =>\n console.warn(\"[FeedbackKit] Couldn't send fix verification.\", error),\n );\n switch (outcome.type) {\n case \"verified\":\n await send({ type: \"verify\" });\n void checkAndShowFix(true);\n break;\n case \"replied\":\n await send({ type: \"reply\", text: outcome.text });\n void checkAndShowFix(true);\n break;\n case \"stillBroken\": {\n // Same capture → annotate flow, delivered as a reopen of the original\n // report so the fix's author sees exactly what's still wrong.\n const report = await widget.open({\n submit: false,\n deliver: (r) => sendFixAction(config, update.feedbackId, { type: \"reopen\", report: r }),\n copy: {\n title: \"Still broken\",\n label: \"What's still wrong?\",\n placeholder: \"Show us on the screenshot and describe what you still see…\",\n thanksTitle: \"Thanks — we're on it\",\n thanksBody: \"Your report was reopened and sent back to the team.\",\n },\n });\n // Closed the dialog without sending: they still said it's broken.\n if (!report) await send({ type: \"reopen\" });\n break;\n }\n case \"later\":\n break;\n }\n}\n\nfunction resolveProducts(): Promise<FeedbackProduct[]> {\n if (products.length > 0 || !configuration) return Promise.resolve(products);\n if (!productsPromise) {\n const config = configuration;\n productsPromise = fetchProducts(config)\n .then((fetched) => {\n if (configuration === config) products = fetched;\n return fetched;\n })\n .catch(() => {\n productsPromise = null; // Retry next time the dialog opens.\n return [];\n });\n }\n return productsPromise;\n}\n\nfunction whenBodyReady(fn: () => void): void {\n if (document.body) fn();\n else document.addEventListener(\"DOMContentLoaded\", fn, { once: true });\n}\n\n/**\n * FeedbackKit for the web — the browser counterpart of the Swift SDK's\n * `FeedbackKit` namespace. Same flow (capture → annotate → describe → a\n * structured `FeedbackReport`), same report shape, same optional delivery\n * to the hosted dashboard.\n */\nexport const FeedbackKit = {\n /**\n * The current screen/page name included in reports. Falls back to\n * `location.pathname` when unset. Set it from your router for nicer names.\n */\n currentScreen: null as string | null,\n\n /** Brand colors for the trigger button and dialog. */\n theme: null as FeedbackTheme | null,\n\n /** Screenshot capture settings. See `CaptureOptions`. */\n captureOptions: {} as CaptureOptions,\n\n /** Whether screenshots should be captured and included in reports by default. Default `true`. */\n includeScreenshot: true,\n\n /** The hosted dashboard's ingestion endpoint, used when `configure` gets no `endpoint`. */\n DEFAULT_ENDPOINT,\n\n /**\n * Configures delivery to the FeedbackKit dashboard (or your own deployment\n * of it). Pass `null` to go back to local-only delivery via `present`.\n * Also starts console/network log capture unless `captureLogs: false`.\n */\n configure(config: FeedbackKitConfiguration | null): void {\n configuration = config ? { ...config, endpoint: config.endpoint ?? DEFAULT_ENDPOINT } : null;\n products = config?.products ?? [];\n productsPromise = null;\n setIgnoredUrlPrefix(configuration?.endpoint ?? null);\n if (configuration && products.length === 0) void resolveProducts();\n if (config && config.captureLogs !== false && !logCapture) {\n FeedbackKit.enableLogCapture(typeof config.captureLogs === \"object\" ? config.captureLogs : {});\n }\n },\n\n get isConfigured(): boolean {\n return configuration !== null;\n },\n\n get configuration(): Readonly<FeedbackKitConfiguration> | null {\n return configuration;\n },\n\n /** Products for the composer's chips — static from `configure`, else fetched from the backend. */\n fetchProducts(): Promise<FeedbackProduct[]> {\n return resolveProducts();\n },\n\n /**\n * Opens the feedback dialog and resolves with the finished report — or\n * `null` if the user cancels. Nothing is sent anywhere; delivery is yours.\n */\n present(options: PresentOptions = {}): Promise<FeedbackReport | null> {\n return widget.open({\n submit: false,\n onReport: options.onReport,\n captureScreenshot: options.captureScreenshot,\n includeScreenshot: options.includeScreenshot,\n });\n },\n\n /**\n * Opens the dialog and, on Send, delivers the report to the configured\n * endpoint (showing progress, errors with retry, and a thank-you state).\n * Resolves with the submitted report, or `null` if cancelled.\n */\n presentAndSubmit(options: PresentAndSubmitOptions = {}): Promise<FeedbackReport | null> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before presentAndSubmit().\"));\n }\n return widget.open({\n submit: true,\n onReport: options.onSubmitted,\n onError: options.onError,\n captureScreenshot: options.captureScreenshot,\n includeScreenshot: options.includeScreenshot,\n });\n },\n\n /** Sends an already-built report (e.g. one from `present`) to the configured endpoint. */\n submit(report: FeedbackReport): Promise<void> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before submit().\"));\n }\n return submitReport(report, configuration, { reporterId: reporterId(), user: getUser() });\n },\n\n get isPresenting(): boolean {\n return widget.isOpen;\n },\n\n /**\n * A floating \"Feedback\" button. Clicking it runs `presentAndSubmit` when\n * configured, otherwise `present` and logs the report to the console.\n */\n showFloatingTriggerButton(options: TriggerOptions = {}): void {\n if (options.keyboardShortcut !== false && options.enableKeyboardShortcut !== false && !shortcutHandler) {\n FeedbackKit.enableKeyboardShortcut(typeof options.keyboardShortcut === \"object\" ? options.keyboardShortcut : {});\n }\n whenBodyReady(() =>\n widget.showTrigger(options, () => {\n const openOptions = {\n captureScreenshot: options.captureScreenshot,\n includeScreenshot: options.includeScreenshot,\n };\n if (configuration) void FeedbackKit.presentAndSubmit(openOptions);\n else void FeedbackKit.present({ ...openOptions, onReport: (r) => console.info(\"[FeedbackKit] report\", r) });\n }),\n );\n },\n\n hideFloatingTriggerButton(): void {\n widget.hideTrigger();\n },\n\n /**\n * The web's stand-in for the native SDKs' shake-to-report: a keyboard\n * shortcut, ⌘⇧F on macOS / Ctrl+Shift+F elsewhere by default.\n */\n enableKeyboardShortcut(options: ShortcutOptions = {}): void {\n FeedbackKit.disableKeyboardShortcut();\n const key = (options.key ?? \"F\").toLowerCase();\n shortcutHandler = (e: KeyboardEvent) => {\n const matchesKey = e.key.toLowerCase() === key || e.code.toLowerCase() === `key${key}`;\n if (!(e.metaKey || e.ctrlKey) || !e.shiftKey || e.altKey || !matchesKey) return;\n e.preventDefault();\n if (configuration) void FeedbackKit.presentAndSubmit();\n else void FeedbackKit.present({ onReport: (r) => console.info(\"[FeedbackKit] report\", r) });\n };\n window.addEventListener(\"keydown\", shortcutHandler);\n },\n\n disableKeyboardShortcut(): void {\n if (shortcutHandler) window.removeEventListener(\"keydown\", shortcutHandler);\n shortcutHandler = null;\n },\n\n /**\n * Starts recording recent console warnings/errors, uncaught exceptions,\n * and failed network requests, attached to each report (users can opt out\n * per report). Call as early as possible so errors before the first\n * report are caught. `false` turns it off.\n */\n enableLogCapture(options: LogCaptureOptions | false = {}): void {\n logCapture?.uninstall();\n logCapture = options === false ? null : installLogCapture(options);\n },\n\n /** Captures the current viewport as a PNG, without opening any UI. */\n async captureScreenshot(options: CaptureOptions = {}): Promise<Blob> {\n const shot = await captureViewport({ ...FeedbackKit.captureOptions, ...options, exclude: widget.isOwnNode });\n return canvasToPngBlob(shot.canvas);\n },\n\n /**\n * Optional identity of the person using your site, attached to every\n * report they submit. Not needed for fix verification (that uses an\n * anonymous per-browser id, `reporterId`). Pass `null` on sign-out.\n */\n setUser(user: FeedbackUser | null): void {\n setUser(user);\n },\n\n /** The anonymous per-browser id attached to reports — how a fix finds its way back here. */\n get reporterId(): string {\n return reporterId();\n },\n\n /**\n * This browser's reports that need the reporter's attention: shipped\n * fixes to confirm and developer/agent questions. For a custom UI — the\n * built-in one is `enableFixVerification`.\n */\n checkForFixUpdates(): Promise<FixUpdate[]> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before checkForFixUpdates().\"));\n }\n return fetchFixUpdates(configuration);\n },\n\n /** Answers one update directly (custom UIs): verify, reopen, or reply. */\n respondToFixUpdate(feedbackId: string, action: FixAction): Promise<void> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before respondToFixUpdate().\"));\n }\n return sendFixAction(configuration, feedbackId, action);\n },\n\n /**\n * Closes the loop with the person who reported a bug: once a fix for one\n * of their reports ships (announced with `feedbackkit release`), a small\n * card shows their original screenshot and asks \"is it fixed?\". \"Still\n * broken\" reopens the capture dialog so they can show what's wrong now,\n * and the report goes straight back to the developer. Also surfaces\n * questions the developer or their coding agent asked.\n *\n * Checks now and whenever the tab becomes visible (at most once a minute).\n * With `appBuild` configured, only fixes shipped in that build or earlier\n * are shown; without it, a fix counts as live as soon as it's released.\n */\n enableFixVerification(): void {\n if (fixVerificationEnabled) return;\n fixVerificationEnabled = true;\n document.addEventListener(\"visibilitychange\", onVisibilityChange);\n whenBodyReady(() => void checkAndShowFix(true));\n },\n\n disableFixVerification(): void {\n fixVerificationEnabled = false;\n document.removeEventListener(\"visibilitychange\", onVisibilityChange);\n widget.hideFixCard();\n },\n\n /**\n * Checks right now (ignoring the throttle) and shows the card if there's\n * something. Resolves once the check is done and any card is on screen.\n */\n presentFixUpdatesIfNeeded(): Promise<void> {\n return checkAndShowFix(true);\n },\n\n /** Removes every trace of the SDK from the page (trigger, dialog host, listeners, log hooks). */\n destroy(): void {\n FeedbackKit.disableFixVerification();\n FeedbackKit.disableKeyboardShortcut();\n logCapture?.uninstall();\n logCapture = null;\n widget.destroy();\n },\n};\n\nexport default FeedbackKit;\n"],"names":["el","text","configuration","m","button","styles","products"],"mappings":"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"}
1
+ {"version":3,"file":"feedbackkit.js","sources":["../src/capture.ts","../src/environment.ts","../src/logs.ts","../src/submit.ts","../src/fixes.ts","../src/ui/icons.ts","../src/ui/fixCard.ts","../src/renderer.ts","../src/ui/editor.ts","../src/ui/styles.ts","../src/ui/widget.ts","../src/index.ts"],"sourcesContent":["import type { CaptureMode } from \"./types\";\n\n/**\n * Viewport screenshot capture.\n *\n * Default (`\"dom\"`) re-renders the page's own DOM into an image with\n * `modern-screenshot` (SVG `foreignObject`, so the browser itself lays out\n * every modern CSS feature — no hand-written CSS engine like html2canvas,\n * which can't even parse Tailwind v4's `oklch()` colors). Same idea as the\n * native SDKs' window-level capture: render our own view hierarchy rather\n * than read the screen buffer, so no permission prompt is ever shown.\n *\n * What the user saw is the *viewport*, not the whole document, so the root\n * is clipped to `innerWidth × innerHeight` and shifted by the scroll offset\n * (`restoreScrollPosition`). Shifting the document puts a transform on\n * `<body>`, which silently turns it into the containing block for every\n * `position: fixed` descendant — so fixed and sticky elements (headers,\n * toasts, floating buttons) are re-pinned in the clone at the exact spot\n * they occupied on screen. See `pinFixedAndSticky`.\n */\n\nexport interface CapturedScreenshot {\n canvas: HTMLCanvasElement;\n /** Viewport size in CSS pixels — the space annotations are normalized against. */\n width: number;\n height: number;\n pixelRatio: number;\n}\n\nexport interface CaptureInternalOptions {\n mode?: CaptureMode;\n maxPixelRatio?: number;\n /** Elements to leave out of the image (the widget itself). */\n exclude?: (node: Node) => boolean;\n}\n\nexport async function captureViewport(options: CaptureInternalOptions = {}): Promise<CapturedScreenshot> {\n const pixelRatio = Math.min(window.devicePixelRatio || 1, options.maxPixelRatio ?? 2);\n if (options.mode === \"display\") {\n try {\n const display = await captureDisplay(pixelRatio);\n if (display) return display;\n } catch {\n // Declined picker / unsupported → fall back to DOM rendering below.\n }\n }\n return captureDom(pixelRatio, options.exclude);\n}\n\nconst PIN_ATTR = \"data-feedbackkit-pin\";\n\ninterface PinInfo {\n kind: \"fixed\" | \"sticky\";\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\nasync function captureDom(pixelRatio: number, exclude?: (node: Node) => boolean): Promise<CapturedScreenshot> {\n const width = window.innerWidth;\n const height = window.innerHeight;\n const pins = pinFixedAndSticky(exclude);\n const root = document.documentElement;\n const bodyBackground = getComputedStyle(document.body).backgroundColor;\n const rootBackground = getComputedStyle(root).backgroundColor;\n const background = isTransparent(rootBackground)\n ? isTransparent(bodyBackground)\n ? \"#ffffff\"\n : bodyBackground\n : rootBackground;\n\n try {\n // Loaded on first capture, so pages that only ever show the trigger\n // button don't pay for the DOM renderer up front.\n const { domToCanvas } = await import(\"modern-screenshot\");\n const canvas = await domToCanvas(root, {\n width,\n height,\n scale: pixelRatio,\n backgroundColor: background,\n filter: exclude ? (node) => !exclude(node) : null,\n features: { restoreScrollPosition: true },\n timeout: 8000,\n onCloneEachNode: (cloned) => {\n if (!(cloned instanceof HTMLElement)) return;\n // Keep <body> transformed even when the page isn't scrolled, so it's\n // the containing block for pinned fixed elements either way.\n if (cloned.tagName === \"BODY\" && !cloned.style.transform) cloned.style.transform = \"translate(0px, 0px)\";\n const id = cloned.getAttribute(PIN_ATTR);\n if (id === null) return;\n cloned.removeAttribute(PIN_ATTR);\n const pin = pins.info.get(id);\n if (!pin) return;\n const s = cloned.style;\n if (pin.kind === \"sticky\") {\n s.setProperty(\"position\", \"relative\", \"important\");\n s.setProperty(\"inset\", \"auto\", \"important\");\n s.setProperty(\"top\", `${pin.top}px`, \"important\");\n s.setProperty(\"left\", `${pin.left}px`, \"important\");\n } else {\n s.setProperty(\"position\", \"fixed\", \"important\");\n s.setProperty(\"inset\", \"auto\", \"important\");\n s.setProperty(\"top\", `${pin.top}px`, \"important\");\n s.setProperty(\"left\", `${pin.left}px`, \"important\");\n s.setProperty(\"width\", `${pin.width}px`, \"important\");\n s.setProperty(\"height\", `${pin.height}px`, \"important\");\n s.setProperty(\"margin\", \"0\", \"important\");\n s.setProperty(\"box-sizing\", \"border-box\", \"important\");\n s.setProperty(\"transform\", \"none\", \"important\");\n s.setProperty(\"translate\", \"none\", \"important\");\n }\n },\n });\n return { canvas, width, height, pixelRatio };\n } finally {\n pins.cleanup();\n }\n}\n\n/**\n * Tags every fixed/sticky element with its on-screen geometry, expressed\n * relative to the containing block it will have in the shifted clone.\n * Only attributes are touched on the live page (and removed right after);\n * styles are rewritten on the clone only.\n */\nfunction pinFixedAndSticky(exclude?: (node: Node) => boolean): { info: Map<string, PinInfo>; cleanup: () => void } {\n const info = new Map<string, PinInfo>();\n const tagged: Element[] = [];\n const body = document.body;\n if (!body) return { info, cleanup: () => {} };\n\n const walker = document.createTreeWalker(body, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node) => (exclude?.(node) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT),\n });\n let counter = 0;\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n const el = node as HTMLElement;\n const style = getComputedStyle(el);\n if (style.position !== \"fixed\" && style.position !== \"sticky\") continue;\n if (style.display === \"none\") continue;\n const rect = el.getBoundingClientRect();\n const id = String(counter++);\n\n if (style.position === \"sticky\") {\n // Where it would sit if it weren't stuck: measure once with sticky off.\n // Synchronous (no frame is painted in between), so nothing flickers.\n const previous = el.style.getPropertyValue(\"position\");\n const previousPriority = el.style.getPropertyPriority(\"position\");\n el.style.setProperty(\"position\", \"static\", \"important\");\n const natural = el.getBoundingClientRect();\n el.style.setProperty(\"position\", previous, previousPriority);\n if (!previous) el.style.removeProperty(\"position\");\n const dy = rect.top - natural.top;\n const dx = rect.left - natural.left;\n if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5) continue;\n // `relative` offsets are relative to its *own* normal position, and\n // its sticky `top`/`left` are dropped, so the delta alone is enough.\n info.set(id, { kind: \"sticky\", top: dy, left: dx, width: rect.width, height: rect.height });\n } else {\n const block = containingBlockInClone(el);\n const blockRect = block.getBoundingClientRect();\n info.set(id, {\n kind: \"fixed\",\n top: rect.top - (blockRect.top + block.clientTop),\n left: rect.left - (blockRect.left + block.clientLeft),\n width: rect.width,\n height: rect.height,\n });\n }\n el.setAttribute(PIN_ATTR, id);\n tagged.push(el);\n }\n return {\n info,\n cleanup: () => {\n for (const el of tagged) el.removeAttribute(PIN_ATTR);\n },\n };\n}\n\n/**\n * The element a fixed-position node will be positioned against in the\n * clone: the nearest ancestor that already creates a containing block for\n * fixed descendants (transform/filter/etc.), or one the scroll-shift will\n * transform (a direct child of a scrolled element), falling back to <body>.\n */\nfunction containingBlockInClone(el: HTMLElement): HTMLElement {\n for (let node = el.parentElement; node && node !== document.body; node = node.parentElement) {\n const s = getComputedStyle(node);\n if (\n s.transform !== \"none\" ||\n s.filter !== \"none\" ||\n s.perspective !== \"none\" ||\n (s as CSSStyleDeclaration & { backdropFilter?: string }).backdropFilter !== undefined &&\n (s as CSSStyleDeclaration & { backdropFilter?: string }).backdropFilter !== \"none\" ||\n /paint|layout|strict|content/.test(s.contain) ||\n /transform|filter|perspective/.test(s.willChange)\n ) {\n return node;\n }\n const parent = node.parentElement;\n if (parent && (parent.scrollTop !== 0 || parent.scrollLeft !== 0)) return node;\n }\n return document.body;\n}\n\nfunction isTransparent(color: string): boolean {\n return !color || color === \"transparent\" || /rgba\\(\\s*0,\\s*0,\\s*0,\\s*0\\s*\\)/.test(color);\n}\n\ninterface DisplayMediaOptionsWithCurrentTab extends DisplayMediaStreamOptions {\n preferCurrentTab?: boolean;\n selfBrowserSurface?: \"include\" | \"exclude\";\n}\n\n/**\n * Pixel-exact capture via the Screen Capture API. Shows the browser's own\n * picker (Chromium preselects this tab with `preferCurrentTab`). Grabs a\n * single frame, then stops the stream immediately.\n */\nasync function captureDisplay(pixelRatio: number): Promise<CapturedScreenshot | null> {\n if (!navigator.mediaDevices?.getDisplayMedia) return null;\n const options: DisplayMediaOptionsWithCurrentTab = {\n video: { displaySurface: \"browser\" } as MediaTrackConstraints,\n audio: false,\n preferCurrentTab: true,\n selfBrowserSurface: \"include\",\n };\n const stream = await navigator.mediaDevices.getDisplayMedia(options);\n try {\n const video = document.createElement(\"video\");\n video.muted = true;\n video.playsInline = true;\n video.srcObject = stream;\n await video.play();\n // Give the picker's own UI a moment to disappear from the captured tab.\n await new Promise((r) => setTimeout(r, 250));\n const width = window.innerWidth;\n const height = window.innerHeight;\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.round(width * pixelRatio);\n canvas.height = Math.round(height * pixelRatio);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return null;\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n return { canvas, width, height, pixelRatio };\n } finally {\n for (const track of stream.getTracks()) track.stop();\n }\n}\n\nexport function canvasToPngBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => (blob ? resolve(blob) : reject(new Error(\"Failed to encode screenshot\"))), \"image/png\");\n });\n}\n","import type { FeedbackEnvironment } from \"./types\";\n\nexport interface ParsedUserAgent {\n osName: string;\n osVersion: string;\n browserName: string;\n browserVersion: string;\n}\n\n/**\n * Best-effort user-agent parsing. Deliberately small (a handful of ordered\n * regexes) rather than a UA-parsing dependency — the goal is a readable\n * \"macOS 15.2 / Chrome 141\" for a human or coding agent, not device\n * fingerprinting. `collectEnvironment` upgrades these with User-Agent Client\n * Hints where the browser offers them (Chromium), since UA strings freeze\n * or lie about OS versions there.\n */\nexport function parseUserAgent(ua: string): ParsedUserAgent {\n let osName = \"Unknown\";\n let osVersion = \"\";\n let m: RegExpMatchArray | null;\n\n if ((m = ua.match(/(?:iPhone|iPad|iPod).*?OS (\\d+[_.\\d]*)/))) {\n osName = /iPad/.test(ua) ? \"iPadOS\" : \"iOS\";\n osVersion = m[1].replace(/_/g, \".\");\n } else if ((m = ua.match(/Android (\\d+(?:\\.\\d+)*)/))) {\n osName = \"Android\";\n osVersion = m[1];\n } else if ((m = ua.match(/Windows NT (\\d+\\.\\d+)/))) {\n osName = \"Windows\";\n osVersion = ({ \"10.0\": \"10\", \"6.3\": \"8.1\", \"6.2\": \"8\", \"6.1\": \"7\" } as Record<string, string>)[m[1]] ?? m[1];\n } else if ((m = ua.match(/Mac OS X (\\d+[_.\\d]*)/))) {\n osName = \"macOS\";\n osVersion = m[1].replace(/_/g, \".\");\n } else if (/CrOS/.test(ua)) {\n osName = \"ChromeOS\";\n } else if (/Linux/.test(ua)) {\n osName = \"Linux\";\n }\n\n let browserName = \"Unknown\";\n let browserVersion = \"\";\n const browsers: [string, RegExp][] = [\n [\"Edge\", /Edg(?:e|A|iOS)?\\/([\\d.]+)/],\n [\"Opera\", /(?:OPR|Opera)\\/([\\d.]+)/],\n [\"Samsung Internet\", /SamsungBrowser\\/([\\d.]+)/],\n [\"Firefox\", /(?:Firefox|FxiOS)\\/([\\d.]+)/],\n [\"Chrome\", /(?:Chrome|CriOS)\\/([\\d.]+)/],\n [\"Safari\", /Version\\/([\\d.]+).*Safari/],\n ];\n for (const [name, re] of browsers) {\n const match = ua.match(re);\n if (match) {\n browserName = name;\n browserVersion = match[1];\n break;\n }\n }\n return { osName, osVersion, browserName, browserVersion };\n}\n\n/** Query parameter names whose values are replaced before a page URL leaves the browser. */\nconst SENSITIVE_PARAM = /token|secret|password|passwd|pwd|auth|session|key|code|signature|sig|jwt|otp|email/i;\n\nexport function redactUrl(href: string): string {\n try {\n const url = new URL(href);\n for (const name of [...url.searchParams.keys()]) {\n if (SENSITIVE_PARAM.test(name)) url.searchParams.set(name, \"[redacted]\");\n }\n // OAuth implicit-flow fragments (#access_token=...) are the classic leak.\n if (url.hash && SENSITIVE_PARAM.test(url.hash)) url.hash = \"#[redacted]\";\n return url.toString();\n } catch {\n return href;\n }\n}\n\ninterface UADataValues {\n platform?: string;\n platformVersion?: string;\n fullVersionList?: { brand: string; version: string }[];\n}\n\ninterface NavigatorWithUAData extends Navigator {\n userAgentData?: {\n getHighEntropyValues(hints: string[]): Promise<UADataValues>;\n };\n}\n\n/**\n * Real OS/version from User-Agent Client Hints where available — Chromium\n * freezes the UA string's OS version (e.g. macOS always reads \"10_15_7\").\n * Never throws; resolves to `null` when hints are unavailable or slow.\n */\nasync function clientHints(): Promise<UADataValues | null> {\n const uaData = (navigator as NavigatorWithUAData).userAgentData;\n if (!uaData?.getHighEntropyValues) return null;\n try {\n return await Promise.race([\n uaData.getHighEntropyValues([\"platform\", \"platformVersion\", \"fullVersionList\"]),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 300)),\n ]);\n } catch {\n return null;\n }\n}\n\nfunction osFromHints(hints: UADataValues, fallback: ParsedUserAgent): { osName: string; osVersion: string } {\n const platform = hints.platform;\n const version = hints.platformVersion ?? \"\";\n if (!platform) return fallback;\n if (platform === \"macOS\") return { osName: \"macOS\", osVersion: trimVersion(version) };\n if (platform === \"Windows\") {\n // platformVersion 13+ means Windows 11; 1–10 means Windows 10.\n const major = parseInt(version, 10);\n return { osName: \"Windows\", osVersion: major >= 13 ? \"11\" : major > 0 ? \"10\" : fallback.osVersion };\n }\n if (platform === \"Android\") return { osName: \"Android\", osVersion: trimVersion(version) || fallback.osVersion };\n if (platform === \"Chrome OS\" || platform === \"ChromeOS\") return { osName: \"ChromeOS\", osVersion: trimVersion(version) };\n return { osName: platform, osVersion: trimVersion(version) || fallback.osVersion };\n}\n\nfunction trimVersion(v: string): string {\n return v.replace(/(\\.0)+$/, \"\");\n}\n\nfunction browserFromHints(hints: UADataValues): { name: string; version: string } | null {\n const list = hints.fullVersionList ?? [];\n const known = [\"Microsoft Edge\", \"Opera\", \"Google Chrome\", \"Chromium\"];\n for (const brand of known) {\n const hit = list.find((b) => b.brand === brand);\n if (hit) {\n const name = brand === \"Microsoft Edge\" ? \"Edge\" : brand === \"Google Chrome\" ? \"Chrome\" : brand;\n return { name, version: hit.version };\n }\n }\n return null;\n}\n\nexport interface EnvironmentInputs {\n screenName?: string | null;\n appVersion?: string;\n appBuild?: string;\n}\n\nexport async function collectEnvironment(inputs: EnvironmentInputs = {}): Promise<FeedbackEnvironment> {\n const ua = navigator.userAgent;\n const parsed = parseUserAgent(ua);\n const hints = await clientHints();\n const os = hints ? osFromHints(hints, parsed) : parsed;\n const browser = (hints && browserFromHints(hints)) || { name: parsed.browserName, version: parsed.browserVersion };\n const major = browser.version.split(\".\")[0];\n\n return {\n osName: os.osName,\n osVersion: os.osVersion,\n deviceModel: major ? `${browser.name} ${major}` : browser.name,\n appVersion: inputs.appVersion ?? \"\",\n appBuild: inputs.appBuild ?? \"\",\n bundleIdentifier: location.host,\n screenName: inputs.screenName || location.pathname || null,\n locale: navigator.language || \"en\",\n screenWidthPoints: window.innerWidth,\n screenHeightPoints: window.innerHeight,\n screenScale: window.devicePixelRatio || 1,\n platform: \"web\",\n pageUrl: redactUrl(location.href),\n userAgent: ua,\n browserName: browser.name,\n browserVersion: browser.version,\n };\n}\n","import type { FeedbackLogEntry, LogLevel } from \"./types\";\nimport { redactUrl } from \"./environment\";\n\n/**\n * Keeps a small ring buffer of recent console output, uncaught errors, and\n * failed network requests, so a report can carry \"what the page was\n * complaining about\" alongside the screenshot. This is the one kind of\n * context a browser has that native reports don't, and it's exactly what a\n * coding agent needs to go from \"the button does nothing\" to a root cause.\n *\n * Privacy: messages are truncated, obvious credentials (bearer tokens, JWTs,\n * sensitive query params) are redacted, request/response *bodies* are never\n * recorded, and `console.log`/`debug` are excluded unless opted in.\n */\n\nexport interface LogCaptureOptions {\n /** Max entries kept (oldest dropped first). Default 50. */\n maxEntries?: number;\n /** Also record `console.log`/`console.info`/`console.debug`. Default false — warn/error only. */\n includeVerbose?: boolean;\n /** Record fetch/XHR requests that fail or return HTTP >= 400. Default true. */\n network?: boolean;\n}\n\nconst MAX_MESSAGE_LENGTH = 1000;\n\nexport function redactMessage(message: string): string {\n return message\n .replace(/\\b(Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]+/gi, \"$1 [redacted]\")\n .replace(/\\beyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}/g, \"[redacted-jwt]\")\n .replace(/https?:\\/\\/[^\\s\"'<>)]+/g, (url) => redactUrl(url))\n .replace(/(\"?(?:password|passwd|secret|token|api[_-]?key|access[_-]?token|refresh[_-]?token)\"?\\s*[:=]\\s*)(\"[^\"]*\"|'[^']*'|[^\\s,}&]+)/gi, \"$1[redacted]\");\n}\n\nexport function stringifyArg(arg: unknown): string {\n if (typeof arg === \"string\") return arg;\n if (arg instanceof Error) return arg.stack || `${arg.name}: ${arg.message}`;\n if (arg === undefined) return \"undefined\";\n if (typeof arg === \"function\") return `[function ${arg.name || \"anonymous\"}]`;\n if (typeof Element !== \"undefined\" && arg instanceof Element) return `<${arg.tagName.toLowerCase()}>`;\n try {\n const seen = new WeakSet<object>();\n return JSON.stringify(arg, (_k, v: unknown) => {\n if (typeof v === \"object\" && v !== null) {\n if (seen.has(v)) return \"[circular]\";\n seen.add(v);\n }\n return typeof v === \"bigint\" ? v.toString() : v;\n });\n } catch {\n return String(arg);\n }\n}\n\nexport class LogBuffer {\n private entries: FeedbackLogEntry[] = [];\n constructor(private maxEntries = 50) {}\n\n push(level: LogLevel, message: string): void {\n let text = redactMessage(message);\n if (text.length > MAX_MESSAGE_LENGTH) text = `${text.slice(0, MAX_MESSAGE_LENGTH)}… [truncated]`;\n this.entries.push({ level, message: text, timestamp: new Date().toISOString() });\n if (this.entries.length > this.maxEntries) this.entries.splice(0, this.entries.length - this.maxEntries);\n }\n\n snapshot(): FeedbackLogEntry[] {\n return this.entries.slice();\n }\n\n clear(): void {\n this.entries = [];\n }\n}\n\ntype ConsoleMethod = \"log\" | \"info\" | \"warn\" | \"error\" | \"debug\";\n\n/** Installs the hooks; returns the buffer plus an uninstall function restoring every patched global. */\nexport function installLogCapture(options: LogCaptureOptions = {}): { buffer: LogBuffer; uninstall: () => void } {\n const buffer = new LogBuffer(options.maxEntries ?? 50);\n const restores: (() => void)[] = [];\n\n const methods: ConsoleMethod[] = options.includeVerbose ? [\"log\", \"info\", \"warn\", \"error\", \"debug\"] : [\"warn\", \"error\"];\n for (const method of methods) {\n const original = console[method];\n console[method] = function (this: Console, ...args: unknown[]) {\n try {\n buffer.push(method, args.map(stringifyArg).join(\" \"));\n } catch {\n // Never let log capture break the host page's own logging.\n }\n return original.apply(this, args);\n };\n restores.push(() => {\n console[method] = original;\n });\n }\n\n const onError = (event: ErrorEvent) => {\n const where = event.filename ? ` (${event.filename}:${event.lineno}:${event.colno})` : \"\";\n buffer.push(\"error\", `Uncaught ${event.error ? stringifyArg(event.error) : event.message}${where}`);\n };\n const onRejection = (event: PromiseRejectionEvent) => {\n buffer.push(\"error\", `Unhandled promise rejection: ${stringifyArg(event.reason)}`);\n };\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n restores.push(() => {\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n });\n\n if (options.network !== false) {\n restores.push(patchFetch(buffer), patchXHR(buffer));\n }\n\n return {\n buffer,\n uninstall: () => {\n for (const restore of restores.reverse()) restore();\n },\n };\n}\n\n/** Requests to FeedbackKit's own endpoint are skipped so a failed submit doesn't log itself. */\nlet ignoredUrlPrefix: string | null = null;\nexport function setIgnoredUrlPrefix(prefix: string | null): void {\n ignoredUrlPrefix = prefix;\n}\n\nfunction isIgnored(url: string): boolean {\n return !!ignoredUrlPrefix && url.startsWith(ignoredUrlPrefix);\n}\n\nfunction patchFetch(buffer: LogBuffer): () => void {\n if (typeof window.fetch !== \"function\") return () => {};\n const original = window.fetch;\n window.fetch = async function (input: RequestInfo | URL, init?: RequestInit) {\n const method = (init?.method || (input instanceof Request ? input.method : \"GET\")).toUpperCase();\n const url = input instanceof Request ? input.url : String(input);\n try {\n const response = await original.call(window, input, init);\n if (response.status >= 400 && !isIgnored(url)) {\n buffer.push(\"network\", `${method} ${url} → ${response.status} ${response.statusText}`.trim());\n }\n return response;\n } catch (error) {\n if (!isIgnored(url) && !(error instanceof DOMException && error.name === \"AbortError\")) {\n buffer.push(\"network\", `${method} ${url} → failed: ${stringifyArg(error)}`);\n }\n throw error;\n }\n };\n return () => {\n window.fetch = original;\n };\n}\n\nfunction patchXHR(buffer: LogBuffer): () => void {\n if (typeof XMLHttpRequest === \"undefined\") return () => {};\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n const meta = new WeakMap<XMLHttpRequest, { method: string; url: string }>();\n\n proto.open = function (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) {\n meta.set(this, { method: String(method).toUpperCase(), url: String(url) });\n return (originalOpen as (...a: unknown[]) => void).call(this, method, url, ...rest);\n } as typeof proto.open;\n\n proto.send = function (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) {\n this.addEventListener(\"loadend\", () => {\n const info = meta.get(this);\n if (!info || isIgnored(info.url)) return;\n if (this.status === 0) buffer.push(\"network\", `${info.method} ${info.url} → failed (network error)`);\n else if (this.status >= 400) buffer.push(\"network\", `${info.method} ${info.url} → ${this.status} ${this.statusText}`.trim());\n });\n return originalSend.call(this, body);\n };\n\n return () => {\n proto.open = originalOpen;\n proto.send = originalSend;\n };\n}\n","import type { FeedbackKitConfiguration, FeedbackProduct, FeedbackReport, FeedbackUser } from \"./types\";\n\n/** The hosted FeedbackKit dashboard's ingestion endpoint. */\nexport const DEFAULT_ENDPOINT = \"https://gpucoladcyvijefdjudf.supabase.co/functions/v1/ingest-feedback\";\n\nexport class FeedbackSubmissionError extends Error {\n constructor(\n message: string,\n readonly kind: \"not_configured\" | \"network\" | \"server\",\n readonly status?: number,\n ) {\n super(message);\n this.name = \"FeedbackSubmissionError\";\n }\n}\n\n/**\n * Wire format sent to the ingestion endpoint — the exact shape the Swift\n * SDK's private `IngestPayload` produces (Sources/FeedbackKit/Networking/FeedbackSubmitter.swift)\n * and `supabase/functions/ingest-feedback` accepts. snake_case at the top\n * level; `environment`/`annotations`/`logs` pass through untouched (camelCase\n * JSONB). Optional fields are omitted rather than sent as null, matching\n * Swift's `encodeIfPresent`.\n */\nexport interface IngestPayload {\n project_key: string;\n id: string;\n created_at: string;\n text: string;\n screenshot_raw_png_base64?: string;\n screenshot_annotated_png_base64?: string;\n annotations: FeedbackReport[\"annotations\"];\n environment: FeedbackReport[\"environment\"];\n attachment_filename?: string;\n attachment_mime_type?: string;\n attachment_data_base64?: string;\n product_keys?: string[];\n products?: { key: string; name: string; description: string; is_default: boolean }[];\n logs?: FeedbackReport[\"logs\"];\n /** Anonymous per-browser id — see fixes.ts `reporterId`. */\n reporter_id?: string;\n /** `FeedbackKit.setUser(...)`, camelCase JSONB like `environment`. */\n reporter?: FeedbackUser;\n /** \"Notify me when it's fixed\"; always sent, false unless the reporter opted in. */\n notify_reporter: boolean;\n}\n\nexport async function blobToBase64(blob: Blob): Promise<string> {\n const bytes = new Uint8Array(await blob.arrayBuffer());\n let binary = \"\";\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return btoa(binary);\n}\n\nexport async function encodePayload(\n report: FeedbackReport,\n projectKey: string,\n identity: { reporterId?: string; user?: FeedbackUser | null } = {},\n): Promise<IngestPayload> {\n const payload: IngestPayload = {\n project_key: projectKey,\n id: report.id,\n created_at: report.createdAt.toISOString(),\n text: report.text,\n annotations: report.annotations,\n environment: report.environment,\n notify_reporter: report.notifyReporter ?? false,\n };\n if (report.screenshotRaw && report.screenshotAnnotated) {\n const [raw, annotated] = await Promise.all([\n blobToBase64(report.screenshotRaw),\n blobToBase64(report.screenshotAnnotated),\n ]);\n payload.screenshot_raw_png_base64 = raw;\n payload.screenshot_annotated_png_base64 = annotated;\n }\n if (report.attachment) {\n payload.attachment_filename = report.attachment.filename;\n payload.attachment_mime_type = report.attachment.mimeType;\n payload.attachment_data_base64 = await blobToBase64(report.attachment.data);\n }\n if (report.products.length > 0) {\n payload.product_keys = report.products.map((p) => p.key);\n payload.products = report.products.map((p) => ({\n key: p.key,\n name: p.name,\n description: p.description ?? \"\",\n is_default: p.isDefault ?? false,\n }));\n }\n if (report.logs.length > 0) payload.logs = report.logs;\n if (identity.reporterId) payload.reporter_id = identity.reporterId;\n if (identity.user) payload.reporter = identity.user;\n return payload;\n}\n\nexport async function submitReport(\n report: FeedbackReport,\n configuration: FeedbackKitConfiguration,\n identity: { reporterId?: string; user?: FeedbackUser | null } = {},\n): Promise<void> {\n if (!configuration.projectKey) {\n throw new FeedbackSubmissionError(\"FeedbackKit is not configured with a project key.\", \"not_configured\");\n }\n const body = JSON.stringify(await encodePayload(report, configuration.projectKey, identity));\n let response: Response;\n try {\n response = await fetch(configuration.endpoint ?? DEFAULT_ENDPOINT, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n } catch (error) {\n throw new FeedbackSubmissionError(\n `Network error: ${error instanceof Error ? error.message : String(error)}`,\n \"network\",\n );\n }\n if (!response.ok) {\n let code = \"\";\n try {\n const json = (await response.json()) as { error?: string };\n code = json.error ?? \"\";\n } catch {\n // Non-JSON error body; the status alone is enough.\n }\n const detail = code ? ` (${code})` : \"\";\n const message =\n code === \"origin_not_allowed\"\n ? `This site (${location.origin}) isn't in the project's allowed origins.`\n : response.status === 401 || response.status === 403\n ? `Server rejected the project key or origin (HTTP ${response.status})${detail}.`\n : response.status === 429\n ? \"Too many reports right now — please try again in a minute.\"\n : response.status === 402\n ? \"Feedback for this site is paused this month. Please try again later.\"\n : `Server returned HTTP ${response.status}${detail}.`;\n throw new FeedbackSubmissionError(message, \"server\", response.status);\n }\n}\n\n/** `GET <endpoint>?project_key=…` — the products configured for the project in the dashboard. */\nexport async function fetchProducts(configuration: FeedbackKitConfiguration): Promise<FeedbackProduct[]> {\n const url = new URL(configuration.endpoint ?? DEFAULT_ENDPOINT);\n url.searchParams.set(\"project_key\", configuration.projectKey);\n const response = await fetch(url.toString());\n if (!response.ok) throw new FeedbackSubmissionError(`HTTP ${response.status}`, \"server\", response.status);\n const json = (await response.json()) as {\n products?: { key: string; name: string; description?: string; is_default?: boolean }[];\n };\n return (json.products ?? []).map((p) => ({\n key: p.key,\n name: p.name,\n description: p.description ?? \"\",\n isDefault: p.is_default ?? false,\n }));\n}\n","import { blobToBase64, DEFAULT_ENDPOINT, FeedbackSubmissionError } from \"./submit\";\nimport type { FeedbackKitConfiguration, FeedbackReport, FeedbackUser, FixUpdate } from \"./types\";\n\n/**\n * The reporter's half of the closed loop — web counterpart of the Swift\n * SDK's `FixUpdatesClient` / `FeedbackReporterIdentity`. Talks to the\n * `reporter-updates` Edge Function (supabase/functions/reporter-updates);\n * keep the wire format in sync with it and with\n * Sources/FeedbackKit/Networking/FixUpdatesClient.swift.\n */\n\n// ------------------------------------------------------------ build order\n\n/**\n * Mirrors `compare_builds` (0014_closed_loop.sql) and every other copy:\n * dotted numeric builds compare numerically; anything else is only equal (0)\n * or incomparable (null).\n */\nexport function compareBuilds(a: string | null | undefined, b: string | null | undefined): -1 | 0 | 1 | null {\n if (a == null || b == null || a === \"\" || b === \"\") return null;\n if (a === b) return 0;\n const numeric = /^[0-9]+(\\.[0-9]+)*$/;\n if (!numeric.test(a) || !numeric.test(b)) return null;\n const pa = a.split(\".\");\n const pb = b.split(\".\");\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const na = BigInt(pa[i] ?? \"0\");\n const nb = BigInt(pb[i] ?? \"0\");\n if (na < nb) return -1;\n if (na > nb) return 1;\n }\n return 0;\n}\n\n// -------------------------------------------------------- reporter identity\n\nconst STORAGE_KEY = \"feedbackkit.reporterId\";\nconst VALID_ID = /^[A-Za-z0-9_-]{16,128}$/;\nlet memoryId: string | null = null;\nlet currentUser: FeedbackUser | null = null;\n\nfunction freshId(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * The anonymous, random id attached to reports from this browser — what lets\n * a fix get back to the person who reported the bug. Kept in localStorage\n * (per origin); where storage is unavailable (private mode, blocked site\n * data) it lasts for the page's lifetime instead, which just means that\n * browser won't be asked to verify fixes later.\n */\nexport function reporterId(): string {\n if (memoryId) return memoryId;\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored && VALID_ID.test(stored)) return (memoryId = stored);\n const id = freshId();\n localStorage.setItem(STORAGE_KEY, id);\n return (memoryId = id);\n } catch {\n return (memoryId = freshId());\n }\n}\n\nexport function setUser(user: FeedbackUser | null): void {\n currentUser = user && (user.id || user.email || user.name) ? { ...user } : null;\n}\n\nexport function getUser(): FeedbackUser | null {\n return currentUser;\n}\n\n// ------------------------------------------------------------- transport\n\n/** `…/functions/v1/ingest-feedback` → `…/functions/v1/reporter-updates`, unless overridden. */\nexport function reporterUpdatesEndpoint(configuration: FeedbackKitConfiguration): string {\n if (configuration.reporterUpdatesEndpoint) return configuration.reporterUpdatesEndpoint;\n const url = new URL(configuration.endpoint ?? DEFAULT_ENDPOINT);\n url.pathname = url.pathname.replace(/\\/[^/]*\\/?$/, \"/reporter-updates\");\n url.search = \"\";\n return url.toString();\n}\n\ninterface WireUpdate {\n feedback_id: string;\n text?: string;\n created_at?: string;\n screen_name?: string | null;\n fix_stage?: string | null;\n fixed_in_build?: string | null;\n fix_summary?: string | null;\n needs_verification?: boolean;\n open_question?: { id: string; body: string; created_at: string } | null;\n screenshot_url?: string | null;\n messages?: { id: string; kind: string; body: string; author: string; created_at: string }[];\n}\n\nexport function decodeUpdate(w: WireUpdate): FixUpdate {\n return {\n feedbackId: w.feedback_id,\n text: w.text ?? \"\",\n createdAt: w.created_at ?? \"\",\n screenName: w.screen_name ?? null,\n fixStage: w.fix_stage ?? null,\n fixedInBuild: w.fixed_in_build ?? null,\n fixSummary: w.fix_summary ?? null,\n needsVerification: w.needs_verification ?? false,\n openQuestion: w.open_question ? { id: w.open_question.id, body: w.open_question.body, createdAt: w.open_question.created_at } : null,\n screenshotUrl: w.screenshot_url ?? null,\n messages: (w.messages ?? []).map((m) => ({ id: m.id, kind: m.kind, body: m.body, author: m.author, createdAt: m.created_at })),\n };\n}\n\nexport async function fetchFixUpdates(configuration: FeedbackKitConfiguration): Promise<FixUpdate[]> {\n const url = new URL(reporterUpdatesEndpoint(configuration));\n url.searchParams.set(\"project_key\", configuration.projectKey);\n url.searchParams.set(\"reporter_id\", reporterId());\n if (configuration.appBuild) url.searchParams.set(\"build\", configuration.appBuild);\n let response: Response;\n try {\n response = await fetch(url.toString());\n } catch (error) {\n throw new FeedbackSubmissionError(`Network error: ${error instanceof Error ? error.message : String(error)}`, \"network\");\n }\n if (!response.ok) throw new FeedbackSubmissionError(`HTTP ${response.status}`, \"server\", response.status);\n const json = (await response.json()) as { updates?: WireUpdate[] };\n return (json.updates ?? []).map(decodeUpdate);\n}\n\nexport type FixAction =\n | { type: \"verify\" }\n /** Still broken — optionally with a fresh report (text + annotated screenshot). */\n | { type: \"reopen\"; report?: FeedbackReport | null; text?: string }\n | { type: \"reply\"; text: string };\n\nexport async function encodeFixAction(\n configuration: FeedbackKitConfiguration,\n feedbackId: string,\n action: FixAction,\n): Promise<Record<string, unknown>> {\n const body: Record<string, unknown> = {\n project_key: configuration.projectKey,\n reporter_id: reporterId(),\n feedback_id: feedbackId,\n action: action.type,\n };\n if (configuration.appBuild) body.build = configuration.appBuild;\n if (action.type === \"reply\") body.text = action.text;\n if (action.type === \"reopen\") {\n const report = action.report;\n const text = report?.text ?? action.text;\n if (text) body.text = text;\n if (report?.screenshotAnnotated) {\n body.screenshot_annotated_png_base64 = await blobToBase64(report.screenshotAnnotated);\n if (report.screenshotRaw) body.screenshot_raw_png_base64 = await blobToBase64(report.screenshotRaw);\n body.annotations = report.annotations;\n }\n }\n return body;\n}\n\nexport async function sendFixAction(configuration: FeedbackKitConfiguration, feedbackId: string, action: FixAction): Promise<void> {\n const body = JSON.stringify(await encodeFixAction(configuration, feedbackId, action));\n let response: Response;\n try {\n response = await fetch(reporterUpdatesEndpoint(configuration), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n } catch (error) {\n throw new FeedbackSubmissionError(`Network error: ${error instanceof Error ? error.message : String(error)}`, \"network\");\n }\n if (!response.ok) throw new FeedbackSubmissionError(`HTTP ${response.status}`, \"server\", response.status);\n}\n","// Inline stroke icons (24×24, currentColor) so the widget has no asset requests.\nconst svg = (body: string) =>\n `<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${body}</svg>`;\n\nexport const icons = {\n feedback: svg(\n '<path d=\"M21 12a8 8 0 0 1-11.6 7.1L4 20l1-4.6A8 8 0 1 1 21 12Z\"/><path d=\"M8.5 10.5h7M8.5 14h4.5\"/>',\n ),\n pen: svg('<path d=\"M4 20l4-1L19 8a2.1 2.1 0 0 0-3-3L5 16l-1 4Z\"/><path d=\"M14.5 6.5l3 3\"/>'),\n rectangle: svg('<rect x=\"4\" y=\"6\" width=\"16\" height=\"12\" rx=\"1.5\"/>'),\n arrow: svg('<path d=\"M6 18L18 6\"/><path d=\"M9 6h9v9\"/>'),\n text: svg('<path d=\"M5 6V5h14v1\"/><path d=\"M12 5v14\"/><path d=\"M9 19h6\"/>'),\n move: svg(\n '<path d=\"M12 3v18M3 12h18\"/><path d=\"M9 6l3-3 3 3M9 18l3 3 3-3M6 9l-3 3 3 3M18 9l3 3-3 3\"/>',\n ),\n undo: svg('<path d=\"M9 14L4 9l5-5\"/><path d=\"M4 9h10.5a5.5 5.5 0 0 1 0 11H11\"/>'),\n trash: svg('<path d=\"M4 7h16\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M6 7l1 13h10l1-13\"/><path d=\"M9 7V4h6v3\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n plus: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n paperclip: svg(\n '<path d=\"M21 11.5l-8.6 8.6a5.5 5.5 0 0 1-7.8-7.8l8.6-8.6a3.7 3.7 0 0 1 5.2 5.2l-8.6 8.6a1.8 1.8 0 0 1-2.6-2.6l7.9-7.9\"/>',\n ),\n send: svg('<path d=\"M4 12l16-8-6 16-3-7-7-1Z\"/>'),\n check: svg('<path d=\"M5 12.5l4.5 4.5L19 7.5\"/>'),\n};\n","import type { FixUpdate } from \"../types\";\nimport { icons } from \"./icons\";\n\nexport type FixCardOutcome =\n | { type: \"verified\" }\n /** The widget then opens the capture flow in \"still broken\" mode. */\n | { type: \"stillBroken\" }\n | { type: \"replied\"; text: string }\n | { type: \"later\" };\n\n/**\n * \"We fixed something you reported — is it fixed?\" A small non-modal card in\n * the page's bottom corner (above the trigger), inside the widget's Shadow\n * DOM. Web counterpart of Swift's `FixVerificationView`; same copy on purpose.\n */\nexport class FixCard {\n private root: HTMLElement | null = null;\n private settled = false;\n\n constructor(\n private readonly shadow: ShadowRoot,\n private readonly update: FixUpdate,\n private readonly onOutcome: (outcome: FixCardOutcome) => void,\n ) {}\n\n show(position: \"bottom-right\" | \"bottom-left\"): void {\n const u = this.update;\n const card = el(\"section\", \"fk-fixcard\");\n card.dataset.position = position;\n card.setAttribute(\"role\", \"dialog\");\n card.setAttribute(\"aria-labelledby\", \"fk-fixcard-title\");\n\n const header = el(\"div\", \"fk-fixcard-header\");\n const title = el(\"h2\", \"fk-title\");\n title.id = \"fk-fixcard-title\";\n title.textContent = u.needsVerification ? \"We fixed something you reported\" : \"A question about your report\";\n const close = document.createElement(\"button\");\n close.type = \"button\";\n close.className = \"fk-close\";\n close.innerHTML = icons.close;\n close.setAttribute(\"aria-label\", \"Remind me later\");\n close.title = \"Remind me later\";\n close.addEventListener(\"click\", () => this.settle({ type: \"later\" }));\n header.append(title, close);\n card.append(header);\n\n if (u.needsVerification && u.fixedInBuild) {\n card.append(text(\"p\", \"fk-meta\", `Fixed in build ${u.fixedInBuild}.`));\n }\n\n if (u.screenshotUrl) {\n const img = document.createElement(\"img\");\n img.className = \"fk-fixcard-shot\";\n img.alt = \"Your screenshot from the original report\";\n img.src = u.screenshotUrl;\n img.addEventListener(\"error\", () => img.remove());\n card.append(img);\n }\n\n card.append(text(\"p\", \"fk-meta\", \"You reported\"));\n card.append(text(\"p\", \"fk-fixcard-quote\", u.text ? `“${u.text}”` : \"(no description)\"));\n if (u.needsVerification && u.fixSummary) {\n card.append(text(\"p\", \"fk-fixcard-summary\", `What changed: ${u.fixSummary}`));\n }\n for (const m of u.messages.filter((m) => m.kind === \"comment\")) {\n const msg = el(\"div\", \"fk-fixcard-message\");\n msg.append(text(\"span\", \"fk-meta\", m.author), text(\"p\", \"\", m.body));\n card.append(msg);\n }\n\n const actions = el(\"div\", \"fk-fixcard-actions\");\n if (u.needsVerification) {\n const yes = button(\"fk-btn fk-btn-primary\", \"Yes, it's fixed\");\n yes.addEventListener(\"click\", () => this.settle({ type: \"verified\" }));\n const no = button(\"fk-btn fk-btn-secondary\", \"No, still broken\");\n no.addEventListener(\"click\", () => this.settle({ type: \"stillBroken\" }));\n actions.append(yes, no);\n } else if (u.openQuestion) {\n actions.append(text(\"p\", \"fk-fixcard-question\", u.openQuestion.body));\n const input = document.createElement(\"textarea\");\n input.className = \"fk-textarea\";\n input.placeholder = \"Your answer\";\n input.setAttribute(\"aria-label\", \"Your answer\");\n const send = button(\"fk-btn fk-btn-primary\", \"Send\");\n send.disabled = true;\n input.addEventListener(\"input\", () => (send.disabled = input.value.trim() === \"\"));\n send.addEventListener(\"click\", () => this.settle({ type: \"replied\", text: input.value.trim() }));\n actions.append(input, send);\n }\n card.append(actions);\n\n this.root = card;\n this.shadow.append(card);\n }\n\n /** Close as \"later\" (e.g. `FeedbackKit.disableFixVerification()`). */\n dismiss(): void {\n this.settle({ type: \"later\" });\n }\n\n /** Remove without reporting an outcome (the widget is being destroyed). */\n remove(): void {\n this.settled = true;\n this.root?.remove();\n this.root = null;\n }\n\n private settle(outcome: FixCardOutcome): void {\n if (this.settled) return;\n this.settled = true;\n this.root?.remove();\n this.root = null;\n this.onOutcome(outcome);\n }\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(tag: K, className: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction text<K extends keyof HTMLElementTagNameMap>(tag: K, className: string, content: string): HTMLElementTagNameMap[K] {\n const node = el(tag, className);\n node.textContent = content;\n return node;\n}\n\nfunction button(className: string, label: string): HTMLButtonElement {\n const b = el(\"button\", className);\n b.type = \"button\";\n b.textContent = label;\n return b;\n}\n","import type { FeedbackAnnotation, NormalizedPoint } from \"./types\";\n\n/**\n * Canvas port of the Swift SDK's `AnnotationRenderer`\n * (Sources/FeedbackKit/Annotation/AnnotationRenderer.swift). Same stroke\n * width, arrowhead geometry, text-bubble metrics, scale/rotation math and\n * hit-testing, so a report annotated in a browser renders the same way a\n * native one does — and the dashboard can use this one file to redraw\n * annotations from any platform on top of the raw screenshot.\n *\n * All sizes are in the *target's* coordinate space (CSS pixels on the web,\n * points on iOS/macOS); callers scale the context for device pixels.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** Anything with `measureText` — lets hit-testing run without a real canvas in tests. */\nexport interface TextMeasurer {\n font: string;\n measureText(text: string): { width: number };\n}\n\nexport const STROKE_WIDTH = 4;\nexport const HIT_TEST_TOLERANCE = 16;\nconst HEAD_LENGTH = 18;\nconst HEAD_ANGLE = Math.PI / 7;\nconst BASE_FONT_SIZE = 16;\nconst TEXT_PADDING = 8;\n/** UIFont.boldSystemFont's line height is ~1.19× its point size; match it so bubbles are the same height. */\nconst LINE_HEIGHT_RATIO = 1.19;\nconst FALLBACK_COLOR = \"#FF0000\";\n\nexport function textFont(scale = 1): string {\n return `bold ${BASE_FONT_SIZE * scale}px -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif`;\n}\n\n/** Accepts both the `[x, y]` wire shape and a legacy/defensive `{x, y}` object. */\nexport function readPoint(p: NormalizedPoint | Point | unknown): Point {\n if (Array.isArray(p)) return { x: Number(p[0]) || 0, y: Number(p[1]) || 0 };\n if (p && typeof p === \"object\") {\n const o = p as Record<string, unknown>;\n return { x: Number(o.x) || 0, y: Number(o.y) || 0 };\n }\n return { x: 0, y: 0 };\n}\n\nexport function denormalize(annotation: FeedbackAnnotation, size: Size): Point[] {\n return (annotation.points ?? []).map((p) => {\n const { x, y } = readPoint(p);\n return { x: x * size.width, y: y * size.height };\n });\n}\n\nexport function normalizeColor(hex: string | undefined): string {\n if (!hex) return FALLBACK_COLOR;\n const cleaned = hex.trim().replace(/^#/, \"\");\n if (/^[0-9a-fA-F]{6}$/.test(cleaned) || /^[0-9a-fA-F]{8}$/.test(cleaned)) return `#${cleaned}`;\n return FALLBACK_COLOR;\n}\n\nexport function drawAnnotations(\n ctx: CanvasRenderingContext2D,\n annotations: readonly FeedbackAnnotation[],\n size: Size,\n): void {\n for (const annotation of annotations) drawAnnotation(ctx, annotation, size);\n}\n\nexport function drawAnnotation(ctx: CanvasRenderingContext2D, annotation: FeedbackAnnotation, size: Size): void {\n const color = normalizeColor(annotation.colorHex);\n const points = denormalize(annotation, size);\n const scale = annotation.scale ?? 1;\n const rotation = annotation.rotation ?? 0;\n\n switch (annotation.kind) {\n case \"freehand\":\n drawFreehand(ctx, points, color);\n break;\n case \"rectangle\":\n if (points.length === 2) drawRectangle(ctx, points[0], points[1], color, scale, rotation);\n break;\n case \"arrow\":\n if (points.length === 2) drawArrow(ctx, points[0], points[1], color, scale, rotation);\n break;\n case \"text\":\n if (points.length >= 1 && annotation.label) drawText(ctx, annotation.label, points[0], color, scale);\n break;\n }\n}\n\nfunction drawFreehand(ctx: CanvasRenderingContext2D, points: Point[], color: string): void {\n if (points.length === 0) return;\n ctx.save();\n ctx.lineWidth = STROKE_WIDTH;\n ctx.lineJoin = \"round\";\n ctx.lineCap = \"round\";\n ctx.strokeStyle = color;\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n // A single tap still leaves a visible dot, like a zero-length CGPath stroke with round caps.\n if (points.length === 1) ctx.lineTo(points[0].x + 0.01, points[0].y);\n for (const p of points.slice(1)) ctx.lineTo(p.x, p.y);\n ctx.stroke();\n ctx.restore();\n}\n\nfunction drawRectangle(\n ctx: CanvasRenderingContext2D,\n start: Point,\n end: Point,\n color: string,\n scale: number,\n rotation: number,\n): void {\n const center = midpoint(start, end);\n const corners = rectangleCorners(\n center,\n (Math.abs(end.x - start.x) / 2) * scale,\n (Math.abs(end.y - start.y) / 2) * scale,\n rotation,\n );\n ctx.save();\n ctx.lineWidth = STROKE_WIDTH;\n ctx.lineJoin = \"miter\";\n ctx.strokeStyle = color;\n ctx.beginPath();\n ctx.moveTo(corners[0].x, corners[0].y);\n for (const c of corners.slice(1)) ctx.lineTo(c.x, c.y);\n ctx.closePath();\n ctx.stroke();\n ctx.restore();\n}\n\nfunction drawArrow(\n ctx: CanvasRenderingContext2D,\n rawStart: Point,\n rawEnd: Point,\n color: string,\n scale: number,\n rotation: number,\n): void {\n const { start, end, left, right } = arrowGeometry(rawStart, rawEnd, scale, rotation);\n ctx.save();\n ctx.lineWidth = STROKE_WIDTH;\n ctx.lineJoin = \"round\";\n ctx.lineCap = \"round\";\n ctx.strokeStyle = color;\n ctx.beginPath();\n ctx.moveTo(start.x, start.y);\n ctx.lineTo(end.x, end.y);\n ctx.lineTo(left.x, left.y);\n ctx.moveTo(end.x, end.y);\n ctx.lineTo(right.x, right.y);\n ctx.stroke();\n ctx.restore();\n}\n\nexport function arrowGeometry(rawStart: Point, rawEnd: Point, scale = 1, rotation = 0) {\n const center = midpoint(rawStart, rawEnd);\n const start = rotate(scaled(rawStart, scale, center), rotation, center);\n const end = rotate(scaled(rawEnd, scale, center), rotation, center);\n const angle = Math.atan2(end.y - start.y, end.x - start.x);\n const left = {\n x: end.x - HEAD_LENGTH * Math.cos(angle - HEAD_ANGLE),\n y: end.y - HEAD_LENGTH * Math.sin(angle - HEAD_ANGLE),\n };\n const right = {\n x: end.x - HEAD_LENGTH * Math.cos(angle + HEAD_ANGLE),\n y: end.y - HEAD_LENGTH * Math.sin(angle + HEAD_ANGLE),\n };\n return { start, end, left, right };\n}\n\nfunction drawText(ctx: CanvasRenderingContext2D, text: string, point: Point, color: string, scale: number): void {\n const rect = textBubbleRect(ctx, text, point, scale);\n ctx.save();\n ctx.fillStyle = color;\n ctx.beginPath();\n roundedRectPath(ctx, rect.x, rect.y, rect.width, rect.height, 8);\n ctx.fill();\n ctx.font = textFont(scale);\n ctx.fillStyle = \"#FFFFFF\";\n ctx.textBaseline = \"top\";\n // Matches Swift, which insets by the *unscaled* padding when drawing but\n // sizes the bubble with the scaled one.\n ctx.fillText(text, rect.x + TEXT_PADDING, rect.y + TEXT_PADDING + (BASE_FONT_SIZE * scale * (LINE_HEIGHT_RATIO - 1)) / 2);\n ctx.restore();\n}\n\nfunction roundedRectPath(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number): void {\n const radius = Math.min(r, w / 2, h / 2);\n ctx.moveTo(x + radius, y);\n ctx.arcTo(x + w, y, x + w, y + h, radius);\n ctx.arcTo(x + w, y + h, x, y + h, radius);\n ctx.arcTo(x, y + h, x, y, radius);\n ctx.arcTo(x, y, x + w, y, radius);\n ctx.closePath();\n}\n\nexport function textBubbleRect(measurer: TextMeasurer, text: string, point: Point, scale = 1) {\n const previous = measurer.font;\n measurer.font = textFont(scale);\n const width = measurer.measureText(text).width;\n measurer.font = previous;\n const height = BASE_FONT_SIZE * scale * LINE_HEIGHT_RATIO;\n const padding = TEXT_PADDING * scale;\n return { x: point.x, y: point.y, width: width + padding * 2, height: height + padding * 2 };\n}\n\nexport function rectangleCorners(center: Point, halfWidth: number, halfHeight: number, rotation: number): Point[] {\n return [\n { x: center.x - halfWidth, y: center.y - halfHeight },\n { x: center.x + halfWidth, y: center.y - halfHeight },\n { x: center.x + halfWidth, y: center.y + halfHeight },\n { x: center.x - halfWidth, y: center.y + halfHeight },\n ].map((p) => rotate(p, rotation, center));\n}\n\n/**\n * Whether a pointer at `point` grabs `annotation` for a drag. Freehand\n * strokes are intentionally not draggable, same as native.\n */\nexport function hitTest(\n annotation: FeedbackAnnotation,\n point: Point,\n size: Size,\n measurer: TextMeasurer,\n): boolean {\n const points = denormalize(annotation, size);\n const scale = annotation.scale ?? 1;\n switch (annotation.kind) {\n case \"rectangle\": {\n if (points.length !== 2) return false;\n // Scaled-but-unrotated bounding box, same approximation as native.\n const center = midpoint(points[0], points[1]);\n const hw = (Math.abs(points[1].x - points[0].x) / 2) * scale + HIT_TEST_TOLERANCE;\n const hh = (Math.abs(points[1].y - points[0].y) / 2) * scale + HIT_TEST_TOLERANCE;\n return Math.abs(point.x - center.x) <= hw && Math.abs(point.y - center.y) <= hh;\n }\n case \"arrow\": {\n if (points.length !== 2) return false;\n const center = midpoint(points[0], points[1]);\n return (\n distanceToSegment(point, scaled(points[0], scale, center), scaled(points[1], scale, center)) <=\n HIT_TEST_TOLERANCE\n );\n }\n case \"text\": {\n if (points.length < 1 || !annotation.label) return false;\n const rect = textBubbleRect(measurer, annotation.label, points[0], scale);\n const t = HIT_TEST_TOLERANCE / 2;\n return (\n point.x >= rect.x - t &&\n point.x <= rect.x + rect.width + t &&\n point.y >= rect.y - t &&\n point.y <= rect.y + rect.height + t\n );\n }\n case \"freehand\":\n return false;\n }\n}\n\nexport function midpoint(a: Point, b: Point): Point {\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n}\n\nexport function rotate(p: Point, angle: number, center: Point): Point {\n const dx = p.x - center.x;\n const dy = p.y - center.y;\n return {\n x: center.x + dx * Math.cos(angle) - dy * Math.sin(angle),\n y: center.y + dx * Math.sin(angle) + dy * Math.cos(angle),\n };\n}\n\nexport function scaled(p: Point, scale: number, center: Point): Point {\n return { x: center.x + (p.x - center.x) * scale, y: center.y + (p.y - center.y) * scale };\n}\n\nexport function distanceToSegment(p: Point, a: Point, b: Point): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lengthSquared = dx * dx + dy * dy;\n if (lengthSquared === 0) return Math.hypot(p.x - a.x, p.y - a.y);\n const t = Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared));\n return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));\n}\n","import type { CapturedScreenshot } from \"../capture\";\nimport { drawAnnotation, drawAnnotations, hitTest, type Point } from \"../renderer\";\nimport type { FeedbackAnnotation, NormalizedPoint } from \"../types\";\n\nexport type Tool = \"pen\" | \"rectangle\" | \"arrow\" | \"text\" | \"move\";\n\n/** Same palette as the native toolbar: systemRed, systemYellow, systemGreen, systemBlue, label. */\nexport const COLORS = [\"#FF3B30\", \"#FFCC00\", \"#34C759\", \"#007AFF\", \"#000000\"] as const;\n\nconst MIN_SCALE = 0.3;\nconst MAX_SCALE = 5;\n\ninterface Gesture {\n index: number;\n startDistance: number;\n startAngle: number;\n startScale: number;\n startRotation: number;\n}\n\ninterface Drag {\n index: number;\n last: Point;\n moved: boolean;\n}\n\n/**\n * The annotation canvas: the screenshot, plus an \"ink\" canvas on top that\n * the user draws on. Everything is stored in the capture's own coordinate\n * space (viewport CSS pixels) and normalized to 0...1 on the way out, so the\n * on-screen display size never leaks into the report — same contract as\n * the native `AnnotationCanvasView`.\n */\nexport class AnnotationEditor {\n readonly element: HTMLDivElement;\n annotations: FeedbackAnnotation[] = [];\n tool: Tool = \"pen\";\n color: string = COLORS[0];\n onChange: () => void = () => {};\n\n private readonly base: HTMLCanvasElement;\n private readonly ink: HTMLCanvasElement;\n private readonly inkCtx: CanvasRenderingContext2D;\n private history: FeedbackAnnotation[][] = [];\n private draft: FeedbackAnnotation | null = null;\n private draftStart: Point | null = null;\n private pointers = new Map<number, Point>();\n private drag: Drag | null = null;\n private gesture: Gesture | null = null;\n private selected: number | null = null;\n private textInput: HTMLInputElement | null = null;\n private displayScale = 1;\n\n constructor(private readonly shot: CapturedScreenshot) {\n this.element = document.createElement(\"div\");\n this.element.className = \"fk-canvas-box\";\n this.base = document.createElement(\"canvas\");\n this.ink = document.createElement(\"canvas\");\n this.ink.className = \"fk-ink\";\n this.ink.setAttribute(\"role\", \"img\");\n this.ink.setAttribute(\"aria-label\", \"Screenshot — draw on it to highlight the problem\");\n this.element.append(this.base, this.ink);\n const ctx = this.ink.getContext(\"2d\");\n if (!ctx) throw new Error(\"Canvas 2D is unavailable\");\n this.inkCtx = ctx;\n\n this.ink.addEventListener(\"pointerdown\", (e) => this.onPointerDown(e));\n this.ink.addEventListener(\"pointermove\", (e) => this.onPointerMove(e));\n this.ink.addEventListener(\"pointerup\", (e) => this.onPointerUp(e));\n this.ink.addEventListener(\"pointercancel\", (e) => this.onPointerUp(e));\n this.ink.addEventListener(\"wheel\", (e) => this.onWheel(e), { passive: false });\n }\n\n /** Fits the screenshot inside `maxWidth × maxHeight` (CSS px) keeping its aspect ratio. */\n layout(maxWidth: number, maxHeight: number): void {\n const scale = Math.max(0.05, Math.min(maxWidth / this.shot.width, maxHeight / this.shot.height, 1));\n this.displayScale = scale;\n const w = Math.round(this.shot.width * scale);\n const h = Math.round(this.shot.height * scale);\n const dpr = window.devicePixelRatio || 1;\n for (const canvas of [this.base, this.ink]) {\n canvas.style.width = `${w}px`;\n canvas.style.height = `${h}px`;\n canvas.width = Math.round(w * dpr);\n canvas.height = Math.round(h * dpr);\n }\n const baseCtx = this.base.getContext(\"2d\");\n if (baseCtx) {\n baseCtx.imageSmoothingQuality = \"high\";\n baseCtx.drawImage(this.shot.canvas, 0, 0, this.base.width, this.base.height);\n }\n this.cancelTextInput();\n this.render();\n }\n\n setTool(tool: Tool): void {\n this.commitTextInput();\n this.tool = tool;\n this.selected = null;\n this.ink.style.cursor = tool === \"move\" ? \"grab\" : tool === \"text\" ? \"text\" : \"crosshair\";\n this.render();\n }\n\n undo(): void {\n this.commitTextInput();\n const previous = this.history.pop();\n if (!previous) return;\n this.annotations = previous;\n this.selected = null;\n this.changed();\n }\n\n clear(): void {\n if (this.annotations.length === 0) return;\n this.snapshot();\n this.annotations = [];\n this.selected = null;\n this.changed();\n }\n\n get canUndo(): boolean {\n return this.history.length > 0;\n }\n\n /** Deletes the annotation last moved/selected with the move tool. */\n deleteSelected(): boolean {\n if (this.selected === null || !this.annotations[this.selected]) return false;\n this.snapshot();\n this.annotations.splice(this.selected, 1);\n this.selected = null;\n this.changed();\n return true;\n }\n\n /** The screenshot at full capture resolution with every annotation burned in. */\n flatten(): HTMLCanvasElement {\n this.commitTextInput();\n const out = document.createElement(\"canvas\");\n out.width = this.shot.canvas.width;\n out.height = this.shot.canvas.height;\n const ctx = out.getContext(\"2d\");\n if (!ctx) throw new Error(\"Canvas 2D is unavailable\");\n ctx.drawImage(this.shot.canvas, 0, 0);\n ctx.scale(out.width / this.shot.width, out.height / this.shot.height);\n drawAnnotations(ctx, this.annotations, { width: this.shot.width, height: this.shot.height });\n return out;\n }\n\n commitTextInput(): void {\n const input = this.textInput;\n if (!input) return;\n this.textInput = null;\n const label = input.value.trim();\n const origin = JSON.parse(input.dataset.origin ?? \"[0,0]\") as NormalizedPoint;\n input.remove();\n if (!label) return;\n this.snapshot();\n this.annotations.push({ kind: \"text\", points: [origin], colorHex: this.color, label, scale: 1, rotation: 0 });\n this.changed();\n }\n\n cancelTextInput(): void {\n this.textInput?.remove();\n this.textInput = null;\n }\n\n // ---------------------------------------------------------------- drawing\n\n render(): void {\n const ctx = this.inkCtx;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, this.ink.width, this.ink.height);\n const k = this.ink.width / this.shot.width;\n ctx.setTransform(k, 0, 0, k, 0, 0);\n const size = { width: this.shot.width, height: this.shot.height };\n drawAnnotations(ctx, this.annotations, size);\n if (this.draft) drawAnnotation(ctx, this.draft, size);\n }\n\n private changed(): void {\n this.render();\n this.onChange();\n }\n\n private snapshot(): void {\n this.history.push(this.annotations.map((a) => ({ ...a, points: a.points.map((p) => [p[0], p[1]] as NormalizedPoint) })));\n if (this.history.length > 100) this.history.shift();\n }\n\n // ---------------------------------------------------------------- input\n\n /** Pointer position in capture coordinates (viewport CSS px of the original page). */\n private toCapture(e: PointerEvent | WheelEvent): Point {\n const rect = this.ink.getBoundingClientRect();\n return {\n x: Math.max(0, Math.min(this.shot.width, (e.clientX - rect.left) / this.displayScale)),\n y: Math.max(0, Math.min(this.shot.height, (e.clientY - rect.top) / this.displayScale)),\n };\n }\n\n private normalize(p: Point): NormalizedPoint {\n return [round4(p.x / this.shot.width), round4(p.y / this.shot.height)];\n }\n\n private hitIndex(p: Point): number | null {\n const size = { width: this.shot.width, height: this.shot.height };\n for (let i = this.annotations.length - 1; i >= 0; i--) {\n if (hitTest(this.annotations[i], p, size, this.inkCtx)) return i;\n }\n return null;\n }\n\n private onPointerDown(e: PointerEvent): void {\n if (e.button !== 0 && e.pointerType === \"mouse\") return;\n e.preventDefault();\n const p = this.toCapture(e);\n this.ink.setPointerCapture(e.pointerId);\n this.pointers.set(e.pointerId, p);\n\n if (this.tool === \"move\") {\n if (this.pointers.size === 2 && this.selected !== null) {\n this.drag = null;\n this.startGesture();\n return;\n }\n const index = this.hitIndex(p);\n this.selected = index;\n if (index !== null) {\n this.snapshot();\n this.drag = { index, last: p, moved: false };\n this.ink.style.cursor = \"grabbing\";\n }\n return;\n }\n\n if (this.pointers.size > 1) return;\n\n if (this.tool === \"text\") {\n this.commitTextInput();\n this.openTextInput(p);\n return;\n }\n\n this.draftStart = p;\n const n = this.normalize(p);\n this.draft = {\n kind: this.tool === \"pen\" ? \"freehand\" : this.tool,\n points: this.tool === \"pen\" ? [n] : [n, n],\n colorHex: this.color,\n scale: 1,\n rotation: 0,\n };\n this.render();\n }\n\n private onPointerMove(e: PointerEvent): void {\n if (!this.pointers.has(e.pointerId)) {\n if (this.tool === \"move\" && e.pointerType === \"mouse\") {\n this.ink.style.cursor = this.hitIndex(this.toCapture(e)) !== null ? \"grab\" : \"default\";\n }\n return;\n }\n const p = this.toCapture(e);\n this.pointers.set(e.pointerId, p);\n\n if (this.gesture) {\n this.updateGesture();\n return;\n }\n if (this.drag) {\n const dx = (p.x - this.drag.last.x) / this.shot.width;\n const dy = (p.y - this.drag.last.y) / this.shot.height;\n this.drag.last = p;\n this.drag.moved = true;\n const a = this.annotations[this.drag.index];\n a.points = a.points.map(([x, y]) => [round4(x + dx), round4(y + dy)] as NormalizedPoint);\n this.render();\n return;\n }\n if (!this.draft || !this.draftStart) return;\n const n = this.normalize(p);\n if (this.draft.kind === \"freehand\") {\n const last = this.draft.points[this.draft.points.length - 1];\n // Skip sub-pixel jitter so long strokes stay compact in the JSON.\n if (Math.hypot((n[0] - last[0]) * this.shot.width, (n[1] - last[1]) * this.shot.height) >= 1.5) {\n this.draft.points.push(n);\n }\n } else {\n this.draft.points = [this.draft.points[0], n];\n }\n this.render();\n }\n\n private onPointerUp(e: PointerEvent): void {\n if (!this.pointers.has(e.pointerId)) return;\n this.pointers.delete(e.pointerId);\n if (this.ink.hasPointerCapture(e.pointerId)) this.ink.releasePointerCapture(e.pointerId);\n\n if (this.gesture) {\n if (this.pointers.size < 2) {\n this.gesture = null;\n this.onChange();\n }\n return;\n }\n if (this.drag) {\n if (!this.drag.moved) this.history.pop(); // A click without movement isn't an edit.\n this.drag = null;\n this.ink.style.cursor = \"grab\";\n this.onChange();\n return;\n }\n const draft = this.draft;\n this.draft = null;\n const start = this.draftStart;\n this.draftStart = null;\n if (!draft || !start) return;\n if (draft.kind !== \"freehand\") {\n const [a, b] = draft.points;\n const tiny = Math.hypot((b[0] - a[0]) * this.shot.width, (b[1] - a[1]) * this.shot.height) < 6;\n if (tiny) {\n this.render();\n return;\n }\n }\n this.snapshot();\n this.annotations.push(draft);\n this.changed();\n }\n\n /** Mouse/trackpad stand-in for pinch/twist: wheel scales, Shift/Alt+wheel rotates. */\n private onWheel(e: WheelEvent): void {\n if (this.tool !== \"move\") return;\n const p = this.toCapture(e);\n const index = this.hitIndex(p) ?? this.selected;\n if (index === null || !this.annotations[index]) return;\n e.preventDefault();\n const a = this.annotations[index];\n if (a.kind === \"freehand\") return;\n this.selected = index;\n if (e.shiftKey || e.altKey) {\n if (a.kind === \"text\") return;\n const delta = e.deltaY !== 0 ? e.deltaY : e.deltaX;\n a.rotation = round4(a.rotation + delta * 0.004);\n } else {\n // ctrlKey is set for trackpad pinch gestures in Chromium/Firefox — same axis, finer steps.\n a.scale = round4(clamp(a.scale * Math.exp(-e.deltaY * (e.ctrlKey ? 0.01 : 0.0015)), MIN_SCALE, MAX_SCALE));\n }\n this.render();\n this.onChange();\n }\n\n private startGesture(): void {\n if (this.selected === null) return;\n const [a, b] = [...this.pointers.values()];\n const annotation = this.annotations[this.selected];\n this.snapshot();\n this.gesture = {\n index: this.selected,\n startDistance: Math.max(1, Math.hypot(b.x - a.x, b.y - a.y)),\n startAngle: Math.atan2(b.y - a.y, b.x - a.x),\n startScale: annotation.scale,\n startRotation: annotation.rotation,\n };\n }\n\n private updateGesture(): void {\n const g = this.gesture;\n if (!g || this.pointers.size < 2) return;\n const [a, b] = [...this.pointers.values()];\n const annotation = this.annotations[g.index];\n if (!annotation || annotation.kind === \"freehand\") return;\n const distance = Math.hypot(b.x - a.x, b.y - a.y);\n annotation.scale = round4(clamp(g.startScale * (distance / g.startDistance), MIN_SCALE, MAX_SCALE));\n if (annotation.kind !== \"text\") {\n annotation.rotation = round4(g.startRotation + (Math.atan2(b.y - a.y, b.x - a.x) - g.startAngle));\n }\n this.render();\n }\n\n private openTextInput(p: Point): void {\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.className = \"fk-text-input\";\n input.placeholder = \"Add a note…\";\n input.setAttribute(\"aria-label\", \"Annotation text\");\n input.dataset.origin = JSON.stringify(this.normalize(p));\n input.style.left = `${Math.min(p.x * this.displayScale, this.shot.width * this.displayScale - 130)}px`;\n input.style.top = `${Math.min(p.y * this.displayScale, this.shot.height * this.displayScale - 36)}px`;\n input.style.borderColor = this.color;\n input.addEventListener(\"keydown\", (e) => {\n e.stopPropagation();\n if (e.key === \"Enter\") this.commitTextInput();\n else if (e.key === \"Escape\") this.cancelTextInput();\n });\n input.addEventListener(\"blur\", () => this.commitTextInput());\n this.element.append(input);\n this.textInput = input;\n requestAnimationFrame(() => input.focus());\n }\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, v));\n}\n\nfunction round4(v: number): number {\n return Math.round(v * 10000) / 10000;\n}\n\n","/**\n * Widget CSS, scoped inside the host's Shadow DOM so neither the page's\n * styles nor ours leak across. `:host { all: initial }` also blocks inherited\n * properties (font, color, line-height) from the page.\n */\nexport const styles = /* css */ `\n:host {\n all: initial;\n --fk-primary: #007aff;\n --fk-secondary: #6b7280;\n --fk-bg: #ffffff;\n --fk-surface: #f5f5f7;\n --fk-border: rgba(0, 0, 0, 0.1);\n --fk-text: #111114;\n --fk-muted: #6b6b73;\n --fk-danger: #d92d20;\n --fk-backdrop: rgba(10, 10, 14, 0.55);\n --fk-shadow: 0 24px 64px rgba(0, 0, 0, 0.28), 0 2px 8px rgba(0, 0, 0, 0.12);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n font-size: 14px;\n line-height: 1.4;\n color: var(--fk-text);\n}\n@media (prefers-color-scheme: dark) {\n :host(:not([data-color-scheme=\"light\"])) {\n --fk-bg: #1c1c1f;\n --fk-surface: #26262a;\n --fk-border: rgba(255, 255, 255, 0.12);\n --fk-text: #f2f2f5;\n --fk-muted: #a0a0a8;\n --fk-backdrop: rgba(0, 0, 0, 0.65);\n }\n}\n:host([data-color-scheme=\"dark\"]) {\n --fk-bg: #1c1c1f;\n --fk-surface: #26262a;\n --fk-border: rgba(255, 255, 255, 0.12);\n --fk-text: #f2f2f5;\n --fk-muted: #a0a0a8;\n --fk-backdrop: rgba(0, 0, 0, 0.65);\n}\n*, *::before, *::after { box-sizing: border-box; }\nbutton { font: inherit; color: inherit; cursor: pointer; }\nbutton:disabled { cursor: not-allowed; opacity: 0.45; }\n:focus-visible { outline: 2px solid var(--fk-primary); outline-offset: 2px; }\n\n/* ---------- floating trigger ---------- */\n.fk-trigger {\n position: fixed;\n z-index: 2147483000;\n bottom: 20px;\n right: 20px;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 44px;\n padding: 0 16px 0 14px;\n border: 0;\n border-radius: 22px;\n background: var(--fk-primary);\n color: #fff;\n font-weight: 600;\n font-size: 14px;\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);\n transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;\n}\n.fk-trigger[data-position=\"bottom-left\"] { right: auto; left: 20px; }\n.fk-trigger:hover { transform: translateY(-1px); box-shadow: 0 10px 26px rgba(0, 0, 0, 0.26); }\n.fk-trigger[data-compact=\"true\"] { width: 48px; height: 48px; padding: 0; justify-content: center; border-radius: 24px; }\n.fk-trigger[data-compact=\"true\"] .fk-trigger-label { display: none; }\n.fk-trigger[aria-busy=\"true\"] { opacity: 0.6; pointer-events: none; }\n.fk-trigger-hint {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%) translateY(4px);\n background: rgba(17, 17, 20, 0.92);\n color: #ffffff;\n padding: 4px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n line-height: 1.2;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.15s ease, transform 0.15s ease;\n box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);\n letter-spacing: 0.02em;\n}\n.fk-trigger-hint::after {\n content: \"\";\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 4px solid transparent;\n border-top-color: rgba(17, 17, 20, 0.92);\n}\n.fk-trigger:hover .fk-trigger-hint,\n.fk-trigger:focus-visible .fk-trigger-hint {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n}\n\n/* ---------- overlay ---------- */\n.fk-overlay {\n position: fixed;\n inset: 0;\n z-index: 2147483001;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: var(--fk-backdrop);\n animation: fk-fade 0.16s ease-out;\n}\n@keyframes fk-fade { from { opacity: 0; } to { opacity: 1; } }\n@keyframes fk-rise { from { opacity: 0; transform: translateY(8px) scale(0.99); } to { opacity: 1; transform: none; } }\n.fk-dialog {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 340px;\n width: min(1180px, 100%);\n height: min(780px, 100%);\n overflow: hidden;\n border-radius: 16px;\n background: var(--fk-bg);\n box-shadow: var(--fk-shadow);\n animation: fk-rise 0.2s ease-out;\n}\n.fk-stage {\n display: flex;\n flex-direction: column;\n min-width: 0;\n min-height: 0;\n background: var(--fk-surface);\n border-right: 1px solid var(--fk-border);\n}\n.fk-toolbar {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n padding: 10px 12px;\n border-bottom: 1px solid var(--fk-border);\n}\n.fk-toolbar-sep { width: 1px; height: 22px; margin: 0 6px; background: var(--fk-border); }\n.fk-tool {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n height: 34px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: var(--fk-muted);\n}\n.fk-tool:hover:not(:disabled) { background: var(--fk-border); color: var(--fk-text); }\n.fk-tool[aria-pressed=\"true\"] { background: var(--fk-primary); color: #fff; }\n.fk-swatch {\n width: 22px;\n height: 22px;\n margin: 0 2px;\n padding: 0;\n border-radius: 11px;\n border: 2px solid var(--fk-bg);\n box-shadow: 0 0 0 1px var(--fk-border);\n}\n.fk-swatch[aria-pressed=\"true\"] { box-shadow: 0 0 0 2px var(--fk-text); }\n/* Shrinks (with an ellipsis) instead of wrapping onto its own line: hints\n differ in length per tool, and a toolbar that changed height on every tool\n switch would make the screenshot below jump mid-annotation. */\n.fk-hint { flex: 1 1 0; min-width: 0; margin-left: auto; text-align: right; font-size: 12px; color: var(--fk-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.fk-canvas-wrap {\n position: relative;\n flex: 1;\n min-height: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n overflow: hidden;\n}\n.fk-canvas-box { position: relative; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18); border-radius: 6px; overflow: hidden; }\n.fk-canvas-box canvas { display: block; }\n.fk-canvas-box .fk-ink { position: absolute; inset: 0; touch-action: none; }\n.fk-stage[data-screenshot=\"off\"] .fk-canvas-box { opacity: 0.25; filter: grayscale(1); }\n.fk-stage[data-screenshot=\"off\"] .fk-toolbar button { pointer-events: none; opacity: 0.35; }\n.fk-off-note {\n position: absolute;\n inset: 0;\n display: none;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n color: var(--fk-muted);\n pointer-events: none;\n}\n.fk-stage[data-screenshot=\"off\"] .fk-off-note { display: flex; }\n.fk-text-input {\n position: absolute;\n z-index: 2;\n min-width: 120px;\n padding: 6px 8px;\n border: 2px solid var(--fk-primary);\n border-radius: 8px;\n background: var(--fk-bg);\n color: var(--fk-text);\n font: bold 14px -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n outline: none;\n}\n\n/* ---------- composer ---------- */\n.fk-composer { display: flex; flex-direction: column; min-height: 0; padding: 18px; gap: 14px; overflow-y: auto; }\n.fk-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n.fk-title { margin: 0; font-size: 17px; font-weight: 650; letter-spacing: -0.01em; }\n.fk-close { display: inline-flex; width: 30px; height: 30px; align-items: center; justify-content: center; border: 0; border-radius: 15px; background: var(--fk-surface); color: var(--fk-muted); }\n.fk-close:hover { color: var(--fk-text); }\n.fk-label { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 600; color: var(--fk-muted); text-transform: uppercase; letter-spacing: 0.04em; }\n.fk-textarea {\n width: 100%;\n min-height: 140px;\n resize: vertical;\n padding: 10px 12px;\n border: 1px solid var(--fk-border);\n border-radius: 10px;\n background: var(--fk-bg);\n color: var(--fk-text);\n font: inherit;\n line-height: 1.45;\n}\n.fk-textarea:focus { outline: none; border-color: var(--fk-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--fk-primary) 22%, transparent); }\n.fk-chips { display: flex; flex-wrap: wrap; gap: 6px; }\n.fk-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 28px;\n padding: 0 11px;\n border: 1px solid var(--fk-border);\n border-radius: 14px;\n background: var(--fk-bg);\n font-size: 13px;\n}\n.fk-chip[aria-pressed=\"true\"] { border-color: var(--fk-primary); background: color-mix(in srgb, var(--fk-primary) 12%, transparent); color: var(--fk-primary); font-weight: 600; }\n.fk-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n.fk-switch { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; user-select: none; }\n.fk-switch input { position: absolute; opacity: 0; width: 0; height: 0; }\n.fk-switch-track { position: relative; width: 36px; height: 22px; border-radius: 11px; background: var(--fk-border); transition: background 0.15s; }\n.fk-switch-track::after { content: \"\"; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 9px; background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); transition: transform 0.15s; }\n.fk-switch input:checked + .fk-switch-track { background: var(--fk-primary); }\n.fk-switch input:checked + .fk-switch-track::after { transform: translateX(14px); }\n.fk-switch input:focus-visible + .fk-switch-track { outline: 2px solid var(--fk-primary); outline-offset: 2px; }\n.fk-attach {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 32px;\n padding: 0 12px;\n border: 1px dashed var(--fk-secondary);\n border-radius: 8px;\n background: transparent;\n color: var(--fk-secondary);\n font-size: 13px;\n}\n.fk-options-left { display: flex; align-items: center; gap: 8px; min-width: 0; }\n.fk-menu-anchor { position: relative; display: inline-flex; }\n.fk-plus { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 1px dashed var(--fk-secondary); border-radius: 8px; background: transparent; color: var(--fk-secondary); cursor: pointer; }\n.fk-options-summary { font-size: 12px; color: var(--fk-muted); white-space: nowrap; }\n.fk-menu { position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 5; min-width: 230px; padding: 4px; border: 1px solid var(--fk-border); border-radius: 10px; background: var(--fk-bg); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); }\n.fk-menu-item { display: flex; align-items: center; gap: 6px; width: 100%; padding: 7px 10px 7px 6px; border: 0; border-radius: 6px; background: transparent; color: var(--fk-text); font-size: 13px; text-align: left; cursor: pointer; }\n.fk-menu-item:hover, .fk-menu-item:focus-visible { background: var(--fk-surface); outline: none; }\n.fk-menu-check { display: inline-flex; width: 16px; height: 16px; color: var(--fk-primary); }\n.fk-menu-check svg { width: 16px; height: 16px; }\n.fk-menu-sep { margin: 4px 0; border: 0; border-top: 1px solid var(--fk-border); }\n.fk-file { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 4px 6px 4px 10px; border-radius: 8px; background: var(--fk-surface); font-size: 12px; }\n.fk-file span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.fk-file button { display: inline-flex; border: 0; background: transparent; color: var(--fk-muted); padding: 2px; }\n.fk-meta { font-size: 12px; color: var(--fk-muted); }\n.fk-meta details summary { cursor: pointer; }\n.fk-meta pre { max-height: 140px; overflow: auto; margin: 6px 0 0; padding: 8px; border-radius: 8px; background: var(--fk-surface); font-size: 11px; white-space: pre-wrap; word-break: break-word; }\n.fk-spacer { flex: 1; }\n.fk-actions { display: flex; gap: 8px; }\n.fk-btn {\n display: inline-flex;\n flex: 1;\n align-items: center;\n justify-content: center;\n gap: 7px;\n height: 40px;\n border-radius: 10px;\n font-weight: 600;\n}\n.fk-btn-secondary { border: 1px solid var(--fk-border); background: transparent; color: var(--fk-secondary); }\n.fk-btn-primary { border: 0; background: var(--fk-primary); color: #fff; }\n.fk-btn-primary:hover:not(:disabled) { filter: brightness(1.06); }\n.fk-error { margin: 0; padding: 8px 10px; border-radius: 8px; background: color-mix(in srgb, var(--fk-danger) 12%, transparent); color: var(--fk-danger); font-size: 13px; }\n.fk-spinner { width: 16px; height: 16px; border: 2px solid rgba(255, 255, 255, 0.45); border-top-color: #fff; border-radius: 50%; animation: fk-spin 0.7s linear infinite; }\n@keyframes fk-spin { to { transform: rotate(360deg); } }\n.fk-done { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; flex: 1; text-align: center; }\n.fk-done-icon { display: inline-flex; width: 48px; height: 48px; align-items: center; justify-content: center; border-radius: 24px; background: var(--fk-primary); color: #fff; }\n.fk-done-icon svg { width: 26px; height: 26px; }\n.fk-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }\n\n/* ---------- \"is it fixed?\" card (fixCard.ts) ---------- */\n.fk-fixcard {\n position: fixed;\n z-index: 2147483000;\n right: 20px;\n bottom: 76px;\n width: min(360px, calc(100vw - 32px));\n max-height: min(640px, calc(100vh - 96px));\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 16px;\n border: 1px solid var(--fk-border);\n border-radius: 16px;\n background: var(--fk-bg);\n box-shadow: var(--fk-shadow);\n animation: fk-rise 0.2s ease-out;\n}\n.fk-fixcard[data-position=\"bottom-left\"] { right: auto; left: 20px; }\n.fk-fixcard > *, .fk-fixcard-actions > * { flex-shrink: 0; }\n.fk-fixcard p { margin: 0; }\n.fk-fixcard-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }\n.fk-fixcard-shot { display: block; width: 100%; max-height: 220px; object-fit: contain; border-radius: 10px; background: var(--fk-surface); }\n.fk-fixcard-quote { font-size: 14px; }\n.fk-fixcard-summary { font-size: 13px; padding: 8px 10px; border-radius: 8px; background: var(--fk-surface); }\n.fk-fixcard-message p { font-size: 13px; }\n.fk-fixcard-question { font-weight: 600; }\n.fk-fixcard-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }\n.fk-fixcard-actions .fk-btn { flex: none; width: 100%; }\n.fk-fixcard-actions .fk-textarea { min-height: 64px; }\n@keyframes fk-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }\n\n/* ---------- narrow screens: stack stage over composer ---------- */\n@media (max-width: 760px) {\n .fk-overlay { padding: 0; }\n .fk-dialog { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) auto; width: 100%; height: 100%; border-radius: 0; }\n .fk-stage { border-right: 0; border-bottom: 1px solid var(--fk-border); }\n .fk-hint { display: none; }\n .fk-canvas-wrap { padding: 10px; }\n .fk-composer { max-height: 55vh; padding: 14px; gap: 10px; }\n .fk-textarea { min-height: 84px; }\n .fk-fixcard, .fk-fixcard[data-position] { right: 16px; left: 16px; width: auto; bottom: 16px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .fk-overlay, .fk-dialog, .fk-fixcard { animation: none; }\n}\n`;\n","import { canvasToPngBlob, captureViewport, type CapturedScreenshot } from \"../capture\";\nimport { collectEnvironment } from \"../environment\";\nimport { submitReport } from \"../submit\";\nimport type {\n CaptureOptions,\n FeedbackAttachment,\n FeedbackEnvironment,\n FeedbackKitConfiguration,\n FeedbackLogEntry,\n FeedbackProduct,\n FeedbackReport,\n FeedbackTheme,\n FeedbackUser,\n FixUpdate,\n} from \"../types\";\nimport { FixCard, type FixCardOutcome } from \"./fixCard\";\nimport { AnnotationEditor, COLORS, type Tool } from \"./editor\";\nimport { icons } from \"./icons\";\nimport { styles } from \"./styles\";\n\nexport interface WidgetDeps {\n configuration(): FeedbackKitConfiguration | null;\n theme(): FeedbackTheme | null;\n products(): Promise<FeedbackProduct[]>;\n defaultProductKey(): string | undefined;\n logs(): FeedbackLogEntry[];\n captureOptions(): CaptureOptions;\n includeScreenshot?(): boolean;\n currentScreen(): string | null;\n /** Reporter identity attached to submitted reports (fixes.ts). */\n identity(): { reporterId: string; user: FeedbackUser | null };\n}\n\nexport interface OpenOptions {\n /** POST the report to the configured endpoint before resolving. */\n submit: boolean;\n /** Called with the finished report (after a successful submit, when `submit` is true). */\n onReport?: (report: FeedbackReport) => void | Promise<void>;\n /** Called if submitting fails. The dialog stays open so the user can retry. */\n onError?: (error: unknown) => void;\n /**\n * Deliver the report somewhere other than the ingestion endpoint — used by\n * \"still broken\", which sends it as a reopen of the original report.\n * Takes precedence over `submit`. Shows the thank-you state like `submit`.\n */\n deliver?: (report: FeedbackReport) => Promise<void>;\n /** Dialog wording overrides (e.g. \"What's still wrong?\" for a reopen). */\n copy?: DialogCopy;\n /** Whether to capture a screenshot for this report. Overrides global settings. */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n}\n\nexport interface DialogCopy {\n title?: string;\n label?: string;\n placeholder?: string;\n thanksTitle?: string;\n thanksBody?: string;\n}\n\nexport interface TriggerOptions {\n position?: \"bottom-right\" | \"bottom-left\";\n /** Button text. Default \"Feedback\". */\n label?: string;\n /** Icon-only round button. */\n compact?: boolean;\n /** Whether to capture a screenshot when triggered. */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n /**\n * Keyboard shortcut to trigger feedback (defaults to true: ⌘⇧F on macOS, Ctrl+Shift+F elsewhere).\n * Pass options to customize the key, or false to disable.\n */\n keyboardShortcut?: boolean | { key?: string };\n /** Alias for `keyboardShortcut`. */\n enableKeyboardShortcut?: boolean;\n}\n\n/** Max attachment size accepted by the composer (base64 in a JSON body grows it by a third). */\nconst MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;\n\nconst TOOLS: { tool: Tool; label: string; icon: string }[] = [\n { tool: \"pen\", label: \"Draw\", icon: icons.pen },\n { tool: \"rectangle\", label: \"Rectangle\", icon: icons.rectangle },\n { tool: \"arrow\", label: \"Arrow\", icon: icons.arrow },\n { tool: \"text\", label: \"Text\", icon: icons.text },\n { tool: \"move\", label: \"Move / resize\", icon: icons.move },\n];\n\nconst HINTS: Record<Tool, string> = {\n pen: \"Draw on the screenshot to highlight the problem\",\n rectangle: \"Drag to box an area\",\n arrow: \"Drag to point at something\",\n text: \"Click to add a note\",\n move: \"Drag to move · scroll to resize · Shift+scroll to rotate · Delete to remove\",\n};\n\n/**\n * Owns the widget's Shadow DOM host: the floating trigger button and the\n * capture → annotate → describe → send dialog. One per page.\n */\nexport class Widget {\n private host: HTMLElement | null = null;\n private shadow: ShadowRoot | null = null;\n private trigger: HTMLButtonElement | null = null;\n private pending: Promise<FeedbackReport | null> | null = null;\n private fixCard: FixCard | null = null;\n\n constructor(private readonly deps: WidgetDeps) {}\n\n get isShowingFixCard(): boolean {\n return this.fixCard !== null;\n }\n\n /**\n * The non-modal \"is it fixed?\" card (bottom corner). Resolves with what\n * the reporter chose; the card removes itself.\n */\n showFixCard(update: FixUpdate): Promise<FixCardOutcome> {\n this.fixCard?.remove();\n const shadow = this.mount();\n return new Promise((resolve) => {\n this.fixCard = new FixCard(shadow, update, (outcome) => {\n this.fixCard = null;\n resolve(outcome);\n });\n this.fixCard.show(this.trigger?.dataset.position === \"bottom-left\" ? \"bottom-left\" : \"bottom-right\");\n });\n }\n\n hideFixCard(): void {\n this.fixCard?.dismiss();\n }\n\n /** True for the widget's own host element — used to keep it out of screenshots. */\n isOwnNode = (node: Node): boolean => node === this.host;\n\n get isOpen(): boolean {\n return this.pending !== null;\n }\n\n showTrigger(options: TriggerOptions, onClick: () => void): void {\n const shadow = this.mount();\n this.trigger?.remove();\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"fk-trigger\";\n button.dataset.position = options.position ?? \"bottom-right\";\n button.dataset.compact = String(!!options.compact);\n const label = options.label ?? \"Feedback\";\n const isMac = typeof navigator !== \"undefined\" && /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);\n const shortcutLabel = isMac ? \"⌘⇧F\" : \"Ctrl+Shift+F\";\n button.title = `${label} (${shortcutLabel})`;\n button.setAttribute(\"aria-label\", `${label} (${shortcutLabel})`);\n button.setAttribute(\"aria-keyshortcuts\", isMac ? \"Meta+Shift+F\" : \"Control+Shift+F\");\n button.innerHTML = `${icons.feedback}<span class=\"fk-trigger-label\"></span><span class=\"fk-trigger-hint\" aria-hidden=\"true\">${shortcutLabel}</span>`;\n (button.querySelector(\".fk-trigger-label\") as HTMLElement).textContent = label;\n button.addEventListener(\"click\", onClick);\n shadow.append(button);\n this.trigger = button;\n this.applyTheme();\n }\n\n hideTrigger(): void {\n this.trigger?.remove();\n this.trigger = null;\n }\n\n destroy(): void {\n this.hideTrigger();\n this.fixCard?.remove();\n this.fixCard = null;\n this.host?.remove();\n this.host = null;\n this.shadow = null;\n }\n\n open(options: OpenOptions): Promise<FeedbackReport | null> {\n if (this.pending) return this.pending;\n this.pending = this.run(options).finally(() => {\n this.pending = null;\n });\n return this.pending;\n }\n\n private mount(): ShadowRoot {\n if (this.shadow && this.host?.isConnected) return this.shadow;\n const host = document.createElement(\"div\");\n host.setAttribute(\"data-feedbackkit-root\", \"\");\n // The host itself takes no space; everything inside is position: fixed.\n host.style.cssText = \"position:static!important;display:contents!important;\";\n const shadow = host.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = styles;\n shadow.append(style);\n document.body.append(host);\n this.host = host;\n this.shadow = shadow;\n this.applyTheme();\n return shadow;\n }\n\n private applyTheme(): void {\n const theme = this.deps.theme();\n const host = this.host;\n if (!host) return;\n const primary = validHex(theme?.primaryColorHex);\n const secondary = validHex(theme?.secondaryColorHex);\n if (primary) host.style.setProperty(\"--fk-primary\", primary);\n else host.style.removeProperty(\"--fk-primary\");\n if (secondary) host.style.setProperty(\"--fk-secondary\", secondary);\n else host.style.removeProperty(\"--fk-secondary\");\n }\n\n private shouldCaptureScreenshot(options: OpenOptions, captureOptions: CaptureOptions): boolean {\n if (options.captureScreenshot !== undefined) return options.captureScreenshot;\n if (options.includeScreenshot !== undefined) return options.includeScreenshot;\n if (captureOptions.enabled !== undefined) return captureOptions.enabled;\n if (captureOptions.includeScreenshot !== undefined) return captureOptions.includeScreenshot;\n if (captureOptions.mode === \"off\") return false;\n if (this.deps.includeScreenshot && !this.deps.includeScreenshot()) return false;\n const config = this.deps.configuration();\n if (config) {\n if (typeof config.captureScreenshot === \"boolean\") return config.captureScreenshot;\n if (typeof config.captureScreenshot === \"object\" && config.captureScreenshot !== null) {\n if (config.captureScreenshot.enabled !== undefined) return config.captureScreenshot.enabled;\n if (config.captureScreenshot.includeScreenshot !== undefined) return config.captureScreenshot.includeScreenshot;\n if (config.captureScreenshot.mode === \"off\") return false;\n }\n if (config.includeScreenshot !== undefined) return config.includeScreenshot;\n }\n return true;\n }\n\n private async run(options: OpenOptions): Promise<FeedbackReport | null> {\n const shadow = this.mount();\n this.applyTheme();\n\n const captureOptions = this.deps.captureOptions();\n const shouldCapture = this.shouldCaptureScreenshot(options, captureOptions);\n if (shouldCapture) {\n this.trigger?.setAttribute(\"aria-busy\", \"true\");\n }\n\n // Everything describing \"the moment of the problem\" is taken *before*\n // the dialog covers the page.\n const [shot, environment] = await Promise.all([\n shouldCapture\n ? captureViewport({ ...captureOptions, exclude: this.isOwnNode }).catch((error: unknown) => {\n console.warn(\"[FeedbackKit] Screenshot capture failed; continuing without one.\", error);\n return null;\n })\n : Promise.resolve(null),\n collectEnvironment({\n screenName: this.deps.currentScreen(),\n appVersion: this.deps.configuration()?.appVersion,\n appBuild: this.deps.configuration()?.appBuild,\n }),\n ]);\n const logs = this.deps.logs();\n this.trigger?.removeAttribute(\"aria-busy\");\n\n return new Promise<FeedbackReport | null>((resolve) => {\n const dialog = new Dialog(\n shadow,\n shot,\n environment,\n logs,\n this.deps,\n options,\n !shouldCapture,\n (result) => {\n resolve(result);\n },\n );\n dialog.show();\n });\n }\n}\n\n/** One open feedback dialog. Resolves exactly once via `done`. */\nclass Dialog {\n private overlay!: HTMLDivElement;\n private editor: AnnotationEditor | null = null;\n private textarea!: HTMLTextAreaElement;\n private sendButton!: HTMLButtonElement;\n private errorBox!: HTMLParagraphElement;\n private stage!: HTMLDivElement;\n private includeScreenshot: boolean;\n private includeLogs = true;\n /** \"Notify me when it's fixed\" — off by default, like the native composers. */\n private notifyReporter = false;\n private optionsMenu: HTMLDivElement | null = null;\n private readonly onPointerDownOutsideMenu = (e: PointerEvent) => {\n const anchor = this.optionsMenu?.parentElement;\n if (anchor && !e.composedPath().includes(anchor)) this.closeOptionsMenu();\n };\n private attachment: FeedbackAttachment | null = null;\n private selectedProducts = new Set<string>();\n private products: FeedbackProduct[] = [];\n private sending = false;\n private finished = false;\n private resizeObserver: ResizeObserver | null = null;\n private previousFocus: Element | null = null;\n private previousOverflow = \"\";\n private toolButtons = new Map<Tool, HTMLButtonElement>();\n private swatches: HTMLButtonElement[] = [];\n private undoButton!: HTMLButtonElement;\n private clearButton!: HTMLButtonElement;\n private hint!: HTMLSpanElement;\n private readonly onKeyDown = (e: KeyboardEvent) => this.handleKey(e);\n\n constructor(\n private readonly shadow: ShadowRoot,\n private readonly shot: CapturedScreenshot | null,\n private readonly environment: FeedbackEnvironment,\n private readonly logs: FeedbackLogEntry[],\n private readonly deps: WidgetDeps,\n private readonly options: OpenOptions,\n private readonly screenshotDisabled: boolean,\n private readonly done: (report: FeedbackReport | null) => void,\n ) {\n if (this.screenshotDisabled || !shot) {\n this.includeScreenshot = false;\n } else if (options.includeScreenshot !== undefined) {\n this.includeScreenshot = options.includeScreenshot;\n } else {\n this.includeScreenshot = true;\n }\n }\n\n show(): void {\n this.previousFocus = document.activeElement;\n this.previousOverflow = document.documentElement.style.overflow;\n document.documentElement.style.overflow = \"hidden\";\n\n const overlay = el(\"div\", \"fk-overlay\");\n const dialog = el(\"div\", \"fk-dialog\");\n dialog.setAttribute(\"role\", \"dialog\");\n dialog.setAttribute(\"aria-modal\", \"true\");\n dialog.setAttribute(\"aria-labelledby\", \"fk-title\");\n dialog.append(this.buildStage(), this.buildComposer());\n overlay.append(dialog);\n overlay.addEventListener(\"mousedown\", (e) => {\n if (e.target === overlay) this.cancel();\n });\n this.overlay = overlay;\n this.shadow.append(overlay);\n // One capture-phase listener on the document sees keys from inside the\n // shadow root too (they're retargeted, not stopped), so the dialog\n // behaves modally without double-handling.\n document.addEventListener(\"keydown\", this.onKeyDown, true);\n\n this.layoutEditor();\n requestAnimationFrame(() => this.textarea.focus());\n void this.loadProducts();\n }\n\n // ---------------------------------------------------------------- stage\n\n private buildStage(): HTMLElement {\n const stage = el(\"div\", \"fk-stage\");\n this.stage = stage;\n stage.dataset.screenshot = this.includeScreenshot ? \"on\" : \"off\";\n\n const toolbar = el(\"div\", \"fk-toolbar\");\n toolbar.setAttribute(\"role\", \"toolbar\");\n toolbar.setAttribute(\"aria-label\", \"Annotation tools\");\n for (const { tool, label, icon } of TOOLS) {\n const b = iconButton(\"fk-tool\", icon, label);\n b.setAttribute(\"aria-pressed\", String(tool === \"pen\"));\n b.addEventListener(\"click\", () => this.selectTool(tool));\n this.toolButtons.set(tool, b);\n toolbar.append(b);\n }\n toolbar.append(el(\"span\", \"fk-toolbar-sep\"));\n COLORS.forEach((color, i) => {\n const b = document.createElement(\"button\");\n b.type = \"button\";\n b.className = \"fk-swatch\";\n b.style.background = color;\n b.setAttribute(\"aria-label\", `Color ${[\"red\", \"yellow\", \"green\", \"blue\", \"black\"][i]}`);\n b.setAttribute(\"aria-pressed\", String(i === 0));\n b.addEventListener(\"click\", () => {\n if (this.editor) this.editor.color = color;\n this.swatches.forEach((s) => s.setAttribute(\"aria-pressed\", String(s === b)));\n });\n this.swatches.push(b);\n toolbar.append(b);\n });\n toolbar.append(el(\"span\", \"fk-toolbar-sep\"));\n this.undoButton = iconButton(\"fk-tool\", icons.undo, \"Undo\");\n this.undoButton.addEventListener(\"click\", () => this.editor?.undo());\n this.clearButton = iconButton(\"fk-tool\", icons.trash, \"Clear all annotations\");\n this.clearButton.addEventListener(\"click\", () => this.editor?.clear());\n toolbar.append(this.undoButton, this.clearButton);\n this.hint = el(\"span\", \"fk-hint\");\n this.hint.textContent = HINTS.pen;\n this.hint.title = HINTS.pen;\n toolbar.append(this.hint);\n\n const wrap = el(\"div\", \"fk-canvas-wrap\");\n if (this.shot) {\n const editor = new AnnotationEditor(this.shot);\n editor.onChange = () => this.refreshState();\n editor.setTool(\"pen\");\n this.editor = editor;\n wrap.append(editor.element);\n this.resizeObserver = new ResizeObserver(() => this.layoutEditor());\n this.resizeObserver.observe(wrap);\n }\n const note = el(\"div\", \"fk-off-note\");\n note.textContent = this.shot || this.screenshotDisabled\n ? \"Screenshot won't be included\"\n : \"Screenshot unavailable on this page\";\n wrap.append(note);\n stage.append(toolbar, wrap);\n return stage;\n }\n\n private layoutEditor(): void {\n if (!this.editor) return;\n const wrap = this.editor.element.parentElement;\n if (!wrap) return;\n const styles = getComputedStyle(wrap);\n const padX = parseFloat(styles.paddingLeft) + parseFloat(styles.paddingRight);\n const padY = parseFloat(styles.paddingTop) + parseFloat(styles.paddingBottom);\n this.editor.layout(Math.max(40, wrap.clientWidth - padX), Math.max(40, wrap.clientHeight - padY));\n }\n\n private selectTool(tool: Tool): void {\n this.editor?.setTool(tool);\n this.toolButtons.forEach((b, t) => b.setAttribute(\"aria-pressed\", String(t === tool)));\n this.hint.textContent = HINTS[tool];\n this.hint.title = HINTS[tool];\n }\n\n // ---------------------------------------------------------------- composer\n\n private buildComposer(): HTMLElement {\n const composer = el(\"div\", \"fk-composer\");\n\n const header = el(\"div\", \"fk-header\");\n const title = el(\"h2\", \"fk-title\");\n title.id = \"fk-title\";\n title.textContent = this.options.copy?.title ?? \"Send feedback\";\n const close = iconButton(\"fk-close\", icons.close, \"Close\");\n close.addEventListener(\"click\", () => this.cancel());\n header.append(title, close);\n\n let renderAttachment = () => {};\n const attachFile = (file: File) => {\n if (file.size > MAX_ATTACHMENT_BYTES) {\n this.showError(`\"${file.name}\" is larger than 10 MB.`);\n return;\n }\n this.attachment = { filename: file.name, mimeType: file.type || \"application/octet-stream\", data: file };\n renderAttachment();\n };\n\n const textLabel = el(\"label\", \"fk-label\");\n textLabel.textContent = this.options.copy?.label ?? \"What's the problem?\";\n textLabel.setAttribute(\"for\", \"fk-text\");\n this.textarea = document.createElement(\"textarea\");\n this.textarea.id = \"fk-text\";\n this.textarea.className = \"fk-textarea\";\n this.textarea.placeholder = this.options.copy?.placeholder ?? \"Describe what happened and what you expected instead…\";\n this.textarea.addEventListener(\"input\", () => this.refreshState());\n this.textarea.addEventListener(\"paste\", (e: ClipboardEvent) => {\n const items = e.clipboardData?.items;\n if (!items || items.length === 0) return;\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n let filename = file.name;\n if (!filename || filename === \"image.png\") {\n const ext = file.type.startsWith(\"image/\") ? file.type.split(\"/\")[1] || \"png\" : \"bin\";\n filename = `clipboard-${Date.now()}.${ext}`;\n }\n const attached = new File([file], filename, { type: file.type || \"application/octet-stream\" });\n attachFile(attached);\n e.preventDefault();\n break;\n }\n }\n }\n });\n const textGroup = el(\"div\");\n textGroup.append(textLabel, this.textarea);\n\n const productsGroup = el(\"div\");\n productsGroup.dataset.role = \"products\";\n productsGroup.hidden = true;\n\n // One \"+\" button opens a menu with the ways to attach and \"notify me\".\n // The screenshot switch sits in the composer itself rather than in that\n // menu (unlike the iOS/macOS composers): the web panel has the room, and\n // reporters didn't find it behind the \"+\".\n const optionsRow = el(\"div\", \"fk-row\");\n const fileInput = document.createElement(\"input\");\n fileInput.type = \"file\";\n fileInput.hidden = true;\n // `capture` opens the camera on phones and tablets; desktop browsers ignore it.\n const cameraInput = document.createElement(\"input\");\n cameraInput.type = \"file\";\n cameraInput.accept = \"image/*\";\n cameraInput.setAttribute(\"capture\", \"environment\");\n cameraInput.hidden = true;\n const onFile = (input: HTMLInputElement) => {\n const file = input.files?.[0];\n input.value = \"\";\n if (!file) return;\n attachFile(file);\n };\n fileInput.addEventListener(\"change\", () => onFile(fileInput));\n cameraInput.addEventListener(\"change\", () => onFile(cameraInput));\n\n const menuAnchor = el(\"div\", \"fk-menu-anchor\");\n const menuButton = iconButton(\"fk-plus\", icons.plus, \"Options and attachments\");\n menuButton.setAttribute(\"aria-haspopup\", \"menu\");\n menuButton.setAttribute(\"aria-expanded\", \"false\");\n menuButton.addEventListener(\"click\", () => (this.optionsMenu ? this.closeOptionsMenu() : openMenu()));\n const summary = el(\"span\", \"fk-options-summary\");\n const renderSummary = () => {\n const parts: string[] = [];\n if (!this.shot) parts.push(\"No screenshot\");\n if (this.notifyReporter) parts.push(\"Notify me\");\n summary.textContent = parts.join(\" · \");\n };\n\n const openMenu = () => {\n const menu = el(\"div\", \"fk-menu\");\n menu.setAttribute(\"role\", \"menu\");\n const item = (label: string, onSelect: () => void, checked?: boolean) => {\n const b = document.createElement(\"button\");\n b.type = \"button\";\n b.className = \"fk-menu-item\";\n b.setAttribute(\"role\", checked === undefined ? \"menuitem\" : \"menuitemcheckbox\");\n if (checked !== undefined) b.setAttribute(\"aria-checked\", String(checked));\n b.innerHTML = `<span class=\"fk-menu-check\">${checked ? icons.check : \"\"}</span><span></span>`;\n b.lastElementChild!.textContent = label;\n b.addEventListener(\"click\", () => {\n this.closeOptionsMenu();\n onSelect();\n });\n return b;\n };\n menu.append(item(\"Attach file…\", () => fileInput.click()));\n if (window.matchMedia?.(\"(pointer: coarse)\").matches) menu.append(item(\"Take photo\", () => cameraInput.click()));\n menu.append(el(\"hr\", \"fk-menu-sep\"));\n menu.append(\n item(\"Notify me when it's fixed\", () => {\n this.notifyReporter = !this.notifyReporter;\n renderSummary();\n }, this.notifyReporter),\n );\n menuAnchor.append(menu);\n menuButton.setAttribute(\"aria-expanded\", \"true\");\n this.optionsMenu = menu;\n this.overlay.addEventListener(\"pointerdown\", this.onPointerDownOutsideMenu, true);\n (menu.querySelector(\".fk-menu-item\") as HTMLButtonElement | null)?.focus();\n };\n\n const attachGroup = el(\"div\", \"fk-attach-group\");\n renderAttachment = () => {\n attachGroup.replaceChildren();\n if (!this.attachment) return;\n const chip = el(\"span\", \"fk-file\");\n const name = el(\"span\");\n name.textContent = this.attachment.filename;\n const remove = iconButton(\"\", icons.close, `Remove ${this.attachment.filename}`);\n remove.addEventListener(\"click\", () => {\n this.attachment = null;\n renderAttachment();\n });\n chip.append(name, remove);\n attachGroup.append(chip);\n };\n renderAttachment();\n renderSummary();\n menuAnchor.append(menuButton, fileInput, cameraInput);\n const left = el(\"div\", \"fk-options-left\");\n left.append(menuAnchor, attachGroup);\n optionsRow.append(left, summary);\n\n const meta = this.buildDiagnostics();\n\n this.errorBox = el(\"p\", \"fk-error\");\n this.errorBox.setAttribute(\"role\", \"alert\");\n this.errorBox.hidden = true;\n\n const actions = el(\"div\", \"fk-actions\");\n const cancel = document.createElement(\"button\");\n cancel.type = \"button\";\n cancel.className = \"fk-btn fk-btn-secondary\";\n cancel.textContent = \"Cancel\";\n cancel.addEventListener(\"click\", () => this.cancel());\n this.sendButton = document.createElement(\"button\");\n this.sendButton.type = \"button\";\n this.sendButton.className = \"fk-btn fk-btn-primary\";\n this.sendButton.innerHTML = `${icons.send}<span>Send</span>`;\n this.sendButton.title = \"Send (⌘/Ctrl + Enter)\";\n this.sendButton.addEventListener(\"click\", () => void this.send());\n actions.append(cancel, this.sendButton);\n\n composer.append(header, textGroup, productsGroup);\n if (this.shot) {\n composer.append(\n switchControl(\"Include screenshot\", this.includeScreenshot, (on) => {\n this.includeScreenshot = on;\n this.stage.dataset.screenshot = on ? \"on\" : \"off\";\n this.refreshState();\n }),\n );\n }\n composer.append(optionsRow);\n if (meta) composer.append(meta);\n composer.append(el(\"div\", \"fk-spacer\"), this.errorBox, actions);\n this.refreshState();\n return composer;\n }\n\n /** Shows the user exactly what page context will be sent, with an opt-out for logs. */\n private buildDiagnostics(): HTMLElement | null {\n const box = el(\"div\", \"fk-meta\");\n const env = this.environment;\n const summary = `${env.deviceModel} · ${env.osName} ${env.osVersion}`.trim();\n const details = document.createElement(\"details\");\n const s = document.createElement(\"summary\");\n s.textContent = `Included: page URL, ${summary}${this.logs.length ? `, ${this.logs.length} log entr${this.logs.length === 1 ? \"y\" : \"ies\"}` : \"\"}`;\n const pre = document.createElement(\"pre\");\n const lines = [`URL: ${env.pageUrl ?? \"\"}`, `Viewport: ${env.screenWidthPoints}×${env.screenHeightPoints} @${env.screenScale}x`];\n if (this.logs.length) {\n lines.push(\"\", ...this.logs.map((l) => `[${l.level}] ${l.message}`));\n }\n pre.textContent = lines.join(\"\\n\");\n details.append(s, pre);\n box.append(details);\n if (this.logs.length) {\n const logsToggle = switchControl(\"Include console & network logs\", true, (on) => {\n this.includeLogs = on;\n });\n logsToggle.style.marginTop = \"8px\";\n box.append(logsToggle);\n }\n return box;\n }\n\n private async loadProducts(): Promise<void> {\n let products: FeedbackProduct[] = [];\n try {\n products = await this.deps.products();\n } catch {\n return; // Products are optional; the composer works without them.\n }\n if (this.finished || products.length === 0) return;\n this.products = products;\n const preferred = this.deps.defaultProductKey();\n const initial =\n (preferred && products.find((p) => p.key === preferred)) || products.find((p) => p.isDefault) || null;\n if (initial) this.selectedProducts.add(initial.key);\n\n const group = this.overlay.querySelector('[data-role=\"products\"]') as HTMLElement | null;\n if (!group) return;\n const label = el(\"span\", \"fk-label\");\n label.textContent = \"Affected product\";\n const chips = el(\"div\", \"fk-chips\");\n chips.setAttribute(\"role\", \"group\");\n chips.setAttribute(\"aria-label\", \"Affected products\");\n for (const product of products) {\n const chip = document.createElement(\"button\");\n chip.type = \"button\";\n chip.className = \"fk-chip\";\n chip.textContent = product.name || product.key;\n if (product.description) chip.title = product.description;\n chip.setAttribute(\"aria-pressed\", String(this.selectedProducts.has(product.key)));\n chip.addEventListener(\"click\", () => {\n if (this.selectedProducts.has(product.key)) this.selectedProducts.delete(product.key);\n else this.selectedProducts.add(product.key);\n chip.setAttribute(\"aria-pressed\", String(this.selectedProducts.has(product.key)));\n });\n chips.append(chip);\n }\n group.replaceChildren(label, chips);\n group.hidden = false;\n }\n\n private refreshState(): void {\n const hasText = this.textarea?.value.trim().length > 0;\n const hasMarks = this.includeScreenshot && (this.editor?.annotations.length ?? 0) > 0;\n if (this.sendButton) this.sendButton.disabled = this.sending || (!hasText && !hasMarks);\n if (this.undoButton) this.undoButton.disabled = !this.editor?.canUndo;\n if (this.clearButton) this.clearButton.disabled = !(this.editor && this.editor.annotations.length > 0);\n }\n\n private closeOptionsMenu(): void {\n this.optionsMenu?.remove();\n this.optionsMenu = null;\n this.overlay?.removeEventListener(\"pointerdown\", this.onPointerDownOutsideMenu, true);\n this.overlay?.querySelector(\".fk-plus\")?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n // ---------------------------------------------------------------- keyboard\n\n private handleKey(e: KeyboardEvent): void {\n if (this.finished) return;\n const mod = e.metaKey || e.ctrlKey;\n const active = this.shadow.activeElement;\n const typing = active instanceof HTMLTextAreaElement || active instanceof HTMLInputElement;\n // The on-canvas note input handles its own Enter/Escape (commit/cancel the note).\n if (active instanceof HTMLInputElement && active.classList.contains(\"fk-text-input\")) return;\n\n if (e.key === \"Escape\" && this.optionsMenu) {\n e.preventDefault();\n e.stopPropagation();\n this.closeOptionsMenu();\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n this.cancel();\n } else if (mod && e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n void this.send();\n } else if (mod && !e.shiftKey && e.key.toLowerCase() === \"z\" && !typing) {\n e.preventDefault();\n e.stopPropagation();\n this.editor?.undo();\n } else if ((e.key === \"Backspace\" || e.key === \"Delete\") && !typing) {\n if (this.editor?.deleteSelected()) {\n e.preventDefault();\n e.stopPropagation();\n }\n } else if (e.key === \"Tab\") {\n this.trapFocus(e);\n }\n }\n\n private trapFocus(e: KeyboardEvent): void {\n const focusable = [\n ...this.overlay.querySelectorAll<HTMLElement>(\"button:not(:disabled), textarea, input:not([type=file]):not(:disabled), summary\"),\n ].filter((n) => n.offsetParent !== null || n.tagName === \"INPUT\");\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = this.shadow.activeElement;\n if (e.shiftKey && (active === first || !active)) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n }\n\n // ---------------------------------------------------------------- results\n\n private showError(message: string | null): void {\n this.errorBox.hidden = !message;\n this.errorBox.textContent = message ?? \"\";\n }\n\n private async buildReport(): Promise<FeedbackReport> {\n let screenshotRaw: Blob | null = null;\n let screenshotAnnotated: Blob | null = null;\n let annotations: FeedbackReport[\"annotations\"] = [];\n if (this.includeScreenshot && this.shot && this.editor) {\n const flattened = this.editor.flatten();\n [screenshotRaw, screenshotAnnotated] = await Promise.all([\n canvasToPngBlob(this.shot.canvas),\n canvasToPngBlob(flattened),\n ]);\n annotations = this.editor.annotations.map((a) => ({ ...a }));\n }\n return {\n id: uuid(),\n createdAt: new Date(),\n text: this.textarea.value.trim(),\n screenshotRaw,\n screenshotAnnotated,\n annotations,\n environment: this.environment,\n attachment: this.attachment,\n products: this.products.filter((p) => this.selectedProducts.has(p.key)),\n logs: this.includeLogs ? this.logs : [],\n notifyReporter: this.notifyReporter,\n };\n }\n\n private async send(): Promise<void> {\n if (this.sending || this.sendButton.disabled) return;\n this.sending = true;\n this.showError(null);\n this.refreshState();\n this.sendButton.innerHTML = `<span class=\"fk-spinner\" aria-hidden=\"true\"></span><span>Sending…</span>`;\n try {\n const report = await this.buildReport();\n if (this.options.deliver) {\n await this.options.deliver(report);\n } else if (this.options.submit) {\n const configuration = this.deps.configuration();\n if (!configuration) throw new Error(\"FeedbackKit.configure() hasn't been called.\");\n await submitReport(report, configuration, this.deps.identity());\n }\n await this.options.onReport?.(report);\n this.showThanks();\n setTimeout(() => this.finish(report), this.delivers ? 1300 : 0);\n } catch (error) {\n this.sending = false;\n this.sendButton.innerHTML = `${icons.send}<span>Retry</span>`;\n this.showError(error instanceof Error ? error.message : \"Something went wrong sending your feedback.\");\n this.refreshState();\n this.options.onError?.(error);\n }\n }\n\n private get delivers(): boolean {\n return this.options.submit || !!this.options.deliver;\n }\n\n private showThanks(): void {\n if (!this.delivers) return;\n const composer = this.overlay.querySelector(\".fk-composer\");\n if (!composer) return;\n const done = el(\"div\", \"fk-done\");\n done.setAttribute(\"role\", \"status\");\n const icon = el(\"span\", \"fk-done-icon\");\n icon.innerHTML = icons.check;\n const title = el(\"h2\", \"fk-title\");\n title.textContent = this.options.copy?.thanksTitle ?? \"Thanks for the feedback!\";\n const sub = el(\"p\", \"fk-meta\");\n sub.textContent = this.options.copy?.thanksBody ?? \"It's on its way to the team.\";\n done.append(icon, title, sub);\n composer.replaceChildren(done);\n }\n\n private cancel(): void {\n if (this.sending) return;\n this.finish(null);\n }\n\n private finish(result: FeedbackReport | null): void {\n if (this.finished) return;\n this.finished = true;\n this.resizeObserver?.disconnect();\n document.removeEventListener(\"keydown\", this.onKeyDown, true);\n this.overlay.remove();\n document.documentElement.style.overflow = this.previousOverflow;\n if (this.previousFocus instanceof HTMLElement) this.previousFocus.focus({ preventScroll: true });\n this.done(result);\n }\n}\n\n// ------------------------------------------------------------------ helpers\n\nfunction el<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (className) node.className = className;\n return node;\n}\n\nfunction iconButton(className: string, icon: string, label: string): HTMLButtonElement {\n const b = document.createElement(\"button\");\n b.type = \"button\";\n if (className) b.className = className;\n b.innerHTML = icon;\n b.setAttribute(\"aria-label\", label);\n b.title = label;\n return b;\n}\n\nfunction switchControl(label: string, checked: boolean, onChange: (on: boolean) => void): HTMLLabelElement {\n const wrap = el(\"label\", \"fk-switch\");\n const input = document.createElement(\"input\");\n input.type = \"checkbox\";\n input.checked = checked;\n input.setAttribute(\"role\", \"switch\");\n input.addEventListener(\"change\", () => onChange(input.checked));\n const track = el(\"span\", \"fk-switch-track\");\n const text = el(\"span\");\n text.textContent = label;\n wrap.append(input, track, text);\n return wrap;\n}\n\nfunction validHex(hex: string | undefined): string | null {\n if (!hex) return null;\n const cleaned = hex.trim().replace(/^#/, \"\");\n return /^[0-9a-fA-F]{6}$/.test(cleaned) ? `#${cleaned}` : null;\n}\n\nexport function uuid(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","import { canvasToPngBlob, captureViewport } from \"./capture\";\nimport { installLogCapture, setIgnoredUrlPrefix, type LogBuffer, type LogCaptureOptions } from \"./logs\";\nimport { DEFAULT_ENDPOINT, fetchProducts, submitReport } from \"./submit\";\nimport { fetchFixUpdates, getUser, reporterId, sendFixAction, setUser, type FixAction } from \"./fixes\";\nimport type {\n CaptureOptions,\n FeedbackKitConfiguration,\n FeedbackProduct,\n FeedbackReport,\n FeedbackTheme,\n FeedbackUser,\n FixUpdate,\n} from \"./types\";\nimport { Widget, type TriggerOptions } from \"./ui/widget\";\n\nexport type * from \"./types\";\nexport type { TriggerOptions } from \"./ui/widget\";\nexport type { LogCaptureOptions } from \"./logs\";\nexport { FeedbackSubmissionError, DEFAULT_ENDPOINT, encodePayload, type IngestPayload } from \"./submit\";\nexport { parseUserAgent, redactUrl } from \"./environment\";\nexport { compareBuilds, reporterUpdatesEndpoint, type FixAction } from \"./fixes\";\nexport {\n drawAnnotation,\n drawAnnotations,\n hitTest,\n readPoint,\n textBubbleRect,\n STROKE_WIDTH,\n type Point,\n type Size,\n} from \"./renderer\";\n\nexport interface PresentOptions {\n /** Called with the finished report when the user taps Send. */\n onReport?: (report: FeedbackReport) => void | Promise<void>;\n /**\n * Whether to capture and include a screenshot for this report.\n * Set to `false` to open the feedback dialog without a screenshot.\n */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n}\n\nexport interface PresentAndSubmitOptions {\n /** Called after the report has been accepted by the ingestion endpoint. */\n onSubmitted?: (report: FeedbackReport) => void;\n /** Called when a submit attempt fails (the dialog stays open for a retry). */\n onError?: (error: unknown) => void;\n /**\n * Whether to capture and include a screenshot for this report.\n * Set to `false` to open the feedback dialog without a screenshot.\n */\n captureScreenshot?: boolean;\n /** Alias for `captureScreenshot`. */\n includeScreenshot?: boolean;\n}\n\nexport interface ShortcutOptions {\n /** Key to combine with ⌘ (macOS) / Ctrl (elsewhere) + Shift. Default \"F\" — e.g. ⌘⇧F. */\n key?: string;\n}\n\nlet configuration: FeedbackKitConfiguration | null = null;\nlet products: FeedbackProduct[] = [];\nlet productsPromise: Promise<FeedbackProduct[]> | null = null;\nlet logCapture: { buffer: LogBuffer; uninstall: () => void } | null = null;\nlet shortcutHandler: ((e: KeyboardEvent) => void) | null = null;\n\nconst widget = new Widget({\n configuration: () => configuration,\n theme: () => FeedbackKit.theme,\n products: () => resolveProducts(),\n defaultProductKey: () => configuration?.defaultProductKey,\n logs: () => logCapture?.buffer.snapshot() ?? [],\n captureOptions: () => FeedbackKit.captureOptions,\n includeScreenshot: () => FeedbackKit.includeScreenshot,\n currentScreen: () => FeedbackKit.currentScreen,\n identity: () => ({ reporterId: reporterId(), user: getUser() }),\n});\n\n// ---- \"Is it fixed?\" loop (see fixes.ts) --------------------------------\n\n/** Don't hit the network more than this often from page-visibility checks. */\nconst FIX_CHECK_INTERVAL_MS = 60_000;\nlet fixVerificationEnabled = false;\nlet lastFixCheck = 0;\nlet fixCheckInFlight = false;\nconst handledThisPage = new Set<string>();\n\nfunction onVisibilityChange(): void {\n if (document.visibilityState === \"visible\") void checkAndShowFix(false);\n}\n\nasync function checkAndShowFix(force: boolean): Promise<void> {\n const config = configuration;\n if (!fixVerificationEnabled || !config || fixCheckInFlight || widget.isOpen || widget.isShowingFixCard) return;\n if (!force && Date.now() - lastFixCheck < FIX_CHECK_INTERVAL_MS) return;\n fixCheckInFlight = true;\n lastFixCheck = Date.now();\n let next: FixUpdate | undefined;\n try {\n next = (await fetchFixUpdates(config)).find((u) => !handledThisPage.has(u.feedbackId));\n } catch {\n return;\n } finally {\n fixCheckInFlight = false;\n }\n if (!next || !fixVerificationEnabled) return;\n // Resolve once the card is up; the reporter answers in their own time.\n void handleFixCard(config, next);\n}\n\nasync function handleFixCard(config: FeedbackKitConfiguration, update: FixUpdate): Promise<void> {\n const outcome = await widget.showFixCard(update);\n handledThisPage.add(update.feedbackId);\n const send = (action: FixAction) =>\n sendFixAction(config, update.feedbackId, action).catch((error: unknown) =>\n console.warn(\"[FeedbackKit] Couldn't send fix verification.\", error),\n );\n switch (outcome.type) {\n case \"verified\":\n await send({ type: \"verify\" });\n void checkAndShowFix(true);\n break;\n case \"replied\":\n await send({ type: \"reply\", text: outcome.text });\n void checkAndShowFix(true);\n break;\n case \"stillBroken\": {\n // Same capture → annotate flow, delivered as a reopen of the original\n // report so the fix's author sees exactly what's still wrong.\n const report = await widget.open({\n submit: false,\n deliver: (r) => sendFixAction(config, update.feedbackId, { type: \"reopen\", report: r }),\n copy: {\n title: \"Still broken\",\n label: \"What's still wrong?\",\n placeholder: \"Show us on the screenshot and describe what you still see…\",\n thanksTitle: \"Thanks — we're on it\",\n thanksBody: \"Your report was reopened and sent back to the team.\",\n },\n });\n // Closed the dialog without sending: they still said it's broken.\n if (!report) await send({ type: \"reopen\" });\n break;\n }\n case \"later\":\n break;\n }\n}\n\nfunction resolveProducts(): Promise<FeedbackProduct[]> {\n if (products.length > 0 || !configuration) return Promise.resolve(products);\n if (!productsPromise) {\n const config = configuration;\n productsPromise = fetchProducts(config)\n .then((fetched) => {\n if (configuration === config) products = fetched;\n return fetched;\n })\n .catch(() => {\n productsPromise = null; // Retry next time the dialog opens.\n return [];\n });\n }\n return productsPromise;\n}\n\nfunction whenBodyReady(fn: () => void): void {\n if (document.body) fn();\n else document.addEventListener(\"DOMContentLoaded\", fn, { once: true });\n}\n\n/**\n * FeedbackKit for the web — the browser counterpart of the Swift SDK's\n * `FeedbackKit` namespace. Same flow (capture → annotate → describe → a\n * structured `FeedbackReport`), same report shape, same optional delivery\n * to the hosted dashboard.\n */\nexport const FeedbackKit = {\n /**\n * The current screen/page name included in reports. Falls back to\n * `location.pathname` when unset. Set it from your router for nicer names.\n */\n currentScreen: null as string | null,\n\n /** Brand colors for the trigger button and dialog. */\n theme: null as FeedbackTheme | null,\n\n /** Screenshot capture settings. See `CaptureOptions`. */\n captureOptions: {} as CaptureOptions,\n\n /** Whether screenshots should be captured and included in reports by default. Default `true`. */\n includeScreenshot: true,\n\n /** The hosted dashboard's ingestion endpoint, used when `configure` gets no `endpoint`. */\n DEFAULT_ENDPOINT,\n\n /**\n * Configures delivery to the FeedbackKit dashboard (or your own deployment\n * of it). Pass `null` to go back to local-only delivery via `present`.\n * Also starts console/network log capture unless `captureLogs: false`.\n */\n configure(config: FeedbackKitConfiguration | null): void {\n configuration = config ? { ...config, endpoint: config.endpoint ?? DEFAULT_ENDPOINT } : null;\n products = config?.products ?? [];\n productsPromise = null;\n setIgnoredUrlPrefix(configuration?.endpoint ?? null);\n if (configuration && products.length === 0) void resolveProducts();\n if (config && config.captureLogs !== false && !logCapture) {\n FeedbackKit.enableLogCapture(typeof config.captureLogs === \"object\" ? config.captureLogs : {});\n }\n },\n\n get isConfigured(): boolean {\n return configuration !== null;\n },\n\n get configuration(): Readonly<FeedbackKitConfiguration> | null {\n return configuration;\n },\n\n /** Products for the composer's chips — static from `configure`, else fetched from the backend. */\n fetchProducts(): Promise<FeedbackProduct[]> {\n return resolveProducts();\n },\n\n /**\n * Opens the feedback dialog and resolves with the finished report — or\n * `null` if the user cancels. Nothing is sent anywhere; delivery is yours.\n */\n present(options: PresentOptions = {}): Promise<FeedbackReport | null> {\n return widget.open({\n submit: false,\n onReport: options.onReport,\n captureScreenshot: options.captureScreenshot,\n includeScreenshot: options.includeScreenshot,\n });\n },\n\n /**\n * Opens the dialog and, on Send, delivers the report to the configured\n * endpoint (showing progress, errors with retry, and a thank-you state).\n * Resolves with the submitted report, or `null` if cancelled.\n */\n presentAndSubmit(options: PresentAndSubmitOptions = {}): Promise<FeedbackReport | null> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before presentAndSubmit().\"));\n }\n return widget.open({\n submit: true,\n onReport: options.onSubmitted,\n onError: options.onError,\n captureScreenshot: options.captureScreenshot,\n includeScreenshot: options.includeScreenshot,\n });\n },\n\n /** Sends an already-built report (e.g. one from `present`) to the configured endpoint. */\n submit(report: FeedbackReport): Promise<void> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before submit().\"));\n }\n return submitReport(report, configuration, { reporterId: reporterId(), user: getUser() });\n },\n\n get isPresenting(): boolean {\n return widget.isOpen;\n },\n\n /**\n * A floating \"Feedback\" button. Clicking it runs `presentAndSubmit` when\n * configured, otherwise `present` and logs the report to the console.\n */\n showFloatingTriggerButton(options: TriggerOptions = {}): void {\n if (options.keyboardShortcut !== false && options.enableKeyboardShortcut !== false && !shortcutHandler) {\n FeedbackKit.enableKeyboardShortcut(typeof options.keyboardShortcut === \"object\" ? options.keyboardShortcut : {});\n }\n whenBodyReady(() =>\n widget.showTrigger(options, () => {\n const openOptions = {\n captureScreenshot: options.captureScreenshot,\n includeScreenshot: options.includeScreenshot,\n };\n if (configuration) void FeedbackKit.presentAndSubmit(openOptions);\n else void FeedbackKit.present({ ...openOptions, onReport: (r) => console.info(\"[FeedbackKit] report\", r) });\n }),\n );\n },\n\n hideFloatingTriggerButton(): void {\n widget.hideTrigger();\n },\n\n /**\n * The web's stand-in for the native SDKs' shake-to-report: a keyboard\n * shortcut, ⌘⇧F on macOS / Ctrl+Shift+F elsewhere by default.\n */\n enableKeyboardShortcut(options: ShortcutOptions = {}): void {\n FeedbackKit.disableKeyboardShortcut();\n const key = (options.key ?? \"F\").toLowerCase();\n shortcutHandler = (e: KeyboardEvent) => {\n const matchesKey = e.key.toLowerCase() === key || e.code.toLowerCase() === `key${key}`;\n if (!(e.metaKey || e.ctrlKey) || !e.shiftKey || e.altKey || !matchesKey) return;\n e.preventDefault();\n if (configuration) void FeedbackKit.presentAndSubmit();\n else void FeedbackKit.present({ onReport: (r) => console.info(\"[FeedbackKit] report\", r) });\n };\n window.addEventListener(\"keydown\", shortcutHandler);\n },\n\n disableKeyboardShortcut(): void {\n if (shortcutHandler) window.removeEventListener(\"keydown\", shortcutHandler);\n shortcutHandler = null;\n },\n\n /**\n * Starts recording recent console warnings/errors, uncaught exceptions,\n * and failed network requests, attached to each report (users can opt out\n * per report). Call as early as possible so errors before the first\n * report are caught. `false` turns it off.\n */\n enableLogCapture(options: LogCaptureOptions | false = {}): void {\n logCapture?.uninstall();\n logCapture = options === false ? null : installLogCapture(options);\n },\n\n /** Captures the current viewport as a PNG, without opening any UI. */\n async captureScreenshot(options: CaptureOptions = {}): Promise<Blob> {\n const shot = await captureViewport({ ...FeedbackKit.captureOptions, ...options, exclude: widget.isOwnNode });\n return canvasToPngBlob(shot.canvas);\n },\n\n /**\n * Optional identity of the person using your site, attached to every\n * report they submit. Not needed for fix verification (that uses an\n * anonymous per-browser id, `reporterId`). Pass `null` on sign-out.\n */\n setUser(user: FeedbackUser | null): void {\n setUser(user);\n },\n\n /** The anonymous per-browser id attached to reports — how a fix finds its way back here. */\n get reporterId(): string {\n return reporterId();\n },\n\n /**\n * This browser's reports that need the reporter's attention: shipped\n * fixes to confirm and developer/agent questions. For a custom UI — the\n * built-in one is `enableFixVerification`.\n */\n checkForFixUpdates(): Promise<FixUpdate[]> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before checkForFixUpdates().\"));\n }\n return fetchFixUpdates(configuration);\n },\n\n /** Answers one update directly (custom UIs): verify, reopen, or reply. */\n respondToFixUpdate(feedbackId: string, action: FixAction): Promise<void> {\n if (!configuration) {\n return Promise.reject(new Error(\"FeedbackKit.configure({ projectKey }) must be called before respondToFixUpdate().\"));\n }\n return sendFixAction(configuration, feedbackId, action);\n },\n\n /**\n * Closes the loop with the person who reported a bug: once a fix for one\n * of their reports ships (announced with `feedbackkit release`), a small\n * card shows their original screenshot and asks \"is it fixed?\". \"Still\n * broken\" reopens the capture dialog so they can show what's wrong now,\n * and the report goes straight back to the developer. Also surfaces\n * questions the developer or their coding agent asked.\n *\n * Checks now and whenever the tab becomes visible (at most once a minute).\n * With `appBuild` configured, only fixes shipped in that build or earlier\n * are shown; without it, a fix counts as live as soon as it's released.\n */\n enableFixVerification(): void {\n if (fixVerificationEnabled) return;\n fixVerificationEnabled = true;\n document.addEventListener(\"visibilitychange\", onVisibilityChange);\n whenBodyReady(() => void checkAndShowFix(true));\n },\n\n disableFixVerification(): void {\n fixVerificationEnabled = false;\n document.removeEventListener(\"visibilitychange\", onVisibilityChange);\n widget.hideFixCard();\n },\n\n /**\n * Checks right now (ignoring the throttle) and shows the card if there's\n * something. Resolves once the check is done and any card is on screen.\n */\n presentFixUpdatesIfNeeded(): Promise<void> {\n return checkAndShowFix(true);\n },\n\n /** Removes every trace of the SDK from the page (trigger, dialog host, listeners, log hooks). */\n destroy(): void {\n FeedbackKit.disableFixVerification();\n FeedbackKit.disableKeyboardShortcut();\n logCapture?.uninstall();\n logCapture = null;\n widget.destroy();\n },\n};\n\nexport default FeedbackKit;\n"],"names":["el","text","configuration","m","button","styles","products"],"mappings":"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"}