bug-widget-library 0.0.0-stage → 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.
@@ -0,0 +1 @@
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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"}
@@ -0,0 +1,16 @@
1
+ import { default as React } from 'react';
2
+ import { BugReportData, ScreenshotItem, WidgetUiSettings } from '../types';
3
+ interface FormProps {
4
+ projectUrl: string;
5
+ isOpen: boolean;
6
+ onClose: () => void;
7
+ uiSettings?: WidgetUiSettings;
8
+ screenshots: ScreenshotItem[];
9
+ onTriggerScreenshot: () => void;
10
+ onEditScreenshot: (screenshot: ScreenshotItem) => void;
11
+ onDeleteScreenshot: (id: string) => void;
12
+ onSubmitReport: (data: BugReportData) => Promise<void> | void;
13
+ }
14
+ export declare const Form: React.FC<FormProps>;
15
+ export {};
16
+ //# sourceMappingURL=Form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../src/components/Form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAYxC,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,gBAAgB,EAEjB,MAAM,UAAU,CAAC;AAElB,UAAU,SAAS;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,gBAAgB,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,kBAAkB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,cAAc,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC/D;AAUD,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAiZpC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { default as React } from 'react';
2
+ interface KonvaEditorProps {
3
+ imageSrc: string;
4
+ onSave: (editedDataUrl: string) => void;
5
+ onCancel: () => void;
6
+ primaryColor?: string;
7
+ }
8
+ export declare const KonvaEditor: React.FC<KonvaEditorProps>;
9
+ export {};
10
+ //# sourceMappingURL=KonvaEditor.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,4 @@
1
+ import { default as React } from 'react';
2
+ import { WidgetProps } from '../types';
3
+ export declare const Widget: React.FC<WidgetProps>;
4
+ //# sourceMappingURL=Widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Widget.d.ts","sourceRoot":"","sources":["../../src/components/Widget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAKxC,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CA8PxC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Widget } from './components/Widget';
2
+ export type { WidgetProps, WidgetUiSettings, WidgetPosition, WidgetButtonSize, BugReportData, BugReportMetadata, ScreenshotItem, } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,cAAc,CAAC;AAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,cAAc,GACf,MAAM,SAAS,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { ReactNode } from 'react';
2
+ export type WidgetPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'left' | 'right';
3
+ export type WidgetButtonSize = 'sm' | 'md' | 'lg';
4
+ export interface WidgetUiSettings {
5
+ /**
6
+ * Position of the widget button and drawer slide direction.
7
+ * Right-aligned positions slide the form in/out from the right.
8
+ * Left-aligned positions slide the form in/out from the left.
9
+ * Default: 'bottom-right'
10
+ */
11
+ position?: WidgetPosition;
12
+ /** Primary theme color for button, highlights, and primary actions. Default: '#2563eb' */
13
+ primaryColor?: string;
14
+ /** Secondary or accent color */
15
+ secondaryColor?: string;
16
+ /** Button size preset. Default: 'md' */
17
+ buttonSize?: WidgetButtonSize;
18
+ /** Optional text label next to the button icon */
19
+ buttonText?: string;
20
+ /** Custom button icon (defaults to Bug icon) */
21
+ buttonIcon?: ReactNode;
22
+ /** Widget header title in the form. Default: 'Report a Bug' */
23
+ title?: string;
24
+ /** Widget header subtitle in the form */
25
+ subtitle?: string;
26
+ /** Custom placeholder for the bug title input */
27
+ placeholderTitle?: string;
28
+ /** Custom placeholder for the bug description input */
29
+ placeholderDescription?: string;
30
+ /** Z-index for the widget overlays. Default: 99999 */
31
+ zIndex?: number;
32
+ }
33
+ export interface ScreenshotItem {
34
+ id: string;
35
+ dataUrl: string;
36
+ createdAt: number;
37
+ }
38
+ export interface BugReportMetadata {
39
+ url: string;
40
+ userAgent: string;
41
+ timestamp?: string;
42
+ screenSize: {
43
+ width: number;
44
+ height: number;
45
+ };
46
+ }
47
+ export interface BugReportData {
48
+ projectUrl: string;
49
+ title: string;
50
+ description: string;
51
+ screenshots: ScreenshotItem[];
52
+ timestamp: string;
53
+ meta: BugReportMetadata;
54
+ }
55
+ export interface WidgetProps {
56
+ /** Project URL included in the report payload (e.g. your backend project endpoint) */
57
+ projectUrl: string;
58
+ /**
59
+ * Required. Called when the user submits a bug report.
60
+ * Send the data to your API (or anywhere) from this handler.
61
+ * Throw or return a rejected promise to show an error in the form.
62
+ */
63
+ onSubmit: (data: BugReportData) => Promise<void> | void;
64
+ /** UI appearance and positioning settings shared by button and form */
65
+ uiSettings?: WidgetUiSettings;
66
+ /** Fired after onSubmit resolves successfully */
67
+ onSuccess?: (data: BugReportData) => void;
68
+ /** Fired when onSubmit throws or rejects */
69
+ onError?: (error: Error) => void;
70
+ /** Controlled open state for the form (optional) */
71
+ isOpen?: boolean;
72
+ /** Callback fired when form open state changes */
73
+ onToggle?: (open: boolean) => void;
74
+ /** Additional custom class names */
75
+ className?: string;
76
+ }
77
+ export type EditorTool = 'select' | 'pencil' | 'eraser' | 'rectangle' | 'circle' | 'arrow';
78
+ export interface BaseAnnotation {
79
+ id: string;
80
+ stroke: string;
81
+ strokeWidth: number;
82
+ }
83
+ export interface LineAnnotation extends BaseAnnotation {
84
+ type: 'line';
85
+ points: number[];
86
+ tool: 'pencil' | 'eraser';
87
+ }
88
+ export interface RectAnnotation extends BaseAnnotation {
89
+ type: 'rectangle';
90
+ x: number;
91
+ y: number;
92
+ width: number;
93
+ height: number;
94
+ rotation?: number;
95
+ }
96
+ export interface CircleAnnotation extends BaseAnnotation {
97
+ type: 'circle';
98
+ x: number;
99
+ y: number;
100
+ radius: number;
101
+ rotation?: number;
102
+ }
103
+ export interface ArrowAnnotation extends BaseAnnotation {
104
+ type: 'arrow';
105
+ points: number[];
106
+ fill: string;
107
+ x?: number;
108
+ y?: number;
109
+ rotation?: number;
110
+ }
111
+ export type AnnotationShape = LineAnnotation | RectAnnotation | CircleAnnotation | ArrowAnnotation;
112
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,71 @@
1
1
  {
2
2
  "name": "bug-widget-library",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "Embeddable React bug reporting widget with screenshot capture and Konva annotation",
5
+ "type": "module",
6
+ "main": "./dist/bug-widget-library.cjs",
7
+ "module": "./dist/bug-widget-library.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/bug-widget-library.js",
13
+ "require": "./dist/bug-widget-library.cjs"
14
+ },
15
+ "./style.css": "./dist/bug-widget-library.css"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "sideEffects": [
22
+ "**/*.css"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsc -b && vite build",
26
+ "typecheck": "tsc -b --pretty false",
27
+ "lint": "eslint .",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "peerDependencies": {
31
+ "react": "^18.0.0 || ^19.0.0",
32
+ "react-dom": "^18.0.0 || ^19.0.0"
33
+ },
34
+ "dependencies": {
35
+ "html2canvas": "^1.4.1",
36
+ "konva": "^10.7.1",
37
+ "lucide-react": "^1.55.0"
38
+ },
39
+ "devDependencies": {
40
+ "@eslint/js": "^10.0.1",
41
+ "@types/node": "^24.13.3",
42
+ "@types/react": "^19.2.18",
43
+ "@types/react-dom": "^19.2.7",
44
+ "@vitejs/plugin-react": "^6.1.1",
45
+ "autoprefixer": "^10.6.1",
46
+ "eslint": "^10.10.0",
47
+ "eslint-plugin-react-hooks": "^7.1.1",
48
+ "globals": "^17.12.0",
49
+ "postcss": "^8.5.29",
50
+ "react": "^19.2.8",
51
+ "react-dom": "^19.2.8",
52
+ "tailwindcss": "^3.4.19",
53
+ "typescript": "~6.0.2",
54
+ "typescript-eslint": "^8.69.0",
55
+ "vite": "^8.3.0",
56
+ "vite-plugin-dts": "^5.1.2"
57
+ },
58
+ "keywords": [
59
+ "react",
60
+ "bug-report",
61
+ "widget",
62
+ "screenshot",
63
+ "annotation",
64
+ "konva",
65
+ "feedback"
66
+ ],
67
+ "license": "MIT",
68
+ "publishConfig": {
69
+ "access": "public"
70
+ }
6
71
  }