🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

ghostbug

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ghostbug - npm Package Compare versions

Comparing version
0.2.0-beta.0
to
0.2.0
+57
-9
dist/index.cjs

@@ -1,3 +0,3 @@

'use strict';Object.defineProperty(exports,'__esModule',{value:true});var f="0.1.0",_={maxReports:50,maxBreadcrumbs:20,maxClicks:20,widget:false,collectors:{errors:true,console:true,network:true,clicks:true,interactions:true,performance:true,memory:true},rateLimit:{maxEvents:10,windowMs:1e3},beforeReport:r=>r,debug:false};var b=class{constructor(){this.listeners=new Map;}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t);}emit(e,t){this.listeners.get(e)?.forEach(o=>{try{o(t);}catch{}});}clear(){this.listeners.clear();}};var m=class{constructor(e){this.capacity=e;this.head=0;this._size=0;this.buffer=new Array(e);}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this._size<this.capacity&&this._size++;}toArray(){if(this._size===0)return [];let e=[],t=this._size<this.capacity?0:this.head;for(let o=0;o<this._size;o++){let n=(t+o)%this.capacity;e.push(this.buffer[n]);}return e}get size(){return this._size}get isFull(){return this._size===this.capacity}peek(){if(this._size===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}find(e){return this.toArray().find(e)}forEach(e){this.toArray().forEach(e);}clear(){this.buffer=new Array(this.capacity),this.head=0,this._size=0;}};var v=class{constructor(e,t){this.maxEvents=e;this.windowMs=t;this.timestamps=[];}allow(){let e=Date.now();return this.timestamps=this.timestamps.filter(t=>e-t<this.windowMs),this.timestamps.length>=this.maxEvents?false:(this.timestamps.push(e),true)}reset(){this.timestamps=[];}};function q(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e+r.charCodeAt(t)&4294967295;return (e>>>0).toString(36)}function I(r){let e;switch(r.kind){case "error":{let t=r.stack?.split(`
`)[1]?.trim()||"";e=`${r.name}:${r.message}:${t}`;break}case "console":e=`console:${r.level}:${r.args.join(",")}`;break;case "network":e=`network:${r.method}:${r.url}:${r.status}`;break;case "performance":e=`performance:${r.metric}:${Math.floor(r.value/100)*100}`;break;case "memory":e=`memory:${Math.floor(r.heapUsagePercent*10)/10}`;break}return q(e)}function A(){let r=new Uint8Array(8);return crypto.getRandomValues(r),Array.from(r,e=>e.toString(36).padStart(2,"0")).join("").slice(0,12)}var W=3e3,y=class{constructor(e,t,o){this.eventBus=e;this.contextCollector=t;this.options=o;this.unsubscribers=[];this.reports=new m(o.maxReports),this.breadcrumbs=new m(o.maxBreadcrumbs),this.rateLimiter=new v(o.rateLimit.maxEvents,o.rateLimit.windowMs),this.subscribe();}subscribe(){this.unsubscribers.push(this.eventBus.on("error:captured",e=>{this.addBreadcrumb({category:"error",message:e.message}),this.handleCapturedEvent("error",e);}),this.eventBus.on("console:captured",e=>{this.addBreadcrumb({category:"console",message:`console.${e.level}: ${e.args.join(", ")}`}),e.level==="error"&&this.handleCapturedEvent("console",e);}),this.eventBus.on("network:captured",e=>{this.handleCapturedEvent("network",e);}),this.eventBus.on("performance:captured",e=>{this.addBreadcrumb({category:"performance",message:`${e.metric}: ${e.value}ms`}),this.handleCapturedEvent("performance",e);}),this.eventBus.on("memory:captured",e=>{this.handleCapturedEvent("memory",e);}),this.eventBus.on("breadcrumb:added",e=>{this.addBreadcrumb(e);}));}async handleCapturedEvent(e,t){if(!this.rateLimiter.allow())return;let o=I(t),n=this.reports.find(l=>l.fingerprint===o);if(n){n.count++,n.timestamp=new Date().toISOString(),this.eventBus.emit("report:deduplicated",n);return}let i={id:A(),fingerprint:o,type:e,timestamp:new Date().toISOString(),count:1,payload:t,breadcrumbs:this.breadcrumbs.toArray(),context:this.contextCollector.snapshot()};if(this.options.screenshotFn)try{i.screenshot=await Promise.race([this.options.screenshotFn(),new Promise((l,a)=>setTimeout(()=>a(new Error("screenshot timeout")),W))]);}catch{}let s=this.options.beforeReport(i);s&&(i=s,this.reports.push(i),this.eventBus.emit("report:created",i));}addBreadcrumb(e){this.breadcrumbs.push({...e,timestamp:new Date().toISOString()});}getReports(){return this.reports.toArray()}clear(){this.reports.clear(),this.breadcrumbs.clear(),this.unsubscribers.forEach(e=>e()),this.unsubscribers=[];}get reportCount(){return this.reports.size}};var w=class{constructor(e){this.eventBus=e;this.name="error";this.originalOnError=null;this.rejectionHandler=null;}setup(){this.originalOnError=window.onerror,window.onerror=(e,t,o,n,i)=>{let s={kind:"error",message:String(e),stack:i?.stack,filename:t??void 0,lineno:o??void 0,colno:n??void 0,name:i?.name};return this.eventBus.emit("error:captured",s),this.originalOnError?this.originalOnError.call(window,e,t,o,n,i):false},this.rejectionHandler=e=>{let t=e.reason,o={kind:"error",message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,name:t instanceof Error?t.name:"UnhandledRejection"};this.eventBus.emit("error:captured",o);},window.addEventListener("unhandledrejection",this.rejectionHandler);}teardown(){window.onerror=this.originalOnError,this.originalOnError=null,this.rejectionHandler&&(window.removeEventListener("unhandledrejection",this.rejectionHandler),this.rejectionHandler=null);}};function g(r,e){let t=new WeakSet;return JSON.stringify(r,(o,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return "[Circular]";t.add(n);}return typeof n=="function"?"[Function]":typeof n=="symbol"?n.toString():n instanceof Error?{name:n.name,message:n.message,stack:n.stack}:n},e)}var x=class{constructor(e){this.eventBus=e;this.name="console";this.originalError=null;this.originalWarn=null;}setup(){this.originalError=console.error,this.originalWarn=console.warn,console.error=(...e)=>{let t={kind:"console",level:"error",args:e.map(o=>g(o))};this.eventBus.emit("console:captured",t),this.originalError.apply(console,e);},console.warn=(...e)=>{let t={kind:"console",level:"warn",args:e.map(o=>g(o))};this.eventBus.emit("console:captured",t),this.originalWarn.apply(console,e);};}teardown(){this.originalError&&(console.error=this.originalError),this.originalWarn&&(console.warn=this.originalWarn),this.originalError=null,this.originalWarn=null;}};var E=class{constructor(e){this.eventBus=e;this.name="network";this.originalFetch=null;this.originalXhrOpen=null;this.originalXhrSend=null;}setup(){this.patchFetch(),this.patchXHR();}patchFetch(){this.originalFetch=window.fetch;let e=this.eventBus,t=this.originalFetch;window.fetch=function(o,n){let i=n?.method?.toUpperCase()||"GET",s=typeof o=="string"?o:o instanceof URL?o.href:o.url,l=performance.now();return t.call(window,o,n).then(a=>{let p=Math.round(performance.now()-l);if(a.status>=400){let u={kind:"network",method:i,url:s,status:a.status,statusText:a.statusText,duration:p};e.emit("network:captured",u);}return e.emit("breadcrumb:added",{category:"network",message:`${i} ${s} -> ${a.status}`}),a},a=>{let p=Math.round(performance.now()-l),u={kind:"network",method:i,url:s,status:0,statusText:a.message||"Network Error",duration:p};throw e.emit("network:captured",u),a})};}patchXHR(){this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let e=this.eventBus,t=this.originalXhrOpen,o=this.originalXhrSend;XMLHttpRequest.prototype.open=function(n,i,...s){return this.__ghostbug_method=n.toUpperCase(),this.__ghostbug_url=String(i),t.apply(this,[n,i,...s])},XMLHttpRequest.prototype.send=function(n){let i=performance.now(),s=this;return s.addEventListener("loadend",function(){let l=Math.round(performance.now()-i),a=s.__ghostbug_method||"UNKNOWN",p=s.__ghostbug_url||"";if(s.status>=400||s.status===0){let u={kind:"network",method:a,url:p,status:s.status,statusText:s.statusText,duration:l};e.emit("network:captured",u);}e.emit("breadcrumb:added",{category:"network",message:`${a} ${p} -> ${s.status}`});}),o.call(this,n)};}teardown(){this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null);}};function F(r){if(r.id)return `#${r.id}`;let e=r.getAttribute("data-testid");if(e)return `[data-testid="${e}"]`;let t=[],o=r,n=0;for(;o&&o!==document.documentElement&&n<5;){let i=o.tagName.toLowerCase();if(o.id){t.unshift(`#${o.id}`);break}let s=Array.from(o.classList).slice(0,2);s.length>0&&(i+="."+s.join("."));let l=o.parentElement;if(l){let a=o.tagName,p=Array.from(l.children).filter(u=>u.tagName===a);if(p.length>1){let u=p.indexOf(o)+1;i+=`:nth-child(${u})`;}}t.unshift(i),o=l,n++;}return t.join(" > ")}var k=class{constructor(e,t){this.eventBus=e;this.name="click";this.handler=null;this.clicks=new m(t);}setup(){this.handler=e=>{let t=e.target;if(!t)return;let o={timestamp:new Date().toISOString(),selector:F(t),tagName:t.tagName.toLowerCase(),text:(t.textContent||"").trim().slice(0,100),position:{x:e.clientX,y:e.clientY}};this.clicks.push(o),this.eventBus.emit("click:captured",o),this.eventBus.emit("breadcrumb:added",{category:"click",message:`Clicked ${o.tagName} "${o.text}"`,data:{selector:o.selector}});},document.addEventListener("click",this.handler,true);}getClickTrail(){return this.clicks.toArray()}teardown(){this.handler&&(document.removeEventListener("click",this.handler,true),this.handler=null),this.clicks.clear();}};var C=class{constructor(e){this.getMeta=e;this.name="context";}setup(){}teardown(){}snapshot(){let e=this.getMeta?.();return {url:window.location.href,referrer:document.referrer,userAgent:navigator.userAgent,language:navigator.language,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},devicePixelRatio:window.devicePixelRatio||1,timestamp:new Date().toISOString(),memory:performance.memory?{usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize}:void 0,user:e?.user,tags:e?.tags}}};var S=class{constructor(e){this.eventBus=e;this.name="interactions";this.handlers=[];this.scrollTimer=null;this.resizeTimer=null;}setup(){this.addHandler(window,"scroll",this.onScroll.bind(this),{passive:true,capture:true}),this.addHandler(document,"input",this.onInput.bind(this),true),this.addHandler(document,"change",this.onChange.bind(this),true),this.addHandler(window,"popstate",this.onPopState.bind(this)),this.addHandler(window,"hashchange",this.onHashChange.bind(this)),this.addHandler(document,"visibilitychange",this.onVisibilityChange.bind(this)),this.addHandler(window,"resize",this.onResize.bind(this),{passive:true});}addHandler(e,t,o,n){e.addEventListener(t,o,n),this.handlers.push({target:e,event:t,handler:o});}onScroll(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Scrolled",data:{x:window.scrollX,y:window.scrollY}});},300);}onInput(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"",i=t.type?`[type="${t.type}"]`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Input on ${o}${n}${i}`});}onChange(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Change on ${o}${n}`});}onPopState(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Navigated to ${window.location.href}`});}onHashChange(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Hash changed to ${window.location.hash}`});}onVisibilityChange(){this.eventBus.emit("breadcrumb:added",{category:"visibility",message:document.hidden?"Tab hidden":"Tab visible"});}onResize(){this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Window resized",data:{width:window.innerWidth,height:window.innerHeight}});},300);}teardown(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.resizeTimer&&clearTimeout(this.resizeTimer),this.handlers.forEach(({target:e,event:t,handler:o})=>{e.removeEventListener(t,o);}),this.handlers=[];}};var B=class{constructor(e){this.eventBus=e;this.name="performance";this.observers=[];}setup(){typeof PerformanceObserver>"u"||(this.observe("longtask",e=>{e.forEach(t=>{if(t.duration<50)return;let o={kind:"performance",metric:"longtask",value:Math.round(t.duration),entries:[{name:t.name,duration:t.duration,startTime:t.startTime}]};this.eventBus.emit("performance:captured",o),this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Long task: ${Math.round(t.duration)}ms`});});}),this.observe("largest-contentful-paint",e=>{let t=e[e.length-1];t&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`LCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});}),this.observe("paint",e=>{e.forEach(t=>{t.name==="first-contentful-paint"&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`FCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});});}),this.observe("layout-shift",e=>{e.forEach(t=>{let o=t.value;o>.1&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Layout shift: ${o.toFixed(4)}`,data:{cls:o}});});}));}observe(e,t){try{let o=new PerformanceObserver(n=>{t(n.getEntries());});o.observe({type:e,buffered:!0}),this.observers.push(o);}catch{}}teardown(){this.observers.forEach(e=>e.disconnect()),this.observers=[];}};function j(){let r=performance.memory;return !r||typeof r.usedJSHeapSize!="number"?null:r}var R=class{constructor(e){this.eventBus=e;this.name="memory";this.intervalId=null;this.baselineUsed=null;}setup(){let e=j();e&&(this.baselineUsed=e.usedJSHeapSize,this.intervalId=setInterval(()=>{let t=j();if(!t)return;let o=t.usedJSHeapSize/t.jsHeapSizeLimit,n=this.baselineUsed>0?(t.usedJSHeapSize-this.baselineUsed)/this.baselineUsed:0;this.eventBus.emit("breadcrumb:added",{category:"memory",message:`Heap: ${(o*100).toFixed(1)}% used (${(t.usedJSHeapSize/1048576).toFixed(1)}MB)`,data:{usedJSHeapSize:t.usedJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit}});let i=o>=.9,s=n>=.5;if(i||s){let a={kind:"memory",message:i?`Heap usage critical: ${(o*100).toFixed(1)}% of limit`:`Heap growth spike: ${(n*100).toFixed(1)}% since init`,usedJSHeapSize:t.usedJSHeapSize,totalJSHeapSize:t.totalJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit,heapUsagePercent:o,heapGrowthPercent:n};this.eventBus.emit("memory:captured",a);}},1e4));}teardown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.baselineUsed=null;}};var U=`
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var b="0.1.0",I={maxReports:50,maxBreadcrumbs:20,maxClicks:20,widget:false,collectors:{errors:true,console:true,network:true,clicks:true,interactions:true,performance:true,memory:true},rateLimit:{maxEvents:10,windowMs:1e3},beforeReport:r=>r,debug:false};var v=class{constructor(){this.listeners=new Map;}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t);}emit(e,t){this.listeners.get(e)?.forEach(o=>{try{o(t);}catch{}});}clear(){this.listeners.clear();}};var m=class{constructor(e){this.capacity=e;this.head=0;this._size=0;this.buffer=new Array(e);}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this._size<this.capacity&&this._size++;}toArray(){if(this._size===0)return [];let e=[],t=this._size<this.capacity?0:this.head;for(let o=0;o<this._size;o++){let n=(t+o)%this.capacity;e.push(this.buffer[n]);}return e}get size(){return this._size}get isFull(){return this._size===this.capacity}peek(){if(this._size===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}find(e){return this.toArray().find(e)}forEach(e){this.toArray().forEach(e);}clear(){this.buffer=new Array(this.capacity),this.head=0,this._size=0;}};var y=class{constructor(e,t){this.maxEvents=e;this.windowMs=t;this.timestamps=[];}allow(){let e=Date.now();return this.timestamps=this.timestamps.filter(t=>e-t<this.windowMs),this.timestamps.length>=this.maxEvents?false:(this.timestamps.push(e),true)}reset(){this.timestamps=[];}};function X(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e+r.charCodeAt(t)&4294967295;return (e>>>0).toString(36)}function A(r){let e;switch(r.kind){case "error":{let t=r.stack?.split(`
`)[1]?.trim()||"";e=`${r.name}:${r.message}:${t}`;break}case "console":e=`console:${r.level}:${r.args.join(",")}`;break;case "network":e=`network:${r.method}:${r.url}:${r.status}`;break;case "performance":e=`performance:${r.metric}:${Math.floor(r.value/100)*100}`;break;case "memory":e=`memory:${Math.floor(r.heapUsagePercent*10)/10}`;break}return X(e)}function j(){let r=new Uint8Array(8);return crypto.getRandomValues(r),Array.from(r,e=>e.toString(36).padStart(2,"0")).join("").slice(0,12)}var w=class{constructor(e,t,o){this.eventBus=e;this.contextCollector=t;this.options=o;this.unsubscribers=[];this.reports=new m(o.maxReports),this.breadcrumbs=new m(o.maxBreadcrumbs),this.rateLimiter=new y(o.rateLimit.maxEvents,o.rateLimit.windowMs),this.subscribe();}subscribe(){this.unsubscribers.push(this.eventBus.on("error:captured",e=>{this.addBreadcrumb({category:"error",message:e.message}),this.handleCapturedEvent("error",e);}),this.eventBus.on("console:captured",e=>{this.addBreadcrumb({category:"console",message:`console.${e.level}: ${e.args.join(", ")}`}),e.level==="error"&&this.handleCapturedEvent("console",e);}),this.eventBus.on("network:captured",e=>{this.handleCapturedEvent("network",e);}),this.eventBus.on("performance:captured",e=>{this.addBreadcrumb({category:"performance",message:`${e.metric}: ${e.value}ms`}),this.handleCapturedEvent("performance",e);}),this.eventBus.on("memory:captured",e=>{this.handleCapturedEvent("memory",e);}),this.eventBus.on("breadcrumb:added",e=>{this.addBreadcrumb(e);}));}async handleCapturedEvent(e,t){if(!this.rateLimiter.allow())return;let o=A(t),n=this.reports.find(l=>l.fingerprint===o);if(n){n.count++,n.timestamp=new Date().toISOString(),this.eventBus.emit("report:deduplicated",n);return}let i={id:j(),fingerprint:o,type:e,timestamp:new Date().toISOString(),count:1,payload:t,breadcrumbs:this.breadcrumbs.toArray(),context:this.contextCollector.snapshot()},a=this.options.beforeReport(i);a&&(i=a,this.reports.push(i),this.eventBus.emit("report:created",i));}addBreadcrumb(e){this.breadcrumbs.push({...e,timestamp:new Date().toISOString()});}getReports(){return this.reports.toArray()}clear(){this.reports.clear(),this.breadcrumbs.clear(),this.unsubscribers.forEach(e=>e()),this.unsubscribers=[];}get reportCount(){return this.reports.size}};var x=class{constructor(e){this.eventBus=e;this.name="error";this.originalOnError=null;this.rejectionHandler=null;}setup(){this.originalOnError=window.onerror,window.onerror=(e,t,o,n,i)=>{let a={kind:"error",message:String(e),stack:i?.stack,filename:t??void 0,lineno:o??void 0,colno:n??void 0,name:i?.name};return this.eventBus.emit("error:captured",a),this.originalOnError?this.originalOnError.call(window,e,t,o,n,i):false},this.rejectionHandler=e=>{let t=e.reason,o={kind:"error",message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,name:t instanceof Error?t.name:"UnhandledRejection"};this.eventBus.emit("error:captured",o);},window.addEventListener("unhandledrejection",this.rejectionHandler);}teardown(){window.onerror=this.originalOnError,this.originalOnError=null,this.rejectionHandler&&(window.removeEventListener("unhandledrejection",this.rejectionHandler),this.rejectionHandler=null);}};function f(r,e){let t=new WeakSet;return JSON.stringify(r,(o,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return "[Circular]";t.add(n);}return typeof n=="function"?"[Function]":typeof n=="symbol"?n.toString():n instanceof Error?{name:n.name,message:n.message,stack:n.stack}:n},e)}var E=class{constructor(e){this.eventBus=e;this.name="console";this.originalError=null;this.originalWarn=null;}setup(){this.originalError=console.error,this.originalWarn=console.warn,console.error=(...e)=>{let t={kind:"console",level:"error",args:e.map(o=>f(o))};this.eventBus.emit("console:captured",t),this.originalError.apply(console,e);},console.warn=(...e)=>{let t={kind:"console",level:"warn",args:e.map(o=>f(o))};this.eventBus.emit("console:captured",t),this.originalWarn.apply(console,e);};}teardown(){this.originalError&&(console.error=this.originalError),this.originalWarn&&(console.warn=this.originalWarn),this.originalError=null,this.originalWarn=null;}};var k=class{constructor(e){this.eventBus=e;this.name="network";this.originalFetch=null;this.originalXhrOpen=null;this.originalXhrSend=null;}setup(){this.patchFetch(),this.patchXHR();}patchFetch(){this.originalFetch=window.fetch;let e=this.eventBus,t=this.originalFetch;window.fetch=function(o,n){let i=n?.method?.toUpperCase()||"GET",a=typeof o=="string"?o:o instanceof URL?o.href:o.url,l=performance.now();return t.call(window,o,n).then(s=>{let p=Math.round(performance.now()-l);if(s.status>=400){let u={kind:"network",method:i,url:a,status:s.status,statusText:s.statusText,duration:p};e.emit("network:captured",u);}return e.emit("breadcrumb:added",{category:"network",message:`${i} ${a} -> ${s.status}`}),s},s=>{let p=Math.round(performance.now()-l),u={kind:"network",method:i,url:a,status:0,statusText:s.message||"Network Error",duration:p};throw e.emit("network:captured",u),s})};}patchXHR(){this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let e=this.eventBus,t=this.originalXhrOpen,o=this.originalXhrSend;XMLHttpRequest.prototype.open=function(n,i,...a){return this.__ghostbug_method=n.toUpperCase(),this.__ghostbug_url=String(i),t.apply(this,[n,i,...a])},XMLHttpRequest.prototype.send=function(n){let i=performance.now(),a=this;return a.addEventListener("loadend",function(){let l=Math.round(performance.now()-i),s=a.__ghostbug_method||"UNKNOWN",p=a.__ghostbug_url||"";if(a.status>=400||a.status===0){let u={kind:"network",method:s,url:p,status:a.status,statusText:a.statusText,duration:l};e.emit("network:captured",u);}e.emit("breadcrumb:added",{category:"network",message:`${s} ${p} -> ${a.status}`});}),o.call(this,n)};}teardown(){this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null);}};function U(r){if(r.id)return `#${r.id}`;let e=r.getAttribute("data-testid");if(e)return `[data-testid="${e}"]`;let t=[],o=r,n=0;for(;o&&o!==document.documentElement&&n<5;){let i=o.tagName.toLowerCase();if(o.id){t.unshift(`#${o.id}`);break}let a=Array.from(o.classList).slice(0,2);a.length>0&&(i+="."+a.join("."));let l=o.parentElement;if(l){let s=o.tagName,p=Array.from(l.children).filter(u=>u.tagName===s);if(p.length>1){let u=p.indexOf(o)+1;i+=`:nth-child(${u})`;}}t.unshift(i),o=l,n++;}return t.join(" > ")}var C=class{constructor(e,t){this.eventBus=e;this.name="click";this.handler=null;this.clicks=new m(t);}setup(){this.handler=e=>{let t=e.target;if(!t)return;let o={timestamp:new Date().toISOString(),selector:U(t),tagName:t.tagName.toLowerCase(),text:(t.textContent||"").trim().slice(0,100),position:{x:e.clientX,y:e.clientY}};this.clicks.push(o),this.eventBus.emit("click:captured",o),this.eventBus.emit("breadcrumb:added",{category:"click",message:`Clicked ${o.tagName} "${o.text}"`,data:{selector:o.selector}});},document.addEventListener("click",this.handler,true);}getClickTrail(){return this.clicks.toArray()}teardown(){this.handler&&(document.removeEventListener("click",this.handler,true),this.handler=null),this.clicks.clear();}};var S=class{constructor(e){this.getMeta=e;this.name="context";}setup(){}teardown(){}snapshot(){let e=this.getMeta?.();return {url:window.location.href,referrer:document.referrer,userAgent:navigator.userAgent,language:navigator.language,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},devicePixelRatio:window.devicePixelRatio||1,timestamp:new Date().toISOString(),memory:performance.memory?{usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize}:void 0,user:e?.user,tags:e?.tags}}};var B=class{constructor(e){this.eventBus=e;this.name="interactions";this.handlers=[];this.scrollTimer=null;this.resizeTimer=null;}setup(){this.addHandler(window,"scroll",this.onScroll.bind(this),{passive:true,capture:true}),this.addHandler(document,"input",this.onInput.bind(this),true),this.addHandler(document,"change",this.onChange.bind(this),true),this.addHandler(window,"popstate",this.onPopState.bind(this)),this.addHandler(window,"hashchange",this.onHashChange.bind(this)),this.addHandler(document,"visibilitychange",this.onVisibilityChange.bind(this)),this.addHandler(window,"resize",this.onResize.bind(this),{passive:true});}addHandler(e,t,o,n){e.addEventListener(t,o,n),this.handlers.push({target:e,event:t,handler:o});}onScroll(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Scrolled",data:{x:window.scrollX,y:window.scrollY}});},300);}onInput(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"",i=t.type?`[type="${t.type}"]`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Input on ${o}${n}${i}`});}onChange(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Change on ${o}${n}`});}onPopState(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Navigated to ${window.location.href}`});}onHashChange(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Hash changed to ${window.location.hash}`});}onVisibilityChange(){this.eventBus.emit("breadcrumb:added",{category:"visibility",message:document.hidden?"Tab hidden":"Tab visible"});}onResize(){this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Window resized",data:{width:window.innerWidth,height:window.innerHeight}});},300);}teardown(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.resizeTimer&&clearTimeout(this.resizeTimer),this.handlers.forEach(({target:e,event:t,handler:o})=>{e.removeEventListener(t,o);}),this.handlers=[];}};var R=class{constructor(e){this.eventBus=e;this.name="performance";this.observers=[];}setup(){typeof PerformanceObserver>"u"||(this.observe("longtask",e=>{e.forEach(t=>{if(t.duration<50)return;let o={kind:"performance",metric:"longtask",value:Math.round(t.duration),entries:[{name:t.name,duration:t.duration,startTime:t.startTime}]};this.eventBus.emit("performance:captured",o),this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Long task: ${Math.round(t.duration)}ms`});});}),this.observe("largest-contentful-paint",e=>{let t=e[e.length-1];t&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`LCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});}),this.observe("paint",e=>{e.forEach(t=>{t.name==="first-contentful-paint"&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`FCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});});}),this.observe("layout-shift",e=>{e.forEach(t=>{let o=t.value;o>.1&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Layout shift: ${o.toFixed(4)}`,data:{cls:o}});});}));}observe(e,t){try{let o=new PerformanceObserver(n=>{t(n.getEntries());});o.observe({type:e,buffered:!0}),this.observers.push(o);}catch{}}teardown(){this.observers.forEach(e=>e.disconnect()),this.observers=[];}};function F(){let r=performance.memory;return !r||typeof r.usedJSHeapSize!="number"?null:r}var T=class{constructor(e){this.eventBus=e;this.name="memory";this.intervalId=null;this.baselineUsed=null;}setup(){let e=F();e&&(this.baselineUsed=e.usedJSHeapSize,this.intervalId=setInterval(()=>{let t=F();if(!t)return;let o=t.usedJSHeapSize/t.jsHeapSizeLimit,n=this.baselineUsed>0?(t.usedJSHeapSize-this.baselineUsed)/this.baselineUsed:0;this.eventBus.emit("breadcrumb:added",{category:"memory",message:`Heap: ${(o*100).toFixed(1)}% used (${(t.usedJSHeapSize/1048576).toFixed(1)}MB)`,data:{usedJSHeapSize:t.usedJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit}});let i=o>=.9,a=n>=.5;if(i||a){let s={kind:"memory",message:i?`Heap usage critical: ${(o*100).toFixed(1)}% of limit`:`Heap growth spike: ${(n*100).toFixed(1)}% since init`,usedJSHeapSize:t.usedJSHeapSize,totalJSHeapSize:t.totalJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit,heapUsagePercent:o,heapGrowthPercent:n};this.eventBus.emit("memory:captured",s);}},1e4));}teardown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.baselineUsed=null;}};var D=`
:host {

@@ -165,16 +165,63 @@ all: initial;

.gb-report-item {
padding: 10px 16px;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
transition: background 0.15s;
}
.gb-report-item:hover {
.gb-report-item:last-child {
border-bottom: none;
}
.gb-report-summary {
padding: 10px 16px;
cursor: pointer;
}
.gb-report-summary:hover {
background: #f8f9fa;
}
.gb-report-item:last-child {
border-bottom: none;
.gb-report-detail {
display: none;
padding: 0 16px 12px;
border-top: 1px dashed #e8e8e8;
}
.gb-report-item.gb-expanded .gb-report-detail {
display: block;
}
.gb-detail-section {
margin-top: 8px;
}
.gb-detail-label {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #999;
margin-bottom: 2px;
}
.gb-detail-value {
font-size: 12px;
color: #555;
word-break: break-word;
line-height: 1.4;
}
.gb-detail-pre {
font-size: 11px;
font-family: 'SF Mono', Menlo, Monaco, monospace;
background: #f5f5f5;
padding: 8px;
border-radius: 6px;
overflow-x: auto;
max-height: 120px;
overflow-y: auto;
color: #333;
white-space: pre-wrap;
word-break: break-word;
}
.gb-report-type {

@@ -257,4 +304,5 @@ display: inline-block;

}
`;var J='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></svg>';function D(){let r=document.createElement("button");r.className="gb-fab",r.setAttribute("aria-label","ghostbug - bug reports");let e=document.createElement("span");e.innerHTML=J,r.appendChild(e);let t=document.createElement("span");return t.className="gb-badge",t.setAttribute("data-count","0"),t.textContent="0",r.appendChild(t),r}function G(r){let e=document.createElement("div");e.className=`gb-panel gb-pos-${r}`;let t=document.createElement("div");t.className="gb-header";let o=document.createElement("span");o.className="gb-header-title",o.textContent="ghostbug",t.appendChild(o);let n=document.createElement("button");n.className="gb-header-btn gb-copy-btn",n.textContent="Copy MD",t.appendChild(n);let i=document.createElement("button");i.className="gb-header-btn gb-download-btn",i.textContent="Export",t.appendChild(i);let s=document.createElement("button");s.className="gb-close-btn",s.textContent="\xD7",s.setAttribute("aria-label","Close"),t.appendChild(s),e.appendChild(t);let l=document.createElement("div");l.className="gb-report-list";let a=document.createElement("div");return a.className="gb-empty",a.textContent="No bugs captured yet.",l.appendChild(a),e.appendChild(l),e}function X(r){let e=document.createElement("div");e.className="gb-report-item";let t=document.createElement("span");if(t.className=`gb-report-type gb-type-${r.payload.kind==="error"?"error":r.payload.kind}`,t.textContent=r.type,e.appendChild(t),r.count>1){let s=document.createElement("span");s.className="gb-report-count",s.textContent=`\xD7${r.count}`,e.appendChild(s);}let o=document.createElement("div");o.className="gb-report-message",o.textContent=V(r),e.appendChild(o);let n=document.createElement("div");n.className="gb-report-meta";let i=r.timestamp.split("T")[1]?.split(".")[0]||r.timestamp;return n.textContent=`${i} \xB7 ${r.context.url}`,e.appendChild(n),e}function V(r){switch(r.payload.kind){case "error":return r.payload.message;case "console":return r.payload.args.join(", ");case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `${r.payload.metric}: ${r.payload.value}ms`;case "memory":return r.payload.message}}function T(r){return g({generator:"ghostbug",version:f,exportedAt:new Date().toISOString(),reportCount:r.length,reports:r},2)}function L(r){let e=[];return e.push(`# Bug Report \u2014 ghostbug v${f}`),e.push(`**Generated:** ${new Date().toISOString()}`),e.push(`**Reports:** ${r.length}`),e.push(""),e.push("---"),e.push(""),r.forEach((t,o)=>{e.push(`## ${o+1}. ${Y(t)}`),e.push(""),e.push(`- **Type:** ${t.type}`),e.push(`- **Time:** ${t.timestamp}`),e.push(`- **Occurrences:** ${t.count}`),e.push(`- **URL:** ${t.context.url}`),e.push(`- **Browser:** ${Q(t.context.userAgent)}`),e.push(`- **Viewport:** ${t.context.viewport.width}x${t.context.viewport.height}`),e.push(""),e.push(...K(t.payload)),e.push(""),t.breadcrumbs.length>0&&(e.push("### Breadcrumbs"),e.push(""),e.push("| Time | Category | Event |"),e.push("|------|----------|-------|"),t.breadcrumbs.forEach(n=>{let i=n.timestamp.split("T")[1]?.split(".")[0]||n.timestamp;e.push(`| ${i} | ${n.category} | ${n.message} |`);}),e.push("")),e.push("---"),e.push("");}),e.join(`
`)}function Y(r){switch(r.payload.kind){case "error":return `${r.payload.name||"Error"}: ${r.payload.message}`;case "console":return `Console ${r.payload.level}: ${r.payload.args[0]||""}`;case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `Performance: ${r.payload.metric} ${r.payload.value}ms`;case "memory":return `Memory: ${r.payload.message}`}}function K(r){let e=[];switch(r.kind){case "error":r.stack&&(e.push("### Stack Trace"),e.push(""),e.push("```"),e.push(r.stack),e.push("```")),r.filename&&e.push(`**File:** ${r.filename}:${r.lineno}:${r.colno}`);break;case "console":e.push("### Console Output"),e.push(""),e.push("```"),r.args.forEach(t=>e.push(t)),e.push("```");break;case "network":e.push("### Network Details"),e.push(""),e.push(`- **Method:** ${r.method}`),e.push(`- **URL:** ${r.url}`),e.push(`- **Status:** ${r.status} ${r.statusText}`),e.push(`- **Duration:** ${r.duration}ms`);break;case "performance":e.push("### Performance Details"),e.push(""),e.push(`- **Metric:** ${r.metric}`),e.push(`- **Value:** ${r.value}ms`),r.entries.length>0&&e.push(`- **Start Time:** ${Math.round(r.entries[0].startTime)}ms`);break;case "memory":e.push("### Memory Details"),e.push(""),e.push(`- **Used:** ${(r.usedJSHeapSize/1048576).toFixed(1)}MB`),e.push(`- **Limit:** ${(r.jsHeapSizeLimit/1048576).toFixed(1)}MB`),e.push(`- **Usage:** ${(r.heapUsagePercent*100).toFixed(1)}%`),e.push(`- **Growth since init:** ${(r.heapGrowthPercent*100).toFixed(1)}%`);break}return e}function Q(r){if(r.includes("Chrome")){let e=r.match(/Chrome\/(\d+)/);return e?`Chrome ${e[1]}`:"Chrome"}if(r.includes("Firefox")){let e=r.match(/Firefox\/(\d+)/);return e?`Firefox ${e[1]}`:"Firefox"}if(r.includes("Safari")&&!r.includes("Chrome")){let e=r.match(/Version\/(\d+)/);return e?`Safari ${e[1]}`:"Safari"}return r.slice(0,50)}var P=class{constructor(e,t,o){this.eventBus=e;this.reportManager=t;this.options=o;this.hostElement=null;this.shadowRoot=null;this.panel=null;this.badge=null;this.reportList=null;this.isExpanded=false;this.unsubscribers=[];}mount(){this.hostElement=document.createElement("div"),this.hostElement.id="ghostbug-widget";let e=this.hostElement.style;e.position="fixed",e.zIndex=String(this.options.zIndex),e.margin="0",e.padding="0",this.applyPosition(e),this.shadowRoot=this.hostElement.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=U,this.shadowRoot.appendChild(t);let o=document.createElement("div");o.className="gb-container";let n=D();this.badge=n.querySelector(".gb-badge"),n.addEventListener("click",()=>this.toggle()),o.appendChild(n),this.panel=G(this.options.position),o.appendChild(this.panel),this.panel.querySelector(".gb-close-btn")?.addEventListener("click",()=>this.toggle()),this.panel.querySelector(".gb-copy-btn")?.addEventListener("click",()=>this.copyMarkdown()),this.panel.querySelector(".gb-download-btn")?.addEventListener("click",()=>this.downloadJSON()),this.reportList=this.panel.querySelector(".gb-report-list"),this.shadowRoot.appendChild(o),document.body.appendChild(this.hostElement),this.unsubscribers.push(this.eventBus.on("report:created",()=>this.update()),this.eventBus.on("report:deduplicated",()=>this.update())),this.options.collapsed||this.toggle();}applyPosition(e){let t=this.options.position;e.top=t.startsWith("top")?"16px":"auto",e.bottom=t.startsWith("bottom")?"16px":"auto",e.left=t.endsWith("left")?"16px":"auto",e.right=t.endsWith("right")?"16px":"auto";}toggle(){this.isExpanded=!this.isExpanded,this.isExpanded?(this.panel?.classList.add("gb-open"),this.renderReportList()):this.panel?.classList.remove("gb-open");}update(){this.updateBadge(),this.isExpanded&&this.renderReportList();}updateBadge(){if(!this.badge)return;let e=this.reportManager.reportCount;this.badge.textContent=String(e),this.badge.setAttribute("data-count",String(e));}renderReportList(){if(!this.reportList)return;this.reportList.textContent="";let e=this.reportManager.getReports();if(e.length===0){let o=document.createElement("div");o.className="gb-empty",o.textContent="No bugs captured yet.",this.reportList.appendChild(o);return}[...e].reverse().forEach(o=>{let n=X(o);this.reportList.appendChild(n);});}copyMarkdown(){let e=L(this.reportManager.getReports());navigator.clipboard.writeText(e).then(()=>this.showToast("Copied to clipboard!"),()=>this.showToast("Copy failed"));}downloadJSON(){let e=T(this.reportManager.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download="ghostbug-report.json",n.click(),URL.revokeObjectURL(o);}showToast(e){if(!this.shadowRoot)return;let t=document.createElement("div");t.className="gb-toast",t.textContent=e,this.shadowRoot.appendChild(t),requestAnimationFrame(()=>{t.classList.add("gb-show");}),setTimeout(()=>{t.classList.remove("gb-show"),setTimeout(()=>t.remove(),300);},2e3);}unmount(){this.unsubscribers.forEach(e=>e()),this.unsubscribers=[],this.hostElement?.remove(),this.hostElement=null,this.shadowRoot=null,this.panel=null,this.badge=null,this.reportList=null;}};var c=null,h=null,d=[],H=null,$=new Set,M=false,z,O;function Z(r,e){return e?{maxReports:e.maxReports??r.maxReports,maxBreadcrumbs:e.maxBreadcrumbs??r.maxBreadcrumbs,maxClicks:e.maxClicks??r.maxClicks,widget:e.widget??r.widget,collectors:{...r.collectors,...e.collectors},rateLimit:{...r.rateLimit,...e.rateLimit},beforeReport:e.beforeReport??r.beforeReport,debug:e.debug??r.debug,screenshotFn:e.screenshotFn}:{...r}}function ee(r){if(M){r?.debug&&console.warn("[ghostbug] Already initialized. Call destroy() first.");return}let e=Z(_,r);c=new b;let t=new C(()=>({user:z,tags:O}));if(h=new y(c,t,e),e.collectors.errors&&d.push(new w(c)),e.collectors.console&&d.push(new x(c)),e.collectors.network&&d.push(new E(c)),e.collectors.clicks&&d.push(new k(c,e.maxClicks)),e.collectors.interactions&&d.push(new S(c)),e.collectors.performance&&d.push(new B(c)),e.collectors.memory&&d.push(new R(c)),d.push(t),d.forEach(o=>o.setup()),c.on("report:created",o=>{$.forEach(n=>{try{n(o);}catch{}});}),e.widget){let o=typeof e.widget=="object"?{position:e.widget.position||"bottom-right",collapsed:e.widget.collapsed??true,zIndex:e.widget.zIndex??2147483647}:{position:"bottom-right",collapsed:true,zIndex:2147483647};H=new P(c,h,o),H.mount();}M=true;}function te(){return N(),h.getReports()}function re(r="ghostbug-report.json"){N();let e=T(h.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download=r,n.click(),URL.revokeObjectURL(o);}function oe(){return N(),L(h.getReports())}function ne(r){return $.add(r),()=>$.delete(r)}function ie(r){z=r;}function se(r){O={...O,...r};}function ae(){H?.unmount(),H=null,d.forEach(r=>r.teardown()),d=[],c?.clear(),c=null,h?.clear(),h=null,$.clear(),z=void 0,O=void 0,M=false;}function N(){if(!M)throw new Error("[ghostbug] Not initialized. Call ghostbug.init() first.")}var nt={init:ee,getReports:te,download:re,toMarkdown:oe,onBug:ne,setUser:ie,setTags:se,destroy:ae};exports.default=nt;exports.destroy=ae;exports.download=re;exports.getReports=te;exports.init=ee;exports.onBug=ne;exports.setTags=se;exports.setUser=ie;exports.toMarkdown=oe;//# sourceMappingURL=index.cjs.map
`;var W='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></svg>';function J(){let r=document.createElement("button");r.className="gb-fab",r.setAttribute("aria-label","ghostbug - bug reports");let e=document.createElement("span");e.innerHTML=W,r.appendChild(e);let t=document.createElement("span");return t.className="gb-badge",t.setAttribute("data-count","0"),t.textContent="0",r.appendChild(t),r}function G(r){let e=document.createElement("div");e.className=`gb-panel gb-pos-${r}`;let t=document.createElement("div");t.className="gb-header";let o=document.createElement("span");o.className="gb-header-title",o.textContent="ghostbug",t.appendChild(o);let n=document.createElement("button");n.className="gb-header-btn gb-copy-btn",n.textContent="Copy MD",t.appendChild(n);let i=document.createElement("button");i.className="gb-header-btn gb-download-btn",i.textContent="Export",t.appendChild(i);let a=document.createElement("button");a.className="gb-close-btn",a.textContent="\xD7",a.setAttribute("aria-label","Close"),t.appendChild(a),e.appendChild(t);let l=document.createElement("div");l.className="gb-report-list";let s=document.createElement("div");return s.className="gb-empty",s.textContent="No bugs captured yet.",l.appendChild(s),e.appendChild(l),e}function q(r){let e=document.createElement("div");e.className="gb-report-item";let t=document.createElement("div");t.className="gb-report-summary";let o=document.createElement("span");if(o.className=`gb-report-type gb-type-${r.payload.kind==="error"?"error":r.payload.kind}`,o.textContent=r.type,t.appendChild(o),r.count>1){let s=document.createElement("span");s.className="gb-report-count",s.textContent=`\xD7${r.count}`,t.appendChild(s);}let n=document.createElement("div");n.className="gb-report-message",n.textContent=Y(r),t.appendChild(n);let i=document.createElement("div");i.className="gb-report-meta";let a=r.timestamp.split("T")[1]?.split(".")[0]||r.timestamp;i.textContent=`${a} \xB7 ${r.context.url}`,t.appendChild(i),e.appendChild(t);let l=document.createElement("div");if(l.className="gb-report-detail",l.appendChild(V(r.payload)),r.context.user){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">User</div><div class="gb-detail-value">${g(JSON.stringify(r.context.user))}</div>`,l.appendChild(s);}if(r.context.tags){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">Tags</div><div class="gb-detail-value">${g(JSON.stringify(r.context.tags))}</div>`,l.appendChild(s);}if(r.breadcrumbs.length>0){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">Breadcrumbs</div><div class="gb-detail-value">${r.breadcrumbs.length} events</div>`,l.appendChild(s);}return e.appendChild(l),t.addEventListener("click",()=>{e.classList.toggle("gb-expanded");}),e}function g(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function V(r){let e=document.createElement("div");switch(e.className="gb-detail-section",r.kind){case "error":{if(r.stack){let t=document.createElement("div");t.className="gb-detail-label",t.textContent="Stack Trace",e.appendChild(t);let o=document.createElement("pre");o.className="gb-detail-pre",o.textContent=r.stack,e.appendChild(o);}if(r.filename){let t=document.createElement("div");t.className="gb-detail-value",t.textContent=`${r.filename}:${r.lineno}:${r.colno}`,e.appendChild(t);}break}case "console":{let t=document.createElement("div");t.className="gb-detail-label",t.textContent="Output",e.appendChild(t);let o=document.createElement("pre");o.className="gb-detail-pre",o.textContent=r.args.join(`
`),e.appendChild(o);break}case "network":{e.innerHTML=`<div class="gb-detail-label">Request</div><div class="gb-detail-value">${g(r.method)} ${g(r.url)}<br>Status: ${r.status} ${g(r.statusText)}<br>Duration: ${r.duration}ms</div>`;break}case "performance":{e.innerHTML=`<div class="gb-detail-label">Performance</div><div class="gb-detail-value">Metric: ${g(r.metric)}<br>Value: ${r.value}ms</div>`;break}case "memory":{e.innerHTML=`<div class="gb-detail-label">Memory</div><div class="gb-detail-value">Used: ${(r.usedJSHeapSize/1048576).toFixed(1)}MB<br>Limit: ${(r.jsHeapSizeLimit/1048576).toFixed(1)}MB<br>Usage: ${(r.heapUsagePercent*100).toFixed(1)}%</div>`;break}}return e}function Y(r){switch(r.payload.kind){case "error":return r.payload.message;case "console":return r.payload.args.join(", ");case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `${r.payload.metric}: ${r.payload.value}ms`;case "memory":return r.payload.message}}function L(r){return f({generator:"ghostbug",version:b,exportedAt:new Date().toISOString(),reportCount:r.length,reports:r},2)}function P(r){let e=[];return e.push(`# Bug Report \u2014 ghostbug v${b}`),e.push(`**Generated:** ${new Date().toISOString()}`),e.push(`**Reports:** ${r.length}`),e.push(""),e.push("---"),e.push(""),r.forEach((t,o)=>{e.push(`## ${o+1}. ${K(t)}`),e.push(""),e.push(`- **Type:** ${t.type}`),e.push(`- **Time:** ${t.timestamp}`),e.push(`- **Occurrences:** ${t.count}`),e.push(`- **URL:** ${t.context.url}`),e.push(`- **Browser:** ${Z(t.context.userAgent)}`),e.push(`- **Viewport:** ${t.context.viewport.width}x${t.context.viewport.height}`),e.push(""),e.push(...Q(t.payload)),e.push(""),t.context.user&&(e.push("### User Context"),e.push(""),e.push("```json"),e.push(JSON.stringify(t.context.user,null,2)),e.push("```"),e.push("")),t.context.tags&&(e.push("### Tags"),e.push(""),e.push("```json"),e.push(JSON.stringify(t.context.tags,null,2)),e.push("```"),e.push("")),t.breadcrumbs.length>0&&(e.push("### Breadcrumbs"),e.push(""),e.push("| Time | Category | Event |"),e.push("|------|----------|-------|"),t.breadcrumbs.forEach(n=>{let i=n.timestamp.split("T")[1]?.split(".")[0]||n.timestamp;e.push(`| ${i} | ${n.category} | ${n.message} |`);}),e.push("")),e.push("---"),e.push("");}),e.join(`
`)}function K(r){switch(r.payload.kind){case "error":return `${r.payload.name||"Error"}: ${r.payload.message}`;case "console":return `Console ${r.payload.level}: ${r.payload.args[0]||""}`;case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `Performance: ${r.payload.metric} ${r.payload.value}ms`;case "memory":return `Memory: ${r.payload.message}`}}function Q(r){let e=[];switch(r.kind){case "error":r.stack&&(e.push("### Stack Trace"),e.push(""),e.push("```"),e.push(r.stack),e.push("```")),r.filename&&e.push(`**File:** ${r.filename}:${r.lineno}:${r.colno}`);break;case "console":e.push("### Console Output"),e.push(""),e.push("```"),r.args.forEach(t=>e.push(t)),e.push("```");break;case "network":e.push("### Network Details"),e.push(""),e.push(`- **Method:** ${r.method}`),e.push(`- **URL:** ${r.url}`),e.push(`- **Status:** ${r.status} ${r.statusText}`),e.push(`- **Duration:** ${r.duration}ms`);break;case "performance":e.push("### Performance Details"),e.push(""),e.push(`- **Metric:** ${r.metric}`),e.push(`- **Value:** ${r.value}ms`),r.entries.length>0&&e.push(`- **Start Time:** ${Math.round(r.entries[0].startTime)}ms`);break;case "memory":e.push("### Memory Details"),e.push(""),e.push(`- **Used:** ${(r.usedJSHeapSize/1048576).toFixed(1)}MB`),e.push(`- **Limit:** ${(r.jsHeapSizeLimit/1048576).toFixed(1)}MB`),e.push(`- **Usage:** ${(r.heapUsagePercent*100).toFixed(1)}%`),e.push(`- **Growth since init:** ${(r.heapGrowthPercent*100).toFixed(1)}%`);break}return e}function Z(r){if(r.includes("Chrome")){let e=r.match(/Chrome\/(\d+)/);return e?`Chrome ${e[1]}`:"Chrome"}if(r.includes("Firefox")){let e=r.match(/Firefox\/(\d+)/);return e?`Firefox ${e[1]}`:"Firefox"}if(r.includes("Safari")&&!r.includes("Chrome")){let e=r.match(/Version\/(\d+)/);return e?`Safari ${e[1]}`:"Safari"}return r.slice(0,50)}var $=class{constructor(e,t,o){this.eventBus=e;this.reportManager=t;this.options=o;this.hostElement=null;this.shadowRoot=null;this.panel=null;this.badge=null;this.reportList=null;this.isExpanded=false;this.unsubscribers=[];}mount(){this.hostElement=document.createElement("div"),this.hostElement.id="ghostbug-widget";let e=this.hostElement.style;e.position="fixed",e.zIndex=String(this.options.zIndex),e.margin="0",e.padding="0",this.applyPosition(e),this.shadowRoot=this.hostElement.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=D,this.shadowRoot.appendChild(t);let o=document.createElement("div");o.className="gb-container";let n=J();this.badge=n.querySelector(".gb-badge"),n.addEventListener("click",()=>this.toggle()),o.appendChild(n),this.panel=G(this.options.position),o.appendChild(this.panel),this.panel.querySelector(".gb-close-btn")?.addEventListener("click",()=>this.toggle()),this.panel.querySelector(".gb-copy-btn")?.addEventListener("click",()=>this.copyMarkdown()),this.panel.querySelector(".gb-download-btn")?.addEventListener("click",()=>this.downloadJSON()),this.reportList=this.panel.querySelector(".gb-report-list"),this.shadowRoot.appendChild(o),document.body.appendChild(this.hostElement),this.unsubscribers.push(this.eventBus.on("report:created",()=>this.update()),this.eventBus.on("report:deduplicated",()=>this.update())),this.options.collapsed||this.toggle();}applyPosition(e){let t=this.options.position;e.top=t.startsWith("top")?"16px":"auto",e.bottom=t.startsWith("bottom")?"16px":"auto",e.left=t.endsWith("left")?"16px":"auto",e.right=t.endsWith("right")?"16px":"auto";}toggle(){this.isExpanded=!this.isExpanded,this.isExpanded?(this.panel?.classList.add("gb-open"),this.renderReportList()):this.panel?.classList.remove("gb-open");}update(){this.updateBadge(),this.isExpanded&&this.renderReportList();}updateBadge(){if(!this.badge)return;let e=this.reportManager.reportCount;this.badge.textContent=String(e),this.badge.setAttribute("data-count",String(e));}renderReportList(){if(!this.reportList)return;this.reportList.textContent="";let e=this.reportManager.getReports();if(e.length===0){let o=document.createElement("div");o.className="gb-empty",o.textContent="No bugs captured yet.",this.reportList.appendChild(o);return}[...e].reverse().forEach(o=>{let n=q(o);this.reportList.appendChild(n);});}copyMarkdown(){let e=P(this.reportManager.getReports());navigator.clipboard.writeText(e).then(()=>this.showToast("Copied to clipboard!"),()=>this.showToast("Copy failed"));}downloadJSON(){let e=L(this.reportManager.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download="ghostbug-report.json",n.click(),URL.revokeObjectURL(o);}showToast(e){if(!this.shadowRoot)return;let t=document.createElement("div");t.className="gb-toast",t.textContent=e,this.shadowRoot.appendChild(t),requestAnimationFrame(()=>{t.classList.add("gb-show");}),setTimeout(()=>{t.classList.remove("gb-show"),setTimeout(()=>t.remove(),300);},2e3);}unmount(){this.unsubscribers.forEach(e=>e()),this.unsubscribers=[],this.hostElement?.remove(),this.hostElement=null,this.shadowRoot=null,this.panel=null,this.badge=null,this.reportList=null;}};var d=null,h=null,c=[],H=null,M=new Set,O=false,z,N;function ee(r,e){return e?{maxReports:e.maxReports??r.maxReports,maxBreadcrumbs:e.maxBreadcrumbs??r.maxBreadcrumbs,maxClicks:e.maxClicks??r.maxClicks,widget:e.widget??r.widget,collectors:{...r.collectors,...e.collectors},rateLimit:{...r.rateLimit,...e.rateLimit},beforeReport:e.beforeReport??r.beforeReport,debug:e.debug??r.debug}:{...r}}function te(r){if(O){r?.debug&&console.warn("[ghostbug] Already initialized. Call destroy() first.");return}let e=ee(I,r);d=new v;let t=new S(()=>({user:z,tags:N}));if(h=new w(d,t,e),e.collectors.errors&&c.push(new x(d)),e.collectors.console&&c.push(new E(d)),e.collectors.network&&c.push(new k(d)),e.collectors.clicks&&c.push(new C(d,e.maxClicks)),e.collectors.interactions&&c.push(new B(d)),e.collectors.performance&&c.push(new R(d)),e.collectors.memory&&c.push(new T(d)),c.push(t),c.forEach(o=>o.setup()),d.on("report:created",o=>{M.forEach(n=>{try{n(o);}catch{}});}),e.widget){let o=typeof e.widget=="object"?{position:e.widget.position||"bottom-right",collapsed:e.widget.collapsed??true,zIndex:e.widget.zIndex??2147483647}:{position:"bottom-right",collapsed:true,zIndex:2147483647};H=new $(d,h,o),H.mount();}O=true;}function re(){return _(),h.getReports()}function oe(r="ghostbug-report.json"){_();let e=L(h.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download=r,n.click(),URL.revokeObjectURL(o);}function ne(){return _(),P(h.getReports())}function ie(r){return M.add(r),()=>M.delete(r)}function se(r){z=r;}function ae(r){N={...N,...r};}function le(){H?.unmount(),H=null,c.forEach(r=>r.teardown()),c=[],d?.clear(),d=null,h?.clear(),h=null,M.clear(),z=void 0,N=void 0,O=false;}function _(){if(!O)throw new Error("[ghostbug] Not initialized. Call ghostbug.init() first.")}var it={init:te,getReports:re,download:oe,toMarkdown:ne,onBug:ie,setUser:se,setTags:ae,destroy:le};exports.default=it;exports.destroy=le;exports.download=oe;exports.getReports=re;exports.init=te;exports.onBug=ie;exports.setTags=ae;exports.setUser=se;exports.toMarkdown=ne;//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map
+0
-3

@@ -18,4 +18,2 @@ interface GhostbugOptions {

debug?: boolean;
/** Async function that returns a screenshot data URL. Called on each new bug report. */
screenshotFn?: () => Promise<string>;
}

@@ -53,3 +51,2 @@ interface CollectorToggle {

context: PageContext;
screenshot?: string;
}

@@ -56,0 +53,0 @@ interface ErrorPayload {

@@ -18,4 +18,2 @@ interface GhostbugOptions {

debug?: boolean;
/** Async function that returns a screenshot data URL. Called on each new bug report. */
screenshotFn?: () => Promise<string>;
}

@@ -53,3 +51,2 @@ interface CollectorToggle {

context: PageContext;
screenshot?: string;
}

@@ -56,0 +53,0 @@ interface ErrorPayload {

@@ -1,3 +0,3 @@

"use strict";var ghostbug=(()=>{var z=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var oe=Object.prototype.hasOwnProperty;var ne=(r,e)=>{for(var t in e)z(r,t,{get:e[t],enumerable:!0})},ie=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of re(e))!oe.call(r,n)&&n!==t&&z(r,n,{get:()=>e[n],enumerable:!(o=te(e,n))||o.enumerable});return r};var se=r=>ie(z({},"__esModule",{value:!0}),r);var fe={};ne(fe,{default:()=>ge,destroy:()=>ee,download:()=>V,getReports:()=>J,init:()=>W,onBug:()=>K,setTags:()=>Z,setUser:()=>Q,toMarkdown:()=>Y});var f="0.1.0",I={maxReports:50,maxBreadcrumbs:20,maxClicks:20,widget:!1,collectors:{errors:!0,console:!0,network:!0,clicks:!0,interactions:!0,performance:!0,memory:!0},rateLimit:{maxEvents:10,windowMs:1e3},beforeReport:r=>r,debug:!1};var b=class{constructor(){this.listeners=new Map}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){this.listeners.get(e)?.forEach(o=>{try{o(t)}catch{}})}clear(){this.listeners.clear()}};var m=class{constructor(e){this.capacity=e;this.head=0;this._size=0;this.buffer=new Array(e)}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this._size<this.capacity&&this._size++}toArray(){if(this._size===0)return[];let e=[],t=this._size<this.capacity?0:this.head;for(let o=0;o<this._size;o++){let n=(t+o)%this.capacity;e.push(this.buffer[n])}return e}get size(){return this._size}get isFull(){return this._size===this.capacity}peek(){if(this._size===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}find(e){return this.toArray().find(e)}forEach(e){this.toArray().forEach(e)}clear(){this.buffer=new Array(this.capacity),this.head=0,this._size=0}};var v=class{constructor(e,t){this.maxEvents=e;this.windowMs=t;this.timestamps=[]}allow(){let e=Date.now();return this.timestamps=this.timestamps.filter(t=>e-t<this.windowMs),this.timestamps.length>=this.maxEvents?!1:(this.timestamps.push(e),!0)}reset(){this.timestamps=[]}};function ae(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e+r.charCodeAt(t)&4294967295;return(e>>>0).toString(36)}function A(r){let e;switch(r.kind){case"error":{let t=r.stack?.split(`
`)[1]?.trim()||"";e=`${r.name}:${r.message}:${t}`;break}case"console":e=`console:${r.level}:${r.args.join(",")}`;break;case"network":e=`network:${r.method}:${r.url}:${r.status}`;break;case"performance":e=`performance:${r.metric}:${Math.floor(r.value/100)*100}`;break;case"memory":e=`memory:${Math.floor(r.heapUsagePercent*10)/10}`;break}return ae(e)}function F(){let r=new Uint8Array(8);return crypto.getRandomValues(r),Array.from(r,e=>e.toString(36).padStart(2,"0")).join("").slice(0,12)}var le=3e3,y=class{constructor(e,t,o){this.eventBus=e;this.contextCollector=t;this.options=o;this.unsubscribers=[];this.reports=new m(o.maxReports),this.breadcrumbs=new m(o.maxBreadcrumbs),this.rateLimiter=new v(o.rateLimit.maxEvents,o.rateLimit.windowMs),this.subscribe()}subscribe(){this.unsubscribers.push(this.eventBus.on("error:captured",e=>{this.addBreadcrumb({category:"error",message:e.message}),this.handleCapturedEvent("error",e)}),this.eventBus.on("console:captured",e=>{this.addBreadcrumb({category:"console",message:`console.${e.level}: ${e.args.join(", ")}`}),e.level==="error"&&this.handleCapturedEvent("console",e)}),this.eventBus.on("network:captured",e=>{this.handleCapturedEvent("network",e)}),this.eventBus.on("performance:captured",e=>{this.addBreadcrumb({category:"performance",message:`${e.metric}: ${e.value}ms`}),this.handleCapturedEvent("performance",e)}),this.eventBus.on("memory:captured",e=>{this.handleCapturedEvent("memory",e)}),this.eventBus.on("breadcrumb:added",e=>{this.addBreadcrumb(e)}))}async handleCapturedEvent(e,t){if(!this.rateLimiter.allow())return;let o=A(t),n=this.reports.find(l=>l.fingerprint===o);if(n){n.count++,n.timestamp=new Date().toISOString(),this.eventBus.emit("report:deduplicated",n);return}let i={id:F(),fingerprint:o,type:e,timestamp:new Date().toISOString(),count:1,payload:t,breadcrumbs:this.breadcrumbs.toArray(),context:this.contextCollector.snapshot()};if(this.options.screenshotFn)try{i.screenshot=await Promise.race([this.options.screenshotFn(),new Promise((l,a)=>setTimeout(()=>a(new Error("screenshot timeout")),le))])}catch{}let s=this.options.beforeReport(i);s&&(i=s,this.reports.push(i),this.eventBus.emit("report:created",i))}addBreadcrumb(e){this.breadcrumbs.push({...e,timestamp:new Date().toISOString()})}getReports(){return this.reports.toArray()}clear(){this.reports.clear(),this.breadcrumbs.clear(),this.unsubscribers.forEach(e=>e()),this.unsubscribers=[]}get reportCount(){return this.reports.size}};var w=class{constructor(e){this.eventBus=e;this.name="error";this.originalOnError=null;this.rejectionHandler=null}setup(){this.originalOnError=window.onerror,window.onerror=(e,t,o,n,i)=>{let s={kind:"error",message:String(e),stack:i?.stack,filename:t??void 0,lineno:o??void 0,colno:n??void 0,name:i?.name};return this.eventBus.emit("error:captured",s),this.originalOnError?this.originalOnError.call(window,e,t,o,n,i):!1},this.rejectionHandler=e=>{let t=e.reason,o={kind:"error",message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,name:t instanceof Error?t.name:"UnhandledRejection"};this.eventBus.emit("error:captured",o)},window.addEventListener("unhandledrejection",this.rejectionHandler)}teardown(){window.onerror=this.originalOnError,this.originalOnError=null,this.rejectionHandler&&(window.removeEventListener("unhandledrejection",this.rejectionHandler),this.rejectionHandler=null)}};function g(r,e){let t=new WeakSet;return JSON.stringify(r,(o,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return"[Circular]";t.add(n)}return typeof n=="function"?"[Function]":typeof n=="symbol"?n.toString():n instanceof Error?{name:n.name,message:n.message,stack:n.stack}:n},e)}var x=class{constructor(e){this.eventBus=e;this.name="console";this.originalError=null;this.originalWarn=null}setup(){this.originalError=console.error,this.originalWarn=console.warn,console.error=(...e)=>{let t={kind:"console",level:"error",args:e.map(o=>g(o))};this.eventBus.emit("console:captured",t),this.originalError.apply(console,e)},console.warn=(...e)=>{let t={kind:"console",level:"warn",args:e.map(o=>g(o))};this.eventBus.emit("console:captured",t),this.originalWarn.apply(console,e)}}teardown(){this.originalError&&(console.error=this.originalError),this.originalWarn&&(console.warn=this.originalWarn),this.originalError=null,this.originalWarn=null}};var E=class{constructor(e){this.eventBus=e;this.name="network";this.originalFetch=null;this.originalXhrOpen=null;this.originalXhrSend=null}setup(){this.patchFetch(),this.patchXHR()}patchFetch(){this.originalFetch=window.fetch;let e=this.eventBus,t=this.originalFetch;window.fetch=function(o,n){let i=n?.method?.toUpperCase()||"GET",s=typeof o=="string"?o:o instanceof URL?o.href:o.url,l=performance.now();return t.call(window,o,n).then(a=>{let p=Math.round(performance.now()-l);if(a.status>=400){let u={kind:"network",method:i,url:s,status:a.status,statusText:a.statusText,duration:p};e.emit("network:captured",u)}return e.emit("breadcrumb:added",{category:"network",message:`${i} ${s} -> ${a.status}`}),a},a=>{let p=Math.round(performance.now()-l),u={kind:"network",method:i,url:s,status:0,statusText:a.message||"Network Error",duration:p};throw e.emit("network:captured",u),a})}}patchXHR(){this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let e=this.eventBus,t=this.originalXhrOpen,o=this.originalXhrSend;XMLHttpRequest.prototype.open=function(n,i,...s){return this.__ghostbug_method=n.toUpperCase(),this.__ghostbug_url=String(i),t.apply(this,[n,i,...s])},XMLHttpRequest.prototype.send=function(n){let i=performance.now(),s=this;return s.addEventListener("loadend",function(){let l=Math.round(performance.now()-i),a=s.__ghostbug_method||"UNKNOWN",p=s.__ghostbug_url||"";if(s.status>=400||s.status===0){let u={kind:"network",method:a,url:p,status:s.status,statusText:s.statusText,duration:l};e.emit("network:captured",u)}e.emit("breadcrumb:added",{category:"network",message:`${a} ${p} -> ${s.status}`})}),o.call(this,n)}}teardown(){this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null)}};function j(r){if(r.id)return`#${r.id}`;let e=r.getAttribute("data-testid");if(e)return`[data-testid="${e}"]`;let t=[],o=r,n=0;for(;o&&o!==document.documentElement&&n<5;){let i=o.tagName.toLowerCase();if(o.id){t.unshift(`#${o.id}`);break}let s=Array.from(o.classList).slice(0,2);s.length>0&&(i+="."+s.join("."));let l=o.parentElement;if(l){let a=o.tagName,p=Array.from(l.children).filter(u=>u.tagName===a);if(p.length>1){let u=p.indexOf(o)+1;i+=`:nth-child(${u})`}}t.unshift(i),o=l,n++}return t.join(" > ")}var k=class{constructor(e,t){this.eventBus=e;this.name="click";this.handler=null;this.clicks=new m(t)}setup(){this.handler=e=>{let t=e.target;if(!t)return;let o={timestamp:new Date().toISOString(),selector:j(t),tagName:t.tagName.toLowerCase(),text:(t.textContent||"").trim().slice(0,100),position:{x:e.clientX,y:e.clientY}};this.clicks.push(o),this.eventBus.emit("click:captured",o),this.eventBus.emit("breadcrumb:added",{category:"click",message:`Clicked ${o.tagName} "${o.text}"`,data:{selector:o.selector}})},document.addEventListener("click",this.handler,!0)}getClickTrail(){return this.clicks.toArray()}teardown(){this.handler&&(document.removeEventListener("click",this.handler,!0),this.handler=null),this.clicks.clear()}};var C=class{constructor(e){this.getMeta=e;this.name="context"}setup(){}teardown(){}snapshot(){let e=this.getMeta?.();return{url:window.location.href,referrer:document.referrer,userAgent:navigator.userAgent,language:navigator.language,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},devicePixelRatio:window.devicePixelRatio||1,timestamp:new Date().toISOString(),memory:performance.memory?{usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize}:void 0,user:e?.user,tags:e?.tags}}};var S=class{constructor(e){this.eventBus=e;this.name="interactions";this.handlers=[];this.scrollTimer=null;this.resizeTimer=null}setup(){this.addHandler(window,"scroll",this.onScroll.bind(this),{passive:!0,capture:!0}),this.addHandler(document,"input",this.onInput.bind(this),!0),this.addHandler(document,"change",this.onChange.bind(this),!0),this.addHandler(window,"popstate",this.onPopState.bind(this)),this.addHandler(window,"hashchange",this.onHashChange.bind(this)),this.addHandler(document,"visibilitychange",this.onVisibilityChange.bind(this)),this.addHandler(window,"resize",this.onResize.bind(this),{passive:!0})}addHandler(e,t,o,n){e.addEventListener(t,o,n),this.handlers.push({target:e,event:t,handler:o})}onScroll(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Scrolled",data:{x:window.scrollX,y:window.scrollY}})},300)}onInput(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"",i=t.type?`[type="${t.type}"]`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Input on ${o}${n}${i}`})}onChange(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Change on ${o}${n}`})}onPopState(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Navigated to ${window.location.href}`})}onHashChange(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Hash changed to ${window.location.hash}`})}onVisibilityChange(){this.eventBus.emit("breadcrumb:added",{category:"visibility",message:document.hidden?"Tab hidden":"Tab visible"})}onResize(){this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Window resized",data:{width:window.innerWidth,height:window.innerHeight}})},300)}teardown(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.resizeTimer&&clearTimeout(this.resizeTimer),this.handlers.forEach(({target:e,event:t,handler:o})=>{e.removeEventListener(t,o)}),this.handlers=[]}};var B=class{constructor(e){this.eventBus=e;this.name="performance";this.observers=[]}setup(){typeof PerformanceObserver>"u"||(this.observe("longtask",e=>{e.forEach(t=>{if(t.duration<50)return;let o={kind:"performance",metric:"longtask",value:Math.round(t.duration),entries:[{name:t.name,duration:t.duration,startTime:t.startTime}]};this.eventBus.emit("performance:captured",o),this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Long task: ${Math.round(t.duration)}ms`})})}),this.observe("largest-contentful-paint",e=>{let t=e[e.length-1];t&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`LCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}})}),this.observe("paint",e=>{e.forEach(t=>{t.name==="first-contentful-paint"&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`FCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}})})}),this.observe("layout-shift",e=>{e.forEach(t=>{let o=t.value;o>.1&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Layout shift: ${o.toFixed(4)}`,data:{cls:o}})})}))}observe(e,t){try{let o=new PerformanceObserver(n=>{t(n.getEntries())});o.observe({type:e,buffered:!0}),this.observers.push(o)}catch{}}teardown(){this.observers.forEach(e=>e.disconnect()),this.observers=[]}};function U(){let r=performance.memory;return!r||typeof r.usedJSHeapSize!="number"?null:r}var R=class{constructor(e){this.eventBus=e;this.name="memory";this.intervalId=null;this.baselineUsed=null}setup(){let e=U();e&&(this.baselineUsed=e.usedJSHeapSize,this.intervalId=setInterval(()=>{let t=U();if(!t)return;let o=t.usedJSHeapSize/t.jsHeapSizeLimit,n=this.baselineUsed>0?(t.usedJSHeapSize-this.baselineUsed)/this.baselineUsed:0;this.eventBus.emit("breadcrumb:added",{category:"memory",message:`Heap: ${(o*100).toFixed(1)}% used (${(t.usedJSHeapSize/1048576).toFixed(1)}MB)`,data:{usedJSHeapSize:t.usedJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit}});let i=o>=.9,s=n>=.5;if(i||s){let a={kind:"memory",message:i?`Heap usage critical: ${(o*100).toFixed(1)}% of limit`:`Heap growth spike: ${(n*100).toFixed(1)}% since init`,usedJSHeapSize:t.usedJSHeapSize,totalJSHeapSize:t.totalJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit,heapUsagePercent:o,heapGrowthPercent:n};this.eventBus.emit("memory:captured",a)}},1e4))}teardown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.baselineUsed=null}};var D=`
"use strict";var ghostbug=(()=>{var z=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ne=Object.prototype.hasOwnProperty;var ie=(t,e)=>{for(var r in e)z(t,r,{get:e[r],enumerable:!0})},se=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of oe(e))!ne.call(t,n)&&n!==r&&z(t,n,{get:()=>e[n],enumerable:!(o=re(e,n))||o.enumerable});return t};var ae=t=>se(z({},"__esModule",{value:!0}),t);var be={};ie(be,{default:()=>fe,destroy:()=>te,download:()=>Y,getReports:()=>V,init:()=>W,onBug:()=>Q,setTags:()=>ee,setUser:()=>Z,toMarkdown:()=>K});var b="0.1.0",A={maxReports:50,maxBreadcrumbs:20,maxClicks:20,widget:!1,collectors:{errors:!0,console:!0,network:!0,clicks:!0,interactions:!0,performance:!0,memory:!0},rateLimit:{maxEvents:10,windowMs:1e3},beforeReport:t=>t,debug:!1};var v=class{constructor(){this.listeners=new Map}on(e,r){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(r),()=>this.off(e,r)}off(e,r){this.listeners.get(e)?.delete(r)}emit(e,r){this.listeners.get(e)?.forEach(o=>{try{o(r)}catch{}})}clear(){this.listeners.clear()}};var m=class{constructor(e){this.capacity=e;this.head=0;this._size=0;this.buffer=new Array(e)}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this._size<this.capacity&&this._size++}toArray(){if(this._size===0)return[];let e=[],r=this._size<this.capacity?0:this.head;for(let o=0;o<this._size;o++){let n=(r+o)%this.capacity;e.push(this.buffer[n])}return e}get size(){return this._size}get isFull(){return this._size===this.capacity}peek(){if(this._size===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}find(e){return this.toArray().find(e)}forEach(e){this.toArray().forEach(e)}clear(){this.buffer=new Array(this.capacity),this.head=0,this._size=0}};var y=class{constructor(e,r){this.maxEvents=e;this.windowMs=r;this.timestamps=[]}allow(){let e=Date.now();return this.timestamps=this.timestamps.filter(r=>e-r<this.windowMs),this.timestamps.length>=this.maxEvents?!1:(this.timestamps.push(e),!0)}reset(){this.timestamps=[]}};function le(t){let e=5381;for(let r=0;r<t.length;r++)e=(e<<5)+e+t.charCodeAt(r)&4294967295;return(e>>>0).toString(36)}function j(t){let e;switch(t.kind){case"error":{let r=t.stack?.split(`
`)[1]?.trim()||"";e=`${t.name}:${t.message}:${r}`;break}case"console":e=`console:${t.level}:${t.args.join(",")}`;break;case"network":e=`network:${t.method}:${t.url}:${t.status}`;break;case"performance":e=`performance:${t.metric}:${Math.floor(t.value/100)*100}`;break;case"memory":e=`memory:${Math.floor(t.heapUsagePercent*10)/10}`;break}return le(e)}function U(){let t=new Uint8Array(8);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(36).padStart(2,"0")).join("").slice(0,12)}var w=class{constructor(e,r,o){this.eventBus=e;this.contextCollector=r;this.options=o;this.unsubscribers=[];this.reports=new m(o.maxReports),this.breadcrumbs=new m(o.maxBreadcrumbs),this.rateLimiter=new y(o.rateLimit.maxEvents,o.rateLimit.windowMs),this.subscribe()}subscribe(){this.unsubscribers.push(this.eventBus.on("error:captured",e=>{this.addBreadcrumb({category:"error",message:e.message}),this.handleCapturedEvent("error",e)}),this.eventBus.on("console:captured",e=>{this.addBreadcrumb({category:"console",message:`console.${e.level}: ${e.args.join(", ")}`}),e.level==="error"&&this.handleCapturedEvent("console",e)}),this.eventBus.on("network:captured",e=>{this.handleCapturedEvent("network",e)}),this.eventBus.on("performance:captured",e=>{this.addBreadcrumb({category:"performance",message:`${e.metric}: ${e.value}ms`}),this.handleCapturedEvent("performance",e)}),this.eventBus.on("memory:captured",e=>{this.handleCapturedEvent("memory",e)}),this.eventBus.on("breadcrumb:added",e=>{this.addBreadcrumb(e)}))}async handleCapturedEvent(e,r){if(!this.rateLimiter.allow())return;let o=j(r),n=this.reports.find(l=>l.fingerprint===o);if(n){n.count++,n.timestamp=new Date().toISOString(),this.eventBus.emit("report:deduplicated",n);return}let i={id:U(),fingerprint:o,type:e,timestamp:new Date().toISOString(),count:1,payload:r,breadcrumbs:this.breadcrumbs.toArray(),context:this.contextCollector.snapshot()},a=this.options.beforeReport(i);a&&(i=a,this.reports.push(i),this.eventBus.emit("report:created",i))}addBreadcrumb(e){this.breadcrumbs.push({...e,timestamp:new Date().toISOString()})}getReports(){return this.reports.toArray()}clear(){this.reports.clear(),this.breadcrumbs.clear(),this.unsubscribers.forEach(e=>e()),this.unsubscribers=[]}get reportCount(){return this.reports.size}};var x=class{constructor(e){this.eventBus=e;this.name="error";this.originalOnError=null;this.rejectionHandler=null}setup(){this.originalOnError=window.onerror,window.onerror=(e,r,o,n,i)=>{let a={kind:"error",message:String(e),stack:i?.stack,filename:r??void 0,lineno:o??void 0,colno:n??void 0,name:i?.name};return this.eventBus.emit("error:captured",a),this.originalOnError?this.originalOnError.call(window,e,r,o,n,i):!1},this.rejectionHandler=e=>{let r=e.reason,o={kind:"error",message:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0,name:r instanceof Error?r.name:"UnhandledRejection"};this.eventBus.emit("error:captured",o)},window.addEventListener("unhandledrejection",this.rejectionHandler)}teardown(){window.onerror=this.originalOnError,this.originalOnError=null,this.rejectionHandler&&(window.removeEventListener("unhandledrejection",this.rejectionHandler),this.rejectionHandler=null)}};function f(t,e){let r=new WeakSet;return JSON.stringify(t,(o,n)=>{if(typeof n=="object"&&n!==null){if(r.has(n))return"[Circular]";r.add(n)}return typeof n=="function"?"[Function]":typeof n=="symbol"?n.toString():n instanceof Error?{name:n.name,message:n.message,stack:n.stack}:n},e)}var E=class{constructor(e){this.eventBus=e;this.name="console";this.originalError=null;this.originalWarn=null}setup(){this.originalError=console.error,this.originalWarn=console.warn,console.error=(...e)=>{let r={kind:"console",level:"error",args:e.map(o=>f(o))};this.eventBus.emit("console:captured",r),this.originalError.apply(console,e)},console.warn=(...e)=>{let r={kind:"console",level:"warn",args:e.map(o=>f(o))};this.eventBus.emit("console:captured",r),this.originalWarn.apply(console,e)}}teardown(){this.originalError&&(console.error=this.originalError),this.originalWarn&&(console.warn=this.originalWarn),this.originalError=null,this.originalWarn=null}};var k=class{constructor(e){this.eventBus=e;this.name="network";this.originalFetch=null;this.originalXhrOpen=null;this.originalXhrSend=null}setup(){this.patchFetch(),this.patchXHR()}patchFetch(){this.originalFetch=window.fetch;let e=this.eventBus,r=this.originalFetch;window.fetch=function(o,n){let i=n?.method?.toUpperCase()||"GET",a=typeof o=="string"?o:o instanceof URL?o.href:o.url,l=performance.now();return r.call(window,o,n).then(s=>{let p=Math.round(performance.now()-l);if(s.status>=400){let u={kind:"network",method:i,url:a,status:s.status,statusText:s.statusText,duration:p};e.emit("network:captured",u)}return e.emit("breadcrumb:added",{category:"network",message:`${i} ${a} -> ${s.status}`}),s},s=>{let p=Math.round(performance.now()-l),u={kind:"network",method:i,url:a,status:0,statusText:s.message||"Network Error",duration:p};throw e.emit("network:captured",u),s})}}patchXHR(){this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let e=this.eventBus,r=this.originalXhrOpen,o=this.originalXhrSend;XMLHttpRequest.prototype.open=function(n,i,...a){return this.__ghostbug_method=n.toUpperCase(),this.__ghostbug_url=String(i),r.apply(this,[n,i,...a])},XMLHttpRequest.prototype.send=function(n){let i=performance.now(),a=this;return a.addEventListener("loadend",function(){let l=Math.round(performance.now()-i),s=a.__ghostbug_method||"UNKNOWN",p=a.__ghostbug_url||"";if(a.status>=400||a.status===0){let u={kind:"network",method:s,url:p,status:a.status,statusText:a.statusText,duration:l};e.emit("network:captured",u)}e.emit("breadcrumb:added",{category:"network",message:`${s} ${p} -> ${a.status}`})}),o.call(this,n)}}teardown(){this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null)}};function F(t){if(t.id)return`#${t.id}`;let e=t.getAttribute("data-testid");if(e)return`[data-testid="${e}"]`;let r=[],o=t,n=0;for(;o&&o!==document.documentElement&&n<5;){let i=o.tagName.toLowerCase();if(o.id){r.unshift(`#${o.id}`);break}let a=Array.from(o.classList).slice(0,2);a.length>0&&(i+="."+a.join("."));let l=o.parentElement;if(l){let s=o.tagName,p=Array.from(l.children).filter(u=>u.tagName===s);if(p.length>1){let u=p.indexOf(o)+1;i+=`:nth-child(${u})`}}r.unshift(i),o=l,n++}return r.join(" > ")}var C=class{constructor(e,r){this.eventBus=e;this.name="click";this.handler=null;this.clicks=new m(r)}setup(){this.handler=e=>{let r=e.target;if(!r)return;let o={timestamp:new Date().toISOString(),selector:F(r),tagName:r.tagName.toLowerCase(),text:(r.textContent||"").trim().slice(0,100),position:{x:e.clientX,y:e.clientY}};this.clicks.push(o),this.eventBus.emit("click:captured",o),this.eventBus.emit("breadcrumb:added",{category:"click",message:`Clicked ${o.tagName} "${o.text}"`,data:{selector:o.selector}})},document.addEventListener("click",this.handler,!0)}getClickTrail(){return this.clicks.toArray()}teardown(){this.handler&&(document.removeEventListener("click",this.handler,!0),this.handler=null),this.clicks.clear()}};var S=class{constructor(e){this.getMeta=e;this.name="context"}setup(){}teardown(){}snapshot(){let e=this.getMeta?.();return{url:window.location.href,referrer:document.referrer,userAgent:navigator.userAgent,language:navigator.language,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},devicePixelRatio:window.devicePixelRatio||1,timestamp:new Date().toISOString(),memory:performance.memory?{usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize}:void 0,user:e?.user,tags:e?.tags}}};var B=class{constructor(e){this.eventBus=e;this.name="interactions";this.handlers=[];this.scrollTimer=null;this.resizeTimer=null}setup(){this.addHandler(window,"scroll",this.onScroll.bind(this),{passive:!0,capture:!0}),this.addHandler(document,"input",this.onInput.bind(this),!0),this.addHandler(document,"change",this.onChange.bind(this),!0),this.addHandler(window,"popstate",this.onPopState.bind(this)),this.addHandler(window,"hashchange",this.onHashChange.bind(this)),this.addHandler(document,"visibilitychange",this.onVisibilityChange.bind(this)),this.addHandler(window,"resize",this.onResize.bind(this),{passive:!0})}addHandler(e,r,o,n){e.addEventListener(r,o,n),this.handlers.push({target:e,event:r,handler:o})}onScroll(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Scrolled",data:{x:window.scrollX,y:window.scrollY}})},300)}onInput(e){let r=e.target;if(!r)return;let o=r.tagName.toLowerCase(),n=r.id?`#${r.id}`:"",i=r.type?`[type="${r.type}"]`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Input on ${o}${n}${i}`})}onChange(e){let r=e.target;if(!r)return;let o=r.tagName.toLowerCase(),n=r.id?`#${r.id}`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Change on ${o}${n}`})}onPopState(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Navigated to ${window.location.href}`})}onHashChange(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Hash changed to ${window.location.hash}`})}onVisibilityChange(){this.eventBus.emit("breadcrumb:added",{category:"visibility",message:document.hidden?"Tab hidden":"Tab visible"})}onResize(){this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Window resized",data:{width:window.innerWidth,height:window.innerHeight}})},300)}teardown(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.resizeTimer&&clearTimeout(this.resizeTimer),this.handlers.forEach(({target:e,event:r,handler:o})=>{e.removeEventListener(r,o)}),this.handlers=[]}};var R=class{constructor(e){this.eventBus=e;this.name="performance";this.observers=[]}setup(){typeof PerformanceObserver>"u"||(this.observe("longtask",e=>{e.forEach(r=>{if(r.duration<50)return;let o={kind:"performance",metric:"longtask",value:Math.round(r.duration),entries:[{name:r.name,duration:r.duration,startTime:r.startTime}]};this.eventBus.emit("performance:captured",o),this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Long task: ${Math.round(r.duration)}ms`})})}),this.observe("largest-contentful-paint",e=>{let r=e[e.length-1];r&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`LCP: ${Math.round(r.startTime)}ms`,data:{value:r.startTime}})}),this.observe("paint",e=>{e.forEach(r=>{r.name==="first-contentful-paint"&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`FCP: ${Math.round(r.startTime)}ms`,data:{value:r.startTime}})})}),this.observe("layout-shift",e=>{e.forEach(r=>{let o=r.value;o>.1&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Layout shift: ${o.toFixed(4)}`,data:{cls:o}})})}))}observe(e,r){try{let o=new PerformanceObserver(n=>{r(n.getEntries())});o.observe({type:e,buffered:!0}),this.observers.push(o)}catch{}}teardown(){this.observers.forEach(e=>e.disconnect()),this.observers=[]}};function D(){let t=performance.memory;return!t||typeof t.usedJSHeapSize!="number"?null:t}var T=class{constructor(e){this.eventBus=e;this.name="memory";this.intervalId=null;this.baselineUsed=null}setup(){let e=D();e&&(this.baselineUsed=e.usedJSHeapSize,this.intervalId=setInterval(()=>{let r=D();if(!r)return;let o=r.usedJSHeapSize/r.jsHeapSizeLimit,n=this.baselineUsed>0?(r.usedJSHeapSize-this.baselineUsed)/this.baselineUsed:0;this.eventBus.emit("breadcrumb:added",{category:"memory",message:`Heap: ${(o*100).toFixed(1)}% used (${(r.usedJSHeapSize/1048576).toFixed(1)}MB)`,data:{usedJSHeapSize:r.usedJSHeapSize,jsHeapSizeLimit:r.jsHeapSizeLimit}});let i=o>=.9,a=n>=.5;if(i||a){let s={kind:"memory",message:i?`Heap usage critical: ${(o*100).toFixed(1)}% of limit`:`Heap growth spike: ${(n*100).toFixed(1)}% since init`,usedJSHeapSize:r.usedJSHeapSize,totalJSHeapSize:r.totalJSHeapSize,jsHeapSizeLimit:r.jsHeapSizeLimit,heapUsagePercent:o,heapGrowthPercent:n};this.eventBus.emit("memory:captured",s)}},1e4))}teardown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.baselineUsed=null}};var J=`
:host {

@@ -165,16 +165,63 @@ all: initial;

.gb-report-item {
padding: 10px 16px;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
transition: background 0.15s;
}
.gb-report-item:hover {
.gb-report-item:last-child {
border-bottom: none;
}
.gb-report-summary {
padding: 10px 16px;
cursor: pointer;
}
.gb-report-summary:hover {
background: #f8f9fa;
}
.gb-report-item:last-child {
border-bottom: none;
.gb-report-detail {
display: none;
padding: 0 16px 12px;
border-top: 1px dashed #e8e8e8;
}
.gb-report-item.gb-expanded .gb-report-detail {
display: block;
}
.gb-detail-section {
margin-top: 8px;
}
.gb-detail-label {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #999;
margin-bottom: 2px;
}
.gb-detail-value {
font-size: 12px;
color: #555;
word-break: break-word;
line-height: 1.4;
}
.gb-detail-pre {
font-size: 11px;
font-family: 'SF Mono', Menlo, Monaco, monospace;
background: #f5f5f5;
padding: 8px;
border-radius: 6px;
overflow-x: auto;
max-height: 120px;
overflow-y: auto;
color: #333;
white-space: pre-wrap;
word-break: break-word;
}
.gb-report-type {

@@ -257,4 +304,5 @@ display: inline-block;

}
`;var ce='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></svg>';function G(){let r=document.createElement("button");r.className="gb-fab",r.setAttribute("aria-label","ghostbug - bug reports");let e=document.createElement("span");e.innerHTML=ce,r.appendChild(e);let t=document.createElement("span");return t.className="gb-badge",t.setAttribute("data-count","0"),t.textContent="0",r.appendChild(t),r}function X(r){let e=document.createElement("div");e.className=`gb-panel gb-pos-${r}`;let t=document.createElement("div");t.className="gb-header";let o=document.createElement("span");o.className="gb-header-title",o.textContent="ghostbug",t.appendChild(o);let n=document.createElement("button");n.className="gb-header-btn gb-copy-btn",n.textContent="Copy MD",t.appendChild(n);let i=document.createElement("button");i.className="gb-header-btn gb-download-btn",i.textContent="Export",t.appendChild(i);let s=document.createElement("button");s.className="gb-close-btn",s.textContent="\xD7",s.setAttribute("aria-label","Close"),t.appendChild(s),e.appendChild(t);let l=document.createElement("div");l.className="gb-report-list";let a=document.createElement("div");return a.className="gb-empty",a.textContent="No bugs captured yet.",l.appendChild(a),e.appendChild(l),e}function q(r){let e=document.createElement("div");e.className="gb-report-item";let t=document.createElement("span");if(t.className=`gb-report-type gb-type-${r.payload.kind==="error"?"error":r.payload.kind}`,t.textContent=r.type,e.appendChild(t),r.count>1){let s=document.createElement("span");s.className="gb-report-count",s.textContent=`\xD7${r.count}`,e.appendChild(s)}let o=document.createElement("div");o.className="gb-report-message",o.textContent=de(r),e.appendChild(o);let n=document.createElement("div");n.className="gb-report-meta";let i=r.timestamp.split("T")[1]?.split(".")[0]||r.timestamp;return n.textContent=`${i} \xB7 ${r.context.url}`,e.appendChild(n),e}function de(r){switch(r.payload.kind){case"error":return r.payload.message;case"console":return r.payload.args.join(", ");case"network":return`${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case"performance":return`${r.payload.metric}: ${r.payload.value}ms`;case"memory":return r.payload.message}}function T(r){return g({generator:"ghostbug",version:f,exportedAt:new Date().toISOString(),reportCount:r.length,reports:r},2)}function L(r){let e=[];return e.push(`# Bug Report \u2014 ghostbug v${f}`),e.push(`**Generated:** ${new Date().toISOString()}`),e.push(`**Reports:** ${r.length}`),e.push(""),e.push("---"),e.push(""),r.forEach((t,o)=>{e.push(`## ${o+1}. ${pe(t)}`),e.push(""),e.push(`- **Type:** ${t.type}`),e.push(`- **Time:** ${t.timestamp}`),e.push(`- **Occurrences:** ${t.count}`),e.push(`- **URL:** ${t.context.url}`),e.push(`- **Browser:** ${me(t.context.userAgent)}`),e.push(`- **Viewport:** ${t.context.viewport.width}x${t.context.viewport.height}`),e.push(""),e.push(...ue(t.payload)),e.push(""),t.breadcrumbs.length>0&&(e.push("### Breadcrumbs"),e.push(""),e.push("| Time | Category | Event |"),e.push("|------|----------|-------|"),t.breadcrumbs.forEach(n=>{let i=n.timestamp.split("T")[1]?.split(".")[0]||n.timestamp;e.push(`| ${i} | ${n.category} | ${n.message} |`)}),e.push("")),e.push("---"),e.push("")}),e.join(`
`)}function pe(r){switch(r.payload.kind){case"error":return`${r.payload.name||"Error"}: ${r.payload.message}`;case"console":return`Console ${r.payload.level}: ${r.payload.args[0]||""}`;case"network":return`${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case"performance":return`Performance: ${r.payload.metric} ${r.payload.value}ms`;case"memory":return`Memory: ${r.payload.message}`}}function ue(r){let e=[];switch(r.kind){case"error":r.stack&&(e.push("### Stack Trace"),e.push(""),e.push("```"),e.push(r.stack),e.push("```")),r.filename&&e.push(`**File:** ${r.filename}:${r.lineno}:${r.colno}`);break;case"console":e.push("### Console Output"),e.push(""),e.push("```"),r.args.forEach(t=>e.push(t)),e.push("```");break;case"network":e.push("### Network Details"),e.push(""),e.push(`- **Method:** ${r.method}`),e.push(`- **URL:** ${r.url}`),e.push(`- **Status:** ${r.status} ${r.statusText}`),e.push(`- **Duration:** ${r.duration}ms`);break;case"performance":e.push("### Performance Details"),e.push(""),e.push(`- **Metric:** ${r.metric}`),e.push(`- **Value:** ${r.value}ms`),r.entries.length>0&&e.push(`- **Start Time:** ${Math.round(r.entries[0].startTime)}ms`);break;case"memory":e.push("### Memory Details"),e.push(""),e.push(`- **Used:** ${(r.usedJSHeapSize/1048576).toFixed(1)}MB`),e.push(`- **Limit:** ${(r.jsHeapSizeLimit/1048576).toFixed(1)}MB`),e.push(`- **Usage:** ${(r.heapUsagePercent*100).toFixed(1)}%`),e.push(`- **Growth since init:** ${(r.heapGrowthPercent*100).toFixed(1)}%`);break}return e}function me(r){if(r.includes("Chrome")){let e=r.match(/Chrome\/(\d+)/);return e?`Chrome ${e[1]}`:"Chrome"}if(r.includes("Firefox")){let e=r.match(/Firefox\/(\d+)/);return e?`Firefox ${e[1]}`:"Firefox"}if(r.includes("Safari")&&!r.includes("Chrome")){let e=r.match(/Version\/(\d+)/);return e?`Safari ${e[1]}`:"Safari"}return r.slice(0,50)}var P=class{constructor(e,t,o){this.eventBus=e;this.reportManager=t;this.options=o;this.hostElement=null;this.shadowRoot=null;this.panel=null;this.badge=null;this.reportList=null;this.isExpanded=!1;this.unsubscribers=[]}mount(){this.hostElement=document.createElement("div"),this.hostElement.id="ghostbug-widget";let e=this.hostElement.style;e.position="fixed",e.zIndex=String(this.options.zIndex),e.margin="0",e.padding="0",this.applyPosition(e),this.shadowRoot=this.hostElement.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=D,this.shadowRoot.appendChild(t);let o=document.createElement("div");o.className="gb-container";let n=G();this.badge=n.querySelector(".gb-badge"),n.addEventListener("click",()=>this.toggle()),o.appendChild(n),this.panel=X(this.options.position),o.appendChild(this.panel),this.panel.querySelector(".gb-close-btn")?.addEventListener("click",()=>this.toggle()),this.panel.querySelector(".gb-copy-btn")?.addEventListener("click",()=>this.copyMarkdown()),this.panel.querySelector(".gb-download-btn")?.addEventListener("click",()=>this.downloadJSON()),this.reportList=this.panel.querySelector(".gb-report-list"),this.shadowRoot.appendChild(o),document.body.appendChild(this.hostElement),this.unsubscribers.push(this.eventBus.on("report:created",()=>this.update()),this.eventBus.on("report:deduplicated",()=>this.update())),this.options.collapsed||this.toggle()}applyPosition(e){let t=this.options.position;e.top=t.startsWith("top")?"16px":"auto",e.bottom=t.startsWith("bottom")?"16px":"auto",e.left=t.endsWith("left")?"16px":"auto",e.right=t.endsWith("right")?"16px":"auto"}toggle(){this.isExpanded=!this.isExpanded,this.isExpanded?(this.panel?.classList.add("gb-open"),this.renderReportList()):this.panel?.classList.remove("gb-open")}update(){this.updateBadge(),this.isExpanded&&this.renderReportList()}updateBadge(){if(!this.badge)return;let e=this.reportManager.reportCount;this.badge.textContent=String(e),this.badge.setAttribute("data-count",String(e))}renderReportList(){if(!this.reportList)return;this.reportList.textContent="";let e=this.reportManager.getReports();if(e.length===0){let o=document.createElement("div");o.className="gb-empty",o.textContent="No bugs captured yet.",this.reportList.appendChild(o);return}[...e].reverse().forEach(o=>{let n=q(o);this.reportList.appendChild(n)})}copyMarkdown(){let e=L(this.reportManager.getReports());navigator.clipboard.writeText(e).then(()=>this.showToast("Copied to clipboard!"),()=>this.showToast("Copy failed"))}downloadJSON(){let e=T(this.reportManager.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download="ghostbug-report.json",n.click(),URL.revokeObjectURL(o)}showToast(e){if(!this.shadowRoot)return;let t=document.createElement("div");t.className="gb-toast",t.textContent=e,this.shadowRoot.appendChild(t),requestAnimationFrame(()=>{t.classList.add("gb-show")}),setTimeout(()=>{t.classList.remove("gb-show"),setTimeout(()=>t.remove(),300)},2e3)}unmount(){this.unsubscribers.forEach(e=>e()),this.unsubscribers=[],this.hostElement?.remove(),this.hostElement=null,this.shadowRoot=null,this.panel=null,this.badge=null,this.reportList=null}};var c=null,h=null,d=[],H=null,$=new Set,M=!1,N,O;function he(r,e){return e?{maxReports:e.maxReports??r.maxReports,maxBreadcrumbs:e.maxBreadcrumbs??r.maxBreadcrumbs,maxClicks:e.maxClicks??r.maxClicks,widget:e.widget??r.widget,collectors:{...r.collectors,...e.collectors},rateLimit:{...r.rateLimit,...e.rateLimit},beforeReport:e.beforeReport??r.beforeReport,debug:e.debug??r.debug,screenshotFn:e.screenshotFn}:{...r}}function W(r){if(M){r?.debug&&console.warn("[ghostbug] Already initialized. Call destroy() first.");return}let e=he(I,r);c=new b;let t=new C(()=>({user:N,tags:O}));if(h=new y(c,t,e),e.collectors.errors&&d.push(new w(c)),e.collectors.console&&d.push(new x(c)),e.collectors.network&&d.push(new E(c)),e.collectors.clicks&&d.push(new k(c,e.maxClicks)),e.collectors.interactions&&d.push(new S(c)),e.collectors.performance&&d.push(new B(c)),e.collectors.memory&&d.push(new R(c)),d.push(t),d.forEach(o=>o.setup()),c.on("report:created",o=>{$.forEach(n=>{try{n(o)}catch{}})}),e.widget){let o=typeof e.widget=="object"?{position:e.widget.position||"bottom-right",collapsed:e.widget.collapsed??!0,zIndex:e.widget.zIndex??2147483647}:{position:"bottom-right",collapsed:!0,zIndex:2147483647};H=new P(c,h,o),H.mount()}M=!0}function J(){return _(),h.getReports()}function V(r="ghostbug-report.json"){_();let e=T(h.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download=r,n.click(),URL.revokeObjectURL(o)}function Y(){return _(),L(h.getReports())}function K(r){return $.add(r),()=>$.delete(r)}function Q(r){N=r}function Z(r){O={...O,...r}}function ee(){H?.unmount(),H=null,d.forEach(r=>r.teardown()),d=[],c?.clear(),c=null,h?.clear(),h=null,$.clear(),N=void 0,O=void 0,M=!1}function _(){if(!M)throw new Error("[ghostbug] Not initialized. Call ghostbug.init() first.")}var ge={init:W,getReports:J,download:V,toMarkdown:Y,onBug:K,setUser:Q,setTags:Z,destroy:ee};return se(fe);})();
`;var de='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></svg>';function G(){let t=document.createElement("button");t.className="gb-fab",t.setAttribute("aria-label","ghostbug - bug reports");let e=document.createElement("span");e.innerHTML=de,t.appendChild(e);let r=document.createElement("span");return r.className="gb-badge",r.setAttribute("data-count","0"),r.textContent="0",t.appendChild(r),t}function q(t){let e=document.createElement("div");e.className=`gb-panel gb-pos-${t}`;let r=document.createElement("div");r.className="gb-header";let o=document.createElement("span");o.className="gb-header-title",o.textContent="ghostbug",r.appendChild(o);let n=document.createElement("button");n.className="gb-header-btn gb-copy-btn",n.textContent="Copy MD",r.appendChild(n);let i=document.createElement("button");i.className="gb-header-btn gb-download-btn",i.textContent="Export",r.appendChild(i);let a=document.createElement("button");a.className="gb-close-btn",a.textContent="\xD7",a.setAttribute("aria-label","Close"),r.appendChild(a),e.appendChild(r);let l=document.createElement("div");l.className="gb-report-list";let s=document.createElement("div");return s.className="gb-empty",s.textContent="No bugs captured yet.",l.appendChild(s),e.appendChild(l),e}function X(t){let e=document.createElement("div");e.className="gb-report-item";let r=document.createElement("div");r.className="gb-report-summary";let o=document.createElement("span");if(o.className=`gb-report-type gb-type-${t.payload.kind==="error"?"error":t.payload.kind}`,o.textContent=t.type,r.appendChild(o),t.count>1){let s=document.createElement("span");s.className="gb-report-count",s.textContent=`\xD7${t.count}`,r.appendChild(s)}let n=document.createElement("div");n.className="gb-report-message",n.textContent=pe(t),r.appendChild(n);let i=document.createElement("div");i.className="gb-report-meta";let a=t.timestamp.split("T")[1]?.split(".")[0]||t.timestamp;i.textContent=`${a} \xB7 ${t.context.url}`,r.appendChild(i),e.appendChild(r);let l=document.createElement("div");if(l.className="gb-report-detail",l.appendChild(ce(t.payload)),t.context.user){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">User</div><div class="gb-detail-value">${g(JSON.stringify(t.context.user))}</div>`,l.appendChild(s)}if(t.context.tags){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">Tags</div><div class="gb-detail-value">${g(JSON.stringify(t.context.tags))}</div>`,l.appendChild(s)}if(t.breadcrumbs.length>0){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">Breadcrumbs</div><div class="gb-detail-value">${t.breadcrumbs.length} events</div>`,l.appendChild(s)}return e.appendChild(l),r.addEventListener("click",()=>{e.classList.toggle("gb-expanded")}),e}function g(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function ce(t){let e=document.createElement("div");switch(e.className="gb-detail-section",t.kind){case"error":{if(t.stack){let r=document.createElement("div");r.className="gb-detail-label",r.textContent="Stack Trace",e.appendChild(r);let o=document.createElement("pre");o.className="gb-detail-pre",o.textContent=t.stack,e.appendChild(o)}if(t.filename){let r=document.createElement("div");r.className="gb-detail-value",r.textContent=`${t.filename}:${t.lineno}:${t.colno}`,e.appendChild(r)}break}case"console":{let r=document.createElement("div");r.className="gb-detail-label",r.textContent="Output",e.appendChild(r);let o=document.createElement("pre");o.className="gb-detail-pre",o.textContent=t.args.join(`
`),e.appendChild(o);break}case"network":{e.innerHTML=`<div class="gb-detail-label">Request</div><div class="gb-detail-value">${g(t.method)} ${g(t.url)}<br>Status: ${t.status} ${g(t.statusText)}<br>Duration: ${t.duration}ms</div>`;break}case"performance":{e.innerHTML=`<div class="gb-detail-label">Performance</div><div class="gb-detail-value">Metric: ${g(t.metric)}<br>Value: ${t.value}ms</div>`;break}case"memory":{e.innerHTML=`<div class="gb-detail-label">Memory</div><div class="gb-detail-value">Used: ${(t.usedJSHeapSize/1048576).toFixed(1)}MB<br>Limit: ${(t.jsHeapSizeLimit/1048576).toFixed(1)}MB<br>Usage: ${(t.heapUsagePercent*100).toFixed(1)}%</div>`;break}}return e}function pe(t){switch(t.payload.kind){case"error":return t.payload.message;case"console":return t.payload.args.join(", ");case"network":return`${t.payload.method} ${t.payload.url} \u2192 ${t.payload.status}`;case"performance":return`${t.payload.metric}: ${t.payload.value}ms`;case"memory":return t.payload.message}}function L(t){return f({generator:"ghostbug",version:b,exportedAt:new Date().toISOString(),reportCount:t.length,reports:t},2)}function P(t){let e=[];return e.push(`# Bug Report \u2014 ghostbug v${b}`),e.push(`**Generated:** ${new Date().toISOString()}`),e.push(`**Reports:** ${t.length}`),e.push(""),e.push("---"),e.push(""),t.forEach((r,o)=>{e.push(`## ${o+1}. ${ue(r)}`),e.push(""),e.push(`- **Type:** ${r.type}`),e.push(`- **Time:** ${r.timestamp}`),e.push(`- **Occurrences:** ${r.count}`),e.push(`- **URL:** ${r.context.url}`),e.push(`- **Browser:** ${he(r.context.userAgent)}`),e.push(`- **Viewport:** ${r.context.viewport.width}x${r.context.viewport.height}`),e.push(""),e.push(...me(r.payload)),e.push(""),r.context.user&&(e.push("### User Context"),e.push(""),e.push("```json"),e.push(JSON.stringify(r.context.user,null,2)),e.push("```"),e.push("")),r.context.tags&&(e.push("### Tags"),e.push(""),e.push("```json"),e.push(JSON.stringify(r.context.tags,null,2)),e.push("```"),e.push("")),r.breadcrumbs.length>0&&(e.push("### Breadcrumbs"),e.push(""),e.push("| Time | Category | Event |"),e.push("|------|----------|-------|"),r.breadcrumbs.forEach(n=>{let i=n.timestamp.split("T")[1]?.split(".")[0]||n.timestamp;e.push(`| ${i} | ${n.category} | ${n.message} |`)}),e.push("")),e.push("---"),e.push("")}),e.join(`
`)}function ue(t){switch(t.payload.kind){case"error":return`${t.payload.name||"Error"}: ${t.payload.message}`;case"console":return`Console ${t.payload.level}: ${t.payload.args[0]||""}`;case"network":return`${t.payload.method} ${t.payload.url} \u2192 ${t.payload.status}`;case"performance":return`Performance: ${t.payload.metric} ${t.payload.value}ms`;case"memory":return`Memory: ${t.payload.message}`}}function me(t){let e=[];switch(t.kind){case"error":t.stack&&(e.push("### Stack Trace"),e.push(""),e.push("```"),e.push(t.stack),e.push("```")),t.filename&&e.push(`**File:** ${t.filename}:${t.lineno}:${t.colno}`);break;case"console":e.push("### Console Output"),e.push(""),e.push("```"),t.args.forEach(r=>e.push(r)),e.push("```");break;case"network":e.push("### Network Details"),e.push(""),e.push(`- **Method:** ${t.method}`),e.push(`- **URL:** ${t.url}`),e.push(`- **Status:** ${t.status} ${t.statusText}`),e.push(`- **Duration:** ${t.duration}ms`);break;case"performance":e.push("### Performance Details"),e.push(""),e.push(`- **Metric:** ${t.metric}`),e.push(`- **Value:** ${t.value}ms`),t.entries.length>0&&e.push(`- **Start Time:** ${Math.round(t.entries[0].startTime)}ms`);break;case"memory":e.push("### Memory Details"),e.push(""),e.push(`- **Used:** ${(t.usedJSHeapSize/1048576).toFixed(1)}MB`),e.push(`- **Limit:** ${(t.jsHeapSizeLimit/1048576).toFixed(1)}MB`),e.push(`- **Usage:** ${(t.heapUsagePercent*100).toFixed(1)}%`),e.push(`- **Growth since init:** ${(t.heapGrowthPercent*100).toFixed(1)}%`);break}return e}function he(t){if(t.includes("Chrome")){let e=t.match(/Chrome\/(\d+)/);return e?`Chrome ${e[1]}`:"Chrome"}if(t.includes("Firefox")){let e=t.match(/Firefox\/(\d+)/);return e?`Firefox ${e[1]}`:"Firefox"}if(t.includes("Safari")&&!t.includes("Chrome")){let e=t.match(/Version\/(\d+)/);return e?`Safari ${e[1]}`:"Safari"}return t.slice(0,50)}var $=class{constructor(e,r,o){this.eventBus=e;this.reportManager=r;this.options=o;this.hostElement=null;this.shadowRoot=null;this.panel=null;this.badge=null;this.reportList=null;this.isExpanded=!1;this.unsubscribers=[]}mount(){this.hostElement=document.createElement("div"),this.hostElement.id="ghostbug-widget";let e=this.hostElement.style;e.position="fixed",e.zIndex=String(this.options.zIndex),e.margin="0",e.padding="0",this.applyPosition(e),this.shadowRoot=this.hostElement.attachShadow({mode:"closed"});let r=document.createElement("style");r.textContent=J,this.shadowRoot.appendChild(r);let o=document.createElement("div");o.className="gb-container";let n=G();this.badge=n.querySelector(".gb-badge"),n.addEventListener("click",()=>this.toggle()),o.appendChild(n),this.panel=q(this.options.position),o.appendChild(this.panel),this.panel.querySelector(".gb-close-btn")?.addEventListener("click",()=>this.toggle()),this.panel.querySelector(".gb-copy-btn")?.addEventListener("click",()=>this.copyMarkdown()),this.panel.querySelector(".gb-download-btn")?.addEventListener("click",()=>this.downloadJSON()),this.reportList=this.panel.querySelector(".gb-report-list"),this.shadowRoot.appendChild(o),document.body.appendChild(this.hostElement),this.unsubscribers.push(this.eventBus.on("report:created",()=>this.update()),this.eventBus.on("report:deduplicated",()=>this.update())),this.options.collapsed||this.toggle()}applyPosition(e){let r=this.options.position;e.top=r.startsWith("top")?"16px":"auto",e.bottom=r.startsWith("bottom")?"16px":"auto",e.left=r.endsWith("left")?"16px":"auto",e.right=r.endsWith("right")?"16px":"auto"}toggle(){this.isExpanded=!this.isExpanded,this.isExpanded?(this.panel?.classList.add("gb-open"),this.renderReportList()):this.panel?.classList.remove("gb-open")}update(){this.updateBadge(),this.isExpanded&&this.renderReportList()}updateBadge(){if(!this.badge)return;let e=this.reportManager.reportCount;this.badge.textContent=String(e),this.badge.setAttribute("data-count",String(e))}renderReportList(){if(!this.reportList)return;this.reportList.textContent="";let e=this.reportManager.getReports();if(e.length===0){let o=document.createElement("div");o.className="gb-empty",o.textContent="No bugs captured yet.",this.reportList.appendChild(o);return}[...e].reverse().forEach(o=>{let n=X(o);this.reportList.appendChild(n)})}copyMarkdown(){let e=P(this.reportManager.getReports());navigator.clipboard.writeText(e).then(()=>this.showToast("Copied to clipboard!"),()=>this.showToast("Copy failed"))}downloadJSON(){let e=L(this.reportManager.getReports()),r=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(r),n=document.createElement("a");n.href=o,n.download="ghostbug-report.json",n.click(),URL.revokeObjectURL(o)}showToast(e){if(!this.shadowRoot)return;let r=document.createElement("div");r.className="gb-toast",r.textContent=e,this.shadowRoot.appendChild(r),requestAnimationFrame(()=>{r.classList.add("gb-show")}),setTimeout(()=>{r.classList.remove("gb-show"),setTimeout(()=>r.remove(),300)},2e3)}unmount(){this.unsubscribers.forEach(e=>e()),this.unsubscribers=[],this.hostElement?.remove(),this.hostElement=null,this.shadowRoot=null,this.panel=null,this.badge=null,this.reportList=null}};var d=null,h=null,c=[],H=null,M=new Set,O=!1,_,N;function ge(t,e){return e?{maxReports:e.maxReports??t.maxReports,maxBreadcrumbs:e.maxBreadcrumbs??t.maxBreadcrumbs,maxClicks:e.maxClicks??t.maxClicks,widget:e.widget??t.widget,collectors:{...t.collectors,...e.collectors},rateLimit:{...t.rateLimit,...e.rateLimit},beforeReport:e.beforeReport??t.beforeReport,debug:e.debug??t.debug}:{...t}}function W(t){if(O){t?.debug&&console.warn("[ghostbug] Already initialized. Call destroy() first.");return}let e=ge(A,t);d=new v;let r=new S(()=>({user:_,tags:N}));if(h=new w(d,r,e),e.collectors.errors&&c.push(new x(d)),e.collectors.console&&c.push(new E(d)),e.collectors.network&&c.push(new k(d)),e.collectors.clicks&&c.push(new C(d,e.maxClicks)),e.collectors.interactions&&c.push(new B(d)),e.collectors.performance&&c.push(new R(d)),e.collectors.memory&&c.push(new T(d)),c.push(r),c.forEach(o=>o.setup()),d.on("report:created",o=>{M.forEach(n=>{try{n(o)}catch{}})}),e.widget){let o=typeof e.widget=="object"?{position:e.widget.position||"bottom-right",collapsed:e.widget.collapsed??!0,zIndex:e.widget.zIndex??2147483647}:{position:"bottom-right",collapsed:!0,zIndex:2147483647};H=new $(d,h,o),H.mount()}O=!0}function V(){return I(),h.getReports()}function Y(t="ghostbug-report.json"){I();let e=L(h.getReports()),r=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(r),n=document.createElement("a");n.href=o,n.download=t,n.click(),URL.revokeObjectURL(o)}function K(){return I(),P(h.getReports())}function Q(t){return M.add(t),()=>M.delete(t)}function Z(t){_=t}function ee(t){N={...N,...t}}function te(){H?.unmount(),H=null,c.forEach(t=>t.teardown()),c=[],d?.clear(),d=null,h?.clear(),h=null,M.clear(),_=void 0,N=void 0,O=!1}function I(){if(!O)throw new Error("[ghostbug] Not initialized. Call ghostbug.init() first.")}var fe={init:W,getReports:V,download:Y,toMarkdown:K,onBug:Q,setUser:Z,setTags:ee,destroy:te};return ae(be);})();
//# sourceMappingURL=index.iife.js.map

@@ -1,3 +0,3 @@

var f="0.1.0",_={maxReports:50,maxBreadcrumbs:20,maxClicks:20,widget:false,collectors:{errors:true,console:true,network:true,clicks:true,interactions:true,performance:true,memory:true},rateLimit:{maxEvents:10,windowMs:1e3},beforeReport:r=>r,debug:false};var b=class{constructor(){this.listeners=new Map;}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t);}emit(e,t){this.listeners.get(e)?.forEach(o=>{try{o(t);}catch{}});}clear(){this.listeners.clear();}};var m=class{constructor(e){this.capacity=e;this.head=0;this._size=0;this.buffer=new Array(e);}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this._size<this.capacity&&this._size++;}toArray(){if(this._size===0)return [];let e=[],t=this._size<this.capacity?0:this.head;for(let o=0;o<this._size;o++){let n=(t+o)%this.capacity;e.push(this.buffer[n]);}return e}get size(){return this._size}get isFull(){return this._size===this.capacity}peek(){if(this._size===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}find(e){return this.toArray().find(e)}forEach(e){this.toArray().forEach(e);}clear(){this.buffer=new Array(this.capacity),this.head=0,this._size=0;}};var v=class{constructor(e,t){this.maxEvents=e;this.windowMs=t;this.timestamps=[];}allow(){let e=Date.now();return this.timestamps=this.timestamps.filter(t=>e-t<this.windowMs),this.timestamps.length>=this.maxEvents?false:(this.timestamps.push(e),true)}reset(){this.timestamps=[];}};function q(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e+r.charCodeAt(t)&4294967295;return (e>>>0).toString(36)}function I(r){let e;switch(r.kind){case "error":{let t=r.stack?.split(`
`)[1]?.trim()||"";e=`${r.name}:${r.message}:${t}`;break}case "console":e=`console:${r.level}:${r.args.join(",")}`;break;case "network":e=`network:${r.method}:${r.url}:${r.status}`;break;case "performance":e=`performance:${r.metric}:${Math.floor(r.value/100)*100}`;break;case "memory":e=`memory:${Math.floor(r.heapUsagePercent*10)/10}`;break}return q(e)}function A(){let r=new Uint8Array(8);return crypto.getRandomValues(r),Array.from(r,e=>e.toString(36).padStart(2,"0")).join("").slice(0,12)}var W=3e3,y=class{constructor(e,t,o){this.eventBus=e;this.contextCollector=t;this.options=o;this.unsubscribers=[];this.reports=new m(o.maxReports),this.breadcrumbs=new m(o.maxBreadcrumbs),this.rateLimiter=new v(o.rateLimit.maxEvents,o.rateLimit.windowMs),this.subscribe();}subscribe(){this.unsubscribers.push(this.eventBus.on("error:captured",e=>{this.addBreadcrumb({category:"error",message:e.message}),this.handleCapturedEvent("error",e);}),this.eventBus.on("console:captured",e=>{this.addBreadcrumb({category:"console",message:`console.${e.level}: ${e.args.join(", ")}`}),e.level==="error"&&this.handleCapturedEvent("console",e);}),this.eventBus.on("network:captured",e=>{this.handleCapturedEvent("network",e);}),this.eventBus.on("performance:captured",e=>{this.addBreadcrumb({category:"performance",message:`${e.metric}: ${e.value}ms`}),this.handleCapturedEvent("performance",e);}),this.eventBus.on("memory:captured",e=>{this.handleCapturedEvent("memory",e);}),this.eventBus.on("breadcrumb:added",e=>{this.addBreadcrumb(e);}));}async handleCapturedEvent(e,t){if(!this.rateLimiter.allow())return;let o=I(t),n=this.reports.find(l=>l.fingerprint===o);if(n){n.count++,n.timestamp=new Date().toISOString(),this.eventBus.emit("report:deduplicated",n);return}let i={id:A(),fingerprint:o,type:e,timestamp:new Date().toISOString(),count:1,payload:t,breadcrumbs:this.breadcrumbs.toArray(),context:this.contextCollector.snapshot()};if(this.options.screenshotFn)try{i.screenshot=await Promise.race([this.options.screenshotFn(),new Promise((l,a)=>setTimeout(()=>a(new Error("screenshot timeout")),W))]);}catch{}let s=this.options.beforeReport(i);s&&(i=s,this.reports.push(i),this.eventBus.emit("report:created",i));}addBreadcrumb(e){this.breadcrumbs.push({...e,timestamp:new Date().toISOString()});}getReports(){return this.reports.toArray()}clear(){this.reports.clear(),this.breadcrumbs.clear(),this.unsubscribers.forEach(e=>e()),this.unsubscribers=[];}get reportCount(){return this.reports.size}};var w=class{constructor(e){this.eventBus=e;this.name="error";this.originalOnError=null;this.rejectionHandler=null;}setup(){this.originalOnError=window.onerror,window.onerror=(e,t,o,n,i)=>{let s={kind:"error",message:String(e),stack:i?.stack,filename:t??void 0,lineno:o??void 0,colno:n??void 0,name:i?.name};return this.eventBus.emit("error:captured",s),this.originalOnError?this.originalOnError.call(window,e,t,o,n,i):false},this.rejectionHandler=e=>{let t=e.reason,o={kind:"error",message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,name:t instanceof Error?t.name:"UnhandledRejection"};this.eventBus.emit("error:captured",o);},window.addEventListener("unhandledrejection",this.rejectionHandler);}teardown(){window.onerror=this.originalOnError,this.originalOnError=null,this.rejectionHandler&&(window.removeEventListener("unhandledrejection",this.rejectionHandler),this.rejectionHandler=null);}};function g(r,e){let t=new WeakSet;return JSON.stringify(r,(o,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return "[Circular]";t.add(n);}return typeof n=="function"?"[Function]":typeof n=="symbol"?n.toString():n instanceof Error?{name:n.name,message:n.message,stack:n.stack}:n},e)}var x=class{constructor(e){this.eventBus=e;this.name="console";this.originalError=null;this.originalWarn=null;}setup(){this.originalError=console.error,this.originalWarn=console.warn,console.error=(...e)=>{let t={kind:"console",level:"error",args:e.map(o=>g(o))};this.eventBus.emit("console:captured",t),this.originalError.apply(console,e);},console.warn=(...e)=>{let t={kind:"console",level:"warn",args:e.map(o=>g(o))};this.eventBus.emit("console:captured",t),this.originalWarn.apply(console,e);};}teardown(){this.originalError&&(console.error=this.originalError),this.originalWarn&&(console.warn=this.originalWarn),this.originalError=null,this.originalWarn=null;}};var E=class{constructor(e){this.eventBus=e;this.name="network";this.originalFetch=null;this.originalXhrOpen=null;this.originalXhrSend=null;}setup(){this.patchFetch(),this.patchXHR();}patchFetch(){this.originalFetch=window.fetch;let e=this.eventBus,t=this.originalFetch;window.fetch=function(o,n){let i=n?.method?.toUpperCase()||"GET",s=typeof o=="string"?o:o instanceof URL?o.href:o.url,l=performance.now();return t.call(window,o,n).then(a=>{let p=Math.round(performance.now()-l);if(a.status>=400){let u={kind:"network",method:i,url:s,status:a.status,statusText:a.statusText,duration:p};e.emit("network:captured",u);}return e.emit("breadcrumb:added",{category:"network",message:`${i} ${s} -> ${a.status}`}),a},a=>{let p=Math.round(performance.now()-l),u={kind:"network",method:i,url:s,status:0,statusText:a.message||"Network Error",duration:p};throw e.emit("network:captured",u),a})};}patchXHR(){this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let e=this.eventBus,t=this.originalXhrOpen,o=this.originalXhrSend;XMLHttpRequest.prototype.open=function(n,i,...s){return this.__ghostbug_method=n.toUpperCase(),this.__ghostbug_url=String(i),t.apply(this,[n,i,...s])},XMLHttpRequest.prototype.send=function(n){let i=performance.now(),s=this;return s.addEventListener("loadend",function(){let l=Math.round(performance.now()-i),a=s.__ghostbug_method||"UNKNOWN",p=s.__ghostbug_url||"";if(s.status>=400||s.status===0){let u={kind:"network",method:a,url:p,status:s.status,statusText:s.statusText,duration:l};e.emit("network:captured",u);}e.emit("breadcrumb:added",{category:"network",message:`${a} ${p} -> ${s.status}`});}),o.call(this,n)};}teardown(){this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null);}};function F(r){if(r.id)return `#${r.id}`;let e=r.getAttribute("data-testid");if(e)return `[data-testid="${e}"]`;let t=[],o=r,n=0;for(;o&&o!==document.documentElement&&n<5;){let i=o.tagName.toLowerCase();if(o.id){t.unshift(`#${o.id}`);break}let s=Array.from(o.classList).slice(0,2);s.length>0&&(i+="."+s.join("."));let l=o.parentElement;if(l){let a=o.tagName,p=Array.from(l.children).filter(u=>u.tagName===a);if(p.length>1){let u=p.indexOf(o)+1;i+=`:nth-child(${u})`;}}t.unshift(i),o=l,n++;}return t.join(" > ")}var k=class{constructor(e,t){this.eventBus=e;this.name="click";this.handler=null;this.clicks=new m(t);}setup(){this.handler=e=>{let t=e.target;if(!t)return;let o={timestamp:new Date().toISOString(),selector:F(t),tagName:t.tagName.toLowerCase(),text:(t.textContent||"").trim().slice(0,100),position:{x:e.clientX,y:e.clientY}};this.clicks.push(o),this.eventBus.emit("click:captured",o),this.eventBus.emit("breadcrumb:added",{category:"click",message:`Clicked ${o.tagName} "${o.text}"`,data:{selector:o.selector}});},document.addEventListener("click",this.handler,true);}getClickTrail(){return this.clicks.toArray()}teardown(){this.handler&&(document.removeEventListener("click",this.handler,true),this.handler=null),this.clicks.clear();}};var C=class{constructor(e){this.getMeta=e;this.name="context";}setup(){}teardown(){}snapshot(){let e=this.getMeta?.();return {url:window.location.href,referrer:document.referrer,userAgent:navigator.userAgent,language:navigator.language,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},devicePixelRatio:window.devicePixelRatio||1,timestamp:new Date().toISOString(),memory:performance.memory?{usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize}:void 0,user:e?.user,tags:e?.tags}}};var S=class{constructor(e){this.eventBus=e;this.name="interactions";this.handlers=[];this.scrollTimer=null;this.resizeTimer=null;}setup(){this.addHandler(window,"scroll",this.onScroll.bind(this),{passive:true,capture:true}),this.addHandler(document,"input",this.onInput.bind(this),true),this.addHandler(document,"change",this.onChange.bind(this),true),this.addHandler(window,"popstate",this.onPopState.bind(this)),this.addHandler(window,"hashchange",this.onHashChange.bind(this)),this.addHandler(document,"visibilitychange",this.onVisibilityChange.bind(this)),this.addHandler(window,"resize",this.onResize.bind(this),{passive:true});}addHandler(e,t,o,n){e.addEventListener(t,o,n),this.handlers.push({target:e,event:t,handler:o});}onScroll(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Scrolled",data:{x:window.scrollX,y:window.scrollY}});},300);}onInput(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"",i=t.type?`[type="${t.type}"]`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Input on ${o}${n}${i}`});}onChange(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Change on ${o}${n}`});}onPopState(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Navigated to ${window.location.href}`});}onHashChange(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Hash changed to ${window.location.hash}`});}onVisibilityChange(){this.eventBus.emit("breadcrumb:added",{category:"visibility",message:document.hidden?"Tab hidden":"Tab visible"});}onResize(){this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Window resized",data:{width:window.innerWidth,height:window.innerHeight}});},300);}teardown(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.resizeTimer&&clearTimeout(this.resizeTimer),this.handlers.forEach(({target:e,event:t,handler:o})=>{e.removeEventListener(t,o);}),this.handlers=[];}};var B=class{constructor(e){this.eventBus=e;this.name="performance";this.observers=[];}setup(){typeof PerformanceObserver>"u"||(this.observe("longtask",e=>{e.forEach(t=>{if(t.duration<50)return;let o={kind:"performance",metric:"longtask",value:Math.round(t.duration),entries:[{name:t.name,duration:t.duration,startTime:t.startTime}]};this.eventBus.emit("performance:captured",o),this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Long task: ${Math.round(t.duration)}ms`});});}),this.observe("largest-contentful-paint",e=>{let t=e[e.length-1];t&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`LCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});}),this.observe("paint",e=>{e.forEach(t=>{t.name==="first-contentful-paint"&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`FCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});});}),this.observe("layout-shift",e=>{e.forEach(t=>{let o=t.value;o>.1&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Layout shift: ${o.toFixed(4)}`,data:{cls:o}});});}));}observe(e,t){try{let o=new PerformanceObserver(n=>{t(n.getEntries());});o.observe({type:e,buffered:!0}),this.observers.push(o);}catch{}}teardown(){this.observers.forEach(e=>e.disconnect()),this.observers=[];}};function j(){let r=performance.memory;return !r||typeof r.usedJSHeapSize!="number"?null:r}var R=class{constructor(e){this.eventBus=e;this.name="memory";this.intervalId=null;this.baselineUsed=null;}setup(){let e=j();e&&(this.baselineUsed=e.usedJSHeapSize,this.intervalId=setInterval(()=>{let t=j();if(!t)return;let o=t.usedJSHeapSize/t.jsHeapSizeLimit,n=this.baselineUsed>0?(t.usedJSHeapSize-this.baselineUsed)/this.baselineUsed:0;this.eventBus.emit("breadcrumb:added",{category:"memory",message:`Heap: ${(o*100).toFixed(1)}% used (${(t.usedJSHeapSize/1048576).toFixed(1)}MB)`,data:{usedJSHeapSize:t.usedJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit}});let i=o>=.9,s=n>=.5;if(i||s){let a={kind:"memory",message:i?`Heap usage critical: ${(o*100).toFixed(1)}% of limit`:`Heap growth spike: ${(n*100).toFixed(1)}% since init`,usedJSHeapSize:t.usedJSHeapSize,totalJSHeapSize:t.totalJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit,heapUsagePercent:o,heapGrowthPercent:n};this.eventBus.emit("memory:captured",a);}},1e4));}teardown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.baselineUsed=null;}};var U=`
var b="0.1.0",I={maxReports:50,maxBreadcrumbs:20,maxClicks:20,widget:false,collectors:{errors:true,console:true,network:true,clicks:true,interactions:true,performance:true,memory:true},rateLimit:{maxEvents:10,windowMs:1e3},beforeReport:r=>r,debug:false};var v=class{constructor(){this.listeners=new Map;}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t);}emit(e,t){this.listeners.get(e)?.forEach(o=>{try{o(t);}catch{}});}clear(){this.listeners.clear();}};var m=class{constructor(e){this.capacity=e;this.head=0;this._size=0;this.buffer=new Array(e);}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this._size<this.capacity&&this._size++;}toArray(){if(this._size===0)return [];let e=[],t=this._size<this.capacity?0:this.head;for(let o=0;o<this._size;o++){let n=(t+o)%this.capacity;e.push(this.buffer[n]);}return e}get size(){return this._size}get isFull(){return this._size===this.capacity}peek(){if(this._size===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}find(e){return this.toArray().find(e)}forEach(e){this.toArray().forEach(e);}clear(){this.buffer=new Array(this.capacity),this.head=0,this._size=0;}};var y=class{constructor(e,t){this.maxEvents=e;this.windowMs=t;this.timestamps=[];}allow(){let e=Date.now();return this.timestamps=this.timestamps.filter(t=>e-t<this.windowMs),this.timestamps.length>=this.maxEvents?false:(this.timestamps.push(e),true)}reset(){this.timestamps=[];}};function X(r){let e=5381;for(let t=0;t<r.length;t++)e=(e<<5)+e+r.charCodeAt(t)&4294967295;return (e>>>0).toString(36)}function A(r){let e;switch(r.kind){case "error":{let t=r.stack?.split(`
`)[1]?.trim()||"";e=`${r.name}:${r.message}:${t}`;break}case "console":e=`console:${r.level}:${r.args.join(",")}`;break;case "network":e=`network:${r.method}:${r.url}:${r.status}`;break;case "performance":e=`performance:${r.metric}:${Math.floor(r.value/100)*100}`;break;case "memory":e=`memory:${Math.floor(r.heapUsagePercent*10)/10}`;break}return X(e)}function j(){let r=new Uint8Array(8);return crypto.getRandomValues(r),Array.from(r,e=>e.toString(36).padStart(2,"0")).join("").slice(0,12)}var w=class{constructor(e,t,o){this.eventBus=e;this.contextCollector=t;this.options=o;this.unsubscribers=[];this.reports=new m(o.maxReports),this.breadcrumbs=new m(o.maxBreadcrumbs),this.rateLimiter=new y(o.rateLimit.maxEvents,o.rateLimit.windowMs),this.subscribe();}subscribe(){this.unsubscribers.push(this.eventBus.on("error:captured",e=>{this.addBreadcrumb({category:"error",message:e.message}),this.handleCapturedEvent("error",e);}),this.eventBus.on("console:captured",e=>{this.addBreadcrumb({category:"console",message:`console.${e.level}: ${e.args.join(", ")}`}),e.level==="error"&&this.handleCapturedEvent("console",e);}),this.eventBus.on("network:captured",e=>{this.handleCapturedEvent("network",e);}),this.eventBus.on("performance:captured",e=>{this.addBreadcrumb({category:"performance",message:`${e.metric}: ${e.value}ms`}),this.handleCapturedEvent("performance",e);}),this.eventBus.on("memory:captured",e=>{this.handleCapturedEvent("memory",e);}),this.eventBus.on("breadcrumb:added",e=>{this.addBreadcrumb(e);}));}async handleCapturedEvent(e,t){if(!this.rateLimiter.allow())return;let o=A(t),n=this.reports.find(l=>l.fingerprint===o);if(n){n.count++,n.timestamp=new Date().toISOString(),this.eventBus.emit("report:deduplicated",n);return}let i={id:j(),fingerprint:o,type:e,timestamp:new Date().toISOString(),count:1,payload:t,breadcrumbs:this.breadcrumbs.toArray(),context:this.contextCollector.snapshot()},a=this.options.beforeReport(i);a&&(i=a,this.reports.push(i),this.eventBus.emit("report:created",i));}addBreadcrumb(e){this.breadcrumbs.push({...e,timestamp:new Date().toISOString()});}getReports(){return this.reports.toArray()}clear(){this.reports.clear(),this.breadcrumbs.clear(),this.unsubscribers.forEach(e=>e()),this.unsubscribers=[];}get reportCount(){return this.reports.size}};var x=class{constructor(e){this.eventBus=e;this.name="error";this.originalOnError=null;this.rejectionHandler=null;}setup(){this.originalOnError=window.onerror,window.onerror=(e,t,o,n,i)=>{let a={kind:"error",message:String(e),stack:i?.stack,filename:t??void 0,lineno:o??void 0,colno:n??void 0,name:i?.name};return this.eventBus.emit("error:captured",a),this.originalOnError?this.originalOnError.call(window,e,t,o,n,i):false},this.rejectionHandler=e=>{let t=e.reason,o={kind:"error",message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,name:t instanceof Error?t.name:"UnhandledRejection"};this.eventBus.emit("error:captured",o);},window.addEventListener("unhandledrejection",this.rejectionHandler);}teardown(){window.onerror=this.originalOnError,this.originalOnError=null,this.rejectionHandler&&(window.removeEventListener("unhandledrejection",this.rejectionHandler),this.rejectionHandler=null);}};function f(r,e){let t=new WeakSet;return JSON.stringify(r,(o,n)=>{if(typeof n=="object"&&n!==null){if(t.has(n))return "[Circular]";t.add(n);}return typeof n=="function"?"[Function]":typeof n=="symbol"?n.toString():n instanceof Error?{name:n.name,message:n.message,stack:n.stack}:n},e)}var E=class{constructor(e){this.eventBus=e;this.name="console";this.originalError=null;this.originalWarn=null;}setup(){this.originalError=console.error,this.originalWarn=console.warn,console.error=(...e)=>{let t={kind:"console",level:"error",args:e.map(o=>f(o))};this.eventBus.emit("console:captured",t),this.originalError.apply(console,e);},console.warn=(...e)=>{let t={kind:"console",level:"warn",args:e.map(o=>f(o))};this.eventBus.emit("console:captured",t),this.originalWarn.apply(console,e);};}teardown(){this.originalError&&(console.error=this.originalError),this.originalWarn&&(console.warn=this.originalWarn),this.originalError=null,this.originalWarn=null;}};var k=class{constructor(e){this.eventBus=e;this.name="network";this.originalFetch=null;this.originalXhrOpen=null;this.originalXhrSend=null;}setup(){this.patchFetch(),this.patchXHR();}patchFetch(){this.originalFetch=window.fetch;let e=this.eventBus,t=this.originalFetch;window.fetch=function(o,n){let i=n?.method?.toUpperCase()||"GET",a=typeof o=="string"?o:o instanceof URL?o.href:o.url,l=performance.now();return t.call(window,o,n).then(s=>{let p=Math.round(performance.now()-l);if(s.status>=400){let u={kind:"network",method:i,url:a,status:s.status,statusText:s.statusText,duration:p};e.emit("network:captured",u);}return e.emit("breadcrumb:added",{category:"network",message:`${i} ${a} -> ${s.status}`}),s},s=>{let p=Math.round(performance.now()-l),u={kind:"network",method:i,url:a,status:0,statusText:s.message||"Network Error",duration:p};throw e.emit("network:captured",u),s})};}patchXHR(){this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let e=this.eventBus,t=this.originalXhrOpen,o=this.originalXhrSend;XMLHttpRequest.prototype.open=function(n,i,...a){return this.__ghostbug_method=n.toUpperCase(),this.__ghostbug_url=String(i),t.apply(this,[n,i,...a])},XMLHttpRequest.prototype.send=function(n){let i=performance.now(),a=this;return a.addEventListener("loadend",function(){let l=Math.round(performance.now()-i),s=a.__ghostbug_method||"UNKNOWN",p=a.__ghostbug_url||"";if(a.status>=400||a.status===0){let u={kind:"network",method:s,url:p,status:a.status,statusText:a.statusText,duration:l};e.emit("network:captured",u);}e.emit("breadcrumb:added",{category:"network",message:`${s} ${p} -> ${a.status}`});}),o.call(this,n)};}teardown(){this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null),this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null);}};function U(r){if(r.id)return `#${r.id}`;let e=r.getAttribute("data-testid");if(e)return `[data-testid="${e}"]`;let t=[],o=r,n=0;for(;o&&o!==document.documentElement&&n<5;){let i=o.tagName.toLowerCase();if(o.id){t.unshift(`#${o.id}`);break}let a=Array.from(o.classList).slice(0,2);a.length>0&&(i+="."+a.join("."));let l=o.parentElement;if(l){let s=o.tagName,p=Array.from(l.children).filter(u=>u.tagName===s);if(p.length>1){let u=p.indexOf(o)+1;i+=`:nth-child(${u})`;}}t.unshift(i),o=l,n++;}return t.join(" > ")}var C=class{constructor(e,t){this.eventBus=e;this.name="click";this.handler=null;this.clicks=new m(t);}setup(){this.handler=e=>{let t=e.target;if(!t)return;let o={timestamp:new Date().toISOString(),selector:U(t),tagName:t.tagName.toLowerCase(),text:(t.textContent||"").trim().slice(0,100),position:{x:e.clientX,y:e.clientY}};this.clicks.push(o),this.eventBus.emit("click:captured",o),this.eventBus.emit("breadcrumb:added",{category:"click",message:`Clicked ${o.tagName} "${o.text}"`,data:{selector:o.selector}});},document.addEventListener("click",this.handler,true);}getClickTrail(){return this.clicks.toArray()}teardown(){this.handler&&(document.removeEventListener("click",this.handler,true),this.handler=null),this.clicks.clear();}};var S=class{constructor(e){this.getMeta=e;this.name="context";}setup(){}teardown(){}snapshot(){let e=this.getMeta?.();return {url:window.location.href,referrer:document.referrer,userAgent:navigator.userAgent,language:navigator.language,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:window.screen.width,height:window.screen.height},devicePixelRatio:window.devicePixelRatio||1,timestamp:new Date().toISOString(),memory:performance.memory?{usedJSHeapSize:performance.memory.usedJSHeapSize,totalJSHeapSize:performance.memory.totalJSHeapSize}:void 0,user:e?.user,tags:e?.tags}}};var B=class{constructor(e){this.eventBus=e;this.name="interactions";this.handlers=[];this.scrollTimer=null;this.resizeTimer=null;}setup(){this.addHandler(window,"scroll",this.onScroll.bind(this),{passive:true,capture:true}),this.addHandler(document,"input",this.onInput.bind(this),true),this.addHandler(document,"change",this.onChange.bind(this),true),this.addHandler(window,"popstate",this.onPopState.bind(this)),this.addHandler(window,"hashchange",this.onHashChange.bind(this)),this.addHandler(document,"visibilitychange",this.onVisibilityChange.bind(this)),this.addHandler(window,"resize",this.onResize.bind(this),{passive:true});}addHandler(e,t,o,n){e.addEventListener(t,o,n),this.handlers.push({target:e,event:t,handler:o});}onScroll(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Scrolled",data:{x:window.scrollX,y:window.scrollY}});},300);}onInput(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"",i=t.type?`[type="${t.type}"]`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Input on ${o}${n}${i}`});}onChange(e){let t=e.target;if(!t)return;let o=t.tagName.toLowerCase(),n=t.id?`#${t.id}`:"";this.eventBus.emit("breadcrumb:added",{category:"interaction",message:`Change on ${o}${n}`});}onPopState(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Navigated to ${window.location.href}`});}onHashChange(){this.eventBus.emit("breadcrumb:added",{category:"navigation",message:`Hash changed to ${window.location.hash}`});}onVisibilityChange(){this.eventBus.emit("breadcrumb:added",{category:"visibility",message:document.hidden?"Tab hidden":"Tab visible"});}onResize(){this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.eventBus.emit("breadcrumb:added",{category:"interaction",message:"Window resized",data:{width:window.innerWidth,height:window.innerHeight}});},300);}teardown(){this.scrollTimer&&clearTimeout(this.scrollTimer),this.resizeTimer&&clearTimeout(this.resizeTimer),this.handlers.forEach(({target:e,event:t,handler:o})=>{e.removeEventListener(t,o);}),this.handlers=[];}};var R=class{constructor(e){this.eventBus=e;this.name="performance";this.observers=[];}setup(){typeof PerformanceObserver>"u"||(this.observe("longtask",e=>{e.forEach(t=>{if(t.duration<50)return;let o={kind:"performance",metric:"longtask",value:Math.round(t.duration),entries:[{name:t.name,duration:t.duration,startTime:t.startTime}]};this.eventBus.emit("performance:captured",o),this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Long task: ${Math.round(t.duration)}ms`});});}),this.observe("largest-contentful-paint",e=>{let t=e[e.length-1];t&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`LCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});}),this.observe("paint",e=>{e.forEach(t=>{t.name==="first-contentful-paint"&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`FCP: ${Math.round(t.startTime)}ms`,data:{value:t.startTime}});});}),this.observe("layout-shift",e=>{e.forEach(t=>{let o=t.value;o>.1&&this.eventBus.emit("breadcrumb:added",{category:"performance",message:`Layout shift: ${o.toFixed(4)}`,data:{cls:o}});});}));}observe(e,t){try{let o=new PerformanceObserver(n=>{t(n.getEntries());});o.observe({type:e,buffered:!0}),this.observers.push(o);}catch{}}teardown(){this.observers.forEach(e=>e.disconnect()),this.observers=[];}};function F(){let r=performance.memory;return !r||typeof r.usedJSHeapSize!="number"?null:r}var T=class{constructor(e){this.eventBus=e;this.name="memory";this.intervalId=null;this.baselineUsed=null;}setup(){let e=F();e&&(this.baselineUsed=e.usedJSHeapSize,this.intervalId=setInterval(()=>{let t=F();if(!t)return;let o=t.usedJSHeapSize/t.jsHeapSizeLimit,n=this.baselineUsed>0?(t.usedJSHeapSize-this.baselineUsed)/this.baselineUsed:0;this.eventBus.emit("breadcrumb:added",{category:"memory",message:`Heap: ${(o*100).toFixed(1)}% used (${(t.usedJSHeapSize/1048576).toFixed(1)}MB)`,data:{usedJSHeapSize:t.usedJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit}});let i=o>=.9,a=n>=.5;if(i||a){let s={kind:"memory",message:i?`Heap usage critical: ${(o*100).toFixed(1)}% of limit`:`Heap growth spike: ${(n*100).toFixed(1)}% since init`,usedJSHeapSize:t.usedJSHeapSize,totalJSHeapSize:t.totalJSHeapSize,jsHeapSizeLimit:t.jsHeapSizeLimit,heapUsagePercent:o,heapGrowthPercent:n};this.eventBus.emit("memory:captured",s);}},1e4));}teardown(){this.intervalId!==null&&(clearInterval(this.intervalId),this.intervalId=null),this.baselineUsed=null;}};var D=`
:host {

@@ -165,16 +165,63 @@ all: initial;

.gb-report-item {
padding: 10px 16px;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
transition: background 0.15s;
}
.gb-report-item:hover {
.gb-report-item:last-child {
border-bottom: none;
}
.gb-report-summary {
padding: 10px 16px;
cursor: pointer;
}
.gb-report-summary:hover {
background: #f8f9fa;
}
.gb-report-item:last-child {
border-bottom: none;
.gb-report-detail {
display: none;
padding: 0 16px 12px;
border-top: 1px dashed #e8e8e8;
}
.gb-report-item.gb-expanded .gb-report-detail {
display: block;
}
.gb-detail-section {
margin-top: 8px;
}
.gb-detail-label {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #999;
margin-bottom: 2px;
}
.gb-detail-value {
font-size: 12px;
color: #555;
word-break: break-word;
line-height: 1.4;
}
.gb-detail-pre {
font-size: 11px;
font-family: 'SF Mono', Menlo, Monaco, monospace;
background: #f5f5f5;
padding: 8px;
border-radius: 6px;
overflow-x: auto;
max-height: 120px;
overflow-y: auto;
color: #333;
white-space: pre-wrap;
word-break: break-word;
}
.gb-report-type {

@@ -257,4 +304,5 @@ display: inline-block;

}
`;var J='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></svg>';function D(){let r=document.createElement("button");r.className="gb-fab",r.setAttribute("aria-label","ghostbug - bug reports");let e=document.createElement("span");e.innerHTML=J,r.appendChild(e);let t=document.createElement("span");return t.className="gb-badge",t.setAttribute("data-count","0"),t.textContent="0",r.appendChild(t),r}function G(r){let e=document.createElement("div");e.className=`gb-panel gb-pos-${r}`;let t=document.createElement("div");t.className="gb-header";let o=document.createElement("span");o.className="gb-header-title",o.textContent="ghostbug",t.appendChild(o);let n=document.createElement("button");n.className="gb-header-btn gb-copy-btn",n.textContent="Copy MD",t.appendChild(n);let i=document.createElement("button");i.className="gb-header-btn gb-download-btn",i.textContent="Export",t.appendChild(i);let s=document.createElement("button");s.className="gb-close-btn",s.textContent="\xD7",s.setAttribute("aria-label","Close"),t.appendChild(s),e.appendChild(t);let l=document.createElement("div");l.className="gb-report-list";let a=document.createElement("div");return a.className="gb-empty",a.textContent="No bugs captured yet.",l.appendChild(a),e.appendChild(l),e}function X(r){let e=document.createElement("div");e.className="gb-report-item";let t=document.createElement("span");if(t.className=`gb-report-type gb-type-${r.payload.kind==="error"?"error":r.payload.kind}`,t.textContent=r.type,e.appendChild(t),r.count>1){let s=document.createElement("span");s.className="gb-report-count",s.textContent=`\xD7${r.count}`,e.appendChild(s);}let o=document.createElement("div");o.className="gb-report-message",o.textContent=V(r),e.appendChild(o);let n=document.createElement("div");n.className="gb-report-meta";let i=r.timestamp.split("T")[1]?.split(".")[0]||r.timestamp;return n.textContent=`${i} \xB7 ${r.context.url}`,e.appendChild(n),e}function V(r){switch(r.payload.kind){case "error":return r.payload.message;case "console":return r.payload.args.join(", ");case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `${r.payload.metric}: ${r.payload.value}ms`;case "memory":return r.payload.message}}function T(r){return g({generator:"ghostbug",version:f,exportedAt:new Date().toISOString(),reportCount:r.length,reports:r},2)}function L(r){let e=[];return e.push(`# Bug Report \u2014 ghostbug v${f}`),e.push(`**Generated:** ${new Date().toISOString()}`),e.push(`**Reports:** ${r.length}`),e.push(""),e.push("---"),e.push(""),r.forEach((t,o)=>{e.push(`## ${o+1}. ${Y(t)}`),e.push(""),e.push(`- **Type:** ${t.type}`),e.push(`- **Time:** ${t.timestamp}`),e.push(`- **Occurrences:** ${t.count}`),e.push(`- **URL:** ${t.context.url}`),e.push(`- **Browser:** ${Q(t.context.userAgent)}`),e.push(`- **Viewport:** ${t.context.viewport.width}x${t.context.viewport.height}`),e.push(""),e.push(...K(t.payload)),e.push(""),t.breadcrumbs.length>0&&(e.push("### Breadcrumbs"),e.push(""),e.push("| Time | Category | Event |"),e.push("|------|----------|-------|"),t.breadcrumbs.forEach(n=>{let i=n.timestamp.split("T")[1]?.split(".")[0]||n.timestamp;e.push(`| ${i} | ${n.category} | ${n.message} |`);}),e.push("")),e.push("---"),e.push("");}),e.join(`
`)}function Y(r){switch(r.payload.kind){case "error":return `${r.payload.name||"Error"}: ${r.payload.message}`;case "console":return `Console ${r.payload.level}: ${r.payload.args[0]||""}`;case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `Performance: ${r.payload.metric} ${r.payload.value}ms`;case "memory":return `Memory: ${r.payload.message}`}}function K(r){let e=[];switch(r.kind){case "error":r.stack&&(e.push("### Stack Trace"),e.push(""),e.push("```"),e.push(r.stack),e.push("```")),r.filename&&e.push(`**File:** ${r.filename}:${r.lineno}:${r.colno}`);break;case "console":e.push("### Console Output"),e.push(""),e.push("```"),r.args.forEach(t=>e.push(t)),e.push("```");break;case "network":e.push("### Network Details"),e.push(""),e.push(`- **Method:** ${r.method}`),e.push(`- **URL:** ${r.url}`),e.push(`- **Status:** ${r.status} ${r.statusText}`),e.push(`- **Duration:** ${r.duration}ms`);break;case "performance":e.push("### Performance Details"),e.push(""),e.push(`- **Metric:** ${r.metric}`),e.push(`- **Value:** ${r.value}ms`),r.entries.length>0&&e.push(`- **Start Time:** ${Math.round(r.entries[0].startTime)}ms`);break;case "memory":e.push("### Memory Details"),e.push(""),e.push(`- **Used:** ${(r.usedJSHeapSize/1048576).toFixed(1)}MB`),e.push(`- **Limit:** ${(r.jsHeapSizeLimit/1048576).toFixed(1)}MB`),e.push(`- **Usage:** ${(r.heapUsagePercent*100).toFixed(1)}%`),e.push(`- **Growth since init:** ${(r.heapGrowthPercent*100).toFixed(1)}%`);break}return e}function Q(r){if(r.includes("Chrome")){let e=r.match(/Chrome\/(\d+)/);return e?`Chrome ${e[1]}`:"Chrome"}if(r.includes("Firefox")){let e=r.match(/Firefox\/(\d+)/);return e?`Firefox ${e[1]}`:"Firefox"}if(r.includes("Safari")&&!r.includes("Chrome")){let e=r.match(/Version\/(\d+)/);return e?`Safari ${e[1]}`:"Safari"}return r.slice(0,50)}var P=class{constructor(e,t,o){this.eventBus=e;this.reportManager=t;this.options=o;this.hostElement=null;this.shadowRoot=null;this.panel=null;this.badge=null;this.reportList=null;this.isExpanded=false;this.unsubscribers=[];}mount(){this.hostElement=document.createElement("div"),this.hostElement.id="ghostbug-widget";let e=this.hostElement.style;e.position="fixed",e.zIndex=String(this.options.zIndex),e.margin="0",e.padding="0",this.applyPosition(e),this.shadowRoot=this.hostElement.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=U,this.shadowRoot.appendChild(t);let o=document.createElement("div");o.className="gb-container";let n=D();this.badge=n.querySelector(".gb-badge"),n.addEventListener("click",()=>this.toggle()),o.appendChild(n),this.panel=G(this.options.position),o.appendChild(this.panel),this.panel.querySelector(".gb-close-btn")?.addEventListener("click",()=>this.toggle()),this.panel.querySelector(".gb-copy-btn")?.addEventListener("click",()=>this.copyMarkdown()),this.panel.querySelector(".gb-download-btn")?.addEventListener("click",()=>this.downloadJSON()),this.reportList=this.panel.querySelector(".gb-report-list"),this.shadowRoot.appendChild(o),document.body.appendChild(this.hostElement),this.unsubscribers.push(this.eventBus.on("report:created",()=>this.update()),this.eventBus.on("report:deduplicated",()=>this.update())),this.options.collapsed||this.toggle();}applyPosition(e){let t=this.options.position;e.top=t.startsWith("top")?"16px":"auto",e.bottom=t.startsWith("bottom")?"16px":"auto",e.left=t.endsWith("left")?"16px":"auto",e.right=t.endsWith("right")?"16px":"auto";}toggle(){this.isExpanded=!this.isExpanded,this.isExpanded?(this.panel?.classList.add("gb-open"),this.renderReportList()):this.panel?.classList.remove("gb-open");}update(){this.updateBadge(),this.isExpanded&&this.renderReportList();}updateBadge(){if(!this.badge)return;let e=this.reportManager.reportCount;this.badge.textContent=String(e),this.badge.setAttribute("data-count",String(e));}renderReportList(){if(!this.reportList)return;this.reportList.textContent="";let e=this.reportManager.getReports();if(e.length===0){let o=document.createElement("div");o.className="gb-empty",o.textContent="No bugs captured yet.",this.reportList.appendChild(o);return}[...e].reverse().forEach(o=>{let n=X(o);this.reportList.appendChild(n);});}copyMarkdown(){let e=L(this.reportManager.getReports());navigator.clipboard.writeText(e).then(()=>this.showToast("Copied to clipboard!"),()=>this.showToast("Copy failed"));}downloadJSON(){let e=T(this.reportManager.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download="ghostbug-report.json",n.click(),URL.revokeObjectURL(o);}showToast(e){if(!this.shadowRoot)return;let t=document.createElement("div");t.className="gb-toast",t.textContent=e,this.shadowRoot.appendChild(t),requestAnimationFrame(()=>{t.classList.add("gb-show");}),setTimeout(()=>{t.classList.remove("gb-show"),setTimeout(()=>t.remove(),300);},2e3);}unmount(){this.unsubscribers.forEach(e=>e()),this.unsubscribers=[],this.hostElement?.remove(),this.hostElement=null,this.shadowRoot=null,this.panel=null,this.badge=null,this.reportList=null;}};var c=null,h=null,d=[],H=null,$=new Set,M=false,z,O;function Z(r,e){return e?{maxReports:e.maxReports??r.maxReports,maxBreadcrumbs:e.maxBreadcrumbs??r.maxBreadcrumbs,maxClicks:e.maxClicks??r.maxClicks,widget:e.widget??r.widget,collectors:{...r.collectors,...e.collectors},rateLimit:{...r.rateLimit,...e.rateLimit},beforeReport:e.beforeReport??r.beforeReport,debug:e.debug??r.debug,screenshotFn:e.screenshotFn}:{...r}}function ee(r){if(M){r?.debug&&console.warn("[ghostbug] Already initialized. Call destroy() first.");return}let e=Z(_,r);c=new b;let t=new C(()=>({user:z,tags:O}));if(h=new y(c,t,e),e.collectors.errors&&d.push(new w(c)),e.collectors.console&&d.push(new x(c)),e.collectors.network&&d.push(new E(c)),e.collectors.clicks&&d.push(new k(c,e.maxClicks)),e.collectors.interactions&&d.push(new S(c)),e.collectors.performance&&d.push(new B(c)),e.collectors.memory&&d.push(new R(c)),d.push(t),d.forEach(o=>o.setup()),c.on("report:created",o=>{$.forEach(n=>{try{n(o);}catch{}});}),e.widget){let o=typeof e.widget=="object"?{position:e.widget.position||"bottom-right",collapsed:e.widget.collapsed??true,zIndex:e.widget.zIndex??2147483647}:{position:"bottom-right",collapsed:true,zIndex:2147483647};H=new P(c,h,o),H.mount();}M=true;}function te(){return N(),h.getReports()}function re(r="ghostbug-report.json"){N();let e=T(h.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download=r,n.click(),URL.revokeObjectURL(o);}function oe(){return N(),L(h.getReports())}function ne(r){return $.add(r),()=>$.delete(r)}function ie(r){z=r;}function se(r){O={...O,...r};}function ae(){H?.unmount(),H=null,d.forEach(r=>r.teardown()),d=[],c?.clear(),c=null,h?.clear(),h=null,$.clear(),z=void 0,O=void 0,M=false;}function N(){if(!M)throw new Error("[ghostbug] Not initialized. Call ghostbug.init() first.")}var nt={init:ee,getReports:te,download:re,toMarkdown:oe,onBug:ne,setUser:ie,setTags:se,destroy:ae};export{nt as default,ae as destroy,re as download,te as getReports,ee as init,ne as onBug,se as setTags,ie as setUser,oe as toMarkdown};//# sourceMappingURL=index.js.map
`;var W='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></svg>';function J(){let r=document.createElement("button");r.className="gb-fab",r.setAttribute("aria-label","ghostbug - bug reports");let e=document.createElement("span");e.innerHTML=W,r.appendChild(e);let t=document.createElement("span");return t.className="gb-badge",t.setAttribute("data-count","0"),t.textContent="0",r.appendChild(t),r}function G(r){let e=document.createElement("div");e.className=`gb-panel gb-pos-${r}`;let t=document.createElement("div");t.className="gb-header";let o=document.createElement("span");o.className="gb-header-title",o.textContent="ghostbug",t.appendChild(o);let n=document.createElement("button");n.className="gb-header-btn gb-copy-btn",n.textContent="Copy MD",t.appendChild(n);let i=document.createElement("button");i.className="gb-header-btn gb-download-btn",i.textContent="Export",t.appendChild(i);let a=document.createElement("button");a.className="gb-close-btn",a.textContent="\xD7",a.setAttribute("aria-label","Close"),t.appendChild(a),e.appendChild(t);let l=document.createElement("div");l.className="gb-report-list";let s=document.createElement("div");return s.className="gb-empty",s.textContent="No bugs captured yet.",l.appendChild(s),e.appendChild(l),e}function q(r){let e=document.createElement("div");e.className="gb-report-item";let t=document.createElement("div");t.className="gb-report-summary";let o=document.createElement("span");if(o.className=`gb-report-type gb-type-${r.payload.kind==="error"?"error":r.payload.kind}`,o.textContent=r.type,t.appendChild(o),r.count>1){let s=document.createElement("span");s.className="gb-report-count",s.textContent=`\xD7${r.count}`,t.appendChild(s);}let n=document.createElement("div");n.className="gb-report-message",n.textContent=Y(r),t.appendChild(n);let i=document.createElement("div");i.className="gb-report-meta";let a=r.timestamp.split("T")[1]?.split(".")[0]||r.timestamp;i.textContent=`${a} \xB7 ${r.context.url}`,t.appendChild(i),e.appendChild(t);let l=document.createElement("div");if(l.className="gb-report-detail",l.appendChild(V(r.payload)),r.context.user){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">User</div><div class="gb-detail-value">${g(JSON.stringify(r.context.user))}</div>`,l.appendChild(s);}if(r.context.tags){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">Tags</div><div class="gb-detail-value">${g(JSON.stringify(r.context.tags))}</div>`,l.appendChild(s);}if(r.breadcrumbs.length>0){let s=document.createElement("div");s.className="gb-detail-section",s.innerHTML=`<div class="gb-detail-label">Breadcrumbs</div><div class="gb-detail-value">${r.breadcrumbs.length} events</div>`,l.appendChild(s);}return e.appendChild(l),t.addEventListener("click",()=>{e.classList.toggle("gb-expanded");}),e}function g(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function V(r){let e=document.createElement("div");switch(e.className="gb-detail-section",r.kind){case "error":{if(r.stack){let t=document.createElement("div");t.className="gb-detail-label",t.textContent="Stack Trace",e.appendChild(t);let o=document.createElement("pre");o.className="gb-detail-pre",o.textContent=r.stack,e.appendChild(o);}if(r.filename){let t=document.createElement("div");t.className="gb-detail-value",t.textContent=`${r.filename}:${r.lineno}:${r.colno}`,e.appendChild(t);}break}case "console":{let t=document.createElement("div");t.className="gb-detail-label",t.textContent="Output",e.appendChild(t);let o=document.createElement("pre");o.className="gb-detail-pre",o.textContent=r.args.join(`
`),e.appendChild(o);break}case "network":{e.innerHTML=`<div class="gb-detail-label">Request</div><div class="gb-detail-value">${g(r.method)} ${g(r.url)}<br>Status: ${r.status} ${g(r.statusText)}<br>Duration: ${r.duration}ms</div>`;break}case "performance":{e.innerHTML=`<div class="gb-detail-label">Performance</div><div class="gb-detail-value">Metric: ${g(r.metric)}<br>Value: ${r.value}ms</div>`;break}case "memory":{e.innerHTML=`<div class="gb-detail-label">Memory</div><div class="gb-detail-value">Used: ${(r.usedJSHeapSize/1048576).toFixed(1)}MB<br>Limit: ${(r.jsHeapSizeLimit/1048576).toFixed(1)}MB<br>Usage: ${(r.heapUsagePercent*100).toFixed(1)}%</div>`;break}}return e}function Y(r){switch(r.payload.kind){case "error":return r.payload.message;case "console":return r.payload.args.join(", ");case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `${r.payload.metric}: ${r.payload.value}ms`;case "memory":return r.payload.message}}function L(r){return f({generator:"ghostbug",version:b,exportedAt:new Date().toISOString(),reportCount:r.length,reports:r},2)}function P(r){let e=[];return e.push(`# Bug Report \u2014 ghostbug v${b}`),e.push(`**Generated:** ${new Date().toISOString()}`),e.push(`**Reports:** ${r.length}`),e.push(""),e.push("---"),e.push(""),r.forEach((t,o)=>{e.push(`## ${o+1}. ${K(t)}`),e.push(""),e.push(`- **Type:** ${t.type}`),e.push(`- **Time:** ${t.timestamp}`),e.push(`- **Occurrences:** ${t.count}`),e.push(`- **URL:** ${t.context.url}`),e.push(`- **Browser:** ${Z(t.context.userAgent)}`),e.push(`- **Viewport:** ${t.context.viewport.width}x${t.context.viewport.height}`),e.push(""),e.push(...Q(t.payload)),e.push(""),t.context.user&&(e.push("### User Context"),e.push(""),e.push("```json"),e.push(JSON.stringify(t.context.user,null,2)),e.push("```"),e.push("")),t.context.tags&&(e.push("### Tags"),e.push(""),e.push("```json"),e.push(JSON.stringify(t.context.tags,null,2)),e.push("```"),e.push("")),t.breadcrumbs.length>0&&(e.push("### Breadcrumbs"),e.push(""),e.push("| Time | Category | Event |"),e.push("|------|----------|-------|"),t.breadcrumbs.forEach(n=>{let i=n.timestamp.split("T")[1]?.split(".")[0]||n.timestamp;e.push(`| ${i} | ${n.category} | ${n.message} |`);}),e.push("")),e.push("---"),e.push("");}),e.join(`
`)}function K(r){switch(r.payload.kind){case "error":return `${r.payload.name||"Error"}: ${r.payload.message}`;case "console":return `Console ${r.payload.level}: ${r.payload.args[0]||""}`;case "network":return `${r.payload.method} ${r.payload.url} \u2192 ${r.payload.status}`;case "performance":return `Performance: ${r.payload.metric} ${r.payload.value}ms`;case "memory":return `Memory: ${r.payload.message}`}}function Q(r){let e=[];switch(r.kind){case "error":r.stack&&(e.push("### Stack Trace"),e.push(""),e.push("```"),e.push(r.stack),e.push("```")),r.filename&&e.push(`**File:** ${r.filename}:${r.lineno}:${r.colno}`);break;case "console":e.push("### Console Output"),e.push(""),e.push("```"),r.args.forEach(t=>e.push(t)),e.push("```");break;case "network":e.push("### Network Details"),e.push(""),e.push(`- **Method:** ${r.method}`),e.push(`- **URL:** ${r.url}`),e.push(`- **Status:** ${r.status} ${r.statusText}`),e.push(`- **Duration:** ${r.duration}ms`);break;case "performance":e.push("### Performance Details"),e.push(""),e.push(`- **Metric:** ${r.metric}`),e.push(`- **Value:** ${r.value}ms`),r.entries.length>0&&e.push(`- **Start Time:** ${Math.round(r.entries[0].startTime)}ms`);break;case "memory":e.push("### Memory Details"),e.push(""),e.push(`- **Used:** ${(r.usedJSHeapSize/1048576).toFixed(1)}MB`),e.push(`- **Limit:** ${(r.jsHeapSizeLimit/1048576).toFixed(1)}MB`),e.push(`- **Usage:** ${(r.heapUsagePercent*100).toFixed(1)}%`),e.push(`- **Growth since init:** ${(r.heapGrowthPercent*100).toFixed(1)}%`);break}return e}function Z(r){if(r.includes("Chrome")){let e=r.match(/Chrome\/(\d+)/);return e?`Chrome ${e[1]}`:"Chrome"}if(r.includes("Firefox")){let e=r.match(/Firefox\/(\d+)/);return e?`Firefox ${e[1]}`:"Firefox"}if(r.includes("Safari")&&!r.includes("Chrome")){let e=r.match(/Version\/(\d+)/);return e?`Safari ${e[1]}`:"Safari"}return r.slice(0,50)}var $=class{constructor(e,t,o){this.eventBus=e;this.reportManager=t;this.options=o;this.hostElement=null;this.shadowRoot=null;this.panel=null;this.badge=null;this.reportList=null;this.isExpanded=false;this.unsubscribers=[];}mount(){this.hostElement=document.createElement("div"),this.hostElement.id="ghostbug-widget";let e=this.hostElement.style;e.position="fixed",e.zIndex=String(this.options.zIndex),e.margin="0",e.padding="0",this.applyPosition(e),this.shadowRoot=this.hostElement.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=D,this.shadowRoot.appendChild(t);let o=document.createElement("div");o.className="gb-container";let n=J();this.badge=n.querySelector(".gb-badge"),n.addEventListener("click",()=>this.toggle()),o.appendChild(n),this.panel=G(this.options.position),o.appendChild(this.panel),this.panel.querySelector(".gb-close-btn")?.addEventListener("click",()=>this.toggle()),this.panel.querySelector(".gb-copy-btn")?.addEventListener("click",()=>this.copyMarkdown()),this.panel.querySelector(".gb-download-btn")?.addEventListener("click",()=>this.downloadJSON()),this.reportList=this.panel.querySelector(".gb-report-list"),this.shadowRoot.appendChild(o),document.body.appendChild(this.hostElement),this.unsubscribers.push(this.eventBus.on("report:created",()=>this.update()),this.eventBus.on("report:deduplicated",()=>this.update())),this.options.collapsed||this.toggle();}applyPosition(e){let t=this.options.position;e.top=t.startsWith("top")?"16px":"auto",e.bottom=t.startsWith("bottom")?"16px":"auto",e.left=t.endsWith("left")?"16px":"auto",e.right=t.endsWith("right")?"16px":"auto";}toggle(){this.isExpanded=!this.isExpanded,this.isExpanded?(this.panel?.classList.add("gb-open"),this.renderReportList()):this.panel?.classList.remove("gb-open");}update(){this.updateBadge(),this.isExpanded&&this.renderReportList();}updateBadge(){if(!this.badge)return;let e=this.reportManager.reportCount;this.badge.textContent=String(e),this.badge.setAttribute("data-count",String(e));}renderReportList(){if(!this.reportList)return;this.reportList.textContent="";let e=this.reportManager.getReports();if(e.length===0){let o=document.createElement("div");o.className="gb-empty",o.textContent="No bugs captured yet.",this.reportList.appendChild(o);return}[...e].reverse().forEach(o=>{let n=q(o);this.reportList.appendChild(n);});}copyMarkdown(){let e=P(this.reportManager.getReports());navigator.clipboard.writeText(e).then(()=>this.showToast("Copied to clipboard!"),()=>this.showToast("Copy failed"));}downloadJSON(){let e=L(this.reportManager.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download="ghostbug-report.json",n.click(),URL.revokeObjectURL(o);}showToast(e){if(!this.shadowRoot)return;let t=document.createElement("div");t.className="gb-toast",t.textContent=e,this.shadowRoot.appendChild(t),requestAnimationFrame(()=>{t.classList.add("gb-show");}),setTimeout(()=>{t.classList.remove("gb-show"),setTimeout(()=>t.remove(),300);},2e3);}unmount(){this.unsubscribers.forEach(e=>e()),this.unsubscribers=[],this.hostElement?.remove(),this.hostElement=null,this.shadowRoot=null,this.panel=null,this.badge=null,this.reportList=null;}};var d=null,h=null,c=[],H=null,M=new Set,O=false,z,N;function ee(r,e){return e?{maxReports:e.maxReports??r.maxReports,maxBreadcrumbs:e.maxBreadcrumbs??r.maxBreadcrumbs,maxClicks:e.maxClicks??r.maxClicks,widget:e.widget??r.widget,collectors:{...r.collectors,...e.collectors},rateLimit:{...r.rateLimit,...e.rateLimit},beforeReport:e.beforeReport??r.beforeReport,debug:e.debug??r.debug}:{...r}}function te(r){if(O){r?.debug&&console.warn("[ghostbug] Already initialized. Call destroy() first.");return}let e=ee(I,r);d=new v;let t=new S(()=>({user:z,tags:N}));if(h=new w(d,t,e),e.collectors.errors&&c.push(new x(d)),e.collectors.console&&c.push(new E(d)),e.collectors.network&&c.push(new k(d)),e.collectors.clicks&&c.push(new C(d,e.maxClicks)),e.collectors.interactions&&c.push(new B(d)),e.collectors.performance&&c.push(new R(d)),e.collectors.memory&&c.push(new T(d)),c.push(t),c.forEach(o=>o.setup()),d.on("report:created",o=>{M.forEach(n=>{try{n(o);}catch{}});}),e.widget){let o=typeof e.widget=="object"?{position:e.widget.position||"bottom-right",collapsed:e.widget.collapsed??true,zIndex:e.widget.zIndex??2147483647}:{position:"bottom-right",collapsed:true,zIndex:2147483647};H=new $(d,h,o),H.mount();}O=true;}function re(){return _(),h.getReports()}function oe(r="ghostbug-report.json"){_();let e=L(h.getReports()),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),n=document.createElement("a");n.href=o,n.download=r,n.click(),URL.revokeObjectURL(o);}function ne(){return _(),P(h.getReports())}function ie(r){return M.add(r),()=>M.delete(r)}function se(r){z=r;}function ae(r){N={...N,...r};}function le(){H?.unmount(),H=null,c.forEach(r=>r.teardown()),c=[],d?.clear(),d=null,h?.clear(),h=null,M.clear(),z=void 0,N=void 0,O=false;}function _(){if(!O)throw new Error("[ghostbug] Not initialized. Call ghostbug.init() first.")}var it={init:te,getReports:re,download:oe,toMarkdown:ne,onBug:ie,setUser:se,setTags:ae,destroy:le};export{it as default,le as destroy,oe as download,re as getReports,te as init,ie as onBug,ae as setTags,se as setUser,ne as toMarkdown};//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map
{
"name": "ghostbug",
"version": "0.2.0-beta.0",
"version": "0.2.0",
"description": "Zero-config automatic bug context collector SDK for the browser",

@@ -14,3 +14,3 @@ "author": "Sounak Das",

},
"homepage": "https://github.com/LittleBoy9/ghostbug#readme",
"homepage": "https://littleboy9.github.io/ghostbug/",
"type": "module",

@@ -38,12 +38,22 @@ "main": "./dist/index.cjs",

"keywords": [
"bug",
"error",
"debug",
"report",
"ghostbug",
"error-tracking",
"bug-reporter",
"browser",
"javascript",
"sdk",
"error-tracking",
"error-monitoring",
"console-capture",
"network-monitoring",
"performance-monitoring",
"memory-leak",
"click-tracking",
"breadcrumbs",
"debugging",
"developer-tools",
"ghostbug"
"sentry-alternative",
"zero-dependency",
"lightweight",
"frontend",
"qa"
],

@@ -50,0 +60,0 @@ "scripts": {

+151
-62

@@ -1,21 +0,44 @@

# ghostbug
<p align="center">
<img src="https://em-content.zobj.net/source/apple/391/ghost_1f47b.png" width="80" alt="ghostbug" />
</p>
Zero-config automatic bug context collector for the browser. Drop it in, forget about it. When something breaks, you already have everything you need.
<h1 align="center">ghostbug</h1>
[![npm version](https://img.shields.io/npm/v/ghostbug.svg)](https://www.npmjs.com/package/ghostbug)
[![bundle size](https://img.shields.io/bundlephobia/minzip/ghostbug)](https://bundlephobia.com/package/ghostbug)
[![license](https://img.shields.io/npm/l/ghostbug.svg)](https://github.com/sounakdas/ghostbug/blob/main/LICENSE)
<p align="center">
<strong>Zero-config bug context collector for the browser.</strong><br />
Drop it in, forget about it. When something breaks, you already have everything you need.
</p>
<p align="center">
<a href="https://www.npmjs.com/package/ghostbug"><img src="https://img.shields.io/npm/v/ghostbug.svg?style=flat-square&color=10b981" alt="npm version" /></a>
<a href="https://bundlephobia.com/package/ghostbug"><img src="https://img.shields.io/bundlephobia/minzip/ghostbug?style=flat-square&color=6ee7b7&label=size" alt="bundle size" /></a>
<a href="https://github.com/LittleBoy9/ghostbug/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/ghostbug.svg?style=flat-square&color=8b5cf6" alt="license" /></a>
<img src="https://img.shields.io/badge/dependencies-0-10b981?style=flat-square" alt="zero dependencies" />
<img src="https://img.shields.io/badge/tests-81%20passing-6ee7b7?style=flat-square" alt="tests passing" />
</p>
<p align="center">
<a href="https://littleboy9.github.io/ghostbug/"><strong>Website</strong></a> &nbsp;&middot;&nbsp;
<a href="https://www.npmjs.com/package/ghostbug"><strong>npm</strong></a> &nbsp;&middot;&nbsp;
<a href="https://github.com/LittleBoy9/ghostbug"><strong>GitHub</strong></a>
</p>
---
## Why ghostbug?
Testers spend 90% of their time manually collecting bug context — screenshots, error messages, console logs, steps to reproduce. ghostbug eliminates that by silently capturing everything in the background.
Testers spend 90% of their time manually collecting bug context — error messages, console logs, network failures, steps to reproduce. **ghostbug eliminates that** by silently capturing everything in the background.
| | Sentry / LogRocket | ghostbug |
| | Sentry / LogRocket | ghostbug |
|---|---|---|
| Setup | Account, API keys, config | `ghostbug.init()` |
| Server needed | Yes (paid) | No — everything local |
| Bundle size | 50-200KB+ | **~7KB gzipped** |
| Dependencies | Multiple | **Zero** |
| Output | Dashboard (another tab) | JSON / Markdown you paste into GitHub Issues |
| **Setup** | Account, API keys, config | `ghostbug.init()` |
| **Server needed** | Yes (paid SaaS) | **No** — 100% client-side |
| **Bundle size** | 50–200KB+ | **~7KB gzipped** |
| **Dependencies** | Multiple | **Zero** |
| **Data privacy** | Sent to their servers | **Stays in the browser** |
| **Output** | Dashboard (another tab) | JSON / Markdown for GitHub Issues |
| **Pricing** | Free tier / Paid | **Free forever** |
---
## Install

@@ -27,2 +50,11 @@

```bash
# or
yarn add ghostbug
# or
pnpm add ghostbug
```
---
## Quick Start

@@ -36,10 +68,17 @@

That's it. ghostbug now auto-captures:
That's it. ghostbug now silently auto-captures:
- **JS errors** — `window.onerror` + unhandled promise rejections
- **Console errors** — `console.error()` and `console.warn()`
- **Failed network requests** — `fetch` and `XMLHttpRequest` (4xx/5xx)
- **User click trail** — last 20 clicks with element selectors
- **Page context** — URL, browser, viewport, timestamp
| Collector | What it catches |
|---|---|
| **Errors** | `window.onerror` + unhandled promise rejections with stack traces |
| **Console** | `console.error()` and `console.warn()` with full arguments |
| **Network** | Failed `fetch` and `XMLHttpRequest` (4xx/5xx) with timing |
| **Clicks** | Last 20 user clicks with element selectors and positions |
| **Interactions** | Form input, scroll, and resize events |
| **Performance** | Long Tasks, FCP, LCP, layout shifts via PerformanceObserver |
| **Memory** | Heap usage sampling, high usage (>90%) and rapid growth (>50%) alerts |
| **Context** | URL, browser, viewport, device pixel ratio, referrer |
---
## API

@@ -69,10 +108,11 @@

clicks: true,
interactions: true,
performance: true,
memory: true,
},
// Max reports stored (oldest dropped when full)
maxReports: 50,
maxReports: 50, // Max reports stored (oldest dropped when full)
maxBreadcrumbs: 20, // Max breadcrumb trail per report
maxClicks: 20, // Max click trail entries
// Max breadcrumb trail per report
maxBreadcrumbs: 20,
// Rate limiting (prevent flood from error loops)

@@ -83,6 +123,8 @@ rateLimit: { maxEvents: 10, windowMs: 1000 },

beforeReport: (report) => {
// Return false to discard
// Return false/null to discard
// Return modified report to transform
return report;
},
debug: false, // Enable SDK debug logging
});

@@ -97,3 +139,2 @@ ```

const reports = ghostbug.getReports();
console.log(reports);
```

@@ -110,3 +151,4 @@

Example output:
<details>
<summary><strong>Example markdown output</strong></summary>

@@ -134,2 +176,4 @@ ```markdown

</details>
### `ghostbug.download(filename?)`

@@ -140,3 +184,3 @@

```js
ghostbug.download(); // downloads ghostbug-report.json
ghostbug.download(); // ghostbug-report.json
ghostbug.download("my-bugs.json"); // custom filename

@@ -151,3 +195,3 @@ ```

const unsubscribe = ghostbug.onBug((report) => {
// Send to Slack
// Send to Slack, your API, anywhere
fetch("/api/slack-webhook", {

@@ -163,2 +207,18 @@ method: "POST",

### `ghostbug.setUser(user)`
Attach user context to every report.
```js
ghostbug.setUser({ id: "user-42", plan: "pro", email: "dev@example.com" });
```
### `ghostbug.setTags(tags)`
Add custom tags to every report. Merges with existing tags.
```js
ghostbug.setTags({ environment: "staging", version: "2.1.0" });
```
### `ghostbug.destroy()`

@@ -172,2 +232,4 @@

---
## Framework Integration

@@ -217,4 +279,19 @@

### Plain HTML
### Svelte
```svelte
<!-- +layout.svelte -->
<script>
import { onMount, onDestroy } from "svelte";
import ghostbug from "ghostbug";
onMount(() => ghostbug.init({ widget: true }));
onDestroy(() => ghostbug.destroy());
</script>
<slot />
```
### Plain HTML (CDN)
```html

@@ -227,5 +304,7 @@ <script src="https://unpkg.com/ghostbug/dist/index.iife.js"></script>

---
## Widget
Enable the floating widget for testers — a small bug icon that shows captured bugs with copy/export buttons.
Enable the floating widget for testers:

@@ -237,9 +316,11 @@ ```js

The widget:
- Shows a bug count badge
- Shows a **live bug count** badge
- Click to expand and see all captured bugs
- **Copy MD** — copies markdown to clipboard
- **Export** — downloads JSON file
- Uses Shadow DOM — styles never leak into your app
- Uses **Shadow DOM** — styles never leak into your app
- Fully isolated — your CSS won't break it
---
## Bug Report Structure

@@ -253,12 +334,20 @@

fingerprint: string; // Hash for deduplication
type: "error" | "console" | "network";
type: "error" | "unhandled-rejection" | "console" | "network" | "performance" | "memory";
timestamp: string; // ISO 8601
count: number; // Occurrences (deduped)
payload: { ... }; // Error details
breadcrumbs: [ ... ]; // Events leading up to the bug
payload: { ... }; // Error/network/console/perf/memory details
breadcrumbs: [ // Events leading up to the bug
{ timestamp, category, message, data }
];
context: {
url: string;
referrer: string;
userAgent: string;
language: string;
viewport: { width, height };
// ...
screen: { width, height };
devicePixelRatio: number;
memory?: { usedJSHeapSize, totalJSHeapSize };
user?: { ... }; // From setUser()
tags?: { ... }; // From setTags()
};

@@ -268,37 +357,37 @@ }

---
## How It Works
- **Error capture** — Patches `window.onerror` and listens for `unhandledrejection`
- **Console capture** — Monkey-patches `console.error` / `console.warn` (always calls originals)
- **Network capture** — Patches `fetch` and `XMLHttpRequest` (only captures 4xx/5xx, never alters responses)
- **Click tracking** — Uses capture-phase click listener (catches clicks even with `stopPropagation`)
- **Deduplication** — Identical errors increment a counter instead of creating duplicate reports
- **Rate limiting** — Token-bucket algorithm prevents floods from error loops
- **Ring buffer** — Fixed-capacity storage prevents memory leaks in long-running apps
- **Safe teardown** — `destroy()` restores all original APIs
| Mechanism | Details |
|---|---|
| **Error capture** | Patches `window.onerror` and listens for `unhandledrejection` |
| **Console capture** | Monkey-patches `console.error` / `console.warn` (always calls originals) |
| **Network capture** | Patches `fetch` and `XMLHttpRequest` (only captures 4xx/5xx, never alters responses) |
| **Click tracking** | Uses capture-phase click listener (catches clicks even with `stopPropagation`) |
| **Interactions** | Listens for `input`, `scroll`, `resize` events as breadcrumbs |
| **Performance** | Uses `PerformanceObserver` for long-task, paint, and layout-shift entries |
| **Memory** | Samples `performance.memory` every 10s, flags high usage and rapid growth |
| **Deduplication** | Identical errors increment a counter instead of creating duplicate reports |
| **Rate limiting** | Token-bucket algorithm prevents floods from error loops |
| **Ring buffer** | Fixed-capacity storage prevents memory leaks in long-running apps |
| **Safe teardown** | `destroy()` restores all original APIs cleanly |
---
## Development
```bash
# Install dependencies
npm install
npm install # Install dependencies
npm run build # Build (ESM + CJS + IIFE)
npm test # Run tests
npm run test:watch # Watch mode
npm run typecheck # TypeScript strict check
npm run lint # ESLint
```
# Build (ESM + CJS + IIFE)
npm run build
---
# Run tests
npm test
# Watch mode
npm run test:watch
# Type check
npm run typecheck
# Lint
npm run lint
```
## License
MIT
MIT — do whatever you want.

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display