bug-widget-library 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"bug-widget-library.js","names":["_Fragment","CircleIcon","_Fragment","KonvaImage","Circle","_Fragment","html2canvas","Circle$1","getProjectLabel","projectUrl","Form","uiSettings","isLeft","pos","position","reportTitle","setReportTitle","useState","description","setDescription","isSubmitting","setIsSubmitting","isSuccess","setIsSuccess","submitError","setSubmitError","errors","setErrors","previewImage","setPreviewImage","projectLabel","validate","errs","Fragment","onClose","isOpen","title","primaryColor","Sparkles","subtitle","X","CheckCircle2","screenshots","e","onSubmitReport","err","prev","placeholderTitle","AlertCircle","placeholderDescription","s","idx","Eye","onEditScreenshot","Edit3","onDeleteScreenshot","Trash2","onTriggerScreenshot","Camera","Loader2","PRESET_COLORS","STROKE_WIDTHS","KonvaEditor","containerRef","useRef","stageRef","transformerRef","image","setImage","scale","setScale","stageDimensions","setStageDimensions","tool","setTool","color","setColor","strokeWidth","setStrokeWidth","selectedId","setSelectedId","shapes","setShapes","draftShape","setDraftShape","isDrawing","setIsDrawing","startPoint","setStartPoint","history","setHistory","historyStep","setHistoryStep","img","imageSrc","updateDimensions","useCallback","availWidth","availHeight","fitScale","useEffect","selectedNode","pushHistory","newHistory","newShapes","handleUndo","newStep","handleRedo","handleClearAll","handleDeleteSelected","handleKeyDown","handlePointerDown","stage","pointer","x","y","clickedNode","shapeId","id","newLine","handlePointerMove","rx","ry","rw","rh","radius","handlePointerUp","isValid","x1","y1","x2","y2","nextShapes","handleTransformEnd","node","targetShape","scaleX","scaleY","updated","handleDragEnd","Undo2","Redo2","onCancel","onSave","Check","MousePointer","Pencil","Eraser","Square","Circle","ArrowUpRight","c","Palette","sw","Stage","Layer","Image","isSelectable","shape","Line","next","Rect","Arrow","Transformer","newBox","oldBox","Widget","controlledIsOpen","internalIsOpen","setInternalIsOpen","setOpen","open","onToggle","setScreenshots","isCapturing","setIsCapturing","isEditorOpen","setIsEditorOpen","editingScreenshot","setEditingScreenshot","getPositionClasses","sizeClasses","size","buttonSize","className","buttonIcon","Bug","buttonText","resolve","dataUrl","element","item","onSubmit","reportData","onSuccess","error","onError","newItem","editedDataUrl"],"sources":["../src/components/Form.tsx","../src/components/KonvaEditor.tsx","../src/components/Widget.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Camera,\n X,\n Trash2,\n Edit3,\n Eye,\n CheckCircle2,\n AlertCircle,\n Loader2,\n Sparkles,\n} from 'lucide-react';\nimport type {\n BugReportData,\n ScreenshotItem,\n WidgetUiSettings,\n WidgetPosition,\n} from '../types';\n\ninterface FormProps {\n projectUrl: string;\n isOpen: boolean;\n onClose: () => void;\n uiSettings?: WidgetUiSettings;\n screenshots: ScreenshotItem[];\n onTriggerScreenshot: () => void;\n onEditScreenshot: (screenshot: ScreenshotItem) => void;\n onDeleteScreenshot: (id: string) => void;\n onSubmitReport: (data: BugReportData) => Promise<void> | void;\n}\n\nfunction getProjectLabel(projectUrl: string): string {\n try {\n return new URL(projectUrl).hostname;\n } catch {\n return 'project';\n }\n}\n\nexport const Form: React.FC<FormProps> = ({\n projectUrl,\n isOpen,\n onClose,\n uiSettings = {},\n screenshots,\n onTriggerScreenshot,\n onEditScreenshot,\n onDeleteScreenshot,\n onSubmitReport,\n}) => {\n const {\n position = 'bottom-right',\n primaryColor = '#2563eb',\n title = 'Report a Bug',\n subtitle = 'Found an issue? Let us know with details and screenshots.',\n placeholderTitle = 'e.g. Broken checkout button on cart page',\n placeholderDescription = 'Describe what happened, steps to reproduce, and expected result...',\n } = uiSettings;\n\n const isLeftPosition = (pos: WidgetPosition) =>\n pos === 'bottom-left' || pos === 'top-left' || pos === 'left';\n\n const isLeft = isLeftPosition(position);\n\n // Form input states\n const [reportTitle, setReportTitle] = useState('');\n const [description, setDescription] = useState('');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isSuccess, setIsSuccess] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [errors, setErrors] = useState<{ title?: string; description?: string }>({});\n const [previewImage, setPreviewImage] = useState<string | null>(null);\n const projectLabel = getProjectLabel(projectUrl);\n\n // Form validation\n const validate = () => {\n const errs: { title?: string; description?: string } = {};\n if (!reportTitle.trim()) {\n errs.title = 'Title / bug name is required.';\n }\n if (!description.trim()) {\n errs.description = 'Description is required.';\n }\n setErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!validate()) return;\n\n setIsSubmitting(true);\n setSubmitError(null);\n try {\n const reportData: BugReportData = {\n projectUrl,\n title: reportTitle.trim(),\n description: description.trim(),\n screenshots,\n timestamp: new Date().toISOString(),\n meta: {\n url: window.location.href,\n userAgent: navigator.userAgent,\n timestamp: new Date().toISOString(),\n screenSize: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n },\n };\n\n await onSubmitReport(reportData);\n setIsSuccess(true);\n } catch (err) {\n console.error('Failed to submit bug report:', err);\n setSubmitError(\n err instanceof Error ? err.message : 'Failed to submit bug report. Please try again.'\n );\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleReset = () => {\n setReportTitle('');\n setDescription('');\n setErrors({});\n setSubmitError(null);\n setIsSuccess(false);\n };\n\n // Determine slide animation direction\n const slideClass = isLeft\n ? isOpen\n ? 'translate-x-0 opacity-100 pointer-events-auto'\n : '-translate-x-full opacity-0 pointer-events-none'\n : isOpen\n ? 'translate-x-0 opacity-100 pointer-events-auto'\n : 'translate-x-full opacity-0 pointer-events-none';\n\n return (\n <>\n {/* Subtle backdrop overlay */}\n <div\n data-bugdrop-widget=\"true\"\n onClick={onClose}\n className={`fixed inset-0 z-[99990] bg-slate-900/40 backdrop-blur-sm transition-opacity duration-300 ${\n isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'\n }`}\n />\n\n {/* Slide-in Drawer Container */}\n <aside\n data-bugdrop-widget=\"true\"\n className={`fixed top-0 z-[99995] flex h-full w-full max-w-md flex-col bg-white shadow-2xl transition-all duration-300 ease-out sm:max-w-lg ${\n isLeft ? 'left-0 border-r border-slate-200' : 'right-0 border-l border-slate-200'\n } ${slideClass}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n {/* Header */}\n <div className=\"flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-5\">\n <div className=\"flex items-center gap-3\">\n <div\n className=\"flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-md font-bold\"\n style={{ backgroundColor: primaryColor }}\n >\n <Sparkles className=\"h-5 w-5\" />\n </div>\n <div>\n <div className=\"flex items-center gap-2\">\n <h2 className=\"text-lg font-bold text-slate-800\">{title}</h2>\n <span\n className=\"rounded-md bg-slate-100 px-2 py-0.5 text-[11px] font-semibold tracking-wider text-slate-500\"\n title={projectUrl}\n >\n {projectLabel}\n </span>\n </div>\n <p className=\"mt-0.5 text-xs text-slate-500\">{subtitle}</p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={onClose}\n className=\"flex h-8 w-8 items-center justify-center rounded-lg text-slate-400 transition hover:bg-slate-100 hover:text-slate-600\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n {/* Content Area */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5\">\n {isSuccess ? (\n <div className=\"flex h-full flex-col items-center justify-center text-center py-10 animate-fadeIn\">\n <div\n className=\"flex h-16 w-16 items-center justify-center rounded-full text-white shadow-lg mb-4\"\n style={{ backgroundColor: primaryColor }}\n >\n <CheckCircle2 className=\"h-9 w-9\" />\n </div>\n <h3 className=\"text-xl font-bold text-slate-800\">\n Bug Report Submitted!\n </h3>\n <p className=\"mt-2 text-sm text-slate-500 max-w-xs\">\n Thank you! Your bug report with {screenshots.length} screenshot{screenshots.length !== 1 ? 's' : ''} has been captured and logged.\n </p>\n\n <div className=\"mt-8 flex flex-col sm:flex-row gap-3 w-full\">\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"flex-1 rounded-xl border border-slate-200 bg-white py-2.5 text-sm font-semibold text-slate-700 shadow-sm transition hover:bg-slate-50\"\n >\n Report Another Bug\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n style={{ backgroundColor: primaryColor }}\n className=\"flex-1 rounded-xl py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110\"\n >\n Close\n </button>\n </div>\n </div>\n ) : (\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Bug Title / Name (Required) */}\n <div>\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Bug Title / Name <span className=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n value={reportTitle}\n onChange={(e) => {\n setReportTitle(e.target.value);\n if (errors.title) setErrors((prev) => ({ ...prev, title: undefined }));\n }}\n placeholder={placeholderTitle}\n className={`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${\n errors.title\n ? 'border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400'\n : 'border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500'\n }`}\n />\n {errors.title && (\n <p className=\"mt-1.5 flex items-center gap-1 text-xs text-red-600\">\n <AlertCircle className=\"h-3.5 w-3.5\" />\n <span>{errors.title}</span>\n </p>\n )}\n </div>\n\n {/* Bug Description (Required) */}\n <div>\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Description <span className=\"text-red-500\">*</span>\n </label>\n <textarea\n rows={4}\n value={description}\n onChange={(e) => {\n setDescription(e.target.value);\n if (errors.description) {\n setErrors((prev) => ({ ...prev, description: undefined }));\n }\n }}\n placeholder={placeholderDescription}\n className={`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${\n errors.description\n ? 'border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400'\n : 'border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500'\n }`}\n />\n {errors.description && (\n <p className=\"mt-1.5 flex items-center gap-1 text-xs text-red-600\">\n <AlertCircle className=\"h-3.5 w-3.5\" />\n <span>{errors.description}</span>\n </p>\n )}\n </div>\n\n {/* Screenshots Section (Max 3, Optional) */}\n <div>\n <div className=\"flex items-center justify-between\">\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Screenshots <span className=\"text-slate-400 font-normal lowercase\">(optional)</span>\n </label>\n <span className=\"rounded-full bg-slate-100 px-2 py-0.5 text-xs font-semibold text-slate-600\">\n {screenshots.length} / 3\n </span>\n </div>\n <p className=\"mt-1 text-xs text-slate-500\">\n Capture your screen and annotate with pencil, shapes, or arrows.\n </p>\n\n {/* Screenshot Thumbnails Grid */}\n {screenshots.length > 0 && (\n <div className=\"mt-3 grid grid-cols-3 gap-2.5\">\n {screenshots.map((s, idx) => (\n <div\n key={s.id}\n className=\"group relative aspect-video overflow-hidden rounded-lg border border-slate-200 bg-slate-100 shadow-sm\"\n >\n <img\n src={s.dataUrl}\n alt={`Screenshot ${idx + 1}`}\n className=\"h-full w-full object-cover transition duration-200 group-hover:scale-105\"\n />\n\n {/* Top badge */}\n <span className=\"absolute top-1 left-1 rounded bg-black/60 px-1 py-0.2 text-[10px] font-semibold text-white\">\n #{idx + 1}\n </span>\n\n {/* Hover Overlay with actions */}\n <div className=\"absolute inset-0 flex items-center justify-center gap-1.5 bg-black/50 opacity-0 backdrop-blur-[1px] transition-opacity duration-200 group-hover:opacity-100\">\n <button\n type=\"button\"\n onClick={() => setPreviewImage(s.dataUrl)}\n title=\"Preview screenshot\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600\"\n >\n <Eye className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onEditScreenshot(s)}\n title=\"Re-edit / annotate\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600\"\n >\n <Edit3 className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteScreenshot(s.id)}\n title=\"Delete screenshot\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-red-600 text-white shadow transition hover:bg-red-700\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Add Screenshot Trigger Button */}\n <div className=\"mt-3\">\n {screenshots.length < 3 ? (\n <button\n type=\"button\"\n onClick={onTriggerScreenshot}\n className=\"flex w-full items-center justify-center gap-2 rounded-xl border-2 border-dashed border-slate-300 bg-slate-50/70 py-3 text-xs font-semibold text-slate-600 transition hover:border-blue-400 hover:bg-blue-50/50 hover:text-blue-600\"\n >\n <Camera className=\"h-4 w-4 text-slate-500\" />\n <span>\n {screenshots.length === 0\n ? 'Capture Screen & Annotate'\n : `Capture Another Screenshot (${3 - screenshots.length} left)`}\n </span>\n </button>\n ) : (\n <div className=\"rounded-lg bg-amber-50 p-2.5 text-center text-xs text-amber-700 border border-amber-200\">\n Maximum 3 screenshots attached. Delete one to take a new one.\n </div>\n )}\n </div>\n </div>\n\n {submitError && (\n <div className=\"rounded-xl border border-red-200 bg-red-50 px-3.5 py-2.5 text-xs text-red-700 flex items-start gap-2\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{submitError}</span>\n </div>\n )}\n\n {/* Form Actions */}\n <div className=\"pt-4 border-t border-slate-100 flex items-center justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-600 transition hover:bg-slate-50\"\n >\n Cancel\n </button>\n\n <button\n type=\"submit\"\n disabled={isSubmitting}\n style={{ backgroundColor: primaryColor }}\n className=\"flex items-center gap-2 rounded-xl px-5 py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95 disabled:opacity-60\"\n >\n {isSubmitting ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span>Submitting...</span>\n </>\n ) : (\n <span>Submit Bug Report</span>\n )}\n </button>\n </div>\n </form>\n )}\n </div>\n </aside>\n\n {/* Lightbox Preview Modal for zoomed screenshot */}\n {previewImage && (\n <div\n data-bugdrop-widget=\"true\"\n onClick={() => setPreviewImage(null)}\n className=\"fixed inset-0 z-[100001] flex items-center justify-center bg-black/80 p-4 backdrop-blur-sm animate-fadeIn\"\n >\n <div\n className=\"relative max-h-[90vh] max-w-[90vw] overflow-hidden rounded-xl bg-slate-900 shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n <img\n src={previewImage}\n alt=\"Screenshot Preview\"\n className=\"max-h-[85vh] w-auto rounded-xl object-contain\"\n />\n <button\n type=\"button\"\n onClick={() => setPreviewImage(null)}\n className=\"absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-black/60 text-white shadow hover:bg-black/90\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n )}\n </>\n );\n};","import React, { useState, useRef, useEffect, useCallback } from 'react';\nimport {\n Stage,\n Layer,\n Image as KonvaImage,\n Line,\n Rect,\n Circle,\n Arrow,\n Transformer,\n} from 'react-konva';\nimport type Konva from 'konva';\nimport {\n Pencil,\n Eraser,\n Square,\n Circle as CircleIcon,\n ArrowUpRight,\n MousePointer,\n Undo2,\n Redo2,\n Trash2,\n Check,\n X,\n Palette,\n} from 'lucide-react';\nimport type {\n EditorTool,\n AnnotationShape,\n LineAnnotation,\n RectAnnotation,\n CircleAnnotation,\n ArrowAnnotation,\n} from '../types';\n\ninterface KonvaEditorProps {\n imageSrc: string;\n onSave: (editedDataUrl: string) => void;\n onCancel: () => void;\n primaryColor?: string;\n}\n\nconst PRESET_COLORS = [\n '#ef4444', // Red\n '#f97316', // Orange\n '#eab308', // Yellow\n '#10b981', // Green\n '#3b82f6', // Blue\n '#8b5cf6', // Purple\n '#ec4899', // Pink\n '#000000', // Black\n '#ffffff', // White\n];\n\nconst STROKE_WIDTHS = [\n { label: 'S', value: 3 },\n { label: 'M', value: 6 },\n { label: 'L', value: 10 },\n { label: 'XL', value: 16 },\n];\n\nexport const KonvaEditor: React.FC<KonvaEditorProps> = ({\n imageSrc,\n onSave,\n onCancel,\n primaryColor = '#2563eb',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<Konva.Stage>(null);\n const transformerRef = useRef<Konva.Transformer>(null);\n\n const [image, setImage] = useState<HTMLImageElement | null>(null);\n const [scale, setScale] = useState<number>(1);\n const [stageDimensions, setStageDimensions] = useState({ width: 800, height: 600 });\n\n // Tool state\n const [tool, setTool] = useState<EditorTool>('pencil');\n const [color, setColor] = useState<string>('#ef4444');\n const [strokeWidth, setStrokeWidth] = useState<number>(6);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n // Shapes & drawing state\n const [shapes, setShapes] = useState<AnnotationShape[]>([]);\n const [draftShape, setDraftShape] = useState<AnnotationShape | null>(null);\n const [isDrawing, setIsDrawing] = useState(false);\n const [startPoint, setStartPoint] = useState<{ x: number; y: number } | null>(null);\n\n // History stack for Undo / Redo\n const [history, setHistory] = useState<AnnotationShape[][]>([[]]);\n const [historyStep, setHistoryStep] = useState<number>(0);\n\n // Load screenshot image\n useEffect(() => {\n const img = new window.Image();\n img.crossOrigin = 'anonymous';\n img.src = imageSrc;\n img.onload = () => {\n setImage(img);\n };\n }, [imageSrc]);\n\n // Compute responsive stage scaling to fit container\n const updateDimensions = useCallback(() => {\n if (!containerRef.current || !image) return;\n const paddingX = 48;\n const paddingY = 120;\n const availWidth = Math.max(300, containerRef.current.clientWidth - paddingX);\n const availHeight = Math.max(300, containerRef.current.clientHeight - paddingY);\n\n const fitScale = Math.min(\n availWidth / image.naturalWidth,\n availHeight / image.naturalHeight,\n 1\n );\n\n setScale(fitScale);\n setStageDimensions({\n width: Math.round(image.naturalWidth * fitScale),\n height: Math.round(image.naturalHeight * fitScale),\n });\n }, [image]);\n\n useEffect(() => {\n updateDimensions();\n window.addEventListener('resize', updateDimensions);\n return () => window.removeEventListener('resize', updateDimensions);\n }, [updateDimensions]);\n\n // Update Transformer attachment when selection or shapes change\n useEffect(() => {\n if (!transformerRef.current || !stageRef.current) return;\n if (selectedId) {\n const selectedNode = stageRef.current.findOne('#' + selectedId);\n if (selectedNode) {\n transformerRef.current.nodes([selectedNode]);\n transformerRef.current.getLayer()?.batchDraw();\n return;\n }\n }\n transformerRef.current.nodes([]);\n transformerRef.current.getLayer()?.batchDraw();\n }, [selectedId, shapes]);\n\n // Push new state to history\n const pushHistory = useCallback((newShapes: AnnotationShape[]) => {\n setHistory((prev) => {\n const newHistory = prev.slice(0, historyStep + 1);\n newHistory.push(newShapes);\n return newHistory;\n });\n setHistoryStep((prev) => prev + 1);\n }, [historyStep]);\n\n const handleUndo = useCallback(() => {\n if (historyStep > 0) {\n const newStep = historyStep - 1;\n setHistoryStep(newStep);\n setShapes(history[newStep]);\n setSelectedId(null);\n }\n }, [historyStep, history]);\n\n const handleRedo = useCallback(() => {\n if (historyStep < history.length - 1) {\n const newStep = historyStep + 1;\n setHistoryStep(newStep);\n setShapes(history[newStep]);\n setSelectedId(null);\n }\n }, [historyStep, history]);\n\n const handleClearAll = () => {\n if (shapes.length === 0) return;\n const newShapes: AnnotationShape[] = [];\n setShapes(newShapes);\n pushHistory(newShapes);\n setSelectedId(null);\n };\n\n const handleDeleteSelected = useCallback(() => {\n if (!selectedId) return;\n const newShapes = shapes.filter((s) => s.id !== selectedId);\n setShapes(newShapes);\n pushHistory(newShapes);\n setSelectedId(null);\n }, [selectedId, shapes, pushHistory]);\n\n // Keyboard shortcuts\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {\n return;\n }\n if ((e.ctrlKey || e.metaKey) && e.key === 'z') {\n if (e.shiftKey) {\n handleRedo();\n } else {\n handleUndo();\n }\n e.preventDefault();\n } else if ((e.ctrlKey || e.metaKey) && e.key === 'y') {\n handleRedo();\n e.preventDefault();\n } else if (e.key === 'Delete' || e.key === 'Backspace') {\n if (selectedId) {\n handleDeleteSelected();\n e.preventDefault();\n }\n } else if (e.key === 'Escape') {\n setSelectedId(null);\n e.preventDefault();\n }\n };\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [handleDeleteSelected, handleRedo, handleUndo, selectedId]);\n\n // Pointer event handlers for drawing shapes\n const handlePointerDown = (e: Konva.KonvaEventObject<MouseEvent | TouchEvent>) => {\n const stage = stageRef.current;\n if (!stage || !image) return;\n\n const pointer = stage.getPointerPosition();\n if (!pointer) return;\n\n // Convert to unscaled natural image coordinates\n const x = pointer.x / scale;\n const y = pointer.y / scale;\n\n // Select Tool behavior\n if (tool === 'select') {\n const clickedOnEmpty = e.target === stage || e.target.hasName('bg-image');\n if (clickedOnEmpty) {\n setSelectedId(null);\n }\n return;\n }\n\n // Eraser Tool click behavior: if clicked on an existing shape, remove it immediately\n if (tool === 'eraser') {\n const clickedNode = e.target;\n if (clickedNode !== stage && !clickedNode.hasName('bg-image')) {\n const shapeId = clickedNode.id();\n if (shapeId) {\n const newShapes = shapes.filter((s) => s.id !== shapeId);\n setShapes(newShapes);\n pushHistory(newShapes);\n setSelectedId(null);\n return;\n }\n }\n }\n\n // Deselect any selected shape while drawing new annotations\n setSelectedId(null);\n setIsDrawing(true);\n setStartPoint({ x, y });\n\n const id = `shape_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n\n if (tool === 'pencil' || tool === 'eraser') {\n const newLine: LineAnnotation = {\n id,\n type: 'line',\n tool,\n points: [x, y],\n stroke: tool === 'eraser' ? '#ffffff' : color,\n strokeWidth: tool === 'eraser' ? strokeWidth * 2.5 : strokeWidth,\n };\n setDraftShape(newLine);\n } else if (tool === 'rectangle') {\n const newRect: RectAnnotation = {\n id,\n type: 'rectangle',\n x,\n y,\n width: 0,\n height: 0,\n stroke: color,\n strokeWidth,\n };\n setDraftShape(newRect);\n } else if (tool === 'circle') {\n const newCircle: CircleAnnotation = {\n id,\n type: 'circle',\n x,\n y,\n radius: 0,\n stroke: color,\n strokeWidth,\n };\n setDraftShape(newCircle);\n } else if (tool === 'arrow') {\n const newArrow: ArrowAnnotation = {\n id,\n type: 'arrow',\n points: [x, y, x, y],\n stroke: color,\n fill: color,\n strokeWidth,\n };\n setDraftShape(newArrow);\n }\n };\n\n const handlePointerMove = () => {\n if (!isDrawing || !draftShape || !startPoint || !stageRef.current) return;\n\n const pointer = stageRef.current.getPointerPosition();\n if (!pointer) return;\n\n const x = pointer.x / scale;\n const y = pointer.y / scale;\n\n if (draftShape.type === 'line') {\n setDraftShape({\n ...draftShape,\n points: [...draftShape.points, x, y],\n });\n } else if (draftShape.type === 'rectangle') {\n const rx = Math.min(startPoint.x, x);\n const ry = Math.min(startPoint.y, y);\n const rw = Math.abs(x - startPoint.x);\n const rh = Math.abs(y - startPoint.y);\n setDraftShape({\n ...draftShape,\n x: rx,\n y: ry,\n width: rw,\n height: rh,\n });\n } else if (draftShape.type === 'circle') {\n const radius = Math.hypot(x - startPoint.x, y - startPoint.y);\n setDraftShape({\n ...draftShape,\n radius,\n });\n } else if (draftShape.type === 'arrow') {\n setDraftShape({\n ...draftShape,\n points: [startPoint.x, startPoint.y, x, y],\n });\n }\n };\n\n const handlePointerUp = () => {\n if (!isDrawing) return;\n setIsDrawing(false);\n if (!draftShape) return;\n\n let isValid = false;\n if (draftShape.type === 'line' && draftShape.points.length >= 2) {\n isValid = true;\n } else if (\n draftShape.type === 'rectangle' &&\n draftShape.width > 6 &&\n draftShape.height > 6\n ) {\n isValid = true;\n } else if (draftShape.type === 'circle' && draftShape.radius > 5) {\n isValid = true;\n } else if (draftShape.type === 'arrow') {\n const [x1, y1, x2, y2] = draftShape.points;\n if (Math.hypot(x2 - x1, y2 - y1) > 10) {\n isValid = true;\n }\n }\n\n if (isValid) {\n const nextShapes = [...shapes, draftShape];\n setShapes(nextShapes);\n pushHistory(nextShapes);\n\n // Automatically select shapes (rect, circle, arrow) for immediate resizing\n if (\n draftShape.type === 'rectangle' ||\n draftShape.type === 'circle' ||\n draftShape.type === 'arrow'\n ) {\n setSelectedId(draftShape.id);\n setTool('select');\n }\n }\n\n setDraftShape(null);\n setStartPoint(null);\n };\n\n // Transform and Drag updates for resizable shapes\n const handleTransformEnd = (e: Konva.KonvaEventObject<Event>, id: string) => {\n const node = e.target;\n const targetShape = shapes.find((s) => s.id === id);\n if (!targetShape) return;\n\n if (targetShape.type === 'rectangle') {\n const scaleX = node.scaleX();\n const scaleY = node.scaleY();\n node.scaleX(1);\n node.scaleY(1);\n const updated: RectAnnotation = {\n ...targetShape,\n x: node.x(),\n y: node.y(),\n width: Math.max(10, node.width() * scaleX),\n height: Math.max(10, node.height() * scaleY),\n rotation: node.rotation(),\n };\n const nextShapes = shapes.map((s) => (s.id === id ? updated : s));\n setShapes(nextShapes);\n pushHistory(nextShapes);\n } else if (targetShape.type === 'circle') {\n const scaleX = node.scaleX();\n node.scaleX(1);\n node.scaleY(1);\n const updated: CircleAnnotation = {\n ...targetShape,\n x: node.x(),\n y: node.y(),\n radius: Math.max(6, targetShape.radius * scaleX),\n rotation: node.rotation(),\n };\n const nextShapes = shapes.map((s) => (s.id === id ? updated : s));\n setShapes(nextShapes);\n pushHistory(nextShapes);\n } else if (targetShape.type === 'arrow') {\n const scaleX = node.scaleX();\n const scaleY = node.scaleY();\n node.scaleX(1);\n node.scaleY(1);\n const [x1, y1, x2, y2] = targetShape.points;\n const updated: ArrowAnnotation = {\n ...targetShape,\n x: node.x(),\n y: node.y(),\n points: [x1, y1, x1 + (x2 - x1) * scaleX, y1 + (y2 - y1) * scaleY],\n rotation: node.rotation(),\n };\n const nextShapes = shapes.map((s) => (s.id === id ? updated : s));\n setShapes(nextShapes);\n pushHistory(nextShapes);\n }\n };\n\n const handleDragEnd = (e: Konva.KonvaEventObject<DragEvent>, id: string) => {\n const node = e.target;\n const targetShape = shapes.find((s) => s.id === id);\n if (!targetShape) return;\n\n const nextShapes = shapes.map((s) => {\n if (s.id === id) {\n return {\n ...s,\n x: node.x(),\n y: node.y(),\n };\n }\n return s;\n });\n setShapes(nextShapes);\n pushHistory(nextShapes);\n };\n\n // Finalize and export screenshot with annotations\n const handleExport = () => {\n if (!stageRef.current) return;\n // Deselect any transformer handles so they aren't included in the exported image\n setSelectedId(null);\n\n // Allow React state to flush transformer detachment before export\n setTimeout(() => {\n if (!stageRef.current) return;\n const exportedDataUrl = stageRef.current.toDataURL({\n pixelRatio: 1 / scale,\n mimeType: 'image/png',\n });\n onSave(exportedDataUrl);\n }, 60);\n };\n\n return (\n <div\n ref={containerRef}\n className=\"fixed inset-0 z-[100000] flex flex-col bg-slate-950/90 backdrop-blur-md select-none text-white overflow-hidden animate-fadeIn\"\n style={{ touchAction: 'none' }}\n >\n {/* Top Header Bar */}\n <div className=\"flex h-16 shrink-0 items-center justify-between border-b border-slate-800 bg-slate-900/90 px-4 sm:px-6\">\n <div className=\"flex items-center gap-3\">\n <div\n className=\"flex h-8 w-8 items-center justify-center rounded-lg text-white font-bold text-sm shadow\"\n style={{ backgroundColor: primaryColor }}\n >\n BD\n </div>\n <div>\n <h1 className=\"text-sm sm:text-base font-semibold leading-tight text-slate-100\">\n Screenshot Editor\n </h1>\n <p className=\"text-xs text-slate-400 hidden sm:block\">\n Highlight issues with pencil, arrows, circles, and boxes\n </p>\n </div>\n </div>\n\n {/* Top Actions: Undo, Redo, Clear, Cancel, Save */}\n <div className=\"flex items-center gap-2 sm:gap-3\">\n <button\n type=\"button\"\n onClick={handleUndo}\n disabled={historyStep <= 0}\n title=\"Undo (Ctrl+Z)\"\n className=\"flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Undo2 className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={handleRedo}\n disabled={historyStep >= history.length - 1}\n title=\"Redo (Ctrl+Y)\"\n className=\"flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Redo2 className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={handleClearAll}\n disabled={shapes.length === 0}\n title=\"Clear all annotations\"\n className=\"flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-2.5 text-xs font-medium text-slate-300 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n <span className=\"hidden md:inline\">Clear All</span>\n </button>\n\n <div className=\"h-5 w-px bg-slate-700 mx-1\" />\n\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-3 text-xs sm:text-sm font-medium text-slate-200 transition hover:bg-slate-700 hover:text-white\"\n >\n <X className=\"h-4 w-4\" />\n <span>Cancel</span>\n </button>\n\n <button\n type=\"button\"\n onClick={handleExport}\n style={{ backgroundColor: primaryColor }}\n className=\"flex h-9 items-center gap-1.5 rounded-lg px-4 text-xs sm:text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95\"\n >\n <Check className=\"h-4 w-4\" />\n <span>Add to Report</span>\n </button>\n </div>\n </div>\n\n {/* Floating Toolbar */}\n <div className=\"absolute top-20 left-1/2 -translate-x-1/2 z-20 flex flex-wrap items-center justify-center gap-2 rounded-2xl border border-slate-700/80 bg-slate-900/95 p-2 shadow-2xl backdrop-blur-md\">\n {/* Tool selector buttons */}\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => setTool('select')}\n title=\"Select & Move / Resize\"\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === 'select'\n ? 'bg-blue-600 text-white shadow-inner'\n : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <MousePointer className=\"h-4 w-4\" />\n </button>\n\n <button\n type=\"button\"\n onClick={() => {\n setTool('pencil');\n setSelectedId(null);\n }}\n title=\"Pencil / Draw\"\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === 'pencil'\n ? 'bg-blue-600 text-white shadow-inner'\n : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <Pencil className=\"h-4 w-4\" />\n </button>\n\n <button\n type=\"button\"\n onClick={() => {\n setTool('eraser');\n setSelectedId(null);\n }}\n title=\"Eraser (click or drag to erase)\"\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === 'eraser'\n ? 'bg-blue-600 text-white shadow-inner'\n : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <Eraser className=\"h-4 w-4\" />\n </button>\n\n <button\n type=\"button\"\n onClick={() => {\n setTool('rectangle');\n setSelectedId(null);\n }}\n title=\"Rectangle (Resizable)\"\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === 'rectangle'\n ? 'bg-blue-600 text-white shadow-inner'\n : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <Square className=\"h-4 w-4\" />\n </button>\n\n <button\n type=\"button\"\n onClick={() => {\n setTool('circle');\n setSelectedId(null);\n }}\n title=\"Circle (Resizable)\"\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === 'circle'\n ? 'bg-blue-600 text-white shadow-inner'\n : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <CircleIcon className=\"h-4 w-4\" />\n </button>\n\n <button\n type=\"button\"\n onClick={() => {\n setTool('arrow');\n setSelectedId(null);\n }}\n title=\"Arrow (Resizable)\"\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === 'arrow'\n ? 'bg-blue-600 text-white shadow-inner'\n : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <ArrowUpRight className=\"h-4 w-4\" />\n </button>\n </div>\n\n <div className=\"h-5 w-px bg-slate-700\" />\n\n {/* Color Palette Switcher */}\n <div className=\"flex items-center gap-1.5 px-1\">\n {PRESET_COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => setColor(c)}\n title={c}\n style={{ backgroundColor: c }}\n className={`h-5 w-5 rounded-full border border-slate-700 transition-transform ${\n color === c ? 'scale-125 ring-2 ring-white ring-offset-1 ring-offset-slate-900' : 'hover:scale-110'\n }`}\n />\n ))}\n\n {/* Custom color input */}\n <label\n title=\"Custom Color\"\n className=\"relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-full border border-slate-600 bg-slate-800 text-slate-300 hover:text-white transition\"\n >\n <Palette className=\"h-3.5 w-3.5\" />\n <input\n type=\"color\"\n value={color}\n onChange={(e) => setColor(e.target.value)}\n className=\"absolute inset-0 opacity-0 cursor-pointer\"\n />\n </label>\n </div>\n\n <div className=\"h-5 w-px bg-slate-700\" />\n\n {/* Stroke Width Selector */}\n <div className=\"flex items-center gap-1\">\n {STROKE_WIDTHS.map((sw) => (\n <button\n key={sw.value}\n type=\"button\"\n onClick={() => setStrokeWidth(sw.value)}\n className={`flex h-7 w-7 items-center justify-center rounded-lg text-xs font-semibold transition ${\n strokeWidth === sw.value\n ? 'bg-slate-700 text-white ring-1 ring-slate-400'\n : 'text-slate-400 hover:bg-slate-800 hover:text-white'\n }`}\n >\n {sw.label}\n </button>\n ))}\n </div>\n\n {/* Delete button if a shape is selected */}\n {selectedId && (\n <>\n <div className=\"h-5 w-px bg-slate-700\" />\n <button\n type=\"button\"\n onClick={handleDeleteSelected}\n title=\"Delete Selected Shape (Del / Backspace)\"\n className=\"flex h-8 items-center gap-1.5 rounded-xl bg-red-600/90 px-3 text-xs font-semibold text-white shadow hover:bg-red-600\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n <span>Delete</span>\n </button>\n </>\n )}\n </div>\n\n {/* Main Canvas Workspace */}\n <div className=\"relative flex flex-1 items-center justify-center p-4 overflow-hidden\">\n {!image ? (\n <div className=\"flex flex-col items-center gap-2 text-slate-400\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-blue-500 border-t-transparent\" />\n <p className=\"text-sm\">Loading screenshot...</p>\n </div>\n ) : (\n <div\n className=\"relative shadow-2xl rounded-md overflow-hidden border border-slate-700 bg-slate-900\"\n style={{\n width: stageDimensions.width,\n height: stageDimensions.height,\n cursor:\n tool === 'select'\n ? 'default'\n : tool === 'eraser'\n ? 'cell'\n : 'crosshair',\n }}\n >\n <Stage\n ref={stageRef}\n width={stageDimensions.width}\n height={stageDimensions.height}\n scaleX={scale}\n scaleY={scale}\n onMouseDown={handlePointerDown}\n onMouseMove={handlePointerMove}\n onMouseUp={handlePointerUp}\n onTouchStart={handlePointerDown}\n onTouchMove={handlePointerMove}\n onTouchEnd={handlePointerUp}\n >\n {/* Background Layer: Screenshot Image */}\n <Layer listening={false}>\n <KonvaImage\n name=\"bg-image\"\n image={image}\n width={image.naturalWidth}\n height={image.naturalHeight}\n />\n </Layer>\n\n {/* Annotations Layer */}\n <Layer>\n {shapes.map((shape) => {\n const isSelectable = tool === 'select';\n\n if (shape.type === 'line') {\n return (\n <Line\n key={shape.id}\n id={shape.id}\n points={shape.points}\n stroke={shape.stroke}\n strokeWidth={shape.strokeWidth}\n tension={0.5}\n lineCap=\"round\"\n lineJoin=\"round\"\n globalCompositeOperation={\n shape.tool === 'eraser' ? 'destination-out' : 'source-over'\n }\n draggable={isSelectable && shape.tool !== 'eraser'}\n onClick={() => {\n if (isSelectable) setSelectedId(shape.id);\n if (tool === 'eraser') {\n const next = shapes.filter((s) => s.id !== shape.id);\n setShapes(next);\n pushHistory(next);\n }\n }}\n onTap={() => {\n if (isSelectable) setSelectedId(shape.id);\n }}\n onDragEnd={(e) => handleDragEnd(e, shape.id)}\n />\n );\n }\n\n if (shape.type === 'rectangle') {\n return (\n <Rect\n key={shape.id}\n id={shape.id}\n x={shape.x}\n y={shape.y}\n width={shape.width}\n height={shape.height}\n stroke={shape.stroke}\n strokeWidth={shape.strokeWidth}\n rotation={shape.rotation || 0}\n draggable={isSelectable}\n onClick={() => {\n if (isSelectable) setSelectedId(shape.id);\n if (tool === 'eraser') {\n const next = shapes.filter((s) => s.id !== shape.id);\n setShapes(next);\n pushHistory(next);\n }\n }}\n onTap={() => {\n if (isSelectable) setSelectedId(shape.id);\n }}\n onTransformEnd={(e) => handleTransformEnd(e, shape.id)}\n onDragEnd={(e) => handleDragEnd(e, shape.id)}\n />\n );\n }\n\n if (shape.type === 'circle') {\n return (\n <Circle\n key={shape.id}\n id={shape.id}\n x={shape.x}\n y={shape.y}\n radius={shape.radius}\n stroke={shape.stroke}\n strokeWidth={shape.strokeWidth}\n rotation={shape.rotation || 0}\n draggable={isSelectable}\n onClick={() => {\n if (isSelectable) setSelectedId(shape.id);\n if (tool === 'eraser') {\n const next = shapes.filter((s) => s.id !== shape.id);\n setShapes(next);\n pushHistory(next);\n }\n }}\n onTap={() => {\n if (isSelectable) setSelectedId(shape.id);\n }}\n onTransformEnd={(e) => handleTransformEnd(e, shape.id)}\n onDragEnd={(e) => handleDragEnd(e, shape.id)}\n />\n );\n }\n\n if (shape.type === 'arrow') {\n return (\n <Arrow\n key={shape.id}\n id={shape.id}\n points={shape.points}\n pointerLength={14}\n pointerWidth={14}\n stroke={shape.stroke}\n fill={shape.fill}\n strokeWidth={shape.strokeWidth}\n rotation={shape.rotation || 0}\n draggable={isSelectable}\n onClick={() => {\n if (isSelectable) setSelectedId(shape.id);\n if (tool === 'eraser') {\n const next = shapes.filter((s) => s.id !== shape.id);\n setShapes(next);\n pushHistory(next);\n }\n }}\n onTap={() => {\n if (isSelectable) setSelectedId(shape.id);\n }}\n onTransformEnd={(e) => handleTransformEnd(e, shape.id)}\n onDragEnd={(e) => handleDragEnd(e, shape.id)}\n />\n );\n }\n\n return null;\n })}\n\n {/* Live Draft Shape during drag */}\n {draftShape && (\n <>\n {draftShape.type === 'line' && (\n <Line\n points={draftShape.points}\n stroke={draftShape.stroke}\n strokeWidth={draftShape.strokeWidth}\n tension={0.5}\n lineCap=\"round\"\n lineJoin=\"round\"\n globalCompositeOperation={\n draftShape.tool === 'eraser'\n ? 'destination-out'\n : 'source-over'\n }\n />\n )}\n {draftShape.type === 'rectangle' && (\n <Rect\n x={draftShape.x}\n y={draftShape.y}\n width={draftShape.width}\n height={draftShape.height}\n stroke={draftShape.stroke}\n strokeWidth={draftShape.strokeWidth}\n dash={[6, 4]}\n />\n )}\n {draftShape.type === 'circle' && (\n <Circle\n x={draftShape.x}\n y={draftShape.y}\n radius={draftShape.radius}\n stroke={draftShape.stroke}\n strokeWidth={draftShape.strokeWidth}\n dash={[6, 4]}\n />\n )}\n {draftShape.type === 'arrow' && (\n <Arrow\n points={draftShape.points}\n pointerLength={14}\n pointerWidth={14}\n stroke={draftShape.stroke}\n fill={draftShape.fill}\n strokeWidth={draftShape.strokeWidth}\n dash={[6, 4]}\n />\n )}\n </>\n )}\n\n {/* Transformer for selected shape */}\n <Transformer\n ref={transformerRef}\n rotateEnabled={true}\n enabledAnchors={[\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n 'middle-left',\n 'middle-right',\n 'top-center',\n 'bottom-center',\n ]}\n borderStroke=\"#3b82f6\"\n borderDash={[4, 4]}\n anchorFill=\"#ffffff\"\n anchorStroke=\"#3b82f6\"\n anchorSize={9}\n anchorCornerRadius={2}\n boundBoxFunc={(oldBox, newBox) => {\n if (newBox.width < 10 || newBox.height < 10) {\n return oldBox;\n }\n return newBox;\n }}\n />\n </Layer>\n </Stage>\n </div>\n )}\n </div>\n\n {/* Bottom helper hints bar */}\n <div className=\"flex h-10 shrink-0 items-center justify-between border-t border-slate-800 bg-slate-900/80 px-4 text-xs text-slate-400\">\n <div className=\"flex items-center gap-4\">\n <span>\n Active tool: <strong className=\"text-slate-200 capitalize\">{tool}</strong>\n </span>\n <span className=\"hidden sm:inline\">\n Use <kbd className=\"rounded bg-slate-800 px-1 py-0.5 text-slate-300\">Ctrl+Z</kbd> to undo, <kbd className=\"rounded bg-slate-800 px-1 py-0.5 text-slate-300\">Del</kbd> to remove selected shape\n </span>\n </div>\n <div>\n {image && (\n <span>\n Original Resolution: {image.naturalWidth} x {image.naturalHeight}px\n </span>\n )}\n </div>\n </div>\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport html2canvas from 'html2canvas';\nimport { Bug, X } from 'lucide-react';\nimport { Form } from './Form';\nimport { KonvaEditor } from './KonvaEditor';\nimport type {\n WidgetProps,\n WidgetPosition,\n WidgetButtonSize,\n ScreenshotItem,\n BugReportData,\n} from '../types';\n\nexport const Widget: React.FC<WidgetProps> = ({\n projectUrl,\n onSubmit,\n uiSettings = {},\n onSuccess,\n onError,\n isOpen: controlledIsOpen,\n onToggle,\n className = '',\n}) => {\n const {\n position = 'bottom-right',\n primaryColor = '#2563eb',\n buttonSize = 'md',\n buttonText,\n buttonIcon,\n zIndex = 99990,\n } = uiSettings;\n\n // Uncontrolled or controlled open state\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n\n const setOpen = (open: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(open);\n }\n onToggle?.(open);\n };\n\n // Screenshots state (max 3)\n const [screenshots, setScreenshots] = useState<ScreenshotItem[]>([]);\n\n // Screenshot capture & Konva editor state\n const [isCapturing, setIsCapturing] = useState(false);\n const [isEditorOpen, setIsEditorOpen] = useState(false);\n const [editingScreenshot, setEditingScreenshot] = useState<{\n id?: string;\n dataUrl: string;\n isNew: boolean;\n } | null>(null);\n\n // Position CSS classes for the trigger button\n const getPositionClasses = (pos: WidgetPosition): string => {\n switch (pos) {\n case 'bottom-left':\n return 'bottom-6 left-6';\n case 'top-left':\n return 'top-6 left-6';\n case 'top-right':\n return 'top-6 right-6';\n case 'left':\n return 'top-1/2 -translate-y-1/2 left-4';\n case 'right':\n return 'top-1/2 -translate-y-1/2 right-4';\n case 'bottom-right':\n default:\n return 'bottom-6 right-6';\n }\n };\n\n // Size CSS classes for the trigger button\n const getSizeClasses = (size: WidgetButtonSize): { button: string; icon: string } => {\n switch (size) {\n case 'sm':\n return {\n button: 'h-10 px-3.5 gap-2 text-xs font-semibold rounded-full shadow-md',\n icon: 'h-4 w-4',\n };\n case 'lg':\n return {\n button: 'h-14 px-5 gap-3 text-base font-bold rounded-full shadow-xl',\n icon: 'h-6 w-6',\n };\n case 'md':\n default:\n return {\n button: 'h-12 px-4 gap-2.5 text-sm font-semibold rounded-full shadow-lg',\n icon: 'h-5 w-5',\n };\n }\n };\n\n const sizeClasses = getSizeClasses(buttonSize);\n\n // Take screenshot flow\n const handleTriggerScreenshot = async () => {\n // 1. Mark as capturing to immediately hide all widget UI (button and form)\n setIsCapturing(true);\n\n try {\n // 2. Wait for DOM to repaint without widget elements\n await new Promise((resolve) => setTimeout(resolve, 180));\n\n // 3. Capture screen using html2canvas\n const canvas = await html2canvas(document.documentElement, {\n useCORS: true,\n allowTaint: true,\n logging: false,\n scrollX: 0,\n scrollY: -window.scrollY,\n windowWidth: document.documentElement.offsetWidth,\n windowHeight: document.documentElement.offsetHeight,\n ignoreElements: (element) => {\n return (\n element.getAttribute('data-bugdrop-widget') === 'true' ||\n element.classList.contains('bugdrop-ignore')\n );\n },\n });\n\n const dataUrl = canvas.toDataURL('image/png');\n\n // 4. Open Konva editor with captured screenshot\n setEditingScreenshot({\n dataUrl,\n isNew: true,\n });\n setIsEditorOpen(true);\n } catch (err) {\n console.error('Error taking screenshot:', err);\n alert('Could not capture screenshot. Please try again.');\n } finally {\n setIsCapturing(false);\n }\n };\n\n // Re-edit an existing screenshot from the form\n const handleEditExistingScreenshot = (item: ScreenshotItem) => {\n setEditingScreenshot({\n id: item.id,\n dataUrl: item.dataUrl,\n isNew: false,\n });\n setIsEditorOpen(true);\n };\n\n // Delete a screenshot\n const handleDeleteScreenshot = (id: string) => {\n setScreenshots((prev) => prev.filter((s) => s.id !== id));\n };\n\n // Save edited screenshot from Konva editor\n const handleSaveEditor = (editedDataUrl: string) => {\n if (editingScreenshot?.isNew) {\n if (screenshots.length < 3) {\n const newItem: ScreenshotItem = {\n id: `ss_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,\n dataUrl: editedDataUrl,\n createdAt: Date.now(),\n };\n setScreenshots((prev) => [...prev, newItem]);\n }\n } else if (editingScreenshot?.id) {\n // Update existing\n setScreenshots((prev) =>\n prev.map((s) =>\n s.id === editingScreenshot.id ? { ...s, dataUrl: editedDataUrl } : s\n )\n );\n }\n\n setIsEditorOpen(false);\n setEditingScreenshot(null);\n setOpen(true); // Return to form\n };\n\n // Cancel Konva editor\n const handleCancelEditor = () => {\n setIsEditorOpen(false);\n setEditingScreenshot(null);\n setOpen(true); // Return to form\n };\n\n // Hand off the report to the consumer's onSubmit handler\n const handleSubmitReport = async (reportData: BugReportData) => {\n try {\n await onSubmit(reportData);\n onSuccess?.(reportData);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to submit bug report');\n onError?.(error);\n throw error;\n }\n };\n\n // If capturing screenshot, completely hide widget elements from DOM/render\n if (isCapturing) {\n return null;\n }\n\n return (\n <>\n {/* Floating Widget Trigger Button */}\n {!isEditorOpen && (\n <div\n data-bugdrop-widget=\"true\"\n className={`fixed ${getPositionClasses(position)} ${className}`}\n style={{ zIndex }}\n >\n <button\n type=\"button\"\n onClick={() => setOpen(!isOpen)}\n style={{ backgroundColor: primaryColor }}\n className={`group flex items-center justify-center text-white transition-all duration-200 hover:brightness-110 active:scale-95 ${sizeClasses.button}`}\n aria-label={isOpen ? 'Close bug report form' : 'Open bug report form'}\n title={isOpen ? 'Close Bug Report' : 'Report a Bug'}\n >\n {isOpen ? (\n <X className={sizeClasses.icon} />\n ) : buttonIcon ? (\n buttonIcon\n ) : (\n <Bug className={sizeClasses.icon} />\n )}\n\n {buttonText && <span>{buttonText}</span>}\n\n {/* Notification Badge if screenshots are attached */}\n {screenshots.length > 0 && !isOpen && (\n <span className=\"flex h-5 w-5 items-center justify-center rounded-full bg-white text-[11px] font-bold text-slate-900 shadow\">\n {screenshots.length}\n </span>\n )}\n </button>\n </div>\n )}\n\n {/* Slide-in Form Drawer */}\n {!isEditorOpen && (\n <Form\n projectUrl={projectUrl}\n isOpen={isOpen}\n onClose={() => setOpen(false)}\n uiSettings={uiSettings}\n screenshots={screenshots}\n onTriggerScreenshot={handleTriggerScreenshot}\n onEditScreenshot={handleEditExistingScreenshot}\n onDeleteScreenshot={handleDeleteScreenshot}\n onSubmitReport={handleSubmitReport}\n />\n )}\n\n {/* Konva Annotation Editor Modal */}\n {isEditorOpen && editingScreenshot && (\n <KonvaEditor\n imageSrc={editingScreenshot.dataUrl}\n onSave={handleSaveEditor}\n onCancel={handleCancelEditor}\n primaryColor={primaryColor}\n />\n )}\n </>\n );\n};"],"mappings":"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"}
1
+ {"version":3,"file":"bug-widget-library.js","names":["_Fragment","CircleIcon","_Fragment","_Fragment","html2canvas","getProjectLabel","projectUrl","Form","uiSettings","isLeft","pos","position","reportTitle","setReportTitle","useState","description","setDescription","isSubmitting","setIsSubmitting","isSuccess","setIsSuccess","submitError","setSubmitError","errors","setErrors","previewImage","setPreviewImage","projectLabel","validate","errs","Fragment","onClose","isOpen","title","primaryColor","Sparkles","subtitle","X","CheckCircle2","screenshots","e","onSubmitReport","err","prev","placeholderTitle","AlertCircle","placeholderDescription","s","idx","Eye","onEditScreenshot","Edit3","onDeleteScreenshot","Trash2","onTriggerScreenshot","Camera","Loader2","konvaPromise","loadKonva","m","mod","useIsomorphicLayoutEffect","useLayoutEffect","useEffect","shapeAttrs","p","shape","base","createNode","attrs","extra","K","PRESET_COLORS","STROKE_WIDTHS","TOOLS","MousePointer","Pencil","Eraser","Square","Circle","ArrowUpRight","TRANSFORMER_ANCHORS","KonvaEditor","containerRef","useRef","stageHostRef","stageRef","layerRef","transformerRef","draftNodeRef","drawingRef","handlersRef","konvaLib","setKonvaLib","loadError","setLoadError","image","setImage","scale","setScale","stageDimensions","setStageDimensions","tool","setTool","color","setColor","strokeWidth","setStrokeWidth","selectedId","setSelectedId","shapes","setShapes","history","setHistory","historyStep","setHistoryStep","cancelled","img","imageSrc","updateDimensions","useCallback","availWidth","availHeight","fitScale","host","stage","bgLayer","layer","transformer","newBox","oldBox","endStroke","node","isSelectable","isEraserStroke","isLine","commit","nextShapes","handleUndo","newStep","handleRedo","handleClearAll","handleDeleteSelected","getPointer","pointer","handlePointerDown","point","target","hitId","hitShape","id","data","x","y","draftNode","handlePointerMove","drawing","next","start","handlePointerUp","draft","isValid","x1","y1","x2","y2","handleDragEnd","handleTransformEnd","scaleX","scaleY","updated","result","handleKeyDown","h","key","handleExport","onSave","selectTool","isReady","Undo2","Redo2","onCancel","Check","Icon","c","Palette","sw","Widget","controlledIsOpen","internalIsOpen","setInternalIsOpen","setOpen","open","onToggle","setScreenshots","isCapturing","setIsCapturing","isEditorOpen","setIsEditorOpen","editingScreenshot","setEditingScreenshot","getPositionClasses","sizeClasses","size","buttonSize","className","buttonIcon","Bug","buttonText","resolve","dataUrl","element","item","onSubmit","reportData","onSuccess","error","onError","newItem","editedDataUrl"],"sources":["../src/components/Form.tsx","../src/components/KonvaEditor.tsx","../src/components/Widget.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Camera,\n X,\n Trash2,\n Edit3,\n Eye,\n CheckCircle2,\n AlertCircle,\n Loader2,\n Sparkles,\n} from 'lucide-react';\nimport type {\n BugReportData,\n ScreenshotItem,\n WidgetUiSettings,\n WidgetPosition,\n} from '../types';\n\ninterface FormProps {\n projectUrl: string;\n isOpen: boolean;\n onClose: () => void;\n uiSettings?: WidgetUiSettings;\n screenshots: ScreenshotItem[];\n onTriggerScreenshot: () => void;\n onEditScreenshot: (screenshot: ScreenshotItem) => void;\n onDeleteScreenshot: (id: string) => void;\n onSubmitReport: (data: BugReportData) => Promise<void> | void;\n}\n\nfunction getProjectLabel(projectUrl: string): string {\n try {\n return new URL(projectUrl).hostname;\n } catch {\n return 'project';\n }\n}\n\nexport const Form: React.FC<FormProps> = ({\n projectUrl,\n isOpen,\n onClose,\n uiSettings = {},\n screenshots,\n onTriggerScreenshot,\n onEditScreenshot,\n onDeleteScreenshot,\n onSubmitReport,\n}) => {\n const {\n position = 'bottom-right',\n primaryColor = '#2563eb',\n title = 'Report a Bug',\n subtitle = 'Found an issue? Let us know with details and screenshots.',\n placeholderTitle = 'e.g. Broken checkout button on cart page',\n placeholderDescription = 'Describe what happened, steps to reproduce, and expected result...',\n } = uiSettings;\n\n const isLeftPosition = (pos: WidgetPosition) =>\n pos === 'bottom-left' || pos === 'top-left' || pos === 'left';\n\n const isLeft = isLeftPosition(position);\n\n // Form input states\n const [reportTitle, setReportTitle] = useState('');\n const [description, setDescription] = useState('');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isSuccess, setIsSuccess] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [errors, setErrors] = useState<{ title?: string; description?: string }>({});\n const [previewImage, setPreviewImage] = useState<string | null>(null);\n const projectLabel = getProjectLabel(projectUrl);\n\n // Form validation\n const validate = () => {\n const errs: { title?: string; description?: string } = {};\n if (!reportTitle.trim()) {\n errs.title = 'Title / bug name is required.';\n }\n if (!description.trim()) {\n errs.description = 'Description is required.';\n }\n setErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!validate()) return;\n\n setIsSubmitting(true);\n setSubmitError(null);\n try {\n const reportData: BugReportData = {\n projectUrl,\n title: reportTitle.trim(),\n description: description.trim(),\n screenshots,\n timestamp: new Date().toISOString(),\n meta: {\n url: window.location.href,\n userAgent: navigator.userAgent,\n timestamp: new Date().toISOString(),\n screenSize: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n },\n };\n\n await onSubmitReport(reportData);\n setIsSuccess(true);\n } catch (err) {\n console.error('Failed to submit bug report:', err);\n setSubmitError(\n err instanceof Error ? err.message : 'Failed to submit bug report. Please try again.'\n );\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleReset = () => {\n setReportTitle('');\n setDescription('');\n setErrors({});\n setSubmitError(null);\n setIsSuccess(false);\n };\n\n // Determine slide animation direction\n const slideClass = isLeft\n ? isOpen\n ? 'translate-x-0 opacity-100 pointer-events-auto'\n : '-translate-x-full opacity-0 pointer-events-none'\n : isOpen\n ? 'translate-x-0 opacity-100 pointer-events-auto'\n : 'translate-x-full opacity-0 pointer-events-none';\n\n return (\n <>\n {/* Subtle backdrop overlay */}\n <div\n data-bugdrop-widget=\"true\"\n onClick={onClose}\n className={`fixed inset-0 z-[99990] bg-slate-900/40 backdrop-blur-sm transition-opacity duration-300 ${\n isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'\n }`}\n />\n\n {/* Slide-in Drawer Container */}\n <aside\n data-bugdrop-widget=\"true\"\n className={`fixed top-0 z-[99995] flex h-full w-full max-w-md flex-col bg-white shadow-2xl transition-all duration-300 ease-out sm:max-w-lg ${\n isLeft ? 'left-0 border-r border-slate-200' : 'right-0 border-l border-slate-200'\n } ${slideClass}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n {/* Header */}\n <div className=\"flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-5\">\n <div className=\"flex items-center gap-3\">\n <div\n className=\"flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-md font-bold\"\n style={{ backgroundColor: primaryColor }}\n >\n <Sparkles className=\"h-5 w-5\" />\n </div>\n <div>\n <div className=\"flex items-center gap-2\">\n <h2 className=\"text-lg font-bold text-slate-800\">{title}</h2>\n <span\n className=\"rounded-md bg-slate-100 px-2 py-0.5 text-[11px] font-semibold tracking-wider text-slate-500\"\n title={projectUrl}\n >\n {projectLabel}\n </span>\n </div>\n <p className=\"mt-0.5 text-xs text-slate-500\">{subtitle}</p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={onClose}\n className=\"flex h-8 w-8 items-center justify-center rounded-lg text-slate-400 transition hover:bg-slate-100 hover:text-slate-600\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n {/* Content Area */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5\">\n {isSuccess ? (\n <div className=\"flex h-full flex-col items-center justify-center text-center py-10 animate-fadeIn\">\n <div\n className=\"flex h-16 w-16 items-center justify-center rounded-full text-white shadow-lg mb-4\"\n style={{ backgroundColor: primaryColor }}\n >\n <CheckCircle2 className=\"h-9 w-9\" />\n </div>\n <h3 className=\"text-xl font-bold text-slate-800\">\n Bug Report Submitted!\n </h3>\n <p className=\"mt-2 text-sm text-slate-500 max-w-xs\">\n Thank you! Your bug report with {screenshots.length} screenshot{screenshots.length !== 1 ? 's' : ''} has been captured and logged.\n </p>\n\n <div className=\"mt-8 flex flex-col sm:flex-row gap-3 w-full\">\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"flex-1 rounded-xl border border-slate-200 bg-white py-2.5 text-sm font-semibold text-slate-700 shadow-sm transition hover:bg-slate-50\"\n >\n Report Another Bug\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n style={{ backgroundColor: primaryColor }}\n className=\"flex-1 rounded-xl py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110\"\n >\n Close\n </button>\n </div>\n </div>\n ) : (\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Bug Title / Name (Required) */}\n <div>\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Bug Title / Name <span className=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n value={reportTitle}\n onChange={(e) => {\n setReportTitle(e.target.value);\n if (errors.title) setErrors((prev) => ({ ...prev, title: undefined }));\n }}\n placeholder={placeholderTitle}\n className={`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${\n errors.title\n ? 'border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400'\n : 'border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500'\n }`}\n />\n {errors.title && (\n <p className=\"mt-1.5 flex items-center gap-1 text-xs text-red-600\">\n <AlertCircle className=\"h-3.5 w-3.5\" />\n <span>{errors.title}</span>\n </p>\n )}\n </div>\n\n {/* Bug Description (Required) */}\n <div>\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Description <span className=\"text-red-500\">*</span>\n </label>\n <textarea\n rows={4}\n value={description}\n onChange={(e) => {\n setDescription(e.target.value);\n if (errors.description) {\n setErrors((prev) => ({ ...prev, description: undefined }));\n }\n }}\n placeholder={placeholderDescription}\n className={`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${\n errors.description\n ? 'border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400'\n : 'border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500'\n }`}\n />\n {errors.description && (\n <p className=\"mt-1.5 flex items-center gap-1 text-xs text-red-600\">\n <AlertCircle className=\"h-3.5 w-3.5\" />\n <span>{errors.description}</span>\n </p>\n )}\n </div>\n\n {/* Screenshots Section (Max 3, Optional) */}\n <div>\n <div className=\"flex items-center justify-between\">\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Screenshots <span className=\"text-slate-400 font-normal lowercase\">(optional)</span>\n </label>\n <span className=\"rounded-full bg-slate-100 px-2 py-0.5 text-xs font-semibold text-slate-600\">\n {screenshots.length} / 3\n </span>\n </div>\n <p className=\"mt-1 text-xs text-slate-500\">\n Capture your screen and annotate with pencil, shapes, or arrows.\n </p>\n\n {/* Screenshot Thumbnails Grid */}\n {screenshots.length > 0 && (\n <div className=\"mt-3 grid grid-cols-3 gap-2.5\">\n {screenshots.map((s, idx) => (\n <div\n key={s.id}\n className=\"group relative aspect-video overflow-hidden rounded-lg border border-slate-200 bg-slate-100 shadow-sm\"\n >\n <img\n src={s.dataUrl}\n alt={`Screenshot ${idx + 1}`}\n className=\"h-full w-full object-cover transition duration-200 group-hover:scale-105\"\n />\n\n {/* Top badge */}\n <span className=\"absolute top-1 left-1 rounded bg-black/60 px-1 py-0.2 text-[10px] font-semibold text-white\">\n #{idx + 1}\n </span>\n\n {/* Hover Overlay with actions */}\n <div className=\"absolute inset-0 flex items-center justify-center gap-1.5 bg-black/50 opacity-0 backdrop-blur-[1px] transition-opacity duration-200 group-hover:opacity-100\">\n <button\n type=\"button\"\n onClick={() => setPreviewImage(s.dataUrl)}\n title=\"Preview screenshot\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600\"\n >\n <Eye className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onEditScreenshot(s)}\n title=\"Re-edit / annotate\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600\"\n >\n <Edit3 className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteScreenshot(s.id)}\n title=\"Delete screenshot\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-red-600 text-white shadow transition hover:bg-red-700\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Add Screenshot Trigger Button */}\n <div className=\"mt-3\">\n {screenshots.length < 3 ? (\n <button\n type=\"button\"\n onClick={onTriggerScreenshot}\n className=\"flex w-full items-center justify-center gap-2 rounded-xl border-2 border-dashed border-slate-300 bg-slate-50/70 py-3 text-xs font-semibold text-slate-600 transition hover:border-blue-400 hover:bg-blue-50/50 hover:text-blue-600\"\n >\n <Camera className=\"h-4 w-4 text-slate-500\" />\n <span>\n {screenshots.length === 0\n ? 'Capture Screen & Annotate'\n : `Capture Another Screenshot (${3 - screenshots.length} left)`}\n </span>\n </button>\n ) : (\n <div className=\"rounded-lg bg-amber-50 p-2.5 text-center text-xs text-amber-700 border border-amber-200\">\n Maximum 3 screenshots attached. Delete one to take a new one.\n </div>\n )}\n </div>\n </div>\n\n {submitError && (\n <div className=\"rounded-xl border border-red-200 bg-red-50 px-3.5 py-2.5 text-xs text-red-700 flex items-start gap-2\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{submitError}</span>\n </div>\n )}\n\n {/* Form Actions */}\n <div className=\"pt-4 border-t border-slate-100 flex items-center justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-600 transition hover:bg-slate-50\"\n >\n Cancel\n </button>\n\n <button\n type=\"submit\"\n disabled={isSubmitting}\n style={{ backgroundColor: primaryColor }}\n className=\"flex items-center gap-2 rounded-xl px-5 py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95 disabled:opacity-60\"\n >\n {isSubmitting ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span>Submitting...</span>\n </>\n ) : (\n <span>Submit Bug Report</span>\n )}\n </button>\n </div>\n </form>\n )}\n </div>\n </aside>\n\n {/* Lightbox Preview Modal for zoomed screenshot */}\n {previewImage && (\n <div\n data-bugdrop-widget=\"true\"\n onClick={() => setPreviewImage(null)}\n className=\"fixed inset-0 z-[100001] flex items-center justify-center bg-black/80 p-4 backdrop-blur-sm animate-fadeIn\"\n >\n <div\n className=\"relative max-h-[90vh] max-w-[90vw] overflow-hidden rounded-xl bg-slate-900 shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n <img\n src={previewImage}\n alt=\"Screenshot Preview\"\n className=\"max-h-[85vh] w-auto rounded-xl object-contain\"\n />\n <button\n type=\"button\"\n onClick={() => setPreviewImage(null)}\n className=\"absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-black/60 text-white shadow hover:bg-black/90\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n )}\n </>\n );\n};","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\nimport type Konva from 'konva';\nimport {\n Pencil,\n Eraser,\n Square,\n Circle as CircleIcon,\n ArrowUpRight,\n MousePointer,\n Undo2,\n Redo2,\n Trash2,\n Check,\n X,\n Palette,\n} from 'lucide-react';\nimport type {\n EditorTool,\n AnnotationShape,\n LineAnnotation,\n RectAnnotation,\n CircleAnnotation,\n ArrowAnnotation,\n} from '../types';\n\ntype KonvaModule = typeof Konva;\ntype ConfigOf<K extends keyof KonvaModule> = KonvaModule[K] extends new (config?: infer C) => unknown\n ? NonNullable<C>\n : never;\n\nlet konvaPromise: Promise<KonvaModule> | null = null;\n\nfunction loadKonva(): Promise<KonvaModule> {\n if (!konvaPromise) {\n konvaPromise = import('konva')\n .then((mod) => {\n const m = mod as unknown as KonvaModule & { default?: KonvaModule };\n return m.default ?? m;\n })\n .catch((err: unknown) => {\n konvaPromise = null; // allow a retry on next mount\n throw err;\n });\n }\n return konvaPromise;\n}\n\n// useLayoutEffect warns during SSR on React 18; fall back to useEffect on the server.\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\n\ntype Positioned = { x?: number; y?: number; rotation?: number };\n\n/** Konva attributes for a shape, used both to create nodes and to update the live draft. */\nfunction shapeAttrs(shape: AnnotationShape) {\n const p = shape as Positioned;\n const base = { stroke: shape.stroke, strokeWidth: shape.strokeWidth, rotation: p.rotation ?? 0 };\n\n switch (shape.type) {\n case 'line':\n return {\n ...base,\n x: p.x ?? 0,\n y: p.y ?? 0,\n points: shape.points,\n tension: 0.5,\n lineCap: 'round' as const,\n lineJoin: 'round' as const,\n globalCompositeOperation:\n shape.tool === 'eraser' ? ('destination-out' as const) : ('source-over' as const),\n };\n case 'rectangle':\n return { ...base, x: shape.x, y: shape.y, width: shape.width, height: shape.height };\n case 'circle':\n return { ...base, x: shape.x, y: shape.y, radius: shape.radius };\n case 'arrow':\n return {\n ...base,\n x: p.x ?? 0,\n y: p.y ?? 0,\n points: shape.points,\n fill: shape.fill,\n pointerLength: 14,\n pointerWidth: 14,\n };\n default:\n return base;\n }\n}\n\nfunction createNode(\n K: KonvaModule,\n shape: AnnotationShape,\n extra: Record<string, unknown>\n): Konva.Shape | null {\n const attrs = { ...shapeAttrs(shape), ...extra };\n switch (shape.type) {\n case 'line':\n return new K.Line(attrs as ConfigOf<'Line'>);\n case 'rectangle':\n return new K.Rect(attrs as ConfigOf<'Rect'>);\n case 'circle':\n return new K.Circle(attrs as ConfigOf<'Circle'>);\n case 'arrow':\n return new K.Arrow(attrs as ConfigOf<'Arrow'>);\n default:\n return null;\n }\n}\n\n\ninterface KonvaEditorProps {\n imageSrc: string;\n onSave: (editedDataUrl: string) => void;\n onCancel: () => void;\n primaryColor?: string;\n}\n\nconst PRESET_COLORS = [\n '#ef4444', // Red\n '#f97316', // Orange\n '#eab308', // Yellow\n '#10b981', // Green\n '#3b82f6', // Blue\n '#8b5cf6', // Purple\n '#ec4899', // Pink\n '#000000', // Black\n '#ffffff', // White\n];\n\nconst STROKE_WIDTHS = [\n { label: 'S', value: 3 },\n { label: 'M', value: 6 },\n { label: 'L', value: 10 },\n { label: 'XL', value: 16 },\n];\n\nconst TOOLS: { id: EditorTool; title: string; Icon: React.ComponentType<{ className?: string }> }[] = [\n { id: 'select', title: 'Select & Move / Resize', Icon: MousePointer },\n { id: 'pencil', title: 'Pencil / Draw', Icon: Pencil },\n { id: 'eraser', title: 'Eraser (click or drag to erase)', Icon: Eraser },\n { id: 'rectangle', title: 'Rectangle (Resizable)', Icon: Square },\n { id: 'circle', title: 'Circle (Resizable)', Icon: CircleIcon },\n { id: 'arrow', title: 'Arrow (Resizable)', Icon: ArrowUpRight },\n];\n\nconst TRANSFORMER_ANCHORS = [\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n 'middle-left',\n 'middle-right',\n 'top-center',\n 'bottom-center',\n];\n\ninterface Handlers {\n pointerDown: (e: Konva.KonvaEventObject<PointerEvent>) => void;\n pointerMove: () => void;\n pointerUp: () => void;\n dragEnd: (node: Konva.Node, id: string) => void;\n transformEnd: (node: Konva.Node, id: string) => void;\n undo: () => void;\n redo: () => void;\n deleteSelected: () => void;\n hasSelection: () => boolean;\n clearSelection: () => void;\n}\n\ninterface DrawingState {\n start: { x: number; y: number };\n data: AnnotationShape;\n}\n\n\nexport const KonvaEditor: React.FC<KonvaEditorProps> = ({\n imageSrc,\n onSave,\n onCancel,\n primaryColor = '#2563eb',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const stageHostRef = useRef<HTMLDivElement>(null);\n\n // Imperative Konva objects\n const stageRef = useRef<Konva.Stage | null>(null);\n const layerRef = useRef<Konva.Layer | null>(null);\n const transformerRef = useRef<Konva.Transformer | null>(null);\n const draftNodeRef = useRef<Konva.Shape | null>(null);\n const drawingRef = useRef<DrawingState | null>(null);\n\n // Always points at the latest handlers, so Konva listeners never use stale state\n const handlersRef = useRef<Handlers | null>(null);\n\n const [konvaLib, setKonvaLib] = useState<KonvaModule | null>(null);\n const [loadError, setLoadError] = useState<string | null>(null);\n const [image, setImage] = useState<HTMLImageElement | null>(null);\n const [scale, setScale] = useState<number>(1);\n const [stageDimensions, setStageDimensions] = useState({ width: 800, height: 600 });\n\n // Tool state\n const [tool, setTool] = useState<EditorTool>('pencil');\n const [color, setColor] = useState<string>('#ef4444');\n const [strokeWidth, setStrokeWidth] = useState<number>(6);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n // Shapes & history\n const [shapes, setShapes] = useState<AnnotationShape[]>([]);\n const [history, setHistory] = useState<AnnotationShape[][]>([[]]);\n const [historyStep, setHistoryStep] = useState<number>(0);\n\n\n\n useEffect(() => {\n let cancelled = false;\n loadKonva()\n .then((K) => {\n if (!cancelled) setKonvaLib(() => K);\n })\n .catch(() => {\n if (!cancelled) setLoadError('The annotation editor could not load. Check your connection and try again.');\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n const img = new window.Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => setImage(img);\n img.src = imageSrc;\n return () => {\n img.onload = null;\n };\n }, [imageSrc]);\n\n // Responsive sizing \n\n const updateDimensions = useCallback(() => {\n if (!containerRef.current || !image) return;\n const paddingX = 48;\n const paddingY = 120;\n const availWidth = Math.max(300, containerRef.current.clientWidth - paddingX);\n const availHeight = Math.max(300, containerRef.current.clientHeight - paddingY);\n\n const fitScale = Math.min(availWidth / image.naturalWidth, availHeight / image.naturalHeight, 1);\n\n setScale(fitScale);\n setStageDimensions({\n width: Math.round(image.naturalWidth * fitScale),\n height: Math.round(image.naturalHeight * fitScale),\n });\n }, [image]);\n\n useEffect(() => {\n updateDimensions();\n window.addEventListener('resize', updateDimensions);\n return () => window.removeEventListener('resize', updateDimensions);\n }, [updateDimensions]);\n\n // Effects below run in declaration order, so the stage always exists\n // before the size / shape / selection effects that depend on it.\n\n useEffect(() => {\n const host = stageHostRef.current;\n if (!konvaLib || !image || !host) return;\n const K = konvaLib;\n\n const stage = new K.Stage({ container: host, width: 1, height: 1 });\n\n const bgLayer = new K.Layer({ listening: false });\n bgLayer.add(\n new K.Image({\n name: 'bg-image',\n image,\n width: image.naturalWidth,\n height: image.naturalHeight,\n })\n );\n\n const layer = new K.Layer();\n const transformer = new K.Transformer({\n rotateEnabled: true,\n enabledAnchors: TRANSFORMER_ANCHORS,\n borderStroke: '#3b82f6',\n borderDash: [4, 4],\n anchorFill: '#ffffff',\n anchorStroke: '#3b82f6',\n anchorSize: 9,\n anchorCornerRadius: 2,\n boundBoxFunc: (oldBox, newBox) =>\n Math.abs(newBox.width) < 10 || Math.abs(newBox.height) < 10 ? oldBox : newBox,\n });\n layer.add(transformer);\n stage.add(bgLayer);\n stage.add(layer);\n\n stage.on('pointerdown', (e) => handlersRef.current?.pointerDown(e));\n stage.on('pointermove', () => handlersRef.current?.pointerMove());\n stage.on('pointerup', () => handlersRef.current?.pointerUp());\n\n // Finish a stroke even if the pointer is released outside the canvas\n const endStroke = () => handlersRef.current?.pointerUp();\n window.addEventListener('pointerup', endStroke);\n window.addEventListener('pointercancel', endStroke);\n\n stageRef.current = stage;\n layerRef.current = layer;\n transformerRef.current = transformer;\n\n return () => {\n window.removeEventListener('pointerup', endStroke);\n window.removeEventListener('pointercancel', endStroke);\n drawingRef.current = null;\n draftNodeRef.current = null;\n stage.destroy();\n stageRef.current = null;\n layerRef.current = null;\n transformerRef.current = null;\n };\n }, [konvaLib, image]);\n\n useEffect(() => {\n const stage = stageRef.current;\n if (!stage) return;\n stage.size(stageDimensions);\n stage.scale({ x: scale, y: scale });\n }, [konvaLib, image, scale, stageDimensions]);\n\n // Rebuild annotation nodes whenever the shape list or tool changes\n useEffect(() => {\n const K = konvaLib;\n const layer = layerRef.current;\n const transformer = transformerRef.current;\n if (!K || !layer || !transformer) return;\n\n transformer.nodes([]);\n layer.find('.annotation').forEach((node) => node.destroy());\n\n const isSelectable = tool === 'select';\n shapes.forEach((shape) => {\n const isEraserStroke = shape.type === 'line' && shape.tool === 'eraser';\n const node = createNode(K, shape, {\n id: shape.id,\n name: 'annotation',\n draggable: isSelectable && !isEraserStroke,\n hitStrokeWidth: Math.max(shape.strokeWidth, 12), // easier to click thin strokes\n });\n if (!node) return;\n node.on('dragend', () => handlersRef.current?.dragEnd(node, shape.id));\n node.on('transformend', () => handlersRef.current?.transformEnd(node, shape.id));\n layer.add(node);\n });\n\n transformer.moveToTop();\n }, [konvaLib, image, shapes, tool]);\n\n // Attach the transformer to the selected shape\n useEffect(() => {\n const layer = layerRef.current;\n const transformer = transformerRef.current;\n if (!layer || !transformer) return;\n\n const node = selectedId ? layer.findOne('#' + selectedId) : undefined;\n if (!node) {\n transformer.nodes([]);\n return;\n }\n // Free-hand lines can be moved but not resized or rotated\n const isLine = node.getClassName() === 'Line';\n transformer.resizeEnabled(!isLine);\n transformer.rotateEnabled(!isLine);\n transformer.nodes([node]);\n }, [konvaLib, image, shapes, tool, selectedId]);\n\n\n const commit = (nextShapes: AnnotationShape[]) => {\n setShapes(nextShapes);\n setHistory([...history.slice(0, historyStep + 1), nextShapes]);\n setHistoryStep(historyStep + 1);\n };\n\n const handleUndo = () => {\n if (historyStep <= 0) return;\n const newStep = historyStep - 1;\n setHistoryStep(newStep);\n setShapes(history[newStep]);\n setSelectedId(null);\n };\n\n const handleRedo = () => {\n if (historyStep >= history.length - 1) return;\n const newStep = historyStep + 1;\n setHistoryStep(newStep);\n setShapes(history[newStep]);\n setSelectedId(null);\n };\n\n const handleClearAll = () => {\n if (shapes.length === 0) return;\n commit([]);\n setSelectedId(null);\n };\n\n const handleDeleteSelected = () => {\n if (!selectedId) return;\n commit(shapes.filter((s) => s.id !== selectedId));\n setSelectedId(null);\n };\n\n // Drawing \n\n const getPointer = () => {\n const pointer = stageRef.current?.getPointerPosition();\n return pointer ? { x: pointer.x / scale, y: pointer.y / scale } : null;\n };\n\n const handlePointerDown = (e: Konva.KonvaEventObject<PointerEvent>) => {\n const stage = stageRef.current;\n const layer = layerRef.current;\n const K = konvaLib;\n if (!stage || !layer || !K || drawingRef.current) return;\n\n const point = getPointer();\n if (!point) return;\n const { x, y } = point;\n\n const target = e.target;\n const hitId = target !== stage ? target.id() : '';\n const hitShape = hitId ? shapes.find((s) => s.id === hitId) : undefined;\n\n if (tool === 'select') {\n if (hitShape) {\n if (!(hitShape.type === 'line' && hitShape.tool === 'eraser')) setSelectedId(hitShape.id);\n } else if (target === stage || target.hasName('bg-image')) {\n setSelectedId(null);\n }\n return;\n }\n\n // Eraser click on an existing annotation removes it\n if (tool === 'eraser' && hitShape) {\n commit(shapes.filter((s) => s.id !== hitShape.id));\n setSelectedId(null);\n return;\n }\n\n setSelectedId(null);\n\n const id = `shape_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n let data: AnnotationShape;\n\n if (tool === 'pencil' || tool === 'eraser') {\n data = {\n id,\n type: 'line',\n tool,\n points: [x, y],\n stroke: tool === 'eraser' ? '#ffffff' : color,\n strokeWidth: tool === 'eraser' ? strokeWidth * 2.5 : strokeWidth,\n } satisfies LineAnnotation;\n } else if (tool === 'rectangle') {\n data = { id, type: 'rectangle', x, y, width: 0, height: 0, stroke: color, strokeWidth } satisfies RectAnnotation;\n } else if (tool === 'circle') {\n data = { id, type: 'circle', x, y, radius: 0, stroke: color, strokeWidth } satisfies CircleAnnotation;\n } else {\n data = {\n id,\n type: 'arrow',\n points: [x, y, x, y],\n stroke: color,\n fill: color,\n strokeWidth,\n } satisfies ArrowAnnotation;\n }\n\n const draftNode = createNode(K, data, {\n listening: false,\n dash: data.type === 'line' ? undefined : [6, 4],\n });\n if (!draftNode) return;\n layer.add(draftNode);\n draftNodeRef.current = draftNode;\n drawingRef.current = { start: { x, y }, data };\n };\n\n const handlePointerMove = () => {\n const drawing = drawingRef.current;\n if (!drawing) return;\n const point = getPointer();\n if (!point) return;\n const { x, y } = point;\n const { start, data } = drawing;\n\n let next: AnnotationShape = data;\n if (data.type === 'line') {\n next = { ...data, points: [...data.points, x, y] };\n } else if (data.type === 'rectangle') {\n next = {\n ...data,\n x: Math.min(start.x, x),\n y: Math.min(start.y, y),\n width: Math.abs(x - start.x),\n height: Math.abs(y - start.y),\n };\n } else if (data.type === 'circle') {\n next = { ...data, radius: Math.hypot(x - start.x, y - start.y) };\n } else if (data.type === 'arrow') {\n next = { ...data, points: [start.x, start.y, x, y] };\n }\n\n drawing.data = next;\n // Update the canvas directly: no React re-render on every pointer move\n draftNodeRef.current?.setAttrs(shapeAttrs(next));\n };\n\n const handlePointerUp = () => {\n const drawing = drawingRef.current;\n if (!drawing) return;\n drawingRef.current = null;\n draftNodeRef.current?.destroy();\n draftNodeRef.current = null;\n\n const draft = drawing.data;\n let isValid = false;\n if (draft.type === 'line') {\n isValid = draft.points.length >= 2;\n } else if (draft.type === 'rectangle') {\n isValid = draft.width > 6 && draft.height > 6;\n } else if (draft.type === 'circle') {\n isValid = draft.radius > 5;\n } else if (draft.type === 'arrow') {\n const [x1, y1, x2, y2] = draft.points;\n isValid = Math.hypot(x2 - x1, y2 - y1) > 10;\n }\n if (!isValid) return;\n\n commit([...shapes, draft]);\n\n // Select new boxes, circles and arrows right away so they can be resized\n if (draft.type === 'rectangle' || draft.type === 'circle' || draft.type === 'arrow') {\n setSelectedId(draft.id);\n setTool('select');\n }\n };\n\n // Drag & transform \n\n const handleDragEnd = (node: Konva.Node, id: string) => {\n if (!shapes.some((s) => s.id === id)) return;\n commit(shapes.map((s) => (s.id === id ? { ...s, x: node.x(), y: node.y() } : s)));\n };\n\n const handleTransformEnd = (node: Konva.Node, id: string) => {\n const target = shapes.find((s) => s.id === id);\n if (!target) return;\n\n const scaleX = node.scaleX();\n const scaleY = node.scaleY();\n node.scaleX(1);\n node.scaleY(1);\n\n let updated: AnnotationShape | null = null;\n if (target.type === 'rectangle') {\n updated = {\n ...target,\n x: node.x(),\n y: node.y(),\n width: Math.max(10, node.width() * scaleX),\n height: Math.max(10, node.height() * scaleY),\n rotation: node.rotation(),\n };\n } else if (target.type === 'circle') {\n updated = {\n ...target,\n x: node.x(),\n y: node.y(),\n radius: Math.max(6, target.radius * scaleX),\n rotation: node.rotation(),\n };\n } else if (target.type === 'arrow') {\n const [x1, y1, x2, y2] = target.points;\n updated = {\n ...target,\n x: node.x(),\n y: node.y(),\n points: [x1, y1, x1 + (x2 - x1) * scaleX, y1 + (y2 - y1) * scaleY],\n rotation: node.rotation(),\n };\n }\n if (!updated) return;\n const result = updated;\n commit(shapes.map((s) => (s.id === id ? result : s)));\n };\n\n // Keep Konva listeners and the keyboard handler pointed at the latest closures\n useIsomorphicLayoutEffect(() => {\n handlersRef.current = {\n pointerDown: handlePointerDown,\n pointerMove: handlePointerMove,\n pointerUp: handlePointerUp,\n dragEnd: handleDragEnd,\n transformEnd: handleTransformEnd,\n undo: handleUndo,\n redo: handleRedo,\n deleteSelected: handleDeleteSelected,\n hasSelection: () => selectedId !== null,\n clearSelection: () => setSelectedId(null),\n };\n });\n\n // Keyboard shortcuts\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n const h = handlersRef.current;\n if (!h) return;\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;\n\n const mod = e.ctrlKey || e.metaKey;\n const key = e.key.toLowerCase();\n if (mod && key === 'z') {\n if (e.shiftKey) h.redo();\n else h.undo();\n e.preventDefault();\n } else if (mod && key === 'y') {\n h.redo();\n e.preventDefault();\n } else if ((e.key === 'Delete' || e.key === 'Backspace') && h.hasSelection()) {\n h.deleteSelected();\n e.preventDefault();\n } else if (e.key === 'Escape') {\n h.clearSelection();\n e.preventDefault();\n }\n };\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, []);\n\n // Export\n\n const handleExport = () => {\n const stage = stageRef.current;\n if (!stage) return;\n // Detach transformer handles synchronously so they never appear in the export\n transformerRef.current?.nodes([]);\n setSelectedId(null);\n const exportedDataUrl = stage.toDataURL({ pixelRatio: 1 / scale, mimeType: 'image/png' });\n onSave(exportedDataUrl);\n };\n\n // Render\n\n const selectTool = (next: EditorTool) => {\n setTool(next);\n if (next !== 'select') setSelectedId(null);\n };\n\n const isReady = Boolean(image && konvaLib);\n\n return (\n <div\n ref={containerRef}\n className=\"fixed inset-0 z-[100000] flex flex-col bg-slate-950/90 backdrop-blur-md select-none text-white overflow-hidden animate-fadeIn\"\n style={{ touchAction: 'none' }}\n >\n {/* Top Header Bar */}\n <div className=\"flex h-16 shrink-0 items-center justify-between border-b border-slate-800 bg-slate-900/90 px-4 sm:px-6\">\n <div className=\"flex items-center gap-3\">\n <div\n className=\"flex h-8 w-8 items-center justify-center rounded-lg text-white font-bold text-sm shadow\"\n style={{ backgroundColor: primaryColor }}\n >\n BD\n </div>\n <div>\n <h1 className=\"text-sm sm:text-base font-semibold leading-tight text-slate-100\">Screenshot Editor</h1>\n <p className=\"text-xs text-slate-400 hidden sm:block\">\n Highlight issues with pencil, arrows, circles, and boxes\n </p>\n </div>\n </div>\n\n {/* Top Actions: Undo, Redo, Clear, Cancel, Save */}\n <div className=\"flex items-center gap-2 sm:gap-3\">\n <button\n type=\"button\"\n onClick={handleUndo}\n disabled={historyStep <= 0}\n title=\"Undo (Ctrl+Z)\"\n className=\"flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Undo2 className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={handleRedo}\n disabled={historyStep >= history.length - 1}\n title=\"Redo (Ctrl+Y)\"\n className=\"flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Redo2 className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={handleClearAll}\n disabled={shapes.length === 0}\n title=\"Clear all annotations\"\n className=\"flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-2.5 text-xs font-medium text-slate-300 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n <span className=\"hidden md:inline\">Clear All</span>\n </button>\n\n <div className=\"h-5 w-px bg-slate-700 mx-1\" />\n\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-3 text-xs sm:text-sm font-medium text-slate-200 transition hover:bg-slate-700 hover:text-white\"\n >\n <X className=\"h-4 w-4\" />\n <span>Cancel</span>\n </button>\n\n <button\n type=\"button\"\n onClick={handleExport}\n disabled={!isReady}\n style={{ backgroundColor: primaryColor }}\n className=\"flex h-9 items-center gap-1.5 rounded-lg px-4 text-xs sm:text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95 disabled:opacity-50 disabled:pointer-events-none\"\n >\n <Check className=\"h-4 w-4\" />\n <span>Add to Report</span>\n </button>\n </div>\n </div>\n\n {/* Floating Toolbar */}\n <div className=\"absolute top-20 left-1/2 -translate-x-1/2 z-20 flex flex-wrap items-center justify-center gap-2 rounded-2xl border border-slate-700/80 bg-slate-900/95 p-2 shadow-2xl backdrop-blur-md\">\n {/* Tool selector buttons */}\n <div className=\"flex items-center gap-1\">\n {TOOLS.map(({ id, title, Icon }) => (\n <button\n key={id}\n type=\"button\"\n onClick={() => selectTool(id)}\n title={title}\n aria-pressed={tool === id}\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === id ? 'bg-blue-600 text-white shadow-inner' : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <Icon className=\"h-4 w-4\" />\n </button>\n ))}\n </div>\n\n <div className=\"h-5 w-px bg-slate-700\" />\n\n {/* Color Palette Switcher */}\n <div className=\"flex items-center gap-1.5 px-1\">\n {PRESET_COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => setColor(c)}\n title={c}\n aria-label={`Color ${c}`}\n style={{ backgroundColor: c }}\n className={`h-5 w-5 rounded-full border border-slate-700 transition-transform ${\n color === c ? 'scale-125 ring-2 ring-white ring-offset-1 ring-offset-slate-900' : 'hover:scale-110'\n }`}\n />\n ))}\n\n {/* Custom color input */}\n <label\n title=\"Custom Color\"\n className=\"relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-full border border-slate-600 bg-slate-800 text-slate-300 hover:text-white transition\"\n >\n <Palette className=\"h-3.5 w-3.5\" />\n <input\n type=\"color\"\n value={color}\n onChange={(e) => setColor(e.target.value)}\n className=\"absolute inset-0 opacity-0 cursor-pointer\"\n />\n </label>\n </div>\n\n <div className=\"h-5 w-px bg-slate-700\" />\n\n {/* Stroke Width Selector */}\n <div className=\"flex items-center gap-1\">\n {STROKE_WIDTHS.map((sw) => (\n <button\n key={sw.value}\n type=\"button\"\n onClick={() => setStrokeWidth(sw.value)}\n className={`flex h-7 w-7 items-center justify-center rounded-lg text-xs font-semibold transition ${\n strokeWidth === sw.value\n ? 'bg-slate-700 text-white ring-1 ring-slate-400'\n : 'text-slate-400 hover:bg-slate-800 hover:text-white'\n }`}\n >\n {sw.label}\n </button>\n ))}\n </div>\n\n {/* Delete button if a shape is selected */}\n {selectedId && (\n <>\n <div className=\"h-5 w-px bg-slate-700\" />\n <button\n type=\"button\"\n onClick={handleDeleteSelected}\n title=\"Delete Selected Shape (Del / Backspace)\"\n className=\"flex h-8 items-center gap-1.5 rounded-xl bg-red-600/90 px-3 text-xs font-semibold text-white shadow hover:bg-red-600\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n <span>Delete</span>\n </button>\n </>\n )}\n </div>\n\n {/* Main Canvas Workspace */}\n <div className=\"relative flex flex-1 items-center justify-center p-4 overflow-hidden\">\n {loadError ? (\n <p className=\"text-sm text-red-300\">{loadError}</p>\n ) : !isReady ? (\n <div className=\"flex flex-col items-center gap-2 text-slate-400\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-blue-500 border-t-transparent\" />\n <p className=\"text-sm\">Loading screenshot...</p>\n </div>\n ) : (\n <div\n className=\"relative shadow-2xl rounded-md overflow-hidden border border-slate-700 bg-slate-900\"\n style={{\n width: stageDimensions.width,\n height: stageDimensions.height,\n cursor: tool === 'select' ? 'default' : tool === 'eraser' ? 'cell' : 'crosshair',\n }}\n >\n <div ref={stageHostRef} />\n </div>\n )}\n </div>\n\n {/* Bottom helper hints bar */}\n <div className=\"flex h-10 shrink-0 items-center justify-between border-t border-slate-800 bg-slate-900/80 px-4 text-xs text-slate-400\">\n <div className=\"flex items-center gap-4\">\n <span>\n Active tool: <strong className=\"text-slate-200 capitalize\">{tool}</strong>\n </span>\n <span className=\"hidden sm:inline\">\n Use <kbd className=\"rounded bg-slate-800 px-1 py-0.5 text-slate-300\">Ctrl+Z</kbd> to undo,{' '}\n <kbd className=\"rounded bg-slate-800 px-1 py-0.5 text-slate-300\">Del</kbd> to remove selected shape\n </span>\n </div>\n <div>\n {image && (\n <span>\n Original Resolution: {image.naturalWidth} x {image.naturalHeight}px\n </span>\n )}\n </div>\n </div>\n </div>\n );\n};","import React, { useState } from 'react';\nimport html2canvas from 'html2canvas';\nimport { Bug, X } from 'lucide-react';\nimport { Form } from './Form';\nimport { KonvaEditor } from './KonvaEditor';\nimport type {\n WidgetProps,\n WidgetPosition,\n WidgetButtonSize,\n ScreenshotItem,\n BugReportData,\n} from '../types';\n\nexport const Widget: React.FC<WidgetProps> = ({\n projectUrl,\n onSubmit,\n uiSettings = {},\n onSuccess,\n onError,\n isOpen: controlledIsOpen,\n onToggle,\n className = '',\n}) => {\n const {\n position = 'bottom-right',\n primaryColor = '#2563eb',\n buttonSize = 'md',\n buttonText,\n buttonIcon,\n zIndex = 99990,\n } = uiSettings;\n\n // Uncontrolled or controlled open state\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n\n const setOpen = (open: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(open);\n }\n onToggle?.(open);\n };\n\n // Screenshots state (max 3)\n const [screenshots, setScreenshots] = useState<ScreenshotItem[]>([]);\n\n // Screenshot capture & Konva editor state\n const [isCapturing, setIsCapturing] = useState(false);\n const [isEditorOpen, setIsEditorOpen] = useState(false);\n const [editingScreenshot, setEditingScreenshot] = useState<{\n id?: string;\n dataUrl: string;\n isNew: boolean;\n } | null>(null);\n\n // Position CSS classes for the trigger button\n const getPositionClasses = (pos: WidgetPosition): string => {\n switch (pos) {\n case 'bottom-left':\n return 'bottom-6 left-6';\n case 'top-left':\n return 'top-6 left-6';\n case 'top-right':\n return 'top-6 right-6';\n case 'left':\n return 'top-1/2 -translate-y-1/2 left-4';\n case 'right':\n return 'top-1/2 -translate-y-1/2 right-4';\n case 'bottom-right':\n default:\n return 'bottom-6 right-6';\n }\n };\n\n // Size CSS classes for the trigger button\n const getSizeClasses = (size: WidgetButtonSize): { button: string; icon: string } => {\n switch (size) {\n case 'sm':\n return {\n button: 'h-10 px-3.5 gap-2 text-xs font-semibold rounded-full shadow-md',\n icon: 'h-4 w-4',\n };\n case 'lg':\n return {\n button: 'h-14 px-5 gap-3 text-base font-bold rounded-full shadow-xl',\n icon: 'h-6 w-6',\n };\n case 'md':\n default:\n return {\n button: 'h-12 px-4 gap-2.5 text-sm font-semibold rounded-full shadow-lg',\n icon: 'h-5 w-5',\n };\n }\n };\n\n const sizeClasses = getSizeClasses(buttonSize);\n\n // Take screenshot flow\n const handleTriggerScreenshot = async () => {\n // 1. Mark as capturing to immediately hide all widget UI (button and form)\n setIsCapturing(true);\n\n try {\n // 2. Wait for DOM to repaint without widget elements\n await new Promise((resolve) => setTimeout(resolve, 180));\n\n // 3. Capture screen using html2canvas\n const canvas = await html2canvas(document.documentElement, {\n useCORS: true,\n allowTaint: true,\n logging: false,\n scrollX: 0,\n scrollY: -window.scrollY,\n windowWidth: document.documentElement.offsetWidth,\n windowHeight: document.documentElement.offsetHeight,\n ignoreElements: (element) => {\n return (\n element.getAttribute('data-bugdrop-widget') === 'true' ||\n element.classList.contains('bugdrop-ignore')\n );\n },\n });\n\n const dataUrl = canvas.toDataURL('image/png');\n\n // 4. Open Konva editor with captured screenshot\n setEditingScreenshot({\n dataUrl,\n isNew: true,\n });\n setIsEditorOpen(true);\n } catch (err) {\n console.error('Error taking screenshot:', err);\n alert('Could not capture screenshot. Please try again.');\n } finally {\n setIsCapturing(false);\n }\n };\n\n // Re-edit an existing screenshot from the form\n const handleEditExistingScreenshot = (item: ScreenshotItem) => {\n setEditingScreenshot({\n id: item.id,\n dataUrl: item.dataUrl,\n isNew: false,\n });\n setIsEditorOpen(true);\n };\n\n // Delete a screenshot\n const handleDeleteScreenshot = (id: string) => {\n setScreenshots((prev) => prev.filter((s) => s.id !== id));\n };\n\n // Save edited screenshot from Konva editor\n const handleSaveEditor = (editedDataUrl: string) => {\n if (editingScreenshot?.isNew) {\n if (screenshots.length < 3) {\n const newItem: ScreenshotItem = {\n id: `ss_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,\n dataUrl: editedDataUrl,\n createdAt: Date.now(),\n };\n setScreenshots((prev) => [...prev, newItem]);\n }\n } else if (editingScreenshot?.id) {\n // Update existing\n setScreenshots((prev) =>\n prev.map((s) =>\n s.id === editingScreenshot.id ? { ...s, dataUrl: editedDataUrl } : s\n )\n );\n }\n\n setIsEditorOpen(false);\n setEditingScreenshot(null);\n setOpen(true); // Return to form\n };\n\n // Cancel Konva editor\n const handleCancelEditor = () => {\n setIsEditorOpen(false);\n setEditingScreenshot(null);\n setOpen(true); // Return to form\n };\n\n // Hand off the report to the consumer's onSubmit handler\n const handleSubmitReport = async (reportData: BugReportData) => {\n try {\n await onSubmit(reportData);\n onSuccess?.(reportData);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to submit bug report');\n onError?.(error);\n throw error;\n }\n };\n\n // If capturing screenshot, completely hide widget elements from DOM/render\n if (isCapturing) {\n return null;\n }\n\n return (\n <>\n {/* Floating Widget Trigger Button */}\n {!isEditorOpen && (\n <div\n data-bugdrop-widget=\"true\"\n className={`fixed ${getPositionClasses(position)} ${className}`}\n style={{ zIndex }}\n >\n <button\n type=\"button\"\n onClick={() => setOpen(!isOpen)}\n style={{ backgroundColor: primaryColor }}\n className={`group flex items-center justify-center text-white transition-all duration-200 hover:brightness-110 active:scale-95 ${sizeClasses.button}`}\n aria-label={isOpen ? 'Close bug report form' : 'Open bug report form'}\n title={isOpen ? 'Close Bug Report' : 'Report a Bug'}\n >\n {isOpen ? (\n <X className={sizeClasses.icon} />\n ) : buttonIcon ? (\n buttonIcon\n ) : (\n <Bug className={sizeClasses.icon} />\n )}\n\n {buttonText && <span>{buttonText}</span>}\n\n {/* Notification Badge if screenshots are attached */}\n {screenshots.length > 0 && !isOpen && (\n <span className=\"flex h-5 w-5 items-center justify-center rounded-full bg-white text-[11px] font-bold text-slate-900 shadow\">\n {screenshots.length}\n </span>\n )}\n </button>\n </div>\n )}\n\n {/* Slide-in Form Drawer */}\n {!isEditorOpen && (\n <Form\n projectUrl={projectUrl}\n isOpen={isOpen}\n onClose={() => setOpen(false)}\n uiSettings={uiSettings}\n screenshots={screenshots}\n onTriggerScreenshot={handleTriggerScreenshot}\n onEditScreenshot={handleEditExistingScreenshot}\n onDeleteScreenshot={handleDeleteScreenshot}\n onSubmitReport={handleSubmitReport}\n />\n )}\n\n {/* Konva Annotation Editor Modal */}\n {isEditorOpen && editingScreenshot && (\n <KonvaEditor\n imageSrc={editingScreenshot.dataUrl}\n onSave={handleSaveEditor}\n onCancel={handleCancelEditor}\n primaryColor={primaryColor}\n />\n )}\n </>\n );\n};"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"KonvaEditor.d.ts","sourceRoot":"","sources":["../../src/components/KonvaEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAmCxE,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqBD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA+6BlD,CAAC"}
1
+ {"version":3,"file":"KonvaEditor.d.ts","sourceRoot":"","sources":["../../src/components/KonvaEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoE,MAAM,OAAO,CAAC;AA+GzF,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA4DD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA2rBlD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bug-widget-library",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Embeddable React bug reporting widget with screenshot capture and Konva annotation",
5
5
  "type": "module",
6
6
  "main": "./dist/bug-widget-library.cjs",
@@ -28,14 +28,13 @@
28
28
  "prepublishOnly": "npm run build"
29
29
  },
30
30
  "peerDependencies": {
31
- "react": ">=18.0.0",
32
- "react-dom": ">=18.0.0"
31
+ "react": "^18.0.0 || ^19.0.0",
32
+ "react-dom": "^18.0.0 || ^19.0.0"
33
33
  },
34
34
  "dependencies": {
35
35
  "html2canvas": "^1.4.1",
36
36
  "konva": "^10.7.1",
37
- "lucide-react": "^1.55.0",
38
- "react-konva": "^19.3.0"
37
+ "lucide-react": "^1.55.0"
39
38
  },
40
39
  "devDependencies": {
41
40
  "@eslint/js": "^10.0.1",
@@ -69,4 +68,4 @@
69
68
  "publishConfig": {
70
69
  "access": "public"
71
70
  }
72
- }
71
+ }