@koderlabs/tasks-sdk-web-reporter 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hotkey.ts","../src/modal/styles.ts","../src/modal/shell.ts","../src/annotator/tools.ts","../src/annotator/draw.ts","../src/annotator/index.ts","../src/capture/support.ts","../src/capture/native.ts","../src/capture/fallback.ts","../src/capture/index.ts","../src/modal/form.ts","../src/transport.ts","../src/index.ts"],"sourcesContent":["/**\n * Hotkey parser and listener factory.\n *\n * Parses strings like 'ctrl+shift+i', 'meta+shift+i'.\n * Modifiers: ctrl, meta, alt, shift (order-insensitive).\n * Ignores keypresses when the focused element is an input, textarea,\n * or any contenteditable element (to avoid interfering with user typing).\n */\n\nexport interface ParsedHotkey {\n ctrl: boolean;\n meta: boolean;\n alt: boolean;\n shift: boolean;\n key: string; // lowercase key name, e.g. 'i'\n}\n\n/**\n * Parse a hotkey string into a structured predicate.\n * Returns null for invalid or falsy input.\n */\nexport function parseHotkey(raw: string | false | undefined): ParsedHotkey | null {\n if (!raw) return null;\n\n // `mod` resolves to Cmd on macOS, Ctrl elsewhere. Sniff once so saved configs\n // like `mod+shift+b` work cross-OS without rewriting.\n const isMac =\n typeof navigator !== 'undefined' &&\n /Mac|iPhone|iPad|iPod/i.test(navigator.platform ?? '');\n\n const parts = raw.toLowerCase().split('+').map((p) => p.trim());\n const modifiers = new Set<string>();\n let key = '';\n\n for (const part of parts) {\n if (part === 'mod') {\n modifiers.add(isMac ? 'meta' : 'ctrl');\n } else if (['ctrl', 'control'].includes(part)) {\n modifiers.add('ctrl');\n } else if (['meta', 'cmd', 'command'].includes(part)) {\n modifiers.add('meta');\n } else if (['alt', 'option', 'opt'].includes(part)) {\n modifiers.add('alt');\n } else if (part === 'shift') {\n modifiers.add('shift');\n } else {\n // Last non-modifier token is the key\n key = part;\n }\n }\n\n if (!key) return null;\n\n return {\n ctrl: modifiers.has('ctrl'),\n meta: modifiers.has('meta'),\n alt: modifiers.has('alt'),\n shift: modifiers.has('shift'),\n key,\n };\n}\n\n/**\n * Returns true if the keyboard event matches the parsed hotkey.\n */\nexport function matchesHotkey(e: KeyboardEvent, parsed: ParsedHotkey): boolean {\n return (\n e.ctrlKey === parsed.ctrl &&\n e.metaKey === parsed.meta &&\n e.altKey === parsed.alt &&\n e.shiftKey === parsed.shift &&\n e.key.toLowerCase() === parsed.key\n );\n}\n\n/**\n * Returns true if the event target should suppress hotkey handling\n * (user is typing in an input, textarea, or contenteditable).\n */\nexport function isTypingTarget(e: KeyboardEvent): boolean {\n const target = e.target as HTMLElement | null;\n if (!target) return false;\n const tag = target.tagName?.toLowerCase();\n if (tag === 'input' || tag === 'textarea' || tag === 'select') return true;\n // Check both the DOM property (isContentEditable) and the attribute. jsdom\n // does not always set `isContentEditable` when the attribute is assigned via\n // `el.contentEditable = 'true'`, so we fall back to the attribute string.\n if (target.isContentEditable) return true;\n // Fallback: check the `contentEditable` property and the raw attribute.\n // jsdom does not always wire `isContentEditable` to attribute changes.\n const ceProp = (target as HTMLElement & { contentEditable?: string }).contentEditable;\n if (ceProp === 'true' || ceProp === 'plaintext-only') return true;\n const ce = target.getAttribute?.('contenteditable');\n if (ce === '' || ce === 'true' || ce === 'plaintext-only') return true;\n return false;\n}\n\n/**\n * Register a keydown listener for the given hotkey string.\n * Returns a cleanup function to remove the listener.\n *\n * @param hotkeyStr - e.g. 'ctrl+shift+i' or false to disable.\n * @param handler - Called when the hotkey fires outside typing targets.\n * @param target - Element to attach to (defaults to window).\n */\nexport function registerHotkey(\n hotkeyStr: string | false | undefined,\n handler: () => void,\n target: EventTarget = window,\n): () => void {\n const parsed = parseHotkey(hotkeyStr);\n if (!parsed) return () => {}; // noop cleanup\n\n // Modifier-bearing chords (Ctrl/Cmd/Alt + something) are never produced by\n // normal typing — register them in CAPTURE phase and skip the \"is the user\n // typing?\" check. That way a chord like Cmd+Shift+B fires even when focus\n // sits in a text input or a TipTap editor (contenteditable).\n const hasModifier = parsed.ctrl || parsed.meta || parsed.alt;\n\n const listener = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (!hasModifier && isTypingTarget(ke)) return;\n if (matchesHotkey(ke, parsed)) {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }\n };\n\n // Capture-phase listener — runs BEFORE bubble-phase listeners on inputs\n // (e.g. character composition in TipTap) so we win the race.\n target.addEventListener('keydown', listener, true);\n return () => target.removeEventListener('keydown', listener, true);\n}\n","/**\n * Inlined CSS string for the widget modal.\n *\n * CSS vars override-able by the host page on the shadow root:\n * --accent-background highlight rect color (default: #ef4444)\n * --foreground text color (default: #111827)\n * --background modal background (default: #ffffff)\n * --border-color borders (default: #e5e7eb)\n * --z-index modal z-index (default: 2147483647)\n * --font-family (default: system-ui, sans-serif)\n */\nexport const WIDGET_STYLES = `\n :host {\n --accent-background: #ef4444;\n --foreground: #111827;\n --background: #ffffff;\n --border-color: #e5e7eb;\n --z-index: 2147483647;\n --font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n all: initial;\n font-family: var(--font-family);\n color: var(--foreground);\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n }\n\n .it-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.35);\n z-index: var(--z-index);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .it-modal {\n background: var(--background);\n border-radius: 12px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.25);\n /* Big enough to annotate a screenshot comfortably without dominating\n the entire viewport. Cap so it doesn't get unwieldy on 4K monitors. */\n width: min(1280px, 88vw);\n height: min(900px, 88vh);\n max-width: 88vw;\n max-height: 88vh;\n overflow-y: auto;\n padding: 24px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n position: relative;\n font-family: var(--font-family);\n color: var(--foreground);\n }\n\n .it-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n\n .it-title {\n font-size: 16px;\n font-weight: 600;\n margin: 0;\n }\n\n .it-close-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--foreground);\n opacity: 0.6;\n padding: 4px;\n border-radius: 6px;\n line-height: 1;\n font-size: 18px;\n transition: opacity 0.15s;\n }\n .it-close-btn:hover { opacity: 1; }\n\n .it-section { display: flex; flex-direction: column; gap: 6px; }\n\n .it-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--foreground);\n opacity: 0.8;\n }\n\n .it-textarea, .it-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--border-color);\n border-radius: 8px;\n font-size: 14px;\n font-family: var(--font-family);\n color: var(--foreground);\n background: var(--background);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n .it-textarea:focus, .it-input:focus {\n border-color: var(--accent-background);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-background) 20%, transparent);\n }\n\n .it-textarea { min-height: 100px; }\n\n .it-error {\n font-size: 12px;\n color: var(--accent-background);\n min-height: 16px;\n }\n\n .it-screenshot-area {\n border: 2px dashed var(--border-color);\n border-radius: 8px;\n padding: 12px;\n text-align: center;\n background: #f9fafb;\n /* Let the screenshot panel grow to fill the modal — description sits\n below and keeps its natural size. */\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .it-screenshot-preview {\n position: relative;\n width: 100%;\n flex: 1 1 auto;\n min-height: 0;\n overflow: hidden;\n border-radius: 6px;\n /* Center the screenshot vertically so smaller captures aren't pinned\n to the top of a tall panel. */\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n /* Stage = aspect-ratio-locked wrapper around bg + fg canvases.\n Sized to fit the preview pane while preserving the screenshot's\n aspect ratio — keeps fg overlay aligned with bg pixel-for-pixel. */\n .it-screenshot-stage {\n position: relative;\n max-width: 100%;\n max-height: 100%;\n /* Default ratio prevents 0-height collapse before the first capture */\n aspect-ratio: 16 / 10;\n /* Lock width to the smaller of (parent width) or (parent height × ratio).\n Browsers honor aspect-ratio for one axis only when the other is auto. */\n width: 100%;\n height: auto;\n }\n\n .it-background-canvas {\n width: 100%;\n height: 100%;\n display: block;\n border-radius: 6px;\n }\n\n .it-foreground-canvas {\n position: absolute;\n top: 0; left: 0;\n width: 100% !important;\n height: 100% !important;\n cursor: crosshair;\n }\n\n .it-screenshot-placeholder {\n color: var(--foreground);\n opacity: 0.5;\n font-size: 13px;\n }\n\n .it-toolbar {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n margin-top: 8px;\n }\n\n .it-btn {\n padding: 7px 14px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border: 1px solid var(--border-color);\n background: var(--background);\n color: var(--foreground);\n transition: background 0.15s, border-color 0.15s;\n font-family: var(--font-family);\n }\n .it-btn:hover { background: #f3f4f6; }\n\n .it-btn-primary {\n background: var(--accent-background);\n color: #fff;\n border-color: var(--accent-background);\n }\n .it-btn-primary:hover { filter: brightness(0.9); background: var(--accent-background); }\n .it-btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }\n\n .it-btn-tool.active {\n background: color-mix(in srgb, var(--accent-background) 15%, var(--background));\n border-color: var(--accent-background);\n color: var(--accent-background);\n }\n\n .it-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n\n .it-branding {\n font-size: 11px;\n color: var(--foreground);\n opacity: 0.4;\n text-decoration: none;\n }\n .it-branding:hover { opacity: 0.7; }\n\n .it-actions {\n display: flex;\n gap: 8px;\n }\n\n .it-spinner {\n display: inline-block;\n width: 14px; height: 14px;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: it-spin 0.7s linear infinite;\n vertical-align: middle;\n margin-right: 6px;\n }\n @keyframes it-spin { to { transform: rotate(360deg); } }\n\n /* Modal collapses to a compact confirmation card after submit succeeds.\n Overrides the wide annotation-mode sizing without re-mounting. */\n .it-modal.it-modal--success {\n width: min(420px, 92vw) !important;\n height: auto !important;\n max-height: 80vh !important;\n }\n\n .it-success {\n text-align: center;\n padding: 16px 8px 8px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n }\n\n .it-success-icon {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: #dcfce7;\n color: #16a34a;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n font-weight: 700;\n line-height: 1;\n box-shadow: 0 0 0 6px rgba(22, 163, 74, 0.08);\n }\n\n .it-success-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--foreground);\n }\n\n .it-success-ticket {\n font-size: 20px;\n font-weight: 700;\n color: var(--accent-background);\n text-decoration: none;\n letter-spacing: 0.02em;\n }\n .it-success-ticket:hover { text-decoration: underline; }\n\n .it-success-hint {\n font-size: 12px;\n color: var(--foreground);\n opacity: 0.55;\n margin-top: 4px;\n }\n\n .it-warning {\n font-size: 12px;\n color: #d97706;\n background: #fef3c7;\n border-radius: 6px;\n padding: 8px 10px;\n }\n\n .it-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: calc(var(--z-index) - 1);\n width: 48px; height: 48px;\n border-radius: 50%;\n background: var(--accent-background);\n color: #fff;\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0,0,0,0.2);\n font-size: 22px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.15s, box-shadow 0.15s;\n }\n .it-fab:hover {\n transform: scale(1.1);\n box-shadow: 0 6px 20px rgba(0,0,0,0.3);\n }\n`;\n","/**\n * Shadow DOM modal shell.\n *\n * Rules:\n * - ESC key closes the modal.\n * - Backdrop click does NOT close (prevents accidental data loss).\n * - Only one shell instance per host element at a time.\n */\n\nimport { WIDGET_STYLES } from './styles';\n\n/**\n * Read the page's CSP nonce from `<meta name=\"csp-nonce\" content=\"...\">`.\n * When present, it is applied to inline `<style>` / `<script>` elements\n * the widget creates so the host CSP doesn't block them. Returns `null`\n * when no meta tag is present (no-op — relies on `style-src 'self'` or\n * shadow-DOM exemption).\n */\nexport function getCspNonce(): string | null {\n if (typeof document === 'undefined') return null;\n const meta = document.querySelector('meta[name=\"csp-nonce\"]');\n const v = meta?.getAttribute('content');\n return v && v.length > 0 ? v : null;\n}\n\nexport interface ShellOptions {\n /** Called when the user closes the modal (ESC or Cancel button). */\n onClose?: () => void;\n}\n\nexport class ModalShell {\n /** Outer host appended to document.body — exposed so callers can hide it\n * from native screenshot capture without leaking the shadow DOM. */\n public readonly host: HTMLElement;\n private shadow: ShadowRoot;\n private _isOpen = false;\n private onCloseCb?: () => void;\n\n // Refs\n private backdropEl: HTMLElement | null = null;\n private modalEl: HTMLElement | null = null;\n private contentSlot: HTMLElement | null = null;\n\n // Cleanup\n private _escListener: ((e: KeyboardEvent) => void) | null = null;\n\n constructor(opts: ShellOptions = {}) {\n this.onCloseCb = opts.onClose;\n this.host = document.createElement('div');\n this.host.setAttribute('data-it-widget', '');\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n // Inject styles — apply CSP nonce if the host page declared one so\n // strict `style-src 'self' 'nonce-...'` policies don't block us.\n const styleEl = document.createElement('style');\n styleEl.textContent = WIDGET_STYLES;\n const nonce = getCspNonce();\n if (nonce) {\n styleEl.setAttribute('nonce', nonce);\n (styleEl as any).nonce = nonce;\n }\n this.shadow.appendChild(styleEl);\n }\n\n get shadowRoot(): ShadowRoot {\n return this.shadow;\n }\n\n get isOpen(): boolean {\n return this._isOpen;\n }\n\n get modalElement(): HTMLElement | null {\n return this.modalEl;\n }\n\n /**\n * Open the modal with the given content element.\n */\n open(content: HTMLElement): void {\n if (this._isOpen) this._teardown();\n\n document.body.appendChild(this.host);\n\n // Backdrop (click does NOT close — spec requirement)\n const backdrop = document.createElement('div');\n backdrop.className = 'it-backdrop';\n // Prevent accidental close on backdrop click\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop) {\n // Do nothing — spec says backdrop click must NOT close\n e.stopPropagation();\n }\n });\n\n const modal = document.createElement('div');\n modal.className = 'it-modal';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n\n this.contentSlot = content;\n modal.appendChild(content);\n backdrop.appendChild(modal);\n this.shadow.appendChild(backdrop);\n\n this.backdropEl = backdrop;\n this.modalEl = modal;\n this._isOpen = true;\n\n // ESC closes\n this._escListener = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && this._isOpen) {\n this.close();\n }\n };\n window.addEventListener('keydown', this._escListener);\n\n // Focus the modal for accessibility\n modal.setAttribute('tabindex', '-1');\n modal.focus();\n }\n\n /** Close and remove the modal. */\n close(): void {\n if (!this._isOpen) return;\n this._teardown();\n this.onCloseCb?.();\n }\n\n /** Destroy completely — remove host from DOM. */\n destroy(): void {\n this._teardown();\n if (this.host.parentNode) this.host.parentNode.removeChild(this.host);\n }\n\n private _teardown(): void {\n if (this._escListener) {\n window.removeEventListener('keydown', this._escListener);\n this._escListener = null;\n }\n if (this.backdropEl && this.shadow.contains(this.backdropEl)) {\n this.shadow.removeChild(this.backdropEl);\n }\n this.backdropEl = null;\n this.modalEl = null;\n this.contentSlot = null;\n this._isOpen = false;\n }\n}\n","/**\n * Annotation tool state management.\n *\n * Manages the list of DrawCommands, active tool, and undo/clear operations.\n * Decoupled from DOM/canvas rendering (that lives in draw.ts and index.ts).\n */\n\nimport type { DrawCommand } from '../types';\n\nexport type ToolMode = 'highlight' | 'hide';\n\nexport interface AnnotationState {\n commands: DrawCommand[];\n activeTool: ToolMode;\n}\n\nexport class AnnotationTools {\n private _commands: DrawCommand[] = [];\n private _activeTool: ToolMode = 'highlight';\n private _onChange?: (state: AnnotationState) => void;\n\n constructor(onChange?: (state: AnnotationState) => void) {\n this._onChange = onChange;\n }\n\n get activeTool(): ToolMode {\n return this._activeTool;\n }\n\n get commands(): Readonly<DrawCommand[]> {\n return this._commands;\n }\n\n /** Switch between highlight and hide tools. */\n setTool(mode: ToolMode): void {\n this._activeTool = mode;\n this._notify();\n }\n\n /** Toggle between the two tools. */\n toggleTool(): void {\n this._activeTool = this._activeTool === 'highlight' ? 'hide' : 'highlight';\n this._notify();\n }\n\n /** Add a new draw command (called when the user finishes drawing a rect). */\n addCommand(cmd: DrawCommand): void {\n this._commands = [...this._commands, cmd];\n this._notify();\n }\n\n /** Remove the last command (undo). */\n undo(): void {\n if (this._commands.length === 0) return;\n this._commands = this._commands.slice(0, -1);\n this._notify();\n }\n\n /** Remove a specific command by index. */\n removeAt(index: number): void {\n this._commands = this._commands.filter((_, i) => i !== index);\n this._notify();\n }\n\n /** Remove all commands. */\n clear(): void {\n this._commands = [];\n this._notify();\n }\n\n /** Get a plain-object snapshot of the current state. */\n getState(): AnnotationState {\n return {\n commands: [...this._commands],\n activeTool: this._activeTool,\n };\n }\n\n private _notify(): void {\n this._onChange?.(this.getState());\n }\n}\n","/**\n * DrawCommand model and paintForeground renderer.\n * Ported from: sentry-javascript/packages/feedback/src/screenshot/components/ScreenshotEditor.tsx\n *\n * Two render modes:\n * 'highlight' — draws a red cutout rectangle over a semi-transparent dim overlay.\n * The cutout appears brighter/clearer; everything else is dimmed.\n * 'hide' — draws an opaque black box (for PII redaction).\n *\n * Three-canvas pipeline:\n * background canvas — raw screenshot frame (drawn once)\n * foreground canvas — dim overlay + annotation rects (redrawn on every change)\n * output canvas — composited result (background + foreground)\n */\n\nimport type { DrawCommand } from '../types';\n\nexport type { DrawCommand };\n\n// CSS var name used for highlight stroke/fill color, falling back to red\nconst ACCENT_VAR = '--accent-background';\nconst ACCENT_DEFAULT = '#ef4444';\n\nfunction getAccentColor(root: HTMLElement | ShadowRoot): string {\n const el = root instanceof ShadowRoot ? root.host as HTMLElement : root;\n return getComputedStyle(el).getPropertyValue(ACCENT_VAR).trim() || ACCENT_DEFAULT;\n}\n\n/**\n * Paint the foreground overlay canvas from a list of DrawCommands.\n *\n * @param foreground - The foreground overlay canvas element.\n * @param commands - List of annotation rectangles (normalized 0..1 coords).\n * @param accent - Highlight color (hex/rgb string).\n */\nexport function paintForeground(\n foreground: HTMLCanvasElement,\n commands: DrawCommand[],\n accent: string = ACCENT_DEFAULT,\n): void {\n const ctx = foreground.getContext('2d');\n if (!ctx) return;\n\n const W = foreground.width;\n const H = foreground.height;\n\n ctx.clearRect(0, 0, W, H);\n\n // Separate commands by type for layered rendering\n const highlights = commands.filter((c) => c.type === 'highlight');\n const hides = commands.filter((c) => c.type === 'hide');\n\n // --- Highlight mode ---\n // 1. Draw a semi-transparent dark overlay over the whole canvas.\n // 2. For each highlight rect, use 'destination-out' to cut a hole — revealing\n // the bright screenshot underneath through the dim overlay.\n if (highlights.length > 0) {\n ctx.save();\n ctx.fillStyle = 'rgba(0, 0, 0, 0.45)';\n ctx.fillRect(0, 0, W, H);\n\n ctx.globalCompositeOperation = 'destination-out';\n for (const cmd of highlights) {\n const rx = cmd.x * W;\n const ry = cmd.y * H;\n const rw = cmd.w * W;\n const rh = cmd.h * H;\n ctx.fillStyle = 'rgba(0,0,0,1)'; // opaque to punch hole\n ctx.fillRect(rx, ry, rw, rh);\n }\n ctx.restore();\n\n // Draw red border around each highlight rect\n ctx.save();\n ctx.strokeStyle = accent;\n ctx.lineWidth = 2;\n for (const cmd of highlights) {\n ctx.strokeRect(cmd.x * W, cmd.y * H, cmd.w * W, cmd.h * H);\n }\n ctx.restore();\n }\n\n // --- Hide mode ---\n // Draw opaque black boxes (PII redaction).\n if (hides.length > 0) {\n ctx.save();\n ctx.fillStyle = '#000000';\n for (const cmd of hides) {\n ctx.fillRect(cmd.x * W, cmd.y * H, cmd.w * W, cmd.h * H);\n }\n ctx.restore();\n }\n}\n\n/**\n * Composite background + foreground into a single output canvas and return it.\n * The caller must set output.width/height to match background dims before calling.\n */\nexport function compositeCanvases(\n background: HTMLCanvasElement,\n foreground: HTMLCanvasElement,\n output: HTMLCanvasElement,\n): void {\n const ctx = output.getContext('2d');\n if (!ctx) return;\n\n output.width = background.width;\n output.height = background.height;\n ctx.clearRect(0, 0, output.width, output.height);\n ctx.drawImage(background, 0, 0);\n ctx.drawImage(foreground, 0, 0);\n}\n\nexport { getAccentColor };\n","/**\n * Annotation canvas overlay.\n *\n * Wires mouse events to AnnotationTools, renders via paintForeground.\n * Normalizes all coordinates to 0..1 against the screenshot image dimensions.\n */\n\nimport { AnnotationTools } from './tools';\nimport { paintForeground, compositeCanvases, getAccentColor } from './draw';\nimport type { DrawCommand } from '../types';\n\nexport interface AnnotatorOptions {\n /** The background canvas showing the raw screenshot. */\n background: HTMLCanvasElement;\n /** Foreground overlay canvas (positioned absolutely over background). */\n foreground: HTMLCanvasElement;\n /** Shadow root or element providing CSS vars (for accent color). */\n cssRoot: HTMLElement | ShadowRoot;\n /** Called whenever the annotation state changes (for re-render triggers). */\n onChange?: (commands: DrawCommand[]) => void;\n}\n\nexport class Annotator {\n private tools: AnnotationTools;\n private background: HTMLCanvasElement;\n private foreground: HTMLCanvasElement;\n private cssRoot: HTMLElement | ShadowRoot;\n private onChangeCb?: (commands: DrawCommand[]) => void;\n\n // In-progress drag state\n private dragging = false;\n private dragStart: { x: number; y: number } | null = null;\n\n // Cleanup for event listeners\n private cleanupListeners: (() => void)[] = [];\n\n constructor(opts: AnnotatorOptions) {\n this.background = opts.background;\n this.foreground = opts.foreground;\n this.cssRoot = opts.cssRoot;\n this.onChangeCb = opts.onChange;\n\n this.tools = new AnnotationTools((state) => {\n this._repaint();\n this.onChangeCb?.(state.commands);\n });\n\n this._attachMouseListeners();\n }\n\n get activeTool() { return this.tools.activeTool; }\n get commands() { return this.tools.commands; }\n\n setTool(mode: 'highlight' | 'hide') { this.tools.setTool(mode); }\n toggleTool() { this.tools.toggleTool(); }\n undo() { this.tools.undo(); }\n clear() { this.tools.clear(); }\n removeAt(i: number) { this.tools.removeAt(i); }\n\n /** Composite background + foreground into an output canvas. */\n composite(output: HTMLCanvasElement): void {\n compositeCanvases(this.background, this.foreground, output);\n }\n\n /** Destroy event listeners. */\n destroy(): void {\n for (const fn of this.cleanupListeners) fn();\n this.cleanupListeners = [];\n }\n\n // ── Private helpers ──────────────────────────────────────────────────────────\n\n private _repaint(): void {\n const accent = getAccentColor(this.cssRoot);\n paintForeground(this.foreground, [...this.tools.commands], accent);\n }\n\n /** Normalize a pixel coordinate within the foreground canvas to 0..1. */\n private _normalize(px: number, py: number): { nx: number; ny: number } {\n const W = this.foreground.width || 1;\n const H = this.foreground.height || 1;\n return {\n nx: Math.max(0, Math.min(1, px / W)),\n ny: Math.max(0, Math.min(1, py / H)),\n };\n }\n\n /**\n * Mouse → internal canvas pixel coordinates.\n *\n * The foreground canvas has a HUGE internal resolution (matches the raw\n * screenshot, e.g. 2880×1800 on retina) but is displayed at a small CSS\n * size in the modal (~400px wide). `clientX - rect.left` returns CSS\n * pixels, so we must scale up to internal pixels — otherwise a 100px CSS\n * drag becomes a 100/2880 ≈ 3.5% rectangle pinned to the top-left.\n */\n private _canvasPos(e: MouseEvent): { x: number; y: number } {\n const rect = this.foreground.getBoundingClientRect();\n const scaleX = rect.width > 0 ? this.foreground.width / rect.width : 1;\n const scaleY = rect.height > 0 ? this.foreground.height / rect.height : 1;\n return {\n x: (e.clientX - rect.left) * scaleX,\n y: (e.clientY - rect.top) * scaleY,\n };\n }\n\n private _attachMouseListeners(): void {\n const fg = this.foreground;\n\n const onMouseDown = (e: MouseEvent) => {\n if (e.button !== 0) return; // left button only\n this.dragging = true;\n this.dragStart = this._canvasPos(e);\n };\n\n const onMouseMove = (e: MouseEvent) => {\n if (!this.dragging || !this.dragStart) return;\n // Show live preview: repaint committed commands + current rect\n const current = this._canvasPos(e);\n const preview = this._buildCommand(this.dragStart, current);\n const accent = getAccentColor(this.cssRoot);\n paintForeground(\n this.foreground,\n [...this.tools.commands, preview],\n accent,\n );\n };\n\n const onMouseUp = (e: MouseEvent) => {\n if (!this.dragging || !this.dragStart) return;\n this.dragging = false;\n const end = this._canvasPos(e);\n const cmd = this._buildCommand(this.dragStart, end);\n // Only commit if the rect has non-trivial size (> 4px in canvas space)\n const W = this.foreground.width || 1;\n const H = this.foreground.height || 1;\n if (Math.abs(cmd.w) * W > 4 && Math.abs(cmd.h) * H > 4) {\n this.tools.addCommand(this._normalizeCommand(cmd));\n } else {\n this._repaint(); // discard tiny rect, repaint cleanly\n }\n this.dragStart = null;\n };\n\n fg.addEventListener('mousedown', onMouseDown);\n fg.addEventListener('mousemove', onMouseMove);\n fg.addEventListener('mouseup', onMouseUp);\n\n this.cleanupListeners.push(\n () => fg.removeEventListener('mousedown', onMouseDown),\n () => fg.removeEventListener('mousemove', onMouseMove),\n () => fg.removeEventListener('mouseup', onMouseUp),\n );\n }\n\n /** Build a raw (pixel-space) DrawCommand from two mouse positions. */\n private _buildCommand(\n start: { x: number; y: number },\n end: { x: number; y: number },\n ): DrawCommand {\n const x = Math.min(start.x, end.x);\n const y = Math.min(start.y, end.y);\n const w = Math.abs(end.x - start.x);\n const h = Math.abs(end.y - start.y);\n const W = this.foreground.width || 1;\n const H = this.foreground.height || 1;\n return {\n type: this.tools.activeTool,\n x: x / W,\n y: y / H,\n w: w / W,\n h: h / H,\n };\n }\n\n /** Ensure a command's coordinates are normalized (clamp to 0..1). */\n private _normalizeCommand(cmd: DrawCommand): DrawCommand {\n const clamp = (v: number) => Math.max(0, Math.min(1, v));\n return {\n type: cmd.type,\n x: clamp(cmd.x),\n y: clamp(cmd.y),\n w: clamp(cmd.w),\n h: clamp(cmd.h),\n };\n }\n}\n","/**\n * Capability detection for native screenshot capture.\n * Ported from: sentry-javascript/packages/feedback/src/util/isScreenshotSupported.ts\n *\n * Returns false on:\n * - Mobile UA (Android, iPhone, iPad via UA, etc.)\n * - iPad-as-Mac (Macintosh UA with maxTouchPoints > 1)\n * - Insecure context (non-HTTPS except localhost)\n * - Missing getDisplayMedia API\n */\nexport function isNativeCaptureSupported(): boolean {\n // Mobile user agents\n if (\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n )\n ) {\n return false;\n }\n\n // iPad-as-Mac: reports Macintosh UA but has touch points\n if (/Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints > 1) {\n return false;\n }\n\n // Require secure context (HTTPS or localhost)\n if (!isSecureContext) {\n return false;\n }\n\n // Require the API to exist\n return typeof navigator.mediaDevices?.getDisplayMedia === 'function';\n}\n","/**\n * Native screenshot capture via getDisplayMedia.\n * Ported from: sentry-javascript/packages/feedback/src/screenshot/components/useTakeScreenshot.tsx\n *\n * Flow:\n * 1. Hides the modal element so it doesn't appear in the screenshot.\n * 2. Calls getDisplayMedia with preferCurrentTab + include self + exclude monitor.\n * 3. Pipes stream into a <video> element, waits for metadata, paints one frame to canvas.\n * 4. Stops all tracks, restores modal visibility.\n */\n\nexport interface NativeCaptureResult {\n canvas: HTMLCanvasElement;\n /** Device pixel ratio used when sizing the canvas */\n dpi: number;\n}\n\nexport interface NativeCaptureOptions {\n /** Element or array of elements to hide during capture (widget modal +\n * FAB host both live separately on document.body). */\n hideElement?: HTMLElement | HTMLElement[] | null;\n}\n\n/**\n * Attempt a native getDisplayMedia capture.\n * Throws if the user cancels (NotAllowedError) or API is unavailable.\n */\nexport async function nativeCapture(\n opts: NativeCaptureOptions = {},\n): Promise<NativeCaptureResult> {\n const dpi = window.devicePixelRatio || 1;\n\n // Hide widget chrome (modal + FAB) before opening the picker. They stay\n // hidden through the picker prompt AND the first video frame paint —\n // restoring earlier means the captured stream includes just-restored\n // elements.\n const hiddenList: HTMLElement[] = Array.isArray(opts.hideElement)\n ? opts.hideElement.filter((el): el is HTMLElement => !!el)\n : opts.hideElement\n ? [opts.hideElement]\n : [];\n const prev = hiddenList.map((el) => ({\n el,\n display: el.style.display,\n visibility: el.style.visibility,\n }));\n for (const el of hiddenList) {\n el.style.visibility = 'hidden';\n el.style.display = 'none';\n }\n\n const restore = () => {\n for (const { el, display, visibility } of prev) {\n el.style.display = display;\n el.style.visibility = visibility;\n }\n };\n\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({\n video: {\n width: window.innerWidth * dpi,\n height: window.innerHeight * dpi,\n },\n audio: false,\n // @ts-expect-error — non-standard constraint flags (Chromium 111+)\n monitorTypeSurfaces: 'exclude',\n preferCurrentTab: true,\n selfBrowserSurface: 'include',\n surfaceSwitching: 'exclude',\n } as DisplayMediaStreamOptions);\n } catch (err) {\n // User cancelled / permission denied. Restore immediately and rethrow.\n restore();\n throw err;\n }\n\n try {\n // Paint first video frame to canvas — must happen while modal is still\n // hidden so the captured frame doesn't include the bug-report dialog.\n const video = document.createElement('video');\n video.srcObject = stream;\n video.muted = true;\n\n await new Promise<void>((resolve, reject) => {\n video.onloadedmetadata = () => resolve();\n video.onerror = () => reject(new Error('Video element error during screenshot'));\n });\n\n // Some browsers need play() before drawing\n await video.play().catch(() => {/* ignore; draw attempt below may still work */});\n\n // Give the compositor one frame to actually present the (modal-less) page,\n // otherwise we sometimes paint a buffered frame that still shows the\n // dialog. Two rAFs is the smallest reliable wait across Chromium/WebKit.\n await new Promise<void>((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));\n\n const canvas = document.createElement('canvas');\n canvas.width = video.videoWidth || window.innerWidth * dpi;\n canvas.height = video.videoHeight || window.innerHeight * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Could not get 2D canvas context for screenshot');\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n\n // Clean up media tracks BEFORE restoring the modal — stopping tracks is\n // synchronous, so we know no further frames will be requested.\n for (const track of stream.getTracks()) track.stop();\n video.srcObject = null;\n\n return { canvas, dpi };\n } finally {\n restore();\n }\n}\n","/**\n * Fallback screenshot via html2canvas.\n *\n * Loaded lazily — only imported when native capture is unavailable or denied.\n * Catches SecurityError (tainted canvas from cross-origin images) and emits\n * a 'tainted_canvas' notification to the caller so the UI can show a warning.\n */\n\nexport interface FallbackCaptureResult {\n canvas: HTMLCanvasElement;\n tainted: boolean; // true = some content was blocked; screenshot may be partial\n}\n\nexport type TaintedCanvasCallback = () => void;\n\nexport interface FallbackCaptureOptions {\n /** Element(s) to hide while html2canvas walks the DOM (widget modal +\n * FAB host both live separately on document.body). */\n hideElement?: HTMLElement | HTMLElement[] | null;\n}\n\n/**\n * Attempt an html2canvas screenshot of document.body.\n *\n * @param onTainted - Called if the canvas is detected as tainted.\n * @param opts.hideElement - Hidden during capture, restored after.\n */\nexport async function fallbackCapture(\n onTainted?: TaintedCanvasCallback,\n opts: FallbackCaptureOptions = {},\n): Promise<FallbackCaptureResult> {\n // Dynamic import so html2canvas is never bundled in the eager chunk\n let html2canvas: typeof import('html2canvas').default;\n try {\n const mod = await import('html2canvas');\n html2canvas = mod.default ?? (mod as any);\n } catch (importErr) {\n throw new Error(\n 'html2canvas is not installed. Install it as a peer dependency or use a browser that supports getDisplayMedia.',\n );\n }\n\n // Hide widget chrome (modal + FAB) so html2canvas doesn't render either\n // into the snapshot. Supports a single element or an array.\n const hiddenList: HTMLElement[] = Array.isArray(opts.hideElement)\n ? opts.hideElement.filter((el): el is HTMLElement => !!el)\n : opts.hideElement\n ? [opts.hideElement]\n : [];\n const prev = hiddenList.map((el) => ({\n el,\n display: el.style.display,\n visibility: el.style.visibility,\n }));\n for (const el of hiddenList) {\n el.style.visibility = 'hidden';\n el.style.display = 'none';\n }\n const restore = () => {\n for (const { el, display, visibility } of prev) {\n el.style.display = display;\n el.style.visibility = visibility;\n }\n };\n\n let tainted = false;\n\n try {\n try {\n const canvas = await html2canvas(document.body, {\n allowTaint: false,\n useCORS: true,\n logging: false,\n scale: window.devicePixelRatio || 1,\n });\n return { canvas, tainted };\n } catch (err) {\n // SecurityError thrown when canvas is tainted by cross-origin content.\n // Retry while modal is still hidden so the partial snapshot is clean.\n if (err instanceof DOMException && err.name === 'SecurityError') {\n tainted = true;\n onTainted?.();\n const canvas = await html2canvas(document.body, {\n allowTaint: true,\n useCORS: false,\n logging: false,\n scale: window.devicePixelRatio || 1,\n }).catch(() => {\n const blank = document.createElement('canvas');\n blank.width = window.innerWidth;\n blank.height = window.innerHeight;\n return blank;\n });\n return { canvas, tainted };\n }\n throw err;\n }\n } finally {\n restore();\n }\n}\n","/**\n * Orchestrate native vs fallback screenshot capture.\n *\n * Decision tree:\n * 1. If useNativeScreenshot=true AND isNativeCaptureSupported() → try nativeCapture().\n * 2. On NotAllowedError (user cancelled) → return null (no screenshot, proceed without).\n * 3. On any other native failure OR useNativeScreenshot=false → fallbackCapture().\n * 4. Return null if both paths fail.\n */\n\nimport { isNativeCaptureSupported } from './support';\nimport { nativeCapture } from './native';\nimport { fallbackCapture } from './fallback';\n\nexport interface CaptureResult {\n canvas: HTMLCanvasElement;\n dpi: number;\n method: 'native' | 'fallback';\n tainted?: boolean;\n}\n\nexport interface CaptureOptions {\n useNativeScreenshot?: boolean;\n /** Single element OR an array — all are hidden through capture + paint\n * and restored in finally. Used to make sure neither the bug-report\n * modal nor the FAB shows up in the screenshot. */\n hideElement?: HTMLElement | HTMLElement[] | null;\n onTainted?: () => void;\n onFallback?: () => void;\n}\n\n/**\n * Perform screenshot capture using the best available method.\n * Returns null if the user cancelled (NotAllowedError on native path).\n */\nexport async function capture(opts: CaptureOptions = {}): Promise<CaptureResult | null> {\n const useNative = opts.useNativeScreenshot !== false; // default true\n\n if (useNative && isNativeCaptureSupported()) {\n try {\n const result = await nativeCapture({ hideElement: opts.hideElement });\n return { ...result, method: 'native' };\n } catch (err) {\n if (err instanceof DOMException && err.name === 'NotAllowedError') {\n // User explicitly cancelled the picker — no screenshot\n return null;\n }\n // Any other error (e.g. NotSupportedError on Firefox) → fall through to fallback\n opts.onFallback?.();\n }\n } else if (useNative) {\n // Native wanted but not supported on this device\n opts.onFallback?.();\n }\n\n // Fallback path — pass hideElement so html2canvas doesn't snapshot the modal\n try {\n const result = await fallbackCapture(opts.onTainted, { hideElement: opts.hideElement });\n return { canvas: result.canvas, dpi: window.devicePixelRatio || 1, method: 'fallback', tainted: result.tainted };\n } catch {\n return null;\n }\n}\n","/**\n * Widget form — description (required, ≥10 chars), optional title, optional email.\n * Handles screenshot capture trigger, annotation toolbar, submit/cancel.\n */\n\nimport { Annotator } from '../annotator/index';\nimport { capture } from '../capture/index';\nimport type { DrawCommand, WidgetOptions } from '../types';\n\nexport interface FormSubmitPayload {\n title: string;\n description: string;\n email?: string;\n screenshot?: HTMLCanvasElement;\n annotations: DrawCommand[];\n}\n\nexport interface FormOptions {\n widgetOpts: WidgetOptions;\n onSubmit: (payload: FormSubmitPayload) => Promise<{ ticketKey: string; ticketUrl: string }>;\n onCancel: () => void;\n /** Shadow root or element for CSS var resolution */\n cssRoot: ShadowRoot | HTMLElement;\n showBranding?: boolean;\n /** Element(s) to hide from screenshot before native capture (modal host\n * + FAB host). Accepts a single element for back-compat. */\n hideForCapture?: HTMLElement | HTMLElement[] | null;\n}\n\nexport function buildFormElement(opts: FormOptions): HTMLElement {\n const container = document.createElement('div');\n\n // ── Header ─────────────────────────────────────────────────────────────────\n const header = document.createElement('div');\n header.className = 'it-header';\n const title = document.createElement('h2');\n title.className = 'it-title';\n title.textContent = 'Report a Bug';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'it-close-btn';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.textContent = '✕';\n closeBtn.addEventListener('click', opts.onCancel);\n header.appendChild(title);\n header.appendChild(closeBtn);\n container.appendChild(header);\n\n // ── Screenshot section ──────────────────────────────────────────────────────\n let capturedCanvas: HTMLCanvasElement | null = null;\n let annotator: Annotator | null = null;\n let annotations: DrawCommand[] = [];\n\n const screenshotArea = document.createElement('div');\n screenshotArea.className = 'it-screenshot-area';\n\n const placeholder = document.createElement('div');\n placeholder.className = 'it-screenshot-placeholder';\n placeholder.textContent = 'No screenshot yet.';\n\n const captureBtn = document.createElement('button');\n captureBtn.className = 'it-btn';\n captureBtn.textContent = 'Add Screenshot';\n\n let taintedWarning: HTMLElement | null = null;\n\n const screenshotPreview = document.createElement('div');\n screenshotPreview.className = 'it-screenshot-preview';\n screenshotPreview.style.display = 'none';\n\n // Background canvas (screenshot) + foreground canvas (annotation overlay)\n // Inner stage matches the screenshot's aspect ratio so the foreground\n // overlay always lines up with the background pixel-for-pixel even when\n // the surrounding preview pane is much larger.\n const stage = document.createElement('div');\n stage.className = 'it-screenshot-stage';\n\n const backgroundCanvas = document.createElement('canvas');\n backgroundCanvas.className = 'it-background-canvas';\n const foregroundCanvas = document.createElement('canvas');\n foregroundCanvas.className = 'it-foreground-canvas';\n\n stage.appendChild(backgroundCanvas);\n stage.appendChild(foregroundCanvas);\n screenshotPreview.appendChild(stage);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'it-toolbar';\n toolbar.style.display = 'none';\n\n const highlightBtn = document.createElement('button');\n highlightBtn.className = 'it-btn it-btn-tool active';\n highlightBtn.textContent = '▭ Highlight';\n\n const hideBtn = document.createElement('button');\n hideBtn.className = 'it-btn it-btn-tool';\n hideBtn.textContent = '■ Hide';\n\n const undoBtn = document.createElement('button');\n undoBtn.className = 'it-btn';\n undoBtn.textContent = '↩ Undo';\n\n const clearBtn = document.createElement('button');\n clearBtn.className = 'it-btn';\n clearBtn.textContent = '✕ Clear';\n\n toolbar.appendChild(highlightBtn);\n toolbar.appendChild(hideBtn);\n toolbar.appendChild(undoBtn);\n toolbar.appendChild(clearBtn);\n\n screenshotArea.appendChild(placeholder);\n screenshotArea.appendChild(captureBtn);\n screenshotArea.appendChild(screenshotPreview);\n screenshotArea.appendChild(toolbar);\n container.appendChild(screenshotArea);\n\n captureBtn.addEventListener('click', async () => {\n captureBtn.disabled = true;\n captureBtn.textContent = 'Capturing…';\n\n try {\n const result = await capture({\n useNativeScreenshot: opts.widgetOpts.useNativeScreenshot,\n hideElement: opts.hideForCapture ?? null,\n onTainted: () => {\n if (!taintedWarning) {\n taintedWarning = document.createElement('div');\n taintedWarning.className = 'it-warning';\n taintedWarning.textContent =\n 'Some content was blocked by browser security. You can still submit without a full screenshot.';\n screenshotArea.appendChild(taintedWarning);\n }\n },\n onFallback: () => {\n if (!opts.widgetOpts.silent) {\n console.info('[InstantTasks Widget] Using html2canvas fallback for screenshot.');\n }\n },\n });\n\n if (result) {\n capturedCanvas = result.canvas;\n\n // Set up background canvas\n backgroundCanvas.width = result.canvas.width;\n backgroundCanvas.height = result.canvas.height;\n const bgCtx = backgroundCanvas.getContext('2d');\n bgCtx?.drawImage(result.canvas, 0, 0);\n\n // Foreground canvas matches dimensions\n foregroundCanvas.width = result.canvas.width;\n foregroundCanvas.height = result.canvas.height;\n\n // Lock the stage to the screenshot's aspect ratio. CSS scales both\n // canvases proportionally, so foreground absolute overlay aligns\n // exactly with background pixels (annotation coords stay correct).\n stage.style.aspectRatio = `${result.canvas.width} / ${result.canvas.height}`;\n\n // Destroy previous annotator if re-capturing\n annotator?.destroy();\n annotator = new Annotator({\n background: backgroundCanvas,\n foreground: foregroundCanvas,\n cssRoot: opts.cssRoot,\n onChange: (cmds) => { annotations = cmds; },\n });\n\n // Tool buttons\n highlightBtn.addEventListener('click', () => {\n annotator?.setTool('highlight');\n highlightBtn.classList.add('active');\n hideBtn.classList.remove('active');\n });\n hideBtn.addEventListener('click', () => {\n annotator?.setTool('hide');\n hideBtn.classList.add('active');\n highlightBtn.classList.remove('active');\n });\n undoBtn.addEventListener('click', () => annotator?.undo());\n clearBtn.addEventListener('click', () => annotator?.clear());\n\n placeholder.style.display = 'none';\n captureBtn.textContent = 'Re-capture';\n screenshotPreview.style.display = '';\n toolbar.style.display = '';\n } else {\n // User cancelled\n captureBtn.textContent = 'Add Screenshot';\n }\n } catch {\n captureBtn.textContent = 'Add Screenshot';\n } finally {\n captureBtn.disabled = false;\n }\n });\n\n // ── Description (required) ─────────────────────────────────────────────────\n const descSection = document.createElement('div');\n descSection.className = 'it-section';\n const descLabel = document.createElement('label');\n descLabel.className = 'it-label';\n descLabel.textContent = 'Description *';\n const descArea = document.createElement('textarea');\n descArea.className = 'it-textarea';\n descArea.placeholder = 'Describe the bug (at least 10 characters)…';\n descArea.rows = 4;\n const descError = document.createElement('div');\n descError.className = 'it-error';\n descSection.appendChild(descLabel);\n descSection.appendChild(descArea);\n descSection.appendChild(descError);\n container.appendChild(descSection);\n\n // ── Optional title ──────────────────────────────────────────────────────────\n const titleSection = document.createElement('div');\n titleSection.className = 'it-section';\n const titleLabel = document.createElement('label');\n titleLabel.className = 'it-label';\n titleLabel.textContent = 'Title (optional)';\n const titleInput = document.createElement('input');\n titleInput.className = 'it-input';\n titleInput.type = 'text';\n titleInput.placeholder = 'Auto-derived from description if blank';\n titleInput.maxLength = 200;\n titleSection.appendChild(titleLabel);\n titleSection.appendChild(titleInput);\n container.appendChild(titleSection);\n\n // ── Optional email ─────────────────────────────────────────────────────────\n let emailInput: HTMLInputElement | null = null;\n if (opts.widgetOpts.collectEmail) {\n const emailSection = document.createElement('div');\n emailSection.className = 'it-section';\n const emailLabel = document.createElement('label');\n emailLabel.className = 'it-label';\n emailLabel.textContent = 'Email (optional)';\n emailInput = document.createElement('input');\n emailInput.className = 'it-input';\n emailInput.type = 'email';\n emailInput.placeholder = 'you@example.com';\n if (opts.widgetOpts.reporter?.email) {\n emailInput.value = opts.widgetOpts.reporter.email;\n }\n emailSection.appendChild(emailLabel);\n emailSection.appendChild(emailInput);\n container.appendChild(emailSection);\n }\n\n // ── Submit error ────────────────────────────────────────────────────────────\n const submitError = document.createElement('div');\n submitError.className = 'it-error';\n container.appendChild(submitError);\n\n // ── Footer ─────────────────────────────────────────────────────────────────\n const footer = document.createElement('div');\n footer.className = 'it-footer';\n\n const brandingEl = document.createElement('a');\n brandingEl.className = 'it-branding';\n brandingEl.href = 'https://tasks.koderlabs.net';\n brandingEl.target = '_blank';\n brandingEl.rel = 'noopener';\n brandingEl.textContent = 'Powered by InstantTasks';\n brandingEl.style.display = opts.showBranding !== false ? '' : 'none';\n\n const actions = document.createElement('div');\n actions.className = 'it-actions';\n\n const cancelBtn = document.createElement('button');\n cancelBtn.className = 'it-btn';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', opts.onCancel);\n\n const submitBtn = document.createElement('button');\n submitBtn.className = 'it-btn it-btn-primary';\n submitBtn.textContent = 'Submit';\n\n actions.appendChild(cancelBtn);\n actions.appendChild(submitBtn);\n footer.appendChild(brandingEl);\n footer.appendChild(actions);\n container.appendChild(footer);\n\n // ── Submit handler ─────────────────────────────────────────────────────────\n submitBtn.addEventListener('click', async () => {\n const desc = descArea.value.trim();\n if (desc.length < 10) {\n descError.textContent = 'Description must be at least 10 characters.';\n descArea.focus();\n return;\n }\n descError.textContent = '';\n submitError.textContent = '';\n\n // Build composite screenshot if we have one\n let screenshotForSubmit: HTMLCanvasElement | undefined;\n if (capturedCanvas && annotator) {\n const out = document.createElement('canvas');\n annotator.composite(out);\n screenshotForSubmit = out;\n } else if (capturedCanvas) {\n screenshotForSubmit = capturedCanvas;\n }\n\n // Derive title\n const derivedTitle = titleInput.value.trim() ||\n (desc.length > 80 ? desc.slice(0, 80) + '…' : desc);\n\n const payload: FormSubmitPayload = {\n title: derivedTitle,\n description: desc,\n email: emailInput?.value.trim() || undefined,\n screenshot: screenshotForSubmit,\n annotations,\n };\n\n submitBtn.disabled = true;\n submitBtn.innerHTML = '<span class=\"it-spinner\"></span>Submitting…';\n\n try {\n const result = await opts.onSubmit(payload);\n // Success state — collapse the modal to a small confirmation card.\n // The annotation modal is 88vw × 88vh; a giant blank space around a\n // checkmark looks broken. Tag the outer modal so CSS can shrink it\n // and replace contents with a compact success block.\n container.innerHTML = '';\n const modalEl = container.closest<HTMLElement>('.it-modal');\n modalEl?.classList.add('it-modal--success');\n\n const successEl = document.createElement('div');\n successEl.className = 'it-success';\n successEl.innerHTML = `\n <div class=\"it-success-icon\">✓</div>\n <div class=\"it-success-title\">Bug reported</div>\n <a class=\"it-success-ticket\" href=\"${result.ticketUrl}\" target=\"_blank\" rel=\"noopener\">${result.ticketKey}</a>\n <div class=\"it-success-hint\">Closing in 4 seconds…</div>\n `;\n container.appendChild(successEl);\n setTimeout(() => opts.onCancel(), 4000);\n } catch (err) {\n submitError.textContent =\n err instanceof Error ? err.message : 'Submission failed. Please try again.';\n submitBtn.disabled = false;\n submitBtn.textContent = 'Submit';\n }\n });\n\n // Pre-fill reporter email if provided\n if (emailInput && opts.widgetOpts.reporter?.email) {\n emailInput.value = opts.widgetOpts.reporter.email;\n }\n\n // Auto-focus description\n setTimeout(() => descArea.focus(), 50);\n\n // Auto-capture: trigger the capture button shortly after mount so the user\n // gets a preview without an extra click. Skipped when `autoCapture:false`.\n // Defer with rAF so the modal is composited before html2canvas starts\n // walking the DOM — otherwise the capture races the modal open animation\n // and grabs a frame with the modal mid-fade-in.\n if (opts.widgetOpts.autoCapture !== false) {\n requestAnimationFrame(() => requestAnimationFrame(() => captureBtn.click()));\n }\n\n return container;\n}\n","/**\n * Widget transport layer.\n *\n * Composes canvas + annotations into a PNG blob, collects metadata,\n * builds a multipart FormData payload, and calls client.send().\n *\n * The event kind is 'bug_report'; screenshots are attached as 'screenshot' file.\n */\n\nimport type { ClientInterface } from '@koderlabs/tasks-sdk';\nimport type { DrawCommand } from './types';\nimport { collectMetadata, formatMetadataBlock } from './metadata';\n\nexport interface TransportPayload {\n title: string;\n description: string;\n email?: string;\n screenshot?: HTMLCanvasElement;\n annotations: DrawCommand[];\n reporter?: { email: string; fullName?: string };\n customData?: Record<string, unknown>;\n captureConsole?: boolean;\n customDataFn?: () => Record<string, unknown> | Promise<Record<string, unknown>>;\n}\n\nexport interface TransportResult {\n ticketKey: string;\n ticketUrl: string;\n}\n\n/**\n * Convert a canvas to a PNG Blob.\n */\nfunction canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) resolve(blob);\n else reject(new Error('Failed to convert canvas to PNG blob'));\n }, 'image/png');\n });\n}\n\n/**\n * Submit a bug report to the InstantTasks SDK ingest endpoint.\n */\nexport async function submitBugReport(\n client: ClientInterface,\n payload: TransportPayload,\n): Promise<TransportResult> {\n // Collect page metadata\n const meta = await collectMetadata(payload.captureConsole, payload.customDataFn as any);\n\n // Append environment block to description\n const fullDescription = payload.description + formatMetadataBlock(meta);\n\n // Build the event object\n const event = {\n kind: 'bug_report' as const,\n ts: new Date().toISOString(),\n url: meta.url,\n userAgent: meta.userAgent,\n viewport: meta.viewport,\n payload: {\n title: payload.title,\n description: fullDescription,\n email: payload.email ?? payload.reporter?.email,\n annotations: payload.annotations,\n reporter: payload.reporter,\n metadata: {\n appVersion: meta.appVersion,\n customData: { ...meta.customData, ...payload.customData },\n consoleTail: meta.consoleTail,\n },\n },\n };\n\n // Build attachments map if screenshot present.\n // Note: annotations are NOT sent as a separate file — they ride inline in\n // event.payload.annotations above. The API's FileInterceptor only accepts\n // the `screenshot` field (any other file field → 400 \"Unexpected field\").\n const attachments = new Map<string, Blob>();\n if (payload.screenshot) {\n try {\n const pngBlob = await canvasToBlob(payload.screenshot);\n attachments.set('screenshot', pngBlob);\n } catch {\n // Non-fatal — proceed without screenshot\n }\n }\n\n const result = await client.send(event as any, attachments.size > 0 ? attachments : undefined);\n\n const ticketKey = result.ticketKey ?? 'unknown';\n const baseUrl = client.options.endpoint;\n const ticketUrl = `${baseUrl}/tickets/${ticketKey}`;\n\n return { ticketKey, ticketUrl };\n}\n","/**\n * @koderlabs/tasks-sdk-web-reporter\n *\n * Browser in-app bug-reporter integration for the InstantTasks SDK.\n * `reporterIntegration(opts)` (alias: `widgetIntegration` for back-compat).\n *\n * Usage:\n * import { init } from '@koderlabs/tasks-sdk';\n * import { reporterIntegration } from '@koderlabs/tasks-sdk-web-reporter';\n *\n * const client = init({\n * projectId: 'FE',\n * accessKey: 'sk_live_…',\n * integrations: [reporterIntegration({ hotkey: 'ctrl+shift+i' })],\n * });\n */\n\nimport type { Integration, ClientInterface } from '@koderlabs/tasks-sdk';\nimport { registerHotkey } from './hotkey';\nimport { ModalShell } from './modal/shell';\nimport { buildFormElement } from './modal/form';\nimport { submitBugReport } from './transport';\nimport type { WidgetOptions, WidgetApi, WidgetEventName, WidgetEvent } from './types';\n\nexport type { WidgetOptions, WidgetApi, WidgetEventName, WidgetEvent };\nexport type { DrawCommand } from './types';\n\n// Re-export utilities for advanced use\nexport { isNativeCaptureSupported } from './capture/support';\nexport { parseHotkey, registerHotkey } from './hotkey';\nexport { collectMetadata, formatMetadataBlock, patchConsole } from './metadata';\n\ntype Listener = (e: WidgetEvent) => void;\n\nclass WidgetIntegration implements Integration {\n readonly name = 'widget';\n\n private opts: WidgetOptions;\n /** Caller-supplied options, before defaults were applied. Used to decide\n * which fields can be overwritten by server-side project config. */\n private _initialOpts: WidgetOptions;\n private client: ClientInterface | null = null;\n private shell: ModalShell | null = null;\n private fabBtn: HTMLButtonElement | null = null;\n /** Outer shadow-host element for the FAB. Tracked separately from the\n * button so capture flows can hide the *entire* widget chrome (not just\n * the modal) from screenshots. */\n private fabHost: HTMLElement | null = null;\n private _visible = false;\n private _reporter: { email: string; fullName?: string } | undefined;\n private _customData: Record<string, unknown> = {};\n /** Reserved for upcoming network capture filters (Phase I).\n * Public so the field stays type-checked and isn't tree-shaken; safe to\n * read but currently has no effect. */\n public networkSettings: { excludedKeys?: string[]; excludedDomains?: string[] } = {};\n private listeners = new Map<WidgetEventName, Listener[]>();\n private cleanupHotkey: (() => void) = () => {};\n private cleanupConsole: (() => void) = () => {};\n\n constructor(opts: WidgetOptions) {\n // Defaults — `useNativeScreenshot:true` for pixel-perfect captures\n // (one-time-per-session browser permission, vs html2canvas which can\n // miss canvas/iframe/WebGL content). `autoCapture:true` snaps a shot\n // the moment the form opens so the user lands on an annotate-ready\n // preview without an extra click.\n this._initialOpts = { ...opts };\n this.opts = { hotkey: 'mod+shift+b', autoInject: true, useNativeScreenshot: true, autoCapture: true, showBranding: true, ...opts };\n this._reporter = opts.reporter;\n this._customData = { ...opts.customData };\n }\n\n setup(client: ClientInterface): void {\n this.client = client;\n\n // Optionally patch console for ring buffer capture\n if ((this.opts as any).captureConsole) {\n // Dynamic import used for optional feature — ESM compatible\n import('./metadata').then(({ patchConsole }) => {\n this.cleanupConsole = patchConsole();\n }).catch(() => {});\n }\n\n // Fetch project's sdkConfig (hotkey, showFab, enabled, …) from the API\n // BEFORE registering the hotkey / injecting the FAB. Server config wins\n // unless the caller passed an explicit override at integration init.\n //\n // The fetch is fire-and-forget — if it fails (offline, server down,\n // invalid key) we still register with the local defaults so the widget\n // never silently disappears. Explicit options always win: when\n // dogfooding the caller can pin a value by passing it to\n // `widgetIntegration({ hotkey: '...' })` — the network fetch won't\n // overwrite it.\n void this._applyRemoteConfig(client).finally(() => this._wireRuntime());\n }\n\n /**\n * GET /sdk/v1/config — uses the SDK's own configured endpoint + access\n * key (the client already has both). Merges into this.opts only for\n * fields the caller didn't explicitly set.\n */\n private async _applyRemoteConfig(client: ClientInterface): Promise<void> {\n try {\n const endpoint = client.options.endpoint?.replace(/\\/+$/, '');\n const accessKey = client.options.accessKey;\n const projectId = client.options.projectId;\n if (!endpoint || !accessKey || !projectId) return;\n\n const res = await fetch(`${endpoint}/api/v1/sdk/v1/config`, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${accessKey}`,\n 'X-Project-Id': projectId,\n },\n });\n if (!res.ok) return;\n const body = await res.json().catch(() => null) as\n | { sdkConfig?: Record<string, unknown> }\n | null;\n const cfg = body?.sdkConfig;\n if (!cfg) return;\n\n // Merge — only fill in fields the integrator did NOT explicitly set.\n // Detection: compare against the original opts passed to the\n // factory (this._initialOpts), not the merged this.opts which\n // already contains defaults.\n const init = this._initialOpts;\n if (init.hotkey === undefined && typeof cfg.hotkey === 'string') {\n this.opts.hotkey = cfg.hotkey;\n }\n if (init.autoInject === undefined && typeof cfg.showFab === 'boolean') {\n this.opts.autoInject = cfg.showFab;\n }\n // `enabled:false` is a hard kill switch — overrides any caller intent.\n if (cfg.enabled === false) {\n this.opts.hotkey = false;\n this.opts.autoInject = false;\n }\n } catch {\n // Network / parse error — keep local defaults. Never block UX.\n }\n }\n\n /** Wires hotkey + FAB + debug surface. Called after _applyRemoteConfig. */\n private _wireRuntime(): void {\n // Register hotkey\n this.cleanupHotkey = registerHotkey(this.opts.hotkey, () => this.show());\n\n // Auto-inject FAB button\n if (this.opts.autoInject) {\n this._injectFab();\n }\n\n // Optional: expose imperative API on window for DevTools debugging.\n // Default: ON in non-production, OFF in production — any 3rd-party script\n // on the page could otherwise call `window.InstantTasks.show()` and force\n // open a reporting widget on real users.\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n const isProd = proc?.env?.NODE_ENV === 'production';\n const exposeGlobal = this.opts.exposeGlobal ?? !isProd;\n if (exposeGlobal) {\n try {\n const w = window as unknown as { InstantTasks?: { show: () => void; hotkey?: string | false | undefined } };\n w.InstantTasks = {\n show: () => this.show(),\n hotkey: this.opts.hotkey,\n };\n if (!this.opts.silent) {\n console.info(`[InstantTasks Widget] ready. Hotkey: ${this.opts.hotkey}. Type \\`InstantTasks.show()\\` in DevTools to open it.`);\n }\n } catch {/* SSR / no window — ignore */}\n } else if (!this.opts.silent) {\n try { console.info(`[InstantTasks Widget] ready. Hotkey: ${this.opts.hotkey}.`); } catch { /* ignore */ }\n }\n\n this._emit({ name: 'load' } as WidgetEvent);\n }\n\n teardown(): void {\n this.cleanupHotkey();\n this.cleanupConsole();\n this.shell?.destroy();\n this.shell = null;\n if (this.fabBtn?.parentNode) this.fabBtn.parentNode.removeChild(this.fabBtn);\n this.fabBtn = null;\n this._visible = false;\n }\n\n // ── WidgetApi methods ──────────────────────────────────────────────────────\n\n show(): void {\n if (this._visible) return;\n if (!this.client) return;\n this._visible = true;\n this._openModal();\n this._emit({ name: 'show' } as WidgetEvent);\n }\n\n hide(): void {\n if (!this._visible) return;\n this.shell?.close();\n this._visible = false;\n this._emit({ name: 'hide' } as WidgetEvent);\n }\n\n isVisible(): boolean {\n return this._visible;\n }\n\n async capture(mode?: 'fullscreen' | 'advanced'): Promise<void> {\n void mode; // mode selector UI deferred to v1.1\n this.show();\n }\n\n cancelCapture(): void {\n this.hide();\n }\n\n setReporter(info: { email: string; fullName?: string }): void {\n this._reporter = info;\n }\n\n clearReporter(): void {\n this._reporter = undefined;\n }\n\n setCustomData(data?: Record<string, unknown>): void {\n this._customData = { ...this._customData, ...data };\n }\n\n setNetworkRecordingSettings(s: { excludedKeys?: string[]; excludedDomains?: string[] }): void {\n this.networkSettings = s;\n }\n\n on(event: WidgetEventName, listener: Listener): void {\n const arr = this.listeners.get(event) ?? [];\n arr.push(listener);\n this.listeners.set(event, arr);\n }\n\n off(event: WidgetEventName, listener: Listener): void {\n const arr = this.listeners.get(event) ?? [];\n this.listeners.set(event, arr.filter((l) => l !== listener));\n }\n\n unload(): void {\n this.teardown();\n }\n\n // ── Private ────────────────────────────────────────────────────────────────\n\n private _openModal(): void {\n const shell = new ModalShell({\n onClose: () => {\n this._visible = false;\n this._emit({ name: 'hide' } as WidgetEvent);\n },\n });\n this.shell?.destroy();\n this.shell = shell;\n\n const formEl = buildFormElement({\n widgetOpts: this.opts,\n cssRoot: shell.shadowRoot,\n // Hide modal AND FAB during capture — both live as separate shadow\n // hosts on document.body and would otherwise show in the screenshot.\n hideForCapture: [shell.host, this.fabHost].filter(\n (el): el is HTMLElement => !!el,\n ),\n showBranding: this.opts.showBranding,\n onCancel: () => {\n this._emit({ name: 'feedbackdiscarded' } as WidgetEvent);\n shell.close();\n this._visible = false;\n },\n onSubmit: async (payload) => {\n // feedbackbeforesend hook — allow mutations\n let cancelled = false;\n const mutableValues: Record<string, unknown> = {\n description: payload.description,\n title: payload.title,\n email: payload.email,\n labels: undefined,\n assignee: undefined,\n customFields: undefined,\n priority: undefined,\n issueType: undefined,\n };\n\n const beforeSendListeners = this.listeners.get('feedbackbeforesend') ?? [];\n for (const listener of beforeSendListeners) {\n listener({\n name: 'feedbackbeforesend',\n values: mutableValues as any,\n setValue: (field: string, value: unknown) => {\n const MUTABLE = new Set(['assignee', 'labels', 'customFields', 'priority', 'issueType']);\n if (MUTABLE.has(field)) (mutableValues as Record<string, unknown>)[field] = value;\n },\n cancel: () => { cancelled = true; },\n } as any);\n if (cancelled) break;\n }\n\n if (cancelled) {\n this._emit({ name: 'feedbackdiscarded' } as WidgetEvent);\n shell.close();\n this._visible = false;\n throw new Error('Cancelled by feedbackbeforesend handler');\n }\n\n if (!this.client) throw new Error('Client not initialized');\n\n const result = await submitBugReport(this.client, {\n title: (mutableValues.title as string) ?? payload.title,\n description: (mutableValues.description as string) ?? payload.description,\n email: (mutableValues.email as string | undefined) ?? payload.email,\n screenshot: payload.screenshot,\n annotations: payload.annotations,\n reporter: this._reporter,\n customData: { ...this._customData, ...(mutableValues.customFields as Record<string, unknown> | undefined) },\n });\n\n this._emit({ name: 'feedbacksent', ...result } as WidgetEvent);\n return result;\n },\n });\n\n shell.open(formEl);\n }\n\n private _injectFab(): void {\n // Create shadow host for the FAB so it doesn't bleed into host styles\n const fabHost = document.createElement('div');\n fabHost.setAttribute('data-it-fab', '');\n const shadow = fabHost.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .it-fab {\n position: fixed; bottom: 20px; right: 20px;\n z-index: 2147483646;\n width: 44px; height: 44px; border-radius: 50%;\n background: #4f46e5; color: #fff;\n border: none; cursor: pointer; padding: 0;\n box-shadow: 0 4px 12px rgba(0,0,0,0.18), 0 1px 2px rgba(0,0,0,0.12);\n display: inline-flex;\n align-items: center; justify-content: center;\n transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;\n font-family: system-ui, -apple-system, sans-serif;\n }\n .it-fab:hover {\n transform: translateY(-1px) scale(1.04);\n background: #4338ca;\n box-shadow: 0 8px 20px rgba(0,0,0,0.22);\n }\n .it-fab:focus-visible {\n outline: 2px solid #c7d2fe;\n outline-offset: 2px;\n }\n .it-fab svg { width: 20px; height: 20px; display: block; }\n `;\n\n const fab = document.createElement('button');\n fab.className = 'it-fab';\n fab.setAttribute('aria-label', 'Report a bug');\n fab.setAttribute('title', 'Report a bug');\n // Lucide \"message-square-warning\" — monochrome SVG, no emoji color rendering\n fab.innerHTML =\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">' +\n '<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>' +\n '<line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"11\"/>' +\n '<circle cx=\"12\" cy=\"14.5\" r=\"1\"/>' +\n '</svg>';\n fab.addEventListener('click', () => this.show());\n\n shadow.appendChild(style);\n shadow.appendChild(fab);\n document.body.appendChild(fabHost);\n\n this.fabBtn = fab;\n this.fabHost = fabHost;\n }\n\n private _emit(event: WidgetEvent): void {\n const name = event.name as WidgetEventName;\n const listeners = this.listeners.get(name) ?? [];\n for (const l of listeners) {\n try { l(event); } catch (e) { console.error('[InstantTasks Widget] listener threw', e); }\n }\n }\n}\n\n/**\n * Create an in-app reporter integration for the InstantTasks SDK client.\n *\n * @param opts - Reporter configuration options.\n * @returns An Integration that can be passed to `init({ integrations: [...] })`.\n */\nexport function reporterIntegration(opts: WidgetOptions = {}): Integration & WidgetApi {\n return new WidgetIntegration(opts);\n}\n\n/** @deprecated Renamed to `reporterIntegration`. Will be removed in v1. */\nexport const widgetIntegration = reporterIntegration;\n\n/** Class export for users who prefer `new ReporterIntegration()`. */\nexport { WidgetIntegration as ReporterIntegration, WidgetIntegration };\n\nexport default reporterIntegration;\n"],"mappings":"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","names":["parseHotkey","raw","isMac","navigator","test","platform","parts","toLowerCase","split","map","p","trim","modifiers","Set","key","part","add","includes","ctrl","has","meta","alt","shift","matchesHotkey","e","parsed","ctrlKey","metaKey","altKey","shiftKey","isTypingTarget","target","tag","tagName","isContentEditable","ceProp","contentEditable","ce","getAttribute","registerHotkey","hotkeyStr","handler","window","hasModifier","listener","ke","preventDefault","stopPropagation","addEventListener","removeEventListener","WIDGET_STYLES","getCspNonce","document","meta","querySelector","v","getAttribute","length","ModalShell","host","shadow","_isOpen","onCloseCb","backdropEl","modalEl","contentSlot","_escListener","opts","onClose","createElement","setAttribute","attachShadow","mode","styleEl","textContent","WIDGET_STYLES","nonce","appendChild","shadowRoot","isOpen","modalElement","open","content","_teardown","body","backdrop","className","addEventListener","e","target","stopPropagation","modal","key","close","window","focus","destroy","parentNode","removeChild","removeEventListener","contains","AnnotationTools","_commands","_activeTool","_onChange","onChange","activeTool","commands","setTool","mode","_notify","toggleTool","addCommand","cmd","undo","length","slice","removeAt","index","filter","_","i","clear","getState","ACCENT_VAR","ACCENT_DEFAULT","getAccentColor","root","el","ShadowRoot","host","getComputedStyle","getPropertyValue","trim","paintForeground","foreground","commands","accent","ctx","getContext","W","width","H","height","clearRect","highlights","filter","c","type","hides","length","save","fillStyle","fillRect","globalCompositeOperation","cmd","rx","x","ry","y","rw","w","rh","h","restore","strokeStyle","lineWidth","strokeRect","compositeCanvases","background","output","drawImage","Annotator","tools","background","foreground","cssRoot","onChangeCb","dragging","dragStart","cleanupListeners","opts","onChange","AnnotationTools","state","_repaint","commands","_attachMouseListeners","activeTool","setTool","mode","toggleTool","undo","clear","removeAt","i","composite","output","compositeCanvases","destroy","fn","accent","getAccentColor","paintForeground","_normalize","px","py","W","width","H","height","nx","Math","max","min","ny","_canvasPos","e","rect","getBoundingClientRect","scaleX","scaleY","x","clientX","left","y","clientY","top","fg","onMouseDown","button","onMouseMove","current","preview","_buildCommand","onMouseUp","end","cmd","abs","w","h","addCommand","_normalizeCommand","addEventListener","push","removeEventListener","start","type","clamp","v","isNativeCaptureSupported","test","navigator","userAgent","maxTouchPoints","isSecureContext","mediaDevices","getDisplayMedia","nativeCapture","opts","dpi","window","devicePixelRatio","hiddenList","Array","isArray","hideElement","filter","el","prev","map","display","style","visibility","restore","stream","navigator","mediaDevices","getDisplayMedia","video","width","innerWidth","height","innerHeight","audio","monitorTypeSurfaces","preferCurrentTab","selfBrowserSurface","surfaceSwitching","err","document","createElement","srcObject","muted","Promise","resolve","reject","onloadedmetadata","onerror","Error","play","catch","r","requestAnimationFrame","canvas","videoWidth","videoHeight","ctx","getContext","drawImage","track","getTracks","stop","fallbackCapture","onTainted","opts","html2canvas","mod","default","importErr","Error","hiddenList","Array","isArray","hideElement","filter","el","prev","map","display","style","visibility","restore","tainted","canvas","document","body","allowTaint","useCORS","logging","scale","window","devicePixelRatio","err","DOMException","name","catch","blank","createElement","width","innerWidth","height","innerHeight","capture","opts","useNative","useNativeScreenshot","isNativeCaptureSupported","result","nativeCapture","hideElement","method","err","DOMException","name","onFallback","fallbackCapture","onTainted","canvas","dpi","window","devicePixelRatio","tainted","buildFormElement","opts","container","document","createElement","header","className","title","textContent","closeBtn","setAttribute","addEventListener","onCancel","appendChild","capturedCanvas","annotator","annotations","screenshotArea","placeholder","captureBtn","taintedWarning","screenshotPreview","style","display","stage","backgroundCanvas","foregroundCanvas","toolbar","highlightBtn","hideBtn","undoBtn","clearBtn","disabled","result","capture","useNativeScreenshot","widgetOpts","hideElement","hideForCapture","onTainted","onFallback","silent","console","info","canvas","width","height","bgCtx","getContext","drawImage","aspectRatio","destroy","Annotator","background","foreground","cssRoot","onChange","cmds","setTool","classList","add","remove","undo","clear","descSection","descLabel","descArea","rows","descError","titleSection","titleLabel","titleInput","type","maxLength","emailInput","collectEmail","emailSection","emailLabel","reporter","email","value","submitError","footer","brandingEl","href","target","rel","showBranding","actions","cancelBtn","submitBtn","desc","trim","length","focus","screenshotForSubmit","out","composite","derivedTitle","slice","payload","description","undefined","screenshot","innerHTML","onSubmit","modalEl","closest","successEl","ticketUrl","ticketKey","setTimeout","err","Error","message","autoCapture","requestAnimationFrame","click","canvasToBlob","canvas","Promise","resolve","reject","toBlob","blob","Error","submitBugReport","client","payload","meta","collectMetadata","captureConsole","customDataFn","fullDescription","description","formatMetadataBlock","event","kind","ts","Date","toISOString","url","userAgent","viewport","title","email","reporter","annotations","metadata","appVersion","customData","consoleTail","attachments","Map","screenshot","pngBlob","set","result","send","size","undefined","ticketKey","baseUrl","options","endpoint","ticketUrl","WidgetIntegration","name","opts","_initialOpts","client","shell","fabBtn","fabHost","_visible","_reporter","_customData","networkSettings","listeners","Map","cleanupHotkey","cleanupConsole","hotkey","autoInject","useNativeScreenshot","autoCapture","showBranding","reporter","customData","setup","captureConsole","then","patchConsole","catch","_applyRemoteConfig","finally","_wireRuntime","endpoint","options","replace","accessKey","projectId","res","fetch","method","headers","Authorization","ok","body","json","cfg","sdkConfig","init","undefined","showFab","enabled","registerHotkey","show","_injectFab","proc","globalThis","process","isProd","env","NODE_ENV","exposeGlobal","w","window","InstantTasks","silent","console","info","_emit","teardown","destroy","parentNode","removeChild","_openModal","hide","close","isVisible","capture","mode","cancelCapture","setReporter","clearReporter","setCustomData","data","setNetworkRecordingSettings","s","on","event","listener","arr","get","push","set","off","filter","l","unload","ModalShell","onClose","formEl","buildFormElement","widgetOpts","cssRoot","shadowRoot","hideForCapture","host","el","onCancel","onSubmit","payload","cancelled","mutableValues","description","title","email","labels","assignee","customFields","priority","issueType","beforeSendListeners","values","setValue","field","value","MUTABLE","Set","has","cancel","Error","result","submitBugReport","screenshot","annotations","open","document","createElement","setAttribute","shadow","attachShadow","style","textContent","fab","className","innerHTML","addEventListener","appendChild","e","error","reporterIntegration","widgetIntegration","reporterIntegration"]}
1
+ {"version":3,"sources":["../src/hotkey.ts","../src/modal/styles.ts","../src/modal/shell.ts","../src/annotator/tools.ts","../src/annotator/draw.ts","../src/annotator/index.ts","../src/capture/support.ts","../src/capture/native.ts","../src/capture/fallback.ts","../src/capture/index.ts","../src/modal/form.ts","../src/transport.ts","../src/index.ts"],"sourcesContent":["/**\n * Hotkey parser and listener factory.\n *\n * Parses strings like 'ctrl+shift+i', 'meta+shift+i'.\n * Modifiers: ctrl, meta, alt, shift (order-insensitive).\n * Ignores keypresses when the focused element is an input, textarea,\n * or any contenteditable element (to avoid interfering with user typing).\n */\n\nexport interface ParsedHotkey {\n ctrl: boolean;\n meta: boolean;\n alt: boolean;\n shift: boolean;\n key: string; // lowercase key name, e.g. 'i'\n}\n\n/**\n * Parse a hotkey string into a structured predicate.\n * Returns null for invalid or falsy input.\n */\nexport function parseHotkey(raw: string | false | undefined): ParsedHotkey | null {\n if (!raw) return null;\n\n // `mod` resolves to Cmd on macOS, Ctrl elsewhere. Sniff once so saved configs\n // like `mod+shift+b` work cross-OS without rewriting.\n const isMac =\n typeof navigator !== 'undefined' &&\n /Mac|iPhone|iPad|iPod/i.test(navigator.platform ?? '');\n\n const parts = raw.toLowerCase().split('+').map((p) => p.trim());\n const modifiers = new Set<string>();\n let key = '';\n\n for (const part of parts) {\n if (part === 'mod') {\n modifiers.add(isMac ? 'meta' : 'ctrl');\n } else if (['ctrl', 'control'].includes(part)) {\n modifiers.add('ctrl');\n } else if (['meta', 'cmd', 'command'].includes(part)) {\n modifiers.add('meta');\n } else if (['alt', 'option', 'opt'].includes(part)) {\n modifiers.add('alt');\n } else if (part === 'shift') {\n modifiers.add('shift');\n } else {\n // Last non-modifier token is the key\n key = part;\n }\n }\n\n if (!key) return null;\n\n return {\n ctrl: modifiers.has('ctrl'),\n meta: modifiers.has('meta'),\n alt: modifiers.has('alt'),\n shift: modifiers.has('shift'),\n key,\n };\n}\n\n/**\n * Returns true if the keyboard event matches the parsed hotkey.\n */\nexport function matchesHotkey(e: KeyboardEvent, parsed: ParsedHotkey): boolean {\n return (\n e.ctrlKey === parsed.ctrl &&\n e.metaKey === parsed.meta &&\n e.altKey === parsed.alt &&\n e.shiftKey === parsed.shift &&\n e.key.toLowerCase() === parsed.key\n );\n}\n\n/**\n * Returns true if the event target should suppress hotkey handling\n * (user is typing in an input, textarea, or contenteditable).\n */\nexport function isTypingTarget(e: KeyboardEvent): boolean {\n const target = e.target as HTMLElement | null;\n if (!target) return false;\n const tag = target.tagName?.toLowerCase();\n if (tag === 'input' || tag === 'textarea' || tag === 'select') return true;\n // Check both the DOM property (isContentEditable) and the attribute. jsdom\n // does not always set `isContentEditable` when the attribute is assigned via\n // `el.contentEditable = 'true'`, so we fall back to the attribute string.\n if (target.isContentEditable) return true;\n // Fallback: check the `contentEditable` property and the raw attribute.\n // jsdom does not always wire `isContentEditable` to attribute changes.\n const ceProp = (target as HTMLElement & { contentEditable?: string }).contentEditable;\n if (ceProp === 'true' || ceProp === 'plaintext-only') return true;\n const ce = target.getAttribute?.('contenteditable');\n if (ce === '' || ce === 'true' || ce === 'plaintext-only') return true;\n return false;\n}\n\n/**\n * Register a keydown listener for the given hotkey string.\n * Returns a cleanup function to remove the listener.\n *\n * @param hotkeyStr - e.g. 'ctrl+shift+i' or false to disable.\n * @param handler - Called when the hotkey fires outside typing targets.\n * @param target - Element to attach to (defaults to window).\n */\nexport function registerHotkey(\n hotkeyStr: string | false | undefined,\n handler: () => void,\n target: EventTarget = window,\n): () => void {\n const parsed = parseHotkey(hotkeyStr);\n if (!parsed) return () => {}; // noop cleanup\n\n // Modifier-bearing chords (Ctrl/Cmd/Alt + something) are never produced by\n // normal typing — register them in CAPTURE phase and skip the \"is the user\n // typing?\" check. That way a chord like Cmd+Shift+B fires even when focus\n // sits in a text input or a TipTap editor (contenteditable).\n const hasModifier = parsed.ctrl || parsed.meta || parsed.alt;\n\n const listener = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (!hasModifier && isTypingTarget(ke)) return;\n if (matchesHotkey(ke, parsed)) {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }\n };\n\n // Capture-phase listener — runs BEFORE bubble-phase listeners on inputs\n // (e.g. character composition in TipTap) so we win the race.\n target.addEventListener('keydown', listener, true);\n return () => target.removeEventListener('keydown', listener, true);\n}\n","/**\n * Inlined CSS string for the widget modal.\n *\n * CSS vars override-able by the host page on the shadow root:\n * --accent-background highlight rect color (default: #ef4444)\n * --foreground text color (default: #111827)\n * --background modal background (default: #ffffff)\n * --border-color borders (default: #e5e7eb)\n * --z-index modal z-index (default: 2147483647)\n * --font-family (default: system-ui, sans-serif)\n */\nexport const WIDGET_STYLES = `\n :host {\n --accent-background: #ef4444;\n --foreground: #111827;\n --background: #ffffff;\n --border-color: #e5e7eb;\n --z-index: 2147483647;\n --font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n all: initial;\n font-family: var(--font-family);\n color: var(--foreground);\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n }\n\n .it-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.35);\n z-index: var(--z-index);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .it-modal {\n background: var(--background);\n border-radius: 12px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.25);\n /* Big enough to annotate a screenshot comfortably without dominating\n the entire viewport. Cap so it doesn't get unwieldy on 4K monitors. */\n width: min(1280px, 88vw);\n height: min(900px, 88vh);\n max-width: 88vw;\n max-height: 88vh;\n overflow-y: auto;\n padding: 24px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n position: relative;\n font-family: var(--font-family);\n color: var(--foreground);\n }\n\n .it-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n\n .it-title {\n font-size: 16px;\n font-weight: 600;\n margin: 0;\n }\n\n .it-close-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--foreground);\n opacity: 0.6;\n padding: 4px;\n border-radius: 6px;\n line-height: 1;\n font-size: 18px;\n transition: opacity 0.15s;\n }\n .it-close-btn:hover { opacity: 1; }\n\n .it-section { display: flex; flex-direction: column; gap: 6px; }\n\n .it-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--foreground);\n opacity: 0.8;\n }\n\n .it-textarea, .it-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--border-color);\n border-radius: 8px;\n font-size: 14px;\n font-family: var(--font-family);\n color: var(--foreground);\n background: var(--background);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n .it-textarea:focus, .it-input:focus {\n border-color: var(--accent-background);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-background) 20%, transparent);\n }\n\n .it-textarea { min-height: 100px; }\n\n .it-error {\n font-size: 12px;\n color: var(--accent-background);\n min-height: 16px;\n }\n\n .it-screenshot-area {\n border: 2px dashed var(--border-color);\n border-radius: 8px;\n padding: 12px;\n text-align: center;\n background: #f9fafb;\n /* Let the screenshot panel grow to fill the modal — description sits\n below and keeps its natural size. */\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .it-screenshot-preview {\n position: relative;\n width: 100%;\n flex: 1 1 auto;\n min-height: 0;\n overflow: hidden;\n border-radius: 6px;\n /* Center the screenshot vertically so smaller captures aren't pinned\n to the top of a tall panel. */\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n /* Stage = aspect-ratio-locked wrapper around bg + fg canvases.\n Sized to fit the preview pane while preserving the screenshot's\n aspect ratio — keeps fg overlay aligned with bg pixel-for-pixel. */\n .it-screenshot-stage {\n position: relative;\n max-width: 100%;\n max-height: 100%;\n /* Default ratio prevents 0-height collapse before the first capture */\n aspect-ratio: 16 / 10;\n /* Lock width to the smaller of (parent width) or (parent height × ratio).\n Browsers honor aspect-ratio for one axis only when the other is auto. */\n width: 100%;\n height: auto;\n }\n\n .it-background-canvas {\n width: 100%;\n height: 100%;\n display: block;\n border-radius: 6px;\n }\n\n .it-foreground-canvas {\n position: absolute;\n top: 0; left: 0;\n width: 100% !important;\n height: 100% !important;\n cursor: crosshair;\n }\n\n .it-screenshot-placeholder {\n color: var(--foreground);\n opacity: 0.5;\n font-size: 13px;\n }\n\n .it-toolbar {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n margin-top: 8px;\n }\n\n .it-btn {\n padding: 7px 14px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border: 1px solid var(--border-color);\n background: var(--background);\n color: var(--foreground);\n transition: background 0.15s, border-color 0.15s;\n font-family: var(--font-family);\n }\n .it-btn:hover { background: #f3f4f6; }\n\n .it-btn-primary {\n background: var(--accent-background);\n color: #fff;\n border-color: var(--accent-background);\n }\n .it-btn-primary:hover { filter: brightness(0.9); background: var(--accent-background); }\n .it-btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }\n\n .it-btn-tool.active {\n background: color-mix(in srgb, var(--accent-background) 15%, var(--background));\n border-color: var(--accent-background);\n color: var(--accent-background);\n }\n\n .it-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n\n .it-branding {\n font-size: 11px;\n color: var(--foreground);\n opacity: 0.4;\n text-decoration: none;\n }\n .it-branding:hover { opacity: 0.7; }\n\n .it-actions {\n display: flex;\n gap: 8px;\n }\n\n .it-spinner {\n display: inline-block;\n width: 14px; height: 14px;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: it-spin 0.7s linear infinite;\n vertical-align: middle;\n margin-right: 6px;\n }\n @keyframes it-spin { to { transform: rotate(360deg); } }\n\n /* Modal collapses to a compact confirmation card after submit succeeds.\n Overrides the wide annotation-mode sizing without re-mounting. */\n .it-modal.it-modal--success {\n width: min(420px, 92vw) !important;\n height: auto !important;\n max-height: 80vh !important;\n }\n\n .it-success {\n text-align: center;\n padding: 16px 8px 8px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n }\n\n .it-success-icon {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: #dcfce7;\n color: #16a34a;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n font-weight: 700;\n line-height: 1;\n box-shadow: 0 0 0 6px rgba(22, 163, 74, 0.08);\n }\n\n .it-success-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--foreground);\n }\n\n .it-success-ticket {\n font-size: 20px;\n font-weight: 700;\n color: var(--accent-background);\n text-decoration: none;\n letter-spacing: 0.02em;\n }\n .it-success-ticket:hover { text-decoration: underline; }\n\n .it-success-hint {\n font-size: 12px;\n color: var(--foreground);\n opacity: 0.55;\n margin-top: 4px;\n }\n\n .it-warning {\n font-size: 12px;\n color: #d97706;\n background: #fef3c7;\n border-radius: 6px;\n padding: 8px 10px;\n }\n\n .it-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: calc(var(--z-index) - 1);\n width: 48px; height: 48px;\n border-radius: 50%;\n background: var(--accent-background);\n color: #fff;\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0,0,0,0.2);\n font-size: 22px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.15s, box-shadow 0.15s;\n }\n .it-fab:hover {\n transform: scale(1.1);\n box-shadow: 0 6px 20px rgba(0,0,0,0.3);\n }\n`;\n","/**\n * Shadow DOM modal shell.\n *\n * Rules:\n * - ESC key closes the modal.\n * - Backdrop click does NOT close (prevents accidental data loss).\n * - Only one shell instance per host element at a time.\n */\n\nimport { WIDGET_STYLES } from './styles';\n\n/**\n * Read the page's CSP nonce from `<meta name=\"csp-nonce\" content=\"...\">`.\n * When present, it is applied to inline `<style>` / `<script>` elements\n * the widget creates so the host CSP doesn't block them. Returns `null`\n * when no meta tag is present (no-op — relies on `style-src 'self'` or\n * shadow-DOM exemption).\n */\nexport function getCspNonce(): string | null {\n if (typeof document === 'undefined') return null;\n const meta = document.querySelector('meta[name=\"csp-nonce\"]');\n const v = meta?.getAttribute('content');\n return v && v.length > 0 ? v : null;\n}\n\nexport interface ShellOptions {\n /** Called when the user closes the modal (ESC or Cancel button). */\n onClose?: () => void;\n}\n\nexport class ModalShell {\n /** Outer host appended to document.body — exposed so callers can hide it\n * from native screenshot capture without leaking the shadow DOM. */\n public readonly host: HTMLElement;\n private shadow: ShadowRoot;\n private _isOpen = false;\n private onCloseCb?: () => void;\n\n // Refs\n private backdropEl: HTMLElement | null = null;\n private modalEl: HTMLElement | null = null;\n private contentSlot: HTMLElement | null = null;\n\n // Cleanup\n private _escListener: ((e: KeyboardEvent) => void) | null = null;\n\n constructor(opts: ShellOptions = {}) {\n this.onCloseCb = opts.onClose;\n this.host = document.createElement('div');\n this.host.setAttribute('data-it-widget', '');\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n // Inject styles — apply CSP nonce if the host page declared one so\n // strict `style-src 'self' 'nonce-...'` policies don't block us.\n const styleEl = document.createElement('style');\n styleEl.textContent = WIDGET_STYLES;\n const nonce = getCspNonce();\n if (nonce) {\n styleEl.setAttribute('nonce', nonce);\n (styleEl as any).nonce = nonce;\n }\n this.shadow.appendChild(styleEl);\n }\n\n get shadowRoot(): ShadowRoot {\n return this.shadow;\n }\n\n get isOpen(): boolean {\n return this._isOpen;\n }\n\n get modalElement(): HTMLElement | null {\n return this.modalEl;\n }\n\n /**\n * Open the modal with the given content element.\n */\n open(content: HTMLElement): void {\n if (this._isOpen) this._teardown();\n\n document.body.appendChild(this.host);\n\n // Backdrop (click does NOT close — spec requirement)\n const backdrop = document.createElement('div');\n backdrop.className = 'it-backdrop';\n // Prevent accidental close on backdrop click\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop) {\n // Do nothing — spec says backdrop click must NOT close\n e.stopPropagation();\n }\n });\n\n const modal = document.createElement('div');\n modal.className = 'it-modal';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n\n this.contentSlot = content;\n modal.appendChild(content);\n backdrop.appendChild(modal);\n this.shadow.appendChild(backdrop);\n\n this.backdropEl = backdrop;\n this.modalEl = modal;\n this._isOpen = true;\n\n // ESC closes\n this._escListener = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && this._isOpen) {\n this.close();\n }\n };\n window.addEventListener('keydown', this._escListener);\n\n // Focus the modal for accessibility\n modal.setAttribute('tabindex', '-1');\n modal.focus();\n }\n\n /** Close and remove the modal. */\n close(): void {\n if (!this._isOpen) return;\n this._teardown();\n this.onCloseCb?.();\n }\n\n /** Destroy completely — remove host from DOM. */\n destroy(): void {\n this._teardown();\n if (this.host.parentNode) this.host.parentNode.removeChild(this.host);\n }\n\n private _teardown(): void {\n if (this._escListener) {\n window.removeEventListener('keydown', this._escListener);\n this._escListener = null;\n }\n if (this.backdropEl && this.shadow.contains(this.backdropEl)) {\n this.shadow.removeChild(this.backdropEl);\n }\n this.backdropEl = null;\n this.modalEl = null;\n this.contentSlot = null;\n this._isOpen = false;\n }\n}\n","/**\n * Annotation tool state management.\n *\n * Manages the list of DrawCommands, active tool, and undo/clear operations.\n * Decoupled from DOM/canvas rendering (that lives in draw.ts and index.ts).\n */\n\nimport type { DrawCommand } from '../types';\n\nexport type ToolMode = 'highlight' | 'hide';\n\nexport interface AnnotationState {\n commands: DrawCommand[];\n activeTool: ToolMode;\n}\n\nexport class AnnotationTools {\n private _commands: DrawCommand[] = [];\n private _activeTool: ToolMode = 'highlight';\n private _onChange?: (state: AnnotationState) => void;\n\n constructor(onChange?: (state: AnnotationState) => void) {\n this._onChange = onChange;\n }\n\n get activeTool(): ToolMode {\n return this._activeTool;\n }\n\n get commands(): Readonly<DrawCommand[]> {\n return this._commands;\n }\n\n /** Switch between highlight and hide tools. */\n setTool(mode: ToolMode): void {\n this._activeTool = mode;\n this._notify();\n }\n\n /** Toggle between the two tools. */\n toggleTool(): void {\n this._activeTool = this._activeTool === 'highlight' ? 'hide' : 'highlight';\n this._notify();\n }\n\n /** Add a new draw command (called when the user finishes drawing a rect). */\n addCommand(cmd: DrawCommand): void {\n this._commands = [...this._commands, cmd];\n this._notify();\n }\n\n /** Remove the last command (undo). */\n undo(): void {\n if (this._commands.length === 0) return;\n this._commands = this._commands.slice(0, -1);\n this._notify();\n }\n\n /** Remove a specific command by index. */\n removeAt(index: number): void {\n this._commands = this._commands.filter((_, i) => i !== index);\n this._notify();\n }\n\n /** Remove all commands. */\n clear(): void {\n this._commands = [];\n this._notify();\n }\n\n /** Get a plain-object snapshot of the current state. */\n getState(): AnnotationState {\n return {\n commands: [...this._commands],\n activeTool: this._activeTool,\n };\n }\n\n private _notify(): void {\n this._onChange?.(this.getState());\n }\n}\n","/**\n * DrawCommand model and paintForeground renderer.\n * Ported from: sentry-javascript/packages/feedback/src/screenshot/components/ScreenshotEditor.tsx\n *\n * Two render modes:\n * 'highlight' — draws a red cutout rectangle over a semi-transparent dim overlay.\n * The cutout appears brighter/clearer; everything else is dimmed.\n * 'hide' — draws an opaque black box (for PII redaction).\n *\n * Three-canvas pipeline:\n * background canvas — raw screenshot frame (drawn once)\n * foreground canvas — dim overlay + annotation rects (redrawn on every change)\n * output canvas — composited result (background + foreground)\n */\n\nimport type { DrawCommand } from '../types';\n\nexport type { DrawCommand };\n\n// CSS var name used for highlight stroke/fill color, falling back to red\nconst ACCENT_VAR = '--accent-background';\nconst ACCENT_DEFAULT = '#ef4444';\n\nfunction getAccentColor(root: HTMLElement | ShadowRoot): string {\n const el = root instanceof ShadowRoot ? root.host as HTMLElement : root;\n return getComputedStyle(el).getPropertyValue(ACCENT_VAR).trim() || ACCENT_DEFAULT;\n}\n\n/**\n * Paint the foreground overlay canvas from a list of DrawCommands.\n *\n * @param foreground - The foreground overlay canvas element.\n * @param commands - List of annotation rectangles (normalized 0..1 coords).\n * @param accent - Highlight color (hex/rgb string).\n */\nexport function paintForeground(\n foreground: HTMLCanvasElement,\n commands: DrawCommand[],\n accent: string = ACCENT_DEFAULT,\n): void {\n const ctx = foreground.getContext('2d');\n if (!ctx) return;\n\n const W = foreground.width;\n const H = foreground.height;\n\n ctx.clearRect(0, 0, W, H);\n\n // Separate commands by type for layered rendering\n const highlights = commands.filter((c) => c.type === 'highlight');\n const hides = commands.filter((c) => c.type === 'hide');\n\n // --- Highlight mode ---\n // 1. Draw a semi-transparent dark overlay over the whole canvas.\n // 2. For each highlight rect, use 'destination-out' to cut a hole — revealing\n // the bright screenshot underneath through the dim overlay.\n if (highlights.length > 0) {\n ctx.save();\n ctx.fillStyle = 'rgba(0, 0, 0, 0.45)';\n ctx.fillRect(0, 0, W, H);\n\n ctx.globalCompositeOperation = 'destination-out';\n for (const cmd of highlights) {\n const rx = cmd.x * W;\n const ry = cmd.y * H;\n const rw = cmd.w * W;\n const rh = cmd.h * H;\n ctx.fillStyle = 'rgba(0,0,0,1)'; // opaque to punch hole\n ctx.fillRect(rx, ry, rw, rh);\n }\n ctx.restore();\n\n // Draw red border around each highlight rect\n ctx.save();\n ctx.strokeStyle = accent;\n ctx.lineWidth = 2;\n for (const cmd of highlights) {\n ctx.strokeRect(cmd.x * W, cmd.y * H, cmd.w * W, cmd.h * H);\n }\n ctx.restore();\n }\n\n // --- Hide mode ---\n // Draw opaque black boxes (PII redaction).\n if (hides.length > 0) {\n ctx.save();\n ctx.fillStyle = '#000000';\n for (const cmd of hides) {\n ctx.fillRect(cmd.x * W, cmd.y * H, cmd.w * W, cmd.h * H);\n }\n ctx.restore();\n }\n}\n\n/**\n * Composite background + foreground into a single output canvas and return it.\n * The caller must set output.width/height to match background dims before calling.\n */\nexport function compositeCanvases(\n background: HTMLCanvasElement,\n foreground: HTMLCanvasElement,\n output: HTMLCanvasElement,\n): void {\n const ctx = output.getContext('2d');\n if (!ctx) return;\n\n output.width = background.width;\n output.height = background.height;\n ctx.clearRect(0, 0, output.width, output.height);\n ctx.drawImage(background, 0, 0);\n ctx.drawImage(foreground, 0, 0);\n}\n\nexport { getAccentColor };\n","/**\n * Annotation canvas overlay.\n *\n * Wires mouse events to AnnotationTools, renders via paintForeground.\n * Normalizes all coordinates to 0..1 against the screenshot image dimensions.\n */\n\nimport { AnnotationTools } from './tools';\nimport { paintForeground, compositeCanvases, getAccentColor } from './draw';\nimport type { DrawCommand } from '../types';\n\nexport interface AnnotatorOptions {\n /** The background canvas showing the raw screenshot. */\n background: HTMLCanvasElement;\n /** Foreground overlay canvas (positioned absolutely over background). */\n foreground: HTMLCanvasElement;\n /** Shadow root or element providing CSS vars (for accent color). */\n cssRoot: HTMLElement | ShadowRoot;\n /** Called whenever the annotation state changes (for re-render triggers). */\n onChange?: (commands: DrawCommand[]) => void;\n}\n\nexport class Annotator {\n private tools: AnnotationTools;\n private background: HTMLCanvasElement;\n private foreground: HTMLCanvasElement;\n private cssRoot: HTMLElement | ShadowRoot;\n private onChangeCb?: (commands: DrawCommand[]) => void;\n\n // In-progress drag state\n private dragging = false;\n private dragStart: { x: number; y: number } | null = null;\n\n // Cleanup for event listeners\n private cleanupListeners: (() => void)[] = [];\n\n constructor(opts: AnnotatorOptions) {\n this.background = opts.background;\n this.foreground = opts.foreground;\n this.cssRoot = opts.cssRoot;\n this.onChangeCb = opts.onChange;\n\n this.tools = new AnnotationTools((state) => {\n this._repaint();\n this.onChangeCb?.(state.commands);\n });\n\n this._attachMouseListeners();\n }\n\n get activeTool() { return this.tools.activeTool; }\n get commands() { return this.tools.commands; }\n\n setTool(mode: 'highlight' | 'hide') { this.tools.setTool(mode); }\n toggleTool() { this.tools.toggleTool(); }\n undo() { this.tools.undo(); }\n clear() { this.tools.clear(); }\n removeAt(i: number) { this.tools.removeAt(i); }\n\n /** Composite background + foreground into an output canvas. */\n composite(output: HTMLCanvasElement): void {\n compositeCanvases(this.background, this.foreground, output);\n }\n\n /** Destroy event listeners. */\n destroy(): void {\n for (const fn of this.cleanupListeners) fn();\n this.cleanupListeners = [];\n }\n\n // ── Private helpers ──────────────────────────────────────────────────────────\n\n private _repaint(): void {\n const accent = getAccentColor(this.cssRoot);\n paintForeground(this.foreground, [...this.tools.commands], accent);\n }\n\n /** Normalize a pixel coordinate within the foreground canvas to 0..1. */\n private _normalize(px: number, py: number): { nx: number; ny: number } {\n const W = this.foreground.width || 1;\n const H = this.foreground.height || 1;\n return {\n nx: Math.max(0, Math.min(1, px / W)),\n ny: Math.max(0, Math.min(1, py / H)),\n };\n }\n\n /**\n * Mouse → internal canvas pixel coordinates.\n *\n * The foreground canvas has a HUGE internal resolution (matches the raw\n * screenshot, e.g. 2880×1800 on retina) but is displayed at a small CSS\n * size in the modal (~400px wide). `clientX - rect.left` returns CSS\n * pixels, so we must scale up to internal pixels — otherwise a 100px CSS\n * drag becomes a 100/2880 ≈ 3.5% rectangle pinned to the top-left.\n */\n private _canvasPos(e: MouseEvent): { x: number; y: number } {\n const rect = this.foreground.getBoundingClientRect();\n const scaleX = rect.width > 0 ? this.foreground.width / rect.width : 1;\n const scaleY = rect.height > 0 ? this.foreground.height / rect.height : 1;\n return {\n x: (e.clientX - rect.left) * scaleX,\n y: (e.clientY - rect.top) * scaleY,\n };\n }\n\n private _attachMouseListeners(): void {\n const fg = this.foreground;\n\n const onMouseDown = (e: MouseEvent) => {\n if (e.button !== 0) return; // left button only\n this.dragging = true;\n this.dragStart = this._canvasPos(e);\n };\n\n const onMouseMove = (e: MouseEvent) => {\n if (!this.dragging || !this.dragStart) return;\n // Show live preview: repaint committed commands + current rect\n const current = this._canvasPos(e);\n const preview = this._buildCommand(this.dragStart, current);\n const accent = getAccentColor(this.cssRoot);\n paintForeground(\n this.foreground,\n [...this.tools.commands, preview],\n accent,\n );\n };\n\n const onMouseUp = (e: MouseEvent) => {\n if (!this.dragging || !this.dragStart) return;\n this.dragging = false;\n const end = this._canvasPos(e);\n const cmd = this._buildCommand(this.dragStart, end);\n // Only commit if the rect has non-trivial size (> 4px in canvas space)\n const W = this.foreground.width || 1;\n const H = this.foreground.height || 1;\n if (Math.abs(cmd.w) * W > 4 && Math.abs(cmd.h) * H > 4) {\n this.tools.addCommand(this._normalizeCommand(cmd));\n } else {\n this._repaint(); // discard tiny rect, repaint cleanly\n }\n this.dragStart = null;\n };\n\n fg.addEventListener('mousedown', onMouseDown);\n fg.addEventListener('mousemove', onMouseMove);\n fg.addEventListener('mouseup', onMouseUp);\n\n this.cleanupListeners.push(\n () => fg.removeEventListener('mousedown', onMouseDown),\n () => fg.removeEventListener('mousemove', onMouseMove),\n () => fg.removeEventListener('mouseup', onMouseUp),\n );\n }\n\n /** Build a raw (pixel-space) DrawCommand from two mouse positions. */\n private _buildCommand(\n start: { x: number; y: number },\n end: { x: number; y: number },\n ): DrawCommand {\n const x = Math.min(start.x, end.x);\n const y = Math.min(start.y, end.y);\n const w = Math.abs(end.x - start.x);\n const h = Math.abs(end.y - start.y);\n const W = this.foreground.width || 1;\n const H = this.foreground.height || 1;\n return {\n type: this.tools.activeTool,\n x: x / W,\n y: y / H,\n w: w / W,\n h: h / H,\n };\n }\n\n /** Ensure a command's coordinates are normalized (clamp to 0..1). */\n private _normalizeCommand(cmd: DrawCommand): DrawCommand {\n const clamp = (v: number) => Math.max(0, Math.min(1, v));\n return {\n type: cmd.type,\n x: clamp(cmd.x),\n y: clamp(cmd.y),\n w: clamp(cmd.w),\n h: clamp(cmd.h),\n };\n }\n}\n","/**\n * Capability detection for native screenshot capture.\n * Ported from: sentry-javascript/packages/feedback/src/util/isScreenshotSupported.ts\n *\n * Returns false on:\n * - Mobile UA (Android, iPhone, iPad via UA, etc.)\n * - iPad-as-Mac (Macintosh UA with maxTouchPoints > 1)\n * - Insecure context (non-HTTPS except localhost)\n * - Missing getDisplayMedia API\n */\nexport function isNativeCaptureSupported(): boolean {\n // Mobile user agents\n if (\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n )\n ) {\n return false;\n }\n\n // iPad-as-Mac: reports Macintosh UA but has touch points\n if (/Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints > 1) {\n return false;\n }\n\n // Require secure context (HTTPS or localhost)\n if (!isSecureContext) {\n return false;\n }\n\n // Require the API to exist\n return typeof navigator.mediaDevices?.getDisplayMedia === 'function';\n}\n","/**\n * Native screenshot capture via getDisplayMedia.\n * Ported from: sentry-javascript/packages/feedback/src/screenshot/components/useTakeScreenshot.tsx\n *\n * Flow:\n * 1. Hides the modal element so it doesn't appear in the screenshot.\n * 2. Calls getDisplayMedia with preferCurrentTab + include self + exclude monitor.\n * 3. Pipes stream into a <video> element, waits for metadata, paints one frame to canvas.\n * 4. Stops all tracks, restores modal visibility.\n */\n\nexport interface NativeCaptureResult {\n canvas: HTMLCanvasElement;\n /** Device pixel ratio used when sizing the canvas */\n dpi: number;\n}\n\nexport interface NativeCaptureOptions {\n /** Element or array of elements to hide during capture (widget modal +\n * FAB host both live separately on document.body). */\n hideElement?: HTMLElement | HTMLElement[] | null;\n}\n\n/**\n * Attempt a native getDisplayMedia capture.\n * Throws if the user cancels (NotAllowedError) or API is unavailable.\n */\nexport async function nativeCapture(\n opts: NativeCaptureOptions = {},\n): Promise<NativeCaptureResult> {\n const dpi = window.devicePixelRatio || 1;\n\n // Hide widget chrome (modal + FAB) before opening the picker. They stay\n // hidden through the picker prompt AND the first video frame paint —\n // restoring earlier means the captured stream includes just-restored\n // elements.\n const hiddenList: HTMLElement[] = Array.isArray(opts.hideElement)\n ? opts.hideElement.filter((el): el is HTMLElement => !!el)\n : opts.hideElement\n ? [opts.hideElement]\n : [];\n const prev = hiddenList.map((el) => ({\n el,\n display: el.style.display,\n visibility: el.style.visibility,\n }));\n for (const el of hiddenList) {\n el.style.visibility = 'hidden';\n el.style.display = 'none';\n }\n\n const restore = () => {\n for (const { el, display, visibility } of prev) {\n el.style.display = display;\n el.style.visibility = visibility;\n }\n };\n\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({\n video: {\n width: window.innerWidth * dpi,\n height: window.innerHeight * dpi,\n },\n audio: false,\n // @ts-expect-error — non-standard constraint flags (Chromium 111+)\n monitorTypeSurfaces: 'exclude',\n preferCurrentTab: true,\n selfBrowserSurface: 'include',\n surfaceSwitching: 'exclude',\n } as DisplayMediaStreamOptions);\n } catch (err) {\n // User cancelled / permission denied. Restore immediately and rethrow.\n restore();\n throw err;\n }\n\n try {\n // Paint first video frame to canvas — must happen while modal is still\n // hidden so the captured frame doesn't include the bug-report dialog.\n const video = document.createElement('video');\n video.srcObject = stream;\n video.muted = true;\n\n await new Promise<void>((resolve, reject) => {\n video.onloadedmetadata = () => resolve();\n video.onerror = () => reject(new Error('Video element error during screenshot'));\n });\n\n // Some browsers need play() before drawing\n await video.play().catch(() => {/* ignore; draw attempt below may still work */});\n\n // Give the compositor one frame to actually present the (modal-less) page,\n // otherwise we sometimes paint a buffered frame that still shows the\n // dialog. Two rAFs is the smallest reliable wait across Chromium/WebKit.\n await new Promise<void>((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));\n\n const canvas = document.createElement('canvas');\n canvas.width = video.videoWidth || window.innerWidth * dpi;\n canvas.height = video.videoHeight || window.innerHeight * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Could not get 2D canvas context for screenshot');\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n\n // Clean up media tracks BEFORE restoring the modal — stopping tracks is\n // synchronous, so we know no further frames will be requested.\n for (const track of stream.getTracks()) track.stop();\n video.srcObject = null;\n\n return { canvas, dpi };\n } finally {\n restore();\n }\n}\n","/**\n * Fallback screenshot via html2canvas.\n *\n * Loaded lazily — only imported when native capture is unavailable or denied.\n * Catches SecurityError (tainted canvas from cross-origin images) and emits\n * a 'tainted_canvas' notification to the caller so the UI can show a warning.\n */\n\nexport interface FallbackCaptureResult {\n canvas: HTMLCanvasElement;\n tainted: boolean; // true = some content was blocked; screenshot may be partial\n}\n\nexport type TaintedCanvasCallback = () => void;\n\nexport interface FallbackCaptureOptions {\n /** Element(s) to hide while html2canvas walks the DOM (widget modal +\n * FAB host both live separately on document.body). */\n hideElement?: HTMLElement | HTMLElement[] | null;\n}\n\n/**\n * Attempt an html2canvas screenshot of document.body.\n *\n * @param onTainted - Called if the canvas is detected as tainted.\n * @param opts.hideElement - Hidden during capture, restored after.\n */\nexport async function fallbackCapture(\n onTainted?: TaintedCanvasCallback,\n opts: FallbackCaptureOptions = {},\n): Promise<FallbackCaptureResult> {\n // Dynamic import so html2canvas is never bundled in the eager chunk\n let html2canvas: typeof import('html2canvas').default;\n try {\n const mod = await import('html2canvas');\n html2canvas = mod.default ?? (mod as any);\n } catch (importErr) {\n throw new Error(\n 'html2canvas is not installed. Install it as a peer dependency or use a browser that supports getDisplayMedia.',\n );\n }\n\n // Hide widget chrome (modal + FAB) so html2canvas doesn't render either\n // into the snapshot. Supports a single element or an array.\n const hiddenList: HTMLElement[] = Array.isArray(opts.hideElement)\n ? opts.hideElement.filter((el): el is HTMLElement => !!el)\n : opts.hideElement\n ? [opts.hideElement]\n : [];\n const prev = hiddenList.map((el) => ({\n el,\n display: el.style.display,\n visibility: el.style.visibility,\n }));\n for (const el of hiddenList) {\n el.style.visibility = 'hidden';\n el.style.display = 'none';\n }\n const restore = () => {\n for (const { el, display, visibility } of prev) {\n el.style.display = display;\n el.style.visibility = visibility;\n }\n };\n\n let tainted = false;\n\n try {\n try {\n const canvas = await html2canvas(document.body, {\n allowTaint: false,\n useCORS: true,\n logging: false,\n scale: window.devicePixelRatio || 1,\n });\n return { canvas, tainted };\n } catch (err) {\n // SecurityError thrown when canvas is tainted by cross-origin content.\n // Retry while modal is still hidden so the partial snapshot is clean.\n if (err instanceof DOMException && err.name === 'SecurityError') {\n tainted = true;\n onTainted?.();\n const canvas = await html2canvas(document.body, {\n allowTaint: true,\n useCORS: false,\n logging: false,\n scale: window.devicePixelRatio || 1,\n }).catch(() => {\n const blank = document.createElement('canvas');\n blank.width = window.innerWidth;\n blank.height = window.innerHeight;\n return blank;\n });\n return { canvas, tainted };\n }\n throw err;\n }\n } finally {\n restore();\n }\n}\n","/**\n * Orchestrate native vs fallback screenshot capture.\n *\n * Decision tree:\n * 1. If useNativeScreenshot=true AND isNativeCaptureSupported() → try nativeCapture().\n * 2. On NotAllowedError (user cancelled) → return null (no screenshot, proceed without).\n * 3. On any other native failure OR useNativeScreenshot=false → fallbackCapture().\n * 4. Return null if both paths fail.\n */\n\nimport { isNativeCaptureSupported } from './support';\nimport { nativeCapture } from './native';\nimport { fallbackCapture } from './fallback';\n\nexport interface CaptureResult {\n canvas: HTMLCanvasElement;\n dpi: number;\n method: 'native' | 'fallback';\n tainted?: boolean;\n}\n\nexport interface CaptureOptions {\n useNativeScreenshot?: boolean;\n /** Single element OR an array — all are hidden through capture + paint\n * and restored in finally. Used to make sure neither the bug-report\n * modal nor the FAB shows up in the screenshot. */\n hideElement?: HTMLElement | HTMLElement[] | null;\n onTainted?: () => void;\n onFallback?: () => void;\n}\n\n/**\n * Perform screenshot capture using the best available method.\n * Returns null if the user cancelled (NotAllowedError on native path).\n */\nexport async function capture(opts: CaptureOptions = {}): Promise<CaptureResult | null> {\n const useNative = opts.useNativeScreenshot !== false; // default true\n\n if (useNative && isNativeCaptureSupported()) {\n try {\n const result = await nativeCapture({ hideElement: opts.hideElement });\n return { ...result, method: 'native' };\n } catch (err) {\n if (err instanceof DOMException && err.name === 'NotAllowedError') {\n // User explicitly cancelled the picker — no screenshot\n return null;\n }\n // Any other error (e.g. NotSupportedError on Firefox) → fall through to fallback\n opts.onFallback?.();\n }\n } else if (useNative) {\n // Native wanted but not supported on this device\n opts.onFallback?.();\n }\n\n // Fallback path — pass hideElement so html2canvas doesn't snapshot the modal\n try {\n const result = await fallbackCapture(opts.onTainted, { hideElement: opts.hideElement });\n return { canvas: result.canvas, dpi: window.devicePixelRatio || 1, method: 'fallback', tainted: result.tainted };\n } catch {\n return null;\n }\n}\n","/**\n * Widget form — description (required, ≥10 chars), optional title, optional email.\n * Handles screenshot capture trigger, annotation toolbar, submit/cancel.\n */\n\nimport { Annotator } from '../annotator/index';\nimport { capture } from '../capture/index';\nimport type { DrawCommand, WidgetOptions } from '../types';\n\nexport interface FormSubmitPayload {\n title: string;\n description: string;\n email?: string;\n screenshot?: HTMLCanvasElement;\n annotations: DrawCommand[];\n}\n\nexport interface FormOptions {\n widgetOpts: WidgetOptions;\n onSubmit: (payload: FormSubmitPayload) => Promise<{ ticketKey: string; ticketUrl: string }>;\n onCancel: () => void;\n /** Shadow root or element for CSS var resolution */\n cssRoot: ShadowRoot | HTMLElement;\n showBranding?: boolean;\n /** Element(s) to hide from screenshot before native capture (modal host\n * + FAB host). Accepts a single element for back-compat. */\n hideForCapture?: HTMLElement | HTMLElement[] | null;\n}\n\nexport function buildFormElement(opts: FormOptions): HTMLElement {\n const container = document.createElement('div');\n\n // ── Header ─────────────────────────────────────────────────────────────────\n const header = document.createElement('div');\n header.className = 'it-header';\n const title = document.createElement('h2');\n title.className = 'it-title';\n title.textContent = 'Report a Bug';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'it-close-btn';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.textContent = '✕';\n closeBtn.addEventListener('click', opts.onCancel);\n header.appendChild(title);\n header.appendChild(closeBtn);\n container.appendChild(header);\n\n // ── Screenshot section ──────────────────────────────────────────────────────\n let capturedCanvas: HTMLCanvasElement | null = null;\n let annotator: Annotator | null = null;\n let annotations: DrawCommand[] = [];\n\n const screenshotArea = document.createElement('div');\n screenshotArea.className = 'it-screenshot-area';\n\n const placeholder = document.createElement('div');\n placeholder.className = 'it-screenshot-placeholder';\n placeholder.textContent = 'No screenshot yet.';\n\n const captureBtn = document.createElement('button');\n captureBtn.className = 'it-btn';\n captureBtn.textContent = 'Add Screenshot';\n\n let taintedWarning: HTMLElement | null = null;\n\n const screenshotPreview = document.createElement('div');\n screenshotPreview.className = 'it-screenshot-preview';\n screenshotPreview.style.display = 'none';\n\n // Background canvas (screenshot) + foreground canvas (annotation overlay)\n // Inner stage matches the screenshot's aspect ratio so the foreground\n // overlay always lines up with the background pixel-for-pixel even when\n // the surrounding preview pane is much larger.\n const stage = document.createElement('div');\n stage.className = 'it-screenshot-stage';\n\n const backgroundCanvas = document.createElement('canvas');\n backgroundCanvas.className = 'it-background-canvas';\n const foregroundCanvas = document.createElement('canvas');\n foregroundCanvas.className = 'it-foreground-canvas';\n\n stage.appendChild(backgroundCanvas);\n stage.appendChild(foregroundCanvas);\n screenshotPreview.appendChild(stage);\n\n const toolbar = document.createElement('div');\n toolbar.className = 'it-toolbar';\n toolbar.style.display = 'none';\n\n const highlightBtn = document.createElement('button');\n highlightBtn.className = 'it-btn it-btn-tool active';\n highlightBtn.textContent = '▭ Highlight';\n\n const hideBtn = document.createElement('button');\n hideBtn.className = 'it-btn it-btn-tool';\n hideBtn.textContent = '■ Hide';\n\n const undoBtn = document.createElement('button');\n undoBtn.className = 'it-btn';\n undoBtn.textContent = '↩ Undo';\n\n const clearBtn = document.createElement('button');\n clearBtn.className = 'it-btn';\n clearBtn.textContent = '✕ Clear';\n\n toolbar.appendChild(highlightBtn);\n toolbar.appendChild(hideBtn);\n toolbar.appendChild(undoBtn);\n toolbar.appendChild(clearBtn);\n\n screenshotArea.appendChild(placeholder);\n screenshotArea.appendChild(captureBtn);\n screenshotArea.appendChild(screenshotPreview);\n screenshotArea.appendChild(toolbar);\n container.appendChild(screenshotArea);\n\n captureBtn.addEventListener('click', async () => {\n captureBtn.disabled = true;\n captureBtn.textContent = 'Capturing…';\n\n try {\n const result = await capture({\n useNativeScreenshot: opts.widgetOpts.useNativeScreenshot,\n hideElement: opts.hideForCapture ?? null,\n onTainted: () => {\n if (!taintedWarning) {\n taintedWarning = document.createElement('div');\n taintedWarning.className = 'it-warning';\n taintedWarning.textContent =\n 'Some content was blocked by browser security. You can still submit without a full screenshot.';\n screenshotArea.appendChild(taintedWarning);\n }\n },\n onFallback: () => {\n if (!opts.widgetOpts.silent) {\n console.info('[InstantTasks Widget] Using html2canvas fallback for screenshot.');\n }\n },\n });\n\n if (result) {\n capturedCanvas = result.canvas;\n\n // Set up background canvas\n backgroundCanvas.width = result.canvas.width;\n backgroundCanvas.height = result.canvas.height;\n const bgCtx = backgroundCanvas.getContext('2d');\n bgCtx?.drawImage(result.canvas, 0, 0);\n\n // Foreground canvas matches dimensions\n foregroundCanvas.width = result.canvas.width;\n foregroundCanvas.height = result.canvas.height;\n\n // Lock the stage to the screenshot's aspect ratio. CSS scales both\n // canvases proportionally, so foreground absolute overlay aligns\n // exactly with background pixels (annotation coords stay correct).\n stage.style.aspectRatio = `${result.canvas.width} / ${result.canvas.height}`;\n\n // Destroy previous annotator if re-capturing\n annotator?.destroy();\n annotator = new Annotator({\n background: backgroundCanvas,\n foreground: foregroundCanvas,\n cssRoot: opts.cssRoot,\n onChange: (cmds) => { annotations = cmds; },\n });\n\n // Tool buttons\n highlightBtn.addEventListener('click', () => {\n annotator?.setTool('highlight');\n highlightBtn.classList.add('active');\n hideBtn.classList.remove('active');\n });\n hideBtn.addEventListener('click', () => {\n annotator?.setTool('hide');\n hideBtn.classList.add('active');\n highlightBtn.classList.remove('active');\n });\n undoBtn.addEventListener('click', () => annotator?.undo());\n clearBtn.addEventListener('click', () => annotator?.clear());\n\n placeholder.style.display = 'none';\n captureBtn.textContent = 'Re-capture';\n screenshotPreview.style.display = '';\n toolbar.style.display = '';\n } else {\n // User cancelled\n captureBtn.textContent = 'Add Screenshot';\n }\n } catch {\n captureBtn.textContent = 'Add Screenshot';\n } finally {\n captureBtn.disabled = false;\n }\n });\n\n // ── Description (required) ─────────────────────────────────────────────────\n const descSection = document.createElement('div');\n descSection.className = 'it-section';\n const descLabel = document.createElement('label');\n descLabel.className = 'it-label';\n descLabel.textContent = 'Description *';\n const descArea = document.createElement('textarea');\n descArea.className = 'it-textarea';\n descArea.placeholder = 'Describe the bug (at least 10 characters)…';\n descArea.rows = 4;\n const descError = document.createElement('div');\n descError.className = 'it-error';\n descSection.appendChild(descLabel);\n descSection.appendChild(descArea);\n descSection.appendChild(descError);\n container.appendChild(descSection);\n\n // ── Optional title ──────────────────────────────────────────────────────────\n const titleSection = document.createElement('div');\n titleSection.className = 'it-section';\n const titleLabel = document.createElement('label');\n titleLabel.className = 'it-label';\n titleLabel.textContent = 'Title (optional)';\n const titleInput = document.createElement('input');\n titleInput.className = 'it-input';\n titleInput.type = 'text';\n titleInput.placeholder = 'Auto-derived from description if blank';\n titleInput.maxLength = 200;\n titleSection.appendChild(titleLabel);\n titleSection.appendChild(titleInput);\n container.appendChild(titleSection);\n\n // ── Optional email ─────────────────────────────────────────────────────────\n let emailInput: HTMLInputElement | null = null;\n if (opts.widgetOpts.collectEmail) {\n const emailSection = document.createElement('div');\n emailSection.className = 'it-section';\n const emailLabel = document.createElement('label');\n emailLabel.className = 'it-label';\n emailLabel.textContent = 'Email (optional)';\n emailInput = document.createElement('input');\n emailInput.className = 'it-input';\n emailInput.type = 'email';\n emailInput.placeholder = 'you@example.com';\n if (opts.widgetOpts.reporter?.email) {\n emailInput.value = opts.widgetOpts.reporter.email;\n }\n emailSection.appendChild(emailLabel);\n emailSection.appendChild(emailInput);\n container.appendChild(emailSection);\n }\n\n // ── Submit error ────────────────────────────────────────────────────────────\n const submitError = document.createElement('div');\n submitError.className = 'it-error';\n container.appendChild(submitError);\n\n // ── Footer ─────────────────────────────────────────────────────────────────\n const footer = document.createElement('div');\n footer.className = 'it-footer';\n\n const brandingEl = document.createElement('a');\n brandingEl.className = 'it-branding';\n brandingEl.href = 'https://tasks.koderlabs.net';\n brandingEl.target = '_blank';\n brandingEl.rel = 'noopener';\n brandingEl.textContent = 'Powered by InstantTasks';\n brandingEl.style.display = opts.showBranding !== false ? '' : 'none';\n\n const actions = document.createElement('div');\n actions.className = 'it-actions';\n\n const cancelBtn = document.createElement('button');\n cancelBtn.className = 'it-btn';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', opts.onCancel);\n\n const submitBtn = document.createElement('button');\n submitBtn.className = 'it-btn it-btn-primary';\n submitBtn.textContent = 'Submit';\n\n actions.appendChild(cancelBtn);\n actions.appendChild(submitBtn);\n footer.appendChild(brandingEl);\n footer.appendChild(actions);\n container.appendChild(footer);\n\n // ── Submit handler ─────────────────────────────────────────────────────────\n submitBtn.addEventListener('click', async () => {\n const desc = descArea.value.trim();\n if (desc.length < 10) {\n descError.textContent = 'Description must be at least 10 characters.';\n descArea.focus();\n return;\n }\n descError.textContent = '';\n submitError.textContent = '';\n\n // Build composite screenshot if we have one\n let screenshotForSubmit: HTMLCanvasElement | undefined;\n if (capturedCanvas && annotator) {\n const out = document.createElement('canvas');\n annotator.composite(out);\n screenshotForSubmit = out;\n } else if (capturedCanvas) {\n screenshotForSubmit = capturedCanvas;\n }\n\n // Derive title\n const derivedTitle = titleInput.value.trim() ||\n (desc.length > 80 ? desc.slice(0, 80) + '…' : desc);\n\n const payload: FormSubmitPayload = {\n title: derivedTitle,\n description: desc,\n email: emailInput?.value.trim() || undefined,\n screenshot: screenshotForSubmit,\n annotations,\n };\n\n submitBtn.disabled = true;\n submitBtn.innerHTML = '<span class=\"it-spinner\"></span>Submitting…';\n\n try {\n const result = await opts.onSubmit(payload);\n // Success state — collapse the modal to a small confirmation card.\n // The annotation modal is 88vw × 88vh; a giant blank space around a\n // checkmark looks broken. Tag the outer modal so CSS can shrink it\n // and replace contents with a compact success block.\n container.innerHTML = '';\n const modalEl = container.closest<HTMLElement>('.it-modal');\n modalEl?.classList.add('it-modal--success');\n\n const successEl = document.createElement('div');\n successEl.className = 'it-success';\n successEl.innerHTML = `\n <div class=\"it-success-icon\">✓</div>\n <div class=\"it-success-title\">Bug reported</div>\n <a class=\"it-success-ticket\" href=\"${result.ticketUrl}\" target=\"_blank\" rel=\"noopener\">${result.ticketKey}</a>\n <div class=\"it-success-hint\">Closing in 4 seconds…</div>\n `;\n container.appendChild(successEl);\n setTimeout(() => opts.onCancel(), 4000);\n } catch (err) {\n submitError.textContent =\n err instanceof Error ? err.message : 'Submission failed. Please try again.';\n submitBtn.disabled = false;\n submitBtn.textContent = 'Submit';\n }\n });\n\n // Pre-fill reporter email if provided\n if (emailInput && opts.widgetOpts.reporter?.email) {\n emailInput.value = opts.widgetOpts.reporter.email;\n }\n\n // Auto-focus description\n setTimeout(() => descArea.focus(), 50);\n\n // Auto-capture: trigger the capture button shortly after mount so the user\n // gets a preview without an extra click. Skipped when `autoCapture:false`.\n // Defer with rAF so the modal is composited before html2canvas starts\n // walking the DOM — otherwise the capture races the modal open animation\n // and grabs a frame with the modal mid-fade-in.\n if (opts.widgetOpts.autoCapture !== false) {\n requestAnimationFrame(() => requestAnimationFrame(() => captureBtn.click()));\n }\n\n return container;\n}\n","/**\n * Widget transport layer.\n *\n * Composes canvas + annotations into a PNG blob, collects metadata,\n * builds a multipart FormData payload, and calls client.send().\n *\n * The event kind is 'bug_report'; screenshots are attached as 'screenshot' file.\n */\n\nimport type { ClientInterface } from '@koderlabs/tasks-sdk';\nimport type { DrawCommand } from './types';\nimport { collectMetadata, formatMetadataBlock } from './metadata';\n\nexport interface TransportPayload {\n title: string;\n description: string;\n email?: string;\n screenshot?: HTMLCanvasElement;\n annotations: DrawCommand[];\n reporter?: { email: string; fullName?: string };\n customData?: Record<string, unknown>;\n captureConsole?: boolean;\n customDataFn?: () => Record<string, unknown> | Promise<Record<string, unknown>>;\n}\n\nexport interface TransportResult {\n ticketKey: string;\n ticketUrl: string;\n}\n\n/**\n * Convert a canvas to a PNG Blob.\n */\nfunction canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) resolve(blob);\n else reject(new Error('Failed to convert canvas to PNG blob'));\n }, 'image/png');\n });\n}\n\n/**\n * Submit a bug report to the InstantTasks SDK ingest endpoint.\n */\nexport async function submitBugReport(\n client: ClientInterface,\n payload: TransportPayload,\n): Promise<TransportResult> {\n // Collect page metadata\n const meta = await collectMetadata(payload.captureConsole, payload.customDataFn as any);\n\n // Append environment block to description\n const fullDescription = payload.description + formatMetadataBlock(meta);\n\n // Build the event object\n const event = {\n kind: 'bug_report' as const,\n ts: new Date().toISOString(),\n url: meta.url,\n userAgent: meta.userAgent,\n viewport: meta.viewport,\n payload: {\n title: payload.title,\n description: fullDescription,\n email: payload.email ?? payload.reporter?.email,\n annotations: payload.annotations,\n reporter: payload.reporter,\n metadata: {\n appVersion: meta.appVersion,\n customData: { ...meta.customData, ...payload.customData },\n consoleTail: meta.consoleTail,\n },\n },\n };\n\n // Build attachments map if screenshot present.\n // Note: annotations are NOT sent as a separate file — they ride inline in\n // event.payload.annotations above. The API's FileInterceptor only accepts\n // the `screenshot` field (any other file field → 400 \"Unexpected field\").\n const attachments = new Map<string, Blob>();\n if (payload.screenshot) {\n try {\n const pngBlob = await canvasToBlob(payload.screenshot);\n attachments.set('screenshot', pngBlob);\n } catch {\n // Non-fatal — proceed without screenshot\n }\n }\n\n const result = await client.send(event as any, attachments.size > 0 ? attachments : undefined);\n\n const ticketKey = result.ticketKey ?? 'unknown';\n const baseUrl = client.options.endpoint;\n const ticketUrl = `${baseUrl}/tickets/${ticketKey}`;\n\n return { ticketKey, ticketUrl };\n}\n","/**\n * @koderlabs/tasks-sdk-web-reporter\n *\n * Browser in-app bug-reporter integration for the InstantTasks SDK.\n * `reporterIntegration(opts)` (alias: `widgetIntegration` for back-compat).\n *\n * Usage:\n * import { init } from '@koderlabs/tasks-sdk';\n * import { reporterIntegration } from '@koderlabs/tasks-sdk-web-reporter';\n *\n * const client = init({\n * projectId: 'FE',\n * accessKey: 'sk_live_…',\n * integrations: [reporterIntegration({ hotkey: 'ctrl+shift+i' })],\n * });\n */\n\nimport type { Integration, ClientInterface } from '@koderlabs/tasks-sdk';\nimport { registerHotkey } from './hotkey';\nimport { ModalShell } from './modal/shell';\nimport { buildFormElement } from './modal/form';\nimport { submitBugReport } from './transport';\nimport type { WidgetOptions, WidgetApi, WidgetEventName, WidgetEvent } from './types';\n\nexport type { WidgetOptions, WidgetApi, WidgetEventName, WidgetEvent };\nexport type { DrawCommand } from './types';\n\n// Re-export utilities for advanced use\nexport { isNativeCaptureSupported } from './capture/support';\nexport { parseHotkey, registerHotkey } from './hotkey';\nexport { collectMetadata, formatMetadataBlock, patchConsole } from './metadata';\n\ntype Listener = (e: WidgetEvent) => void;\n\nclass WidgetIntegration implements Integration {\n readonly name = 'widget';\n\n private opts: WidgetOptions;\n /** Caller-supplied options, before defaults were applied. Used to decide\n * which fields can be overwritten by server-side project config. */\n private _initialOpts: WidgetOptions;\n private client: ClientInterface | null = null;\n private shell: ModalShell | null = null;\n private fabBtn: HTMLButtonElement | null = null;\n /** Outer shadow-host element for the FAB. Tracked separately from the\n * button so capture flows can hide the *entire* widget chrome (not just\n * the modal) from screenshots. */\n private fabHost: HTMLElement | null = null;\n private _visible = false;\n private _reporter: { email: string; fullName?: string } | undefined;\n private _customData: Record<string, unknown> = {};\n /** Reserved for upcoming network capture filters (Phase I).\n * Public so the field stays type-checked and isn't tree-shaken; safe to\n * read but currently has no effect. */\n public networkSettings: { excludedKeys?: string[]; excludedDomains?: string[] } = {};\n private listeners = new Map<WidgetEventName, Listener[]>();\n private cleanupHotkey: (() => void) = () => {};\n private cleanupConsole: (() => void) = () => {};\n\n constructor(opts: WidgetOptions) {\n // Defaults — `useNativeScreenshot:true` for pixel-perfect captures\n // (one-time-per-session browser permission, vs html2canvas which can\n // miss canvas/iframe/WebGL content). `autoCapture:true` snaps a shot\n // the moment the form opens so the user lands on an annotate-ready\n // preview without an extra click.\n this._initialOpts = { ...opts };\n this.opts = { hotkey: 'mod+shift+b', autoInject: true, useNativeScreenshot: true, autoCapture: true, showBranding: true, ...opts };\n this._reporter = opts.reporter;\n this._customData = { ...opts.customData };\n }\n\n setup(client: ClientInterface): void {\n this.client = client;\n\n // Optionally patch console for ring buffer capture\n if ((this.opts as any).captureConsole) {\n // Dynamic import used for optional feature — ESM compatible\n import('./metadata').then(({ patchConsole }) => {\n this.cleanupConsole = patchConsole();\n }).catch(() => {});\n }\n\n // Fetch project's sdkConfig (hotkey, showFab, enabled, …) from the API\n // BEFORE registering the hotkey / injecting the FAB. Server config wins\n // unless the caller passed an explicit override at integration init.\n //\n // The fetch is fire-and-forget — if it fails (offline, server down,\n // invalid key) we still register with the local defaults so the widget\n // never silently disappears. Explicit options always win: when\n // dogfooding the caller can pin a value by passing it to\n // `widgetIntegration({ hotkey: '...' })` — the network fetch won't\n // overwrite it.\n void this._applyRemoteConfig(client).finally(() => this._wireRuntime());\n }\n\n /**\n * GET /sdk/v1/config — uses the SDK's own configured endpoint + access\n * key (the client already has both). Merges into this.opts only for\n * fields the caller didn't explicitly set.\n */\n private async _applyRemoteConfig(client: ClientInterface): Promise<void> {\n try {\n const endpoint = client.options.endpoint?.replace(/\\/+$/, '');\n const accessKey = client.options.accessKey;\n const projectId = client.options.projectId;\n if (!endpoint || !accessKey || !projectId) return;\n\n const res = await fetch(`${endpoint}/api/v1/sdk/v1/config`, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${accessKey}`,\n 'X-Project-Id': projectId,\n },\n });\n if (!res.ok) return;\n const body = await res.json().catch(() => null) as\n | { sdkConfig?: Record<string, unknown> }\n | null;\n const cfg = body?.sdkConfig;\n if (!cfg) return;\n\n // Merge — only fill in fields the integrator did NOT explicitly set.\n // Detection: compare against the original opts passed to the\n // factory (this._initialOpts), not the merged this.opts which\n // already contains defaults.\n const init = this._initialOpts;\n if (init.hotkey === undefined && typeof cfg.hotkey === 'string') {\n this.opts.hotkey = cfg.hotkey;\n }\n if (init.autoInject === undefined && typeof cfg.showFab === 'boolean') {\n this.opts.autoInject = cfg.showFab;\n }\n // `enabled:false` is a hard kill switch — overrides any caller intent.\n if (cfg.enabled === false) {\n this.opts.hotkey = false;\n this.opts.autoInject = false;\n }\n // Mirror the project's reporter-behavior preference. Integrator can\n // still hard-override by passing `requireUser` to the factory.\n if (init.requireUser === undefined && typeof cfg.defaultReporterBehavior === 'string') {\n this.opts.requireUser = cfg.defaultReporterBehavior === 'current_user';\n }\n } catch {\n // Network / parse error — keep local defaults. Never block UX.\n }\n }\n\n /** Wires hotkey + FAB + debug surface. Called after _applyRemoteConfig. */\n private _wireRuntime(): void {\n // Register hotkey\n this.cleanupHotkey = registerHotkey(this.opts.hotkey, () => this.show());\n\n // Auto-inject FAB button\n if (this.opts.autoInject) {\n this._injectFab();\n }\n\n // Optional: expose imperative API on window for DevTools debugging.\n // Default: ON in non-production, OFF in production — any 3rd-party script\n // on the page could otherwise call `window.InstantTasks.show()` and force\n // open a reporting widget on real users.\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n const isProd = proc?.env?.NODE_ENV === 'production';\n const exposeGlobal = this.opts.exposeGlobal ?? !isProd;\n if (exposeGlobal) {\n try {\n const w = window as unknown as { InstantTasks?: { show: () => void; hotkey?: string | false | undefined } };\n w.InstantTasks = {\n show: () => this.show(),\n hotkey: this.opts.hotkey,\n };\n if (!this.opts.silent) {\n console.info(`[InstantTasks Widget] ready. Hotkey: ${this.opts.hotkey}. Type \\`InstantTasks.show()\\` in DevTools to open it.`);\n }\n } catch {/* SSR / no window — ignore */}\n } else if (!this.opts.silent) {\n try { console.info(`[InstantTasks Widget] ready. Hotkey: ${this.opts.hotkey}.`); } catch { /* ignore */ }\n }\n\n this._emit({ name: 'load' } as WidgetEvent);\n }\n\n teardown(): void {\n this.cleanupHotkey();\n this.cleanupConsole();\n this.shell?.destroy();\n this.shell = null;\n if (this.fabBtn?.parentNode) this.fabBtn.parentNode.removeChild(this.fabBtn);\n this.fabBtn = null;\n this._visible = false;\n }\n\n // ── WidgetApi methods ──────────────────────────────────────────────────────\n\n show(): void {\n if (this._visible) return;\n if (!this.client) return;\n this._visible = true;\n if (this.opts.requireUser && !this._hasIdentity()) {\n this._openLoginPrompt();\n } else {\n this._openModal();\n }\n this._emit({ name: 'show' } as WidgetEvent);\n }\n\n /** True when the client carries a logged-in user (id or email present). */\n private _hasIdentity(): boolean {\n const u = this.client?.options.user as { id?: string; email?: string } | undefined;\n return Boolean(u && (u.id || u.email));\n }\n\n /** Build a minimal \"Please sign in\" modal — no form, just a CTA + cancel. */\n private _openLoginPrompt(): void {\n const shell = new ModalShell({\n onClose: () => {\n this._visible = false;\n this._emit({ name: 'hide' } as WidgetEvent);\n },\n });\n this.shell?.destroy();\n this.shell = shell;\n\n const here = typeof window !== 'undefined'\n ? window.location.pathname + window.location.search\n : '/';\n const loginUrl = this.opts.loginUrl\n ?? `/login?next=${encodeURIComponent(here)}`;\n\n const wrapper = document.createElement('div');\n wrapper.style.cssText = 'padding:24px;font-family:system-ui,-apple-system,sans-serif;text-align:center;max-width:340px;';\n wrapper.innerHTML = `\n <div style=\"font-size:32px;margin-bottom:8px\">🔒</div>\n <div style=\"font-size:18px;font-weight:600;color:#111827;margin-bottom:6px\">Sign in to report a bug</div>\n <div style=\"font-size:13px;color:#6b7280;margin-bottom:18px;line-height:1.5\">This project requires reporters to be signed in so bug reports can be linked to your account.</div>\n `;\n\n const signInBtn = document.createElement('button');\n signInBtn.type = 'button';\n signInBtn.textContent = 'Sign in';\n signInBtn.style.cssText = 'width:100%;padding:10px 16px;background:#2563eb;color:#fff;border:0;border-radius:6px;font-size:14px;font-weight:600;cursor:pointer;margin-bottom:8px;';\n signInBtn.addEventListener('click', () => {\n try { window.location.assign(loginUrl); } catch { /* ignore */ }\n });\n\n const cancelBtn = document.createElement('button');\n cancelBtn.type = 'button';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.style.cssText = 'width:100%;padding:10px 16px;background:transparent;color:#6b7280;border:1px solid #e5e7eb;border-radius:6px;font-size:14px;cursor:pointer;';\n cancelBtn.addEventListener('click', () => {\n shell.close();\n this._visible = false;\n this._emit({ name: 'feedbackdiscarded' } as WidgetEvent);\n });\n\n wrapper.appendChild(signInBtn);\n wrapper.appendChild(cancelBtn);\n shell.open(wrapper);\n }\n\n hide(): void {\n if (!this._visible) return;\n this.shell?.close();\n this._visible = false;\n this._emit({ name: 'hide' } as WidgetEvent);\n }\n\n isVisible(): boolean {\n return this._visible;\n }\n\n async capture(mode?: 'fullscreen' | 'advanced'): Promise<void> {\n void mode; // mode selector UI deferred to v1.1\n this.show();\n }\n\n cancelCapture(): void {\n this.hide();\n }\n\n setReporter(info: { email: string; fullName?: string }): void {\n this._reporter = info;\n }\n\n clearReporter(): void {\n this._reporter = undefined;\n }\n\n setCustomData(data?: Record<string, unknown>): void {\n this._customData = { ...this._customData, ...data };\n }\n\n setNetworkRecordingSettings(s: { excludedKeys?: string[]; excludedDomains?: string[] }): void {\n this.networkSettings = s;\n }\n\n on(event: WidgetEventName, listener: Listener): void {\n const arr = this.listeners.get(event) ?? [];\n arr.push(listener);\n this.listeners.set(event, arr);\n }\n\n off(event: WidgetEventName, listener: Listener): void {\n const arr = this.listeners.get(event) ?? [];\n this.listeners.set(event, arr.filter((l) => l !== listener));\n }\n\n unload(): void {\n this.teardown();\n }\n\n // ── Private ────────────────────────────────────────────────────────────────\n\n private _openModal(): void {\n const shell = new ModalShell({\n onClose: () => {\n this._visible = false;\n this._emit({ name: 'hide' } as WidgetEvent);\n },\n });\n this.shell?.destroy();\n this.shell = shell;\n\n const formEl = buildFormElement({\n widgetOpts: this.opts,\n cssRoot: shell.shadowRoot,\n // Hide modal AND FAB during capture — both live as separate shadow\n // hosts on document.body and would otherwise show in the screenshot.\n hideForCapture: [shell.host, this.fabHost].filter(\n (el): el is HTMLElement => !!el,\n ),\n showBranding: this.opts.showBranding,\n onCancel: () => {\n this._emit({ name: 'feedbackdiscarded' } as WidgetEvent);\n shell.close();\n this._visible = false;\n },\n onSubmit: async (payload) => {\n // feedbackbeforesend hook — allow mutations\n let cancelled = false;\n const mutableValues: Record<string, unknown> = {\n description: payload.description,\n title: payload.title,\n email: payload.email,\n labels: undefined,\n assignee: undefined,\n customFields: undefined,\n priority: undefined,\n issueType: undefined,\n };\n\n const beforeSendListeners = this.listeners.get('feedbackbeforesend') ?? [];\n for (const listener of beforeSendListeners) {\n listener({\n name: 'feedbackbeforesend',\n values: mutableValues as any,\n setValue: (field: string, value: unknown) => {\n const MUTABLE = new Set(['assignee', 'labels', 'customFields', 'priority', 'issueType']);\n if (MUTABLE.has(field)) (mutableValues as Record<string, unknown>)[field] = value;\n },\n cancel: () => { cancelled = true; },\n } as any);\n if (cancelled) break;\n }\n\n if (cancelled) {\n this._emit({ name: 'feedbackdiscarded' } as WidgetEvent);\n shell.close();\n this._visible = false;\n throw new Error('Cancelled by feedbackbeforesend handler');\n }\n\n if (!this.client) throw new Error('Client not initialized');\n\n const result = await submitBugReport(this.client, {\n title: (mutableValues.title as string) ?? payload.title,\n description: (mutableValues.description as string) ?? payload.description,\n email: (mutableValues.email as string | undefined) ?? payload.email,\n screenshot: payload.screenshot,\n annotations: payload.annotations,\n reporter: this._reporter,\n customData: { ...this._customData, ...(mutableValues.customFields as Record<string, unknown> | undefined) },\n });\n\n this._emit({ name: 'feedbacksent', ...result } as WidgetEvent);\n return result;\n },\n });\n\n shell.open(formEl);\n }\n\n private _injectFab(): void {\n // Create shadow host for the FAB so it doesn't bleed into host styles\n const fabHost = document.createElement('div');\n fabHost.setAttribute('data-it-fab', '');\n const shadow = fabHost.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = `\n .it-fab {\n position: fixed; bottom: 20px; right: 20px;\n z-index: 2147483646;\n width: 44px; height: 44px; border-radius: 50%;\n background: #4f46e5; color: #fff;\n border: none; cursor: pointer; padding: 0;\n box-shadow: 0 4px 12px rgba(0,0,0,0.18), 0 1px 2px rgba(0,0,0,0.12);\n display: inline-flex;\n align-items: center; justify-content: center;\n transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;\n font-family: system-ui, -apple-system, sans-serif;\n }\n .it-fab:hover {\n transform: translateY(-1px) scale(1.04);\n background: #4338ca;\n box-shadow: 0 8px 20px rgba(0,0,0,0.22);\n }\n .it-fab:focus-visible {\n outline: 2px solid #c7d2fe;\n outline-offset: 2px;\n }\n .it-fab svg { width: 20px; height: 20px; display: block; }\n `;\n\n const fab = document.createElement('button');\n fab.className = 'it-fab';\n fab.setAttribute('aria-label', 'Report a bug');\n fab.setAttribute('title', 'Report a bug');\n // Lucide \"message-square-warning\" — monochrome SVG, no emoji color rendering\n fab.innerHTML =\n '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">' +\n '<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>' +\n '<line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"11\"/>' +\n '<circle cx=\"12\" cy=\"14.5\" r=\"1\"/>' +\n '</svg>';\n fab.addEventListener('click', () => this.show());\n\n shadow.appendChild(style);\n shadow.appendChild(fab);\n document.body.appendChild(fabHost);\n\n this.fabBtn = fab;\n this.fabHost = fabHost;\n }\n\n private _emit(event: WidgetEvent): void {\n const name = event.name as WidgetEventName;\n const listeners = this.listeners.get(name) ?? [];\n for (const l of listeners) {\n try { l(event); } catch (e) { console.error('[InstantTasks Widget] listener threw', e); }\n }\n }\n}\n\n/**\n * Create an in-app reporter integration for the InstantTasks SDK client.\n *\n * @param opts - Reporter configuration options.\n * @returns An Integration that can be passed to `init({ integrations: [...] })`.\n */\nexport function reporterIntegration(opts: WidgetOptions = {}): Integration & WidgetApi {\n return new WidgetIntegration(opts);\n}\n\n/** @deprecated Renamed to `reporterIntegration`. Will be removed in v1. */\nexport const widgetIntegration = reporterIntegration;\n\n/** Class export for users who prefer `new ReporterIntegration()`. */\nexport { WidgetIntegration as ReporterIntegration, WidgetIntegration };\n\nexport default reporterIntegration;\n"],"mappings":"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","names":["parseHotkey","raw","isMac","navigator","test","platform","parts","toLowerCase","split","map","p","trim","modifiers","Set","key","part","add","includes","ctrl","has","meta","alt","shift","matchesHotkey","e","parsed","ctrlKey","metaKey","altKey","shiftKey","isTypingTarget","target","tag","tagName","isContentEditable","ceProp","contentEditable","ce","getAttribute","registerHotkey","hotkeyStr","handler","window","hasModifier","listener","ke","preventDefault","stopPropagation","addEventListener","removeEventListener","WIDGET_STYLES","getCspNonce","document","meta","querySelector","v","getAttribute","length","ModalShell","host","shadow","_isOpen","onCloseCb","backdropEl","modalEl","contentSlot","_escListener","opts","onClose","createElement","setAttribute","attachShadow","mode","styleEl","textContent","WIDGET_STYLES","nonce","appendChild","shadowRoot","isOpen","modalElement","open","content","_teardown","body","backdrop","className","addEventListener","e","target","stopPropagation","modal","key","close","window","focus","destroy","parentNode","removeChild","removeEventListener","contains","AnnotationTools","_commands","_activeTool","_onChange","onChange","activeTool","commands","setTool","mode","_notify","toggleTool","addCommand","cmd","undo","length","slice","removeAt","index","filter","_","i","clear","getState","ACCENT_VAR","ACCENT_DEFAULT","getAccentColor","root","el","ShadowRoot","host","getComputedStyle","getPropertyValue","trim","paintForeground","foreground","commands","accent","ctx","getContext","W","width","H","height","clearRect","highlights","filter","c","type","hides","length","save","fillStyle","fillRect","globalCompositeOperation","cmd","rx","x","ry","y","rw","w","rh","h","restore","strokeStyle","lineWidth","strokeRect","compositeCanvases","background","output","drawImage","Annotator","tools","background","foreground","cssRoot","onChangeCb","dragging","dragStart","cleanupListeners","opts","onChange","AnnotationTools","state","_repaint","commands","_attachMouseListeners","activeTool","setTool","mode","toggleTool","undo","clear","removeAt","i","composite","output","compositeCanvases","destroy","fn","accent","getAccentColor","paintForeground","_normalize","px","py","W","width","H","height","nx","Math","max","min","ny","_canvasPos","e","rect","getBoundingClientRect","scaleX","scaleY","x","clientX","left","y","clientY","top","fg","onMouseDown","button","onMouseMove","current","preview","_buildCommand","onMouseUp","end","cmd","abs","w","h","addCommand","_normalizeCommand","addEventListener","push","removeEventListener","start","type","clamp","v","isNativeCaptureSupported","test","navigator","userAgent","maxTouchPoints","isSecureContext","mediaDevices","getDisplayMedia","nativeCapture","opts","dpi","window","devicePixelRatio","hiddenList","Array","isArray","hideElement","filter","el","prev","map","display","style","visibility","restore","stream","navigator","mediaDevices","getDisplayMedia","video","width","innerWidth","height","innerHeight","audio","monitorTypeSurfaces","preferCurrentTab","selfBrowserSurface","surfaceSwitching","err","document","createElement","srcObject","muted","Promise","resolve","reject","onloadedmetadata","onerror","Error","play","catch","r","requestAnimationFrame","canvas","videoWidth","videoHeight","ctx","getContext","drawImage","track","getTracks","stop","fallbackCapture","onTainted","opts","html2canvas","mod","default","importErr","Error","hiddenList","Array","isArray","hideElement","filter","el","prev","map","display","style","visibility","restore","tainted","canvas","document","body","allowTaint","useCORS","logging","scale","window","devicePixelRatio","err","DOMException","name","catch","blank","createElement","width","innerWidth","height","innerHeight","capture","opts","useNative","useNativeScreenshot","isNativeCaptureSupported","result","nativeCapture","hideElement","method","err","DOMException","name","onFallback","fallbackCapture","onTainted","canvas","dpi","window","devicePixelRatio","tainted","buildFormElement","opts","container","document","createElement","header","className","title","textContent","closeBtn","setAttribute","addEventListener","onCancel","appendChild","capturedCanvas","annotator","annotations","screenshotArea","placeholder","captureBtn","taintedWarning","screenshotPreview","style","display","stage","backgroundCanvas","foregroundCanvas","toolbar","highlightBtn","hideBtn","undoBtn","clearBtn","disabled","result","capture","useNativeScreenshot","widgetOpts","hideElement","hideForCapture","onTainted","onFallback","silent","console","info","canvas","width","height","bgCtx","getContext","drawImage","aspectRatio","destroy","Annotator","background","foreground","cssRoot","onChange","cmds","setTool","classList","add","remove","undo","clear","descSection","descLabel","descArea","rows","descError","titleSection","titleLabel","titleInput","type","maxLength","emailInput","collectEmail","emailSection","emailLabel","reporter","email","value","submitError","footer","brandingEl","href","target","rel","showBranding","actions","cancelBtn","submitBtn","desc","trim","length","focus","screenshotForSubmit","out","composite","derivedTitle","slice","payload","description","undefined","screenshot","innerHTML","onSubmit","modalEl","closest","successEl","ticketUrl","ticketKey","setTimeout","err","Error","message","autoCapture","requestAnimationFrame","click","canvasToBlob","canvas","Promise","resolve","reject","toBlob","blob","Error","submitBugReport","client","payload","meta","collectMetadata","captureConsole","customDataFn","fullDescription","description","formatMetadataBlock","event","kind","ts","Date","toISOString","url","userAgent","viewport","title","email","reporter","annotations","metadata","appVersion","customData","consoleTail","attachments","Map","screenshot","pngBlob","set","result","send","size","undefined","ticketKey","baseUrl","options","endpoint","ticketUrl","WidgetIntegration","name","opts","_initialOpts","client","shell","fabBtn","fabHost","_visible","_reporter","_customData","networkSettings","listeners","Map","cleanupHotkey","cleanupConsole","hotkey","autoInject","useNativeScreenshot","autoCapture","showBranding","reporter","customData","setup","captureConsole","then","patchConsole","catch","_applyRemoteConfig","finally","_wireRuntime","endpoint","options","replace","accessKey","projectId","res","fetch","method","headers","Authorization","ok","body","json","cfg","sdkConfig","init","undefined","showFab","enabled","requireUser","defaultReporterBehavior","registerHotkey","show","_injectFab","proc","globalThis","process","isProd","env","NODE_ENV","exposeGlobal","w","window","InstantTasks","silent","console","info","_emit","teardown","destroy","parentNode","removeChild","_hasIdentity","_openLoginPrompt","_openModal","u","user","Boolean","id","email","ModalShell","onClose","here","location","pathname","search","loginUrl","encodeURIComponent","wrapper","document","createElement","style","cssText","innerHTML","signInBtn","type","textContent","addEventListener","assign","cancelBtn","close","appendChild","open","hide","isVisible","capture","mode","cancelCapture","setReporter","clearReporter","setCustomData","data","setNetworkRecordingSettings","s","on","event","listener","arr","get","push","set","off","filter","l","unload","formEl","buildFormElement","widgetOpts","cssRoot","shadowRoot","hideForCapture","host","el","onCancel","onSubmit","payload","cancelled","mutableValues","description","title","labels","assignee","customFields","priority","issueType","beforeSendListeners","values","setValue","field","value","MUTABLE","Set","has","cancel","Error","result","submitBugReport","screenshot","annotations","setAttribute","shadow","attachShadow","fab","className","e","error","reporterIntegration","widgetIntegration","reporterIntegration"]}