makethisbetter 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"makethisbetter.cjs","sources":["../src/widget/shadow.ts","../src/widget/tab.ts","../src/widget/frustration-prompt.ts","../src/widget/dim-overlay.ts","../src/annotate/toolbar.ts","../src/annotate/overlay.ts","../src/annotate/highlighter.ts","../src/annotate/pin.ts","../src/styles.ts","../src/annotate/draw.ts","../src/annotate/session.ts","../src/context/dom-utils.ts","../src/annotate/draw-note-bar.ts","../src/popup/comment.ts","../src/popup/clarify.ts","../src/popup/success.ts","../node_modules/html-to-image/es/util.js","../node_modules/html-to-image/es/clone-pseudos.js","../node_modules/html-to-image/es/mimes.js","../node_modules/html-to-image/es/dataurl.js","../node_modules/html-to-image/es/clone-node.js","../node_modules/html-to-image/es/embed-resources.js","../node_modules/html-to-image/es/embed-images.js","../node_modules/html-to-image/es/apply-style.js","../node_modules/html-to-image/es/embed-webfonts.js","../node_modules/html-to-image/es/index.js","../src/screenshot/capture.ts","../src/context/error-source.ts","../src/context/console.ts","../src/context/breadcrumbs.ts","../src/context/frustration.ts","../src/context/collector.ts","../src/api/client.ts","../src/widget/payload.ts","../src/widget/anon-id.ts","../src/i18n/en.ts","../src/i18n/zh-CN.ts","../src/i18n/ja.ts","../src/i18n/ko.ts","../src/i18n/es.ts","../src/i18n/fr.ts","../src/i18n/de.ts","../src/i18n/index.ts","../src/record/session.ts","../src/record/control-bar.ts","../src/widget/recording-manager.ts","../src/widget/controller.ts","../src/index.ts"],"sourcesContent":["import cssText from '../styles/widget.css?inline'\nimport type { MakeThisBetterConfig } from '../types'\n\nexport class ShadowContainer {\n private host: HTMLElement\n readonly root: ShadowRoot\n\n constructor(theme: MakeThisBetterConfig['theme'] = 'auto') {\n this.host = document.createElement('div')\n this.host.id = 'mtb-widget-host'\n this.host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;overflow:visible;z-index:2147483646;'\n this.host.setAttribute('data-mtb-theme', theme)\n document.body.appendChild(this.host)\n\n this.root = this.host.attachShadow({ mode: 'open' })\n\n const style = document.createElement('style')\n style.textContent = cssText\n this.root.appendChild(style)\n }\n\n el<T extends HTMLElement = HTMLElement>(tag: string, className?: string): T {\n const el = document.createElement(tag) as T\n if (className) el.className = className\n return el\n }\n\n append(...nodes: Node[]): void {\n for (const n of nodes) this.root.appendChild(n)\n }\n\n remove(...nodes: Node[]): void {\n for (const n of nodes) {\n if (n.parentNode === this.root) this.root.removeChild(n)\n }\n }\n\n destroy(): void {\n // host.remove() is a safe no-op if the host is already detached — e.g.\n // when Turbo swapped document.body on navigation. removeChild(host) would\n // throw NotFoundError there, aborting re-init and dropping the widget.\n this.host.remove()\n }\n}\n","import type { ShadowContainer } from './shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport class FeedbackTab {\n private el: HTMLButtonElement\n private onClick: () => void\n private idleLabel: string\n private activeLabel: string\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n position: 'left' | 'right',\n onClick: () => void,\n customText?: string,\n ) {\n this.onClick = onClick\n this.el = shadow.el<HTMLButtonElement>('button', 'mtb-tab')\n if (position === 'left') this.el.classList.add('left')\n this.idleLabel = customText ?? messages.tab\n this.activeLabel = messages.toolbar.exit\n this.setLabel(this.idleLabel)\n this.el.addEventListener('click', onClick)\n shadow.append(this.el)\n }\n\n private setLabel(label: string): void {\n this.el.textContent = label\n this.el.setAttribute('aria-label', label)\n }\n\n setActive(active: boolean): void {\n this.el.classList.toggle('active', active)\n this.setLabel(active ? this.activeLabel : this.idleLabel)\n }\n\n destroy(): void {\n this.el.removeEventListener('click', this.onClick)\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from './shadow'\nimport type { I18nMessages } from '../i18n'\n\nconst FRUSTRATION_DISMISS_MS = 8000\n\nexport class FrustrationPromptCard {\n private el: HTMLDivElement\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n handlers: { onTell: () => void; onDismiss: () => void },\n ) {\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-frustration-prompt')\n this.el.innerHTML = `\n <div class=\"mtb-frustration-icon\">&#9888;&#65039;</div>\n <span class=\"mtb-frustration-text\">${messages.frustration.prompt}</span>\n <div class=\"mtb-frustration-actions\">\n <button class=\"mtb-frustration-tell\">${messages.frustration.action}</button>\n <button class=\"mtb-frustration-dismiss\">${messages.frustration.dismiss}</button>\n </div>\n `\n\n this.el.querySelector('.mtb-frustration-tell')!.addEventListener('click', handlers.onTell)\n this.el.querySelector('.mtb-frustration-dismiss')!.addEventListener('click', handlers.onDismiss)\n\n shadow.append(this.el)\n setTimeout(handlers.onDismiss, FRUSTRATION_DISMISS_MS)\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from './shadow'\n\n// Full-screen scrim shown behind the comment popup. Clicking it resets the\n// widget, mirroring the design's dim-to-dismiss behaviour.\nexport class DimOverlay {\n private el: HTMLDivElement\n private onClick: () => void\n\n constructor(shadow: ShadowContainer, onClick: () => void) {\n this.onClick = onClick\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-dim mtb-dim-clickable')\n this.el.addEventListener('click', this.onClick)\n shadow.append(this.el)\n }\n\n destroy(): void {\n this.el.removeEventListener('click', this.onClick)\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport type ToolbarMode = 'markup' | 'record'\n\nexport class AnnotationToolbar {\n private el: HTMLDivElement\n private hintEl!: HTMLSpanElement\n private markupBtn!: HTMLButtonElement\n private recordBtn!: HTMLButtonElement\n private messages: I18nMessages\n private currentMode: ToolbarMode = 'markup'\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n onExit: () => void,\n onModeChange?: (mode: ToolbarMode) => void,\n ) {\n this.messages = messages\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-toolbar')\n this.el.innerHTML = this.buildHTML(messages)\n shadow.append(this.el)\n\n this.hintEl = this.el.querySelector('.mtb-toolbar-hint')!\n this.markupBtn = this.el.querySelector('.mtb-toolbar-mode-markup')!\n this.recordBtn = this.el.querySelector('.mtb-toolbar-mode-record')!\n\n this.markupBtn.addEventListener('click', () => {\n this.setMode('markup')\n onModeChange?.('markup')\n })\n this.recordBtn.addEventListener('click', () => {\n this.setMode('record')\n onModeChange?.('record')\n })\n this.el.querySelector('.mtb-exit-btn')!.addEventListener('click', onExit)\n }\n\n private buildHTML(m: I18nMessages): string {\n return `\n <div class=\"mtb-toolbar-modes\">\n <button class=\"mtb-toolbar-mode-btn mtb-toolbar-mode-markup active\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"7\"/><line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"21\"/><line x1=\"3\" y1=\"12\" x2=\"7\" y2=\"12\"/><line x1=\"17\" y1=\"12\" x2=\"21\" y2=\"12\"/></svg>${m.toolbar.markup}\n </button>\n <button class=\"mtb-toolbar-mode-btn mtb-toolbar-mode-record\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"4\" fill=\"currentColor\" stroke=\"none\"/></svg>${m.toolbar.record}\n </button>\n </div>\n <span class=\"mtb-toolbar-hint\">${m.toolbar.hint}</span>\n <span class=\"mtb-toolbar-sep\"></span>\n <button class=\"mtb-exit-btn\">\n <svg width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>${m.toolbar.exit}\n </button>\n `\n }\n\n setMode(mode: ToolbarMode): void {\n this.currentMode = mode\n if (mode === 'markup') {\n this.markupBtn.classList.add('active')\n this.recordBtn.classList.remove('active')\n this.hintEl.textContent = this.messages.toolbar.hint\n } else {\n this.markupBtn.classList.remove('active')\n this.recordBtn.classList.add('active')\n this.hintEl.textContent = this.messages.toolbar.hintRecord\n }\n }\n\n getMode(): ToolbarMode {\n return this.currentMode\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\nexport class AnnotationOverlay {\n private overlayEl: HTMLDivElement\n private dimEl: HTMLDivElement\n private onMouseDown: (e: MouseEvent) => void\n private onMouseMove: (e: MouseEvent) => void\n private onMouseUp: (e: MouseEvent) => void\n private onMouseLeave: (e: MouseEvent) => void\n\n constructor(\n shadow: ShadowContainer,\n handlers: {\n onMouseDown: (e: MouseEvent) => void\n onMouseMove: (e: MouseEvent) => void\n onMouseUp: (e: MouseEvent) => void\n onMouseLeave: (e: MouseEvent) => void\n },\n ) {\n this.onMouseDown = handlers.onMouseDown\n this.onMouseMove = handlers.onMouseMove\n this.onMouseUp = handlers.onMouseUp\n this.onMouseLeave = handlers.onMouseLeave\n\n this.overlayEl = shadow.el<HTMLDivElement>('div', 'mtb-overlay')\n this.overlayEl.addEventListener('mousedown', this.onMouseDown)\n this.overlayEl.addEventListener('mousemove', this.onMouseMove)\n this.overlayEl.addEventListener('mouseup', this.onMouseUp)\n this.overlayEl.addEventListener('mouseleave', this.onMouseLeave)\n shadow.append(this.overlayEl)\n\n this.dimEl = shadow.el<HTMLDivElement>('div', 'mtb-dim')\n shadow.append(this.dimEl)\n }\n\n destroy(): void {\n this.overlayEl.removeEventListener('mousedown', this.onMouseDown)\n this.overlayEl.removeEventListener('mousemove', this.onMouseMove)\n this.overlayEl.removeEventListener('mouseup', this.onMouseUp)\n this.overlayEl.removeEventListener('mouseleave', this.onMouseLeave)\n this.overlayEl.remove()\n this.dimEl.remove()\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\nexport class ElementHighlighter {\n private highlightEl: HTMLDivElement\n private tooltipEl: HTMLDivElement\n\n constructor(shadow: ShadowContainer) {\n this.highlightEl = shadow.el<HTMLDivElement>('div', 'mtb-highlight')\n this.tooltipEl = shadow.el<HTMLDivElement>('div', 'mtb-highlight-tooltip')\n this.hide()\n shadow.append(this.highlightEl, this.tooltipEl)\n }\n\n highlight(el: Element): void {\n const rect = el.getBoundingClientRect()\n this.highlightEl.style.top = `${rect.top - 2}px`\n this.highlightEl.style.left = `${rect.left - 2}px`\n this.highlightEl.style.width = `${rect.width + 4}px`\n this.highlightEl.style.height = `${rect.height + 4}px`\n this.highlightEl.style.display = 'block'\n this.showTooltip(el, rect)\n }\n\n private showTooltip(el: Element, rect: DOMRect): void {\n this.tooltipEl.textContent = getElementName(el)\n const below = rect.top < 30\n this.tooltipEl.classList.toggle('below', below)\n this.tooltipEl.style.left = `${rect.left + rect.width / 2}px`\n this.tooltipEl.style.top = below ? `${rect.bottom + 8}px` : `${rect.top - 8}px`\n this.tooltipEl.style.display = 'block'\n }\n\n hide(): void {\n this.highlightEl.style.display = 'none'\n this.tooltipEl.style.display = 'none'\n }\n\n destroy(): void {\n this.highlightEl.remove()\n this.tooltipEl.remove()\n }\n}\n\nexport function getElementName(el: Element): string {\n if (el instanceof HTMLElement) {\n const label = el.getAttribute('aria-label')\n if (label) return label\n\n const title = el.getAttribute('title')\n if (title) return title\n\n const text = el.textContent?.trim().slice(0, 40)\n if (text) return text\n\n const placeholder = (el as HTMLInputElement).placeholder\n if (placeholder) return placeholder\n\n const alt = (el as HTMLImageElement).alt\n if (alt) return alt\n\n const dataMark = el.getAttribute('data-mark')\n if (dataMark) return dataMark\n }\n return el.tagName.toLowerCase()\n}\n\nexport function getCssSelector(el: Element): string {\n const parts: string[] = []\n let current: Element | null = el\n while (current && current !== document.body && parts.length < 5) {\n let selector = current.tagName.toLowerCase()\n if (current.id) {\n selector = `#${current.id}`\n parts.unshift(selector)\n break\n }\n const classNames = Array.from(current.classList)\n .filter(c => !c.startsWith('mtb-'))\n .slice(0, 2)\n .join('.')\n if (classNames) selector += `.${classNames}`\n\n const parent = current.parentElement\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n c => c.tagName === current!.tagName,\n )\n if (siblings.length > 1) {\n const idx = siblings.indexOf(current) + 1\n selector += `:nth-of-type(${idx})`\n }\n }\n\n parts.unshift(selector)\n current = current.parentElement\n }\n return parts.join(' > ')\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\nexport class PinMarker {\n private pins: HTMLDivElement[] = []\n private shadow: ShadowContainer\n\n constructor(shadow: ShadowContainer) {\n this.shadow = shadow\n }\n\n addPin(x: number, y: number, index: number): void {\n const pin = this.shadow.el<HTMLDivElement>('div', 'mtb-pin')\n pin.textContent = String(index)\n pin.style.top = `${y}px`\n pin.style.left = `${x}px`\n this.shadow.append(pin)\n this.pins.push(pin)\n }\n\n clearAll(): void {\n for (const pin of this.pins) pin.remove()\n this.pins = []\n }\n\n destroy(): void {\n this.clearAll()\n }\n}\n","export const BRAND_COLOR = '#059669'\n\nexport const FONT_STACK = '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif'\n\nexport const DRAW_STROKE = {\n color: BRAND_COLOR,\n width: '3.5',\n linecap: 'round',\n linejoin: 'round',\n filter: 'drop-shadow(0 1px 2px rgba(5,150,105,0.35))',\n} as const\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { Annotation } from '../types'\nimport { DRAW_STROKE } from '../styles'\n\ntype Point = [number, number]\n\ninterface Stroke {\n path: SVGPathElement\n d: string\n points: Point[]\n}\n\nexport class DrawLayer {\n private svg: SVGSVGElement\n private currentPath: SVGPathElement | null = null\n private currentPoints: Point[] = []\n private isDrawing = false\n private committed: Stroke[] = []\n private redoStack: { d: string; points: Point[] }[] = []\n\n constructor(shadow: ShadowContainer) {\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n this.svg.setAttribute('class', 'mtb-draw-svg')\n shadow.append(this.svg)\n }\n\n startDraw(x: number, y: number): void {\n this.isDrawing = true\n this.currentPoints = [[x, y]]\n this.currentPath = this.createPath()\n this.svg.appendChild(this.currentPath)\n }\n\n continueDraw(x: number, y: number): void {\n if (!this.isDrawing || !this.currentPath) return\n this.currentPoints.push([x, y])\n this.currentPath.setAttribute('d', buildPathD(this.currentPoints))\n }\n\n // Commits the in-progress stroke to the undo stack and clears the redo stack.\n // Callers decide whether the stroke has enough points before committing.\n commitStroke(): boolean {\n if (!this.isDrawing || !this.currentPath) return false\n this.isDrawing = false\n this.committed.push({ path: this.currentPath, d: buildPathD(this.currentPoints), points: this.currentPoints })\n this.redoStack = []\n this.currentPath = null\n this.currentPoints = []\n return true\n }\n\n cancelCurrentDraw(): void {\n this.currentPath?.remove()\n this.currentPath = null\n this.isDrawing = false\n this.currentPoints = []\n }\n\n undo(): boolean {\n const stroke = this.committed.pop()\n if (!stroke) return false\n stroke.path.remove()\n this.redoStack.push({ d: stroke.d, points: stroke.points })\n return true\n }\n\n redo(): boolean {\n const entry = this.redoStack.pop()\n if (!entry) return false\n const path = this.createPath()\n path.setAttribute('d', entry.d)\n this.svg.appendChild(path)\n this.committed.push({ path, d: entry.d, points: entry.points })\n return true\n }\n\n canUndo(): boolean {\n return this.committed.length > 0\n }\n\n canRedo(): boolean {\n return this.redoStack.length > 0\n }\n\n hasStrokes(): boolean {\n return this.committed.length > 0\n }\n\n getAnnotation(): Annotation | null {\n if (this.committed.length === 0) return null\n const points = this.committed.flatMap(s => s.points)\n const [cx, cy] = center(points)\n return {\n type: 'draw',\n x: cx,\n y: cy,\n drawPath: this.committed.map(s => s.d).join(' '),\n }\n }\n\n clearAll(): void {\n while (this.svg.firstChild) this.svg.removeChild(this.svg.firstChild)\n this.currentPath = null\n this.isDrawing = false\n this.currentPoints = []\n this.committed = []\n this.redoStack = []\n }\n\n isCurrentlyDrawing(): boolean {\n return this.isDrawing\n }\n\n getCurrentPointCount(): number {\n return this.currentPoints.length\n }\n\n destroy(): void {\n this.svg.remove()\n }\n\n private createPath(): SVGPathElement {\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('fill', 'none')\n path.setAttribute('stroke', DRAW_STROKE.color)\n path.setAttribute('stroke-width', DRAW_STROKE.width)\n path.setAttribute('stroke-linecap', DRAW_STROKE.linecap)\n path.setAttribute('stroke-linejoin', DRAW_STROKE.linejoin)\n path.setAttribute('style', `filter:${DRAW_STROKE.filter}`)\n return path\n }\n}\n\nfunction buildPathD(points: Point[]): string {\n if (points.length === 0) return ''\n const [fx, fy] = points[0]\n let d = `M ${fx} ${fy}`\n for (let i = 1; i < points.length; i++) {\n const [x, y] = points[i]\n d += ` L ${x} ${y}`\n }\n return d\n}\n\nfunction center(points: Point[]): Point {\n const xs = points.map(p => p[0])\n const ys = points.map(p => p[1])\n const cx = (Math.min(...xs) + Math.max(...xs)) / 2\n const cy = (Math.min(...ys) + Math.max(...ys)) / 2\n return [cx, cy]\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport type { Annotation } from '../types'\nimport { AnnotationOverlay } from './overlay'\nimport { ElementHighlighter, getElementName, getCssSelector } from './highlighter'\nimport { PinMarker } from './pin'\nimport { DrawLayer } from './draw'\n\nconst DRAW_MIN_POINTS = 5\n\ninterface SessionHandlers {\n onPin: (annotation: Annotation, targetName: string) => void\n onDrawStroke: () => void\n}\n\nexport class AnnotationSession {\n private overlay: AnnotationOverlay\n private highlighter: ElementHighlighter\n private pinMarker: PinMarker\n private drawLayer: DrawLayer\n private pinCount = 0\n private interactionActive = true\n private pendingHighlightFrame: number | null = null\n private lastMoveX = 0\n private lastMoveY = 0\n\n constructor(\n shadow: ShadowContainer,\n private messages: I18nMessages,\n private handlers: SessionHandlers,\n ) {\n this.highlighter = new ElementHighlighter(shadow)\n this.pinMarker = new PinMarker(shadow)\n this.drawLayer = new DrawLayer(shadow)\n this.overlay = new AnnotationOverlay(shadow, {\n onMouseDown: (e) => this.handleMouseDown(e),\n onMouseMove: (e) => this.handleMouseMove(e),\n onMouseUp: (e) => this.handleMouseUp(e),\n onMouseLeave: () => {\n if (this.drawLayer.isCurrentlyDrawing()) this.finishStroke()\n this.cancelPendingHighlight()\n this.highlighter.hide()\n },\n })\n }\n\n private handleMouseDown(e: MouseEvent): void {\n e.preventDefault()\n this.drawLayer.startDraw(e.clientX, e.clientY)\n }\n\n private handleMouseMove(e: MouseEvent): void {\n if (this.drawLayer.isCurrentlyDrawing()) {\n this.cancelPendingHighlight()\n this.drawLayer.continueDraw(e.clientX, e.clientY)\n this.highlighter.hide()\n return\n }\n\n this.lastMoveX = e.clientX\n this.lastMoveY = e.clientY\n if (this.pendingHighlightFrame !== null) return\n this.pendingHighlightFrame = requestAnimationFrame(() => {\n this.pendingHighlightFrame = null\n this.updateHighlight()\n })\n }\n\n private updateHighlight(): void {\n if (!this.interactionActive || this.drawLayer.isCurrentlyDrawing() || this.drawSessionActive()) return\n const underEl = getElementUnder(this.lastMoveX, this.lastMoveY)\n if (underEl) this.highlighter.highlight(underEl)\n else this.highlighter.hide()\n }\n\n private cancelPendingHighlight(): void {\n if (this.pendingHighlightFrame === null) return\n cancelAnimationFrame(this.pendingHighlightFrame)\n this.pendingHighlightFrame = null\n }\n\n private handleMouseUp(e: MouseEvent): void {\n if (!this.drawLayer.isCurrentlyDrawing()) return\n this.finishStroke(e)\n }\n\n // A drag past the point threshold becomes a freehand stroke and opens the\n // draw note bar; a tap on an element becomes a pin. Stray taps while a\n // drawing already exists are ignored so they don't hijack the draw flow.\n private finishStroke(e?: MouseEvent): void {\n if (this.drawLayer.getCurrentPointCount() >= DRAW_MIN_POINTS) {\n this.drawLayer.commitStroke()\n this.highlighter.hide()\n this.handlers.onDrawStroke()\n return\n }\n\n this.drawLayer.cancelCurrentDraw()\n if (this.drawLayer.hasStrokes() || !e) return\n\n const underEl = getElementUnder(e.clientX, e.clientY)\n const targetName = underEl ? getElementName(underEl) : this.messages.annotation.element\n const annotation: Annotation = {\n type: 'pin',\n x: e.clientX,\n y: e.clientY,\n targetSelector: underEl ? getCssSelector(underEl) : undefined,\n targetText: underEl?.textContent?.trim().slice(0, 200) ?? '',\n targetName,\n }\n this.pinMarker.addPin(e.clientX, e.clientY, ++this.pinCount)\n this.highlighter.hide()\n this.handlers.onPin(annotation, targetName)\n }\n\n undoDraw(): void {\n this.drawLayer.undo()\n }\n\n redoDraw(): void {\n this.drawLayer.redo()\n }\n\n canUndoDraw(): boolean {\n return this.drawLayer.canUndo()\n }\n\n canRedoDraw(): boolean {\n return this.drawLayer.canRedo()\n }\n\n hasDrawStrokes(): boolean {\n return this.drawLayer.hasStrokes()\n }\n\n private drawSessionActive(): boolean {\n return this.drawLayer.hasStrokes() || this.drawLayer.canRedo()\n }\n\n getDrawAnnotation(): Annotation | null {\n return this.drawLayer.getAnnotation()\n }\n\n clearDraw(): void {\n this.drawLayer.clearAll()\n }\n\n dismissInteraction(): void {\n if (!this.interactionActive) return\n this.interactionActive = false\n this.cancelPendingHighlight()\n this.overlay.destroy()\n this.highlighter.destroy()\n }\n\n destroy(): void {\n this.dismissInteraction()\n this.pinMarker.destroy()\n this.drawLayer.destroy()\n }\n}\n\n// Skips the widget host via elementsFromPoint instead of toggling its\n// display — hiding the host on every mousemove flickered the toolbar.\nfunction getElementUnder(x: number, y: number): Element | null {\n return document.elementsFromPoint(x, y).find(el => el.id !== 'mtb-widget-host') ?? null\n}\n","const WIDGET_HOST_ID = 'mtb-widget-host'\n\nexport function isWidgetElement(el: Element): boolean {\n const host = document.getElementById(WIDGET_HOST_ID)\n if (!host) return false\n return host === el || host.contains(el)\n}\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;')\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport { escapeHtml } from '../context/dom-utils'\n\ninterface DrawNoteBarOptions {\n messages: I18nMessages\n onUndo: () => void\n onRedo: () => void\n onCancel: () => void\n onSubmit: (note: string) => void\n}\n\nexport class DrawNoteBar {\n private el: HTMLDivElement\n private input!: HTMLInputElement\n private undoBtn!: HTMLButtonElement\n private redoBtn!: HTMLButtonElement\n private submitBtn!: HTMLButtonElement\n private errorEl!: HTMLDivElement\n private onSubmit: (note: string) => void\n private submitLabel: string\n private loading = false\n\n constructor(shadow: ShadowContainer, opts: DrawNoteBarOptions) {\n this.onSubmit = opts.onSubmit\n this.submitLabel = opts.messages.draw.submit\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-draw-bar')\n this.el.innerHTML = this.buildHTML(opts.messages)\n shadow.append(this.el)\n\n this.input = this.el.querySelector('.mtb-draw-input')!\n this.undoBtn = this.el.querySelector('.mtb-draw-undo')!\n this.redoBtn = this.el.querySelector('.mtb-draw-redo')!\n this.submitBtn = this.el.querySelector('.mtb-draw-submit')!\n this.errorEl = this.el.querySelector('.mtb-draw-error')!\n\n this.undoBtn.addEventListener('click', opts.onUndo)\n this.redoBtn.addEventListener('click', opts.onRedo)\n this.el.querySelector('.mtb-draw-cancel')!.addEventListener('click', opts.onCancel)\n this.submitBtn.addEventListener('click', () => this.submit())\n this.input.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.isComposing || e.keyCode === 229) return\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this.submit()\n }\n })\n\n this.input.focus()\n }\n\n private buildHTML(m: I18nMessages): string {\n return `\n <input class=\"mtb-draw-input\" type=\"text\" placeholder=\"${escapeHtml(m.draw.note_placeholder)}\" />\n <button class=\"mtb-draw-icon-btn mtb-draw-undo\" type=\"button\" title=\"${escapeHtml(m.draw.undo)}\" aria-label=\"${escapeHtml(m.draw.undo)}\" disabled>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 14L4 9l5-5\"/><path d=\"M4 9h11a5 5 0 0 1 0 10h-1\"/></svg>\n </button>\n <button class=\"mtb-draw-icon-btn mtb-draw-redo\" type=\"button\" title=\"${escapeHtml(m.draw.redo)}\" aria-label=\"${escapeHtml(m.draw.redo)}\" disabled>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 14l5-5-5-5\"/><path d=\"M20 9H9a5 5 0 0 0 0 10h1\"/></svg>\n </button>\n <span class=\"mtb-draw-sep\"></span>\n <button class=\"mtb-draw-cancel\" type=\"button\">${escapeHtml(m.draw.cancel)}</button>\n <button class=\"mtb-draw-submit\" type=\"button\">${escapeHtml(m.draw.submit)}</button>\n <div class=\"mtb-draw-error\" role=\"alert\" hidden></div>\n `\n }\n\n setUndoRedo(canUndo: boolean, canRedo: boolean): void {\n this.undoBtn.disabled = !canUndo || this.loading\n this.redoBtn.disabled = !canRedo || this.loading\n }\n\n setLoading(loading: boolean): void {\n this.loading = loading\n this.input.disabled = loading\n this.submitBtn.disabled = loading\n this.undoBtn.disabled = loading || this.undoBtn.disabled\n this.redoBtn.disabled = loading || this.redoBtn.disabled\n if (loading) {\n this.submitBtn.classList.add('loading')\n this.submitBtn.innerHTML = `<span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span>`\n this.errorEl.hidden = true\n this.errorEl.textContent = ''\n } else {\n this.submitBtn.classList.remove('loading')\n this.submitBtn.textContent = this.submitLabel\n }\n }\n\n setError(message: string): void {\n this.errorEl.textContent = message\n this.errorEl.hidden = false\n }\n\n private submit(): void {\n if (this.loading) return\n this.onSubmit(this.input.value.trim())\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport { escapeHtml } from '../context/dom-utils'\n\ninterface PopupOptions {\n targetName: string\n x: number\n y: number\n onSubmit: (description: string) => void\n onClose: () => void\n onMyFeedback?: () => void\n messages: I18nMessages\n}\n\nexport class CommentPopup {\n private el: HTMLDivElement\n private textarea!: HTMLTextAreaElement\n private submitBtn!: HTMLButtonElement\n private errorEl!: HTMLDivElement\n private onSubmit: (description: string) => void\n private onClose: () => void\n private submitLabel: string\n private loading = false\n private messages: I18nMessages\n\n constructor(shadow: ShadowContainer, opts: PopupOptions) {\n this.onSubmit = opts.onSubmit\n this.onClose = opts.onClose\n this.submitLabel = opts.messages.popup.submit\n this.messages = opts.messages\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-popup')\n this.el.innerHTML = this.buildHTML(opts)\n shadow.append(this.el)\n\n this.textarea = this.el.querySelector('.mtb-textarea')!\n this.submitBtn = this.el.querySelector('.mtb-submit-btn')!\n\n this.positionPopup(opts.x, opts.y)\n this.bindEvents(opts.messages)\n if (opts.onMyFeedback) {\n this.el.querySelector('.mtb-my-feedback')!.addEventListener('click', opts.onMyFeedback)\n }\n this.textarea.focus()\n }\n\n private buildHTML(opts: PopupOptions): string {\n const m = opts.messages\n const quickOpts = m.popup.quickOptions\n .map(\n o => `\n <button class=\"mtb-quick-option\" data-quick=\"${escapeHtml(o.label)}\">\n <span class=\"mtb-quick-option-emoji\">${o.emoji}</span>\n <span>${escapeHtml(o.label)}</span>\n </button>`,\n )\n .join('')\n\n return `\n <div class=\"mtb-popup-header\">\n <div class=\"mtb-popup-icon\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#059669\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/>\n </svg>\n </div>\n <span class=\"mtb-popup-title\">${m.popup.about} \"${escapeHtml(opts.targetName)}\"</span>\n <button class=\"mtb-popup-close\" aria-label=\"Close\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n <div class=\"mtb-popup-body\">\n <div class=\"mtb-quick-options\">\n ${quickOpts}\n </div>\n <div class=\"mtb-textarea-wrap\">\n <textarea class=\"mtb-textarea\" placeholder=\"${escapeHtml(m.popup.placeholder)}\"></textarea>\n </div>\n <div class=\"mtb-popup-error\" role=\"alert\"></div>\n <div class=\"mtb-popup-actions\">\n <button class=\"mtb-cancel-btn\" type=\"button\">${escapeHtml(m.popup.cancel)}</button>\n <button class=\"mtb-submit-btn\" type=\"button\" disabled>${escapeHtml(m.popup.submit)}</button>\n </div>\n ${opts.onMyFeedback ? `<button class=\"mtb-my-feedback\" type=\"button\">${escapeHtml(m.popup.my_feedback)}</button>` : ''}\n </div>\n `\n }\n\n\n\n private positionPopup(x: number, y: number): void {\n const popupW = 320\n const popupH = 260\n const vw = window.innerWidth\n const vh = window.innerHeight\n const margin = 12\n\n let left = x + 12\n let top = y + 12\n\n if (left + popupW > vw - margin) {\n left = x - popupW - 12\n }\n if (left < margin) left = margin\n\n if (top + popupH > vh - margin) {\n top = vh - popupH - margin\n }\n if (top < margin) top = margin\n\n this.el.style.left = `${left}px`\n this.el.style.top = `${top}px`\n this.el.style.maxHeight = `${vh - top - margin}px`\n }\n\n private bindEvents(messages: I18nMessages): void {\n this.el.querySelector('.mtb-popup-close')!.addEventListener('click', () => this.onClose())\n this.el.querySelector('.mtb-cancel-btn')!.addEventListener('click', () => this.onClose())\n this.errorEl = this.el.querySelector('.mtb-popup-error')!\n\n this.el.querySelectorAll('.mtb-quick-option').forEach(btn => {\n btn.addEventListener('click', () => {\n const label = (btn as HTMLElement).dataset['quick'] ?? ''\n this.textarea.value = label\n this.updateSubmitState()\n this.submit()\n })\n })\n\n this.textarea.addEventListener('input', () => this.updateSubmitState())\n\n this.textarea.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.isComposing || e.keyCode === 229) return\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this.submit()\n }\n })\n\n this.submitBtn.addEventListener('click', () => this.submit())\n }\n\n private updateSubmitState(): void {\n const hasText = this.textarea.value.trim().length > 0\n this.submitBtn.classList.toggle('ready', hasText && !this.loading)\n this.submitBtn.disabled = !hasText || this.loading\n this.errorEl.hidden = true\n this.errorEl.textContent = ''\n }\n\n private submit(): void {\n const text = this.textarea.value.trim()\n if (!text || this.loading) return\n this.onSubmit(text)\n }\n\n setLoading(loading: boolean): void {\n this.loading = loading\n if (loading) {\n this.submitBtn.classList.add('loading')\n this.submitBtn.innerHTML = `<span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span>`\n this.textarea.disabled = true\n } else {\n this.submitBtn.classList.remove('loading')\n this.submitBtn.textContent = this.submitLabel\n this.textarea.disabled = false\n }\n this.updateSubmitState()\n }\n\n setError(message: string): void {\n this.errorEl.textContent = message\n this.errorEl.hidden = false\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n\nfunction formatDuration(seconds: number): string {\n const total = Math.max(0, Math.round(seconds))\n const mm = String(Math.floor(total / 60)).padStart(2, '0')\n const ss = String(total % 60).padStart(2, '0')\n return `${mm}:${ss}`\n}\n\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport type { ApiClient } from '../api/client'\nimport type { ClarifyMessage } from '../types'\nimport { escapeHtml } from '../context/dom-utils'\n\nconst POLL_INTERVAL_MS = 2000\n// Give up polling after this long with no assistant reply so the card never\n// spins forever (e.g. a backend job that silently died).\nconst POLL_TIMEOUT_MS = 45000\n\nexport interface ClarifySummaryContext {\n originalDescription: string\n element: string\n page: string\n browser: string\n captured: string\n}\n\ninterface ClarifyCardOptions {\n submissionSessionId: string\n submissionToken: string\n apiClient: ApiClient\n messages: I18nMessages\n onFinalize: () => Promise<void> | void\n summary?: ClarifySummaryContext\n x?: number\n y?: number\n}\n\nconst CARD_WIDTH = 346\nconst CARD_HEIGHT = 320\n\nexport class ClarifyCard {\n private el: HTMLDivElement\n private messagesEl!: HTMLDivElement\n private inputEl!: HTMLTextAreaElement\n private sendBtn!: HTMLButtonElement\n private pollTimer: ReturnType<typeof setInterval> | null = null\n private pollDeadline = 0\n private streamingBubble: HTMLDivElement | null = null\n private submissionSessionId: string\n private submissionToken: string\n private apiClient: ApiClient\n private onFinalize: () => Promise<void> | void\n private i18n: I18nMessages\n private summaryCtx?: ClarifySummaryContext\n private lastMessages: ClarifyMessage[] = []\n private done = false\n private sending = false\n private finalizing = false\n private destroyed = false\n\n constructor(shadow: ShadowContainer, opts: ClarifyCardOptions) {\n this.submissionSessionId = opts.submissionSessionId\n this.submissionToken = opts.submissionToken\n this.apiClient = opts.apiClient\n this.onFinalize = opts.onFinalize\n this.i18n = opts.messages\n this.summaryCtx = opts.summary\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-clarify')\n this.el.innerHTML = this.buildHTML(opts.messages)\n this.positionCard(opts.x, opts.y)\n shadow.append(this.el)\n\n this.messagesEl = this.el.querySelector('.mtb-clarify-messages')!\n this.inputEl = this.el.querySelector('.mtb-clarify-input')!\n this.sendBtn = this.el.querySelector('.mtb-clarify-send')!\n\n this.bindEvents()\n this.startConversation()\n }\n\n // Anchors the card near the annotation point, clamped to the viewport so it\n // never overflows a screen edge (mirrors CommentPopup.positionPopup).\n private positionCard(x?: number, y?: number): void {\n const vw = window.innerWidth\n const vh = window.innerHeight\n const margin = 12\n\n if (x === undefined || y === undefined) {\n this.el.style.left = `${Math.max(margin, (vw - CARD_WIDTH) / 2)}px`\n this.el.style.top = `${Math.max(margin, (vh - CARD_HEIGHT) / 2)}px`\n return\n }\n\n let left = x + 12\n let top = y + 12\n if (left + CARD_WIDTH > vw - margin) left = x - CARD_WIDTH - 12\n if (left < margin) left = margin\n if (top + CARD_HEIGHT > vh - margin) top = vh - CARD_HEIGHT - margin\n if (top < margin) top = margin\n\n this.el.style.left = `${left}px`\n this.el.style.top = `${top}px`\n }\n\n private buildHTML(m: I18nMessages): string {\n return `\n <div class=\"mtb-clarify-header\">\n <span class=\"mtb-clarify-icon\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M12 3l1.6 5.4L19 10l-5.4 1.6L12 17l-1.6-5.4L5 10l5.4-1.6L12 3z\"/>\n </svg>\n </span>\n <div class=\"mtb-clarify-titles\">\n <div class=\"mtb-clarify-title\">${escapeHtml(m.clarify.title)}</div>\n <div class=\"mtb-clarify-subtitle\">${escapeHtml(m.clarify.subtitle)}</div>\n </div>\n <button class=\"mtb-clarify-close\" type=\"button\" title=\"${escapeHtml(m.clarify.skip)}\" aria-label=\"${escapeHtml(m.clarify.skip)}\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n <div class=\"mtb-clarify-messages\"></div>\n <div class=\"mtb-clarify-footer\">\n <textarea class=\"mtb-clarify-input\" rows=\"2\" placeholder=\"${escapeHtml(m.clarify.placeholder)}\"></textarea>\n <div class=\"mtb-clarify-actions\">\n <button class=\"mtb-clarify-skip\" type=\"button\">${escapeHtml(m.clarify.skip)}</button>\n <button class=\"mtb-clarify-send\" type=\"button\" disabled>\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"/>\n </svg>\n <span>${escapeHtml(m.clarify.send)}</span>\n </button>\n </div>\n </div>\n `\n }\n\n private bindEvents(): void {\n const skip = () => {\n this.stopPolling()\n void this.finalize()\n }\n this.el.querySelector('.mtb-clarify-skip')!.addEventListener('click', skip)\n this.el.querySelector('.mtb-clarify-close')!.addEventListener('click', skip)\n\n this.inputEl.addEventListener('input', () => {\n this.sendBtn.disabled = !this.inputEl.value.trim()\n })\n\n this.inputEl.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.isComposing || e.keyCode === 229) return\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this.sendMessage()\n }\n })\n\n this.sendBtn.addEventListener('click', () => this.sendMessage())\n }\n\n private async startConversation(): Promise<void> {\n this.showThinking()\n await this.runInitialTurn()\n }\n\n private async sendMessage(): Promise<void> {\n const text = this.inputEl.value.trim()\n if (!text || this.sending) return\n\n this.sending = true\n this.inputEl.disabled = true\n this.sendBtn.disabled = true\n this.stopPolling()\n\n this.appendMessage({ role: 'user', content: text })\n this.inputEl.value = ''\n this.showThinking()\n this.clearError()\n\n try {\n await this.runAnswerTurn(text)\n } catch {\n if (this.destroyed) return\n this.renderConversation(this.lastMessages, false)\n this.inputEl.value = text\n this.showError()\n } finally {\n this.sending = false\n this.inputEl.disabled = false\n this.sendBtn.disabled = !this.inputEl.value.trim()\n this.inputEl.focus()\n }\n }\n\n // Streams the assistant reply; falls back to POST + polling if the backend\n // doesn't support SSE (older server) or the stream errors mid-flight.\n private async runInitialTurn(): Promise<void> {\n try {\n const result = await this.apiClient.streamClarification(\n this.submissionSessionId,\n this.submissionToken,\n (text) => this.appendStreamDelta(text),\n )\n if (this.destroyed) return\n this.endStreamingBubble()\n this.renderConversation(result.messages, result.done)\n if (result.done) this.handleDone()\n else this.startPolling()\n } catch {\n if (this.destroyed) return\n this.endStreamingBubble()\n await this.runInitialTurnViaPolling()\n }\n }\n\n private async runInitialTurnViaPolling(): Promise<void> {\n try {\n const res = await this.apiClient.startClarification(\n this.submissionSessionId,\n this.submissionToken,\n )\n if (this.destroyed) return\n this.renderConversation(res.messages, res.done)\n if (res.done) this.handleDone()\n else this.startPolling()\n } catch {\n if (this.destroyed) return\n this.handleDone()\n }\n }\n\n private async runAnswerTurn(message: string): Promise<void> {\n const res = await this.apiClient.startClarification(\n this.submissionSessionId,\n this.submissionToken,\n message,\n )\n if (this.destroyed) return\n this.renderConversation(res.messages, res.done)\n if (res.done) this.handleDone()\n else this.startPolling()\n }\n\n private showError(): void {\n const footer = this.el.querySelector('.mtb-clarify-footer')!\n const error = document.createElement('div')\n error.className = 'mtb-clarify-error'\n error.textContent = this.i18n.error.submit\n footer.prepend(error)\n }\n\n private clearError(): void {\n this.el.querySelector('.mtb-clarify-error')?.remove()\n }\n\n private appendStreamDelta(text: string): void {\n if (!this.streamingBubble) {\n this.removeThinking()\n this.streamingBubble = document.createElement('div')\n this.streamingBubble.className = 'mtb-clarify-bubble mtb-clarify-ai'\n this.messagesEl.appendChild(this.streamingBubble)\n }\n this.streamingBubble.textContent = (this.streamingBubble.textContent ?? '') + text\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private endStreamingBubble(): void {\n this.streamingBubble = null\n }\n\n private startPolling(): void {\n this.stopPolling()\n this.pollDeadline = Date.now() + POLL_TIMEOUT_MS\n this.pollTimer = setInterval(() => this.poll(), POLL_INTERVAL_MS)\n }\n\n private stopPolling(): void {\n if (this.pollTimer !== null) {\n clearInterval(this.pollTimer)\n this.pollTimer = null\n }\n }\n\n private async poll(): Promise<void> {\n if (Date.now() > this.pollDeadline) {\n this.stopPolling()\n this.handleDone()\n return\n }\n try {\n const res = await this.apiClient.getClarification(\n this.submissionSessionId,\n this.submissionToken,\n )\n if (this.destroyed) return\n this.renderConversation(res.messages, res.done)\n if (res.done) {\n this.stopPolling()\n this.handleDone()\n }\n } catch {\n if (this.destroyed) return\n this.stopPolling()\n this.handleDone()\n }\n }\n\n private handleDone(): void {\n if (this.done) return\n this.done = true\n this.stopPolling()\n this.removeThinking()\n this.renderSummary()\n }\n\n private renderSummary(): void {\n const s = this.i18n.clarify.summary\n const card = document.createElement('div')\n card.className = 'mtb-clarify-summary'\n card.innerHTML = this.buildSummaryHTML(s)\n this.messagesEl.appendChild(card)\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n\n const footer = this.el.querySelector('.mtb-clarify-footer')!\n footer.innerHTML = `<button class=\"mtb-clarify-send-feedback\" type=\"button\">${escapeHtml(s.send_feedback)}</button>`\n footer.querySelector('.mtb-clarify-send-feedback')!.addEventListener('click', () => {\n if (!this.destroyed) void this.finalize()\n })\n }\n\n private async finalize(): Promise<void> {\n if (this.finalizing || this.destroyed) return\n\n this.finalizing = true\n this.el.querySelectorAll<HTMLButtonElement>('button').forEach(button => { button.disabled = true })\n try {\n await this.onFinalize()\n } catch {\n if (this.destroyed) return\n this.finalizing = false\n this.handleDone()\n this.el.querySelectorAll<HTMLButtonElement>('button').forEach(button => { button.disabled = false })\n this.clearError()\n this.showError()\n }\n }\n\n private buildSummaryHTML(s: I18nMessages['clarify']['summary']): string {\n const said = this.summaryCtx?.originalDescription?.trim()\n const saidBlock = said\n ? `<div class=\"mtb-summary-section\">\n <div class=\"mtb-summary-label\">${escapeHtml(s.what_you_said)}</div>\n <div class=\"mtb-summary-quote\">${escapeHtml(said)}</div>\n </div>`\n : ''\n\n const pairs = this.clarifiedPairs()\n const clarifiedBlock = pairs.length\n ? `<div class=\"mtb-summary-section\">\n <div class=\"mtb-summary-label\">${escapeHtml(s.clarified)}</div>\n ${pairs.map(p => `<div class=\"mtb-summary-qa\"><span class=\"mtb-summary-q\">${escapeHtml(p.q)}</span><span class=\"mtb-summary-a\">${escapeHtml(p.a)}</span></div>`).join('')}\n </div>`\n : ''\n\n return `\n <div class=\"mtb-summary-head\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>\n <span>${escapeHtml(s.ready)}</span>\n </div>\n ${saidBlock}\n ${clarifiedBlock}\n `\n }\n\n private clarifiedPairs(): { q: string; a: string }[] {\n const pairs: { q: string; a: string }[] = []\n for (let i = 0; i < this.lastMessages.length - 1; i++) {\n const q = this.lastMessages[i]\n const a = this.lastMessages[i + 1]\n if (q.role !== 'user' && a.role === 'user') pairs.push({ q: q.content, a: a.content })\n }\n return pairs\n }\n\n private renderConversation(messages: ClarifyMessage[], done: boolean): void {\n this.lastMessages = messages\n this.renderMessages(messages)\n const last = messages[messages.length - 1]\n if (!done && (!last || last.role === 'user')) this.showThinking()\n }\n\n private renderMessages(messages: ClarifyMessage[]): void {\n this.messagesEl.innerHTML = ''\n for (const msg of messages) {\n this.appendMessage(msg)\n }\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private appendMessage(msg: ClarifyMessage): void {\n const bubble = document.createElement('div')\n bubble.className = msg.role === 'user' ? 'mtb-clarify-bubble mtb-clarify-user' : 'mtb-clarify-bubble mtb-clarify-ai'\n bubble.textContent = msg.content\n this.messagesEl.appendChild(bubble)\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private showThinking(): void {\n if (this.messagesEl.querySelector('.mtb-clarify-thinking')) return\n const dots = document.createElement('div')\n dots.className = 'mtb-clarify-bubble mtb-clarify-ai mtb-clarify-thinking'\n dots.innerHTML = '<span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span>'\n this.messagesEl.appendChild(dots)\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private removeThinking(): void {\n this.messagesEl.querySelector('.mtb-clarify-thinking')?.remove()\n }\n\n destroy(): void {\n this.destroyed = true\n this.stopPolling()\n this.el.remove()\n }\n}\n\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport { BRAND_COLOR } from '../styles'\n\nconst SUCCESS_AUTO_CLOSE_MS = 5000\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport interface SuccessCardOptions {\n skipFollowup?: boolean\n emailCapture?: {\n onSubmit: (email: string) => Promise<boolean>\n }\n}\n\nexport class SuccessCard {\n private el: HTMLDivElement\n private messages: I18nMessages\n\n constructor(shadow: ShadowContainer, messages: I18nMessages, onClose: () => void, onViewFeedback?: () => void, options?: SuccessCardOptions) {\n this.messages = messages\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-success')\n this.el.style.right = '20px'\n this.el.style.bottom = '20px'\n\n const title = options?.skipFollowup ? messages.success.title_no_ai : messages.success.title\n const msg = options?.skipFollowup ? messages.success.message_no_ai : messages.success.message\n\n const viewLink = onViewFeedback\n ? `<button class=\"mtb-view-feedback-link\">${messages.success.view_feedback} <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg></button>`\n : ''\n\n const emailCapture = options?.emailCapture\n ? `\n <div class=\"mtb-email-capture\">\n <div class=\"mtb-email-prompt\">${messages.success.email_prompt}</div>\n <div class=\"mtb-email-row\">\n <input class=\"mtb-email-input\" type=\"email\" placeholder=\"${messages.success.email_placeholder}\">\n <button class=\"mtb-email-submit\">${messages.success.email_submit}</button>\n </div>\n <div class=\"mtb-email-error\" hidden>${messages.success.email_error}</div>\n </div>`\n : ''\n\n this.el.innerHTML = `\n <div class=\"mtb-success-icon\">\n <svg width=\"23\" height=\"23\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${BRAND_COLOR}\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>\n </div>\n <div class=\"mtb-success-title\">${title}</div>\n <div class=\"mtb-success-msg\">${msg}</div>\n ${emailCapture}\n ${viewLink}\n <button class=\"mtb-close-link\">${messages.success.close}</button>\n `\n shadow.append(this.el)\n this.el.querySelector('.mtb-close-link')!.addEventListener('click', onClose)\n\n if (onViewFeedback) {\n this.el.querySelector('.mtb-view-feedback-link')!.addEventListener('click', onViewFeedback)\n }\n\n if (options?.emailCapture) {\n this.bindEmailCapture(options.emailCapture.onSubmit)\n } else {\n setTimeout(() => onClose(), SUCCESS_AUTO_CLOSE_MS)\n }\n }\n\n private bindEmailCapture(onSubmit: (email: string) => Promise<boolean>): void {\n const input = this.el.querySelector<HTMLInputElement>('.mtb-email-input')!\n const submit = this.el.querySelector<HTMLButtonElement>('.mtb-email-submit')!\n const error = this.el.querySelector<HTMLDivElement>('.mtb-email-error')!\n\n const handle = async () => {\n const email = input.value.trim()\n if (!EMAIL_PATTERN.test(email)) {\n input.classList.add('mtb-email-invalid')\n return\n }\n input.classList.remove('mtb-email-invalid')\n error.hidden = true\n submit.disabled = true\n\n const saved = await onSubmit(email)\n if (saved) {\n this.el.querySelector('.mtb-email-capture')!.innerHTML =\n `<div class=\"mtb-email-saved\">${this.messages.success.email_saved}</div>`\n } else {\n error.hidden = false\n submit.disabled = false\n }\n }\n\n submit.addEventListener('click', handle)\n input.addEventListener('keydown', (event) => {\n if (event.key === 'Enter') handle()\n })\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n","export function resolveUrl(url, baseUrl) {\n // url is absolute already\n if (url.match(/^[a-z]+:\\/\\//i)) {\n return url;\n }\n // url is absolute already, without protocol\n if (url.match(/^\\/\\//)) {\n return window.location.protocol + url;\n }\n // dataURI, mailto:, tel:, etc.\n if (url.match(/^[a-z]+:/i)) {\n return url;\n }\n const doc = document.implementation.createHTMLDocument();\n const base = doc.createElement('base');\n const a = doc.createElement('a');\n doc.head.appendChild(base);\n doc.body.appendChild(a);\n if (baseUrl) {\n base.href = baseUrl;\n }\n a.href = url;\n return a.href;\n}\nexport const uuid = (() => {\n // generate uuid for className of pseudo elements.\n // We should not use GUIDs, otherwise pseudo elements sometimes cannot be captured.\n let counter = 0;\n // ref: http://stackoverflow.com/a/6248722/2519373\n const random = () => \n // eslint-disable-next-line no-bitwise\n `0000${((Math.random() * 36 ** 4) << 0).toString(36)}`.slice(-4);\n return () => {\n counter += 1;\n return `u${random()}${counter}`;\n };\n})();\nexport function delay(ms) {\n return (args) => new Promise((resolve) => {\n setTimeout(() => resolve(args), ms);\n });\n}\nexport function toArray(arrayLike) {\n const arr = [];\n for (let i = 0, l = arrayLike.length; i < l; i++) {\n arr.push(arrayLike[i]);\n }\n return arr;\n}\nlet styleProps = null;\nexport function getStyleProperties(options = {}) {\n if (styleProps) {\n return styleProps;\n }\n if (options.includeStyleProperties) {\n styleProps = options.includeStyleProperties;\n return styleProps;\n }\n styleProps = toArray(window.getComputedStyle(document.documentElement));\n return styleProps;\n}\nfunction px(node, styleProperty) {\n const win = node.ownerDocument.defaultView || window;\n const val = win.getComputedStyle(node).getPropertyValue(styleProperty);\n return val ? parseFloat(val.replace('px', '')) : 0;\n}\nfunction getNodeWidth(node) {\n const leftBorder = px(node, 'border-left-width');\n const rightBorder = px(node, 'border-right-width');\n return node.clientWidth + leftBorder + rightBorder;\n}\nfunction getNodeHeight(node) {\n const topBorder = px(node, 'border-top-width');\n const bottomBorder = px(node, 'border-bottom-width');\n return node.clientHeight + topBorder + bottomBorder;\n}\nexport function getImageSize(targetNode, options = {}) {\n const width = options.width || getNodeWidth(targetNode);\n const height = options.height || getNodeHeight(targetNode);\n return { width, height };\n}\nexport function getPixelRatio() {\n let ratio;\n let FINAL_PROCESS;\n try {\n FINAL_PROCESS = process;\n }\n catch (e) {\n // pass\n }\n const val = FINAL_PROCESS && FINAL_PROCESS.env\n ? FINAL_PROCESS.env.devicePixelRatio\n : null;\n if (val) {\n ratio = parseInt(val, 10);\n if (Number.isNaN(ratio)) {\n ratio = 1;\n }\n }\n return ratio || window.devicePixelRatio || 1;\n}\n// @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size\nconst canvasDimensionLimit = 16384;\nexport function checkCanvasDimensions(canvas) {\n if (canvas.width > canvasDimensionLimit ||\n canvas.height > canvasDimensionLimit) {\n if (canvas.width > canvasDimensionLimit &&\n canvas.height > canvasDimensionLimit) {\n if (canvas.width > canvas.height) {\n canvas.height *= canvasDimensionLimit / canvas.width;\n canvas.width = canvasDimensionLimit;\n }\n else {\n canvas.width *= canvasDimensionLimit / canvas.height;\n canvas.height = canvasDimensionLimit;\n }\n }\n else if (canvas.width > canvasDimensionLimit) {\n canvas.height *= canvasDimensionLimit / canvas.width;\n canvas.width = canvasDimensionLimit;\n }\n else {\n canvas.width *= canvasDimensionLimit / canvas.height;\n canvas.height = canvasDimensionLimit;\n }\n }\n}\nexport function canvasToBlob(canvas, options = {}) {\n if (canvas.toBlob) {\n return new Promise((resolve) => {\n canvas.toBlob(resolve, options.type ? options.type : 'image/png', options.quality ? options.quality : 1);\n });\n }\n return new Promise((resolve) => {\n const binaryString = window.atob(canvas\n .toDataURL(options.type ? options.type : undefined, options.quality ? options.quality : undefined)\n .split(',')[1]);\n const len = binaryString.length;\n const binaryArray = new Uint8Array(len);\n for (let i = 0; i < len; i += 1) {\n binaryArray[i] = binaryString.charCodeAt(i);\n }\n resolve(new Blob([binaryArray], {\n type: options.type ? options.type : 'image/png',\n }));\n });\n}\nexport function createImage(url) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n img.decode().then(() => {\n requestAnimationFrame(() => resolve(img));\n });\n };\n img.onerror = reject;\n img.crossOrigin = 'anonymous';\n img.decoding = 'async';\n img.src = url;\n });\n}\nexport async function svgToDataURL(svg) {\n return Promise.resolve()\n .then(() => new XMLSerializer().serializeToString(svg))\n .then(encodeURIComponent)\n .then((html) => `data:image/svg+xml;charset=utf-8,${html}`);\n}\nexport async function nodeToDataURL(node, width, height) {\n const xmlns = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(xmlns, 'svg');\n const foreignObject = document.createElementNS(xmlns, 'foreignObject');\n svg.setAttribute('width', `${width}`);\n svg.setAttribute('height', `${height}`);\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n foreignObject.setAttribute('x', '0');\n foreignObject.setAttribute('y', '0');\n foreignObject.setAttribute('externalResourcesRequired', 'true');\n svg.appendChild(foreignObject);\n foreignObject.appendChild(node);\n return svgToDataURL(svg);\n}\nexport const isInstanceOfElement = (node, instance) => {\n if (node instanceof instance)\n return true;\n const nodePrototype = Object.getPrototypeOf(node);\n if (nodePrototype === null)\n return false;\n return (nodePrototype.constructor.name === instance.name ||\n isInstanceOfElement(nodePrototype, instance));\n};\n//# sourceMappingURL=util.js.map","import { uuid, getStyleProperties } from './util';\nfunction formatCSSText(style) {\n const content = style.getPropertyValue('content');\n return `${style.cssText} content: '${content.replace(/'|\"/g, '')}';`;\n}\nfunction formatCSSProperties(style, options) {\n return getStyleProperties(options)\n .map((name) => {\n const value = style.getPropertyValue(name);\n const priority = style.getPropertyPriority(name);\n return `${name}: ${value}${priority ? ' !important' : ''};`;\n })\n .join(' ');\n}\nfunction getPseudoElementStyle(className, pseudo, style, options) {\n const selector = `.${className}:${pseudo}`;\n const cssText = style.cssText\n ? formatCSSText(style)\n : formatCSSProperties(style, options);\n return document.createTextNode(`${selector}{${cssText}}`);\n}\nfunction clonePseudoElement(nativeNode, clonedNode, pseudo, options) {\n const style = window.getComputedStyle(nativeNode, pseudo);\n const content = style.getPropertyValue('content');\n if (content === '' || content === 'none') {\n return;\n }\n const className = uuid();\n try {\n clonedNode.className = `${clonedNode.className} ${className}`;\n }\n catch (err) {\n return;\n }\n const styleElement = document.createElement('style');\n styleElement.appendChild(getPseudoElementStyle(className, pseudo, style, options));\n clonedNode.appendChild(styleElement);\n}\nexport function clonePseudoElements(nativeNode, clonedNode, options) {\n clonePseudoElement(nativeNode, clonedNode, ':before', options);\n clonePseudoElement(nativeNode, clonedNode, ':after', options);\n}\n//# sourceMappingURL=clone-pseudos.js.map","const WOFF = 'application/font-woff';\nconst JPEG = 'image/jpeg';\nconst mimes = {\n woff: WOFF,\n woff2: WOFF,\n ttf: 'application/font-truetype',\n eot: 'application/vnd.ms-fontobject',\n png: 'image/png',\n jpg: JPEG,\n jpeg: JPEG,\n gif: 'image/gif',\n tiff: 'image/tiff',\n svg: 'image/svg+xml',\n webp: 'image/webp',\n};\nfunction getExtension(url) {\n const match = /\\.([^./]*?)$/g.exec(url);\n return match ? match[1] : '';\n}\nexport function getMimeType(url) {\n const extension = getExtension(url).toLowerCase();\n return mimes[extension] || '';\n}\n//# sourceMappingURL=mimes.js.map","function getContentFromDataUrl(dataURL) {\n return dataURL.split(/,/)[1];\n}\nexport function isDataUrl(url) {\n return url.search(/^(data:)/) !== -1;\n}\nexport function makeDataUrl(content, mimeType) {\n return `data:${mimeType};base64,${content}`;\n}\nexport async function fetchAsDataURL(url, init, process) {\n const res = await fetch(url, init);\n if (res.status === 404) {\n throw new Error(`Resource \"${res.url}\" not found`);\n }\n const blob = await res.blob();\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = reject;\n reader.onloadend = () => {\n try {\n resolve(process({ res, result: reader.result }));\n }\n catch (error) {\n reject(error);\n }\n };\n reader.readAsDataURL(blob);\n });\n}\nconst cache = {};\nfunction getCacheKey(url, contentType, includeQueryParams) {\n let key = url.replace(/\\?.*/, '');\n if (includeQueryParams) {\n key = url;\n }\n // font resource\n if (/ttf|otf|eot|woff2?/i.test(key)) {\n key = key.replace(/.*\\//, '');\n }\n return contentType ? `[${contentType}]${key}` : key;\n}\nexport async function resourceToDataURL(resourceUrl, contentType, options) {\n const cacheKey = getCacheKey(resourceUrl, contentType, options.includeQueryParams);\n if (cache[cacheKey] != null) {\n return cache[cacheKey];\n }\n // ref: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache\n if (options.cacheBust) {\n // eslint-disable-next-line no-param-reassign\n resourceUrl += (/\\?/.test(resourceUrl) ? '&' : '?') + new Date().getTime();\n }\n let dataURL;\n try {\n const content = await fetchAsDataURL(resourceUrl, options.fetchRequestInit, ({ res, result }) => {\n if (!contentType) {\n // eslint-disable-next-line no-param-reassign\n contentType = res.headers.get('Content-Type') || '';\n }\n return getContentFromDataUrl(result);\n });\n dataURL = makeDataUrl(content, contentType);\n }\n catch (error) {\n dataURL = options.imagePlaceholder || '';\n let msg = `Failed to fetch resource: ${resourceUrl}`;\n if (error) {\n msg = typeof error === 'string' ? error : error.message;\n }\n if (msg) {\n console.warn(msg);\n }\n }\n cache[cacheKey] = dataURL;\n return dataURL;\n}\n//# sourceMappingURL=dataurl.js.map","import { clonePseudoElements } from './clone-pseudos';\nimport { createImage, toArray, isInstanceOfElement, getStyleProperties, } from './util';\nimport { getMimeType } from './mimes';\nimport { resourceToDataURL } from './dataurl';\nasync function cloneCanvasElement(canvas) {\n const dataURL = canvas.toDataURL();\n if (dataURL === 'data:,') {\n return canvas.cloneNode(false);\n }\n return createImage(dataURL);\n}\nasync function cloneVideoElement(video, options) {\n if (video.currentSrc) {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n canvas.width = video.clientWidth;\n canvas.height = video.clientHeight;\n ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n const dataURL = canvas.toDataURL();\n return createImage(dataURL);\n }\n const poster = video.poster;\n const contentType = getMimeType(poster);\n const dataURL = await resourceToDataURL(poster, contentType, options);\n return createImage(dataURL);\n}\nasync function cloneIFrameElement(iframe, options) {\n var _a;\n try {\n if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) {\n return (await cloneNode(iframe.contentDocument.body, options, true));\n }\n }\n catch (_b) {\n // Failed to clone iframe\n }\n return iframe.cloneNode(false);\n}\nasync function cloneSingleNode(node, options) {\n if (isInstanceOfElement(node, HTMLCanvasElement)) {\n return cloneCanvasElement(node);\n }\n if (isInstanceOfElement(node, HTMLVideoElement)) {\n return cloneVideoElement(node, options);\n }\n if (isInstanceOfElement(node, HTMLIFrameElement)) {\n return cloneIFrameElement(node, options);\n }\n return node.cloneNode(isSVGElement(node));\n}\nconst isSlotElement = (node) => node.tagName != null && node.tagName.toUpperCase() === 'SLOT';\nconst isSVGElement = (node) => node.tagName != null && node.tagName.toUpperCase() === 'SVG';\nasync function cloneChildren(nativeNode, clonedNode, options) {\n var _a, _b;\n if (isSVGElement(clonedNode)) {\n return clonedNode;\n }\n let children = [];\n if (isSlotElement(nativeNode) && nativeNode.assignedNodes) {\n children = toArray(nativeNode.assignedNodes());\n }\n else if (isInstanceOfElement(nativeNode, HTMLIFrameElement) &&\n ((_a = nativeNode.contentDocument) === null || _a === void 0 ? void 0 : _a.body)) {\n children = toArray(nativeNode.contentDocument.body.childNodes);\n }\n else {\n children = toArray(((_b = nativeNode.shadowRoot) !== null && _b !== void 0 ? _b : nativeNode).childNodes);\n }\n if (children.length === 0 ||\n isInstanceOfElement(nativeNode, HTMLVideoElement)) {\n return clonedNode;\n }\n await children.reduce((deferred, child) => deferred\n .then(() => cloneNode(child, options))\n .then((clonedChild) => {\n if (clonedChild) {\n clonedNode.appendChild(clonedChild);\n }\n }), Promise.resolve());\n return clonedNode;\n}\nfunction cloneCSSStyle(nativeNode, clonedNode, options) {\n const targetStyle = clonedNode.style;\n if (!targetStyle) {\n return;\n }\n const sourceStyle = window.getComputedStyle(nativeNode);\n if (sourceStyle.cssText) {\n targetStyle.cssText = sourceStyle.cssText;\n targetStyle.transformOrigin = sourceStyle.transformOrigin;\n }\n else {\n getStyleProperties(options).forEach((name) => {\n let value = sourceStyle.getPropertyValue(name);\n if (name === 'font-size' && value.endsWith('px')) {\n const reducedFont = Math.floor(parseFloat(value.substring(0, value.length - 2))) - 0.1;\n value = `${reducedFont}px`;\n }\n if (isInstanceOfElement(nativeNode, HTMLIFrameElement) &&\n name === 'display' &&\n value === 'inline') {\n value = 'block';\n }\n if (name === 'd' && clonedNode.getAttribute('d')) {\n value = `path(${clonedNode.getAttribute('d')})`;\n }\n targetStyle.setProperty(name, value, sourceStyle.getPropertyPriority(name));\n });\n }\n}\nfunction cloneInputValue(nativeNode, clonedNode) {\n if (isInstanceOfElement(nativeNode, HTMLTextAreaElement)) {\n clonedNode.innerHTML = nativeNode.value;\n }\n if (isInstanceOfElement(nativeNode, HTMLInputElement)) {\n clonedNode.setAttribute('value', nativeNode.value);\n }\n}\nfunction cloneSelectValue(nativeNode, clonedNode) {\n if (isInstanceOfElement(nativeNode, HTMLSelectElement)) {\n const clonedSelect = clonedNode;\n const selectedOption = Array.from(clonedSelect.children).find((child) => nativeNode.value === child.getAttribute('value'));\n if (selectedOption) {\n selectedOption.setAttribute('selected', '');\n }\n }\n}\nfunction decorate(nativeNode, clonedNode, options) {\n if (isInstanceOfElement(clonedNode, Element)) {\n cloneCSSStyle(nativeNode, clonedNode, options);\n clonePseudoElements(nativeNode, clonedNode, options);\n cloneInputValue(nativeNode, clonedNode);\n cloneSelectValue(nativeNode, clonedNode);\n }\n return clonedNode;\n}\nasync function ensureSVGSymbols(clone, options) {\n const uses = clone.querySelectorAll ? clone.querySelectorAll('use') : [];\n if (uses.length === 0) {\n return clone;\n }\n const processedDefs = {};\n for (let i = 0; i < uses.length; i++) {\n const use = uses[i];\n const id = use.getAttribute('xlink:href');\n if (id) {\n const exist = clone.querySelector(id);\n const definition = document.querySelector(id);\n if (!exist && definition && !processedDefs[id]) {\n // eslint-disable-next-line no-await-in-loop\n processedDefs[id] = (await cloneNode(definition, options, true));\n }\n }\n }\n const nodes = Object.values(processedDefs);\n if (nodes.length) {\n const ns = 'http://www.w3.org/1999/xhtml';\n const svg = document.createElementNS(ns, 'svg');\n svg.setAttribute('xmlns', ns);\n svg.style.position = 'absolute';\n svg.style.width = '0';\n svg.style.height = '0';\n svg.style.overflow = 'hidden';\n svg.style.display = 'none';\n const defs = document.createElementNS(ns, 'defs');\n svg.appendChild(defs);\n for (let i = 0; i < nodes.length; i++) {\n defs.appendChild(nodes[i]);\n }\n clone.appendChild(svg);\n }\n return clone;\n}\nexport async function cloneNode(node, options, isRoot) {\n if (!isRoot && options.filter && !options.filter(node)) {\n return null;\n }\n return Promise.resolve(node)\n .then((clonedNode) => cloneSingleNode(clonedNode, options))\n .then((clonedNode) => cloneChildren(node, clonedNode, options))\n .then((clonedNode) => decorate(node, clonedNode, options))\n .then((clonedNode) => ensureSVGSymbols(clonedNode, options));\n}\n//# sourceMappingURL=clone-node.js.map","import { resolveUrl } from './util';\nimport { getMimeType } from './mimes';\nimport { isDataUrl, makeDataUrl, resourceToDataURL } from './dataurl';\nconst URL_REGEX = /url\\((['\"]?)([^'\"]+?)\\1\\)/g;\nconst URL_WITH_FORMAT_REGEX = /url\\([^)]+\\)\\s*format\\(([\"']?)([^\"']+)\\1\\)/g;\nconst FONT_SRC_REGEX = /src:\\s*(?:url\\([^)]+\\)\\s*format\\([^)]+\\)[,;]\\s*)+/g;\nfunction toRegex(url) {\n // eslint-disable-next-line no-useless-escape\n const escaped = url.replace(/([.*+?^${}()|\\[\\]\\/\\\\])/g, '\\\\$1');\n return new RegExp(`(url\\\\(['\"]?)(${escaped})(['\"]?\\\\))`, 'g');\n}\nexport function parseURLs(cssText) {\n const urls = [];\n cssText.replace(URL_REGEX, (raw, quotation, url) => {\n urls.push(url);\n return raw;\n });\n return urls.filter((url) => !isDataUrl(url));\n}\nexport async function embed(cssText, resourceURL, baseURL, options, getContentFromUrl) {\n try {\n const resolvedURL = baseURL ? resolveUrl(resourceURL, baseURL) : resourceURL;\n const contentType = getMimeType(resourceURL);\n let dataURL;\n if (getContentFromUrl) {\n const content = await getContentFromUrl(resolvedURL);\n dataURL = makeDataUrl(content, contentType);\n }\n else {\n dataURL = await resourceToDataURL(resolvedURL, contentType, options);\n }\n return cssText.replace(toRegex(resourceURL), `$1${dataURL}$3`);\n }\n catch (error) {\n // pass\n }\n return cssText;\n}\nfunction filterPreferredFontFormat(str, { preferredFontFormat }) {\n return !preferredFontFormat\n ? str\n : str.replace(FONT_SRC_REGEX, (match) => {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const [src, , format] = URL_WITH_FORMAT_REGEX.exec(match) || [];\n if (!format) {\n return '';\n }\n if (format === preferredFontFormat) {\n return `src: ${src};`;\n }\n }\n });\n}\nexport function shouldEmbed(url) {\n return url.search(URL_REGEX) !== -1;\n}\nexport async function embedResources(cssText, baseUrl, options) {\n if (!shouldEmbed(cssText)) {\n return cssText;\n }\n const filteredCSSText = filterPreferredFontFormat(cssText, options);\n const urls = parseURLs(filteredCSSText);\n return urls.reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText));\n}\n//# sourceMappingURL=embed-resources.js.map","import { embedResources } from './embed-resources';\nimport { toArray, isInstanceOfElement } from './util';\nimport { isDataUrl, resourceToDataURL } from './dataurl';\nimport { getMimeType } from './mimes';\nasync function embedProp(propName, node, options) {\n var _a;\n const propValue = (_a = node.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue(propName);\n if (propValue) {\n const cssString = await embedResources(propValue, null, options);\n node.style.setProperty(propName, cssString, node.style.getPropertyPriority(propName));\n return true;\n }\n return false;\n}\nasync function embedBackground(clonedNode, options) {\n ;\n (await embedProp('background', clonedNode, options)) ||\n (await embedProp('background-image', clonedNode, options));\n (await embedProp('mask', clonedNode, options)) ||\n (await embedProp('-webkit-mask', clonedNode, options)) ||\n (await embedProp('mask-image', clonedNode, options)) ||\n (await embedProp('-webkit-mask-image', clonedNode, options));\n}\nasync function embedImageNode(clonedNode, options) {\n const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement);\n if (!(isImageElement && !isDataUrl(clonedNode.src)) &&\n !(isInstanceOfElement(clonedNode, SVGImageElement) &&\n !isDataUrl(clonedNode.href.baseVal))) {\n return;\n }\n const url = isImageElement ? clonedNode.src : clonedNode.href.baseVal;\n const dataURL = await resourceToDataURL(url, getMimeType(url), options);\n await new Promise((resolve, reject) => {\n clonedNode.onload = resolve;\n clonedNode.onerror = options.onImageErrorHandler\n ? (...attributes) => {\n try {\n resolve(options.onImageErrorHandler(...attributes));\n }\n catch (error) {\n reject(error);\n }\n }\n : reject;\n const image = clonedNode;\n if (image.decode) {\n image.decode = resolve;\n }\n if (image.loading === 'lazy') {\n image.loading = 'eager';\n }\n if (isImageElement) {\n clonedNode.srcset = '';\n clonedNode.src = dataURL;\n }\n else {\n clonedNode.href.baseVal = dataURL;\n }\n });\n}\nasync function embedChildren(clonedNode, options) {\n const children = toArray(clonedNode.childNodes);\n const deferreds = children.map((child) => embedImages(child, options));\n await Promise.all(deferreds).then(() => clonedNode);\n}\nexport async function embedImages(clonedNode, options) {\n if (isInstanceOfElement(clonedNode, Element)) {\n await embedBackground(clonedNode, options);\n await embedImageNode(clonedNode, options);\n await embedChildren(clonedNode, options);\n }\n}\n//# sourceMappingURL=embed-images.js.map","export function applyStyle(node, options) {\n const { style } = node;\n if (options.backgroundColor) {\n style.backgroundColor = options.backgroundColor;\n }\n if (options.width) {\n style.width = `${options.width}px`;\n }\n if (options.height) {\n style.height = `${options.height}px`;\n }\n const manual = options.style;\n if (manual != null) {\n Object.keys(manual).forEach((key) => {\n style[key] = manual[key];\n });\n }\n return node;\n}\n//# sourceMappingURL=apply-style.js.map","import { toArray } from './util';\nimport { fetchAsDataURL } from './dataurl';\nimport { shouldEmbed, embedResources } from './embed-resources';\nconst cssFetchCache = {};\nasync function fetchCSS(url) {\n let cache = cssFetchCache[url];\n if (cache != null) {\n return cache;\n }\n const res = await fetch(url);\n const cssText = await res.text();\n cache = { url, cssText };\n cssFetchCache[url] = cache;\n return cache;\n}\nasync function embedFonts(data, options) {\n let cssText = data.cssText;\n const regexUrl = /url\\([\"']?([^\"')]+)[\"']?\\)/g;\n const fontLocs = cssText.match(/url\\([^)]+\\)/g) || [];\n const loadFonts = fontLocs.map(async (loc) => {\n let url = loc.replace(regexUrl, '$1');\n if (!url.startsWith('https://')) {\n url = new URL(url, data.url).href;\n }\n return fetchAsDataURL(url, options.fetchRequestInit, ({ result }) => {\n cssText = cssText.replace(loc, `url(${result})`);\n return [loc, result];\n });\n });\n return Promise.all(loadFonts).then(() => cssText);\n}\nfunction parseCSS(source) {\n if (source == null) {\n return [];\n }\n const result = [];\n const commentsRegex = /(\\/\\*[\\s\\S]*?\\*\\/)/gi;\n // strip out comments\n let cssText = source.replace(commentsRegex, '');\n // eslint-disable-next-line prefer-regex-literals\n const keyframesRegex = new RegExp('((@.*?keyframes [\\\\s\\\\S]*?){([\\\\s\\\\S]*?}\\\\s*?)})', 'gi');\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const matches = keyframesRegex.exec(cssText);\n if (matches === null) {\n break;\n }\n result.push(matches[0]);\n }\n cssText = cssText.replace(keyframesRegex, '');\n const importRegex = /@import[\\s\\S]*?url\\([^)]*\\)[\\s\\S]*?;/gi;\n // to match css & media queries together\n const combinedCSSRegex = '((\\\\s*?(?:\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/)?\\\\s*?@media[\\\\s\\\\S]' +\n '*?){([\\\\s\\\\S]*?)}\\\\s*?})|(([\\\\s\\\\S]*?){([\\\\s\\\\S]*?)})';\n // unified regex\n const unifiedRegex = new RegExp(combinedCSSRegex, 'gi');\n // eslint-disable-next-line no-constant-condition\n while (true) {\n let matches = importRegex.exec(cssText);\n if (matches === null) {\n matches = unifiedRegex.exec(cssText);\n if (matches === null) {\n break;\n }\n else {\n importRegex.lastIndex = unifiedRegex.lastIndex;\n }\n }\n else {\n unifiedRegex.lastIndex = importRegex.lastIndex;\n }\n result.push(matches[0]);\n }\n return result;\n}\nasync function getCSSRules(styleSheets, options) {\n const ret = [];\n const deferreds = [];\n // First loop inlines imports\n styleSheets.forEach((sheet) => {\n if ('cssRules' in sheet) {\n try {\n toArray(sheet.cssRules || []).forEach((item, index) => {\n if (item.type === CSSRule.IMPORT_RULE) {\n let importIndex = index + 1;\n const url = item.href;\n const deferred = fetchCSS(url)\n .then((metadata) => embedFonts(metadata, options))\n .then((cssText) => parseCSS(cssText).forEach((rule) => {\n try {\n sheet.insertRule(rule, rule.startsWith('@import')\n ? (importIndex += 1)\n : sheet.cssRules.length);\n }\n catch (error) {\n console.error('Error inserting rule from remote css', {\n rule,\n error,\n });\n }\n }))\n .catch((e) => {\n console.error('Error loading remote css', e.toString());\n });\n deferreds.push(deferred);\n }\n });\n }\n catch (e) {\n const inline = styleSheets.find((a) => a.href == null) || document.styleSheets[0];\n if (sheet.href != null) {\n deferreds.push(fetchCSS(sheet.href)\n .then((metadata) => embedFonts(metadata, options))\n .then((cssText) => parseCSS(cssText).forEach((rule) => {\n inline.insertRule(rule, inline.cssRules.length);\n }))\n .catch((err) => {\n console.error('Error loading remote stylesheet', err);\n }));\n }\n console.error('Error inlining remote css file', e);\n }\n }\n });\n return Promise.all(deferreds).then(() => {\n // Second loop parses rules\n styleSheets.forEach((sheet) => {\n if ('cssRules' in sheet) {\n try {\n toArray(sheet.cssRules || []).forEach((item) => {\n ret.push(item);\n });\n }\n catch (e) {\n console.error(`Error while reading CSS rules from ${sheet.href}`, e);\n }\n }\n });\n return ret;\n });\n}\nfunction getWebFontRules(cssRules) {\n return cssRules\n .filter((rule) => rule.type === CSSRule.FONT_FACE_RULE)\n .filter((rule) => shouldEmbed(rule.style.getPropertyValue('src')));\n}\nasync function parseWebFontRules(node, options) {\n if (node.ownerDocument == null) {\n throw new Error('Provided element is not within a Document');\n }\n const styleSheets = toArray(node.ownerDocument.styleSheets);\n const cssRules = await getCSSRules(styleSheets, options);\n return getWebFontRules(cssRules);\n}\nfunction normalizeFontFamily(font) {\n return font.trim().replace(/[\"']/g, '');\n}\nfunction getUsedFonts(node) {\n const fonts = new Set();\n function traverse(node) {\n const fontFamily = node.style.fontFamily || getComputedStyle(node).fontFamily;\n fontFamily.split(',').forEach((font) => {\n fonts.add(normalizeFontFamily(font));\n });\n Array.from(node.children).forEach((child) => {\n if (child instanceof HTMLElement) {\n traverse(child);\n }\n });\n }\n traverse(node);\n return fonts;\n}\nexport async function getWebFontCSS(node, options) {\n const rules = await parseWebFontRules(node, options);\n const usedFonts = getUsedFonts(node);\n const cssTexts = await Promise.all(rules\n .filter((rule) => usedFonts.has(normalizeFontFamily(rule.style.fontFamily)))\n .map((rule) => {\n const baseUrl = rule.parentStyleSheet\n ? rule.parentStyleSheet.href\n : null;\n return embedResources(rule.cssText, baseUrl, options);\n }));\n return cssTexts.join('\\n');\n}\nexport async function embedWebFonts(clonedNode, options) {\n const cssText = options.fontEmbedCSS != null\n ? options.fontEmbedCSS\n : options.skipFonts\n ? null\n : await getWebFontCSS(clonedNode, options);\n if (cssText) {\n const styleNode = document.createElement('style');\n const sytleContent = document.createTextNode(cssText);\n styleNode.appendChild(sytleContent);\n if (clonedNode.firstChild) {\n clonedNode.insertBefore(styleNode, clonedNode.firstChild);\n }\n else {\n clonedNode.appendChild(styleNode);\n }\n }\n}\n//# sourceMappingURL=embed-webfonts.js.map","import { cloneNode } from './clone-node';\nimport { embedImages } from './embed-images';\nimport { applyStyle } from './apply-style';\nimport { embedWebFonts, getWebFontCSS } from './embed-webfonts';\nimport { getImageSize, getPixelRatio, createImage, canvasToBlob, nodeToDataURL, checkCanvasDimensions, } from './util';\nexport async function toSvg(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const clonedNode = (await cloneNode(node, options, true));\n await embedWebFonts(clonedNode, options);\n await embedImages(clonedNode, options);\n applyStyle(clonedNode, options);\n const datauri = await nodeToDataURL(clonedNode, width, height);\n return datauri;\n}\nexport async function toCanvas(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const svg = await toSvg(node, options);\n const img = await createImage(svg);\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n const ratio = options.pixelRatio || getPixelRatio();\n const canvasWidth = options.canvasWidth || width;\n const canvasHeight = options.canvasHeight || height;\n canvas.width = canvasWidth * ratio;\n canvas.height = canvasHeight * ratio;\n if (!options.skipAutoScale) {\n checkCanvasDimensions(canvas);\n }\n canvas.style.width = `${canvasWidth}`;\n canvas.style.height = `${canvasHeight}`;\n if (options.backgroundColor) {\n context.fillStyle = options.backgroundColor;\n context.fillRect(0, 0, canvas.width, canvas.height);\n }\n context.drawImage(img, 0, 0, canvas.width, canvas.height);\n return canvas;\n}\nexport async function toPixelData(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const canvas = await toCanvas(node, options);\n const ctx = canvas.getContext('2d');\n return ctx.getImageData(0, 0, width, height).data;\n}\nexport async function toPng(node, options = {}) {\n const canvas = await toCanvas(node, options);\n return canvas.toDataURL();\n}\nexport async function toJpeg(node, options = {}) {\n const canvas = await toCanvas(node, options);\n return canvas.toDataURL('image/jpeg', options.quality || 1);\n}\nexport async function toBlob(node, options = {}) {\n const canvas = await toCanvas(node, options);\n const blob = await canvasToBlob(canvas);\n return blob;\n}\nexport async function getFontEmbedCSS(node, options = {}) {\n return getWebFontCSS(node, options);\n}\n//# sourceMappingURL=index.js.map","import { toJpeg } from 'html-to-image'\nimport type { Annotation } from '../types'\nimport { BRAND_COLOR, FONT_STACK } from '../styles'\n\n// Capture at CSS pixels (pixelRatio 1) as JPEG to keep the upload small: on\n// retina screens the default devicePixelRatio would quadruple the pixel count,\n// and the model downscales past ~1568px anyway.\n//\n// Annotations are baked onto the captured bitmap with canvas 2D afterwards —\n// never mounted into the live page — so the capture leaves the page visually\n// untouched no matter how long the DOM snapshot takes.\nexport async function captureScreenshot(annotations: Annotation[] = []): Promise<Blob | null> {\n try {\n const dataUrl = await toJpeg(document.body, {\n quality: 0.85,\n pixelRatio: 1,\n backgroundColor: '#ffffff',\n skipFonts: true,\n skipAutoScale: false,\n filter: (node) => {\n if (node instanceof HTMLElement && node.id === 'mtb-widget-host') return false\n return true\n },\n })\n if (annotations.length > 0) {\n const annotated = await bakeAnnotations(dataUrl, annotations)\n if (annotated) return annotated\n }\n return dataUrlToBlob(dataUrl)\n } catch {\n return null\n }\n}\n\nasync function bakeAnnotations(dataUrl: string, annotations: Annotation[]): Promise<Blob | null> {\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx) return null\n\n const image = await loadImage(dataUrl)\n if (!image) return null\n\n canvas.width = image.naturalWidth || window.innerWidth\n canvas.height = image.naturalHeight || window.innerHeight\n ctx.drawImage(image, 0, 0)\n const scaleX = canvas.width / window.innerWidth\n const scaleY = canvas.height / window.innerHeight\n\n let pinIndex = 0\n for (const annotation of annotations) {\n if (annotation.type === 'draw' && annotation.drawPath) {\n drawStroke(ctx, annotation.drawPath, scaleX, scaleY)\n } else if (annotation.type === 'pin') {\n drawPin(ctx, annotation.x * scaleX, annotation.y * scaleY, ++pinIndex)\n }\n }\n\n return canvasToJpegBlob(canvas)\n}\n\nfunction drawStroke(ctx: CanvasRenderingContext2D, drawPath: string, scaleX: number, scaleY: number): void {\n ctx.save()\n ctx.strokeStyle = BRAND_COLOR\n ctx.lineWidth = 3.5\n ctx.lineCap = 'round'\n ctx.lineJoin = 'round'\n ctx.shadowColor = 'rgba(5,150,105,0.35)'\n ctx.shadowOffsetY = 1\n ctx.shadowBlur = 2\n for (const points of parsePathPolylines(drawPath)) {\n if (points.length === 0) continue\n ctx.beginPath()\n ctx.moveTo(points[0][0] * scaleX, points[0][1] * scaleY)\n for (let i = 1; i < points.length; i++) ctx.lineTo(points[i][0] * scaleX, points[i][1] * scaleY)\n ctx.stroke()\n }\n ctx.restore()\n}\n\nfunction drawPin(ctx: CanvasRenderingContext2D, x: number, y: number, index: number): void {\n ctx.save()\n ctx.shadowColor = 'rgba(5,150,105,0.45)'\n ctx.shadowOffsetY = 2\n ctx.shadowBlur = 8\n ctx.fillStyle = BRAND_COLOR\n ctx.beginPath()\n ctx.arc(x, y, 11, 0, Math.PI * 2)\n ctx.fill()\n ctx.shadowColor = 'transparent'\n ctx.lineWidth = 2\n ctx.strokeStyle = '#ffffff'\n ctx.stroke()\n ctx.fillStyle = '#ffffff'\n ctx.font = `700 10px ${FONT_STACK}`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillText(String(index), x, y)\n ctx.restore()\n}\n\n// The draw layer only ever emits M/L polyline commands (see buildPathD in\n// annotate/draw.ts); anything else in the string is ignored.\nexport function parsePathPolylines(drawPath: string): Array<Array<[number, number]>> {\n const polylines: Array<Array<[number, number]>> = []\n let current: Array<[number, number]> | null = null\n const tokens = drawPath.match(/[ML]\\s*[-\\d.]+\\s+[-\\d.]+/g) ?? []\n for (const token of tokens) {\n const [x, y] = token.slice(1).trim().split(/\\s+/).map(Number)\n if (Number.isNaN(x) || Number.isNaN(y)) continue\n if (token[0] === 'M') {\n current = [[x, y]]\n polylines.push(current)\n } else if (current) {\n current.push([x, y])\n }\n }\n return polylines\n}\n\nfunction loadImage(dataUrl: string): Promise<HTMLImageElement | null> {\n return new Promise(resolve => {\n const image = new Image()\n image.onload = () => resolve(image)\n image.onerror = () => resolve(null)\n image.src = dataUrl\n })\n}\n\nfunction canvasToJpegBlob(canvas: HTMLCanvasElement): Promise<Blob | null> {\n return new Promise(resolve => {\n try {\n canvas.toBlob(blob => resolve(blob), 'image/jpeg', 0.85)\n } catch {\n resolve(null)\n }\n })\n}\n\nfunction dataUrlToBlob(dataUrl: string): Blob {\n const [header, data] = dataUrl.split(',')\n const mime = header.match(/:(.*?);/)?.[1] ?? 'image/png'\n const binary = atob(data)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return new Blob([bytes], { type: mime })\n}\n","export interface ErrorSourceEvent {\n message: string\n source?: string\n line?: number\n col?: number\n error?: unknown\n}\n\ntype ErrorListener = (event: ErrorSourceEvent) => void\n\nclass ErrorSource {\n private listeners = new Set<ErrorListener>()\n private originalOnError: OnErrorEventHandler | null = null\n private installedOnError: OnErrorEventHandler | null = null\n private rejectionHandler: ((e: PromiseRejectionEvent) => void) | null = null\n private hooked = false\n\n subscribe(listener: ErrorListener): () => void {\n this.listeners.add(listener)\n this.hook()\n return () => {\n this.listeners.delete(listener)\n if (this.listeners.size === 0) this.unhook()\n }\n }\n\n private hook(): void {\n if (this.hooked) return\n this.hooked = true\n\n this.originalOnError = window.onerror\n this.installedOnError = (msg, source, line, col, error) => {\n this.emit({ message: String(msg), source, line, col, error })\n if (this.originalOnError) {\n return this.originalOnError.call(window, msg, source, line, col, error)\n }\n return false\n }\n window.onerror = this.installedOnError\n\n this.rejectionHandler = (e: PromiseRejectionEvent) => {\n const reason = e.reason instanceof Error ? e.reason.message : String(e.reason)\n this.emit({ message: `Unhandled rejection: ${reason}` })\n }\n window.addEventListener('unhandledrejection', this.rejectionHandler)\n }\n\n private unhook(): void {\n if (!this.hooked) return\n this.hooked = false\n // Only restore if nothing replaced our handler meanwhile — restoring\n // the stale snapshot would clobber a handler the page installed later.\n if (window.onerror === this.installedOnError) {\n window.onerror = this.originalOnError\n }\n this.installedOnError = null\n this.originalOnError = null\n if (this.rejectionHandler) {\n window.removeEventListener('unhandledrejection', this.rejectionHandler)\n this.rejectionHandler = null\n }\n }\n\n private emit(event: ErrorSourceEvent): void {\n for (const listener of this.listeners) listener(event)\n }\n}\n\nexport const errorSource = new ErrorSource()\n","import { errorSource, type ErrorSourceEvent } from './error-source'\n\nconst MAX_CONSOLE_ERRORS = 20\n\nexport class ConsoleErrorCollector {\n private errors: string[] = []\n private unsubscribe: (() => void) | null = null\n\n start(): void {\n if (this.unsubscribe) return\n this.unsubscribe = errorSource.subscribe((e) => this.record(e))\n }\n\n private record(e: ErrorSourceEvent): void {\n const location = e.line != null ? ` (${e.line}:${e.col ?? 0})` : ''\n this.addError(`${e.message}${location}`)\n }\n\n private addError(msg: string): void {\n if (this.errors.length >= MAX_CONSOLE_ERRORS) return\n if (!this.errors.includes(msg)) {\n this.errors.push(msg)\n }\n }\n\n getErrors(): string[] {\n return [...this.errors]\n }\n\n stop(): void {\n this.unsubscribe?.()\n this.unsubscribe = null\n }\n}\n","import { errorSource, type ErrorSourceEvent } from './error-source'\nimport { getCssSelector, getElementName } from '../annotate/highlighter'\nimport { isWidgetElement } from './dom-utils'\nimport type { Breadcrumb } from '../types'\n\nconst MAX_BREADCRUMBS = 20\n\nexport class BreadcrumbCollector {\n private breadcrumbs: Breadcrumb[] = []\n private active = false\n private unsubscribeErrors: (() => void) | null = null\n private boundClickHandler: (e: MouseEvent) => void\n private boundChangeHandler: (e: Event) => void\n private boundPopstateHandler: (() => void) | null = null\n private originalPushState: History['pushState'] | null = null\n private originalReplaceState: History['replaceState'] | null = null\n private installedPushState: History['pushState'] | null = null\n private installedReplaceState: History['replaceState'] | null = null\n private lastUrl = ''\n\n constructor() {\n this.boundClickHandler = (e: MouseEvent) => this.handleClick(e)\n this.boundChangeHandler = (e: Event) => this.handleChange(e)\n }\n\n start(): void {\n if (this.active) return\n this.active = true\n this.lastUrl = location.href\n document.addEventListener('click', this.boundClickHandler, { capture: true, passive: true })\n document.addEventListener('change', this.boundChangeHandler, { capture: true, passive: true })\n this.unsubscribeErrors = errorSource.subscribe((e) => this.recordError(e))\n this.startNavigationTracking()\n }\n\n stop(): void {\n if (!this.active) return\n this.active = false\n document.removeEventListener('click', this.boundClickHandler, true)\n document.removeEventListener('change', this.boundChangeHandler, true)\n this.unsubscribeErrors?.()\n this.unsubscribeErrors = null\n this.stopNavigationTracking()\n }\n\n getBreadcrumbs(): Breadcrumb[] {\n return [...this.breadcrumbs]\n }\n\n private add(crumb: Breadcrumb): void {\n this.breadcrumbs.push(crumb)\n if (this.breadcrumbs.length > MAX_BREADCRUMBS) {\n this.breadcrumbs.shift()\n }\n }\n\n private handleClick(e: MouseEvent): void {\n const target = e.target as Element | null\n if (!target) return\n if (isWidgetElement(target)) return\n\n try {\n this.add({\n type: 'ui',\n category: 'ui.click',\n timestamp: Date.now(),\n message: getElementName(target),\n data: { selector: getCssSelector(target) },\n })\n } catch { /* never propagate into host page */ }\n }\n\n private handleChange(e: Event): void {\n const target = e.target as Element | null\n if (!target) return\n if (isWidgetElement(target)) return\n\n try {\n const input = target as HTMLInputElement\n const field = input.name || input.placeholder || target.getAttribute('aria-label') || target.tagName\n this.add({\n type: 'ui',\n category: 'ui.input',\n timestamp: Date.now(),\n message: field,\n data: { field },\n })\n } catch { /* never propagate into host page */ }\n }\n\n private recordError(e: ErrorSourceEvent): void {\n this.add({\n type: 'console',\n category: 'console.error',\n timestamp: Date.now(),\n message: e.message,\n data: { message: e.message },\n })\n }\n\n private startNavigationTracking(): void {\n this.boundPopstateHandler = () => this.handleNavigation()\n window.addEventListener('popstate', this.boundPopstateHandler)\n\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n const pushOrig = this.originalPushState\n const replaceOrig = this.originalReplaceState\n const onNav = () => this.handleNavigation()\n\n this.installedPushState = function (data: unknown, unused: string, url?: string | URL | null) {\n pushOrig(data, unused, url)\n onNav()\n }\n this.installedReplaceState = function (data: unknown, unused: string, url?: string | URL | null) {\n replaceOrig(data, unused, url)\n onNav()\n }\n history.pushState = this.installedPushState\n history.replaceState = this.installedReplaceState\n }\n\n private stopNavigationTracking(): void {\n if (this.boundPopstateHandler) {\n window.removeEventListener('popstate', this.boundPopstateHandler)\n this.boundPopstateHandler = null\n }\n // Only restore if nothing (e.g. an SPA router) re-wrapped the functions\n // after us — restoring the stale snapshot would discard their wrapper.\n if (this.originalPushState && history.pushState === this.installedPushState) {\n history.pushState = this.originalPushState\n }\n if (this.originalReplaceState && history.replaceState === this.installedReplaceState) {\n history.replaceState = this.originalReplaceState\n }\n this.originalPushState = null\n this.originalReplaceState = null\n this.installedPushState = null\n this.installedReplaceState = null\n }\n\n private handleNavigation(): void {\n if (!this.active) return\n const from = this.lastUrl\n const to = location.href\n if (from === to) return\n this.lastUrl = to\n this.add({\n type: 'navigation',\n category: 'navigation',\n timestamp: Date.now(),\n message: `${from} → ${to}`,\n data: { from, to },\n })\n }\n\n}\n","import { errorSource } from './error-source'\nimport { isWidgetElement } from './dom-utils'\n\nexport type FrustrationSignal =\n | 'rage_click'\n | 'dead_click'\n | 'rapid_navigation'\n | 'form_failure'\n | 'error_page'\n | 'dead_click_dom'\n\nexport interface FrustrationEvent {\n signal: FrustrationSignal\n target?: string\n detail?: string\n timestamp: number\n}\n\ninterface ClickRecord {\n target: EventTarget | null\n time: number\n}\n\nconst RAGE_CLICK_THRESHOLD = 3\nconst RAGE_CLICK_WINDOW_MS = 1000\nconst RAPID_NAV_THRESHOLD = 3\nconst RAPID_NAV_WINDOW_MS = 5000\nconst FORM_CHECK_DELAY_MS = 500\nconst DEAD_CLICK_DOM_DELAY_MS = 500\nconst ERROR_PAGE_CHECK_DELAY_MS = 300\n\nconst INTERACTIVE_TAGS = new Set([\n 'A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL', 'SUMMARY', 'DETAILS',\n])\n\nconst INTERACTIVE_ROLES = new Set([\n 'button', 'link', 'checkbox', 'radio', 'tab', 'menuitem', 'option',\n 'switch', 'textbox', 'combobox', 'listbox', 'slider', 'spinbutton',\n])\n\nconst ERROR_PAGE_PATTERNS = [\n '404', '500', 'not found', 'page not found',\n 'server error', 'internal server error',\n]\n\nexport class FrustrationDetector {\n private clickHistory: ClickRecord[] = []\n private onFrustration: (event: FrustrationEvent) => void\n private boundClickHandler: (e: MouseEvent) => void\n private unsubscribeErrors: (() => void) | null = null\n private active = false\n private errorCount = 0\n private deadClickCount = 0\n private cooldownUntil = 0\n private static readonly COOLDOWN_MS = 60_000\n\n private navTimestamps: number[] = []\n private boundPopstateHandler: (() => void) | null = null\n private originalPushState: History['pushState'] | null = null\n private originalReplaceState: History['replaceState'] | null = null\n private installedPushState: History['pushState'] | null = null\n private installedReplaceState: History['replaceState'] | null = null\n private boundSubmitHandler: ((e: Event) => void) | null = null\n private boundInvalidHandler: ((e: Event) => void) | null = null\n private errorPageUrls = new Set<string>()\n private domObserver: MutationObserver | null = null\n private pendingDomChecks = 0\n private lastMutationAt = -1\n\n constructor(onFrustration: (event: FrustrationEvent) => void) {\n this.onFrustration = onFrustration\n this.boundClickHandler = (e: MouseEvent) => this.handleClick(e)\n }\n\n start(): void {\n if (this.active) return\n this.active = true\n document.addEventListener('click', this.boundClickHandler, true)\n this.unsubscribeErrors = errorSource.subscribe((_e) => {\n this.errorCount++\n })\n\n this.startNavigationTracking()\n this.startFormTracking()\n this.checkErrorPage()\n }\n\n stop(): void {\n if (!this.active) return\n this.active = false\n document.removeEventListener('click', this.boundClickHandler, true)\n this.unsubscribeErrors?.()\n this.unsubscribeErrors = null\n this.clickHistory = []\n\n this.stopNavigationTracking()\n this.stopFormTracking()\n this.errorPageUrls.clear()\n\n this.disconnectDomObserver()\n }\n\n private startNavigationTracking(): void {\n this.boundPopstateHandler = () => this.handleNavigation()\n window.addEventListener('popstate', this.boundPopstateHandler)\n\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n const pushOrig = this.originalPushState\n const replaceOrig = this.originalReplaceState\n const onNav = () => this.handleNavigation()\n\n this.installedPushState = function (data: unknown, unused: string, url?: string | URL | null) {\n pushOrig(data, unused, url)\n onNav()\n }\n this.installedReplaceState = function (data: unknown, unused: string, url?: string | URL | null) {\n replaceOrig(data, unused, url)\n onNav()\n }\n history.pushState = this.installedPushState\n history.replaceState = this.installedReplaceState\n }\n\n private stopNavigationTracking(): void {\n if (this.boundPopstateHandler) {\n window.removeEventListener('popstate', this.boundPopstateHandler)\n this.boundPopstateHandler = null\n }\n // Only restore if nothing (e.g. an SPA router) re-wrapped the functions\n // after us — restoring the stale snapshot would discard their wrapper.\n if (this.originalPushState && history.pushState === this.installedPushState) {\n history.pushState = this.originalPushState\n }\n if (this.originalReplaceState && history.replaceState === this.installedReplaceState) {\n history.replaceState = this.originalReplaceState\n }\n this.originalPushState = null\n this.originalReplaceState = null\n this.installedPushState = null\n this.installedReplaceState = null\n this.navTimestamps = []\n }\n\n private startFormTracking(): void {\n this.boundSubmitHandler = (e: Event) => this.handleFormSubmit(e)\n this.boundInvalidHandler = (e: Event) => this.handleFormInvalid(e)\n document.addEventListener('submit', this.boundSubmitHandler, true)\n document.addEventListener('invalid', this.boundInvalidHandler, true)\n }\n\n private stopFormTracking(): void {\n if (this.boundSubmitHandler) {\n document.removeEventListener('submit', this.boundSubmitHandler, true)\n this.boundSubmitHandler = null\n }\n if (this.boundInvalidHandler) {\n document.removeEventListener('invalid', this.boundInvalidHandler, true)\n this.boundInvalidHandler = null\n }\n }\n\n private handleClick(e: MouseEvent): void {\n const target = e.target as Element | null\n if (!target) return\n\n if (isWidgetElement(target)) return\n\n const now = Date.now()\n this.clickHistory.push({ target, time: now })\n\n const cutoff = now - RAGE_CLICK_WINDOW_MS\n this.clickHistory = this.clickHistory.filter(r => r.time > cutoff)\n\n const sameTargetClicks = this.clickHistory.filter(r => r.target === target)\n if (sameTargetClicks.length >= RAGE_CLICK_THRESHOLD) {\n this.clickHistory = []\n this.emitHighPriority({\n signal: 'rage_click',\n target: describeElement(target),\n timestamp: now,\n })\n return\n }\n\n if (!this.isInteractive(target)) {\n this.deadClickCount++\n if (this.deadClickCount >= 3 && this.errorCount > 0) {\n this.deadClickCount = 0\n this.errorCount = 0\n this.emitIfReady({\n signal: 'dead_click',\n target: describeElement(target),\n timestamp: now,\n })\n }\n }\n\n this.checkDeadClickDom(target, now)\n }\n\n private handleNavigation(): void {\n const now = Date.now()\n this.navTimestamps.push(now)\n const cutoff = now - RAPID_NAV_WINDOW_MS\n this.navTimestamps = this.navTimestamps.filter(t => t > cutoff)\n if (this.navTimestamps.length >= RAPID_NAV_THRESHOLD) {\n this.navTimestamps = []\n this.emitIfReady({\n signal: 'rapid_navigation',\n timestamp: now,\n })\n }\n setTimeout(() => {\n if (this.active) this.checkErrorPage()\n }, ERROR_PAGE_CHECK_DELAY_MS)\n }\n\n private handleFormSubmit(e: Event): void {\n const form = e.target\n if (!(form instanceof HTMLFormElement)) return\n if (isWidgetElement(form)) return\n\n setTimeout(() => {\n if (!this.active) return\n if (form.querySelector('[aria-invalid=\"true\"], .is-invalid')) {\n this.emitIfReady({\n signal: 'form_failure',\n target: describeElement(form),\n timestamp: Date.now(),\n })\n }\n }, FORM_CHECK_DELAY_MS)\n }\n\n private handleFormInvalid(e: Event): void {\n const el = e.target as Element | null\n if (!el) return\n if (isWidgetElement(el)) return\n const form = el.closest('form')\n this.emitIfReady({\n signal: 'form_failure',\n target: form ? describeElement(form) : describeElement(el),\n timestamp: Date.now(),\n })\n }\n\n private checkErrorPage(): void {\n const url = location.href\n if (this.errorPageUrls.has(url)) return\n\n const title = document.title.toLowerCase()\n if (ERROR_PAGE_PATTERNS.some(p => title.includes(p))) {\n this.errorPageUrls.add(url)\n this.emitHighPriority({\n signal: 'error_page',\n detail: document.title,\n timestamp: Date.now(),\n })\n return\n }\n\n const candidates = document.querySelectorAll(\n 'h1, h2, [class*=\"error\"], [class*=\"not-found\"], [id*=\"error\"], [id*=\"not-found\"]'\n )\n for (const el of candidates) {\n const text = el.textContent ?? ''\n if (text.length < 200 && ERROR_PAGE_PATTERNS.some(p => text.toLowerCase().includes(p))) {\n this.errorPageUrls.add(url)\n this.emitHighPriority({\n signal: 'error_page',\n detail: text.trim().slice(0, 60),\n timestamp: Date.now(),\n })\n return\n }\n }\n }\n\n // One shared observer for all in-flight dead-click checks, connected only\n // while at least one check is pending — a full-page observer per click was\n // too heavy on mutation-busy pages.\n private checkDeadClickDom(target: Element, clickTime: number): void {\n if (!this.looksInteractive(target)) return\n\n this.pendingDomChecks++\n this.ensureDomObserver()\n\n setTimeout(() => {\n this.pendingDomChecks--\n const mutated = this.lastMutationAt >= clickTime\n if (this.pendingDomChecks === 0) this.disconnectDomObserver()\n\n if (!mutated && this.active) {\n this.emitIfReady({\n signal: 'dead_click_dom',\n target: describeElement(target),\n timestamp: clickTime,\n })\n }\n }, DEAD_CLICK_DOM_DELAY_MS)\n }\n\n private ensureDomObserver(): void {\n if (this.domObserver) return\n this.domObserver = new MutationObserver(() => {\n this.lastMutationAt = Date.now()\n })\n this.domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n })\n }\n\n private disconnectDomObserver(): void {\n this.domObserver?.disconnect()\n this.domObserver = null\n }\n\n private looksInteractive(el: Element): boolean {\n const style = window.getComputedStyle(el)\n if (style.cursor === 'pointer') return true\n\n if (el.classList) {\n for (const cls of el.classList) {\n const lower = cls.toLowerCase()\n if (lower.includes('btn') || lower.includes('button')) return true\n }\n }\n\n return false\n }\n\n private isInteractive(el: Element): boolean {\n if (INTERACTIVE_TAGS.has(el.tagName)) return true\n\n const role = el.getAttribute('role')\n if (role && INTERACTIVE_ROLES.has(role)) return true\n\n if (el.hasAttribute('onclick') || el.hasAttribute('tabindex')) return true\n if ((el as HTMLElement).contentEditable === 'true') return true\n\n const style = window.getComputedStyle(el)\n if (style.cursor === 'pointer') return true\n\n const parent = el.closest('a, button, [role=\"button\"], [role=\"link\"], label')\n if (parent) return true\n\n return false\n }\n\n\n private emitIfReady(event: FrustrationEvent): void {\n const now = Date.now()\n if (now < this.cooldownUntil) return\n this.cooldownUntil = now + FrustrationDetector.COOLDOWN_MS\n this.onFrustration(event)\n }\n\n private emitHighPriority(event: FrustrationEvent): void {\n this.cooldownUntil = Date.now() + FrustrationDetector.COOLDOWN_MS\n this.onFrustration(event)\n }\n}\n\nfunction describeElement(el: Element): string {\n const tag = el.tagName.toLowerCase()\n const id = el.id ? `#${el.id}` : ''\n const cls = el.className && typeof el.className === 'string'\n ? '.' + el.className.trim().split(/\\s+/).slice(0, 2).join('.')\n : ''\n const text = el.textContent?.trim().slice(0, 30) ?? ''\n return `<${tag}${id}${cls}>${text ? ` \"${text}\"` : ''}`\n}\n","export interface PageContext {\n page_url: string\n user_agent: string\n browser: string\n os: string\n screen_width: number\n screen_height: number\n}\n\nexport function collectPageContext(): PageContext {\n return {\n page_url: window.location.href,\n user_agent: navigator.userAgent,\n browser: detectBrowser(),\n os: detectOS(),\n screen_width: window.screen.width,\n screen_height: window.screen.height,\n }\n}\n\nfunction detectBrowser(): string {\n const ua = navigator.userAgent\n if (/Edg\\//.test(ua)) return `Edge ${ua.match(/Edg\\/(\\S+)/)?.[1] ?? ''}`\n if (/OPR\\//.test(ua)) return `Opera ${ua.match(/OPR\\/(\\S+)/)?.[1] ?? ''}`\n if (/Chrome\\//.test(ua)) return `Chrome ${ua.match(/Chrome\\/(\\S+)/)?.[1] ?? ''}`\n if (/Safari\\//.test(ua) && /Version\\//.test(ua)) return `Safari ${ua.match(/Version\\/(\\S+)/)?.[1] ?? ''}`\n if (/Firefox\\//.test(ua)) return `Firefox ${ua.match(/Firefox\\/(\\S+)/)?.[1] ?? ''}`\n return 'Unknown'\n}\n\nfunction detectOS(): string {\n const ua = navigator.userAgent\n if (/Windows NT 10/.test(ua)) return 'Windows 10/11'\n if (/Windows NT/.test(ua)) return 'Windows'\n if (/Mac OS X 10_15|macOS 1[56789]/.test(ua)) return 'macOS'\n if (/Mac OS X/.test(ua)) return 'macOS'\n if (/Android/.test(ua)) return `Android ${ua.match(/Android (\\d+)/)?.[1] ?? ''}`\n if (/iPhone|iPad|iPod/.test(ua)) return 'iOS'\n if (/Linux/.test(ua)) return 'Linux'\n return 'Unknown'\n}\n","import type {\n FeedbackPayload,\n FeedbackResponse,\n SubmissionSessionResponse,\n ClarifyResponse,\n ClarifyMessage,\n} from '../types'\n\nexport interface ClarifyStreamResult {\n messages: ClarifyMessage[]\n done: boolean\n}\n\nconst DEFAULT_API_URL = 'https://makethisbetter.dev/api/v1'\n\nexport class ApiClient {\n private apiUrl: string\n private projectKey: string\n private retryDelayMs: number\n private userToken?: string\n private userTokenFn?: () => Promise<string>\n\n constructor(projectKey: string, apiUrl?: string, retryDelayMs = 1000, userToken?: string, userTokenFn?: () => Promise<string>) {\n this.projectKey = projectKey\n this.apiUrl = (apiUrl ?? DEFAULT_API_URL).replace(/\\/$/, '')\n this.retryDelayMs = retryDelayMs\n this.userToken = userToken\n this.userTokenFn = userTokenFn\n }\n\n async resolveUserToken(): Promise<string | undefined> {\n if (this.userTokenFn) return this.userTokenFn()\n return this.userToken\n }\n\n private async authHeaders(contentType?: string): Promise<Record<string, string>> {\n const headers: Record<string, string> = { 'X-Project-Key': this.projectKey }\n const token = await this.resolveUserToken()\n if (token) headers['X-User-Token'] = token\n if (contentType) headers['Content-Type'] = contentType\n return headers\n }\n\n private async submissionHeaders(token: string, contentType?: string): Promise<Record<string, string>> {\n const headers = await this.authHeaders(contentType)\n headers['X-Submission-Token'] = token\n return headers\n }\n\n async createSubmissionSession(payload: FeedbackPayload, screenshot: Blob | null): Promise<SubmissionSessionResponse> {\n const submissionToken = generateSubmissionToken()\n const form = new FormData()\n form.append('feedback[description]', payload.description)\n form.append('feedback[page_url]', payload.page_url)\n form.append('feedback[user_agent]', payload.user_agent)\n form.append('feedback[browser]', payload.browser)\n form.append('feedback[os]', payload.os)\n form.append('feedback[screen_width]', String(payload.screen_width))\n form.append('feedback[screen_height]', String(payload.screen_height))\n form.append('feedback[console_errors]', JSON.stringify(payload.console_errors))\n form.append('feedback[annotations]', JSON.stringify(payload.annotations))\n\n if (payload.target_element) {\n form.append('feedback[target_element]', JSON.stringify(payload.target_element))\n }\n if (payload.user_id) form.append('feedback[user_id]', payload.user_id)\n if (payload.reporter_external_id) form.append('feedback[reporter_external_id]', payload.reporter_external_id)\n if (payload.reporter_email) form.append('feedback[reporter_email]', payload.reporter_email)\n if (payload.user_email) form.append('feedback[user_email]', payload.user_email)\n if (payload.user_name) form.append('feedback[user_name]', payload.user_name)\n\n if (payload.breadcrumbs && payload.breadcrumbs.length > 0) {\n form.append('feedback[breadcrumbs]', JSON.stringify(payload.breadcrumbs))\n }\n\n if (payload.recording_events && payload.recording_events.length > 0) {\n const json = JSON.stringify(payload.recording_events)\n const blob = new Blob([json], { type: 'application/json' })\n form.append('feedback[recording]', blob, 'interaction-replay.json')\n form.append('feedback[recording_duration]', String(payload.recording_duration ?? 0))\n }\n\n if (screenshot) {\n const ext = screenshot.type === 'image/jpeg' ? 'jpg' : 'png'\n form.append('feedback[screenshot]', screenshot, `screenshot.${ext}`)\n }\n\n const headers = await this.authHeaders()\n headers['X-Submission-Token'] = submissionToken\n // One key per submission, reused across retries: if the first POST\n // reached the server but the response was lost, the retry must not\n // create a second feedback.\n headers['X-Idempotency-Key'] = generateIdempotencyKey()\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions`, {\n method: 'POST',\n headers,\n body: form,\n })\n const body = await res.json() as {\n submission_session: Omit<SubmissionSessionResponse, 'token'> & { token?: string }\n }\n return { ...body.submission_session, token: submissionToken }\n }\n\n async createIdentityToken(reporterExternalId: string): Promise<{ identity_token: string; board_url: string } | null> {\n const headers = await this.authHeaders('application/json')\n try {\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/identity_tokens`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ reporter_external_id: reporterExternalId }),\n })\n return await res.json()\n } catch {\n return null\n }\n }\n\n async updateReporter(feedbackId: string, email: string, identityToken: string): Promise<boolean> {\n const headers = await this.authHeaders('application/json')\n headers['X-Identity-Token'] = identityToken\n try {\n await this.fetchWithRetry(`${this.apiUrl}/widget/feedbacks/${feedbackId}/reporter`, {\n method: 'PATCH',\n headers,\n body: JSON.stringify({ reporter: { email } }),\n })\n return true\n } catch {\n return false\n }\n }\n\n async startClarification(submissionSessionId: string, token: string, message?: string): Promise<ClarifyResponse> {\n const body: Record<string, string> = {}\n if (message) body.message = message\n const headers = await this.submissionHeaders(token, 'application/json')\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/clarification`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n const response = await res.json() as { clarification: ClarifyResponse }\n return response.clarification\n }\n\n async getClarification(submissionSessionId: string, token: string): Promise<ClarifyResponse> {\n const headers = await this.submissionHeaders(token)\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/clarification`, {\n method: 'GET',\n headers,\n })\n const response = await res.json() as { clarification: ClarifyResponse }\n return response.clarification\n }\n\n // Streams a clarification turn over SSE. Calls onDelta for each token and\n // resolves with the committed result. Throws if the server doesn't stream\n // (e.g. old backend returns JSON) so the caller can fall back to polling.\n async streamClarification(\n submissionSessionId: string,\n token: string,\n onDelta: (text: string) => void,\n ): Promise<ClarifyStreamResult> {\n const headers = await this.submissionHeaders(token, 'application/json')\n headers['Accept'] = 'text/event-stream'\n\n const res = await fetch(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/clarification`, {\n method: 'POST',\n headers,\n body: JSON.stringify({}),\n })\n\n const contentType = res.headers.get('Content-Type') ?? ''\n if (!res.ok || !res.body || !contentType.includes('text/event-stream')) {\n throw new Error('clarify stream unavailable')\n }\n\n return consumeSse(res.body, onDelta)\n }\n\n async finalizeSubmissionSession(submissionSessionId: string, token: string): Promise<FeedbackResponse> {\n const headers = await this.submissionHeaders(token)\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/feedback`, {\n method: 'POST',\n headers,\n })\n const response = await res.json() as { feedback: FeedbackResponse }\n return response.feedback\n }\n\n async abandonSubmissionSession(submissionSessionId: string, token: string): Promise<void> {\n const headers = await this.submissionHeaders(token)\n await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}`, {\n method: 'DELETE',\n headers,\n })\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, retries = 1): Promise<Response> {\n let res: Response\n try {\n res = await fetch(url, init)\n } catch (err) {\n if (retries > 0) {\n await delay(this.retryDelayMs)\n return this.fetchWithRetry(url, init, retries - 1)\n }\n throw err\n }\n\n if (res.ok) return res\n if (res.status >= 500 && retries > 0) {\n await delay(this.retryDelayMs)\n return this.fetchWithRetry(url, init, retries - 1)\n }\n throw new Error(`HTTP ${res.status}`)\n }\n}\n\nfunction delay(ms: number): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nasync function consumeSse(\n body: ReadableStream<Uint8Array>,\n onDelta: (text: string) => void,\n): Promise<ClarifyStreamResult> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let result: ClarifyStreamResult = { messages: [], done: true }\n\n const flush = (raw: string): void => {\n // Each SSE record is \"event: <name>\\n data: <json>\". Parse event + data.\n const eventLine = raw.split('\\n').find(l => l.startsWith('event:'))\n const dataLine = raw.split('\\n').find(l => l.startsWith('data:'))\n if (!dataLine) return\n const event = eventLine?.slice(6).trim()\n const payload = JSON.parse(dataLine.slice(5).trim())\n if (event === 'delta' && typeof payload.text === 'string') {\n onDelta(payload.text)\n } else if (event === 'done') {\n result = {\n messages: Array.isArray(payload.messages) ? payload.messages : [],\n done: payload.done !== false,\n }\n }\n }\n\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n let sep: number\n while ((sep = buffer.indexOf('\\n\\n')) !== -1) {\n const record = buffer.slice(0, sep)\n buffer = buffer.slice(sep + 2)\n try { flush(record) } catch { /* skip malformed record */ }\n }\n }\n return result\n}\n\nfunction generateIdempotencyKey(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`\n}\n\nfunction generateSubmissionToken(): string {\n if (typeof crypto === 'undefined' || typeof crypto.getRandomValues !== 'function') {\n throw new Error('Secure random generation is unavailable')\n }\n\n const bytes = crypto.getRandomValues(new Uint8Array(32))\n return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('')\n}\n","import type { PageContext } from '../context/collector'\nimport type { Annotation, Breadcrumb, FeedbackPayload, MakeThisBetterConfig } from '../types'\nimport type { RecordingResult } from '../record/session'\n\nexport function buildPayload(\n description: string,\n pageContext: PageContext,\n consoleErrors: string[],\n annotation: Annotation | null,\n user: MakeThisBetterConfig['user'],\n recording?: RecordingResult,\n anonId?: string,\n anonEmail?: string,\n breadcrumbs?: Breadcrumb[],\n): FeedbackPayload {\n return {\n description,\n ...pageContext,\n console_errors: consoleErrors,\n annotations: annotation ? [annotation] : [],\n target_element: annotation?.targetSelector\n ? {\n selector: annotation.targetSelector,\n text: annotation.targetText ?? '',\n name: annotation.targetName ?? '',\n }\n : undefined,\n user_id: user?.id,\n user_email: user?.email,\n user_name: user?.name,\n reporter_external_id: user ? undefined : anonId,\n reporter_email: user ? undefined : anonEmail,\n recording_events: recording?.events,\n recording_duration: recording?.duration,\n breadcrumbs,\n }\n}\n","const STORAGE_KEY = 'mtb_anon_id'\nconst EMAIL_KEY = 'mtb_reporter_email'\nconst BOARD_URL_KEY = 'mtb_board_url'\n\nlet memoryId: string | null = null\nlet memoryEmail: string | null = null\nlet memoryBoardUrl: string | null = null\n\nexport function getAnonId(): string {\n try {\n const stored = window.localStorage.getItem(STORAGE_KEY)\n if (stored?.startsWith('anon_')) return stored\n const id = generateAnonId()\n window.localStorage.setItem(STORAGE_KEY, id)\n return id\n } catch {\n memoryId ??= generateAnonId()\n return memoryId\n }\n}\n\nexport function getStoredReporterEmail(): string | undefined {\n try {\n return window.localStorage.getItem(EMAIL_KEY) ?? undefined\n } catch {\n return memoryEmail ?? undefined\n }\n}\n\nexport function rememberReporterEmail(email: string): void {\n memoryEmail = email\n try {\n window.localStorage.setItem(EMAIL_KEY, email)\n } catch {\n // localStorage unavailable — the in-memory copy covers this session\n }\n}\n\nexport function getCachedBoardUrl(): string | undefined {\n try {\n return window.localStorage.getItem(BOARD_URL_KEY) ?? undefined\n } catch {\n return memoryBoardUrl ?? undefined\n }\n}\n\nexport function cacheBoardUrl(url: string): void {\n memoryBoardUrl = url\n try {\n window.localStorage.setItem(BOARD_URL_KEY, url)\n } catch {\n // localStorage unavailable — the in-memory copy covers this session\n }\n}\n\nfunction generateAnonId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return `anon_${crypto.randomUUID()}`\n }\n const random = `${Date.now().toString(16)}-${Math.random().toString(16).slice(2, 10)}`\n return `anon_${random}`\n}\n","export default {\n tab: 'Feedback',\n toolbar: {\n markup: 'Mark up',\n record: 'Record',\n hint: 'Click any element to annotate · drag to draw',\n hintRecord: 'Recording your screen',\n exit: 'Exit',\n },\n popup: {\n about: 'About',\n placeholder: 'Describe the issue or suggestion...',\n submit: 'Submit',\n cancel: 'Cancel',\n my_feedback: 'My feedback',\n quickOptions: [\n { emoji: '🐛', label: \"Something's broken\" },\n { emoji: '💡', label: 'I have a suggestion' },\n { emoji: '🤔', label: \"I'm confused\" },\n ],\n },\n success: {\n title: 'Sent — thanks!',\n message: 'Your note and captured technical context are on their way to the team. You’ll hear back when it’s resolved.',\n title_no_ai: \"Thanks! We've received your feedback.\",\n message_no_ai: \"The team will take it from here. You'll hear back when it's resolved.\",\n view_feedback: 'View my feedback',\n close: 'Close',\n email_prompt: \"Want updates? Leave your email and we'll let you know when it's resolved.\",\n email_placeholder: 'you@example.com',\n email_submit: 'Notify me',\n email_saved: \"You'll get an email when it's resolved.\",\n email_error: \"Couldn't save your email. Please try again.\",\n },\n error: {\n submit: 'Failed to submit. Please try again.',\n },\n pet: {\n bubble: 'Need help?',\n },\n frustration: {\n prompt: 'Something not working? Tell us.',\n action: 'Annotate',\n dismiss: 'Dismiss',\n },\n annotation: {\n drawing: 'Drawing',\n element: 'element',\n },\n draw: {\n note_placeholder: 'Add a note to your drawing',\n undo: 'Undo',\n redo: 'Redo',\n cancel: 'Cancel',\n submit: 'Submit',\n },\n record: {\n stop: 'Stop',\n timer_label: 'Recording',\n max_reached: 'Maximum recording time reached',\n replay_label: 'screen-recording.json',\n play: 'Play recording',\n close: 'Close',\n preview_unavailable: 'Preview unavailable',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Sharpening your feedback',\n thinking: 'Thinking...',\n placeholder: 'Type your answer — or skip the question',\n send: 'Send',\n skip: 'Skip & send',\n summary: {\n ready: 'Ready to send',\n what_you_said: 'What you said',\n clarified: 'Clarified with AI',\n auto_captured: 'Auto-captured',\n element: 'Element',\n page: 'Page',\n browser: 'Browser',\n captured: 'Captured',\n send_feedback: 'Send feedback',\n screenshot: 'Screenshot',\n recording: 'Interaction replay',\n },\n },\n}\n","export default {\n tab: '反馈',\n toolbar: {\n markup: '标注',\n record: '录屏',\n hint: '点击任意元素进行标注 · 拖拽可自由绘制',\n hintRecord: '正在录制屏幕',\n exit: '退出',\n },\n popup: {\n about: '关于',\n placeholder: '描述问题或建议...',\n submit: '提交',\n cancel: '取消',\n my_feedback: '我的反馈',\n quickOptions: [\n { emoji: '🐛', label: '出问题了' },\n { emoji: '💡', label: '我有一个建议' },\n { emoji: '🤔', label: '我有点困惑' },\n ],\n },\n success: {\n title: '已发送,感谢!',\n message: '您的反馈和采集到的技术上下文正在发送给团队。问题解决后,您会收到通知。',\n title_no_ai: '感谢!我们已收到您的反馈。',\n message_no_ai: '接下来由团队处理。问题解决后,您会收到通知。',\n view_feedback: '查看我的反馈',\n close: '关闭',\n email_prompt: '想了解进展?留下邮箱,问题解决后我们会通知您。',\n email_placeholder: 'you@example.com',\n email_submit: '通知我',\n email_saved: '问题解决后您会收到邮件通知。',\n email_error: '邮箱保存失败,请重试。',\n },\n error: {\n submit: '提交失败,请重试。',\n },\n pet: {\n bubble: '需要帮助吗?',\n },\n frustration: {\n prompt: '遇到问题了?告诉我们。',\n action: '标注',\n dismiss: '关闭',\n },\n annotation: {\n drawing: '绘制',\n element: '元素',\n },\n draw: {\n note_placeholder: '给你的绘制添加说明',\n undo: '撤销',\n redo: '重做',\n cancel: '取消',\n submit: '提交',\n },\n record: {\n stop: '停止',\n timer_label: '录制中',\n max_reached: '已达到最长录制时间',\n replay_label: 'screen-recording.json',\n play: '播放录屏',\n close: '关闭',\n preview_unavailable: '暂无法预览',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: '正在完善你的反馈',\n thinking: '思考中...',\n placeholder: '输入回答,或跳过问题',\n send: '发送',\n skip: '跳过并发送',\n summary: {\n ready: '准备发送',\n what_you_said: '你的描述',\n clarified: 'AI 追问澄清',\n auto_captured: '自动采集',\n element: '元素',\n page: '页面',\n browser: '浏览器',\n captured: '已采集',\n send_feedback: '发送反馈',\n screenshot: '截图',\n recording: '交互回放',\n },\n },\n}\n","export default {\n tab: 'フィードバック',\n toolbar: {\n markup: 'マークアップ',\n record: '録画',\n hint: '要素をクリックして注釈 · ドラッグで描画',\n hintRecord: '画面を録画中',\n exit: '終了',\n },\n popup: {\n about: '概要',\n placeholder: '問題や提案を入力してください...',\n submit: '送信',\n cancel: 'キャンセル',\n my_feedback: '自分のフィードバック',\n quickOptions: [\n { emoji: '🐛', label: '不具合があります' },\n { emoji: '💡', label: '提案があります' },\n { emoji: '🤔', label: 'わかりにくいです' },\n ],\n },\n success: {\n title: '送信しました。ありがとうございます!',\n message: 'ご意見と取得した技術情報をチームに送信しました。解決次第お知らせします。',\n title_no_ai: 'ありがとうございます!フィードバックを受け付けました。',\n message_no_ai: 'チームが対応します。解決次第お知らせします。',\n view_feedback: 'フィードバックを確認',\n close: '閉じる',\n email_prompt: '進捗を知りたい場合は、メールアドレスをご記入ください。解決次第お知らせします。',\n email_placeholder: 'you@example.com',\n email_submit: '通知を受け取る',\n email_saved: '解決次第メールでお知らせします。',\n email_error: 'メールアドレスを保存できませんでした。もう一度お試しください。',\n },\n error: {\n submit: '送信に失敗しました。もう一度お試しください。',\n },\n pet: {\n bubble: 'お困りですか?',\n },\n frustration: {\n prompt: 'うまくいかないことがありますか?お知らせください。',\n action: '注釈',\n dismiss: '閉じる',\n },\n annotation: {\n drawing: '描画',\n element: '要素',\n },\n draw: {\n note_placeholder: '描画にメモを追加',\n undo: '元に戻す',\n redo: 'やり直す',\n cancel: 'キャンセル',\n submit: '送信',\n },\n record: {\n stop: '停止',\n timer_label: '録画中',\n max_reached: '最大記録時間に達しました',\n replay_label: 'screen-recording.json',\n play: '録画を再生',\n close: '閉じる',\n preview_unavailable: 'プレビューは利用できません',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'フィードバックを整えています',\n thinking: '考え中...',\n placeholder: '回答を入力、または質問をスキップ',\n send: '送信',\n skip: 'スキップして送信',\n summary: {\n ready: '送信の準備ができました',\n what_you_said: 'あなたの入力',\n clarified: 'AI で明確化',\n auto_captured: '自動取得',\n element: '要素',\n page: 'ページ',\n browser: 'ブラウザ',\n captured: '取得済み',\n send_feedback: 'フィードバックを送信',\n screenshot: 'スクリーンショット',\n recording: '操作リプレイ',\n },\n },\n}\n","export default {\n tab: '피드백',\n toolbar: {\n markup: '마크업',\n record: '녹화',\n hint: '요소를 클릭하여 주석 · 드래그하여 그리기',\n hintRecord: '화면 녹화 중',\n exit: '나가기',\n },\n popup: {\n about: '정보',\n placeholder: '문제 또는 제안 사항을 설명해 주세요...',\n submit: '제출',\n cancel: '취소',\n my_feedback: '내 피드백',\n quickOptions: [\n { emoji: '🐛', label: '문제가 있어요' },\n { emoji: '💡', label: '제안이 있어요' },\n { emoji: '🤔', label: '헷갈려요' },\n ],\n },\n success: {\n title: '전송되었습니다. 감사합니다!',\n message: '피드백과 수집된 기술 정보가 팀에 전달되었습니다. 해결되면 알려드리겠습니다.',\n title_no_ai: '감사합니다! 피드백을 접수했습니다.',\n message_no_ai: '팀에서 처리합니다. 해결되면 알려드리겠습니다.',\n view_feedback: '내 피드백 보기',\n close: '닫기',\n email_prompt: '진행 상황이 궁금하신가요? 이메일을 남겨주시면 해결 시 알려드립니다.',\n email_placeholder: 'you@example.com',\n email_submit: '알림 받기',\n email_saved: '해결되면 이메일로 알려드립니다.',\n email_error: '이메일을 저장하지 못했습니다. 다시 시도해 주세요.',\n },\n error: {\n submit: '제출에 실패했습니다. 다시 시도해 주세요.',\n },\n pet: {\n bubble: '도움이 필요하신가요?',\n },\n frustration: {\n prompt: '문제가 있으신가요? 알려 주세요.',\n action: '주석',\n dismiss: '닫기',\n },\n annotation: {\n drawing: '그리기',\n element: '요소',\n },\n draw: {\n note_placeholder: '그림에 메모 추가',\n undo: '실행 취소',\n redo: '다시 실행',\n cancel: '취소',\n submit: '보내기',\n },\n record: {\n stop: '중지',\n timer_label: '녹화 중',\n max_reached: '최대 녹화 시간에 도달했습니다',\n replay_label: 'screen-recording.json',\n play: '녹화 재생',\n close: '닫기',\n preview_unavailable: '미리보기를 사용할 수 없습니다',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: '피드백을 다듬는 중',\n thinking: '생각 중...',\n placeholder: '답변을 입력하거나 질문을 건너뛰세요',\n send: '보내기',\n skip: '건너뛰고 보내기',\n summary: {\n ready: '보낼 준비 완료',\n what_you_said: '입력한 내용',\n clarified: 'AI로 명확화',\n auto_captured: '자동 수집',\n element: '요소',\n page: '페이지',\n browser: '브라우저',\n captured: '수집됨',\n send_feedback: '피드백 보내기',\n screenshot: '스크린샷',\n recording: '상호작용 리플레이',\n },\n },\n}\n","export default {\n tab: 'Comentarios',\n toolbar: {\n markup: 'Anotar',\n record: 'Grabar',\n hint: 'Haz clic en cualquier elemento para anotar · arrastra para dibujar',\n hintRecord: 'Grabando pantalla',\n exit: 'Salir',\n },\n popup: {\n about: 'Acerca de',\n placeholder: 'Describe el problema o sugerencia...',\n submit: 'Enviar',\n cancel: 'Cancelar',\n my_feedback: 'Mis comentarios',\n quickOptions: [\n { emoji: '🐛', label: 'Algo no funciona' },\n { emoji: '💡', label: 'Tengo una sugerencia' },\n { emoji: '🤔', label: 'Estoy confundido' },\n ],\n },\n success: {\n title: 'Enviado, ¡gracias!',\n message: 'Tu nota y el contexto técnico capturado se han enviado al equipo. Te avisaremos cuando se resuelva.',\n title_no_ai: '¡Gracias! Hemos recibido tu comentario.',\n message_no_ai: 'El equipo se encargará a partir de aquí. Te avisaremos cuando se resuelva.',\n view_feedback: 'Ver mis comentarios',\n close: 'Cerrar',\n email_prompt: '¿Quieres novedades? Deja tu correo y te avisaremos cuando se resuelva.',\n email_placeholder: 'tu@ejemplo.com',\n email_submit: 'Avisarme',\n email_saved: 'Recibirás un correo cuando se resuelva.',\n email_error: 'No se pudo guardar tu correo. Inténtalo de nuevo.',\n },\n error: {\n submit: 'Error al enviar. Por favor, inténtalo de nuevo.',\n },\n pet: {\n bubble: '¿Necesitas ayuda?',\n },\n frustration: {\n prompt: '¿Algo no funciona? Cuéntanos.',\n action: 'Anotar',\n dismiss: 'Cerrar',\n },\n annotation: {\n drawing: 'Dibujo',\n element: 'elemento',\n },\n draw: {\n note_placeholder: 'Añade una nota a tu dibujo',\n undo: 'Deshacer',\n redo: 'Rehacer',\n cancel: 'Cancelar',\n submit: 'Enviar',\n },\n record: {\n stop: 'Detener',\n timer_label: 'Grabando',\n max_reached: 'Tiempo máximo de grabación alcanzado',\n replay_label: 'screen-recording.json',\n play: 'Reproducir grabación',\n close: 'Cerrar',\n preview_unavailable: 'Vista previa no disponible',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Afinando tus comentarios',\n thinking: 'Pensando...',\n placeholder: 'Escribe tu respuesta — u omite la pregunta',\n send: 'Enviar',\n skip: 'Omitir y enviar',\n summary: {\n ready: 'Listo para enviar',\n what_you_said: 'Lo que dijiste',\n clarified: 'Aclarado con IA',\n auto_captured: 'Capturado automáticamente',\n element: 'Elemento',\n page: 'Página',\n browser: 'Navegador',\n captured: 'Capturado',\n send_feedback: 'Enviar comentario',\n screenshot: 'Captura de pantalla',\n recording: 'Repetición de interacción',\n },\n },\n}\n","export default {\n tab: 'Avis',\n toolbar: {\n markup: 'Annoter',\n record: 'Enregistrer',\n hint: \"Cliquez sur un élément pour l'annoter · glissez pour dessiner\",\n hintRecord: \"Enregistrement de l'écran\",\n exit: 'Quitter',\n },\n popup: {\n about: 'À propos',\n placeholder: 'Décrivez le problème ou votre suggestion...',\n submit: 'Envoyer',\n cancel: 'Annuler',\n my_feedback: 'Mes avis',\n quickOptions: [\n { emoji: '🐛', label: 'Quelque chose ne fonctionne pas' },\n { emoji: '💡', label: \"J'ai une suggestion\" },\n { emoji: '🤔', label: 'Je suis perplexe' },\n ],\n },\n success: {\n title: 'Envoyé, merci !',\n message: 'Votre message et le contexte technique collecté ont été transmis à l’équipe. Vous serez informé(e) dès que ce sera résolu.',\n title_no_ai: 'Merci ! Nous avons bien reçu votre avis.',\n message_no_ai: \"L’équipe prend le relais. Vous serez informé(e) dès que ce sera résolu.\",\n view_feedback: 'Voir mes avis',\n close: 'Fermer',\n email_prompt: \"Envie de suivre l'avancement ? Laissez votre e-mail et nous vous préviendrons une fois résolu.\",\n email_placeholder: 'vous@exemple.com',\n email_submit: 'Me prévenir',\n email_saved: 'Vous recevrez un e-mail une fois résolu.',\n email_error: \"Impossible d'enregistrer votre e-mail. Veuillez réessayer.\",\n },\n error: {\n submit: \"Échec de l'envoi. Veuillez réessayer.\",\n },\n pet: {\n bubble: \"Besoin d'aide ?\",\n },\n frustration: {\n prompt: 'Un problème ? Dites-le-nous.',\n action: 'Annoter',\n dismiss: 'Fermer',\n },\n annotation: {\n drawing: 'Dessin',\n element: 'élément',\n },\n draw: {\n note_placeholder: 'Ajoutez une note à votre dessin',\n undo: 'Annuler',\n redo: 'Rétablir',\n cancel: 'Annuler',\n submit: 'Envoyer',\n },\n record: {\n stop: 'Arrêter',\n timer_label: 'Enregistrement',\n max_reached: \"Durée maximale d'enregistrement atteinte\",\n replay_label: 'screen-recording.json',\n play: \"Lire l'enregistrement\",\n close: 'Fermer',\n preview_unavailable: 'Aperçu indisponible',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Affinement de votre retour',\n thinking: 'Réflexion...',\n placeholder: 'Saisissez votre réponse — ou ignorez la question',\n send: 'Envoyer',\n skip: 'Ignorer et envoyer',\n summary: {\n ready: 'Prêt à envoyer',\n what_you_said: 'Ce que vous avez dit',\n clarified: \"Clarifié avec l'IA\",\n auto_captured: 'Capturé automatiquement',\n element: 'Élément',\n page: 'Page',\n browser: 'Navigateur',\n captured: 'Capturé',\n send_feedback: 'Envoyer le retour',\n screenshot: \"Capture d'écran\",\n recording: 'Relecture des interactions',\n },\n },\n}\n","export default {\n tab: 'Feedback',\n toolbar: {\n markup: 'Markieren',\n record: 'Aufnehmen',\n hint: 'Klicken Sie auf ein Element zum Kommentieren · ziehen Sie zum Zeichnen',\n hintRecord: 'Bildschirm wird aufgenommen',\n exit: 'Beenden',\n },\n popup: {\n about: 'Info',\n placeholder: 'Beschreiben Sie das Problem oder Ihren Vorschlag...',\n submit: 'Absenden',\n cancel: 'Abbrechen',\n my_feedback: 'Mein Feedback',\n quickOptions: [\n { emoji: '🐛', label: 'Etwas funktioniert nicht' },\n { emoji: '💡', label: 'Ich habe einen Vorschlag' },\n { emoji: '🤔', label: 'Ich bin verwirrt' },\n ],\n },\n success: {\n title: 'Gesendet, vielen Dank!',\n message: 'Ihre Nachricht und der erfasste technische Kontext wurden an das Team gesendet. Sie werden benachrichtigt, sobald das Problem gelöst ist.',\n title_no_ai: 'Vielen Dank! Wir haben Ihr Feedback erhalten.',\n message_no_ai: 'Das Team übernimmt ab hier. Sie werden benachrichtigt, sobald das Problem gelöst ist.',\n view_feedback: 'Mein Feedback ansehen',\n close: 'Schließen',\n email_prompt: 'Updates gewünscht? Hinterlassen Sie Ihre E-Mail und wir melden uns, sobald es gelöst ist.',\n email_placeholder: 'sie@beispiel.de',\n email_submit: 'Benachrichtigen',\n email_saved: 'Sie erhalten eine E-Mail, sobald es gelöst ist.',\n email_error: 'E-Mail konnte nicht gespeichert werden. Bitte versuchen Sie es erneut.',\n },\n error: {\n submit: 'Senden fehlgeschlagen. Bitte versuchen Sie es erneut.',\n },\n pet: {\n bubble: 'Brauchen Sie Hilfe?',\n },\n frustration: {\n prompt: 'Etwas funktioniert nicht? Sagen Sie es uns.',\n action: 'Kommentieren',\n dismiss: 'Schließen',\n },\n annotation: {\n drawing: 'Zeichnung',\n element: 'Element',\n },\n draw: {\n note_placeholder: 'Fügen Sie Ihrer Zeichnung eine Notiz hinzu',\n undo: 'Rückgängig',\n redo: 'Wiederholen',\n cancel: 'Abbrechen',\n submit: 'Absenden',\n },\n record: {\n stop: 'Stopp',\n timer_label: 'Aufnahme',\n max_reached: 'Maximale Aufnahmedauer erreicht',\n replay_label: 'screen-recording.json',\n play: 'Aufnahme abspielen',\n close: 'Schließen',\n preview_unavailable: 'Vorschau nicht verfügbar',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Wir schärfen dein Feedback',\n thinking: 'Einen Moment...',\n placeholder: 'Antwort eingeben — oder Frage überspringen',\n send: 'Senden',\n skip: 'Überspringen & senden',\n summary: {\n ready: 'Bereit zum Senden',\n what_you_said: 'Was Sie gesagt haben',\n clarified: 'Mit KI geklärt',\n auto_captured: 'Automatisch erfasst',\n element: 'Element',\n page: 'Seite',\n browser: 'Browser',\n captured: 'Erfasst',\n send_feedback: 'Feedback senden',\n screenshot: 'Screenshot',\n recording: 'Interaktions-Replay',\n },\n },\n}\n","import en from './en'\nimport zhCN from './zh-CN'\nimport ja from './ja'\nimport ko from './ko'\nimport es from './es'\nimport fr from './fr'\nimport de from './de'\n\nexport type I18nMessages = typeof en\n\nconst locales: Record<string, I18nMessages> = {\n en,\n 'zh-CN': zhCN,\n ja,\n ko,\n es,\n fr,\n de,\n}\n\nexport function getMessages(locale: string): I18nMessages {\n if (locales[locale]) return locales[locale]\n const lang = locale.split('-')[0]\n if (locales[lang]) return locales[lang]\n return locales['en']\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\ntype RRWebEvent = Record<string, unknown>\ntype StopFn = () => void\n\ninterface RRWebRecordFn {\n (options: { emit: (event: RRWebEvent) => void }): StopFn\n addCustomEvent: (tag: string, payload: Record<string, unknown>) => void\n}\n\nexport interface RecordingResult {\n events: RRWebEvent[]\n duration: number\n}\n\nconst MAX_DURATION_S = 60\n// Pinned version + SRI: this script executes on customers' pages, so a\n// floating tag or unverified content would be a supply-chain hole. Bumping\n// the version requires recomputing the hash from the exact CDN file:\n// curl -sL <url> | openssl dgst -sha384 -binary | openssl base64 -A\n// Must stay on @rrweb/record's static /umd/ build: the `rrweb` package ships\n// no UMD in 2.x (its dist files are ESM and throw \"Unexpected token 'export'\"\n// in a classic script tag), and jsDelivr's auto-minified files are unsafe for\n// SRI because their hash changes when jsDelivr upgrades its minifier.\nconst RRWEB_CDN = 'https://cdn.jsdelivr.net/npm/@rrweb/record@2.1.0/umd/record.min.js'\nconst RRWEB_SRI = 'sha384-MrD66HBNSykaP2N95+6hQCFlF5oH2tvL3TD/zyvHNkP/sAFWZx98DX9MEDy8MdVT'\n\nlet rrwebLoaded: Promise<RRWebRecordFn> | null = null\n\nfunction loadRrweb(): Promise<RRWebRecordFn> {\n if (rrwebLoaded) return rrwebLoaded\n rrwebLoaded = loadViaImport().catch(() => loadViaCdn())\n return rrwebLoaded\n}\n\nasync function loadViaImport(): Promise<RRWebRecordFn> {\n const mod = await import('@rrweb/record')\n return mod.record as unknown as RRWebRecordFn\n}\n\ninterface RRWebGlobals {\n rrwebRecord?: { record: RRWebRecordFn }\n rrweb?: { record: RRWebRecordFn }\n}\n\nfunction findGlobalRecord(): RRWebRecordFn | undefined {\n const win = globalThis as unknown as Window & RRWebGlobals\n return win.rrwebRecord?.record ?? win.rrweb?.record\n}\n\nfunction loadViaCdn(): Promise<RRWebRecordFn> {\n return new Promise((resolve, reject) => {\n const existing = findGlobalRecord()\n if (existing) { resolve(existing); return }\n const script = document.createElement('script')\n script.src = RRWEB_CDN\n script.integrity = RRWEB_SRI\n script.crossOrigin = 'anonymous'\n script.onload = () => {\n const record = findGlobalRecord()\n if (record) resolve(record)\n else reject(new Error('rrweb record global not found after script load'))\n }\n script.onerror = () => reject(new Error('Failed to load rrweb from CDN'))\n document.head.appendChild(script)\n })\n}\n\nexport class RecordSession {\n private events: RRWebEvent[] = []\n private stopFn: StopFn | null = null\n private startedAt = 0\n private timer: ReturnType<typeof setTimeout> | null = null\n private clickHandler: ((e: MouseEvent) => void) | null = null\n private shadow: ShadowContainer\n private onMaxReached?: () => void\n private stopped = false\n\n constructor(shadow: ShadowContainer, onMaxReached?: () => void) {\n this.shadow = shadow\n this.onMaxReached = onMaxReached\n }\n\n async start(): Promise<void> {\n const record = await loadRrweb()\n\n this.startedAt = Date.now()\n this.stopped = false\n\n this.stopFn = record({\n emit: (event: RRWebEvent) => {\n if (!this.stopped) this.events.push(event)\n },\n })\n\n this.clickHandler = (e: MouseEvent) => {\n this.showClickRipple(e.clientX, e.clientY)\n record.addCustomEvent?.('mtb-click', {\n x: e.clientX,\n y: e.clientY,\n target: e.target instanceof HTMLElement ? e.target.tagName : '',\n })\n }\n document.addEventListener('click', this.clickHandler, true)\n\n this.timer = setTimeout(() => {\n this.onMaxReached?.()\n }, MAX_DURATION_S * 1000)\n }\n\n stop(): RecordingResult {\n this.stopped = true\n this.stopFn?.()\n this.stopFn = null\n this.cleanupTimer()\n this.cleanupClickHandler()\n\n return {\n events: this.events,\n duration: this.getDuration(),\n }\n }\n\n getDuration(): number {\n if (this.startedAt === 0) return 0\n return Math.max(1, Math.round((Date.now() - this.startedAt) / 1000))\n }\n\n destroy(): void {\n this.stopped = true\n this.stopFn?.()\n this.stopFn = null\n this.cleanupTimer()\n this.cleanupClickHandler()\n this.events = []\n this.startedAt = 0\n }\n\n private cleanupTimer(): void {\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n }\n\n private cleanupClickHandler(): void {\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler, true)\n this.clickHandler = null\n }\n }\n\n private showClickRipple(x: number, y: number): void {\n const ripple = this.shadow.el<HTMLDivElement>('div', 'mtb-click-ripple')\n ripple.style.left = `${x}px`\n ripple.style.top = `${y}px`\n this.shadow.append(ripple)\n ripple.addEventListener('animationend', () => ripple.remove())\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport class RecordControlBar {\n private el: HTMLDivElement\n private timerEl!: HTMLSpanElement\n private intervalId: ReturnType<typeof setInterval> | null = null\n private getDuration: () => number\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n getDuration: () => number,\n onStop: () => void,\n ) {\n this.getDuration = getDuration\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-record-bar')\n this.el.innerHTML = `\n <span class=\"mtb-record-dot\"></span>\n <span class=\"mtb-record-timer\">00:00</span>\n <button class=\"mtb-record-stop\" type=\"button\">${messages.record.stop}</button>\n `\n shadow.append(this.el)\n\n this.timerEl = this.el.querySelector('.mtb-record-timer')!\n this.el.querySelector('.mtb-record-stop')!.addEventListener('click', onStop)\n\n this.intervalId = setInterval(() => this.updateTimer(), 1000)\n }\n\n private updateTimer(): void {\n const secs = this.getDuration()\n const mm = String(Math.floor(secs / 60)).padStart(2, '0')\n const ss = String(secs % 60).padStart(2, '0')\n this.timerEl.textContent = `${mm}:${ss}`\n }\n\n destroy(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId)\n this.intervalId = null\n }\n this.el.remove()\n }\n}\n","import { RecordSession } from '../record/session'\nimport type { RecordingResult } from '../record/session'\nimport { RecordControlBar } from '../record/control-bar'\nimport type { ShadowContainer } from './shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport type { RecordingResult }\n\nexport class RecordingManager {\n private session: RecordSession | null = null\n private bar: RecordControlBar | null = null\n private result: RecordingResult | null = null\n\n async start(\n shadow: ShadowContainer,\n messages: I18nMessages,\n onStop: () => void,\n ): Promise<void> {\n this.session = new RecordSession(shadow, onStop)\n this.bar = new RecordControlBar(\n shadow,\n messages,\n () => this.session?.getDuration() ?? 0,\n onStop,\n )\n await this.session.start()\n }\n\n stop(): RecordingResult | null {\n if (!this.session) return null\n this.result = this.session.stop()\n this.teardownUI()\n return this.result\n }\n\n getRecording(): RecordingResult | null {\n return this.result\n }\n\n destroy(): void {\n this.teardownUI()\n this.result = null\n }\n\n private teardownUI(): void {\n this.session?.destroy()\n this.session = null\n this.bar?.destroy()\n this.bar = null\n }\n}\n","import { ShadowContainer } from './shadow'\nimport { FeedbackTab } from './tab'\nimport { FrustrationPromptCard } from './frustration-prompt'\nimport { DimOverlay } from './dim-overlay'\nimport { AnnotationToolbar } from '../annotate/toolbar'\nimport type { ToolbarMode } from '../annotate/toolbar'\nimport { AnnotationSession } from '../annotate/session'\nimport { DrawNoteBar } from '../annotate/draw-note-bar'\nimport { CommentPopup } from '../popup/comment'\nimport { ClarifyCard } from '../popup/clarify'\nimport type { ClarifySummaryContext } from '../popup/clarify'\nimport { SuccessCard } from '../popup/success'\nimport type { SuccessCardOptions } from '../popup/success'\nimport { captureScreenshot } from '../screenshot/capture'\nimport { ConsoleErrorCollector } from '../context/console'\nimport { BreadcrumbCollector } from '../context/breadcrumbs'\nimport { FrustrationDetector } from '../context/frustration'\nimport { collectPageContext } from '../context/collector'\nimport type { PageContext } from '../context/collector'\nimport { ApiClient } from '../api/client'\nimport { buildPayload } from './payload'\nimport { cacheBoardUrl, getAnonId, getCachedBoardUrl, getStoredReporterEmail, rememberReporterEmail } from './anon-id'\nimport { getMessages } from '../i18n'\nimport { RecordingManager } from './recording-manager'\nimport type { MakeThisBetterConfig, Annotation, SubmissionSessionResponse } from '../types'\n\ntype Mode = 'idle' | 'annotating' | 'recording' | 'drawing' | 'popup' | 'clarifying'\ntype Via = 'pin' | 'draw' | 'record'\n\ninterface SubmittingUi {\n setLoading: (loading: boolean) => void\n setError: (message: string) => void\n}\n\nexport class WidgetController {\n private config: MakeThisBetterConfig\n private shadow!: ShadowContainer\n private tab: FeedbackTab | null = null\n private toolbar: AnnotationToolbar | null = null\n private session: AnnotationSession | null = null\n private drawBar: DrawNoteBar | null = null\n private dim: DimOverlay | null = null\n private popup: CommentPopup | null = null\n private clarify: ClarifyCard | null = null\n private success: SuccessCard | null = null\n private frustrationPrompt: FrustrationPromptCard | null = null\n private apiClient: ApiClient\n private consoleCollector: ConsoleErrorCollector\n private breadcrumbCollector: BreadcrumbCollector\n private frustrationDetector: FrustrationDetector | null = null\n private messages: ReturnType<typeof getMessages>\n private mode: Mode = 'idle'\n private via: Via = 'pin'\n private currentAnnotation: Annotation | null = null\n private submittingUi: SubmittingUi | null = null\n private lastPopupPos: { x: number; y: number } | null = null\n private recordingManager: RecordingManager | null = null\n private activeSubmission: SubmissionSessionResponse | null = null\n private submissionAttempt = 0\n private lastHandoff: { feedbackId?: string; boardUrl?: string; identityToken?: string } = {}\n\n constructor(config: MakeThisBetterConfig) {\n this.config = config\n this.messages = getMessages(config.locale ?? 'en')\n this.apiClient = new ApiClient(config.projectKey, config.apiUrl, undefined, config.userToken, config.userTokenFn)\n this.consoleCollector = new ConsoleErrorCollector()\n this.consoleCollector.start()\n this.breadcrumbCollector = new BreadcrumbCollector()\n this.breadcrumbCollector.start()\n this.buildUI()\n\n if (config.frustrationDetection !== false) {\n this.frustrationDetector = new FrustrationDetector(() => this.handleFrustration())\n this.frustrationDetector.start()\n }\n }\n\n private buildUI(): void {\n this.shadow = new ShadowContainer(this.config.theme ?? 'auto')\n\n this.tab = new FeedbackTab(\n this.shadow,\n this.messages,\n this.config.position ?? 'right',\n () => this.handleTabClick(),\n this.config.tabText,\n )\n }\n\n private handleTabClick(): void {\n if (this.mode === 'idle') {\n this.dismissFrustrationPrompt()\n this.enterAnnotationMode()\n } else {\n this.exitAll()\n }\n }\n\n private handleFrustration(): void {\n if (this.mode !== 'idle' || this.frustrationPrompt) return\n\n this.frustrationPrompt = new FrustrationPromptCard(this.shadow, this.messages, {\n onTell: () => {\n this.dismissFrustrationPrompt()\n this.enterAnnotationMode()\n },\n onDismiss: () => this.dismissFrustrationPrompt(),\n })\n }\n\n private dismissFrustrationPrompt(): void {\n this.frustrationPrompt?.destroy()\n this.frustrationPrompt = null\n }\n\n private enterAnnotationMode(): void {\n this.mode = 'annotating'\n this.tab?.setActive(true)\n\n this.toolbar = new AnnotationToolbar(\n this.shadow,\n this.messages,\n () => this.exitAll(),\n (mode: ToolbarMode) => this.handleToolbarModeChange(mode),\n )\n this.session = this.createSession()\n }\n\n private createSession(): AnnotationSession {\n return new AnnotationSession(this.shadow, this.messages, {\n onPin: (annotation, targetName) => {\n this.currentAnnotation = annotation\n this.via = 'pin'\n this.showPopup(annotation.x, annotation.y, targetName)\n },\n onDrawStroke: () => this.handleDrawStroke(),\n })\n }\n\n private handleToolbarModeChange(mode: ToolbarMode): void {\n if (this.mode === 'clarifying') {\n this.toolbar?.setMode(this.via === 'record' ? 'record' : 'markup')\n return\n }\n\n if (mode === 'record') {\n if (this.mode === 'recording') return\n\n this.mode = 'recording'\n this.currentAnnotation = null\n this.teardownDraw()\n this.session?.destroy()\n this.session = null\n this.recordingManager = new RecordingManager()\n this.recordingManager.start(this.shadow, this.messages, () => {\n if (!this.recordingManager) return\n this.recordingManager.stop()\n this.via = 'record'\n this.showPopup(window.innerWidth / 2, window.innerHeight / 2, this.messages.record.timer_label)\n }).catch((error) => {\n // rrweb failed to load (network / SRI mismatch) — fall back to markup\n console.warn('[MakeThisBetter] Interaction replay unavailable, falling back to markup:', error)\n if (this.mode !== 'recording') return\n this.toolbar?.setMode('markup')\n this.handleToolbarModeChange('markup')\n })\n } else {\n this.recordingManager?.destroy()\n this.recordingManager = null\n this.teardownDraw()\n if (!this.session) this.session = this.createSession()\n this.mode = 'annotating'\n }\n }\n\n private handleDrawStroke(): void {\n if (this.mode !== 'drawing') {\n this.mode = 'drawing'\n this.drawBar = new DrawNoteBar(this.shadow, {\n messages: this.messages,\n onUndo: () => this.handleDrawUndoRedo('undo'),\n onRedo: () => this.handleDrawUndoRedo('redo'),\n onCancel: () => this.cancelDraw(),\n onSubmit: (note) => this.handleDrawSubmit(note),\n })\n }\n this.refreshDrawBar()\n }\n\n private handleDrawUndoRedo(action: 'undo' | 'redo'): void {\n if (action === 'undo') this.session?.undoDraw()\n else this.session?.redoDraw()\n this.refreshDrawBar()\n }\n\n private refreshDrawBar(): void {\n if (!this.session) return\n this.drawBar?.setUndoRedo(this.session.canUndoDraw(), this.session.canRedoDraw())\n }\n\n private cancelDraw(): void {\n this.session?.clearDraw()\n this.teardownDraw()\n this.mode = 'annotating'\n }\n\n private teardownDraw(): void {\n this.drawBar?.destroy()\n this.drawBar = null\n }\n\n private handleDrawSubmit(note: string): void {\n const annotation = this.session?.getDrawAnnotation()\n if (!annotation) {\n this.cancelDraw()\n return\n }\n this.currentAnnotation = annotation\n this.via = 'draw'\n this.session?.dismissInteraction()\n this.submittingUi = this.drawBar\n void this.handleSubmit(note || this.messages.annotation.drawing)\n }\n\n private showPopup(x: number, y: number, targetName: string): void {\n this.mode = 'popup'\n this.lastPopupPos = { x, y }\n this.teardownDraw()\n this.session?.dismissInteraction()\n this.popup?.destroy()\n this.popup = null\n this.dim?.destroy()\n this.dim = null\n this.dim = new DimOverlay(this.shadow, () => this.exitAll())\n\n const recording = this.via === 'record' ? this.recordingManager?.getRecording() ?? undefined : undefined\n this.popup = new CommentPopup(this.shadow, {\n targetName,\n x,\n y,\n messages: this.messages,\n recording: recording ? { events: recording.events, duration: recording.duration } : undefined,\n onSubmit: (description) => this.handleSubmit(description),\n onClose: () => this.exitAll(),\n onMyFeedback: this.buildMyFeedbackHandler(),\n })\n this.submittingUi = this.popup\n }\n\n private buildMyFeedbackHandler(): (() => void) | undefined {\n if (this.config.user) return undefined\n if (!getCachedBoardUrl()) return undefined\n\n return async () => {\n const exchange = await this.apiClient.createIdentityToken(getAnonId())\n if (!exchange?.identity_token || !exchange.board_url) return\n cacheBoardUrl(exchange.board_url)\n window.open(`${exchange.board_url}?identity=${encodeURIComponent(exchange.identity_token)}`, '_blank')\n }\n }\n\n private async handleSubmit(description: string): Promise<void> {\n const ui = this.submittingUi\n if (!ui) return\n const submissionAttempt = ++this.submissionAttempt\n ui.setLoading(true)\n await waitForPaint()\n const annotation = this.currentAnnotation\n const recording = this.recordingManager?.getRecording() ?? undefined\n\n const [screenshot, pageContext] = await Promise.all([\n captureScreenshot(annotation ? [annotation] : []),\n Promise.resolve(collectPageContext()),\n ])\n\n const payload = buildPayload(\n description,\n pageContext,\n this.consoleCollector.getErrors(),\n annotation,\n this.config.user,\n recording,\n this.config.user ? undefined : getAnonId(),\n this.config.user ? undefined : getStoredReporterEmail(),\n this.breadcrumbCollector.getBreadcrumbs(),\n )\n\n try {\n const submission = await this.apiClient.createSubmissionSession(payload, screenshot)\n if (submissionAttempt !== this.submissionAttempt) {\n await this.apiClient.abandonSubmissionSession(submission.id, submission.token).catch(() => {})\n return\n }\n this.activeSubmission = submission\n const summary = this.buildSummaryContext(description, pageContext, annotation)\n this.teardownDraw()\n this.popup?.destroy()\n this.popup = null\n this.dim?.destroy()\n this.dim = null\n this.session?.destroy()\n this.session = null\n this.recordingManager?.destroy()\n this.recordingManager = null\n this.submittingUi = null\n this.showClarify(submission, this.lastPopupPos, summary)\n } catch {\n if (submissionAttempt !== this.submissionAttempt) return\n ui.setLoading(false)\n ui.setError(this.messages.error.submit)\n }\n }\n\n private buildSummaryContext(\n description: string,\n pageContext: PageContext,\n annotation: Annotation | null,\n ): ClarifySummaryContext {\n const s = this.messages.clarify.summary\n return {\n originalDescription: description,\n element: annotation?.targetName ?? this.messages.annotation.element,\n page: pageContext.page_url,\n browser: `${pageContext.browser} · ${pageContext.os}`,\n captured: this.via === 'record' ? s.recording : s.screenshot,\n }\n }\n\n private showClarify(\n submission: SubmissionSessionResponse,\n pos: { x: number; y: number } | null,\n summary: ClarifySummaryContext,\n ): void {\n // 'clarifying' keeps the tab and frustration prompt from starting a second\n // feedback while the current one is still being clarified.\n this.mode = 'clarifying'\n this.tab?.setActive(true)\n this.clarify = new ClarifyCard(this.shadow, {\n submissionSessionId: submission.id,\n submissionToken: submission.token,\n apiClient: this.apiClient,\n messages: this.messages,\n summary,\n x: pos?.x,\n y: pos?.y,\n onFinalize: () => this.finalizeSubmission(),\n })\n }\n\n private async finalizeSubmission(): Promise<void> {\n const submission = this.activeSubmission\n if (!submission) throw new Error('No active submission session')\n const submissionAttempt = this.submissionAttempt\n\n const feedback = await this.apiClient.finalizeSubmissionSession(submission.id, submission.token)\n if (submissionAttempt !== this.submissionAttempt || this.activeSubmission !== submission) return\n\n this.activeSubmission = null\n this.lastHandoff = {\n feedbackId: feedback.id,\n boardUrl: feedback.board_url,\n identityToken: feedback.identity_token,\n }\n if (feedback.board_url) cacheBoardUrl(feedback.board_url)\n this.clarify?.destroy()\n this.clarify = null\n this.toolbar?.destroy()\n this.toolbar = null\n this.showSuccess({ skipFollowup: submission.ai_clarify_available === false })\n }\n\n private showSuccess(options?: SuccessCardOptions): void {\n this.mode = 'idle'\n this.tab?.setActive(false)\n this.success = new SuccessCard(this.shadow, this.messages, () => {\n this.success?.destroy()\n this.success = null\n }, this.buildViewFeedbackHandler(), { ...options, emailCapture: this.buildEmailCapture() })\n }\n\n private buildEmailCapture(): { onSubmit: (email: string) => Promise<boolean> } | undefined {\n const { feedbackId, identityToken } = this.lastHandoff\n if (!feedbackId || !identityToken) return undefined\n if (getStoredReporterEmail()) return undefined\n\n return {\n onSubmit: async (email: string) => {\n const saved = await this.apiClient.updateReporter(feedbackId, email, identityToken)\n if (saved) rememberReporterEmail(email)\n return saved\n },\n }\n }\n\n private buildViewFeedbackHandler(): (() => void) | undefined {\n const { boardUrl, identityToken } = this.lastHandoff\n if (!boardUrl) return undefined\n\n if (identityToken) {\n return () => {\n window.open(`${boardUrl}?identity=${encodeURIComponent(identityToken)}`, '_blank')\n }\n }\n\n if (this.config.userToken || this.config.userTokenFn) {\n return async () => {\n const token = await this.apiClient.resolveUserToken()\n if (token) window.open(`${boardUrl}?identity=${encodeURIComponent(token)}`, '_blank')\n }\n }\n\n return undefined\n }\n\n private exitAll(): void {\n this.submissionAttempt += 1\n const submission = this.activeSubmission\n this.activeSubmission = null\n if (submission) {\n void this.apiClient.abandonSubmissionSession(submission.id, submission.token).catch(() => {})\n }\n this.mode = 'idle'\n this.via = 'pin'\n this.tab?.setActive(false)\n this.teardownDraw()\n this.toolbar?.destroy()\n this.toolbar = null\n this.session?.destroy()\n this.session = null\n this.dim?.destroy()\n this.dim = null\n this.popup?.destroy()\n this.popup = null\n this.clarify?.destroy()\n this.clarify = null\n this.currentAnnotation = null\n this.submittingUi = null\n this.recordingManager?.destroy()\n this.recordingManager = null\n }\n\n destroy(): void {\n this.exitAll()\n this.consoleCollector.stop()\n this.breadcrumbCollector.stop()\n this.frustrationDetector?.stop()\n this.dismissFrustrationPrompt()\n this.clarify?.destroy()\n this.success?.destroy()\n this.tab?.destroy()\n this.recordingManager?.destroy()\n this.shadow.destroy()\n }\n}\n\nfunction waitForPaint(): Promise<void> {\n return new Promise<void>((r) => requestAnimationFrame(() => setTimeout(r, 0)))\n}\n","import { WidgetController } from './widget/controller'\nimport type { MakeThisBetterConfig } from './types'\n\nlet instance: WidgetController | null = null\n\nconst MakeThisBetter = {\n init(config: MakeThisBetterConfig): void {\n if (instance) {\n instance.destroy()\n instance = null\n }\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n instance = new WidgetController(config)\n })\n } else {\n instance = new WidgetController(config)\n }\n },\n\n destroy(): void {\n instance?.destroy()\n instance = null\n },\n}\n\nexport { MakeThisBetter }\nexport type { MakeThisBetterConfig }\n\nif (typeof window !== 'undefined') {\n (window as Window & { MakeThisBetter?: typeof MakeThisBetter }).MakeThisBetter = MakeThisBetter\n}\n"],"names":["ShadowContainer","theme","style","cssText","tag","className","el","nodes","n","FeedbackTab","shadow","messages","position","onClick","customText","label","active","FRUSTRATION_DISMISS_MS","FrustrationPromptCard","handlers","DimOverlay","AnnotationToolbar","onExit","onModeChange","m","mode","AnnotationOverlay","ElementHighlighter","rect","getElementName","below","title","text","placeholder","alt","dataMark","getCssSelector","parts","current","selector","classNames","c","parent","siblings","idx","PinMarker","x","y","index","pin","BRAND_COLOR","FONT_STACK","DRAW_STROKE","DrawLayer","buildPathD","stroke","entry","path","points","cx","cy","center","fx","fy","d","i","xs","p","ys","DRAW_MIN_POINTS","AnnotationSession","e","underEl","getElementUnder","targetName","annotation","WIDGET_HOST_ID","isWidgetElement","host","escapeHtml","DrawNoteBar","opts","canUndo","canRedo","loading","message","CommentPopup","quickOpts","o","vw","vh","margin","left","top","btn","hasText","POLL_INTERVAL_MS","POLL_TIMEOUT_MS","CARD_WIDTH","CARD_HEIGHT","ClarifyCard","skip","result","res","footer","error","s","card","button","said","saidBlock","pairs","clarifiedBlock","q","a","done","last","msg","bubble","dots","SUCCESS_AUTO_CLOSE_MS","EMAIL_PATTERN","SuccessCard","onClose","onViewFeedback","options","viewLink","emailCapture","onSubmit","input","submit","handle","email","event","resolveUrl","url","baseUrl","doc","base","uuid","counter","random","toArray","arrayLike","arr","l","styleProps","getStyleProperties","px","node","styleProperty","val","getNodeWidth","leftBorder","rightBorder","getNodeHeight","topBorder","bottomBorder","getImageSize","targetNode","width","height","getPixelRatio","ratio","FINAL_PROCESS","canvasDimensionLimit","checkCanvasDimensions","canvas","createImage","resolve","reject","img","svgToDataURL","svg","html","nodeToDataURL","xmlns","foreignObject","isInstanceOfElement","instance","nodePrototype","formatCSSText","content","formatCSSProperties","name","value","priority","getPseudoElementStyle","pseudo","clonePseudoElement","nativeNode","clonedNode","styleElement","clonePseudoElements","WOFF","JPEG","mimes","getExtension","match","getMimeType","extension","getContentFromDataUrl","dataURL","isDataUrl","makeDataUrl","mimeType","fetchAsDataURL","init","process","blob","reader","cache","getCacheKey","contentType","includeQueryParams","key","resourceToDataURL","resourceUrl","cacheKey","cloneCanvasElement","cloneVideoElement","video","ctx","poster","cloneIFrameElement","iframe","_a","cloneNode","cloneSingleNode","isSVGElement","isSlotElement","cloneChildren","_b","children","deferred","child","clonedChild","cloneCSSStyle","targetStyle","sourceStyle","cloneInputValue","cloneSelectValue","clonedSelect","selectedOption","decorate","ensureSVGSymbols","clone","uses","processedDefs","id","exist","definition","ns","defs","isRoot","URL_REGEX","URL_WITH_FORMAT_REGEX","FONT_SRC_REGEX","toRegex","escaped","parseURLs","urls","raw","quotation","embed","resourceURL","baseURL","getContentFromUrl","resolvedURL","filterPreferredFontFormat","str","preferredFontFormat","src","format","shouldEmbed","embedResources","filteredCSSText","css","embedProp","propName","propValue","cssString","embedBackground","embedImageNode","isImageElement","attributes","image","embedChildren","deferreds","embedImages","applyStyle","manual","cssFetchCache","fetchCSS","embedFonts","data","regexUrl","loadFonts","loc","parseCSS","source","commentsRegex","keyframesRegex","matches","importRegex","combinedCSSRegex","unifiedRegex","getCSSRules","styleSheets","ret","sheet","item","importIndex","metadata","rule","inline","err","getWebFontRules","cssRules","parseWebFontRules","normalizeFontFamily","font","getUsedFonts","fonts","traverse","getWebFontCSS","rules","usedFonts","embedWebFonts","styleNode","sytleContent","toSvg","toCanvas","context","canvasWidth","canvasHeight","toJpeg","captureScreenshot","annotations","dataUrl","annotated","bakeAnnotations","dataUrlToBlob","loadImage","scaleX","scaleY","pinIndex","drawStroke","drawPin","canvasToJpegBlob","drawPath","parsePathPolylines","polylines","tokens","token","header","mime","binary","bytes","ErrorSource","listener","line","col","reason","errorSource","MAX_CONSOLE_ERRORS","ConsoleErrorCollector","location","MAX_BREADCRUMBS","BreadcrumbCollector","crumb","target","field","pushOrig","replaceOrig","onNav","unused","from","to","RAGE_CLICK_THRESHOLD","RAGE_CLICK_WINDOW_MS","RAPID_NAV_THRESHOLD","RAPID_NAV_WINDOW_MS","FORM_CHECK_DELAY_MS","DEAD_CLICK_DOM_DELAY_MS","ERROR_PAGE_CHECK_DELAY_MS","INTERACTIVE_TAGS","INTERACTIVE_ROLES","ERROR_PAGE_PATTERNS","_FrustrationDetector","onFrustration","_e","now","cutoff","r","describeElement","t","form","candidates","clickTime","mutated","cls","lower","role","FrustrationDetector","collectPageContext","detectBrowser","detectOS","ua","DEFAULT_API_URL","ApiClient","projectKey","apiUrl","retryDelayMs","userToken","userTokenFn","headers","payload","screenshot","submissionToken","generateSubmissionToken","json","ext","generateIdempotencyKey","reporterExternalId","feedbackId","identityToken","submissionSessionId","body","onDelta","consumeSse","retries","delay","ms","decoder","buffer","flush","eventLine","dataLine","sep","record","byte","buildPayload","description","pageContext","consoleErrors","user","recording","anonId","anonEmail","breadcrumbs","STORAGE_KEY","EMAIL_KEY","BOARD_URL_KEY","memoryId","memoryEmail","memoryBoardUrl","getAnonId","stored","generateAnonId","getStoredReporterEmail","rememberReporterEmail","getCachedBoardUrl","cacheBoardUrl","en","zhCN","ja","ko","es","fr","de","locales","getMessages","locale","lang","MAX_DURATION_S","RRWEB_CDN","RRWEB_SRI","rrwebLoaded","loadRrweb","loadViaImport","loadViaCdn","findGlobalRecord","win","existing","script","RecordSession","onMaxReached","ripple","RecordControlBar","getDuration","onStop","secs","mm","ss","RecordingManager","WidgetController","config","note","action","exchange","ui","submissionAttempt","waitForPaint","submission","summary","pos","feedback","saved","boardUrl","MakeThisBetter"],"mappings":"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","x_google_ignoreList":[16,17,18,19,20,21,22,23,24,25]}
1
+ {"version":3,"file":"makethisbetter.cjs","sources":["../src/widget/shadow.ts","../src/widget/tab.ts","../src/widget/frustration-prompt.ts","../src/widget/dim-overlay.ts","../src/annotate/toolbar.ts","../src/annotate/overlay.ts","../src/annotate/highlighter.ts","../src/annotate/pin.ts","../src/styles.ts","../src/annotate/draw.ts","../src/annotate/session.ts","../src/context/dom-utils.ts","../src/annotate/draw-note-bar.ts","../src/popup/comment.ts","../src/popup/clarify.ts","../src/popup/success.ts","../node_modules/html-to-image/es/util.js","../node_modules/html-to-image/es/clone-pseudos.js","../node_modules/html-to-image/es/mimes.js","../node_modules/html-to-image/es/dataurl.js","../node_modules/html-to-image/es/clone-node.js","../node_modules/html-to-image/es/embed-resources.js","../node_modules/html-to-image/es/embed-images.js","../node_modules/html-to-image/es/apply-style.js","../node_modules/html-to-image/es/embed-webfonts.js","../node_modules/html-to-image/es/index.js","../src/screenshot/capture.ts","../src/context/error-source.ts","../src/context/console.ts","../src/context/breadcrumbs.ts","../src/context/frustration.ts","../src/context/collector.ts","../src/api/client.ts","../src/widget/payload.ts","../src/widget/anon-id.ts","../src/i18n/en.ts","../src/i18n/zh-CN.ts","../src/i18n/ja.ts","../src/i18n/ko.ts","../src/i18n/es.ts","../src/i18n/fr.ts","../src/i18n/de.ts","../src/i18n/index.ts","../src/record/session.ts","../src/record/control-bar.ts","../src/widget/recording-manager.ts","../src/widget/controller.ts","../src/index.ts"],"sourcesContent":["import cssText from '../styles/widget.css?inline'\nimport type { MakeThisBetterConfig } from '../types'\n\nexport class ShadowContainer {\n private host: HTMLElement\n readonly root: ShadowRoot\n\n constructor(theme: MakeThisBetterConfig['theme'] = 'auto') {\n this.host = document.createElement('div')\n this.host.id = 'mtb-widget-host'\n this.host.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;overflow:visible;z-index:2147483646;'\n this.host.setAttribute('data-mtb-theme', theme)\n document.body.appendChild(this.host)\n\n this.root = this.host.attachShadow({ mode: 'open' })\n\n const style = document.createElement('style')\n style.textContent = cssText\n this.root.appendChild(style)\n }\n\n el<T extends HTMLElement = HTMLElement>(tag: string, className?: string): T {\n const el = document.createElement(tag) as T\n if (className) el.className = className\n return el\n }\n\n append(...nodes: Node[]): void {\n for (const n of nodes) this.root.appendChild(n)\n }\n\n remove(...nodes: Node[]): void {\n for (const n of nodes) {\n if (n.parentNode === this.root) this.root.removeChild(n)\n }\n }\n\n destroy(): void {\n // host.remove() is a safe no-op if the host is already detached — e.g.\n // when Turbo swapped document.body on navigation. removeChild(host) would\n // throw NotFoundError there, aborting re-init and dropping the widget.\n this.host.remove()\n }\n}\n","import type { ShadowContainer } from './shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport class FeedbackTab {\n private el: HTMLButtonElement\n private onClick: () => void\n private idleLabel: string\n private activeLabel: string\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n position: 'left' | 'right',\n onClick: () => void,\n customText?: string,\n ) {\n this.onClick = onClick\n this.el = shadow.el<HTMLButtonElement>('button', 'mtb-tab')\n if (position === 'left') this.el.classList.add('left')\n this.idleLabel = customText ?? messages.tab\n this.activeLabel = messages.toolbar.exit\n this.setLabel(this.idleLabel)\n this.el.addEventListener('click', onClick)\n shadow.append(this.el)\n }\n\n private setLabel(label: string): void {\n this.el.textContent = label\n this.el.setAttribute('aria-label', label)\n }\n\n setActive(active: boolean): void {\n this.el.classList.toggle('active', active)\n this.setLabel(active ? this.activeLabel : this.idleLabel)\n }\n\n destroy(): void {\n this.el.removeEventListener('click', this.onClick)\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from './shadow'\nimport type { I18nMessages } from '../i18n'\n\nconst FRUSTRATION_DISMISS_MS = 8000\n\nexport class FrustrationPromptCard {\n private el: HTMLDivElement\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n handlers: { onTell: () => void; onDismiss: () => void },\n ) {\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-frustration-prompt')\n this.el.innerHTML = `\n <div class=\"mtb-frustration-icon\">&#9888;&#65039;</div>\n <span class=\"mtb-frustration-text\">${messages.frustration.prompt}</span>\n <div class=\"mtb-frustration-actions\">\n <button class=\"mtb-frustration-tell\">${messages.frustration.action}</button>\n <button class=\"mtb-frustration-dismiss\">${messages.frustration.dismiss}</button>\n </div>\n `\n\n this.el.querySelector('.mtb-frustration-tell')!.addEventListener('click', handlers.onTell)\n this.el.querySelector('.mtb-frustration-dismiss')!.addEventListener('click', handlers.onDismiss)\n\n shadow.append(this.el)\n setTimeout(handlers.onDismiss, FRUSTRATION_DISMISS_MS)\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from './shadow'\n\n// Full-screen scrim shown behind the comment popup. Clicking it resets the\n// widget, mirroring the design's dim-to-dismiss behaviour.\nexport class DimOverlay {\n private el: HTMLDivElement\n private onClick: () => void\n\n constructor(shadow: ShadowContainer, onClick: () => void) {\n this.onClick = onClick\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-dim mtb-dim-clickable')\n this.el.addEventListener('click', this.onClick)\n shadow.append(this.el)\n }\n\n destroy(): void {\n this.el.removeEventListener('click', this.onClick)\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport type ToolbarMode = 'markup' | 'record'\n\nexport class AnnotationToolbar {\n private el: HTMLDivElement\n private hintEl!: HTMLSpanElement\n private markupBtn!: HTMLButtonElement\n private recordBtn!: HTMLButtonElement\n private messages: I18nMessages\n private currentMode: ToolbarMode = 'markup'\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n onExit: () => void,\n onModeChange?: (mode: ToolbarMode) => void,\n ) {\n this.messages = messages\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-toolbar')\n this.el.innerHTML = this.buildHTML(messages)\n shadow.append(this.el)\n\n this.hintEl = this.el.querySelector('.mtb-toolbar-hint')!\n this.markupBtn = this.el.querySelector('.mtb-toolbar-mode-markup')!\n this.recordBtn = this.el.querySelector('.mtb-toolbar-mode-record')!\n\n this.markupBtn.addEventListener('click', () => {\n this.setMode('markup')\n onModeChange?.('markup')\n })\n this.recordBtn.addEventListener('click', () => {\n this.setMode('record')\n onModeChange?.('record')\n })\n this.el.querySelector('.mtb-exit-btn')!.addEventListener('click', onExit)\n }\n\n private buildHTML(m: I18nMessages): string {\n return `\n <div class=\"mtb-toolbar-modes\">\n <button class=\"mtb-toolbar-mode-btn mtb-toolbar-mode-markup active\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"7\"/><line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"21\"/><line x1=\"3\" y1=\"12\" x2=\"7\" y2=\"12\"/><line x1=\"17\" y1=\"12\" x2=\"21\" y2=\"12\"/></svg>${m.toolbar.markup}\n </button>\n <button class=\"mtb-toolbar-mode-btn mtb-toolbar-mode-record\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"4\" fill=\"currentColor\" stroke=\"none\"/></svg>${m.toolbar.record}\n </button>\n </div>\n <span class=\"mtb-toolbar-hint\">${m.toolbar.hint}</span>\n <span class=\"mtb-toolbar-sep\"></span>\n <button class=\"mtb-exit-btn\">\n <svg width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>${m.toolbar.exit}\n </button>\n `\n }\n\n setMode(mode: ToolbarMode): void {\n this.currentMode = mode\n if (mode === 'markup') {\n this.markupBtn.classList.add('active')\n this.recordBtn.classList.remove('active')\n this.hintEl.textContent = this.messages.toolbar.hint\n } else {\n this.markupBtn.classList.remove('active')\n this.recordBtn.classList.add('active')\n this.hintEl.textContent = this.messages.toolbar.hintRecord\n }\n }\n\n getMode(): ToolbarMode {\n return this.currentMode\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\nexport class AnnotationOverlay {\n private overlayEl: HTMLDivElement\n private dimEl: HTMLDivElement\n private onMouseDown: (e: MouseEvent) => void\n private onMouseMove: (e: MouseEvent) => void\n private onMouseUp: (e: MouseEvent) => void\n private onMouseLeave: (e: MouseEvent) => void\n\n constructor(\n shadow: ShadowContainer,\n handlers: {\n onMouseDown: (e: MouseEvent) => void\n onMouseMove: (e: MouseEvent) => void\n onMouseUp: (e: MouseEvent) => void\n onMouseLeave: (e: MouseEvent) => void\n },\n ) {\n this.onMouseDown = handlers.onMouseDown\n this.onMouseMove = handlers.onMouseMove\n this.onMouseUp = handlers.onMouseUp\n this.onMouseLeave = handlers.onMouseLeave\n\n this.overlayEl = shadow.el<HTMLDivElement>('div', 'mtb-overlay')\n this.overlayEl.addEventListener('mousedown', this.onMouseDown)\n this.overlayEl.addEventListener('mousemove', this.onMouseMove)\n this.overlayEl.addEventListener('mouseup', this.onMouseUp)\n this.overlayEl.addEventListener('mouseleave', this.onMouseLeave)\n shadow.append(this.overlayEl)\n\n this.dimEl = shadow.el<HTMLDivElement>('div', 'mtb-dim')\n shadow.append(this.dimEl)\n }\n\n destroy(): void {\n this.overlayEl.removeEventListener('mousedown', this.onMouseDown)\n this.overlayEl.removeEventListener('mousemove', this.onMouseMove)\n this.overlayEl.removeEventListener('mouseup', this.onMouseUp)\n this.overlayEl.removeEventListener('mouseleave', this.onMouseLeave)\n this.overlayEl.remove()\n this.dimEl.remove()\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\nexport class ElementHighlighter {\n private highlightEl: HTMLDivElement\n private tooltipEl: HTMLDivElement\n\n constructor(shadow: ShadowContainer) {\n this.highlightEl = shadow.el<HTMLDivElement>('div', 'mtb-highlight')\n this.tooltipEl = shadow.el<HTMLDivElement>('div', 'mtb-highlight-tooltip')\n this.hide()\n shadow.append(this.highlightEl, this.tooltipEl)\n }\n\n highlight(el: Element): void {\n const rect = el.getBoundingClientRect()\n this.highlightEl.style.top = `${rect.top - 2}px`\n this.highlightEl.style.left = `${rect.left - 2}px`\n this.highlightEl.style.width = `${rect.width + 4}px`\n this.highlightEl.style.height = `${rect.height + 4}px`\n this.highlightEl.style.display = 'block'\n this.showTooltip(el, rect)\n }\n\n private showTooltip(el: Element, rect: DOMRect): void {\n this.tooltipEl.textContent = getElementName(el)\n const below = rect.top < 30\n this.tooltipEl.classList.toggle('below', below)\n this.tooltipEl.style.left = `${rect.left + rect.width / 2}px`\n this.tooltipEl.style.top = below ? `${rect.bottom + 8}px` : `${rect.top - 8}px`\n this.tooltipEl.style.display = 'block'\n }\n\n hide(): void {\n this.highlightEl.style.display = 'none'\n this.tooltipEl.style.display = 'none'\n }\n\n destroy(): void {\n this.highlightEl.remove()\n this.tooltipEl.remove()\n }\n}\n\nexport function getElementName(el: Element): string {\n if (el instanceof HTMLElement) {\n const label = el.getAttribute('aria-label')\n if (label) return label\n\n const title = el.getAttribute('title')\n if (title) return title\n\n const text = el.textContent?.trim().slice(0, 40)\n if (text) return text\n\n const placeholder = (el as HTMLInputElement).placeholder\n if (placeholder) return placeholder\n\n const alt = (el as HTMLImageElement).alt\n if (alt) return alt\n\n const dataMark = el.getAttribute('data-mark')\n if (dataMark) return dataMark\n }\n return el.tagName.toLowerCase()\n}\n\nexport function getCssSelector(el: Element): string {\n const parts: string[] = []\n let current: Element | null = el\n while (current && current !== document.body && parts.length < 5) {\n let selector = current.tagName.toLowerCase()\n if (current.id) {\n selector = `#${current.id}`\n parts.unshift(selector)\n break\n }\n const classNames = Array.from(current.classList)\n .filter(c => !c.startsWith('mtb-'))\n .slice(0, 2)\n .join('.')\n if (classNames) selector += `.${classNames}`\n\n const parent = current.parentElement\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n c => c.tagName === current!.tagName,\n )\n if (siblings.length > 1) {\n const idx = siblings.indexOf(current) + 1\n selector += `:nth-of-type(${idx})`\n }\n }\n\n parts.unshift(selector)\n current = current.parentElement\n }\n return parts.join(' > ')\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\nexport class PinMarker {\n private pins: HTMLDivElement[] = []\n private shadow: ShadowContainer\n\n constructor(shadow: ShadowContainer) {\n this.shadow = shadow\n }\n\n addPin(x: number, y: number, index: number): void {\n const pin = this.shadow.el<HTMLDivElement>('div', 'mtb-pin')\n pin.textContent = String(index)\n pin.style.top = `${y}px`\n pin.style.left = `${x}px`\n this.shadow.append(pin)\n this.pins.push(pin)\n }\n\n clearAll(): void {\n for (const pin of this.pins) pin.remove()\n this.pins = []\n }\n\n destroy(): void {\n this.clearAll()\n }\n}\n","export const BRAND_COLOR = '#059669'\n\nexport const FONT_STACK = '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif'\n\nexport const DRAW_STROKE = {\n color: BRAND_COLOR,\n width: '3.5',\n linecap: 'round',\n linejoin: 'round',\n filter: 'drop-shadow(0 1px 2px rgba(5,150,105,0.35))',\n} as const\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { Annotation } from '../types'\nimport { DRAW_STROKE } from '../styles'\n\ntype Point = [number, number]\n\ninterface Stroke {\n path: SVGPathElement\n d: string\n points: Point[]\n}\n\nexport class DrawLayer {\n private svg: SVGSVGElement\n private currentPath: SVGPathElement | null = null\n private currentPoints: Point[] = []\n private isDrawing = false\n private committed: Stroke[] = []\n private redoStack: { d: string; points: Point[] }[] = []\n\n constructor(shadow: ShadowContainer) {\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n this.svg.setAttribute('class', 'mtb-draw-svg')\n shadow.append(this.svg)\n }\n\n startDraw(x: number, y: number): void {\n this.isDrawing = true\n this.currentPoints = [[x, y]]\n this.currentPath = this.createPath()\n this.svg.appendChild(this.currentPath)\n }\n\n continueDraw(x: number, y: number): void {\n if (!this.isDrawing || !this.currentPath) return\n this.currentPoints.push([x, y])\n this.currentPath.setAttribute('d', buildPathD(this.currentPoints))\n }\n\n // Commits the in-progress stroke to the undo stack and clears the redo stack.\n // Callers decide whether the stroke has enough points before committing.\n commitStroke(): boolean {\n if (!this.isDrawing || !this.currentPath) return false\n this.isDrawing = false\n this.committed.push({ path: this.currentPath, d: buildPathD(this.currentPoints), points: this.currentPoints })\n this.redoStack = []\n this.currentPath = null\n this.currentPoints = []\n return true\n }\n\n cancelCurrentDraw(): void {\n this.currentPath?.remove()\n this.currentPath = null\n this.isDrawing = false\n this.currentPoints = []\n }\n\n undo(): boolean {\n const stroke = this.committed.pop()\n if (!stroke) return false\n stroke.path.remove()\n this.redoStack.push({ d: stroke.d, points: stroke.points })\n return true\n }\n\n redo(): boolean {\n const entry = this.redoStack.pop()\n if (!entry) return false\n const path = this.createPath()\n path.setAttribute('d', entry.d)\n this.svg.appendChild(path)\n this.committed.push({ path, d: entry.d, points: entry.points })\n return true\n }\n\n canUndo(): boolean {\n return this.committed.length > 0\n }\n\n canRedo(): boolean {\n return this.redoStack.length > 0\n }\n\n hasStrokes(): boolean {\n return this.committed.length > 0\n }\n\n getAnnotation(): Annotation | null {\n if (this.committed.length === 0) return null\n const points = this.committed.flatMap(s => s.points)\n const [cx, cy] = center(points)\n return {\n type: 'draw',\n x: cx,\n y: cy,\n drawPath: this.committed.map(s => s.d).join(' '),\n }\n }\n\n clearAll(): void {\n while (this.svg.firstChild) this.svg.removeChild(this.svg.firstChild)\n this.currentPath = null\n this.isDrawing = false\n this.currentPoints = []\n this.committed = []\n this.redoStack = []\n }\n\n isCurrentlyDrawing(): boolean {\n return this.isDrawing\n }\n\n getCurrentPointCount(): number {\n return this.currentPoints.length\n }\n\n destroy(): void {\n this.svg.remove()\n }\n\n private createPath(): SVGPathElement {\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('fill', 'none')\n path.setAttribute('stroke', DRAW_STROKE.color)\n path.setAttribute('stroke-width', DRAW_STROKE.width)\n path.setAttribute('stroke-linecap', DRAW_STROKE.linecap)\n path.setAttribute('stroke-linejoin', DRAW_STROKE.linejoin)\n path.setAttribute('style', `filter:${DRAW_STROKE.filter}`)\n return path\n }\n}\n\nfunction buildPathD(points: Point[]): string {\n if (points.length === 0) return ''\n const [fx, fy] = points[0]\n let d = `M ${fx} ${fy}`\n for (let i = 1; i < points.length; i++) {\n const [x, y] = points[i]\n d += ` L ${x} ${y}`\n }\n return d\n}\n\nfunction center(points: Point[]): Point {\n const xs = points.map(p => p[0])\n const ys = points.map(p => p[1])\n const cx = (Math.min(...xs) + Math.max(...xs)) / 2\n const cy = (Math.min(...ys) + Math.max(...ys)) / 2\n return [cx, cy]\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport type { Annotation } from '../types'\nimport { AnnotationOverlay } from './overlay'\nimport { ElementHighlighter, getElementName, getCssSelector } from './highlighter'\nimport { PinMarker } from './pin'\nimport { DrawLayer } from './draw'\n\nconst DRAW_MIN_POINTS = 5\n\ninterface SessionHandlers {\n onPin: (annotation: Annotation, targetName: string) => void\n onDrawStroke: () => void\n}\n\nexport class AnnotationSession {\n private overlay: AnnotationOverlay\n private highlighter: ElementHighlighter\n private pinMarker: PinMarker\n private drawLayer: DrawLayer\n private pinCount = 0\n private interactionActive = true\n private pendingHighlightFrame: number | null = null\n private lastMoveX = 0\n private lastMoveY = 0\n\n constructor(\n shadow: ShadowContainer,\n private messages: I18nMessages,\n private handlers: SessionHandlers,\n ) {\n this.highlighter = new ElementHighlighter(shadow)\n this.pinMarker = new PinMarker(shadow)\n this.drawLayer = new DrawLayer(shadow)\n this.overlay = new AnnotationOverlay(shadow, {\n onMouseDown: (e) => this.handleMouseDown(e),\n onMouseMove: (e) => this.handleMouseMove(e),\n onMouseUp: (e) => this.handleMouseUp(e),\n onMouseLeave: () => {\n if (this.drawLayer.isCurrentlyDrawing()) this.finishStroke()\n this.cancelPendingHighlight()\n this.highlighter.hide()\n },\n })\n }\n\n private handleMouseDown(e: MouseEvent): void {\n e.preventDefault()\n this.drawLayer.startDraw(e.clientX, e.clientY)\n }\n\n private handleMouseMove(e: MouseEvent): void {\n if (this.drawLayer.isCurrentlyDrawing()) {\n this.cancelPendingHighlight()\n this.drawLayer.continueDraw(e.clientX, e.clientY)\n this.highlighter.hide()\n return\n }\n\n this.lastMoveX = e.clientX\n this.lastMoveY = e.clientY\n if (this.pendingHighlightFrame !== null) return\n this.pendingHighlightFrame = requestAnimationFrame(() => {\n this.pendingHighlightFrame = null\n this.updateHighlight()\n })\n }\n\n private updateHighlight(): void {\n if (!this.interactionActive || this.drawLayer.isCurrentlyDrawing() || this.drawSessionActive()) return\n const underEl = getElementUnder(this.lastMoveX, this.lastMoveY)\n if (underEl) this.highlighter.highlight(underEl)\n else this.highlighter.hide()\n }\n\n private cancelPendingHighlight(): void {\n if (this.pendingHighlightFrame === null) return\n cancelAnimationFrame(this.pendingHighlightFrame)\n this.pendingHighlightFrame = null\n }\n\n private handleMouseUp(e: MouseEvent): void {\n if (!this.drawLayer.isCurrentlyDrawing()) return\n this.finishStroke(e)\n }\n\n // A drag past the point threshold becomes a freehand stroke and opens the\n // draw note bar; a tap on an element becomes a pin. Stray taps while a\n // drawing already exists are ignored so they don't hijack the draw flow.\n private finishStroke(e?: MouseEvent): void {\n if (this.drawLayer.getCurrentPointCount() >= DRAW_MIN_POINTS) {\n this.drawLayer.commitStroke()\n this.highlighter.hide()\n this.handlers.onDrawStroke()\n return\n }\n\n this.drawLayer.cancelCurrentDraw()\n if (this.drawLayer.hasStrokes() || !e) return\n\n const underEl = getElementUnder(e.clientX, e.clientY)\n const targetName = underEl ? getElementName(underEl) : this.messages.annotation.element\n const annotation: Annotation = {\n type: 'pin',\n x: e.clientX,\n y: e.clientY,\n targetSelector: underEl ? getCssSelector(underEl) : undefined,\n targetText: underEl?.textContent?.trim().slice(0, 200) ?? '',\n targetName,\n }\n this.pinMarker.addPin(e.clientX, e.clientY, ++this.pinCount)\n this.highlighter.hide()\n this.handlers.onPin(annotation, targetName)\n }\n\n undoDraw(): void {\n this.drawLayer.undo()\n }\n\n redoDraw(): void {\n this.drawLayer.redo()\n }\n\n canUndoDraw(): boolean {\n return this.drawLayer.canUndo()\n }\n\n canRedoDraw(): boolean {\n return this.drawLayer.canRedo()\n }\n\n hasDrawStrokes(): boolean {\n return this.drawLayer.hasStrokes()\n }\n\n private drawSessionActive(): boolean {\n return this.drawLayer.hasStrokes() || this.drawLayer.canRedo()\n }\n\n getDrawAnnotation(): Annotation | null {\n return this.drawLayer.getAnnotation()\n }\n\n clearDraw(): void {\n this.drawLayer.clearAll()\n }\n\n dismissInteraction(): void {\n if (!this.interactionActive) return\n this.interactionActive = false\n this.cancelPendingHighlight()\n this.overlay.destroy()\n this.highlighter.destroy()\n }\n\n destroy(): void {\n this.dismissInteraction()\n this.pinMarker.destroy()\n this.drawLayer.destroy()\n }\n}\n\n// Skips the widget host via elementsFromPoint instead of toggling its\n// display — hiding the host on every mousemove flickered the toolbar.\nfunction getElementUnder(x: number, y: number): Element | null {\n return document.elementsFromPoint(x, y).find(el => el.id !== 'mtb-widget-host') ?? null\n}\n","const WIDGET_HOST_ID = 'mtb-widget-host'\n\nexport function isWidgetElement(el: Element): boolean {\n const host = document.getElementById(WIDGET_HOST_ID)\n if (!host) return false\n return host === el || host.contains(el)\n}\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;')\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport { escapeHtml } from '../context/dom-utils'\n\ninterface DrawNoteBarOptions {\n messages: I18nMessages\n onUndo: () => void\n onRedo: () => void\n onCancel: () => void\n onSubmit: (note: string) => void\n}\n\nexport class DrawNoteBar {\n private el: HTMLDivElement\n private input!: HTMLInputElement\n private undoBtn!: HTMLButtonElement\n private redoBtn!: HTMLButtonElement\n private submitBtn!: HTMLButtonElement\n private errorEl!: HTMLDivElement\n private onSubmit: (note: string) => void\n private submitLabel: string\n private loading = false\n\n constructor(shadow: ShadowContainer, opts: DrawNoteBarOptions) {\n this.onSubmit = opts.onSubmit\n this.submitLabel = opts.messages.draw.submit\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-draw-bar')\n this.el.innerHTML = this.buildHTML(opts.messages)\n shadow.append(this.el)\n\n this.input = this.el.querySelector('.mtb-draw-input')!\n this.undoBtn = this.el.querySelector('.mtb-draw-undo')!\n this.redoBtn = this.el.querySelector('.mtb-draw-redo')!\n this.submitBtn = this.el.querySelector('.mtb-draw-submit')!\n this.errorEl = this.el.querySelector('.mtb-draw-error')!\n\n this.undoBtn.addEventListener('click', opts.onUndo)\n this.redoBtn.addEventListener('click', opts.onRedo)\n this.el.querySelector('.mtb-draw-cancel')!.addEventListener('click', opts.onCancel)\n this.submitBtn.addEventListener('click', () => this.submit())\n this.input.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.isComposing || e.keyCode === 229) return\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this.submit()\n }\n })\n\n this.input.focus()\n }\n\n private buildHTML(m: I18nMessages): string {\n return `\n <input class=\"mtb-draw-input\" type=\"text\" placeholder=\"${escapeHtml(m.draw.note_placeholder)}\" />\n <button class=\"mtb-draw-icon-btn mtb-draw-undo\" type=\"button\" title=\"${escapeHtml(m.draw.undo)}\" aria-label=\"${escapeHtml(m.draw.undo)}\" disabled>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 14L4 9l5-5\"/><path d=\"M4 9h11a5 5 0 0 1 0 10h-1\"/></svg>\n </button>\n <button class=\"mtb-draw-icon-btn mtb-draw-redo\" type=\"button\" title=\"${escapeHtml(m.draw.redo)}\" aria-label=\"${escapeHtml(m.draw.redo)}\" disabled>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 14l5-5-5-5\"/><path d=\"M20 9H9a5 5 0 0 0 0 10h1\"/></svg>\n </button>\n <span class=\"mtb-draw-sep\"></span>\n <button class=\"mtb-draw-cancel\" type=\"button\">${escapeHtml(m.draw.cancel)}</button>\n <button class=\"mtb-draw-submit\" type=\"button\">${escapeHtml(m.draw.submit)}</button>\n <div class=\"mtb-draw-error\" role=\"alert\" hidden></div>\n `\n }\n\n setUndoRedo(canUndo: boolean, canRedo: boolean): void {\n this.undoBtn.disabled = !canUndo || this.loading\n this.redoBtn.disabled = !canRedo || this.loading\n }\n\n setLoading(loading: boolean): void {\n this.loading = loading\n this.input.disabled = loading\n this.submitBtn.disabled = loading\n this.undoBtn.disabled = loading || this.undoBtn.disabled\n this.redoBtn.disabled = loading || this.redoBtn.disabled\n if (loading) {\n this.submitBtn.classList.add('loading')\n this.submitBtn.innerHTML = `<span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span>`\n this.errorEl.hidden = true\n this.errorEl.textContent = ''\n } else {\n this.submitBtn.classList.remove('loading')\n this.submitBtn.textContent = this.submitLabel\n }\n }\n\n setError(message: string): void {\n this.errorEl.textContent = message\n this.errorEl.hidden = false\n }\n\n private submit(): void {\n if (this.loading) return\n this.onSubmit(this.input.value.trim())\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport { escapeHtml } from '../context/dom-utils'\n\ninterface PopupOptions {\n targetName: string\n x: number\n y: number\n onSubmit: (description: string) => void\n onClose: () => void\n onMyFeedback?: () => void\n messages: I18nMessages\n}\n\nexport class CommentPopup {\n private el: HTMLDivElement\n private textarea!: HTMLTextAreaElement\n private submitBtn!: HTMLButtonElement\n private errorEl!: HTMLDivElement\n private onSubmit: (description: string) => void\n private onClose: () => void\n private submitLabel: string\n private loading = false\n private messages: I18nMessages\n\n constructor(shadow: ShadowContainer, opts: PopupOptions) {\n this.onSubmit = opts.onSubmit\n this.onClose = opts.onClose\n this.submitLabel = opts.messages.popup.submit\n this.messages = opts.messages\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-popup')\n this.el.innerHTML = this.buildHTML(opts)\n shadow.append(this.el)\n\n this.textarea = this.el.querySelector('.mtb-textarea')!\n this.submitBtn = this.el.querySelector('.mtb-submit-btn')!\n\n this.positionPopup(opts.x, opts.y)\n this.bindEvents(opts.messages)\n if (opts.onMyFeedback) {\n this.el.querySelector('.mtb-my-feedback')!.addEventListener('click', opts.onMyFeedback)\n }\n this.textarea.focus()\n }\n\n private buildHTML(opts: PopupOptions): string {\n const m = opts.messages\n const quickOpts = m.popup.quickOptions\n .map(\n o => `\n <button class=\"mtb-quick-option\" data-quick=\"${escapeHtml(o.label)}\">\n <span class=\"mtb-quick-option-emoji\">${o.emoji}</span>\n <span>${escapeHtml(o.label)}</span>\n </button>`,\n )\n .join('')\n\n return `\n <div class=\"mtb-popup-header\">\n <div class=\"mtb-popup-icon\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#059669\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/>\n </svg>\n </div>\n <span class=\"mtb-popup-title\">${m.popup.about} \"${escapeHtml(opts.targetName)}\"</span>\n <button class=\"mtb-popup-close\" aria-label=\"Close\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n <div class=\"mtb-popup-body\">\n <div class=\"mtb-quick-options\">\n ${quickOpts}\n </div>\n <div class=\"mtb-textarea-wrap\">\n <textarea class=\"mtb-textarea\" placeholder=\"${escapeHtml(m.popup.placeholder)}\"></textarea>\n </div>\n <div class=\"mtb-popup-error\" role=\"alert\"></div>\n <div class=\"mtb-popup-actions\">\n <button class=\"mtb-cancel-btn\" type=\"button\">${escapeHtml(m.popup.cancel)}</button>\n <button class=\"mtb-submit-btn\" type=\"button\" disabled>${escapeHtml(m.popup.submit)}</button>\n </div>\n ${opts.onMyFeedback ? `<button class=\"mtb-my-feedback\" type=\"button\">${escapeHtml(m.popup.my_feedback)}</button>` : ''}\n </div>\n `\n }\n\n\n\n private positionPopup(x: number, y: number): void {\n const popupW = 320\n const popupH = 260\n const vw = window.innerWidth\n const vh = window.innerHeight\n const margin = 12\n\n let left = x + 12\n let top = y + 12\n\n if (left + popupW > vw - margin) {\n left = x - popupW - 12\n }\n if (left < margin) left = margin\n\n if (top + popupH > vh - margin) {\n top = vh - popupH - margin\n }\n if (top < margin) top = margin\n\n this.el.style.left = `${left}px`\n this.el.style.top = `${top}px`\n this.el.style.maxHeight = `${vh - top - margin}px`\n }\n\n private bindEvents(messages: I18nMessages): void {\n this.el.querySelector('.mtb-popup-close')!.addEventListener('click', () => this.onClose())\n this.el.querySelector('.mtb-cancel-btn')!.addEventListener('click', () => this.onClose())\n this.errorEl = this.el.querySelector('.mtb-popup-error')!\n\n this.el.querySelectorAll('.mtb-quick-option').forEach(btn => {\n btn.addEventListener('click', () => {\n const label = (btn as HTMLElement).dataset['quick'] ?? ''\n this.textarea.value = label\n this.updateSubmitState()\n this.submit()\n })\n })\n\n this.textarea.addEventListener('input', () => this.updateSubmitState())\n\n this.textarea.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.isComposing || e.keyCode === 229) return\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this.submit()\n }\n })\n\n this.submitBtn.addEventListener('click', () => this.submit())\n }\n\n private updateSubmitState(): void {\n const hasText = this.textarea.value.trim().length > 0\n this.submitBtn.classList.toggle('ready', hasText && !this.loading)\n this.submitBtn.disabled = !hasText || this.loading\n this.errorEl.hidden = true\n this.errorEl.textContent = ''\n }\n\n private submit(): void {\n const text = this.textarea.value.trim()\n if (!text || this.loading) return\n this.onSubmit(text)\n }\n\n setLoading(loading: boolean): void {\n this.loading = loading\n if (loading) {\n this.submitBtn.classList.add('loading')\n this.submitBtn.innerHTML = `<span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span>`\n this.textarea.disabled = true\n } else {\n this.submitBtn.classList.remove('loading')\n this.submitBtn.textContent = this.submitLabel\n this.textarea.disabled = false\n }\n this.updateSubmitState()\n }\n\n setError(message: string): void {\n this.errorEl.textContent = message\n this.errorEl.hidden = false\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n\nfunction formatDuration(seconds: number): string {\n const total = Math.max(0, Math.round(seconds))\n const mm = String(Math.floor(total / 60)).padStart(2, '0')\n const ss = String(total % 60).padStart(2, '0')\n return `${mm}:${ss}`\n}\n\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport type { ApiClient } from '../api/client'\nimport type { ClarifyMessage } from '../types'\nimport { escapeHtml } from '../context/dom-utils'\n\nconst POLL_INTERVAL_MS = 2000\n// Give up polling after this long with no assistant reply so the card never\n// spins forever (e.g. a backend job that silently died).\nconst POLL_TIMEOUT_MS = 45000\n\nexport interface ClarifySummaryContext {\n originalDescription: string\n element: string\n page: string\n browser: string\n captured: string\n}\n\ninterface ClarifyCardOptions {\n submissionSessionId: string\n submissionToken: string\n apiClient: ApiClient\n messages: I18nMessages\n onFinalize: () => Promise<void> | void\n summary?: ClarifySummaryContext\n x?: number\n y?: number\n}\n\nconst CARD_WIDTH = 346\nconst CARD_HEIGHT = 320\n\nexport class ClarifyCard {\n private el: HTMLDivElement\n private messagesEl!: HTMLDivElement\n private inputEl!: HTMLTextAreaElement\n private sendBtn!: HTMLButtonElement\n private pollTimer: ReturnType<typeof setInterval> | null = null\n private pollDeadline = 0\n private streamingBubble: HTMLDivElement | null = null\n private submissionSessionId: string\n private submissionToken: string\n private apiClient: ApiClient\n private onFinalize: () => Promise<void> | void\n private i18n: I18nMessages\n private summaryCtx?: ClarifySummaryContext\n private lastMessages: ClarifyMessage[] = []\n private done = false\n private sending = false\n private finalizing = false\n private destroyed = false\n\n constructor(shadow: ShadowContainer, opts: ClarifyCardOptions) {\n this.submissionSessionId = opts.submissionSessionId\n this.submissionToken = opts.submissionToken\n this.apiClient = opts.apiClient\n this.onFinalize = opts.onFinalize\n this.i18n = opts.messages\n this.summaryCtx = opts.summary\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-clarify')\n this.el.innerHTML = this.buildHTML(opts.messages)\n this.positionCard(opts.x, opts.y)\n shadow.append(this.el)\n\n this.messagesEl = this.el.querySelector('.mtb-clarify-messages')!\n this.inputEl = this.el.querySelector('.mtb-clarify-input')!\n this.sendBtn = this.el.querySelector('.mtb-clarify-send')!\n\n this.bindEvents()\n this.startConversation()\n }\n\n // Anchors the card near the annotation point, clamped to the viewport so it\n // never overflows a screen edge (mirrors CommentPopup.positionPopup).\n private positionCard(x?: number, y?: number): void {\n const vw = window.innerWidth\n const vh = window.innerHeight\n const margin = 12\n\n if (x === undefined || y === undefined) {\n this.el.style.left = `${Math.max(margin, (vw - CARD_WIDTH) / 2)}px`\n this.el.style.top = `${Math.max(margin, (vh - CARD_HEIGHT) / 2)}px`\n return\n }\n\n let left = x + 12\n let top = y + 12\n if (left + CARD_WIDTH > vw - margin) left = x - CARD_WIDTH - 12\n if (left < margin) left = margin\n if (top + CARD_HEIGHT > vh - margin) top = vh - CARD_HEIGHT - margin\n if (top < margin) top = margin\n\n this.el.style.left = `${left}px`\n this.el.style.top = `${top}px`\n }\n\n private buildHTML(m: I18nMessages): string {\n return `\n <div class=\"mtb-clarify-header\">\n <span class=\"mtb-clarify-icon\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M12 3l1.6 5.4L19 10l-5.4 1.6L12 17l-1.6-5.4L5 10l5.4-1.6L12 3z\"/>\n </svg>\n </span>\n <div class=\"mtb-clarify-titles\">\n <div class=\"mtb-clarify-title\">${escapeHtml(m.clarify.title)}</div>\n <div class=\"mtb-clarify-subtitle\">${escapeHtml(m.clarify.subtitle)}</div>\n </div>\n <button class=\"mtb-clarify-close\" type=\"button\" title=\"${escapeHtml(m.clarify.skip)}\" aria-label=\"${escapeHtml(m.clarify.skip)}\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n <div class=\"mtb-clarify-messages\"></div>\n <div class=\"mtb-clarify-footer\">\n <textarea class=\"mtb-clarify-input\" rows=\"2\" placeholder=\"${escapeHtml(m.clarify.placeholder)}\"></textarea>\n <div class=\"mtb-clarify-actions\">\n <button class=\"mtb-clarify-skip\" type=\"button\">${escapeHtml(m.clarify.skip)}</button>\n <button class=\"mtb-clarify-send\" type=\"button\" disabled>\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"/>\n </svg>\n <span>${escapeHtml(m.clarify.send)}</span>\n </button>\n </div>\n </div>\n `\n }\n\n private bindEvents(): void {\n const skip = () => {\n this.stopPolling()\n void this.finalize()\n }\n this.el.querySelector('.mtb-clarify-skip')!.addEventListener('click', skip)\n this.el.querySelector('.mtb-clarify-close')!.addEventListener('click', skip)\n\n this.inputEl.addEventListener('input', () => {\n this.sendBtn.disabled = !this.inputEl.value.trim()\n })\n\n this.inputEl.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.isComposing || e.keyCode === 229) return\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this.sendMessage()\n }\n })\n\n this.sendBtn.addEventListener('click', () => this.sendMessage())\n }\n\n private async startConversation(): Promise<void> {\n this.showThinking()\n await this.runInitialTurn()\n }\n\n private async sendMessage(): Promise<void> {\n const text = this.inputEl.value.trim()\n if (!text || this.sending) return\n\n this.sending = true\n this.inputEl.disabled = true\n this.sendBtn.disabled = true\n this.stopPolling()\n\n this.appendMessage({ role: 'user', content: text })\n this.inputEl.value = ''\n this.showThinking()\n this.clearError()\n\n try {\n await this.runAnswerTurn(text)\n } catch {\n if (this.destroyed) return\n this.renderConversation(this.lastMessages, false)\n this.inputEl.value = text\n this.showError()\n } finally {\n this.sending = false\n this.inputEl.disabled = false\n this.sendBtn.disabled = !this.inputEl.value.trim()\n this.inputEl.focus()\n }\n }\n\n // Streams the assistant reply; falls back to POST + polling if the backend\n // doesn't support SSE (older server) or the stream errors mid-flight.\n private async runInitialTurn(): Promise<void> {\n try {\n const result = await this.apiClient.streamClarification(\n this.submissionSessionId,\n this.submissionToken,\n (text) => this.appendStreamDelta(text),\n )\n if (this.destroyed) return\n this.endStreamingBubble()\n this.renderConversation(result.messages, result.done)\n if (result.done) this.handleDone()\n else this.startPolling()\n } catch {\n if (this.destroyed) return\n this.endStreamingBubble()\n await this.runInitialTurnViaPolling()\n }\n }\n\n private async runInitialTurnViaPolling(): Promise<void> {\n try {\n const res = await this.apiClient.startClarification(\n this.submissionSessionId,\n this.submissionToken,\n )\n if (this.destroyed) return\n this.renderConversation(res.messages, res.done)\n if (res.done) this.handleDone()\n else this.startPolling()\n } catch {\n if (this.destroyed) return\n this.handleDone()\n }\n }\n\n private async runAnswerTurn(message: string): Promise<void> {\n const res = await this.apiClient.startClarification(\n this.submissionSessionId,\n this.submissionToken,\n message,\n )\n if (this.destroyed) return\n this.renderConversation(res.messages, res.done)\n if (res.done) this.handleDone()\n else this.startPolling()\n }\n\n private showError(): void {\n const footer = this.el.querySelector('.mtb-clarify-footer')!\n const error = document.createElement('div')\n error.className = 'mtb-clarify-error'\n error.textContent = this.i18n.error.submit\n footer.prepend(error)\n }\n\n private clearError(): void {\n this.el.querySelector('.mtb-clarify-error')?.remove()\n }\n\n private appendStreamDelta(text: string): void {\n if (!this.streamingBubble) {\n this.removeThinking()\n this.streamingBubble = document.createElement('div')\n this.streamingBubble.className = 'mtb-clarify-bubble mtb-clarify-ai'\n this.messagesEl.appendChild(this.streamingBubble)\n }\n this.streamingBubble.textContent = (this.streamingBubble.textContent ?? '') + text\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private endStreamingBubble(): void {\n this.streamingBubble = null\n }\n\n private startPolling(): void {\n this.stopPolling()\n this.pollDeadline = Date.now() + POLL_TIMEOUT_MS\n this.pollTimer = setInterval(() => this.poll(), POLL_INTERVAL_MS)\n }\n\n private stopPolling(): void {\n if (this.pollTimer !== null) {\n clearInterval(this.pollTimer)\n this.pollTimer = null\n }\n }\n\n private async poll(): Promise<void> {\n if (Date.now() > this.pollDeadline) {\n this.stopPolling()\n this.handleDone()\n return\n }\n try {\n const res = await this.apiClient.getClarification(\n this.submissionSessionId,\n this.submissionToken,\n )\n if (this.destroyed) return\n this.renderConversation(res.messages, res.done)\n if (res.done) {\n this.stopPolling()\n this.handleDone()\n }\n } catch {\n if (this.destroyed) return\n this.stopPolling()\n this.handleDone()\n }\n }\n\n private handleDone(): void {\n if (this.done) return\n this.done = true\n this.stopPolling()\n this.removeThinking()\n this.renderSummary()\n }\n\n private renderSummary(): void {\n const s = this.i18n.clarify.summary\n const card = document.createElement('div')\n card.className = 'mtb-clarify-summary'\n card.innerHTML = this.buildSummaryHTML(s)\n this.messagesEl.appendChild(card)\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n\n const footer = this.el.querySelector('.mtb-clarify-footer')!\n footer.innerHTML = `<button class=\"mtb-clarify-send-feedback\" type=\"button\">${escapeHtml(s.send_feedback)}</button>`\n footer.querySelector('.mtb-clarify-send-feedback')!.addEventListener('click', () => {\n if (!this.destroyed) void this.finalize()\n })\n }\n\n private async finalize(): Promise<void> {\n if (this.finalizing || this.destroyed) return\n\n this.finalizing = true\n this.el.querySelectorAll<HTMLButtonElement>('button').forEach(button => { button.disabled = true })\n try {\n await this.onFinalize()\n } catch {\n if (this.destroyed) return\n this.finalizing = false\n this.handleDone()\n this.el.querySelectorAll<HTMLButtonElement>('button').forEach(button => { button.disabled = false })\n this.clearError()\n this.showError()\n }\n }\n\n private buildSummaryHTML(s: I18nMessages['clarify']['summary']): string {\n const said = this.summaryCtx?.originalDescription?.trim()\n const saidBlock = said\n ? `<div class=\"mtb-summary-section\">\n <div class=\"mtb-summary-label\">${escapeHtml(s.what_you_said)}</div>\n <div class=\"mtb-summary-quote\">${escapeHtml(said)}</div>\n </div>`\n : ''\n\n const pairs = this.clarifiedPairs()\n const clarifiedBlock = pairs.length\n ? `<div class=\"mtb-summary-section\">\n <div class=\"mtb-summary-label\">${escapeHtml(s.clarified)}</div>\n ${pairs.map(p => `<div class=\"mtb-summary-qa\"><span class=\"mtb-summary-q\">${escapeHtml(p.q)}</span><span class=\"mtb-summary-a\">${escapeHtml(p.a)}</span></div>`).join('')}\n </div>`\n : ''\n\n return `\n <div class=\"mtb-summary-head\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>\n <span>${escapeHtml(s.ready)}</span>\n </div>\n ${saidBlock}\n ${clarifiedBlock}\n `\n }\n\n private clarifiedPairs(): { q: string; a: string }[] {\n const pairs: { q: string; a: string }[] = []\n for (let i = 0; i < this.lastMessages.length - 1; i++) {\n const q = this.lastMessages[i]\n const a = this.lastMessages[i + 1]\n if (q.role !== 'user' && a.role === 'user') pairs.push({ q: q.content, a: a.content })\n }\n return pairs\n }\n\n private renderConversation(messages: ClarifyMessage[], done: boolean): void {\n this.lastMessages = messages\n this.renderMessages(messages)\n const last = messages[messages.length - 1]\n if (!done && (!last || last.role === 'user')) this.showThinking()\n }\n\n private renderMessages(messages: ClarifyMessage[]): void {\n this.messagesEl.innerHTML = ''\n for (const msg of messages) {\n this.appendMessage(msg)\n }\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private appendMessage(msg: ClarifyMessage): void {\n const bubble = document.createElement('div')\n bubble.className = msg.role === 'user' ? 'mtb-clarify-bubble mtb-clarify-user' : 'mtb-clarify-bubble mtb-clarify-ai'\n bubble.textContent = msg.content\n this.messagesEl.appendChild(bubble)\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private showThinking(): void {\n if (this.messagesEl.querySelector('.mtb-clarify-thinking')) return\n const dots = document.createElement('div')\n dots.className = 'mtb-clarify-bubble mtb-clarify-ai mtb-clarify-thinking'\n dots.innerHTML = '<span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span><span class=\"mtb-dot\"></span>'\n this.messagesEl.appendChild(dots)\n this.messagesEl.scrollTop = this.messagesEl.scrollHeight\n }\n\n private removeThinking(): void {\n this.messagesEl.querySelector('.mtb-clarify-thinking')?.remove()\n }\n\n destroy(): void {\n this.destroyed = true\n this.stopPolling()\n this.el.remove()\n }\n}\n\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\nimport { BRAND_COLOR } from '../styles'\n\nconst SUCCESS_AUTO_CLOSE_MS = 5000\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport interface SuccessCardOptions {\n skipFollowup?: boolean\n emailCapture?: {\n onSubmit: (email: string) => Promise<boolean>\n }\n}\n\nexport class SuccessCard {\n private el: HTMLDivElement\n private messages: I18nMessages\n\n constructor(shadow: ShadowContainer, messages: I18nMessages, onClose: () => void, onViewFeedback?: () => void, options?: SuccessCardOptions) {\n this.messages = messages\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-success')\n this.el.style.right = '20px'\n this.el.style.bottom = '20px'\n\n const title = options?.skipFollowup ? messages.success.title_no_ai : messages.success.title\n const msg = options?.skipFollowup ? messages.success.message_no_ai : messages.success.message\n\n const viewLink = onViewFeedback\n ? `<button class=\"mtb-view-feedback-link\">${messages.success.view_feedback} <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg></button>`\n : ''\n\n const emailCapture = options?.emailCapture\n ? `\n <div class=\"mtb-email-capture\">\n <div class=\"mtb-email-prompt\">${messages.success.email_prompt}</div>\n <div class=\"mtb-email-row\">\n <input class=\"mtb-email-input\" type=\"email\" placeholder=\"${messages.success.email_placeholder}\">\n <button class=\"mtb-email-submit\">${messages.success.email_submit}</button>\n </div>\n <div class=\"mtb-email-error\" hidden>${messages.success.email_error}</div>\n </div>`\n : ''\n\n this.el.innerHTML = `\n <div class=\"mtb-success-icon\">\n <svg width=\"23\" height=\"23\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"${BRAND_COLOR}\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>\n </div>\n <div class=\"mtb-success-title\">${title}</div>\n <div class=\"mtb-success-msg\">${msg}</div>\n ${emailCapture}\n ${viewLink}\n <button class=\"mtb-close-link\">${messages.success.close}</button>\n `\n shadow.append(this.el)\n this.el.querySelector('.mtb-close-link')!.addEventListener('click', onClose)\n\n if (onViewFeedback) {\n this.el.querySelector('.mtb-view-feedback-link')!.addEventListener('click', onViewFeedback)\n }\n\n if (options?.emailCapture) {\n this.bindEmailCapture(options.emailCapture.onSubmit)\n } else {\n setTimeout(() => onClose(), SUCCESS_AUTO_CLOSE_MS)\n }\n }\n\n private bindEmailCapture(onSubmit: (email: string) => Promise<boolean>): void {\n const input = this.el.querySelector<HTMLInputElement>('.mtb-email-input')!\n const submit = this.el.querySelector<HTMLButtonElement>('.mtb-email-submit')!\n const error = this.el.querySelector<HTMLDivElement>('.mtb-email-error')!\n\n const handle = async () => {\n const email = input.value.trim()\n if (!EMAIL_PATTERN.test(email)) {\n input.classList.add('mtb-email-invalid')\n return\n }\n input.classList.remove('mtb-email-invalid')\n error.hidden = true\n submit.disabled = true\n\n const saved = await onSubmit(email)\n if (saved) {\n this.el.querySelector('.mtb-email-capture')!.innerHTML =\n `<div class=\"mtb-email-saved\">${this.messages.success.email_saved}</div>`\n } else {\n error.hidden = false\n submit.disabled = false\n }\n }\n\n submit.addEventListener('click', handle)\n input.addEventListener('keydown', (event) => {\n if (event.key === 'Enter') handle()\n })\n }\n\n destroy(): void {\n this.el.remove()\n }\n}\n","export function resolveUrl(url, baseUrl) {\n // url is absolute already\n if (url.match(/^[a-z]+:\\/\\//i)) {\n return url;\n }\n // url is absolute already, without protocol\n if (url.match(/^\\/\\//)) {\n return window.location.protocol + url;\n }\n // dataURI, mailto:, tel:, etc.\n if (url.match(/^[a-z]+:/i)) {\n return url;\n }\n const doc = document.implementation.createHTMLDocument();\n const base = doc.createElement('base');\n const a = doc.createElement('a');\n doc.head.appendChild(base);\n doc.body.appendChild(a);\n if (baseUrl) {\n base.href = baseUrl;\n }\n a.href = url;\n return a.href;\n}\nexport const uuid = (() => {\n // generate uuid for className of pseudo elements.\n // We should not use GUIDs, otherwise pseudo elements sometimes cannot be captured.\n let counter = 0;\n // ref: http://stackoverflow.com/a/6248722/2519373\n const random = () => \n // eslint-disable-next-line no-bitwise\n `0000${((Math.random() * 36 ** 4) << 0).toString(36)}`.slice(-4);\n return () => {\n counter += 1;\n return `u${random()}${counter}`;\n };\n})();\nexport function delay(ms) {\n return (args) => new Promise((resolve) => {\n setTimeout(() => resolve(args), ms);\n });\n}\nexport function toArray(arrayLike) {\n const arr = [];\n for (let i = 0, l = arrayLike.length; i < l; i++) {\n arr.push(arrayLike[i]);\n }\n return arr;\n}\nlet styleProps = null;\nexport function getStyleProperties(options = {}) {\n if (styleProps) {\n return styleProps;\n }\n if (options.includeStyleProperties) {\n styleProps = options.includeStyleProperties;\n return styleProps;\n }\n styleProps = toArray(window.getComputedStyle(document.documentElement));\n return styleProps;\n}\nfunction px(node, styleProperty) {\n const win = node.ownerDocument.defaultView || window;\n const val = win.getComputedStyle(node).getPropertyValue(styleProperty);\n return val ? parseFloat(val.replace('px', '')) : 0;\n}\nfunction getNodeWidth(node) {\n const leftBorder = px(node, 'border-left-width');\n const rightBorder = px(node, 'border-right-width');\n return node.clientWidth + leftBorder + rightBorder;\n}\nfunction getNodeHeight(node) {\n const topBorder = px(node, 'border-top-width');\n const bottomBorder = px(node, 'border-bottom-width');\n return node.clientHeight + topBorder + bottomBorder;\n}\nexport function getImageSize(targetNode, options = {}) {\n const width = options.width || getNodeWidth(targetNode);\n const height = options.height || getNodeHeight(targetNode);\n return { width, height };\n}\nexport function getPixelRatio() {\n let ratio;\n let FINAL_PROCESS;\n try {\n FINAL_PROCESS = process;\n }\n catch (e) {\n // pass\n }\n const val = FINAL_PROCESS && FINAL_PROCESS.env\n ? FINAL_PROCESS.env.devicePixelRatio\n : null;\n if (val) {\n ratio = parseInt(val, 10);\n if (Number.isNaN(ratio)) {\n ratio = 1;\n }\n }\n return ratio || window.devicePixelRatio || 1;\n}\n// @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size\nconst canvasDimensionLimit = 16384;\nexport function checkCanvasDimensions(canvas) {\n if (canvas.width > canvasDimensionLimit ||\n canvas.height > canvasDimensionLimit) {\n if (canvas.width > canvasDimensionLimit &&\n canvas.height > canvasDimensionLimit) {\n if (canvas.width > canvas.height) {\n canvas.height *= canvasDimensionLimit / canvas.width;\n canvas.width = canvasDimensionLimit;\n }\n else {\n canvas.width *= canvasDimensionLimit / canvas.height;\n canvas.height = canvasDimensionLimit;\n }\n }\n else if (canvas.width > canvasDimensionLimit) {\n canvas.height *= canvasDimensionLimit / canvas.width;\n canvas.width = canvasDimensionLimit;\n }\n else {\n canvas.width *= canvasDimensionLimit / canvas.height;\n canvas.height = canvasDimensionLimit;\n }\n }\n}\nexport function canvasToBlob(canvas, options = {}) {\n if (canvas.toBlob) {\n return new Promise((resolve) => {\n canvas.toBlob(resolve, options.type ? options.type : 'image/png', options.quality ? options.quality : 1);\n });\n }\n return new Promise((resolve) => {\n const binaryString = window.atob(canvas\n .toDataURL(options.type ? options.type : undefined, options.quality ? options.quality : undefined)\n .split(',')[1]);\n const len = binaryString.length;\n const binaryArray = new Uint8Array(len);\n for (let i = 0; i < len; i += 1) {\n binaryArray[i] = binaryString.charCodeAt(i);\n }\n resolve(new Blob([binaryArray], {\n type: options.type ? options.type : 'image/png',\n }));\n });\n}\nexport function createImage(url) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n img.decode().then(() => {\n requestAnimationFrame(() => resolve(img));\n });\n };\n img.onerror = reject;\n img.crossOrigin = 'anonymous';\n img.decoding = 'async';\n img.src = url;\n });\n}\nexport async function svgToDataURL(svg) {\n return Promise.resolve()\n .then(() => new XMLSerializer().serializeToString(svg))\n .then(encodeURIComponent)\n .then((html) => `data:image/svg+xml;charset=utf-8,${html}`);\n}\nexport async function nodeToDataURL(node, width, height) {\n const xmlns = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(xmlns, 'svg');\n const foreignObject = document.createElementNS(xmlns, 'foreignObject');\n svg.setAttribute('width', `${width}`);\n svg.setAttribute('height', `${height}`);\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n foreignObject.setAttribute('width', '100%');\n foreignObject.setAttribute('height', '100%');\n foreignObject.setAttribute('x', '0');\n foreignObject.setAttribute('y', '0');\n foreignObject.setAttribute('externalResourcesRequired', 'true');\n svg.appendChild(foreignObject);\n foreignObject.appendChild(node);\n return svgToDataURL(svg);\n}\nexport const isInstanceOfElement = (node, instance) => {\n if (node instanceof instance)\n return true;\n const nodePrototype = Object.getPrototypeOf(node);\n if (nodePrototype === null)\n return false;\n return (nodePrototype.constructor.name === instance.name ||\n isInstanceOfElement(nodePrototype, instance));\n};\n//# sourceMappingURL=util.js.map","import { uuid, getStyleProperties } from './util';\nfunction formatCSSText(style) {\n const content = style.getPropertyValue('content');\n return `${style.cssText} content: '${content.replace(/'|\"/g, '')}';`;\n}\nfunction formatCSSProperties(style, options) {\n return getStyleProperties(options)\n .map((name) => {\n const value = style.getPropertyValue(name);\n const priority = style.getPropertyPriority(name);\n return `${name}: ${value}${priority ? ' !important' : ''};`;\n })\n .join(' ');\n}\nfunction getPseudoElementStyle(className, pseudo, style, options) {\n const selector = `.${className}:${pseudo}`;\n const cssText = style.cssText\n ? formatCSSText(style)\n : formatCSSProperties(style, options);\n return document.createTextNode(`${selector}{${cssText}}`);\n}\nfunction clonePseudoElement(nativeNode, clonedNode, pseudo, options) {\n const style = window.getComputedStyle(nativeNode, pseudo);\n const content = style.getPropertyValue('content');\n if (content === '' || content === 'none') {\n return;\n }\n const className = uuid();\n try {\n clonedNode.className = `${clonedNode.className} ${className}`;\n }\n catch (err) {\n return;\n }\n const styleElement = document.createElement('style');\n styleElement.appendChild(getPseudoElementStyle(className, pseudo, style, options));\n clonedNode.appendChild(styleElement);\n}\nexport function clonePseudoElements(nativeNode, clonedNode, options) {\n clonePseudoElement(nativeNode, clonedNode, ':before', options);\n clonePseudoElement(nativeNode, clonedNode, ':after', options);\n}\n//# sourceMappingURL=clone-pseudos.js.map","const WOFF = 'application/font-woff';\nconst JPEG = 'image/jpeg';\nconst mimes = {\n woff: WOFF,\n woff2: WOFF,\n ttf: 'application/font-truetype',\n eot: 'application/vnd.ms-fontobject',\n png: 'image/png',\n jpg: JPEG,\n jpeg: JPEG,\n gif: 'image/gif',\n tiff: 'image/tiff',\n svg: 'image/svg+xml',\n webp: 'image/webp',\n};\nfunction getExtension(url) {\n const match = /\\.([^./]*?)$/g.exec(url);\n return match ? match[1] : '';\n}\nexport function getMimeType(url) {\n const extension = getExtension(url).toLowerCase();\n return mimes[extension] || '';\n}\n//# sourceMappingURL=mimes.js.map","function getContentFromDataUrl(dataURL) {\n return dataURL.split(/,/)[1];\n}\nexport function isDataUrl(url) {\n return url.search(/^(data:)/) !== -1;\n}\nexport function makeDataUrl(content, mimeType) {\n return `data:${mimeType};base64,${content}`;\n}\nexport async function fetchAsDataURL(url, init, process) {\n const res = await fetch(url, init);\n if (res.status === 404) {\n throw new Error(`Resource \"${res.url}\" not found`);\n }\n const blob = await res.blob();\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = reject;\n reader.onloadend = () => {\n try {\n resolve(process({ res, result: reader.result }));\n }\n catch (error) {\n reject(error);\n }\n };\n reader.readAsDataURL(blob);\n });\n}\nconst cache = {};\nfunction getCacheKey(url, contentType, includeQueryParams) {\n let key = url.replace(/\\?.*/, '');\n if (includeQueryParams) {\n key = url;\n }\n // font resource\n if (/ttf|otf|eot|woff2?/i.test(key)) {\n key = key.replace(/.*\\//, '');\n }\n return contentType ? `[${contentType}]${key}` : key;\n}\nexport async function resourceToDataURL(resourceUrl, contentType, options) {\n const cacheKey = getCacheKey(resourceUrl, contentType, options.includeQueryParams);\n if (cache[cacheKey] != null) {\n return cache[cacheKey];\n }\n // ref: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache\n if (options.cacheBust) {\n // eslint-disable-next-line no-param-reassign\n resourceUrl += (/\\?/.test(resourceUrl) ? '&' : '?') + new Date().getTime();\n }\n let dataURL;\n try {\n const content = await fetchAsDataURL(resourceUrl, options.fetchRequestInit, ({ res, result }) => {\n if (!contentType) {\n // eslint-disable-next-line no-param-reassign\n contentType = res.headers.get('Content-Type') || '';\n }\n return getContentFromDataUrl(result);\n });\n dataURL = makeDataUrl(content, contentType);\n }\n catch (error) {\n dataURL = options.imagePlaceholder || '';\n let msg = `Failed to fetch resource: ${resourceUrl}`;\n if (error) {\n msg = typeof error === 'string' ? error : error.message;\n }\n if (msg) {\n console.warn(msg);\n }\n }\n cache[cacheKey] = dataURL;\n return dataURL;\n}\n//# sourceMappingURL=dataurl.js.map","import { clonePseudoElements } from './clone-pseudos';\nimport { createImage, toArray, isInstanceOfElement, getStyleProperties, } from './util';\nimport { getMimeType } from './mimes';\nimport { resourceToDataURL } from './dataurl';\nasync function cloneCanvasElement(canvas) {\n const dataURL = canvas.toDataURL();\n if (dataURL === 'data:,') {\n return canvas.cloneNode(false);\n }\n return createImage(dataURL);\n}\nasync function cloneVideoElement(video, options) {\n if (video.currentSrc) {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n canvas.width = video.clientWidth;\n canvas.height = video.clientHeight;\n ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n const dataURL = canvas.toDataURL();\n return createImage(dataURL);\n }\n const poster = video.poster;\n const contentType = getMimeType(poster);\n const dataURL = await resourceToDataURL(poster, contentType, options);\n return createImage(dataURL);\n}\nasync function cloneIFrameElement(iframe, options) {\n var _a;\n try {\n if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) {\n return (await cloneNode(iframe.contentDocument.body, options, true));\n }\n }\n catch (_b) {\n // Failed to clone iframe\n }\n return iframe.cloneNode(false);\n}\nasync function cloneSingleNode(node, options) {\n if (isInstanceOfElement(node, HTMLCanvasElement)) {\n return cloneCanvasElement(node);\n }\n if (isInstanceOfElement(node, HTMLVideoElement)) {\n return cloneVideoElement(node, options);\n }\n if (isInstanceOfElement(node, HTMLIFrameElement)) {\n return cloneIFrameElement(node, options);\n }\n return node.cloneNode(isSVGElement(node));\n}\nconst isSlotElement = (node) => node.tagName != null && node.tagName.toUpperCase() === 'SLOT';\nconst isSVGElement = (node) => node.tagName != null && node.tagName.toUpperCase() === 'SVG';\nasync function cloneChildren(nativeNode, clonedNode, options) {\n var _a, _b;\n if (isSVGElement(clonedNode)) {\n return clonedNode;\n }\n let children = [];\n if (isSlotElement(nativeNode) && nativeNode.assignedNodes) {\n children = toArray(nativeNode.assignedNodes());\n }\n else if (isInstanceOfElement(nativeNode, HTMLIFrameElement) &&\n ((_a = nativeNode.contentDocument) === null || _a === void 0 ? void 0 : _a.body)) {\n children = toArray(nativeNode.contentDocument.body.childNodes);\n }\n else {\n children = toArray(((_b = nativeNode.shadowRoot) !== null && _b !== void 0 ? _b : nativeNode).childNodes);\n }\n if (children.length === 0 ||\n isInstanceOfElement(nativeNode, HTMLVideoElement)) {\n return clonedNode;\n }\n await children.reduce((deferred, child) => deferred\n .then(() => cloneNode(child, options))\n .then((clonedChild) => {\n if (clonedChild) {\n clonedNode.appendChild(clonedChild);\n }\n }), Promise.resolve());\n return clonedNode;\n}\nfunction cloneCSSStyle(nativeNode, clonedNode, options) {\n const targetStyle = clonedNode.style;\n if (!targetStyle) {\n return;\n }\n const sourceStyle = window.getComputedStyle(nativeNode);\n if (sourceStyle.cssText) {\n targetStyle.cssText = sourceStyle.cssText;\n targetStyle.transformOrigin = sourceStyle.transformOrigin;\n }\n else {\n getStyleProperties(options).forEach((name) => {\n let value = sourceStyle.getPropertyValue(name);\n if (name === 'font-size' && value.endsWith('px')) {\n const reducedFont = Math.floor(parseFloat(value.substring(0, value.length - 2))) - 0.1;\n value = `${reducedFont}px`;\n }\n if (isInstanceOfElement(nativeNode, HTMLIFrameElement) &&\n name === 'display' &&\n value === 'inline') {\n value = 'block';\n }\n if (name === 'd' && clonedNode.getAttribute('d')) {\n value = `path(${clonedNode.getAttribute('d')})`;\n }\n targetStyle.setProperty(name, value, sourceStyle.getPropertyPriority(name));\n });\n }\n}\nfunction cloneInputValue(nativeNode, clonedNode) {\n if (isInstanceOfElement(nativeNode, HTMLTextAreaElement)) {\n clonedNode.innerHTML = nativeNode.value;\n }\n if (isInstanceOfElement(nativeNode, HTMLInputElement)) {\n clonedNode.setAttribute('value', nativeNode.value);\n }\n}\nfunction cloneSelectValue(nativeNode, clonedNode) {\n if (isInstanceOfElement(nativeNode, HTMLSelectElement)) {\n const clonedSelect = clonedNode;\n const selectedOption = Array.from(clonedSelect.children).find((child) => nativeNode.value === child.getAttribute('value'));\n if (selectedOption) {\n selectedOption.setAttribute('selected', '');\n }\n }\n}\nfunction decorate(nativeNode, clonedNode, options) {\n if (isInstanceOfElement(clonedNode, Element)) {\n cloneCSSStyle(nativeNode, clonedNode, options);\n clonePseudoElements(nativeNode, clonedNode, options);\n cloneInputValue(nativeNode, clonedNode);\n cloneSelectValue(nativeNode, clonedNode);\n }\n return clonedNode;\n}\nasync function ensureSVGSymbols(clone, options) {\n const uses = clone.querySelectorAll ? clone.querySelectorAll('use') : [];\n if (uses.length === 0) {\n return clone;\n }\n const processedDefs = {};\n for (let i = 0; i < uses.length; i++) {\n const use = uses[i];\n const id = use.getAttribute('xlink:href');\n if (id) {\n const exist = clone.querySelector(id);\n const definition = document.querySelector(id);\n if (!exist && definition && !processedDefs[id]) {\n // eslint-disable-next-line no-await-in-loop\n processedDefs[id] = (await cloneNode(definition, options, true));\n }\n }\n }\n const nodes = Object.values(processedDefs);\n if (nodes.length) {\n const ns = 'http://www.w3.org/1999/xhtml';\n const svg = document.createElementNS(ns, 'svg');\n svg.setAttribute('xmlns', ns);\n svg.style.position = 'absolute';\n svg.style.width = '0';\n svg.style.height = '0';\n svg.style.overflow = 'hidden';\n svg.style.display = 'none';\n const defs = document.createElementNS(ns, 'defs');\n svg.appendChild(defs);\n for (let i = 0; i < nodes.length; i++) {\n defs.appendChild(nodes[i]);\n }\n clone.appendChild(svg);\n }\n return clone;\n}\nexport async function cloneNode(node, options, isRoot) {\n if (!isRoot && options.filter && !options.filter(node)) {\n return null;\n }\n return Promise.resolve(node)\n .then((clonedNode) => cloneSingleNode(clonedNode, options))\n .then((clonedNode) => cloneChildren(node, clonedNode, options))\n .then((clonedNode) => decorate(node, clonedNode, options))\n .then((clonedNode) => ensureSVGSymbols(clonedNode, options));\n}\n//# sourceMappingURL=clone-node.js.map","import { resolveUrl } from './util';\nimport { getMimeType } from './mimes';\nimport { isDataUrl, makeDataUrl, resourceToDataURL } from './dataurl';\nconst URL_REGEX = /url\\((['\"]?)([^'\"]+?)\\1\\)/g;\nconst URL_WITH_FORMAT_REGEX = /url\\([^)]+\\)\\s*format\\(([\"']?)([^\"']+)\\1\\)/g;\nconst FONT_SRC_REGEX = /src:\\s*(?:url\\([^)]+\\)\\s*format\\([^)]+\\)[,;]\\s*)+/g;\nfunction toRegex(url) {\n // eslint-disable-next-line no-useless-escape\n const escaped = url.replace(/([.*+?^${}()|\\[\\]\\/\\\\])/g, '\\\\$1');\n return new RegExp(`(url\\\\(['\"]?)(${escaped})(['\"]?\\\\))`, 'g');\n}\nexport function parseURLs(cssText) {\n const urls = [];\n cssText.replace(URL_REGEX, (raw, quotation, url) => {\n urls.push(url);\n return raw;\n });\n return urls.filter((url) => !isDataUrl(url));\n}\nexport async function embed(cssText, resourceURL, baseURL, options, getContentFromUrl) {\n try {\n const resolvedURL = baseURL ? resolveUrl(resourceURL, baseURL) : resourceURL;\n const contentType = getMimeType(resourceURL);\n let dataURL;\n if (getContentFromUrl) {\n const content = await getContentFromUrl(resolvedURL);\n dataURL = makeDataUrl(content, contentType);\n }\n else {\n dataURL = await resourceToDataURL(resolvedURL, contentType, options);\n }\n return cssText.replace(toRegex(resourceURL), `$1${dataURL}$3`);\n }\n catch (error) {\n // pass\n }\n return cssText;\n}\nfunction filterPreferredFontFormat(str, { preferredFontFormat }) {\n return !preferredFontFormat\n ? str\n : str.replace(FONT_SRC_REGEX, (match) => {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const [src, , format] = URL_WITH_FORMAT_REGEX.exec(match) || [];\n if (!format) {\n return '';\n }\n if (format === preferredFontFormat) {\n return `src: ${src};`;\n }\n }\n });\n}\nexport function shouldEmbed(url) {\n return url.search(URL_REGEX) !== -1;\n}\nexport async function embedResources(cssText, baseUrl, options) {\n if (!shouldEmbed(cssText)) {\n return cssText;\n }\n const filteredCSSText = filterPreferredFontFormat(cssText, options);\n const urls = parseURLs(filteredCSSText);\n return urls.reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText));\n}\n//# sourceMappingURL=embed-resources.js.map","import { embedResources } from './embed-resources';\nimport { toArray, isInstanceOfElement } from './util';\nimport { isDataUrl, resourceToDataURL } from './dataurl';\nimport { getMimeType } from './mimes';\nasync function embedProp(propName, node, options) {\n var _a;\n const propValue = (_a = node.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue(propName);\n if (propValue) {\n const cssString = await embedResources(propValue, null, options);\n node.style.setProperty(propName, cssString, node.style.getPropertyPriority(propName));\n return true;\n }\n return false;\n}\nasync function embedBackground(clonedNode, options) {\n ;\n (await embedProp('background', clonedNode, options)) ||\n (await embedProp('background-image', clonedNode, options));\n (await embedProp('mask', clonedNode, options)) ||\n (await embedProp('-webkit-mask', clonedNode, options)) ||\n (await embedProp('mask-image', clonedNode, options)) ||\n (await embedProp('-webkit-mask-image', clonedNode, options));\n}\nasync function embedImageNode(clonedNode, options) {\n const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement);\n if (!(isImageElement && !isDataUrl(clonedNode.src)) &&\n !(isInstanceOfElement(clonedNode, SVGImageElement) &&\n !isDataUrl(clonedNode.href.baseVal))) {\n return;\n }\n const url = isImageElement ? clonedNode.src : clonedNode.href.baseVal;\n const dataURL = await resourceToDataURL(url, getMimeType(url), options);\n await new Promise((resolve, reject) => {\n clonedNode.onload = resolve;\n clonedNode.onerror = options.onImageErrorHandler\n ? (...attributes) => {\n try {\n resolve(options.onImageErrorHandler(...attributes));\n }\n catch (error) {\n reject(error);\n }\n }\n : reject;\n const image = clonedNode;\n if (image.decode) {\n image.decode = resolve;\n }\n if (image.loading === 'lazy') {\n image.loading = 'eager';\n }\n if (isImageElement) {\n clonedNode.srcset = '';\n clonedNode.src = dataURL;\n }\n else {\n clonedNode.href.baseVal = dataURL;\n }\n });\n}\nasync function embedChildren(clonedNode, options) {\n const children = toArray(clonedNode.childNodes);\n const deferreds = children.map((child) => embedImages(child, options));\n await Promise.all(deferreds).then(() => clonedNode);\n}\nexport async function embedImages(clonedNode, options) {\n if (isInstanceOfElement(clonedNode, Element)) {\n await embedBackground(clonedNode, options);\n await embedImageNode(clonedNode, options);\n await embedChildren(clonedNode, options);\n }\n}\n//# sourceMappingURL=embed-images.js.map","export function applyStyle(node, options) {\n const { style } = node;\n if (options.backgroundColor) {\n style.backgroundColor = options.backgroundColor;\n }\n if (options.width) {\n style.width = `${options.width}px`;\n }\n if (options.height) {\n style.height = `${options.height}px`;\n }\n const manual = options.style;\n if (manual != null) {\n Object.keys(manual).forEach((key) => {\n style[key] = manual[key];\n });\n }\n return node;\n}\n//# sourceMappingURL=apply-style.js.map","import { toArray } from './util';\nimport { fetchAsDataURL } from './dataurl';\nimport { shouldEmbed, embedResources } from './embed-resources';\nconst cssFetchCache = {};\nasync function fetchCSS(url) {\n let cache = cssFetchCache[url];\n if (cache != null) {\n return cache;\n }\n const res = await fetch(url);\n const cssText = await res.text();\n cache = { url, cssText };\n cssFetchCache[url] = cache;\n return cache;\n}\nasync function embedFonts(data, options) {\n let cssText = data.cssText;\n const regexUrl = /url\\([\"']?([^\"')]+)[\"']?\\)/g;\n const fontLocs = cssText.match(/url\\([^)]+\\)/g) || [];\n const loadFonts = fontLocs.map(async (loc) => {\n let url = loc.replace(regexUrl, '$1');\n if (!url.startsWith('https://')) {\n url = new URL(url, data.url).href;\n }\n return fetchAsDataURL(url, options.fetchRequestInit, ({ result }) => {\n cssText = cssText.replace(loc, `url(${result})`);\n return [loc, result];\n });\n });\n return Promise.all(loadFonts).then(() => cssText);\n}\nfunction parseCSS(source) {\n if (source == null) {\n return [];\n }\n const result = [];\n const commentsRegex = /(\\/\\*[\\s\\S]*?\\*\\/)/gi;\n // strip out comments\n let cssText = source.replace(commentsRegex, '');\n // eslint-disable-next-line prefer-regex-literals\n const keyframesRegex = new RegExp('((@.*?keyframes [\\\\s\\\\S]*?){([\\\\s\\\\S]*?}\\\\s*?)})', 'gi');\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const matches = keyframesRegex.exec(cssText);\n if (matches === null) {\n break;\n }\n result.push(matches[0]);\n }\n cssText = cssText.replace(keyframesRegex, '');\n const importRegex = /@import[\\s\\S]*?url\\([^)]*\\)[\\s\\S]*?;/gi;\n // to match css & media queries together\n const combinedCSSRegex = '((\\\\s*?(?:\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/)?\\\\s*?@media[\\\\s\\\\S]' +\n '*?){([\\\\s\\\\S]*?)}\\\\s*?})|(([\\\\s\\\\S]*?){([\\\\s\\\\S]*?)})';\n // unified regex\n const unifiedRegex = new RegExp(combinedCSSRegex, 'gi');\n // eslint-disable-next-line no-constant-condition\n while (true) {\n let matches = importRegex.exec(cssText);\n if (matches === null) {\n matches = unifiedRegex.exec(cssText);\n if (matches === null) {\n break;\n }\n else {\n importRegex.lastIndex = unifiedRegex.lastIndex;\n }\n }\n else {\n unifiedRegex.lastIndex = importRegex.lastIndex;\n }\n result.push(matches[0]);\n }\n return result;\n}\nasync function getCSSRules(styleSheets, options) {\n const ret = [];\n const deferreds = [];\n // First loop inlines imports\n styleSheets.forEach((sheet) => {\n if ('cssRules' in sheet) {\n try {\n toArray(sheet.cssRules || []).forEach((item, index) => {\n if (item.type === CSSRule.IMPORT_RULE) {\n let importIndex = index + 1;\n const url = item.href;\n const deferred = fetchCSS(url)\n .then((metadata) => embedFonts(metadata, options))\n .then((cssText) => parseCSS(cssText).forEach((rule) => {\n try {\n sheet.insertRule(rule, rule.startsWith('@import')\n ? (importIndex += 1)\n : sheet.cssRules.length);\n }\n catch (error) {\n console.error('Error inserting rule from remote css', {\n rule,\n error,\n });\n }\n }))\n .catch((e) => {\n console.error('Error loading remote css', e.toString());\n });\n deferreds.push(deferred);\n }\n });\n }\n catch (e) {\n const inline = styleSheets.find((a) => a.href == null) || document.styleSheets[0];\n if (sheet.href != null) {\n deferreds.push(fetchCSS(sheet.href)\n .then((metadata) => embedFonts(metadata, options))\n .then((cssText) => parseCSS(cssText).forEach((rule) => {\n inline.insertRule(rule, inline.cssRules.length);\n }))\n .catch((err) => {\n console.error('Error loading remote stylesheet', err);\n }));\n }\n console.error('Error inlining remote css file', e);\n }\n }\n });\n return Promise.all(deferreds).then(() => {\n // Second loop parses rules\n styleSheets.forEach((sheet) => {\n if ('cssRules' in sheet) {\n try {\n toArray(sheet.cssRules || []).forEach((item) => {\n ret.push(item);\n });\n }\n catch (e) {\n console.error(`Error while reading CSS rules from ${sheet.href}`, e);\n }\n }\n });\n return ret;\n });\n}\nfunction getWebFontRules(cssRules) {\n return cssRules\n .filter((rule) => rule.type === CSSRule.FONT_FACE_RULE)\n .filter((rule) => shouldEmbed(rule.style.getPropertyValue('src')));\n}\nasync function parseWebFontRules(node, options) {\n if (node.ownerDocument == null) {\n throw new Error('Provided element is not within a Document');\n }\n const styleSheets = toArray(node.ownerDocument.styleSheets);\n const cssRules = await getCSSRules(styleSheets, options);\n return getWebFontRules(cssRules);\n}\nfunction normalizeFontFamily(font) {\n return font.trim().replace(/[\"']/g, '');\n}\nfunction getUsedFonts(node) {\n const fonts = new Set();\n function traverse(node) {\n const fontFamily = node.style.fontFamily || getComputedStyle(node).fontFamily;\n fontFamily.split(',').forEach((font) => {\n fonts.add(normalizeFontFamily(font));\n });\n Array.from(node.children).forEach((child) => {\n if (child instanceof HTMLElement) {\n traverse(child);\n }\n });\n }\n traverse(node);\n return fonts;\n}\nexport async function getWebFontCSS(node, options) {\n const rules = await parseWebFontRules(node, options);\n const usedFonts = getUsedFonts(node);\n const cssTexts = await Promise.all(rules\n .filter((rule) => usedFonts.has(normalizeFontFamily(rule.style.fontFamily)))\n .map((rule) => {\n const baseUrl = rule.parentStyleSheet\n ? rule.parentStyleSheet.href\n : null;\n return embedResources(rule.cssText, baseUrl, options);\n }));\n return cssTexts.join('\\n');\n}\nexport async function embedWebFonts(clonedNode, options) {\n const cssText = options.fontEmbedCSS != null\n ? options.fontEmbedCSS\n : options.skipFonts\n ? null\n : await getWebFontCSS(clonedNode, options);\n if (cssText) {\n const styleNode = document.createElement('style');\n const sytleContent = document.createTextNode(cssText);\n styleNode.appendChild(sytleContent);\n if (clonedNode.firstChild) {\n clonedNode.insertBefore(styleNode, clonedNode.firstChild);\n }\n else {\n clonedNode.appendChild(styleNode);\n }\n }\n}\n//# sourceMappingURL=embed-webfonts.js.map","import { cloneNode } from './clone-node';\nimport { embedImages } from './embed-images';\nimport { applyStyle } from './apply-style';\nimport { embedWebFonts, getWebFontCSS } from './embed-webfonts';\nimport { getImageSize, getPixelRatio, createImage, canvasToBlob, nodeToDataURL, checkCanvasDimensions, } from './util';\nexport async function toSvg(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const clonedNode = (await cloneNode(node, options, true));\n await embedWebFonts(clonedNode, options);\n await embedImages(clonedNode, options);\n applyStyle(clonedNode, options);\n const datauri = await nodeToDataURL(clonedNode, width, height);\n return datauri;\n}\nexport async function toCanvas(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const svg = await toSvg(node, options);\n const img = await createImage(svg);\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n const ratio = options.pixelRatio || getPixelRatio();\n const canvasWidth = options.canvasWidth || width;\n const canvasHeight = options.canvasHeight || height;\n canvas.width = canvasWidth * ratio;\n canvas.height = canvasHeight * ratio;\n if (!options.skipAutoScale) {\n checkCanvasDimensions(canvas);\n }\n canvas.style.width = `${canvasWidth}`;\n canvas.style.height = `${canvasHeight}`;\n if (options.backgroundColor) {\n context.fillStyle = options.backgroundColor;\n context.fillRect(0, 0, canvas.width, canvas.height);\n }\n context.drawImage(img, 0, 0, canvas.width, canvas.height);\n return canvas;\n}\nexport async function toPixelData(node, options = {}) {\n const { width, height } = getImageSize(node, options);\n const canvas = await toCanvas(node, options);\n const ctx = canvas.getContext('2d');\n return ctx.getImageData(0, 0, width, height).data;\n}\nexport async function toPng(node, options = {}) {\n const canvas = await toCanvas(node, options);\n return canvas.toDataURL();\n}\nexport async function toJpeg(node, options = {}) {\n const canvas = await toCanvas(node, options);\n return canvas.toDataURL('image/jpeg', options.quality || 1);\n}\nexport async function toBlob(node, options = {}) {\n const canvas = await toCanvas(node, options);\n const blob = await canvasToBlob(canvas);\n return blob;\n}\nexport async function getFontEmbedCSS(node, options = {}) {\n return getWebFontCSS(node, options);\n}\n//# sourceMappingURL=index.js.map","import { toJpeg } from 'html-to-image'\nimport type { Annotation } from '../types'\nimport { BRAND_COLOR, FONT_STACK } from '../styles'\n\n// Capture at CSS pixels (pixelRatio 1) as JPEG to keep the upload small: on\n// retina screens the default devicePixelRatio would quadruple the pixel count,\n// and the model downscales past ~1568px anyway.\n//\n// Annotations are baked onto the captured bitmap with canvas 2D afterwards —\n// never mounted into the live page — so the capture leaves the page visually\n// untouched no matter how long the DOM snapshot takes.\nexport async function captureScreenshot(annotations: Annotation[] = []): Promise<Blob | null> {\n try {\n const dataUrl = await toJpeg(document.body, {\n quality: 0.85,\n pixelRatio: 1,\n backgroundColor: '#ffffff',\n skipFonts: true,\n skipAutoScale: false,\n filter: (node) => {\n if (node instanceof HTMLElement && node.id === 'mtb-widget-host') return false\n return true\n },\n })\n if (annotations.length > 0) {\n const annotated = await bakeAnnotations(dataUrl, annotations)\n if (annotated) return annotated\n }\n return dataUrlToBlob(dataUrl)\n } catch {\n return null\n }\n}\n\nasync function bakeAnnotations(dataUrl: string, annotations: Annotation[]): Promise<Blob | null> {\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx) return null\n\n const image = await loadImage(dataUrl)\n if (!image) return null\n\n canvas.width = image.naturalWidth || window.innerWidth\n canvas.height = image.naturalHeight || window.innerHeight\n ctx.drawImage(image, 0, 0)\n const scaleX = canvas.width / window.innerWidth\n const scaleY = canvas.height / window.innerHeight\n\n let pinIndex = 0\n for (const annotation of annotations) {\n if (annotation.type === 'draw' && annotation.drawPath) {\n drawStroke(ctx, annotation.drawPath, scaleX, scaleY)\n } else if (annotation.type === 'pin') {\n drawPin(ctx, annotation.x * scaleX, annotation.y * scaleY, ++pinIndex)\n }\n }\n\n return canvasToJpegBlob(canvas)\n}\n\nfunction drawStroke(ctx: CanvasRenderingContext2D, drawPath: string, scaleX: number, scaleY: number): void {\n ctx.save()\n ctx.strokeStyle = BRAND_COLOR\n ctx.lineWidth = 3.5\n ctx.lineCap = 'round'\n ctx.lineJoin = 'round'\n ctx.shadowColor = 'rgba(5,150,105,0.35)'\n ctx.shadowOffsetY = 1\n ctx.shadowBlur = 2\n for (const points of parsePathPolylines(drawPath)) {\n if (points.length === 0) continue\n ctx.beginPath()\n ctx.moveTo(points[0][0] * scaleX, points[0][1] * scaleY)\n for (let i = 1; i < points.length; i++) ctx.lineTo(points[i][0] * scaleX, points[i][1] * scaleY)\n ctx.stroke()\n }\n ctx.restore()\n}\n\nfunction drawPin(ctx: CanvasRenderingContext2D, x: number, y: number, index: number): void {\n ctx.save()\n ctx.shadowColor = 'rgba(5,150,105,0.45)'\n ctx.shadowOffsetY = 2\n ctx.shadowBlur = 8\n ctx.fillStyle = BRAND_COLOR\n ctx.beginPath()\n ctx.arc(x, y, 11, 0, Math.PI * 2)\n ctx.fill()\n ctx.shadowColor = 'transparent'\n ctx.lineWidth = 2\n ctx.strokeStyle = '#ffffff'\n ctx.stroke()\n ctx.fillStyle = '#ffffff'\n ctx.font = `700 10px ${FONT_STACK}`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillText(String(index), x, y)\n ctx.restore()\n}\n\n// The draw layer only ever emits M/L polyline commands (see buildPathD in\n// annotate/draw.ts); anything else in the string is ignored.\nexport function parsePathPolylines(drawPath: string): Array<Array<[number, number]>> {\n const polylines: Array<Array<[number, number]>> = []\n let current: Array<[number, number]> | null = null\n const tokens = drawPath.match(/[ML]\\s*[-\\d.]+\\s+[-\\d.]+/g) ?? []\n for (const token of tokens) {\n const [x, y] = token.slice(1).trim().split(/\\s+/).map(Number)\n if (Number.isNaN(x) || Number.isNaN(y)) continue\n if (token[0] === 'M') {\n current = [[x, y]]\n polylines.push(current)\n } else if (current) {\n current.push([x, y])\n }\n }\n return polylines\n}\n\nfunction loadImage(dataUrl: string): Promise<HTMLImageElement | null> {\n return new Promise(resolve => {\n const image = new Image()\n image.onload = () => resolve(image)\n image.onerror = () => resolve(null)\n image.src = dataUrl\n })\n}\n\nfunction canvasToJpegBlob(canvas: HTMLCanvasElement): Promise<Blob | null> {\n return new Promise(resolve => {\n try {\n canvas.toBlob(blob => resolve(blob), 'image/jpeg', 0.85)\n } catch {\n resolve(null)\n }\n })\n}\n\nfunction dataUrlToBlob(dataUrl: string): Blob {\n const [header, data] = dataUrl.split(',')\n const mime = header.match(/:(.*?);/)?.[1] ?? 'image/png'\n const binary = atob(data)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return new Blob([bytes], { type: mime })\n}\n","export interface ErrorSourceEvent {\n message: string\n source?: string\n line?: number\n col?: number\n error?: unknown\n}\n\ntype ErrorListener = (event: ErrorSourceEvent) => void\n\nclass ErrorSource {\n private listeners = new Set<ErrorListener>()\n private originalOnError: OnErrorEventHandler | null = null\n private installedOnError: OnErrorEventHandler | null = null\n private rejectionHandler: ((e: PromiseRejectionEvent) => void) | null = null\n private hooked = false\n\n subscribe(listener: ErrorListener): () => void {\n this.listeners.add(listener)\n this.hook()\n return () => {\n this.listeners.delete(listener)\n if (this.listeners.size === 0) this.unhook()\n }\n }\n\n private hook(): void {\n if (this.hooked) return\n this.hooked = true\n\n this.originalOnError = window.onerror\n this.installedOnError = (msg, source, line, col, error) => {\n this.emit({ message: String(msg), source, line, col, error })\n if (this.originalOnError) {\n return this.originalOnError.call(window, msg, source, line, col, error)\n }\n return false\n }\n window.onerror = this.installedOnError\n\n this.rejectionHandler = (e: PromiseRejectionEvent) => {\n const reason = e.reason instanceof Error ? e.reason.message : String(e.reason)\n this.emit({ message: `Unhandled rejection: ${reason}` })\n }\n window.addEventListener('unhandledrejection', this.rejectionHandler)\n }\n\n private unhook(): void {\n if (!this.hooked) return\n this.hooked = false\n // Only restore if nothing replaced our handler meanwhile — restoring\n // the stale snapshot would clobber a handler the page installed later.\n if (window.onerror === this.installedOnError) {\n window.onerror = this.originalOnError\n }\n this.installedOnError = null\n this.originalOnError = null\n if (this.rejectionHandler) {\n window.removeEventListener('unhandledrejection', this.rejectionHandler)\n this.rejectionHandler = null\n }\n }\n\n private emit(event: ErrorSourceEvent): void {\n for (const listener of this.listeners) listener(event)\n }\n}\n\nexport const errorSource = new ErrorSource()\n","import { errorSource, type ErrorSourceEvent } from './error-source'\n\nconst MAX_CONSOLE_ERRORS = 20\n\nexport class ConsoleErrorCollector {\n private errors: string[] = []\n private unsubscribe: (() => void) | null = null\n\n start(): void {\n if (this.unsubscribe) return\n this.unsubscribe = errorSource.subscribe((e) => this.record(e))\n }\n\n private record(e: ErrorSourceEvent): void {\n const location = e.line != null ? ` (${e.line}:${e.col ?? 0})` : ''\n this.addError(`${e.message}${location}`)\n }\n\n private addError(msg: string): void {\n if (this.errors.length >= MAX_CONSOLE_ERRORS) return\n if (!this.errors.includes(msg)) {\n this.errors.push(msg)\n }\n }\n\n getErrors(): string[] {\n return [...this.errors]\n }\n\n stop(): void {\n this.unsubscribe?.()\n this.unsubscribe = null\n }\n}\n","import { errorSource, type ErrorSourceEvent } from './error-source'\nimport { getCssSelector, getElementName } from '../annotate/highlighter'\nimport { isWidgetElement } from './dom-utils'\nimport type { Breadcrumb } from '../types'\n\nconst MAX_BREADCRUMBS = 20\n\nexport class BreadcrumbCollector {\n private breadcrumbs: Breadcrumb[] = []\n private active = false\n private unsubscribeErrors: (() => void) | null = null\n private boundClickHandler: (e: MouseEvent) => void\n private boundChangeHandler: (e: Event) => void\n private boundPopstateHandler: (() => void) | null = null\n private originalPushState: History['pushState'] | null = null\n private originalReplaceState: History['replaceState'] | null = null\n private installedPushState: History['pushState'] | null = null\n private installedReplaceState: History['replaceState'] | null = null\n private lastUrl = ''\n\n constructor() {\n this.boundClickHandler = (e: MouseEvent) => this.handleClick(e)\n this.boundChangeHandler = (e: Event) => this.handleChange(e)\n }\n\n start(): void {\n if (this.active) return\n this.active = true\n this.lastUrl = location.href\n document.addEventListener('click', this.boundClickHandler, { capture: true, passive: true })\n document.addEventListener('change', this.boundChangeHandler, { capture: true, passive: true })\n this.unsubscribeErrors = errorSource.subscribe((e) => this.recordError(e))\n this.startNavigationTracking()\n }\n\n stop(): void {\n if (!this.active) return\n this.active = false\n document.removeEventListener('click', this.boundClickHandler, true)\n document.removeEventListener('change', this.boundChangeHandler, true)\n this.unsubscribeErrors?.()\n this.unsubscribeErrors = null\n this.stopNavigationTracking()\n }\n\n getBreadcrumbs(): Breadcrumb[] {\n return [...this.breadcrumbs]\n }\n\n private add(crumb: Breadcrumb): void {\n this.breadcrumbs.push(crumb)\n if (this.breadcrumbs.length > MAX_BREADCRUMBS) {\n this.breadcrumbs.shift()\n }\n }\n\n private handleClick(e: MouseEvent): void {\n const target = e.target as Element | null\n if (!target) return\n if (isWidgetElement(target)) return\n\n try {\n this.add({\n type: 'ui',\n category: 'ui.click',\n timestamp: Date.now(),\n message: getElementName(target),\n data: { selector: getCssSelector(target) },\n })\n } catch { /* never propagate into host page */ }\n }\n\n private handleChange(e: Event): void {\n const target = e.target as Element | null\n if (!target) return\n if (isWidgetElement(target)) return\n\n try {\n const input = target as HTMLInputElement\n const field = input.name || input.placeholder || target.getAttribute('aria-label') || target.tagName\n this.add({\n type: 'ui',\n category: 'ui.input',\n timestamp: Date.now(),\n message: field,\n data: { field },\n })\n } catch { /* never propagate into host page */ }\n }\n\n private recordError(e: ErrorSourceEvent): void {\n this.add({\n type: 'console',\n category: 'console.error',\n timestamp: Date.now(),\n message: e.message,\n data: { message: e.message },\n })\n }\n\n private startNavigationTracking(): void {\n this.boundPopstateHandler = () => this.handleNavigation()\n window.addEventListener('popstate', this.boundPopstateHandler)\n\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n const pushOrig = this.originalPushState\n const replaceOrig = this.originalReplaceState\n const onNav = () => this.handleNavigation()\n\n this.installedPushState = function (data: unknown, unused: string, url?: string | URL | null) {\n pushOrig(data, unused, url)\n onNav()\n }\n this.installedReplaceState = function (data: unknown, unused: string, url?: string | URL | null) {\n replaceOrig(data, unused, url)\n onNav()\n }\n history.pushState = this.installedPushState\n history.replaceState = this.installedReplaceState\n }\n\n private stopNavigationTracking(): void {\n if (this.boundPopstateHandler) {\n window.removeEventListener('popstate', this.boundPopstateHandler)\n this.boundPopstateHandler = null\n }\n // Only restore if nothing (e.g. an SPA router) re-wrapped the functions\n // after us — restoring the stale snapshot would discard their wrapper.\n if (this.originalPushState && history.pushState === this.installedPushState) {\n history.pushState = this.originalPushState\n }\n if (this.originalReplaceState && history.replaceState === this.installedReplaceState) {\n history.replaceState = this.originalReplaceState\n }\n this.originalPushState = null\n this.originalReplaceState = null\n this.installedPushState = null\n this.installedReplaceState = null\n }\n\n private handleNavigation(): void {\n if (!this.active) return\n const from = this.lastUrl\n const to = location.href\n if (from === to) return\n this.lastUrl = to\n this.add({\n type: 'navigation',\n category: 'navigation',\n timestamp: Date.now(),\n message: `${from} → ${to}`,\n data: { from, to },\n })\n }\n\n}\n","import { errorSource } from './error-source'\nimport { isWidgetElement } from './dom-utils'\n\nexport type FrustrationSignal =\n | 'rage_click'\n | 'dead_click'\n | 'rapid_navigation'\n | 'form_failure'\n | 'error_page'\n | 'dead_click_dom'\n\nexport interface FrustrationEvent {\n signal: FrustrationSignal\n target?: string\n detail?: string\n timestamp: number\n}\n\ninterface ClickRecord {\n target: EventTarget | null\n time: number\n}\n\nconst RAGE_CLICK_THRESHOLD = 3\nconst RAGE_CLICK_WINDOW_MS = 1000\nconst RAPID_NAV_THRESHOLD = 3\nconst RAPID_NAV_WINDOW_MS = 5000\nconst FORM_CHECK_DELAY_MS = 500\nconst DEAD_CLICK_DOM_DELAY_MS = 500\nconst ERROR_PAGE_CHECK_DELAY_MS = 300\n\nconst INTERACTIVE_TAGS = new Set([\n 'A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL', 'SUMMARY', 'DETAILS',\n])\n\nconst INTERACTIVE_ROLES = new Set([\n 'button', 'link', 'checkbox', 'radio', 'tab', 'menuitem', 'option',\n 'switch', 'textbox', 'combobox', 'listbox', 'slider', 'spinbutton',\n])\n\nconst ERROR_PAGE_PATTERNS = [\n '404', '500', 'not found', 'page not found',\n 'server error', 'internal server error',\n]\n\nexport class FrustrationDetector {\n private clickHistory: ClickRecord[] = []\n private onFrustration: (event: FrustrationEvent) => void\n private boundClickHandler: (e: MouseEvent) => void\n private unsubscribeErrors: (() => void) | null = null\n private active = false\n private errorCount = 0\n private deadClickCount = 0\n private cooldownUntil = 0\n private static readonly COOLDOWN_MS = 60_000\n\n private navTimestamps: number[] = []\n private boundPopstateHandler: (() => void) | null = null\n private originalPushState: History['pushState'] | null = null\n private originalReplaceState: History['replaceState'] | null = null\n private installedPushState: History['pushState'] | null = null\n private installedReplaceState: History['replaceState'] | null = null\n private boundSubmitHandler: ((e: Event) => void) | null = null\n private boundInvalidHandler: ((e: Event) => void) | null = null\n private errorPageUrls = new Set<string>()\n private domObserver: MutationObserver | null = null\n private pendingDomChecks = 0\n private lastMutationAt = -1\n\n constructor(onFrustration: (event: FrustrationEvent) => void) {\n this.onFrustration = onFrustration\n this.boundClickHandler = (e: MouseEvent) => this.handleClick(e)\n }\n\n start(): void {\n if (this.active) return\n this.active = true\n document.addEventListener('click', this.boundClickHandler, true)\n this.unsubscribeErrors = errorSource.subscribe((_e) => {\n this.errorCount++\n })\n\n this.startNavigationTracking()\n this.startFormTracking()\n this.checkErrorPage()\n }\n\n stop(): void {\n if (!this.active) return\n this.active = false\n document.removeEventListener('click', this.boundClickHandler, true)\n this.unsubscribeErrors?.()\n this.unsubscribeErrors = null\n this.clickHistory = []\n\n this.stopNavigationTracking()\n this.stopFormTracking()\n this.errorPageUrls.clear()\n\n this.disconnectDomObserver()\n }\n\n private startNavigationTracking(): void {\n this.boundPopstateHandler = () => this.handleNavigation()\n window.addEventListener('popstate', this.boundPopstateHandler)\n\n this.originalPushState = history.pushState.bind(history)\n this.originalReplaceState = history.replaceState.bind(history)\n const pushOrig = this.originalPushState\n const replaceOrig = this.originalReplaceState\n const onNav = () => this.handleNavigation()\n\n this.installedPushState = function (data: unknown, unused: string, url?: string | URL | null) {\n pushOrig(data, unused, url)\n onNav()\n }\n this.installedReplaceState = function (data: unknown, unused: string, url?: string | URL | null) {\n replaceOrig(data, unused, url)\n onNav()\n }\n history.pushState = this.installedPushState\n history.replaceState = this.installedReplaceState\n }\n\n private stopNavigationTracking(): void {\n if (this.boundPopstateHandler) {\n window.removeEventListener('popstate', this.boundPopstateHandler)\n this.boundPopstateHandler = null\n }\n // Only restore if nothing (e.g. an SPA router) re-wrapped the functions\n // after us — restoring the stale snapshot would discard their wrapper.\n if (this.originalPushState && history.pushState === this.installedPushState) {\n history.pushState = this.originalPushState\n }\n if (this.originalReplaceState && history.replaceState === this.installedReplaceState) {\n history.replaceState = this.originalReplaceState\n }\n this.originalPushState = null\n this.originalReplaceState = null\n this.installedPushState = null\n this.installedReplaceState = null\n this.navTimestamps = []\n }\n\n private startFormTracking(): void {\n this.boundSubmitHandler = (e: Event) => this.handleFormSubmit(e)\n this.boundInvalidHandler = (e: Event) => this.handleFormInvalid(e)\n document.addEventListener('submit', this.boundSubmitHandler, true)\n document.addEventListener('invalid', this.boundInvalidHandler, true)\n }\n\n private stopFormTracking(): void {\n if (this.boundSubmitHandler) {\n document.removeEventListener('submit', this.boundSubmitHandler, true)\n this.boundSubmitHandler = null\n }\n if (this.boundInvalidHandler) {\n document.removeEventListener('invalid', this.boundInvalidHandler, true)\n this.boundInvalidHandler = null\n }\n }\n\n private handleClick(e: MouseEvent): void {\n const target = e.target as Element | null\n if (!target) return\n\n if (isWidgetElement(target)) return\n\n const now = Date.now()\n this.clickHistory.push({ target, time: now })\n\n const cutoff = now - RAGE_CLICK_WINDOW_MS\n this.clickHistory = this.clickHistory.filter(r => r.time > cutoff)\n\n const sameTargetClicks = this.clickHistory.filter(r => r.target === target)\n if (sameTargetClicks.length >= RAGE_CLICK_THRESHOLD) {\n this.clickHistory = []\n this.emitHighPriority({\n signal: 'rage_click',\n target: describeElement(target),\n timestamp: now,\n })\n return\n }\n\n if (!this.isInteractive(target)) {\n this.deadClickCount++\n if (this.deadClickCount >= 3 && this.errorCount > 0) {\n this.deadClickCount = 0\n this.errorCount = 0\n this.emitIfReady({\n signal: 'dead_click',\n target: describeElement(target),\n timestamp: now,\n })\n }\n }\n\n this.checkDeadClickDom(target, now)\n }\n\n private handleNavigation(): void {\n const now = Date.now()\n this.navTimestamps.push(now)\n const cutoff = now - RAPID_NAV_WINDOW_MS\n this.navTimestamps = this.navTimestamps.filter(t => t > cutoff)\n if (this.navTimestamps.length >= RAPID_NAV_THRESHOLD) {\n this.navTimestamps = []\n this.emitIfReady({\n signal: 'rapid_navigation',\n timestamp: now,\n })\n }\n setTimeout(() => {\n if (this.active) this.checkErrorPage()\n }, ERROR_PAGE_CHECK_DELAY_MS)\n }\n\n private handleFormSubmit(e: Event): void {\n const form = e.target\n if (!(form instanceof HTMLFormElement)) return\n if (isWidgetElement(form)) return\n\n setTimeout(() => {\n if (!this.active) return\n if (form.querySelector('[aria-invalid=\"true\"], .is-invalid')) {\n this.emitIfReady({\n signal: 'form_failure',\n target: describeElement(form),\n timestamp: Date.now(),\n })\n }\n }, FORM_CHECK_DELAY_MS)\n }\n\n private handleFormInvalid(e: Event): void {\n const el = e.target as Element | null\n if (!el) return\n if (isWidgetElement(el)) return\n const form = el.closest('form')\n this.emitIfReady({\n signal: 'form_failure',\n target: form ? describeElement(form) : describeElement(el),\n timestamp: Date.now(),\n })\n }\n\n private checkErrorPage(): void {\n const url = location.href\n if (this.errorPageUrls.has(url)) return\n\n const title = document.title.toLowerCase()\n if (ERROR_PAGE_PATTERNS.some(p => title.includes(p))) {\n this.errorPageUrls.add(url)\n this.emitHighPriority({\n signal: 'error_page',\n detail: document.title,\n timestamp: Date.now(),\n })\n return\n }\n\n const candidates = document.querySelectorAll(\n 'h1, h2, [class*=\"error\"], [class*=\"not-found\"], [id*=\"error\"], [id*=\"not-found\"]'\n )\n for (const el of candidates) {\n const text = el.textContent ?? ''\n if (text.length < 200 && ERROR_PAGE_PATTERNS.some(p => text.toLowerCase().includes(p))) {\n this.errorPageUrls.add(url)\n this.emitHighPriority({\n signal: 'error_page',\n detail: text.trim().slice(0, 60),\n timestamp: Date.now(),\n })\n return\n }\n }\n }\n\n // One shared observer for all in-flight dead-click checks, connected only\n // while at least one check is pending — a full-page observer per click was\n // too heavy on mutation-busy pages.\n private checkDeadClickDom(target: Element, clickTime: number): void {\n if (!this.looksInteractive(target)) return\n\n this.pendingDomChecks++\n this.ensureDomObserver()\n\n setTimeout(() => {\n this.pendingDomChecks--\n const mutated = this.lastMutationAt >= clickTime\n if (this.pendingDomChecks === 0) this.disconnectDomObserver()\n\n if (!mutated && this.active) {\n this.emitIfReady({\n signal: 'dead_click_dom',\n target: describeElement(target),\n timestamp: clickTime,\n })\n }\n }, DEAD_CLICK_DOM_DELAY_MS)\n }\n\n private ensureDomObserver(): void {\n if (this.domObserver) return\n this.domObserver = new MutationObserver(() => {\n this.lastMutationAt = Date.now()\n })\n this.domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n })\n }\n\n private disconnectDomObserver(): void {\n this.domObserver?.disconnect()\n this.domObserver = null\n }\n\n private looksInteractive(el: Element): boolean {\n const style = window.getComputedStyle(el)\n if (style.cursor === 'pointer') return true\n\n if (el.classList) {\n for (const cls of el.classList) {\n const lower = cls.toLowerCase()\n if (lower.includes('btn') || lower.includes('button')) return true\n }\n }\n\n return false\n }\n\n private isInteractive(el: Element): boolean {\n if (INTERACTIVE_TAGS.has(el.tagName)) return true\n\n const role = el.getAttribute('role')\n if (role && INTERACTIVE_ROLES.has(role)) return true\n\n if (el.hasAttribute('onclick') || el.hasAttribute('tabindex')) return true\n if ((el as HTMLElement).contentEditable === 'true') return true\n\n const style = window.getComputedStyle(el)\n if (style.cursor === 'pointer') return true\n\n const parent = el.closest('a, button, [role=\"button\"], [role=\"link\"], label')\n if (parent) return true\n\n return false\n }\n\n\n private emitIfReady(event: FrustrationEvent): void {\n const now = Date.now()\n if (now < this.cooldownUntil) return\n this.cooldownUntil = now + FrustrationDetector.COOLDOWN_MS\n this.onFrustration(event)\n }\n\n private emitHighPriority(event: FrustrationEvent): void {\n this.cooldownUntil = Date.now() + FrustrationDetector.COOLDOWN_MS\n this.onFrustration(event)\n }\n}\n\nfunction describeElement(el: Element): string {\n const tag = el.tagName.toLowerCase()\n const id = el.id ? `#${el.id}` : ''\n const cls = el.className && typeof el.className === 'string'\n ? '.' + el.className.trim().split(/\\s+/).slice(0, 2).join('.')\n : ''\n const text = el.textContent?.trim().slice(0, 30) ?? ''\n return `<${tag}${id}${cls}>${text ? ` \"${text}\"` : ''}`\n}\n","export interface PageContext {\n page_url: string\n user_agent: string\n browser: string\n os: string\n screen_width: number\n screen_height: number\n}\n\nexport function collectPageContext(): PageContext {\n return {\n page_url: window.location.href,\n user_agent: navigator.userAgent,\n browser: detectBrowser(),\n os: detectOS(),\n screen_width: window.screen.width,\n screen_height: window.screen.height,\n }\n}\n\nfunction detectBrowser(): string {\n const ua = navigator.userAgent\n if (/Edg\\//.test(ua)) return `Edge ${ua.match(/Edg\\/(\\S+)/)?.[1] ?? ''}`\n if (/OPR\\//.test(ua)) return `Opera ${ua.match(/OPR\\/(\\S+)/)?.[1] ?? ''}`\n if (/Chrome\\//.test(ua)) return `Chrome ${ua.match(/Chrome\\/(\\S+)/)?.[1] ?? ''}`\n if (/Safari\\//.test(ua) && /Version\\//.test(ua)) return `Safari ${ua.match(/Version\\/(\\S+)/)?.[1] ?? ''}`\n if (/Firefox\\//.test(ua)) return `Firefox ${ua.match(/Firefox\\/(\\S+)/)?.[1] ?? ''}`\n return 'Unknown'\n}\n\nfunction detectOS(): string {\n const ua = navigator.userAgent\n if (/Windows NT 10/.test(ua)) return 'Windows 10/11'\n if (/Windows NT/.test(ua)) return 'Windows'\n if (/Mac OS X 10_15|macOS 1[56789]/.test(ua)) return 'macOS'\n if (/Mac OS X/.test(ua)) return 'macOS'\n if (/Android/.test(ua)) return `Android ${ua.match(/Android (\\d+)/)?.[1] ?? ''}`\n if (/iPhone|iPad|iPod/.test(ua)) return 'iOS'\n if (/Linux/.test(ua)) return 'Linux'\n return 'Unknown'\n}\n","import type {\n FeedbackPayload,\n FeedbackResponse,\n SubmissionSessionResponse,\n ClarifyResponse,\n ClarifyMessage,\n} from '../types'\n\nexport interface ClarifyStreamResult {\n messages: ClarifyMessage[]\n done: boolean\n}\n\nconst DEFAULT_API_URL = 'https://makethisbetter.dev/api/v1'\n\nexport class ApiClient {\n private apiUrl: string\n private projectKey: string\n private retryDelayMs: number\n private userToken?: string\n private userTokenFn?: () => Promise<string>\n\n constructor(projectKey: string, apiUrl?: string, retryDelayMs = 1000, userToken?: string, userTokenFn?: () => Promise<string>) {\n this.projectKey = projectKey\n this.apiUrl = (apiUrl ?? DEFAULT_API_URL).replace(/\\/$/, '')\n this.retryDelayMs = retryDelayMs\n this.userToken = userToken\n this.userTokenFn = userTokenFn\n }\n\n async resolveUserToken(): Promise<string | undefined> {\n if (this.userTokenFn) return this.userTokenFn()\n return this.userToken\n }\n\n private async authHeaders(contentType?: string): Promise<Record<string, string>> {\n const headers: Record<string, string> = { 'X-Project-Key': this.projectKey }\n const token = await this.resolveUserToken()\n if (token) headers['X-User-Token'] = token\n if (contentType) headers['Content-Type'] = contentType\n return headers\n }\n\n private async submissionHeaders(token: string, contentType?: string): Promise<Record<string, string>> {\n const headers = await this.authHeaders(contentType)\n headers['X-Submission-Token'] = token\n return headers\n }\n\n async createSubmissionSession(payload: FeedbackPayload, screenshot: Blob | null): Promise<SubmissionSessionResponse> {\n const submissionToken = generateSubmissionToken()\n const form = new FormData()\n form.append('feedback[description]', payload.description)\n form.append('feedback[page_url]', payload.page_url)\n form.append('feedback[user_agent]', payload.user_agent)\n form.append('feedback[browser]', payload.browser)\n form.append('feedback[os]', payload.os)\n form.append('feedback[screen_width]', String(payload.screen_width))\n form.append('feedback[screen_height]', String(payload.screen_height))\n form.append('feedback[console_errors]', JSON.stringify(payload.console_errors))\n form.append('feedback[annotations]', JSON.stringify(payload.annotations))\n\n if (payload.target_element) {\n form.append('feedback[target_element]', JSON.stringify(payload.target_element))\n }\n if (payload.user_id) form.append('feedback[user_id]', payload.user_id)\n if (payload.reporter_external_id) form.append('feedback[reporter_external_id]', payload.reporter_external_id)\n if (payload.reporter_email) form.append('feedback[reporter_email]', payload.reporter_email)\n if (payload.user_email) form.append('feedback[user_email]', payload.user_email)\n if (payload.user_name) form.append('feedback[user_name]', payload.user_name)\n\n if (payload.breadcrumbs && payload.breadcrumbs.length > 0) {\n form.append('feedback[breadcrumbs]', JSON.stringify(payload.breadcrumbs))\n }\n\n if (payload.recording_events && payload.recording_events.length > 0) {\n const json = JSON.stringify(payload.recording_events)\n const blob = new Blob([json], { type: 'application/json' })\n form.append('feedback[recording]', blob, 'interaction-replay.json')\n form.append('feedback[recording_duration]', String(payload.recording_duration ?? 0))\n }\n\n if (screenshot) {\n const ext = screenshot.type === 'image/jpeg' ? 'jpg' : 'png'\n form.append('feedback[screenshot]', screenshot, `screenshot.${ext}`)\n }\n\n const headers = await this.authHeaders()\n headers['X-Submission-Token'] = submissionToken\n // One key per submission, reused across retries: if the first POST\n // reached the server but the response was lost, the retry must not\n // create a second feedback.\n headers['X-Idempotency-Key'] = generateIdempotencyKey()\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions`, {\n method: 'POST',\n headers,\n body: form,\n })\n const body = await res.json() as {\n submission_session: Omit<SubmissionSessionResponse, 'token'> & { token?: string }\n }\n return { ...body.submission_session, token: submissionToken }\n }\n\n async createIdentityToken(reporterExternalId: string): Promise<{ identity_token: string; board_url: string } | null> {\n const headers = await this.authHeaders('application/json')\n try {\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/identity_tokens`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ reporter_external_id: reporterExternalId }),\n })\n return await res.json()\n } catch {\n return null\n }\n }\n\n async updateReporter(feedbackId: string, email: string, identityToken: string): Promise<boolean> {\n const headers = await this.authHeaders('application/json')\n headers['X-Identity-Token'] = identityToken\n try {\n await this.fetchWithRetry(`${this.apiUrl}/widget/feedbacks/${feedbackId}/reporter`, {\n method: 'PATCH',\n headers,\n body: JSON.stringify({ reporter: { email } }),\n })\n return true\n } catch {\n return false\n }\n }\n\n async startClarification(submissionSessionId: string, token: string, message?: string): Promise<ClarifyResponse> {\n const body: Record<string, string> = {}\n if (message) body.message = message\n const headers = await this.submissionHeaders(token, 'application/json')\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/clarification`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n const response = await res.json() as { clarification: ClarifyResponse }\n return response.clarification\n }\n\n async getClarification(submissionSessionId: string, token: string): Promise<ClarifyResponse> {\n const headers = await this.submissionHeaders(token)\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/clarification`, {\n method: 'GET',\n headers,\n })\n const response = await res.json() as { clarification: ClarifyResponse }\n return response.clarification\n }\n\n // Streams a clarification turn over SSE. Calls onDelta for each token and\n // resolves with the committed result. Throws if the server doesn't stream\n // (e.g. old backend returns JSON) so the caller can fall back to polling.\n async streamClarification(\n submissionSessionId: string,\n token: string,\n onDelta: (text: string) => void,\n ): Promise<ClarifyStreamResult> {\n const headers = await this.submissionHeaders(token, 'application/json')\n headers['Accept'] = 'text/event-stream'\n\n const res = await fetch(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/clarification`, {\n method: 'POST',\n headers,\n body: JSON.stringify({}),\n })\n\n const contentType = res.headers.get('Content-Type') ?? ''\n if (!res.ok || !res.body || !contentType.includes('text/event-stream')) {\n throw new Error('clarify stream unavailable')\n }\n\n return consumeSse(res.body, onDelta)\n }\n\n async finalizeSubmissionSession(submissionSessionId: string, token: string): Promise<FeedbackResponse> {\n const headers = await this.submissionHeaders(token)\n const res = await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}/feedback`, {\n method: 'POST',\n headers,\n })\n const response = await res.json() as { feedback: FeedbackResponse }\n return response.feedback\n }\n\n async abandonSubmissionSession(submissionSessionId: string, token: string): Promise<void> {\n const headers = await this.submissionHeaders(token)\n await this.fetchWithRetry(`${this.apiUrl}/widget/feedback_submission_sessions/${submissionSessionId}`, {\n method: 'DELETE',\n headers,\n })\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, retries = 1): Promise<Response> {\n let res: Response\n try {\n res = await fetch(url, init)\n } catch (err) {\n if (retries > 0) {\n await delay(this.retryDelayMs)\n return this.fetchWithRetry(url, init, retries - 1)\n }\n throw err\n }\n\n if (res.ok) return res\n if (res.status >= 500 && retries > 0) {\n await delay(this.retryDelayMs)\n return this.fetchWithRetry(url, init, retries - 1)\n }\n throw new Error(`HTTP ${res.status}`)\n }\n}\n\nfunction delay(ms: number): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nasync function consumeSse(\n body: ReadableStream<Uint8Array>,\n onDelta: (text: string) => void,\n): Promise<ClarifyStreamResult> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let result: ClarifyStreamResult = { messages: [], done: true }\n\n const flush = (raw: string): void => {\n // Each SSE record is \"event: <name>\\n data: <json>\". Parse event + data.\n const eventLine = raw.split('\\n').find(l => l.startsWith('event:'))\n const dataLine = raw.split('\\n').find(l => l.startsWith('data:'))\n if (!dataLine) return\n const event = eventLine?.slice(6).trim()\n const payload = JSON.parse(dataLine.slice(5).trim())\n if (event === 'delta' && typeof payload.text === 'string') {\n onDelta(payload.text)\n } else if (event === 'done') {\n result = {\n messages: Array.isArray(payload.messages) ? payload.messages : [],\n done: payload.done !== false,\n }\n }\n }\n\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n let sep: number\n while ((sep = buffer.indexOf('\\n\\n')) !== -1) {\n const record = buffer.slice(0, sep)\n buffer = buffer.slice(sep + 2)\n try { flush(record) } catch { /* skip malformed record */ }\n }\n }\n return result\n}\n\nfunction generateIdempotencyKey(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`\n}\n\nfunction generateSubmissionToken(): string {\n if (typeof crypto === 'undefined' || typeof crypto.getRandomValues !== 'function') {\n throw new Error('Secure random generation is unavailable')\n }\n\n const bytes = crypto.getRandomValues(new Uint8Array(32))\n return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('')\n}\n","import type { PageContext } from '../context/collector'\nimport type { Annotation, Breadcrumb, FeedbackPayload, MakeThisBetterConfig } from '../types'\nimport type { RecordingResult } from '../record/session'\n\nexport function buildPayload(\n description: string,\n pageContext: PageContext,\n consoleErrors: string[],\n annotation: Annotation | null,\n user: MakeThisBetterConfig['user'],\n recording?: RecordingResult,\n anonId?: string,\n anonEmail?: string,\n breadcrumbs?: Breadcrumb[],\n): FeedbackPayload {\n return {\n description,\n ...pageContext,\n console_errors: consoleErrors,\n annotations: annotation ? [annotation] : [],\n target_element: annotation?.targetSelector\n ? {\n selector: annotation.targetSelector,\n text: annotation.targetText ?? '',\n name: annotation.targetName ?? '',\n }\n : undefined,\n user_id: user?.id,\n user_email: user?.email,\n user_name: user?.name,\n reporter_external_id: user ? undefined : anonId,\n reporter_email: user ? undefined : anonEmail,\n recording_events: recording?.events,\n recording_duration: recording?.duration,\n breadcrumbs,\n }\n}\n","const STORAGE_KEY = 'mtb_anon_id'\nconst EMAIL_KEY = 'mtb_reporter_email'\nconst BOARD_URL_KEY = 'mtb_board_url'\n\nlet memoryId: string | null = null\nlet memoryEmail: string | null = null\nlet memoryBoardUrl: string | null = null\n\nexport function getAnonId(): string {\n try {\n const stored = window.localStorage.getItem(STORAGE_KEY)\n if (stored?.startsWith('anon_')) return stored\n const id = generateAnonId()\n window.localStorage.setItem(STORAGE_KEY, id)\n return id\n } catch {\n memoryId ??= generateAnonId()\n return memoryId\n }\n}\n\nexport function getStoredReporterEmail(): string | undefined {\n try {\n return window.localStorage.getItem(EMAIL_KEY) ?? undefined\n } catch {\n return memoryEmail ?? undefined\n }\n}\n\nexport function rememberReporterEmail(email: string): void {\n memoryEmail = email\n try {\n window.localStorage.setItem(EMAIL_KEY, email)\n } catch {\n // localStorage unavailable — the in-memory copy covers this session\n }\n}\n\nexport function getCachedBoardUrl(): string | undefined {\n try {\n return window.localStorage.getItem(BOARD_URL_KEY) ?? undefined\n } catch {\n return memoryBoardUrl ?? undefined\n }\n}\n\nexport function cacheBoardUrl(url: string): void {\n memoryBoardUrl = url\n try {\n window.localStorage.setItem(BOARD_URL_KEY, url)\n } catch {\n // localStorage unavailable — the in-memory copy covers this session\n }\n}\n\nfunction generateAnonId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return `anon_${crypto.randomUUID()}`\n }\n const random = `${Date.now().toString(16)}-${Math.random().toString(16).slice(2, 10)}`\n return `anon_${random}`\n}\n","export default {\n tab: 'Feedback',\n toolbar: {\n markup: 'Mark up',\n record: 'Record',\n hint: 'Click any element to annotate · drag to draw',\n hintRecord: 'Recording your screen',\n exit: 'Exit',\n },\n popup: {\n about: 'About',\n placeholder: 'Describe the issue or suggestion...',\n submit: 'Submit',\n cancel: 'Cancel',\n my_feedback: 'My feedback',\n quickOptions: [\n { emoji: '🐛', label: \"Something's broken\" },\n { emoji: '💡', label: 'I have a suggestion' },\n { emoji: '🤔', label: \"I'm confused\" },\n ],\n },\n success: {\n title: 'Sent — thanks!',\n message: 'Your note and captured technical context are on their way to the team. You’ll hear back when it’s resolved.',\n title_no_ai: \"Thanks! We've received your feedback.\",\n message_no_ai: \"The team will take it from here. You'll hear back when it's resolved.\",\n view_feedback: 'View my feedback',\n close: 'Close',\n email_prompt: \"Want updates? Leave your email and we'll let you know when it's resolved.\",\n email_placeholder: 'you@example.com',\n email_submit: 'Notify me',\n email_saved: \"You'll get an email when it's resolved.\",\n email_error: \"Couldn't save your email. Please try again.\",\n },\n error: {\n submit: 'Failed to submit. Please try again.',\n },\n pet: {\n bubble: 'Need help?',\n },\n frustration: {\n prompt: 'Something not working? Tell us.',\n action: 'Annotate',\n dismiss: 'Dismiss',\n },\n annotation: {\n drawing: 'Drawing',\n element: 'element',\n },\n draw: {\n note_placeholder: 'Add a note to your drawing',\n undo: 'Undo',\n redo: 'Redo',\n cancel: 'Cancel',\n submit: 'Submit',\n },\n record: {\n stop: 'Stop',\n timer_label: 'Recording',\n max_reached: 'Maximum recording time reached',\n replay_label: 'screen-recording.json',\n play: 'Play recording',\n close: 'Close',\n preview_unavailable: 'Preview unavailable',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Sharpening your feedback',\n thinking: 'Thinking...',\n placeholder: 'Type your answer — or skip the question',\n send: 'Send',\n skip: 'Skip & send',\n summary: {\n ready: 'Ready to send',\n what_you_said: 'What you said',\n clarified: 'Clarified with AI',\n auto_captured: 'Auto-captured',\n element: 'Element',\n page: 'Page',\n browser: 'Browser',\n captured: 'Captured',\n send_feedback: 'Send feedback',\n screenshot: 'Screenshot',\n recording: 'Interaction replay',\n },\n },\n}\n","export default {\n tab: '反馈',\n toolbar: {\n markup: '标注',\n record: '录屏',\n hint: '点击任意元素进行标注 · 拖拽可自由绘制',\n hintRecord: '正在录制屏幕',\n exit: '退出',\n },\n popup: {\n about: '关于',\n placeholder: '描述问题或建议...',\n submit: '提交',\n cancel: '取消',\n my_feedback: '我的反馈',\n quickOptions: [\n { emoji: '🐛', label: '出问题了' },\n { emoji: '💡', label: '我有一个建议' },\n { emoji: '🤔', label: '我有点困惑' },\n ],\n },\n success: {\n title: '已发送,感谢!',\n message: '您的反馈和采集到的技术上下文正在发送给团队。问题解决后,您会收到通知。',\n title_no_ai: '感谢!我们已收到您的反馈。',\n message_no_ai: '接下来由团队处理。问题解决后,您会收到通知。',\n view_feedback: '查看我的反馈',\n close: '关闭',\n email_prompt: '想了解进展?留下邮箱,问题解决后我们会通知您。',\n email_placeholder: 'you@example.com',\n email_submit: '通知我',\n email_saved: '问题解决后您会收到邮件通知。',\n email_error: '邮箱保存失败,请重试。',\n },\n error: {\n submit: '提交失败,请重试。',\n },\n pet: {\n bubble: '需要帮助吗?',\n },\n frustration: {\n prompt: '遇到问题了?告诉我们。',\n action: '标注',\n dismiss: '关闭',\n },\n annotation: {\n drawing: '绘制',\n element: '元素',\n },\n draw: {\n note_placeholder: '给你的绘制添加说明',\n undo: '撤销',\n redo: '重做',\n cancel: '取消',\n submit: '提交',\n },\n record: {\n stop: '停止',\n timer_label: '录制中',\n max_reached: '已达到最长录制时间',\n replay_label: 'screen-recording.json',\n play: '播放录屏',\n close: '关闭',\n preview_unavailable: '暂无法预览',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: '正在完善你的反馈',\n thinking: '思考中...',\n placeholder: '输入回答,或跳过问题',\n send: '发送',\n skip: '跳过并发送',\n summary: {\n ready: '准备发送',\n what_you_said: '你的描述',\n clarified: 'AI 追问澄清',\n auto_captured: '自动采集',\n element: '元素',\n page: '页面',\n browser: '浏览器',\n captured: '已采集',\n send_feedback: '发送反馈',\n screenshot: '截图',\n recording: '交互回放',\n },\n },\n}\n","export default {\n tab: 'フィードバック',\n toolbar: {\n markup: 'マークアップ',\n record: '録画',\n hint: '要素をクリックして注釈 · ドラッグで描画',\n hintRecord: '画面を録画中',\n exit: '終了',\n },\n popup: {\n about: '概要',\n placeholder: '問題や提案を入力してください...',\n submit: '送信',\n cancel: 'キャンセル',\n my_feedback: '自分のフィードバック',\n quickOptions: [\n { emoji: '🐛', label: '不具合があります' },\n { emoji: '💡', label: '提案があります' },\n { emoji: '🤔', label: 'わかりにくいです' },\n ],\n },\n success: {\n title: '送信しました。ありがとうございます!',\n message: 'ご意見と取得した技術情報をチームに送信しました。解決次第お知らせします。',\n title_no_ai: 'ありがとうございます!フィードバックを受け付けました。',\n message_no_ai: 'チームが対応します。解決次第お知らせします。',\n view_feedback: 'フィードバックを確認',\n close: '閉じる',\n email_prompt: '進捗を知りたい場合は、メールアドレスをご記入ください。解決次第お知らせします。',\n email_placeholder: 'you@example.com',\n email_submit: '通知を受け取る',\n email_saved: '解決次第メールでお知らせします。',\n email_error: 'メールアドレスを保存できませんでした。もう一度お試しください。',\n },\n error: {\n submit: '送信に失敗しました。もう一度お試しください。',\n },\n pet: {\n bubble: 'お困りですか?',\n },\n frustration: {\n prompt: 'うまくいかないことがありますか?お知らせください。',\n action: '注釈',\n dismiss: '閉じる',\n },\n annotation: {\n drawing: '描画',\n element: '要素',\n },\n draw: {\n note_placeholder: '描画にメモを追加',\n undo: '元に戻す',\n redo: 'やり直す',\n cancel: 'キャンセル',\n submit: '送信',\n },\n record: {\n stop: '停止',\n timer_label: '録画中',\n max_reached: '最大記録時間に達しました',\n replay_label: 'screen-recording.json',\n play: '録画を再生',\n close: '閉じる',\n preview_unavailable: 'プレビューは利用できません',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'フィードバックを整えています',\n thinking: '考え中...',\n placeholder: '回答を入力、または質問をスキップ',\n send: '送信',\n skip: 'スキップして送信',\n summary: {\n ready: '送信の準備ができました',\n what_you_said: 'あなたの入力',\n clarified: 'AI で明確化',\n auto_captured: '自動取得',\n element: '要素',\n page: 'ページ',\n browser: 'ブラウザ',\n captured: '取得済み',\n send_feedback: 'フィードバックを送信',\n screenshot: 'スクリーンショット',\n recording: '操作リプレイ',\n },\n },\n}\n","export default {\n tab: '피드백',\n toolbar: {\n markup: '마크업',\n record: '녹화',\n hint: '요소를 클릭하여 주석 · 드래그하여 그리기',\n hintRecord: '화면 녹화 중',\n exit: '나가기',\n },\n popup: {\n about: '정보',\n placeholder: '문제 또는 제안 사항을 설명해 주세요...',\n submit: '제출',\n cancel: '취소',\n my_feedback: '내 피드백',\n quickOptions: [\n { emoji: '🐛', label: '문제가 있어요' },\n { emoji: '💡', label: '제안이 있어요' },\n { emoji: '🤔', label: '헷갈려요' },\n ],\n },\n success: {\n title: '전송되었습니다. 감사합니다!',\n message: '피드백과 수집된 기술 정보가 팀에 전달되었습니다. 해결되면 알려드리겠습니다.',\n title_no_ai: '감사합니다! 피드백을 접수했습니다.',\n message_no_ai: '팀에서 처리합니다. 해결되면 알려드리겠습니다.',\n view_feedback: '내 피드백 보기',\n close: '닫기',\n email_prompt: '진행 상황이 궁금하신가요? 이메일을 남겨주시면 해결 시 알려드립니다.',\n email_placeholder: 'you@example.com',\n email_submit: '알림 받기',\n email_saved: '해결되면 이메일로 알려드립니다.',\n email_error: '이메일을 저장하지 못했습니다. 다시 시도해 주세요.',\n },\n error: {\n submit: '제출에 실패했습니다. 다시 시도해 주세요.',\n },\n pet: {\n bubble: '도움이 필요하신가요?',\n },\n frustration: {\n prompt: '문제가 있으신가요? 알려 주세요.',\n action: '주석',\n dismiss: '닫기',\n },\n annotation: {\n drawing: '그리기',\n element: '요소',\n },\n draw: {\n note_placeholder: '그림에 메모 추가',\n undo: '실행 취소',\n redo: '다시 실행',\n cancel: '취소',\n submit: '보내기',\n },\n record: {\n stop: '중지',\n timer_label: '녹화 중',\n max_reached: '최대 녹화 시간에 도달했습니다',\n replay_label: 'screen-recording.json',\n play: '녹화 재생',\n close: '닫기',\n preview_unavailable: '미리보기를 사용할 수 없습니다',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: '피드백을 다듬는 중',\n thinking: '생각 중...',\n placeholder: '답변을 입력하거나 질문을 건너뛰세요',\n send: '보내기',\n skip: '건너뛰고 보내기',\n summary: {\n ready: '보낼 준비 완료',\n what_you_said: '입력한 내용',\n clarified: 'AI로 명확화',\n auto_captured: '자동 수집',\n element: '요소',\n page: '페이지',\n browser: '브라우저',\n captured: '수집됨',\n send_feedback: '피드백 보내기',\n screenshot: '스크린샷',\n recording: '상호작용 리플레이',\n },\n },\n}\n","export default {\n tab: 'Comentarios',\n toolbar: {\n markup: 'Anotar',\n record: 'Grabar',\n hint: 'Haz clic en cualquier elemento para anotar · arrastra para dibujar',\n hintRecord: 'Grabando pantalla',\n exit: 'Salir',\n },\n popup: {\n about: 'Acerca de',\n placeholder: 'Describe el problema o sugerencia...',\n submit: 'Enviar',\n cancel: 'Cancelar',\n my_feedback: 'Mis comentarios',\n quickOptions: [\n { emoji: '🐛', label: 'Algo no funciona' },\n { emoji: '💡', label: 'Tengo una sugerencia' },\n { emoji: '🤔', label: 'Estoy confundido' },\n ],\n },\n success: {\n title: 'Enviado, ¡gracias!',\n message: 'Tu nota y el contexto técnico capturado se han enviado al equipo. Te avisaremos cuando se resuelva.',\n title_no_ai: '¡Gracias! Hemos recibido tu comentario.',\n message_no_ai: 'El equipo se encargará a partir de aquí. Te avisaremos cuando se resuelva.',\n view_feedback: 'Ver mis comentarios',\n close: 'Cerrar',\n email_prompt: '¿Quieres novedades? Deja tu correo y te avisaremos cuando se resuelva.',\n email_placeholder: 'tu@ejemplo.com',\n email_submit: 'Avisarme',\n email_saved: 'Recibirás un correo cuando se resuelva.',\n email_error: 'No se pudo guardar tu correo. Inténtalo de nuevo.',\n },\n error: {\n submit: 'Error al enviar. Por favor, inténtalo de nuevo.',\n },\n pet: {\n bubble: '¿Necesitas ayuda?',\n },\n frustration: {\n prompt: '¿Algo no funciona? Cuéntanos.',\n action: 'Anotar',\n dismiss: 'Cerrar',\n },\n annotation: {\n drawing: 'Dibujo',\n element: 'elemento',\n },\n draw: {\n note_placeholder: 'Añade una nota a tu dibujo',\n undo: 'Deshacer',\n redo: 'Rehacer',\n cancel: 'Cancelar',\n submit: 'Enviar',\n },\n record: {\n stop: 'Detener',\n timer_label: 'Grabando',\n max_reached: 'Tiempo máximo de grabación alcanzado',\n replay_label: 'screen-recording.json',\n play: 'Reproducir grabación',\n close: 'Cerrar',\n preview_unavailable: 'Vista previa no disponible',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Afinando tus comentarios',\n thinking: 'Pensando...',\n placeholder: 'Escribe tu respuesta — u omite la pregunta',\n send: 'Enviar',\n skip: 'Omitir y enviar',\n summary: {\n ready: 'Listo para enviar',\n what_you_said: 'Lo que dijiste',\n clarified: 'Aclarado con IA',\n auto_captured: 'Capturado automáticamente',\n element: 'Elemento',\n page: 'Página',\n browser: 'Navegador',\n captured: 'Capturado',\n send_feedback: 'Enviar comentario',\n screenshot: 'Captura de pantalla',\n recording: 'Repetición de interacción',\n },\n },\n}\n","export default {\n tab: 'Avis',\n toolbar: {\n markup: 'Annoter',\n record: 'Enregistrer',\n hint: \"Cliquez sur un élément pour l'annoter · glissez pour dessiner\",\n hintRecord: \"Enregistrement de l'écran\",\n exit: 'Quitter',\n },\n popup: {\n about: 'À propos',\n placeholder: 'Décrivez le problème ou votre suggestion...',\n submit: 'Envoyer',\n cancel: 'Annuler',\n my_feedback: 'Mes avis',\n quickOptions: [\n { emoji: '🐛', label: 'Quelque chose ne fonctionne pas' },\n { emoji: '💡', label: \"J'ai une suggestion\" },\n { emoji: '🤔', label: 'Je suis perplexe' },\n ],\n },\n success: {\n title: 'Envoyé, merci !',\n message: 'Votre message et le contexte technique collecté ont été transmis à l’équipe. Vous serez informé(e) dès que ce sera résolu.',\n title_no_ai: 'Merci ! Nous avons bien reçu votre avis.',\n message_no_ai: \"L’équipe prend le relais. Vous serez informé(e) dès que ce sera résolu.\",\n view_feedback: 'Voir mes avis',\n close: 'Fermer',\n email_prompt: \"Envie de suivre l'avancement ? Laissez votre e-mail et nous vous préviendrons une fois résolu.\",\n email_placeholder: 'vous@exemple.com',\n email_submit: 'Me prévenir',\n email_saved: 'Vous recevrez un e-mail une fois résolu.',\n email_error: \"Impossible d'enregistrer votre e-mail. Veuillez réessayer.\",\n },\n error: {\n submit: \"Échec de l'envoi. Veuillez réessayer.\",\n },\n pet: {\n bubble: \"Besoin d'aide ?\",\n },\n frustration: {\n prompt: 'Un problème ? Dites-le-nous.',\n action: 'Annoter',\n dismiss: 'Fermer',\n },\n annotation: {\n drawing: 'Dessin',\n element: 'élément',\n },\n draw: {\n note_placeholder: 'Ajoutez une note à votre dessin',\n undo: 'Annuler',\n redo: 'Rétablir',\n cancel: 'Annuler',\n submit: 'Envoyer',\n },\n record: {\n stop: 'Arrêter',\n timer_label: 'Enregistrement',\n max_reached: \"Durée maximale d'enregistrement atteinte\",\n replay_label: 'screen-recording.json',\n play: \"Lire l'enregistrement\",\n close: 'Fermer',\n preview_unavailable: 'Aperçu indisponible',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Affinement de votre retour',\n thinking: 'Réflexion...',\n placeholder: 'Saisissez votre réponse — ou ignorez la question',\n send: 'Envoyer',\n skip: 'Ignorer et envoyer',\n summary: {\n ready: 'Prêt à envoyer',\n what_you_said: 'Ce que vous avez dit',\n clarified: \"Clarifié avec l'IA\",\n auto_captured: 'Capturé automatiquement',\n element: 'Élément',\n page: 'Page',\n browser: 'Navigateur',\n captured: 'Capturé',\n send_feedback: 'Envoyer le retour',\n screenshot: \"Capture d'écran\",\n recording: 'Relecture des interactions',\n },\n },\n}\n","export default {\n tab: 'Feedback',\n toolbar: {\n markup: 'Markieren',\n record: 'Aufnehmen',\n hint: 'Klicken Sie auf ein Element zum Kommentieren · ziehen Sie zum Zeichnen',\n hintRecord: 'Bildschirm wird aufgenommen',\n exit: 'Beenden',\n },\n popup: {\n about: 'Info',\n placeholder: 'Beschreiben Sie das Problem oder Ihren Vorschlag...',\n submit: 'Absenden',\n cancel: 'Abbrechen',\n my_feedback: 'Mein Feedback',\n quickOptions: [\n { emoji: '🐛', label: 'Etwas funktioniert nicht' },\n { emoji: '💡', label: 'Ich habe einen Vorschlag' },\n { emoji: '🤔', label: 'Ich bin verwirrt' },\n ],\n },\n success: {\n title: 'Gesendet, vielen Dank!',\n message: 'Ihre Nachricht und der erfasste technische Kontext wurden an das Team gesendet. Sie werden benachrichtigt, sobald das Problem gelöst ist.',\n title_no_ai: 'Vielen Dank! Wir haben Ihr Feedback erhalten.',\n message_no_ai: 'Das Team übernimmt ab hier. Sie werden benachrichtigt, sobald das Problem gelöst ist.',\n view_feedback: 'Mein Feedback ansehen',\n close: 'Schließen',\n email_prompt: 'Updates gewünscht? Hinterlassen Sie Ihre E-Mail und wir melden uns, sobald es gelöst ist.',\n email_placeholder: 'sie@beispiel.de',\n email_submit: 'Benachrichtigen',\n email_saved: 'Sie erhalten eine E-Mail, sobald es gelöst ist.',\n email_error: 'E-Mail konnte nicht gespeichert werden. Bitte versuchen Sie es erneut.',\n },\n error: {\n submit: 'Senden fehlgeschlagen. Bitte versuchen Sie es erneut.',\n },\n pet: {\n bubble: 'Brauchen Sie Hilfe?',\n },\n frustration: {\n prompt: 'Etwas funktioniert nicht? Sagen Sie es uns.',\n action: 'Kommentieren',\n dismiss: 'Schließen',\n },\n annotation: {\n drawing: 'Zeichnung',\n element: 'Element',\n },\n draw: {\n note_placeholder: 'Fügen Sie Ihrer Zeichnung eine Notiz hinzu',\n undo: 'Rückgängig',\n redo: 'Wiederholen',\n cancel: 'Abbrechen',\n submit: 'Absenden',\n },\n record: {\n stop: 'Stopp',\n timer_label: 'Aufnahme',\n max_reached: 'Maximale Aufnahmedauer erreicht',\n replay_label: 'screen-recording.json',\n play: 'Aufnahme abspielen',\n close: 'Schließen',\n preview_unavailable: 'Vorschau nicht verfügbar',\n },\n clarify: {\n title: 'Make This Better AI',\n subtitle: 'Wir schärfen dein Feedback',\n thinking: 'Einen Moment...',\n placeholder: 'Antwort eingeben — oder Frage überspringen',\n send: 'Senden',\n skip: 'Überspringen & senden',\n summary: {\n ready: 'Bereit zum Senden',\n what_you_said: 'Was Sie gesagt haben',\n clarified: 'Mit KI geklärt',\n auto_captured: 'Automatisch erfasst',\n element: 'Element',\n page: 'Seite',\n browser: 'Browser',\n captured: 'Erfasst',\n send_feedback: 'Feedback senden',\n screenshot: 'Screenshot',\n recording: 'Interaktions-Replay',\n },\n },\n}\n","import en from './en'\nimport zhCN from './zh-CN'\nimport ja from './ja'\nimport ko from './ko'\nimport es from './es'\nimport fr from './fr'\nimport de from './de'\n\nexport type I18nMessages = typeof en\n\nconst locales: Record<string, I18nMessages> = {\n en,\n 'zh-CN': zhCN,\n ja,\n ko,\n es,\n fr,\n de,\n}\n\nexport function getMessages(locale: string): I18nMessages {\n if (locales[locale]) return locales[locale]\n const lang = locale.split('-')[0]\n if (locales[lang]) return locales[lang]\n return locales['en']\n}\n","import type { ShadowContainer } from '../widget/shadow'\n\ntype RRWebEvent = Record<string, unknown>\ntype StopFn = () => void\n\ninterface RRWebRecordFn {\n (options: { emit: (event: RRWebEvent) => void }): StopFn\n addCustomEvent: (tag: string, payload: Record<string, unknown>) => void\n}\n\nexport interface RecordingResult {\n events: RRWebEvent[]\n duration: number\n}\n\nconst MAX_DURATION_S = 60\n// Pinned version + SRI: this script executes on customers' pages, so a\n// floating tag or unverified content would be a supply-chain hole. Bumping\n// the version requires recomputing the hash from the exact CDN file:\n// curl -sL <url> | openssl dgst -sha384 -binary | openssl base64 -A\n// Must stay on @rrweb/record's static /umd/ build: the `rrweb` package ships\n// no UMD in 2.x (its dist files are ESM and throw \"Unexpected token 'export'\"\n// in a classic script tag), and jsDelivr's auto-minified files are unsafe for\n// SRI because their hash changes when jsDelivr upgrades its minifier.\nconst RRWEB_CDN = 'https://cdn.jsdelivr.net/npm/@rrweb/record@2.1.0/umd/record.min.js'\nconst RRWEB_SRI = 'sha384-MrD66HBNSykaP2N95+6hQCFlF5oH2tvL3TD/zyvHNkP/sAFWZx98DX9MEDy8MdVT'\n\nlet rrwebLoaded: Promise<RRWebRecordFn> | null = null\n\nfunction loadRrweb(): Promise<RRWebRecordFn> {\n if (rrwebLoaded) return rrwebLoaded\n rrwebLoaded = loadViaImport().catch(() => loadViaCdn())\n return rrwebLoaded\n}\n\nasync function loadViaImport(): Promise<RRWebRecordFn> {\n const mod = await import('@rrweb/record')\n return mod.record as unknown as RRWebRecordFn\n}\n\ninterface RRWebGlobals {\n rrwebRecord?: { record: RRWebRecordFn }\n rrweb?: { record: RRWebRecordFn }\n}\n\nfunction findGlobalRecord(): RRWebRecordFn | undefined {\n const win = globalThis as unknown as Window & RRWebGlobals\n return win.rrwebRecord?.record ?? win.rrweb?.record\n}\n\nfunction loadViaCdn(): Promise<RRWebRecordFn> {\n return new Promise((resolve, reject) => {\n const existing = findGlobalRecord()\n if (existing) { resolve(existing); return }\n const script = document.createElement('script')\n script.src = RRWEB_CDN\n script.integrity = RRWEB_SRI\n script.crossOrigin = 'anonymous'\n script.onload = () => {\n const record = findGlobalRecord()\n if (record) resolve(record)\n else reject(new Error('rrweb record global not found after script load'))\n }\n script.onerror = () => reject(new Error('Failed to load rrweb from CDN'))\n document.head.appendChild(script)\n })\n}\n\nexport class RecordSession {\n private events: RRWebEvent[] = []\n private stopFn: StopFn | null = null\n private startedAt = 0\n private timer: ReturnType<typeof setTimeout> | null = null\n private clickHandler: ((e: MouseEvent) => void) | null = null\n private shadow: ShadowContainer\n private onMaxReached?: () => void\n private stopped = false\n\n constructor(shadow: ShadowContainer, onMaxReached?: () => void) {\n this.shadow = shadow\n this.onMaxReached = onMaxReached\n }\n\n async start(): Promise<void> {\n const record = await loadRrweb()\n\n this.startedAt = Date.now()\n this.stopped = false\n\n this.stopFn = record({\n emit: (event: RRWebEvent) => {\n if (!this.stopped) this.events.push(event)\n },\n })\n\n this.clickHandler = (e: MouseEvent) => {\n this.showClickRipple(e.clientX, e.clientY)\n record.addCustomEvent?.('mtb-click', {\n x: e.clientX,\n y: e.clientY,\n target: e.target instanceof HTMLElement ? e.target.tagName : '',\n })\n }\n document.addEventListener('click', this.clickHandler, true)\n\n this.timer = setTimeout(() => {\n this.onMaxReached?.()\n }, MAX_DURATION_S * 1000)\n }\n\n stop(): RecordingResult {\n this.stopped = true\n this.stopFn?.()\n this.stopFn = null\n this.cleanupTimer()\n this.cleanupClickHandler()\n\n return {\n events: this.events,\n duration: this.getDuration(),\n }\n }\n\n getDuration(): number {\n if (this.startedAt === 0) return 0\n return Math.max(1, Math.round((Date.now() - this.startedAt) / 1000))\n }\n\n destroy(): void {\n this.stopped = true\n this.stopFn?.()\n this.stopFn = null\n this.cleanupTimer()\n this.cleanupClickHandler()\n this.events = []\n this.startedAt = 0\n }\n\n private cleanupTimer(): void {\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n }\n\n private cleanupClickHandler(): void {\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler, true)\n this.clickHandler = null\n }\n }\n\n private showClickRipple(x: number, y: number): void {\n const ripple = this.shadow.el<HTMLDivElement>('div', 'mtb-click-ripple')\n ripple.style.left = `${x}px`\n ripple.style.top = `${y}px`\n this.shadow.append(ripple)\n ripple.addEventListener('animationend', () => ripple.remove())\n }\n}\n","import type { ShadowContainer } from '../widget/shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport class RecordControlBar {\n private el: HTMLDivElement\n private timerEl!: HTMLSpanElement\n private intervalId: ReturnType<typeof setInterval> | null = null\n private getDuration: () => number\n\n constructor(\n shadow: ShadowContainer,\n messages: I18nMessages,\n getDuration: () => number,\n onStop: () => void,\n ) {\n this.getDuration = getDuration\n\n this.el = shadow.el<HTMLDivElement>('div', 'mtb-record-bar')\n this.el.innerHTML = `\n <span class=\"mtb-record-dot\"></span>\n <span class=\"mtb-record-timer\">00:00</span>\n <button class=\"mtb-record-stop\" type=\"button\">${messages.record.stop}</button>\n `\n shadow.append(this.el)\n\n this.timerEl = this.el.querySelector('.mtb-record-timer')!\n this.el.querySelector('.mtb-record-stop')!.addEventListener('click', onStop)\n\n this.intervalId = setInterval(() => this.updateTimer(), 1000)\n }\n\n private updateTimer(): void {\n const secs = this.getDuration()\n const mm = String(Math.floor(secs / 60)).padStart(2, '0')\n const ss = String(secs % 60).padStart(2, '0')\n this.timerEl.textContent = `${mm}:${ss}`\n }\n\n destroy(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId)\n this.intervalId = null\n }\n this.el.remove()\n }\n}\n","import { RecordSession } from '../record/session'\nimport type { RecordingResult } from '../record/session'\nimport { RecordControlBar } from '../record/control-bar'\nimport type { ShadowContainer } from './shadow'\nimport type { I18nMessages } from '../i18n'\n\nexport type { RecordingResult }\n\nexport class RecordingManager {\n private session: RecordSession | null = null\n private bar: RecordControlBar | null = null\n private result: RecordingResult | null = null\n\n async start(\n shadow: ShadowContainer,\n messages: I18nMessages,\n onStop: () => void,\n ): Promise<void> {\n this.session = new RecordSession(shadow, onStop)\n this.bar = new RecordControlBar(\n shadow,\n messages,\n () => this.session?.getDuration() ?? 0,\n onStop,\n )\n await this.session.start()\n }\n\n stop(): RecordingResult | null {\n if (!this.session) return null\n this.result = this.session.stop()\n this.teardownUI()\n return this.result\n }\n\n getRecording(): RecordingResult | null {\n return this.result\n }\n\n destroy(): void {\n this.teardownUI()\n this.result = null\n }\n\n private teardownUI(): void {\n this.session?.destroy()\n this.session = null\n this.bar?.destroy()\n this.bar = null\n }\n}\n","import { ShadowContainer } from './shadow'\nimport { FeedbackTab } from './tab'\nimport { FrustrationPromptCard } from './frustration-prompt'\nimport { DimOverlay } from './dim-overlay'\nimport { AnnotationToolbar } from '../annotate/toolbar'\nimport type { ToolbarMode } from '../annotate/toolbar'\nimport { AnnotationSession } from '../annotate/session'\nimport { DrawNoteBar } from '../annotate/draw-note-bar'\nimport { CommentPopup } from '../popup/comment'\nimport { ClarifyCard } from '../popup/clarify'\nimport type { ClarifySummaryContext } from '../popup/clarify'\nimport { SuccessCard } from '../popup/success'\nimport type { SuccessCardOptions } from '../popup/success'\nimport { captureScreenshot } from '../screenshot/capture'\nimport { ConsoleErrorCollector } from '../context/console'\nimport { BreadcrumbCollector } from '../context/breadcrumbs'\nimport { FrustrationDetector } from '../context/frustration'\nimport { collectPageContext } from '../context/collector'\nimport type { PageContext } from '../context/collector'\nimport { ApiClient } from '../api/client'\nimport { buildPayload } from './payload'\nimport { cacheBoardUrl, getAnonId, getCachedBoardUrl, getStoredReporterEmail, rememberReporterEmail } from './anon-id'\nimport { getMessages } from '../i18n'\nimport { RecordingManager } from './recording-manager'\nimport type { MakeThisBetterConfig, Annotation, SubmissionSessionResponse } from '../types'\n\ntype Mode = 'idle' | 'annotating' | 'recording' | 'drawing' | 'popup' | 'clarifying'\ntype Via = 'pin' | 'draw' | 'record'\n\ninterface SubmittingUi {\n setLoading: (loading: boolean) => void\n setError: (message: string) => void\n}\n\nexport class WidgetController {\n private config: MakeThisBetterConfig\n private shadow!: ShadowContainer\n private tab: FeedbackTab | null = null\n private toolbar: AnnotationToolbar | null = null\n private session: AnnotationSession | null = null\n private drawBar: DrawNoteBar | null = null\n private dim: DimOverlay | null = null\n private popup: CommentPopup | null = null\n private clarify: ClarifyCard | null = null\n private success: SuccessCard | null = null\n private frustrationPrompt: FrustrationPromptCard | null = null\n private apiClient: ApiClient\n private consoleCollector: ConsoleErrorCollector\n private breadcrumbCollector: BreadcrumbCollector\n private frustrationDetector: FrustrationDetector | null = null\n private messages: ReturnType<typeof getMessages>\n private mode: Mode = 'idle'\n private via: Via = 'pin'\n private currentAnnotation: Annotation | null = null\n private submittingUi: SubmittingUi | null = null\n private lastPopupPos: { x: number; y: number } | null = null\n private recordingManager: RecordingManager | null = null\n private activeSubmission: SubmissionSessionResponse | null = null\n private submissionAttempt = 0\n private lastHandoff: { feedbackId?: string; boardUrl?: string; identityToken?: string } = {}\n\n constructor(config: MakeThisBetterConfig) {\n this.config = config\n this.messages = getMessages(config.locale ?? 'en')\n this.apiClient = new ApiClient(config.projectKey, config.apiUrl, undefined, config.userToken, config.userTokenFn)\n this.consoleCollector = new ConsoleErrorCollector()\n this.consoleCollector.start()\n this.breadcrumbCollector = new BreadcrumbCollector()\n this.breadcrumbCollector.start()\n this.buildUI()\n\n if (config.frustrationDetection !== false) {\n this.frustrationDetector = new FrustrationDetector(() => this.handleFrustration())\n this.frustrationDetector.start()\n }\n\n document.addEventListener('keydown', this.handleKeydown, true)\n }\n\n // Escape only acts while the widget is in an active state; idle/clarifying\n // fall through untouched so the host page's own Escape handling still works.\n private handleKeydown = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape') return\n\n switch (this.mode) {\n case 'annotating':\n case 'popup':\n event.preventDefault()\n event.stopPropagation()\n this.exitAll()\n break\n case 'drawing':\n event.preventDefault()\n event.stopPropagation()\n this.cancelDraw()\n break\n case 'recording':\n event.preventDefault()\n event.stopPropagation()\n this.handleRecordStop()\n break\n default:\n break\n }\n }\n\n private buildUI(): void {\n this.shadow = new ShadowContainer(this.config.theme ?? 'auto')\n\n this.tab = new FeedbackTab(\n this.shadow,\n this.messages,\n this.config.position ?? 'right',\n () => this.handleTabClick(),\n this.config.tabText,\n )\n }\n\n private handleTabClick(): void {\n if (this.mode === 'idle') {\n this.dismissFrustrationPrompt()\n this.enterAnnotationMode()\n } else {\n this.exitAll()\n }\n }\n\n private handleFrustration(): void {\n if (this.mode !== 'idle' || this.frustrationPrompt) return\n\n this.frustrationPrompt = new FrustrationPromptCard(this.shadow, this.messages, {\n onTell: () => {\n this.dismissFrustrationPrompt()\n this.enterAnnotationMode()\n },\n onDismiss: () => this.dismissFrustrationPrompt(),\n })\n }\n\n private dismissFrustrationPrompt(): void {\n this.frustrationPrompt?.destroy()\n this.frustrationPrompt = null\n }\n\n private enterAnnotationMode(): void {\n this.mode = 'annotating'\n this.tab?.setActive(true)\n\n this.toolbar = new AnnotationToolbar(\n this.shadow,\n this.messages,\n () => this.exitAll(),\n (mode: ToolbarMode) => this.handleToolbarModeChange(mode),\n )\n this.session = this.createSession()\n }\n\n private createSession(): AnnotationSession {\n return new AnnotationSession(this.shadow, this.messages, {\n onPin: (annotation, targetName) => {\n this.currentAnnotation = annotation\n this.via = 'pin'\n this.showPopup(annotation.x, annotation.y, targetName)\n },\n onDrawStroke: () => this.handleDrawStroke(),\n })\n }\n\n private handleToolbarModeChange(mode: ToolbarMode): void {\n if (this.mode === 'clarifying') {\n this.toolbar?.setMode(this.via === 'record' ? 'record' : 'markup')\n return\n }\n\n if (mode === 'record') {\n if (this.mode === 'recording') return\n\n this.mode = 'recording'\n this.currentAnnotation = null\n this.teardownDraw()\n this.session?.destroy()\n this.session = null\n this.recordingManager = new RecordingManager()\n this.recordingManager.start(this.shadow, this.messages, this.handleRecordStop).catch((error) => {\n // rrweb failed to load (network / SRI mismatch) — fall back to markup\n console.warn('[MakeThisBetter] Interaction replay unavailable, falling back to markup:', error)\n if (this.mode !== 'recording') return\n this.toolbar?.setMode('markup')\n this.handleToolbarModeChange('markup')\n })\n } else {\n this.recordingManager?.destroy()\n this.recordingManager = null\n this.teardownDraw()\n if (!this.session) this.session = this.createSession()\n this.mode = 'annotating'\n }\n }\n\n private handleRecordStop = (): void => {\n if (!this.recordingManager) return\n this.recordingManager.stop()\n this.via = 'record'\n this.showPopup(window.innerWidth / 2, window.innerHeight / 2, this.messages.record.timer_label)\n }\n\n private handleDrawStroke(): void {\n if (this.mode !== 'drawing') {\n this.mode = 'drawing'\n this.drawBar = new DrawNoteBar(this.shadow, {\n messages: this.messages,\n onUndo: () => this.handleDrawUndoRedo('undo'),\n onRedo: () => this.handleDrawUndoRedo('redo'),\n onCancel: () => this.cancelDraw(),\n onSubmit: (note) => this.handleDrawSubmit(note),\n })\n }\n this.refreshDrawBar()\n }\n\n private handleDrawUndoRedo(action: 'undo' | 'redo'): void {\n if (action === 'undo') this.session?.undoDraw()\n else this.session?.redoDraw()\n this.refreshDrawBar()\n }\n\n private refreshDrawBar(): void {\n if (!this.session) return\n this.drawBar?.setUndoRedo(this.session.canUndoDraw(), this.session.canRedoDraw())\n }\n\n private cancelDraw(): void {\n this.session?.clearDraw()\n this.teardownDraw()\n this.mode = 'annotating'\n }\n\n private teardownDraw(): void {\n this.drawBar?.destroy()\n this.drawBar = null\n }\n\n private handleDrawSubmit(note: string): void {\n const annotation = this.session?.getDrawAnnotation()\n if (!annotation) {\n this.cancelDraw()\n return\n }\n this.currentAnnotation = annotation\n this.via = 'draw'\n this.session?.dismissInteraction()\n this.submittingUi = this.drawBar\n void this.handleSubmit(note || this.messages.annotation.drawing)\n }\n\n private showPopup(x: number, y: number, targetName: string): void {\n this.mode = 'popup'\n this.lastPopupPos = { x, y }\n this.teardownDraw()\n this.session?.dismissInteraction()\n this.popup?.destroy()\n this.popup = null\n this.dim?.destroy()\n this.dim = null\n this.dim = new DimOverlay(this.shadow, () => this.exitAll())\n\n this.popup = new CommentPopup(this.shadow, {\n targetName,\n x,\n y,\n messages: this.messages,\n onSubmit: (description) => this.handleSubmit(description),\n onClose: () => this.exitAll(),\n onMyFeedback: this.buildMyFeedbackHandler(),\n })\n this.submittingUi = this.popup\n }\n\n private buildMyFeedbackHandler(): (() => void) | undefined {\n if (this.config.user) return undefined\n if (!getCachedBoardUrl()) return undefined\n\n return async () => {\n const exchange = await this.apiClient.createIdentityToken(getAnonId())\n if (!exchange?.identity_token || !exchange.board_url) return\n cacheBoardUrl(exchange.board_url)\n window.open(`${exchange.board_url}?identity=${encodeURIComponent(exchange.identity_token)}`, '_blank')\n }\n }\n\n private async handleSubmit(description: string): Promise<void> {\n const ui = this.submittingUi\n if (!ui) return\n const submissionAttempt = ++this.submissionAttempt\n ui.setLoading(true)\n await waitForPaint()\n const annotation = this.currentAnnotation\n const recording = this.recordingManager?.getRecording() ?? undefined\n\n const [screenshot, pageContext] = await Promise.all([\n captureScreenshot(annotation ? [annotation] : []),\n Promise.resolve(collectPageContext()),\n ])\n\n const payload = buildPayload(\n description,\n pageContext,\n this.consoleCollector.getErrors(),\n annotation,\n this.config.user,\n recording,\n this.config.user ? undefined : getAnonId(),\n this.config.user ? undefined : getStoredReporterEmail(),\n this.breadcrumbCollector.getBreadcrumbs(),\n )\n\n try {\n const submission = await this.apiClient.createSubmissionSession(payload, screenshot)\n if (submissionAttempt !== this.submissionAttempt) {\n await this.apiClient.abandonSubmissionSession(submission.id, submission.token).catch(() => {})\n return\n }\n this.activeSubmission = submission\n const summary = this.buildSummaryContext(description, pageContext, annotation)\n this.teardownDraw()\n this.popup?.destroy()\n this.popup = null\n this.dim?.destroy()\n this.dim = null\n this.session?.destroy()\n this.session = null\n this.recordingManager?.destroy()\n this.recordingManager = null\n this.submittingUi = null\n this.showClarify(submission, this.lastPopupPos, summary)\n } catch {\n if (submissionAttempt !== this.submissionAttempt) return\n ui.setLoading(false)\n ui.setError(this.messages.error.submit)\n }\n }\n\n private buildSummaryContext(\n description: string,\n pageContext: PageContext,\n annotation: Annotation | null,\n ): ClarifySummaryContext {\n const s = this.messages.clarify.summary\n return {\n originalDescription: description,\n element: annotation?.targetName ?? this.messages.annotation.element,\n page: pageContext.page_url,\n browser: `${pageContext.browser} · ${pageContext.os}`,\n captured: this.via === 'record' ? s.recording : s.screenshot,\n }\n }\n\n private showClarify(\n submission: SubmissionSessionResponse,\n pos: { x: number; y: number } | null,\n summary: ClarifySummaryContext,\n ): void {\n // 'clarifying' keeps the tab and frustration prompt from starting a second\n // feedback while the current one is still being clarified.\n this.mode = 'clarifying'\n this.tab?.setActive(true)\n this.clarify = new ClarifyCard(this.shadow, {\n submissionSessionId: submission.id,\n submissionToken: submission.token,\n apiClient: this.apiClient,\n messages: this.messages,\n summary,\n x: pos?.x,\n y: pos?.y,\n onFinalize: () => this.finalizeSubmission(),\n })\n }\n\n private async finalizeSubmission(): Promise<void> {\n const submission = this.activeSubmission\n if (!submission) throw new Error('No active submission session')\n const submissionAttempt = this.submissionAttempt\n\n const feedback = await this.apiClient.finalizeSubmissionSession(submission.id, submission.token)\n if (submissionAttempt !== this.submissionAttempt || this.activeSubmission !== submission) return\n\n this.activeSubmission = null\n this.lastHandoff = {\n feedbackId: feedback.id,\n boardUrl: feedback.board_url,\n identityToken: feedback.identity_token,\n }\n if (feedback.board_url) cacheBoardUrl(feedback.board_url)\n this.clarify?.destroy()\n this.clarify = null\n this.toolbar?.destroy()\n this.toolbar = null\n this.showSuccess({ skipFollowup: submission.ai_clarify_available === false })\n }\n\n private showSuccess(options?: SuccessCardOptions): void {\n this.mode = 'idle'\n this.tab?.setActive(false)\n this.success = new SuccessCard(this.shadow, this.messages, () => {\n this.success?.destroy()\n this.success = null\n }, this.buildViewFeedbackHandler(), { ...options, emailCapture: this.buildEmailCapture() })\n }\n\n private buildEmailCapture(): { onSubmit: (email: string) => Promise<boolean> } | undefined {\n const { feedbackId, identityToken } = this.lastHandoff\n if (!feedbackId || !identityToken) return undefined\n if (getStoredReporterEmail()) return undefined\n\n return {\n onSubmit: async (email: string) => {\n const saved = await this.apiClient.updateReporter(feedbackId, email, identityToken)\n if (saved) rememberReporterEmail(email)\n return saved\n },\n }\n }\n\n private buildViewFeedbackHandler(): (() => void) | undefined {\n const { boardUrl, identityToken } = this.lastHandoff\n if (!boardUrl) return undefined\n\n if (identityToken) {\n return () => {\n window.open(`${boardUrl}?identity=${encodeURIComponent(identityToken)}`, '_blank')\n }\n }\n\n if (this.config.userToken || this.config.userTokenFn) {\n return async () => {\n const token = await this.apiClient.resolveUserToken()\n if (token) window.open(`${boardUrl}?identity=${encodeURIComponent(token)}`, '_blank')\n }\n }\n\n return undefined\n }\n\n private exitAll(): void {\n this.submissionAttempt += 1\n const submission = this.activeSubmission\n this.activeSubmission = null\n if (submission) {\n void this.apiClient.abandonSubmissionSession(submission.id, submission.token).catch(() => {})\n }\n this.mode = 'idle'\n this.via = 'pin'\n this.tab?.setActive(false)\n this.teardownDraw()\n this.toolbar?.destroy()\n this.toolbar = null\n this.session?.destroy()\n this.session = null\n this.dim?.destroy()\n this.dim = null\n this.popup?.destroy()\n this.popup = null\n this.clarify?.destroy()\n this.clarify = null\n this.currentAnnotation = null\n this.submittingUi = null\n this.recordingManager?.destroy()\n this.recordingManager = null\n }\n\n destroy(): void {\n document.removeEventListener('keydown', this.handleKeydown, true)\n this.exitAll()\n this.consoleCollector.stop()\n this.breadcrumbCollector.stop()\n this.frustrationDetector?.stop()\n this.dismissFrustrationPrompt()\n this.clarify?.destroy()\n this.success?.destroy()\n this.tab?.destroy()\n this.recordingManager?.destroy()\n this.shadow.destroy()\n }\n}\n\nfunction waitForPaint(): Promise<void> {\n return new Promise<void>((r) => requestAnimationFrame(() => setTimeout(r, 0)))\n}\n","import { WidgetController } from './widget/controller'\nimport type { MakeThisBetterConfig } from './types'\n\nlet instance: WidgetController | null = null\n\nconst MakeThisBetter = {\n init(config: MakeThisBetterConfig): void {\n if (instance) {\n instance.destroy()\n instance = null\n }\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n instance = new WidgetController(config)\n })\n } else {\n instance = new WidgetController(config)\n }\n },\n\n destroy(): void {\n instance?.destroy()\n instance = null\n },\n}\n\nexport { MakeThisBetter }\nexport type { MakeThisBetterConfig }\n\nif (typeof window !== 'undefined') {\n (window as Window & { MakeThisBetter?: typeof MakeThisBetter }).MakeThisBetter = MakeThisBetter\n}\n"],"names":["ShadowContainer","theme","style","cssText","tag","className","el","nodes","n","FeedbackTab","shadow","messages","position","onClick","customText","label","active","FRUSTRATION_DISMISS_MS","FrustrationPromptCard","handlers","DimOverlay","AnnotationToolbar","onExit","onModeChange","m","mode","AnnotationOverlay","ElementHighlighter","rect","getElementName","below","title","text","placeholder","alt","dataMark","getCssSelector","parts","current","selector","classNames","c","parent","siblings","idx","PinMarker","x","y","index","pin","BRAND_COLOR","FONT_STACK","DRAW_STROKE","DrawLayer","buildPathD","stroke","entry","path","points","cx","cy","center","fx","fy","d","i","xs","p","ys","DRAW_MIN_POINTS","AnnotationSession","e","underEl","getElementUnder","targetName","annotation","WIDGET_HOST_ID","isWidgetElement","host","escapeHtml","DrawNoteBar","opts","canUndo","canRedo","loading","message","CommentPopup","quickOpts","o","vw","vh","margin","left","top","btn","hasText","POLL_INTERVAL_MS","POLL_TIMEOUT_MS","CARD_WIDTH","CARD_HEIGHT","ClarifyCard","skip","result","res","footer","error","s","card","button","said","saidBlock","pairs","clarifiedBlock","q","a","done","last","msg","bubble","dots","SUCCESS_AUTO_CLOSE_MS","EMAIL_PATTERN","SuccessCard","onClose","onViewFeedback","options","viewLink","emailCapture","onSubmit","input","submit","handle","email","event","resolveUrl","url","baseUrl","doc","base","uuid","counter","random","toArray","arrayLike","arr","l","styleProps","getStyleProperties","px","node","styleProperty","val","getNodeWidth","leftBorder","rightBorder","getNodeHeight","topBorder","bottomBorder","getImageSize","targetNode","width","height","getPixelRatio","ratio","FINAL_PROCESS","canvasDimensionLimit","checkCanvasDimensions","canvas","createImage","resolve","reject","img","svgToDataURL","svg","html","nodeToDataURL","xmlns","foreignObject","isInstanceOfElement","instance","nodePrototype","formatCSSText","content","formatCSSProperties","name","value","priority","getPseudoElementStyle","pseudo","clonePseudoElement","nativeNode","clonedNode","styleElement","clonePseudoElements","WOFF","JPEG","mimes","getExtension","match","getMimeType","extension","getContentFromDataUrl","dataURL","isDataUrl","makeDataUrl","mimeType","fetchAsDataURL","init","process","blob","reader","cache","getCacheKey","contentType","includeQueryParams","key","resourceToDataURL","resourceUrl","cacheKey","cloneCanvasElement","cloneVideoElement","video","ctx","poster","cloneIFrameElement","iframe","_a","cloneNode","cloneSingleNode","isSVGElement","isSlotElement","cloneChildren","_b","children","deferred","child","clonedChild","cloneCSSStyle","targetStyle","sourceStyle","cloneInputValue","cloneSelectValue","clonedSelect","selectedOption","decorate","ensureSVGSymbols","clone","uses","processedDefs","id","exist","definition","ns","defs","isRoot","URL_REGEX","URL_WITH_FORMAT_REGEX","FONT_SRC_REGEX","toRegex","escaped","parseURLs","urls","raw","quotation","embed","resourceURL","baseURL","getContentFromUrl","resolvedURL","filterPreferredFontFormat","str","preferredFontFormat","src","format","shouldEmbed","embedResources","filteredCSSText","css","embedProp","propName","propValue","cssString","embedBackground","embedImageNode","isImageElement","attributes","image","embedChildren","deferreds","embedImages","applyStyle","manual","cssFetchCache","fetchCSS","embedFonts","data","regexUrl","loadFonts","loc","parseCSS","source","commentsRegex","keyframesRegex","matches","importRegex","combinedCSSRegex","unifiedRegex","getCSSRules","styleSheets","ret","sheet","item","importIndex","metadata","rule","inline","err","getWebFontRules","cssRules","parseWebFontRules","normalizeFontFamily","font","getUsedFonts","fonts","traverse","getWebFontCSS","rules","usedFonts","embedWebFonts","styleNode","sytleContent","toSvg","toCanvas","context","canvasWidth","canvasHeight","toJpeg","captureScreenshot","annotations","dataUrl","annotated","bakeAnnotations","dataUrlToBlob","loadImage","scaleX","scaleY","pinIndex","drawStroke","drawPin","canvasToJpegBlob","drawPath","parsePathPolylines","polylines","tokens","token","header","mime","binary","bytes","ErrorSource","listener","line","col","reason","errorSource","MAX_CONSOLE_ERRORS","ConsoleErrorCollector","location","MAX_BREADCRUMBS","BreadcrumbCollector","crumb","target","field","pushOrig","replaceOrig","onNav","unused","from","to","RAGE_CLICK_THRESHOLD","RAGE_CLICK_WINDOW_MS","RAPID_NAV_THRESHOLD","RAPID_NAV_WINDOW_MS","FORM_CHECK_DELAY_MS","DEAD_CLICK_DOM_DELAY_MS","ERROR_PAGE_CHECK_DELAY_MS","INTERACTIVE_TAGS","INTERACTIVE_ROLES","ERROR_PAGE_PATTERNS","_FrustrationDetector","onFrustration","_e","now","cutoff","r","describeElement","t","form","candidates","clickTime","mutated","cls","lower","role","FrustrationDetector","collectPageContext","detectBrowser","detectOS","ua","DEFAULT_API_URL","ApiClient","projectKey","apiUrl","retryDelayMs","userToken","userTokenFn","headers","payload","screenshot","submissionToken","generateSubmissionToken","json","ext","generateIdempotencyKey","reporterExternalId","feedbackId","identityToken","submissionSessionId","body","onDelta","consumeSse","retries","delay","ms","decoder","buffer","flush","eventLine","dataLine","sep","record","byte","buildPayload","description","pageContext","consoleErrors","user","recording","anonId","anonEmail","breadcrumbs","STORAGE_KEY","EMAIL_KEY","BOARD_URL_KEY","memoryId","memoryEmail","memoryBoardUrl","getAnonId","stored","generateAnonId","getStoredReporterEmail","rememberReporterEmail","getCachedBoardUrl","cacheBoardUrl","en","zhCN","ja","ko","es","fr","de","locales","getMessages","locale","lang","MAX_DURATION_S","RRWEB_CDN","RRWEB_SRI","rrwebLoaded","loadRrweb","loadViaImport","loadViaCdn","findGlobalRecord","win","existing","script","RecordSession","onMaxReached","ripple","RecordControlBar","getDuration","onStop","secs","mm","ss","RecordingManager","WidgetController","config","note","action","exchange","ui","submissionAttempt","waitForPaint","submission","summary","pos","feedback","saved","boardUrl","MakeThisBetter"],"mappings":"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","x_google_ignoreList":[16,17,18,19,20,21,22,23,24,25]}