@lumen-stack/react 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { ReactNode, RefObject } from 'react';
4
- import { LumenUser, ScreenshotCaptureOptions, LumenClient, SubmitPayload, SubmitOptions, SubmitResult } from '@lumen-stack/core';
4
+ import { LumenUser, AmplitudeIdentity, ScreenshotCaptureOptions, LumenClient, SubmitPayload, SubmitOptions, SubmitResult } from '@lumen-stack/core';
5
5
  export { CaptureMetadata, CaptureMethod, CapturePlatform, CaptureResult, FeedbackCategory, LumenClient, LumenError, LumenUser, ScreenshotCaptureMode, ScreenshotCaptureOptions, ScreenshotCaptureProvider, SubmitPayload, SubmitResult } from '@lumen-stack/core';
6
6
 
7
7
  type LumenTriggerPlacement = "br" | "bl" | "tr" | "tl";
@@ -51,6 +51,14 @@ interface LumenProviderProps {
51
51
  /** Override the dashboard origin. Defaults to https://shakebugs.vercel.app. */
52
52
  apiUrl?: string;
53
53
  user?: LumenUser;
54
+ /**
55
+ * Amplitude analytics identity for the current user. When set and the
56
+ * project has the Amplitude integration enabled, Lumen pulls this user's
57
+ * recent event timeline at enrichment time so the AI triage understands
58
+ * what they did before reporting. Pass what your Amplitude instance holds:
59
+ * `amplitude={{ userId: amp.getUserId(), deviceId: amp.getDeviceId(), sessionId: String(amp.getSessionId()) }}`.
60
+ */
61
+ amplitude?: AmplitudeIdentity;
54
62
  /**
55
63
  * @deprecated Use `trigger` instead. `floatingButton={false}` is
56
64
  * equivalent to `trigger={{ kind: "headless" }}`.
@@ -73,7 +81,7 @@ interface LumenProviderProps {
73
81
  capture?: ScreenshotCaptureOptions;
74
82
  children: React.ReactNode;
75
83
  }
76
- declare function LumenProvider({ apiKey, apiUrl, user, floatingButton, trigger, hideOn, theme, portalTarget, capture, children, }: LumenProviderProps): react_jsx_runtime.JSX.Element;
84
+ declare function LumenProvider({ apiKey, apiUrl, user, amplitude, floatingButton, trigger, hideOn, theme, portalTarget, capture, children, }: LumenProviderProps): react_jsx_runtime.JSX.Element;
77
85
 
78
86
  interface FeedbackButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
79
87
  variant?: "default" | "ghost" | "outline";
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { ReactNode, RefObject } from 'react';
4
- import { LumenUser, ScreenshotCaptureOptions, LumenClient, SubmitPayload, SubmitOptions, SubmitResult } from '@lumen-stack/core';
4
+ import { LumenUser, AmplitudeIdentity, ScreenshotCaptureOptions, LumenClient, SubmitPayload, SubmitOptions, SubmitResult } from '@lumen-stack/core';
5
5
  export { CaptureMetadata, CaptureMethod, CapturePlatform, CaptureResult, FeedbackCategory, LumenClient, LumenError, LumenUser, ScreenshotCaptureMode, ScreenshotCaptureOptions, ScreenshotCaptureProvider, SubmitPayload, SubmitResult } from '@lumen-stack/core';
6
6
 
7
7
  type LumenTriggerPlacement = "br" | "bl" | "tr" | "tl";
@@ -51,6 +51,14 @@ interface LumenProviderProps {
51
51
  /** Override the dashboard origin. Defaults to https://shakebugs.vercel.app. */
52
52
  apiUrl?: string;
53
53
  user?: LumenUser;
54
+ /**
55
+ * Amplitude analytics identity for the current user. When set and the
56
+ * project has the Amplitude integration enabled, Lumen pulls this user's
57
+ * recent event timeline at enrichment time so the AI triage understands
58
+ * what they did before reporting. Pass what your Amplitude instance holds:
59
+ * `amplitude={{ userId: amp.getUserId(), deviceId: amp.getDeviceId(), sessionId: String(amp.getSessionId()) }}`.
60
+ */
61
+ amplitude?: AmplitudeIdentity;
54
62
  /**
55
63
  * @deprecated Use `trigger` instead. `floatingButton={false}` is
56
64
  * equivalent to `trigger={{ kind: "headless" }}`.
@@ -73,7 +81,7 @@ interface LumenProviderProps {
73
81
  capture?: ScreenshotCaptureOptions;
74
82
  children: React.ReactNode;
75
83
  }
76
- declare function LumenProvider({ apiKey, apiUrl, user, floatingButton, trigger, hideOn, theme, portalTarget, capture, children, }: LumenProviderProps): react_jsx_runtime.JSX.Element;
84
+ declare function LumenProvider({ apiKey, apiUrl, user, amplitude, floatingButton, trigger, hideOn, theme, portalTarget, capture, children, }: LumenProviderProps): react_jsx_runtime.JSX.Element;
77
85
 
78
86
  interface FeedbackButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
79
87
  variant?: "default" | "ghost" | "outline";
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import {createContext,useContext,useState,useRef,useEffect,useMemo,useCallback,useImperativeHandle,useId}from'react';import {toast}from'sonner';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {createPortal}from'react-dom';var C=class extends Error{constructor(e,t,n){super(e),this.code=t,this.status=n,this.name="LumenError";}code;status},ve=class extends C{constructor(){super("Origin not allowed. Add this origin in your Lumen project settings.","ORIGIN_NOT_ALLOWED",403),this.name="LumenOriginError";}},xe=class extends C{constructor(e){super(`Rate limited \u2014 retry after ${e}s.`,"RATE_LIMITED",429),this.retryAfter=e,this.name="LumenRateLimitError";}retryAfter},X=class extends C{constructor(e){super(e,"NETWORK_ERROR"),this.name="LumenNetworkError";}},bt="https://shakebugs.vercel.app",wt="/api/v1/sdk/submit",yt=new Set([502,503,504]),Re=class{apiKey;apiUrl;user;constructor(e){if(!e.apiKey||!e.apiKey.startsWith("lk_pub_"))throw new C("Invalid Lumen apiKey \u2014 expected a key starting with `lk_pub_`.","INVALID_API_KEY");this.apiKey=e.apiKey,this.apiUrl=(e.apiUrl??bt).replace(/\/$/,""),this.user=e.user;}async submit(e,t={}){let n=`${this.apiUrl}${wt}`,r=this.#e(e),a=null;for(let o=0;o<3;o++){o>0&&await xt(2**o*250);try{return await this.#t(n,r,t)}catch(i){if(a=i,i instanceof ve||i instanceof xe||i instanceof C&&typeof i.status=="number"&&!yt.has(i.status))throw i}}throw a instanceof Error?a:new X("Submit failed after 3 attempts.")}#e(e){let t=new FormData;return e.rawText&&t.append("rawText",e.rawText),e.category&&t.append("category",e.category),e.submitterEmail&&t.append("submitterEmail",e.submitterEmail),e.submitterFingerprint&&t.append("submitterFingerprint",e.submitterFingerprint),t.append("context",JSON.stringify(e.context)),e.screenshot&&t.append("screenshot",e.screenshot,vt(e.screenshot)),e.audio&&t.append("audio",e.audio,"audio"),e.audioDurationMs!=null&&t.append("audioDurationMs",String(e.audioDurationMs)),t}#t(e,t,n){return new Promise((r,a)=>{let o=new XMLHttpRequest;o.open("POST",e,true),o.setRequestHeader("X-Lumen-Api-Key",this.apiKey),o.responseType="text";let{onUploadProgress:i,signal:l}=n;i&&o.upload.addEventListener("progress",d=>{d.lengthComputable&&d.total>0&&i(Math.min(1,d.loaded/d.total));});let s=()=>{o.abort(),a(new X("Submit aborted."));};if(l){if(l.aborted){a(new X("Submit aborted."));return}l.addEventListener("abort",s,{once:true});}o.addEventListener("load",()=>{if(l&&l.removeEventListener("abort",s),o.status===403){a(new ve);return}if(o.status===429){let d=Number(o.getResponseHeader("Retry-After"))||60;a(new xe(d));return}if(o.status<200||o.status>=300){a(new C(Et(o.responseText)??`HTTP ${o.status}`,"HTTP_ERROR",o.status));return}try{let d=JSON.parse(o.responseText);r(d);}catch{a(new C("Malformed response from server.","BAD_RESPONSE"));}}),o.addEventListener("error",()=>{l&&l.removeEventListener("abort",s),a(new X("Network error during submit."));}),o.send(t);})}};function vt(e){return `screenshot.${e.type==="image/jpeg"?"jpg":e.type==="image/webp"?"webp":"png"}`}function xt(e){return new Promise(t=>setTimeout(t,e))}function Et(e){try{let t=JSON.parse(e);return t.error??t.message??null}catch{return e||null}}var kt=2,$=8*1024*1024;async function oe(e={}){Pe();let t=e.mode??"auto";if(e.provider&&(t==="auto"||t==="custom"))try{return Lt(await e.provider(),e)}catch(n){if(t==="custom")throw n;e.onWarning?.(["Custom capture provider failed; falling back to browser DOM capture."]);}if(t==="manual")throw new C("Manual screenshot upload is required for this capture mode.","MANUAL_CAPTURE_REQUIRED");if(t==="true-screen")return ke(e);if(t==="dom")return Ee(e);if(t==="custom")throw new C("`capture.provider` is required when capture mode is `custom`.","CAPTURE_PROVIDER_REQUIRED");try{return await Ee(e)}catch(n){if(Se()){let r=await ke(e);return r.warnings=q(["DOM screenshot failed; used browser screen permission fallback.",...r.warnings]),e.onWarning?.(r.warnings),r}throw n}}function Ae(e,t=[]){Pe();let n=Z();return {blob:e,method:"manual-upload",platform:"web",viewport:n,pixelRatio:window.devicePixelRatio??1,warnings:q(t)}}async function Ee(e){let t=await Ct(),n=e.target??document.documentElement,r=Z(),a=Math.max(1,Math.min(window.devicePixelRatio??1,e.maxScale??kt)),o=Tt(n),i=await t(n,{backgroundColor:null,logging:false,useCORS:true,allowTaint:false,width:r.width,height:r.height,windowWidth:r.width,windowHeight:r.height,scrollX:window.scrollX,scrollY:window.scrollY,x:window.scrollX,y:window.scrollY,scale:a,ignoreElements:s=>s instanceof HTMLElement&&(s.dataset.lumenCaptureIgnore==="true"||!!s.closest("[data-lumen-capture-ignore='true']"))}),l={blob:await Me(i,o),method:"web-dom",platform:"web",viewport:r,pixelRatio:a,warnings:q(o)};return l.warnings.length>0&&e.onWarning?.(l.warnings),l}async function Ct(){let{default:e}=await import('html2canvas-pro');return e}async function ke(e){if(!Se())throw new C("Browser screen capture is unavailable in this environment.","DISPLAY_MEDIA_UNAVAILABLE");let t=await navigator.mediaDevices.getDisplayMedia({video:true,audio:false});try{let n=document.createElement("video");n.muted=!0,n.playsInline=!0,n.srcObject=t,await Rt(n);let r=document.createElement("canvas");r.width=n.videoWidth,r.height=n.videoHeight;let a=r.getContext("2d");if(!a)throw new C("Could not create a drawing context for screen capture.","CANVAS_CONTEXT_UNAVAILABLE");a.drawImage(n,0,0,r.width,r.height);let o=Z(),i=["Browser screen capture uses the window or tab selected by the user."],l={blob:await Me(r,i),method:"web-display-media",platform:"web",viewport:o,pixelRatio:o.width>0?r.width/o.width:void 0,warnings:q(i)};return e.onWarning?.(l.warnings),l}finally{for(let n of t.getTracks())n.stop();}}function Lt(e,t){let n=Z(),r={...e,method:e.method??"custom",platform:e.platform??"custom",viewport:e.viewport??n,pixelRatio:e.pixelRatio??window.devicePixelRatio??1,warnings:q(e.warnings??[])};return r.warnings.length>0&&t.onWarning?.(r.warnings),r}function Tt(e){let t=new Set;e.querySelector("iframe")&&t.add("Embedded iframes may be blank or incomplete in DOM capture."),e.querySelector("video")&&t.add("Video frames may be blank or stale in DOM capture."),e.querySelector("canvas")&&t.add("Canvas/WebGL content may be blank if it is cross-origin tainted."),document.fonts&&document.fonts.status!=="loaded"&&t.add("Web fonts were still loading when the screenshot was captured.");let n=0;for(let r of Array.from(e.querySelectorAll("img"))){let a=r.currentSrc||r.src;if(a)try{new URL(a,window.location.href).origin!==window.location.origin&&!r.crossOrigin&&(n+=1);}catch{}}return n>0&&t.add(`${n} cross-origin image${n===1?"":"s"} without CORS may be omitted from the screenshot.`),Array.from(t)}async function Me(e,t){let n=await Ce(e,"image/png",.92);if(n.size<=$)return n;t.push("Screenshot exceeded the upload cap and was compressed.");let r=e,a=0;for(;n.size>$&&a<6;){let o=Math.max(.35,Math.min(.95,Math.sqrt($/n.size)*.9)),i=document.createElement("canvas");i.width=Math.max(1,Math.round(r.width*o)),i.height=Math.max(1,Math.round(r.height*o));let l=i.getContext("2d");if(!l)return n;l.drawImage(r,0,0,i.width,i.height),r=i;for(let s of [.86,.74,.62,.5])if(n=await Ce(r,"image/jpeg",s),n.size<=$)return n;if(a+=1,i.width<480||i.height<320)break}return n.size>$&&t.push("Screenshot remained large after compression; upload may be rejected."),n}function Ce(e,t,n){return new Promise((r,a)=>{e.toBlob(o=>{if(!o){a(new C("Could not encode screenshot.","ENCODE_FAILED"));return}r(o);},t,n);})}function Z(){let e=window.visualViewport;return {width:Math.round(e?.width??window.innerWidth),height:Math.round(e?.height??window.innerHeight)}}function Se(){return !!navigator.mediaDevices?.getDisplayMedia}async function Rt(e){await new Promise((r,a)=>{let o=()=>r(),i=()=>a(new C("Could not read screen capture video.","VIDEO_FAILED"));e.addEventListener("loadedmetadata",o,{once:true}),e.addEventListener("error",i,{once:true}),e.play().catch(i);});let t=performance.now(),n=1500;for(;e.videoWidth===0||e.videoHeight===0;){if(performance.now()-t>n)throw new C("Screen capture did not produce a frame in time.","VIDEO_TIMEOUT");await new Promise(r=>requestAnimationFrame(()=>r()));}}function Pe(){if(typeof window>"u"||typeof document>"u")throw new C("Screenshot capture can only run in the browser.","INVALID_ENV")}function q(e){return Array.from(new Set(e.filter(Boolean)))}var Ne=[],G=[],Le=false,ne=null;function Ie(e={}){Le||typeof window>"u"||(Le=true,ne=e.ignoreUrlPrefix??null,Pt(),Nt(),It());}function At(){return {consoleLog:Ne.slice(),networkLog:G.slice()}}function J(e,t){e.push(t),e.length>200&&e.splice(0,e.length-200);}function Mt(e){let t=[];for(let r of e){if(typeof r=="string"){t.push(r);continue}if(r instanceof Error){t.push(`${r.name}: ${r.message}${r.stack?`
3
- ${r.stack}`:""}`);continue}try{t.push(JSON.stringify(r,St));}catch{t.push(String(r));}}let n=t.join(" ");return n.length>4096?n.slice(0,4096)+"\u2026[truncated]":n}function St(e,t){return t instanceof Element?`[Element ${t.tagName}]`:typeof t=="function"?"[Function]":t}function Pt(){let e=window.console;if(!e)return;let t=["log","info","warn","error","debug"];for(let n of t){let r=e[n]?.bind(e);r&&(e[n]=(...a)=>{try{J(Ne,{level:n,ts:Date.now(),message:Mt(a)});}catch{}r(...a);});}}function Oe(e){return ne?e.startsWith(ne):false}function Nt(){let e=window.fetch;typeof e=="function"&&(window.fetch=async function(t,n){let r=typeof t=="string"?t:t instanceof URL?t.toString():t.url,a=(n?.method??(t instanceof Request?t.method:"GET")).toUpperCase();if(Oe(r))return e.call(window,t,n);let o=performance.now();try{let i=await e.call(window,t,n);return J(G,{type:"fetch",method:a,url:re(r),status:i.status,ok:i.ok,durationMs:Math.round(performance.now()-o),ts:Date.now()}),i}catch(i){throw J(G,{type:"fetch",method:a,url:re(r),status:0,ok:false,durationMs:Math.round(performance.now()-o),ts:Date.now(),error:i instanceof Error?i.message:"fetch error"}),i}});}function It(){let e=window.XMLHttpRequest;if(!e)return;let t=e.prototype.open,n=e.prototype.send;e.prototype.open=function(r,a,...o){return this.__lumen={method:String(r).toUpperCase(),url:typeof a=="string"?a:a.toString(),t:0},t.call(this,r,a,...o)},e.prototype.send=function(r){let a=this.__lumen;if(a&&!Oe(a.url)){a.t=performance.now();let o=()=>{try{J(G,{type:"xhr",method:a.method,url:re(a.url),status:this.status,ok:this.status>=200&&this.status<400,durationMs:Math.round(performance.now()-a.t),ts:Date.now()});}catch{}this.removeEventListener("loadend",o);};this.addEventListener("loadend",o);}return n.call(this,r??null)};}function re(e){return e.length>512?e.slice(0,512)+"\u2026":e}function De(e){if(typeof window>"u")return {url:"",userAgent:"",viewport:{width:0,height:0},capture:Te(e),consoleLog:[],networkLog:[]};let t=At();return {url:window.location.href,userAgent:navigator.userAgent,viewport:{width:window.innerWidth,height:window.innerHeight},capture:Te(e),device:Ot(),consoleLog:t.consoleLog,networkLog:t.networkLog}}function Ot(){let e={};try{e.screen={width:window.screen?.width??0,height:window.screen?.height??0},e.pixelRatio=window.devicePixelRatio??1,e.language=navigator.language,e.languages=Array.from(navigator.languages??[]),e.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone,e.colorScheme=window.matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light",e.referrer=document.referrer||void 0,e.title=document.title||void 0,e.online=navigator.onLine,performance.getEntriesByType("navigation")[0]&&(e.uptimeMs=Math.round(performance.now()));}catch{}return e}function Te(e){if(e)return {method:e.method,platform:e.platform,viewport:e.viewport,pixelRatio:e.pixelRatio,warnings:e.warnings}}async function He(e=60){if(typeof window>"u"||!navigator.mediaDevices)throw new C("Audio recording requires a browser with MediaDevices.","INVALID_ENV");let t;try{t=await navigator.mediaDevices.getUserMedia({audio:!0});}catch{throw new C("Microphone access denied or unavailable.","MIC_DENIED")}let n=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg;codecs=opus"].find(s=>MediaRecorder.isTypeSupported(s))??"",r=new MediaRecorder(t,n?{mimeType:n}:void 0),a=[],o=performance.now(),i=null;r.addEventListener("dataavailable",s=>{s.data&&s.data.size>0&&a.push(s.data);}),r.start(),i=window.setTimeout(()=>{r.state!=="inactive"&&r.stop();},e*1e3);function l(){i!==null&&window.clearTimeout(i),i=null;for(let s of t.getTracks())s.stop();}return {stream:t,cancel(){try{r.state!=="inactive"&&r.stop();}catch{}l();},stop(){return new Promise((s,d)=>{if(r.state==="inactive"){l(),d(new C("Recorder already stopped.","RECORDER_STOPPED"));return}r.addEventListener("stop",()=>{let g=performance.now()-o,f=r.mimeType||n||"audio/webm",k=new Blob(a,{type:f});l(),s({blob:k,durationMs:g,mimeType:f});},{once:true}),r.stop();})}}}var ae=createContext(null);function K(){let e=useContext(ae);if(!e)throw new Error("useLumen() must be used inside <LumenProvider>.");return e}function _e({screenshot:e,tool:t,color:n="rgb(239, 68, 68)",strokeWidth:r=4,onDrawingChange:a,ref:o}){let i=useRef(null),l=useRef(null),s=useRef(null),[d,g]=useState(null),[f,k]=useState([]),y=useRef(null),b=useRef(false),v=useRef(0),L=useRef(false);useEffect(()=>{let c=false,p=null;return (async()=>{try{let h=await createImageBitmap(e);if(c){h.close?.();return}p=h,g(h);}catch{}})(),()=>{c=true,p?.close?.();}},[e]),useEffect(()=>{if(!d)return;let c=i.current,p=l.current;if(!c||!p)return;c.width=d.width,c.height=d.height,p.width=d.width,p.height=d.height;let h=c.getContext("2d");h&&(h.imageSmoothingEnabled=false,h.drawImage(d,0,0));},[d]),useEffect(()=>{let c=l.current;c&&Q(c,f,y.current);},[f]),useImperativeHandle(o,()=>({hasAnnotations:()=>f.length>0,reset:()=>k([]),undo:()=>k(c=>c.length===0?c:c.slice(0,-1)),async flatten(){let c=y.current,p=c?[...f,c]:f;if(p.length===0||!d)return e;let h=document.createElement("canvas");h.width=d.width,h.height=d.height;let R=h.getContext("2d");if(!R)return e;R.imageSmoothingEnabled=false,R.drawImage(d,0,0);for(let H of p)le(R,H);return await new Promise(H=>{h.toBlob(F=>{H(F??e);},"image/jpeg",.85);})}}),[f,d,e]);function T(c){let p=l.current;if(!p)return {x:0,y:0};let h=p.getBoundingClientRect(),R=p.width/Math.max(h.width,1),H=p.height/Math.max(h.height,1);return {x:(c.clientX-h.left)*R,y:(c.clientY-h.top)*H}}function S(){L.current||(L.current=true,requestAnimationFrame(()=>{L.current=false;let c=l.current;c&&Q(c,f,y.current);}));}function E(c){if(c.button!==void 0&&c.button!==0)return;c.currentTarget.setPointerCapture(c.pointerId),b.current=true,a?.(true);let p=T(c);t==="arrow"?y.current={kind:"arrow",from:p,to:p,color:n,width:r}:t==="rect"?y.current={kind:"rect",from:p,to:p,color:n,width:r}:y.current={kind:"freehand",points:[p],color:n,width:r},v.current=performance.now(),S();}function A(c){if(!b.current||!y.current)return;let p=T(c),h=y.current;if(h.kind==="arrow"||h.kind==="rect")h.to=p;else {let R=h.points[h.points.length-1],H=R?(R.x-p.x)**2+(R.y-p.y)**2:1/0,F=performance.now(),W=F-v.current;(H>16||W>16)&&(h.points.push(p),v.current=F);}S();}function P(){if(!b.current)return;b.current=false,a?.(false);let c=y.current;if(y.current=null,!!c){if(c.kind==="arrow"||c.kind==="rect"){let p=c.to.x-c.from.x,h=c.to.y-c.from.y;if(p*p+h*h<16){let R=l.current;R&&Q(R,f,null);return}}else if(c.points.length<2){let p=l.current;p&&Q(p,f,null);return}k(p=>[...p,c].slice(-50));}}return jsxs("div",{ref:s,className:"lumen-annotate-frame",children:[jsx("canvas",{ref:i}),jsx("canvas",{ref:l,className:"lumen-annotate-overlay",onPointerDown:E,onPointerMove:A,onPointerUp:P,onPointerCancel:P})]})}function Q(e,t,n){let r=e.getContext("2d");if(r){r.clearRect(0,0,e.width,e.height);for(let a of t)le(r,a);n&&le(r,n);}}function le(e,t){if(e.save(),e.strokeStyle=t.color,e.fillStyle=t.color,e.lineWidth=t.width,e.lineCap="round",e.lineJoin="round",t.kind==="rect"){let n=Math.min(t.from.x,t.to.x),r=Math.min(t.from.y,t.to.y),a=Math.abs(t.to.x-t.from.x),o=Math.abs(t.to.y-t.from.y);e.strokeRect(n,r,a,o);}else if(t.kind==="freehand")_t(e,t.points);else {let{from:n,to:r,width:a}=t;e.beginPath(),e.moveTo(n.x,n.y),e.lineTo(r.x,r.y),e.stroke();let o=Math.atan2(r.y-n.y,r.x-n.x),i=Math.max(12,a*4);e.beginPath(),e.moveTo(r.x,r.y),e.lineTo(r.x-i*Math.cos(o-Math.PI/7),r.y-i*Math.sin(o-Math.PI/7)),e.lineTo(r.x-i*Math.cos(o+Math.PI/7),r.y-i*Math.sin(o+Math.PI/7)),e.closePath(),e.fill();}e.restore();}function _t(e,t){if(t.length===0)return;e.beginPath();let n=t[0];if(!n)return;if(e.moveTo(n.x,n.y),t.length===1){e.arc(n.x,n.y,e.lineWidth/2,0,Math.PI*2),e.fill();return}if(t.length===2){let a=t[1];e.lineTo(a.x,a.y),e.stroke();return}for(let a=1;a<t.length-1;a++){let o=t[a],i=t[a+1],l=(o.x+i.x)/2,s=(o.y+i.y)/2;e.quadraticCurveTo(o.x,o.y,l,s);}let r=t[t.length-1];e.lineTo(r.x,r.y),e.stroke();}var se=60,Ue=[{label:"Red",value:"rgb(239, 68, 68)"},{label:"Amber",value:"rgb(245, 158, 11)"},{label:"Blue",value:"rgb(59, 130, 246)"},{label:"Green",value:"rgb(34, 197, 94)"},{label:"Neutral",value:"rgb(244, 244, 245)"}],ze=[{label:"Small",value:2,dot:6},{label:"Medium",value:4,dot:9},{label:"Large",value:6,dot:12}],zt=[{value:"bug",label:"Bug"},{value:"feature",label:"Idea"},{value:"other",label:"Other"}];function de(){let{client:e,isOpen:t,closeCapture:n,user:r,capture:a}=K(),[o,i]=useState({kind:"idle"}),[l,s]=useState("arrow"),[d,g]=useState(Ue[0].value),[f,k]=useState(ze[1].value),[y,b]=useState(""),[v,L]=useState("bug"),[T,S]=useState(r?.email??""),[E,A]=useState(null),[P,c]=useState(null),[p,h]=useState(0),[R,H]=useState(false),F=useRef(null),W=useRef(null),he=useRef(null),V=useRef(false);if(useEffect(()=>{if(t)return V.current=false,i({kind:"capturing"}),b(""),c(null),h(0),(async()=>{if(a?.mode==="manual"){V.current||i({kind:"manual"});return}try{let u=await oe({...a,target:a?.target??document.documentElement});if(V.current)return;ye(u),i({kind:"ready",capture:u});}catch(u){if(V.current)return;i({kind:"manual",error:u instanceof Error?u.message:"Automatic screenshot capture was unavailable."});}})(),()=>{V.current=true;}},[t,a]),useEffect(()=>{if(!t)return;he.current=document.activeElement??null;let u=document.documentElement,w=u.style.overflow,N=u.style.paddingRight,M=window.innerWidth-u.clientWidth;u.style.overflow="hidden",M>0&&(u.style.paddingRight=`${M}px`);let O=false,D=()=>{if(!O){O=true,u.style.overflow=w,u.style.paddingRight=N;try{he.current?.focus?.();}catch{}}};return window.addEventListener("pagehide",D),()=>{window.removeEventListener("pagehide",D),D();}},[t]),useEffect(()=>{if(!t)return;function u(w){if(w.key==="Escape"){w.preventDefault(),n();return}if(w.key!=="Tab")return;let N=W.current;if(!N)return;let M=We(N);if(M.length===0)return;let O=M[0],D=M[M.length-1],te=document.activeElement;w.shiftKey&&(te===O||!N.contains(te))?(w.preventDefault(),D.focus()):!w.shiftKey&&te===D&&(w.preventDefault(),O.focus());}return document.addEventListener("keydown",u),()=>document.removeEventListener("keydown",u)},[t,n]),useEffect(()=>{if(!t||o.kind!=="ready"&&o.kind!=="manual")return;let u=W.current;if(!u)return;let w=We(u);(u.querySelector("textarea.lumen-input")??w[0])?.focus();},[t,o.kind]),useEffect(()=>{if(!t||o.kind!=="manual")return;function u(w){let O=Array.from(w.clipboardData?.items??[]).find(D=>D.type.startsWith("image/"))?.getAsFile();O&&(w.preventDefault(),we(O));}return window.addEventListener("paste",u),()=>window.removeEventListener("paste",u)},[t,o.kind]),useEffect(()=>{if(!E)return;let u=Date.now(),w=window.setInterval(()=>{let N=Math.floor((Date.now()-u)/1e3);h(N),N>=se&&be();},250);return ()=>window.clearInterval(w)},[E]),!t)return null;async function mt(){try{let u=await He(se);A(u);}catch(u){toast.error(u instanceof Error?u.message:"Microphone unavailable");}}async function be(){if(E)try{let u=await E.stop();c({blob:u.blob,durationMs:u.durationMs});}catch(u){toast.error(u instanceof Error?u.message:"Could not stop recording");}finally{A(null);}}function ft(){E?.cancel(),A(null),c(null),h(0);}function we(u){if(!u.type.startsWith("image/")){toast.error("Choose a PNG, JPEG, or WebP screenshot.");return}let w=Ae(u,["Manual screenshot upload used."]);i({kind:"ready",capture:w});}async function pt(){i({kind:"capturing"});try{let u=await oe({...a,mode:"true-screen",target:a?.target??document.documentElement});ye(u),i({kind:"ready",capture:u});}catch(u){i({kind:"manual",error:u instanceof Error?u.message:"Browser screen capture was unavailable."});}}function ye(u){u.warnings.length!==0&&toast.warning("Screenshot captured, but iframe, video, canvas, or cross-origin content may be incomplete.");}async function gt(){if(o.kind!=="ready")return;let u=y.trim();if(!P&&u.length===0){toast.error("Add a voice note or write a description.");return}let{capture:w}=o,N=w.blob;i({kind:"uploading",capture:w,progress:0});try{let M=await F.current?.flatten()??N,O=await e.submit({rawText:u.length>0?u:void 0,category:v,submitterEmail:T.trim()||void 0,screenshot:M,audio:P?.blob,audioDurationMs:P?.durationMs,context:De(w)},{onUploadProgress:D=>{i({kind:"uploading",capture:w,progress:Math.min(.95,D)});}});i({kind:"uploading",capture:w,progress:1}),toast.success("Feedback sent \u2014 thank you."),O.id,n();}catch(M){toast.error(M instanceof Error?M.message:"Could not submit feedback"),i({kind:"ready",capture:w});}}let Y=o.kind==="uploading"?Math.round(o.progress*100):0,j=o.kind==="uploading";function ht(u){u.target===u.currentTarget&&n();}return jsx("div",{role:"dialog","aria-modal":"true","aria-label":"Send feedback",className:"lumen-modal-backdrop","data-lumen-capture-ignore":"true",onMouseDown:ht,children:jsxs("div",{ref:W,className:"lumen-modal","data-lumen-drawing":R?"true":void 0,children:[jsx(Wt,{onDismiss:n}),jsxs("header",{className:"lumen-modal-header",children:[jsxs("h2",{className:"lumen-modal-title",children:[jsx("span",{className:"lumen-modal-title-dot","aria-hidden":"true"}),"Send feedback"]}),jsx("button",{type:"button",onClick:n,className:"lumen-icon-btn","aria-label":"Close",children:"\xD7"})]}),jsxs("div",{className:"lumen-modal-body",children:[o.kind==="capturing"?jsxs("p",{className:"lumen-status",children:[jsx("span",{className:"lumen-spinner","aria-hidden":"true"}),"Capturing screenshot\u2026"]}):null,o.kind==="manual"?jsxs("div",{className:"lumen-manual-capture",children:[jsx("p",{className:"lumen-status",children:o.error?"Automatic screenshot capture was unavailable. Upload or paste a screenshot to continue.":"Upload or paste a screenshot to continue."}),jsxs("label",{className:"lumen-manual-drop",children:[jsx("span",{children:"Choose or paste a screenshot"}),jsx("input",{type:"file",accept:"image/png,image/jpeg,image/webp",onChange:u=>{let w=u.currentTarget.files?.[0];w&&we(w),u.currentTarget.value="";}})]})]}):null,o.kind==="ready"||o.kind==="uploading"?jsxs(Fragment,{children:[jsxs("div",{className:"lumen-toolbar",children:[jsxs("div",{className:"lumen-segmented",role:"group","aria-label":"Annotation tool",children:[jsx(ue,{label:"Arrow",active:l==="arrow",onClick:()=>s("arrow")}),jsx(ue,{label:"Box",active:l==="rect",onClick:()=>s("rect")}),jsx(ue,{label:"Draw",active:l==="freehand",onClick:()=>s("freehand")})]}),jsx("span",{className:"lumen-toolbar-sep"}),jsx("div",{className:"lumen-swatches",role:"group","aria-label":"Color",children:Ue.map(u=>jsx("button",{type:"button",className:"lumen-swatch",style:{background:u.value},"aria-label":u.label,"aria-pressed":d===u.value,onClick:()=>g(u.value)},u.value))}),jsx("div",{className:"lumen-stroke-sizes",role:"group","aria-label":"Stroke width",children:ze.map(u=>jsx("button",{type:"button",className:"lumen-stroke-size","aria-label":u.label,"aria-pressed":f===u.value,onClick:()=>k(u.value),children:jsx("span",{className:"lumen-stroke-size-dot",style:{width:u.dot,height:u.dot}})},u.value))}),jsx("span",{className:"lumen-toolbar-spacer"}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:()=>F.current?.undo(),title:"Undo",children:"Undo"}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:()=>F.current?.reset(),title:"Clear all annotations",children:"Clear"})]}),jsx("div",{className:"lumen-annotate",children:jsx(_e,{ref:F,screenshot:o.capture.blob,tool:l,color:d,strokeWidth:f,onDrawingChange:H})}),jsxs("div",{className:"lumen-form",children:[jsxs("div",{className:"lumen-label",children:[jsx("span",{children:"Category"}),jsx("div",{className:"lumen-category",role:"group","aria-label":"Feedback category",children:zt.map(u=>jsx("button",{type:"button",className:"lumen-category-opt","aria-pressed":v===u.value,onClick:()=>L(u.value),children:u.label},u.value))})]}),jsxs("label",{className:"lumen-label",children:[jsxs("span",{children:["Description ",P?"(optional with audio)":""]}),jsx("textarea",{value:y,onChange:u=>b(u.target.value),rows:3,placeholder:"What happened?",className:"lumen-input"})]}),jsxs("label",{className:"lumen-label",children:[jsx("span",{children:"Your email (optional)"}),jsx("input",{type:"email",value:T,onChange:u=>S(u.target.value),placeholder:"you@example.com",className:"lumen-input"})]}),jsxs("div",{className:"lumen-audio-row",children:[!E&&!P?jsx("button",{type:"button",onClick:mt,className:"lumen-btn-ghost",children:"Record voice note"}):null,E?jsxs(Fragment,{children:[jsxs("span",{className:"lumen-recording",children:[jsx("span",{className:"lumen-rec-dot","aria-hidden":"true"}),p,"s / ",se,"s"]}),jsx("button",{type:"button",onClick:be,className:"lumen-btn-ghost",children:"Stop"}),jsx("button",{type:"button",onClick:ft,className:"lumen-btn-ghost",children:"Cancel"})]}):null,P&&!E?jsxs(Fragment,{children:[jsxs("span",{className:"lumen-audio-meta",children:["Voice note \xB7 ",Math.round(P.durationMs/1e3),"s"]}),jsx("button",{type:"button",onClick:()=>c(null),className:"lumen-btn-ghost",children:"Remove"})]}):null,jsx("span",{className:"lumen-toolbar-spacer"}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:pt,title:"Use the browser's screen capture",children:"Screen capture"}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:()=>i({kind:"manual"}),title:"Upload a screenshot file",children:"Upload"})]})]})]}):null]}),o.kind==="ready"||o.kind==="uploading"?jsxs("footer",{className:"lumen-modal-footer",children:[j?jsx("div",{className:"lumen-progress",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Y,children:jsx("div",{className:"lumen-progress-fill",style:{width:`${Y}%`}})}):null,jsxs("div",{className:"lumen-modal-actions",children:[jsx("button",{type:"button",onClick:n,className:"lumen-btn-ghost",disabled:j,children:"Cancel"}),jsx("button",{type:"button",onClick:gt,className:"lumen-btn-primary",disabled:j,children:j?Y<95?`Uploading ${Y}%\u2026`:"Almost done\u2026":"Send feedback"})]})]}):null]})})}function ue({label:e,active:t,onClick:n}){return jsx("button",{type:"button",onClick:n,className:"lumen-tool","aria-pressed":t,children:e})}function Wt({onDismiss:e}){let t=useRef(null),n=useRef(0),r=useRef(null);function a(l){l.currentTarget.setPointerCapture(l.pointerId),t.current=l.clientY,n.current=performance.now(),r.current=l.currentTarget.parentElement;}function o(l){if(t.current==null||!r.current)return;let s=Math.max(0,l.clientY-t.current);r.current.style.transform=`translateY(${s}px)`;}function i(l){if(t.current==null||!r.current)return;let s=Math.max(0,l.clientY-t.current),d=Math.max(1,performance.now()-n.current),g=s/d;r.current.style.transform="",r.current.style.transition="",t.current=null,(s>80||g>.6)&&e();}return jsx("div",{className:"lumen-modal-grabber","aria-hidden":"true",onPointerDown:a,onPointerMove:o,onPointerUp:i,onPointerCancel:i})}var Vt='a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';function We(e){return Array.from(e.querySelectorAll(Vt)).filter(t=>!t.hasAttribute("disabled")&&t.offsetParent!==null)}function Ve(){if(typeof document>"u"||typeof window>"u")return 0;let e=window.innerWidth,t=window.innerHeight;if(e===0||t===0)return 0;let n=t-4,r=[Math.round(e*.1),Math.round(e*.5),Math.round(e*.9)],a=new Set,o=0;for(let i of r){let l=document.elementsFromPoint(i,n);for(let s of l){if(a.has(s))continue;a.add(s);let d=window.getComputedStyle(s);if(d.position!=="fixed"&&d.position!=="sticky")continue;let g=s.getBoundingClientRect();g.bottom<t-8||g.bottom>t+8||g.width<e*.6||g.height>o&&(o=g.height);}}return o}function me(e,t){if(typeof document>"u"||typeof window>"u")return 0;let n=window.innerWidth,r=window.innerHeight,a=0;for(let o of e){let i;try{i=document.querySelectorAll(o);}catch{continue}for(let l of Array.from(i)){let s=l.getBoundingClientRect();if(s.height===0||s.width===0)continue;let d=0;switch(t){case "bottom":if(s.bottom<r-8)break;d=Math.max(0,r-s.top);break;case "top":if(s.top>8)break;d=Math.max(0,s.bottom);break;case "left":if(s.left>8)break;d=Math.max(0,s.right);break;case "right":if(s.right<n-8)break;d=Math.max(0,n-s.left);break}d>a&&(a=d);}}return a}function $e(e){let[t,n]=useState(()=>({bottom:e.offset.y,right:e.offset.x,left:e.offset.x,top:e.offset.y})),r=useRef(t),a=Yt(e.avoid),o=e.placement,i=e.offset.x,l=e.offset.y;return useEffect(()=>{if(typeof window>"u")return;let s=0,d=false,g=()=>{if(s=0,d)return;let v=o[0]==="b"?"bottom":"top",L=o[1]==="r"?"right":"left",T=0,S=0;e.avoid==="auto"&&v==="bottom"?T=Ve():Array.isArray(e.avoid)&&(T=me(e.avoid,v),S=me(e.avoid,L));let E={bottom:v==="bottom"?l+T:0,top:v==="top"?l+T:0,right:L==="right"?i+S:0,left:L==="left"?i+S:0},A=r.current;(E.bottom!==A.bottom||E.top!==A.top||E.right!==A.right||E.left!==A.left)&&(r.current=E,n(E));},f=()=>{s||(s=window.requestAnimationFrame(g));};f();let k=typeof ResizeObserver<"u"?new ResizeObserver(f):null;k?.observe(document.documentElement);let y=typeof MutationObserver<"u"?new MutationObserver(f):null;y?.observe(document.body,{childList:true,subtree:true,attributes:true,attributeFilter:["class","style","hidden"]}),window.addEventListener("resize",f);let b=window.visualViewport;return b?.addEventListener("resize",f),b?.addEventListener("scroll",f),()=>{d=true,s&&window.cancelAnimationFrame(s),k?.disconnect(),y?.disconnect(),window.removeEventListener("resize",f),b?.removeEventListener("resize",f),b?.removeEventListener("scroll",f);}},[o,i,l,a]),t}function Yt(e){return e===false?"false":e==="auto"?"auto":e.join("|")}function qe(e){let[t,n]=useState(false);return useEffect(()=>{if(!e){n(false);return}if(typeof window>"u")return;let r=window.visualViewport;if(!r||typeof window.matchMedia!="function"||!window.matchMedia("(pointer: coarse)").matches)return;let a=100,o=0,i=()=>{o=0;let s=window.innerHeight-r.height;n(s>a);},l=()=>{o||(o=window.requestAnimationFrame(i));};return l(),r.addEventListener("resize",l),r.addEventListener("scroll",l),()=>{o&&window.cancelAnimationFrame(o),r.removeEventListener("resize",l),r.removeEventListener("scroll",l);}},[e]),t}function Xe({config:e,portalTarget:t,hidden:n,onClick:r}){let[a,o]=useState(null),i=useRef(null),l=$e(e),s=qe(e.hideOnKeyboard);if(useEffect(()=>{typeof document>"u"||o(t??document.body);},[t]),Zt(i,!n&&!s),!a)return null;let d=e.placement,g=d[0]==="b"?"bottom":"top",f=d[1]==="r"?"right":"left",k=g==="bottom"?l.bottom:l.top,y=f==="right"?l.right:l.left,b={position:"fixed",[g]:e.safeArea?`calc(${k}px + env(safe-area-inset-${g}, 0px))`:`${k}px`,[f]:e.safeArea?`calc(${y}px + env(safe-area-inset-${f}, 0px))`:`${y}px`,zIndex:e.zIndex,opacity:n||s?0:1,pointerEvents:n||s?"none":"auto",transition:"opacity 160ms ease"};return createPortal(jsxs("button",{ref:i,type:"button",className:"lumen-btn lumen-btn-primary lumen-btn-floating",style:b,"aria-label":e.label,"aria-hidden":n||s?true:void 0,tabIndex:n||s?-1:0,onClick:r,"data-lumen-trigger":"",children:[e.icon,jsx("span",{children:e.label})]}),a)}function Zt(e,t){let n=useRef(false);useEffect(()=>{if(process.env.NODE_ENV==="production"||!t||n.current||typeof window>"u")return;let r=window.setTimeout(()=>{let a=e.current;if(!a)return;let o=a.getBoundingClientRect();if(o.width===0||o.height===0)return;let i=o.left+o.width/2,l=o.top+o.height/2,s=document.elementsFromPoint(i,l),d=Ke(window.getComputedStyle(a).zIndex);for(let g of s){if(g===a||a.contains(g))continue;if(Ke(window.getComputedStyle(g).zIndex)>d){n.current=true,console.warn("[lumen] trigger is occluded by",g);break}}},250);return ()=>window.clearTimeout(r)},[t,e]);}function Ke(e){let t=parseInt(e,10);return Number.isNaN(t)?0:t}function Ge({mount:e,label:t,icon:n,onClick:r}){let[a,o]=useState(null);return useEffect(()=>{if(typeof document>"u")return;let i=e instanceof HTMLElement?e:e.current??null;o(i);},[e]),a?createPortal(jsxs("button",{type:"button",className:"lumen-btn lumen-btn-primary",onClick:r,"aria-label":t,"data-lumen-trigger":"",children:[n,jsx("span",{children:t})]}),a):null}function Qe({config:e,portalTarget:t,hidden:n,onClick:r}){let[a,o]=useState(null),[i,l]=useState(false),s=useRef(null);if(useEffect(()=>{typeof document>"u"||o(t??document.body);},[t]),!a)return null;let d=`lumen-notch lumen-notch-${e.edge}${i?" lumen-notch-expanded":""}`;function g(b){s.current={x:b.clientX,y:b.clientY},l(true),b.currentTarget.setPointerCapture(b.pointerId);}function f(b){let v=s.current;if(!v)return;let L=b.clientX-v.x,T=b.clientY-v.y;(e.edge==="top"&&T>16||e.edge==="bottom"&&T<-16||e.edge==="right"&&L<-16||e.edge==="left"&&L>16)&&(s.current=null,r());}function k(){s.current=null,l(false);}function y(){s.current=null,l(false);}return createPortal(jsxs("button",{type:"button",className:d,style:{zIndex:e.zIndex,opacity:n?0:1,pointerEvents:n?"none":"auto"},"aria-label":e.label,"aria-hidden":n?true:void 0,tabIndex:n?-1:0,onClick:r,onPointerDown:g,onPointerMove:f,onPointerUp:k,onPointerCancel:y,onMouseEnter:()=>l(true),onMouseLeave:()=>l(false),"data-lumen-trigger":"",children:[jsx("span",{className:"lumen-notch-handle","aria-hidden":"true"}),jsxs("span",{className:"lumen-notch-label",children:[e.icon,e.label]})]}),a)}function et(e){return {kind:"notch",edge:e.edge??"top",label:e.label??"Feedback",icon:e.icon,zIndex:e.zIndex??2147483600}}function tt(e){return {kind:"floating",placement:e.placement??"br",offset:{x:e.offset?.x??16,y:e.offset?.y??16},safeArea:e.safeArea??true,avoid:e.avoid===false?false:e.avoid==null?"auto":Array.isArray(e.avoid)?e.avoid:[e.avoid],hideOnKeyboard:e.hideOnKeyboard??true,zIndex:e.zIndex??2147483600,label:e.label??"Feedback",icon:e.icon}}var fn={"--lumen-bg":"background","--lumen-fg":"foreground","--lumen-primary":"accent","--lumen-radius":"radius"};function nt(e){let t=useId();useEffect(()=>{if(typeof document>"u")return;let n=document.documentElement,r=`data-lumen-theme-${pn(t)}`,a={};if(e==="auto"||e==null)n.removeAttribute("data-lumen-theme");else if(e==="light"||e==="dark")a["data-lumen-theme"]=n.getAttribute("data-lumen-theme"),n.setAttribute("data-lumen-theme",e);else for(let[o,i]of Object.entries(fn)){let l=e[i];typeof l=="string"&&l.length>0&&(a[o]=n.style.getPropertyValue(o)||null,n.style.setProperty(o,l));}return n.setAttribute(r,""),()=>{n.removeAttribute(r);for(let[o,i]of Object.entries(a))o.startsWith("--")?i?n.style.setProperty(o,i):n.style.removeProperty(o):i==null?n.removeAttribute(o):n.setAttribute(o,i);}},[e,t]);}function pn(e){return e.replace(/[^a-zA-Z0-9]/g,"")}var rt=Symbol.for("lumen.history.patched"),fe="lumen:locationchange";function bn(){if(typeof window>"u")return;let e=window;if(e[rt])return;e[rt]=true;let t=()=>window.dispatchEvent(new Event(fe)),n=history.pushState;history.pushState=function(...a){let o=n.apply(this,a);return t(),o};let r=history.replaceState;history.replaceState=function(...a){let o=r.apply(this,a);return t(),o},window.addEventListener("popstate",t);}function ot(e){let[t,n]=useState(false);return useEffect(()=>{if(!e){n(false);return}if(typeof window>"u")return;bn();let r=()=>{try{n(!!e({pathname:window.location.pathname}));}catch{n(false);}};return r(),window.addEventListener(fe,r),window.addEventListener("popstate",r),()=>{window.removeEventListener(fe,r),window.removeEventListener("popstate",r);}},[e]),t}var vn=["wv","Capacitor","Cordova","Expo","FBAN","FBAV","Instagram","Line/","Twitter"];function at(){let[e,t]=useState(false);return useEffect(()=>{if(typeof window>"u")return;let n=window;if(n.ReactNativeWebView){t(true);return}let r=n.webkit;if(r&&r.messageHandlers){t(true);return}let a=navigator.userAgent||"";vn.some(o=>a.includes(o))&&t(true);},[]),e}var lt="lumen.config.v1.",kn=3600*1e3;function st(e,t){let[n,r]=useState(()=>({trigger:null,enabled:true,loading:true}));return useEffect(()=>{if(typeof window>"u")return;let a=Tn(e);a&&r({trigger:a.trigger,enabled:it(a.trigger),loading:false});let o=new AbortController,i=window.setTimeout(()=>o.abort(),5e3),l=`${t.replace(/\/$/,"")}/api/v1/sdk/config?apiKey=${encodeURIComponent(e)}`;return fetch(l,{method:"GET",mode:"cors",credentials:"omit",signal:o.signal}).then(async s=>{if(!s.ok)throw new Error(`HTTP ${s.status}`);let d=await s.json(),g=ut(d.trigger);if(!g)throw new Error("Malformed config response");Rn(e,g),r({trigger:g,enabled:it(g),loading:false});}).catch(()=>{r(s=>s.loading?{trigger:null,enabled:true,loading:false}:s);}).finally(()=>window.clearTimeout(i)),()=>{window.clearTimeout(i),o.abort();}},[e,t]),n}function it(e){return e.kind!=="headless"}var Cn=["br","bl","tr","tl"],Ln=["top","right","bottom","left"];function ut(e){if(!e||typeof e!="object")return null;let t=e;if(t.enabled===false)return {kind:"headless"};let n=typeof t.label=="string"?t.label:"Feedback";return t.kind==="floating"?{kind:"floating",placement:Cn.find(a=>a===t.placement)??"br",label:n}:t.kind==="notch"?{kind:"notch",edge:Ln.find(a=>a===t.edge)??"top",label:n}:null}function Tn(e){try{let t=window.localStorage.getItem(lt+e);if(!t)return null;let n=JSON.parse(t);if(typeof n?.fetchedAt!="number"||Date.now()-n.fetchedAt>kn)return null;let r=ut(n.trigger);return r?{fetchedAt:n.fetchedAt,trigger:r}:null}catch{return null}}function Rn(e,t){try{window.localStorage.setItem(lt+e,JSON.stringify({fetchedAt:Date.now(),trigger:t}));}catch{}}var dt="https://shakebugs.vercel.app";function Mn({apiKey:e,apiUrl:t,user:n,floatingButton:r=true,trigger:a,hideOn:o,theme:i,portalTarget:l,capture:s,children:d}){let[g,f]=useState(false),[k]=useState(false),[y]=useState(null),b=useMemo(()=>new Re({apiKey:e,apiUrl:t,user:n}),[e,t,n?.id,n?.email,n?.name]);useEffect(()=>{Ie({ignoreUrlPrefix:(t??dt).replace(/\/$/,"")});},[t]);let v=useCallback(()=>f(true),[]),L=useCallback(()=>f(false),[]),T=useCallback(b.submit.bind(b),[b]),S=at(),E=ot(o);nt(i);let A=st(a?"":e,t??dt),P=useMemo(()=>({client:b,user:n,isOpen:g,isSubmitting:k,error:y,open:v,close:L,openCapture:v,closeCapture:L,submit:T,isNativeShell:S,capture:s}),[b,n,g,k,y,v,L,T,S,s]),c=Sn({explicit:a,remote:A.trigger,remoteLoading:A.loading,floatingButton:r});return jsxs(ae.Provider,{value:P,children:[d,c?.kind==="floating"?jsx(Xe,{config:tt(c),portalTarget:l,hidden:E,onClick:v}):null,c?.kind==="notch"?jsx(Qe,{config:et(c),portalTarget:l,hidden:E,onClick:v}):null,c?.kind==="inline"?jsx(Ge,{mount:c.mount,label:c.label??"Feedback",icon:c.icon,onClick:v}):null,jsx(de,{})]})}function Sn(e){return e.explicit?e.explicit:e.floatingButton===false?{kind:"headless"}:e.remote?e.remote:e.remoteLoading?null:{kind:"floating"}}function Nn({variant:e="default",floating:t=false,className:n,children:r="Feedback",onClick:a,...o}){let{openCapture:i}=K(),l=["lumen-btn",e==="default"?"lumen-btn-primary":null,e==="ghost"?"lumen-btn-ghost":null,e==="outline"?"lumen-btn-outline":null,t?"lumen-btn-floating":null,n].filter(Boolean).join(" ");return jsx("button",{type:"button",className:l,onClick:s=>{a?.(s),s.defaultPrevented||i();},...o,children:r})}
4
- export{de as CaptureModal,Nn as FeedbackButton,Mn as LumenProvider,K as useLumen};//# sourceMappingURL=index.js.map
2
+ import {createContext,useContext,useState,useRef,useEffect,useMemo,useCallback,useImperativeHandle,useId}from'react';import {toast}from'sonner';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {createPortal}from'react-dom';var R=class extends Error{constructor(e,t,n){super(e),this.code=t,this.status=n,this.name="LumenError";}code;status},Oe=class extends R{constructor(){super("Origin not allowed. Add this origin in your Lumen project settings.","ORIGIN_NOT_ALLOWED",403),this.name="LumenOriginError";}},He=class extends R{constructor(e){super(`Rate limited \u2014 retry after ${e}s.`,"RATE_LIMITED",429),this.retryAfter=e,this.name="LumenRateLimitError";}retryAfter},re=class extends R{constructor(e){super(e,"NETWORK_ERROR"),this.name="LumenNetworkError";}},Ut="https://shakebugs.vercel.app",Wt="/api/v1/sdk/submit",$t=new Set([502,503,504]),Ue=class{apiKey;apiUrl;user;amplitude;constructor(e){if(!e.apiKey||!e.apiKey.startsWith("lk_pub_"))throw new R("Invalid Lumen apiKey \u2014 expected a key starting with `lk_pub_`.","INVALID_API_KEY");this.apiKey=e.apiKey,this.apiUrl=(e.apiUrl??Ut).replace(/\/$/,""),this.user=e.user,this.amplitude=e.amplitude;}async submit(e,t={}){let n=`${this.apiUrl}${Wt}`,o=this.#e(e),r=null;for(let a=0;a<3;a++){a>0&&await Kt(2**a*250);try{return await this.#t(n,o,t)}catch(i){if(r=i,i instanceof Oe||i instanceof He||i instanceof R&&typeof i.status=="number"&&!$t.has(i.status))throw i}}throw r instanceof Error?r:new re("Submit failed after 3 attempts.")}#e(e){let t=new FormData;e.rawText&&t.append("rawText",e.rawText),e.category&&t.append("category",e.category),e.submitterEmail&&t.append("submitterEmail",e.submitterEmail),e.submitterFingerprint&&t.append("submitterFingerprint",e.submitterFingerprint);let n=e.context.amplitude??this.amplitude,o=n?{...e.context,amplitude:n}:e.context;return t.append("context",JSON.stringify(o)),e.screenshot&&t.append("screenshot",e.screenshot,qt(e.screenshot)),e.audio&&t.append("audio",e.audio,"audio"),e.audioDurationMs!=null&&t.append("audioDurationMs",String(e.audioDurationMs)),e.video&&t.append("video",e.video,"video"),e.videoDurationMs!=null&&t.append("videoDurationMs",String(e.videoDurationMs)),t}#t(e,t,n){return new Promise((o,r)=>{let a=new XMLHttpRequest;a.open("POST",e,true),a.setRequestHeader("X-Lumen-Api-Key",this.apiKey),a.responseType="text";let{onUploadProgress:i,signal:s}=n;i&&a.upload.addEventListener("progress",c=>{c.lengthComputable&&c.total>0&&i(Math.min(1,c.loaded/c.total));});let u=()=>{a.abort(),r(new re("Submit aborted."));};if(s){if(s.aborted){r(new re("Submit aborted."));return}s.addEventListener("abort",u,{once:true});}a.addEventListener("load",()=>{if(s&&s.removeEventListener("abort",u),a.status===403){r(new Oe);return}if(a.status===429){let c=Number(a.getResponseHeader("Retry-After"))||60;r(new He(c));return}if(a.status<200||a.status>=300){r(new R(jt(a.responseText)??`HTTP ${a.status}`,"HTTP_ERROR",a.status));return}try{let c=JSON.parse(a.responseText);o(c);}catch{r(new R("Malformed response from server.","BAD_RESPONSE"));}}),a.addEventListener("error",()=>{s&&s.removeEventListener("abort",u),r(new re("Network error during submit."));}),a.send(t);})}};function qt(e){return `screenshot.${e.type==="image/jpeg"?"jpg":e.type==="image/webp"?"webp":"png"}`}function Kt(e){return new Promise(t=>setTimeout(t,e))}function jt(e){try{let t=JSON.parse(e);return t.error??t.message??null}catch{return e||null}}var Yt=2,G=8*1024*1024;async function We(e={}){je();let t=e.mode??"auto";if(e.provider&&(t==="auto"||t==="custom"))try{return Gt(await e.provider(),e)}catch(n){if(t==="custom")throw n;e.onWarning?.(["Custom capture provider failed; falling back to browser DOM capture."]);}if(t==="manual")throw new R("Manual screenshot upload is required for this capture mode.","MANUAL_CAPTURE_REQUIRED");if(t==="true-screen")return Be(e);if(t==="dom")return Fe(e);if(t==="custom")throw new R("`capture.provider` is required when capture mode is `custom`.","CAPTURE_PROVIDER_REQUIRED");try{return await Fe(e)}catch(n){if(Ke()){let o=await Be(e);return o.warnings=J(["DOM screenshot failed; used browser screen permission fallback.",...o.warnings]),e.onWarning?.(o.warnings),o}throw n}}function $e(e,t=[]){je();let n=se();return {blob:e,method:"manual-upload",platform:"web",viewport:n,pixelRatio:window.devicePixelRatio??1,warnings:J(t)}}async function Fe(e){let t=await Xt(),n=e.target??document.documentElement,o=se(),r=Math.max(1,Math.min(window.devicePixelRatio??1,e.maxScale??Yt)),a=Jt(n),i=await t(n,{backgroundColor:null,logging:false,useCORS:true,allowTaint:false,width:o.width,height:o.height,windowWidth:o.width,windowHeight:o.height,scrollX:window.scrollX,scrollY:window.scrollY,x:window.scrollX,y:window.scrollY,scale:r,ignoreElements:u=>u instanceof HTMLElement&&(u.dataset.lumenCaptureIgnore==="true"||!!u.closest("[data-lumen-capture-ignore='true']"))}),s={blob:await qe(i,a),method:"web-dom",platform:"web",viewport:o,pixelRatio:r,warnings:J(a)};return s.warnings.length>0&&e.onWarning?.(s.warnings),s}async function Xt(){let{default:e}=await import('html2canvas-pro');return e}async function Be(e){if(!Ke())throw new R("Browser screen capture is unavailable in this environment.","DISPLAY_MEDIA_UNAVAILABLE");let t=await navigator.mediaDevices.getDisplayMedia({video:true,audio:false});try{let n=document.createElement("video");n.muted=!0,n.playsInline=!0,n.srcObject=t,await Zt(n);let o=document.createElement("canvas");o.width=n.videoWidth,o.height=n.videoHeight;let r=o.getContext("2d");if(!r)throw new R("Could not create a drawing context for screen capture.","CANVAS_CONTEXT_UNAVAILABLE");r.drawImage(n,0,0,o.width,o.height);let a=se(),i=["Browser screen capture uses the window or tab selected by the user."],s={blob:await qe(o,i),method:"web-display-media",platform:"web",viewport:a,pixelRatio:a.width>0?o.width/a.width:void 0,warnings:J(i)};return e.onWarning?.(s.warnings),s}finally{for(let n of t.getTracks())n.stop();}}function Gt(e,t){let n=se(),o={...e,method:e.method??"custom",platform:e.platform??"custom",viewport:e.viewport??n,pixelRatio:e.pixelRatio??window.devicePixelRatio??1,warnings:J(e.warnings??[])};return o.warnings.length>0&&t.onWarning?.(o.warnings),o}function Jt(e){let t=new Set;e.querySelector("iframe")&&t.add("Embedded iframes may be blank or incomplete in DOM capture."),e.querySelector("video")&&t.add("Video frames may be blank or stale in DOM capture."),e.querySelector("canvas")&&t.add("Canvas/WebGL content may be blank if it is cross-origin tainted."),document.fonts&&document.fonts.status!=="loaded"&&t.add("Web fonts were still loading when the screenshot was captured.");let n=0;for(let o of Array.from(e.querySelectorAll("img"))){let r=o.currentSrc||o.src;if(r)try{new URL(r,window.location.href).origin!==window.location.origin&&!o.crossOrigin&&(n+=1);}catch{}}return n>0&&t.add(`${n} cross-origin image${n===1?"":"s"} without CORS may be omitted from the screenshot.`),Array.from(t)}async function qe(e,t){let n=await _e(e,"image/png",.92);if(n.size<=G)return n;t.push("Screenshot exceeded the upload cap and was compressed.");let o=e,r=0;for(;n.size>G&&r<6;){let a=Math.max(.35,Math.min(.95,Math.sqrt(G/n.size)*.9)),i=document.createElement("canvas");i.width=Math.max(1,Math.round(o.width*a)),i.height=Math.max(1,Math.round(o.height*a));let s=i.getContext("2d");if(!s)return n;s.drawImage(o,0,0,i.width,i.height),o=i;for(let u of [.86,.74,.62,.5])if(n=await _e(o,"image/jpeg",u),n.size<=G)return n;if(r+=1,i.width<480||i.height<320)break}return n.size>G&&t.push("Screenshot remained large after compression; upload may be rejected."),n}function _e(e,t,n){return new Promise((o,r)=>{e.toBlob(a=>{if(!a){r(new R("Could not encode screenshot.","ENCODE_FAILED"));return}o(a);},t,n);})}function se(){let e=window.visualViewport;return {width:Math.round(e?.width??window.innerWidth),height:Math.round(e?.height??window.innerHeight)}}function Ke(){return !!navigator.mediaDevices?.getDisplayMedia}async function Zt(e){await new Promise((o,r)=>{let a=()=>o(),i=()=>r(new R("Could not read screen capture video.","VIDEO_FAILED"));e.addEventListener("loadedmetadata",a,{once:true}),e.addEventListener("error",i,{once:true}),e.play().catch(i);});let t=performance.now(),n=1500;for(;e.videoWidth===0||e.videoHeight===0;){if(performance.now()-t>n)throw new R("Screen capture did not produce a frame in time.","VIDEO_TIMEOUT");await new Promise(o=>requestAnimationFrame(()=>o()));}}function je(){if(typeof window>"u"||typeof document>"u")throw new R("Screenshot capture can only run in the browser.","INVALID_ENV")}function J(e){return Array.from(new Set(e.filter(Boolean)))}var Ye=[],ae=[],Ve=false,ge=null;function Xe(e={}){Ve||typeof window>"u"||(Ve=true,ge=e.ignoreUrlPrefix??null,nn(),on(),rn());}function Qt(){return {consoleLog:Ye.slice(),networkLog:ae.slice()}}function ie(e,t){e.push(t),e.length>200&&e.splice(0,e.length-200);}function en(e){let t=[];for(let o of e){if(typeof o=="string"){t.push(o);continue}if(o instanceof Error){t.push(`${o.name}: ${o.message}${o.stack?`
3
+ ${o.stack}`:""}`);continue}try{t.push(JSON.stringify(o,tn));}catch{t.push(String(o));}}let n=t.join(" ");return n.length>4096?n.slice(0,4096)+"\u2026[truncated]":n}function tn(e,t){return t instanceof Element?`[Element ${t.tagName}]`:typeof t=="function"?"[Function]":t}function nn(){let e=window.console;if(!e)return;let t=["log","info","warn","error","debug"];for(let n of t){let o=e[n]?.bind(e);o&&(e[n]=(...r)=>{try{ie(Ye,{level:n,ts:Date.now(),message:en(r)});}catch{}o(...r);});}}function Ge(e){return ge?e.startsWith(ge):false}function on(){let e=window.fetch;typeof e=="function"&&(window.fetch=async function(t,n){let o=typeof t=="string"?t:t instanceof URL?t.toString():t.url,r=(n?.method??(t instanceof Request?t.method:"GET")).toUpperCase();if(Ge(o))return e.call(window,t,n);let a=performance.now();try{let i=await e.call(window,t,n);return ie(ae,{type:"fetch",method:r,url:be(o),status:i.status,ok:i.ok,durationMs:Math.round(performance.now()-a),ts:Date.now()}),i}catch(i){throw ie(ae,{type:"fetch",method:r,url:be(o),status:0,ok:false,durationMs:Math.round(performance.now()-a),ts:Date.now(),error:i instanceof Error?i.message:"fetch error"}),i}});}function rn(){let e=window.XMLHttpRequest;if(!e)return;let t=e.prototype.open,n=e.prototype.send;e.prototype.open=function(o,r,...a){return this.__lumen={method:String(o).toUpperCase(),url:typeof r=="string"?r:r.toString(),t:0},t.call(this,o,r,...a)},e.prototype.send=function(o){let r=this.__lumen;if(r&&!Ge(r.url)){r.t=performance.now();let a=()=>{try{ie(ae,{type:"xhr",method:r.method,url:be(r.url),status:this.status,ok:this.status>=200&&this.status<400,durationMs:Math.round(performance.now()-r.t),ts:Date.now()});}catch{}this.removeEventListener("loadend",a);};this.addEventListener("loadend",a);}return n.call(this,o??null)};}function be(e){return e.length>512?e.slice(0,512)+"\u2026":e}function Je(e){if(typeof window>"u")return {url:"",userAgent:"",viewport:{width:0,height:0},capture:ze(e),consoleLog:[],networkLog:[]};let t=Qt();return {url:window.location.href,userAgent:navigator.userAgent,viewport:{width:window.innerWidth,height:window.innerHeight},capture:ze(e),device:an(),consoleLog:t.consoleLog,networkLog:t.networkLog}}function an(){let e={};try{e.screen={width:window.screen?.width??0,height:window.screen?.height??0},e.pixelRatio=window.devicePixelRatio??1,e.language=navigator.language,e.languages=Array.from(navigator.languages??[]),e.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone,e.colorScheme=window.matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light",e.referrer=document.referrer||void 0,e.title=document.title||void 0,e.online=navigator.onLine,performance.getEntriesByType("navigation")[0]&&(e.uptimeMs=Math.round(performance.now()));}catch{}return e}function ze(e){if(e)return {method:e.method,platform:e.platform,viewport:e.viewport,pixelRatio:e.pixelRatio,warnings:e.warnings}}async function Ze(e=60){if(typeof window>"u"||!navigator.mediaDevices)throw new R("Audio recording requires a browser with MediaDevices.","INVALID_ENV");let t;try{t=await navigator.mediaDevices.getUserMedia({audio:!0});}catch{throw new R("Microphone access denied or unavailable.","MIC_DENIED")}let n=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg;codecs=opus"].find(u=>MediaRecorder.isTypeSupported(u))??"",o=new MediaRecorder(t,n?{mimeType:n}:void 0),r=[],a=performance.now(),i=null;o.addEventListener("dataavailable",u=>{u.data&&u.data.size>0&&r.push(u.data);}),o.start(),i=window.setTimeout(()=>{o.state!=="inactive"&&o.stop();},e*1e3);function s(){i!==null&&window.clearTimeout(i),i=null;for(let u of t.getTracks())u.stop();}return {stream:t,cancel(){try{o.state!=="inactive"&&o.stop();}catch{}s();},stop(){return new Promise((u,c)=>{if(o.state==="inactive"){s(),c(new R("Recorder already stopped.","RECORDER_STOPPED"));return}o.addEventListener("stop",()=>{let f=performance.now()-a,b=o.mimeType||n||"audio/webm",v=new Blob(r,{type:b});s(),u({blob:v,durationMs:f,mimeType:b});},{once:true}),o.stop();})}}}async function Qe(e=60){if(typeof window>"u"||!navigator.mediaDevices||typeof navigator.mediaDevices.getDisplayMedia!="function")throw new R("Screen recording requires a browser with getDisplayMedia.","INVALID_ENV");let t;try{t=await navigator.mediaDevices.getDisplayMedia({video:!0,audio:!0});}catch{throw new R("Screen capture was denied or cancelled.","SCREEN_DENIED")}let n=["video/webm;codecs=vp9,opus","video/webm;codecs=vp8,opus","video/webm","video/mp4"].find(c=>MediaRecorder.isTypeSupported(c))??"",o=new MediaRecorder(t,n?{mimeType:n}:void 0),r=[],a=performance.now(),i=null;o.addEventListener("dataavailable",c=>{c.data&&c.data.size>0&&r.push(c.data);}),o.start(),i=window.setTimeout(()=>{o.state!=="inactive"&&o.stop();},e*1e3);let s=t.getVideoTracks()[0];s&&s.addEventListener("ended",()=>{o.state!=="inactive"&&o.stop();});function u(){i!==null&&window.clearTimeout(i),i=null;for(let c of t.getTracks())c.stop();}return {stream:t,cancel(){try{o.state!=="inactive"&&o.stop();}catch{}u();},stop(){return new Promise((c,f)=>{if(o.state==="inactive"){u(),f(new R("Recorder already stopped.","RECORDER_STOPPED"));return}o.addEventListener("stop",()=>{let b=performance.now()-a,v=o.mimeType||n||"video/webm",x=new Blob(r,{type:v});u(),c({blob:x,durationMs:b,mimeType:v});},{once:true}),o.stop();})}}}var he=createContext(null);function Z(){let e=useContext(he);if(!e)throw new Error("useLumen() must be used inside <LumenProvider>.");return e}function nt({screenshot:e,tool:t,color:n="rgb(239, 68, 68)",strokeWidth:o=4,onDrawingChange:r,ref:a}){let i=useRef(null),s=useRef(null),u=useRef(null),[c,f]=useState(null),[b,v]=useState([]),x=useRef(null),y=useRef(false),E=useRef(0),C=useRef(false);useEffect(()=>{let m=false,p=null;return (async()=>{try{let w=await createImageBitmap(e);if(m){w.close?.();return}p=w,f(w);}catch{}})(),()=>{m=true,p?.close?.();}},[e]),useEffect(()=>{if(!c)return;let m=i.current,p=s.current;if(!m||!p)return;m.width=c.width,m.height=c.height,p.width=c.width,p.height=c.height;let w=m.getContext("2d");w&&(w.imageSmoothingEnabled=false,w.drawImage(c,0,0));},[c]),useEffect(()=>{let m=s.current;m&&le(m,b,x.current);},[b]),useImperativeHandle(a,()=>({hasAnnotations:()=>b.length>0,reset:()=>v([]),undo:()=>v(m=>m.length===0?m:m.slice(0,-1)),async flatten(){let m=x.current,p=m?[...b,m]:b;if(p.length===0||!c)return e;let w=document.createElement("canvas");w.width=c.width,w.height=c.height;let L=w.getContext("2d");if(!L)return e;L.imageSmoothingEnabled=false,L.drawImage(c,0,0);for(let I of p)ve(L,I);return await new Promise(I=>{w.toBlob(O=>{I(O??e);},"image/jpeg",.85);})}}),[b,c,e]);function k(m){let p=s.current;if(!p)return {x:0,y:0};let w=p.getBoundingClientRect(),L=p.width/Math.max(w.width,1),I=p.height/Math.max(w.height,1);return {x:(m.clientX-w.left)*L,y:(m.clientY-w.top)*I}}function M(){C.current||(C.current=true,requestAnimationFrame(()=>{C.current=false;let m=s.current;m&&le(m,b,x.current);}));}function N(m){if(m.button!==void 0&&m.button!==0)return;try{m.currentTarget.setPointerCapture(m.pointerId);}catch{}y.current=true,r?.(true);let p=k(m);t==="arrow"?x.current={kind:"arrow",from:p,to:p,color:n,width:o}:t==="rect"?x.current={kind:"rect",from:p,to:p,color:n,width:o}:x.current={kind:"freehand",points:[p],color:n,width:o},E.current=performance.now(),M();}function S(m){if(!y.current||!x.current)return;let p=k(m),w=x.current;if(w.kind==="arrow"||w.kind==="rect")w.to=p;else {let L=w.points[w.points.length-1],I=L?(L.x-p.x)**2+(L.y-p.y)**2:1/0,O=performance.now(),j=O-E.current;(I>16||j>16)&&(w.points.push(p),E.current=O);}M();}function D(){if(!y.current)return;y.current=false,r?.(false);let m=x.current;if(x.current=null,!!m){if(m.kind==="arrow"||m.kind==="rect"){let p=m.to.x-m.from.x,w=m.to.y-m.from.y;if(p*p+w*w<16){let L=s.current;L&&le(L,b,null);return}}else if(m.points.length<2){let p=s.current;p&&le(p,b,null);return}v(p=>[...p,m].slice(-50));}}return jsxs("div",{ref:u,className:"lumen-annotate-frame",children:[jsx("canvas",{ref:i}),jsx("canvas",{ref:s,className:"lumen-annotate-overlay",onPointerDown:N,onPointerMove:S,onPointerUp:D,onPointerCancel:D})]})}function le(e,t,n){let o=e.getContext("2d");if(o){o.clearRect(0,0,e.width,e.height);for(let r of t)ve(o,r);n&&ve(o,n);}}function ve(e,t){if(e.save(),e.strokeStyle=t.color,e.fillStyle=t.color,e.lineWidth=t.width,e.lineCap="round",e.lineJoin="round",t.kind==="rect"){let n=Math.min(t.from.x,t.to.x),o=Math.min(t.from.y,t.to.y),r=Math.abs(t.to.x-t.from.x),a=Math.abs(t.to.y-t.from.y);e.strokeRect(n,o,r,a);}else if(t.kind==="freehand")dn(e,t.points);else {let{from:n,to:o,width:r}=t;e.beginPath(),e.moveTo(n.x,n.y),e.lineTo(o.x,o.y),e.stroke();let a=Math.atan2(o.y-n.y,o.x-n.x),i=Math.max(12,r*4);e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(o.x-i*Math.cos(a-Math.PI/7),o.y-i*Math.sin(a-Math.PI/7)),e.lineTo(o.x-i*Math.cos(a+Math.PI/7),o.y-i*Math.sin(a+Math.PI/7)),e.closePath(),e.fill();}e.restore();}function dn(e,t){if(t.length===0)return;e.beginPath();let n=t[0];if(!n)return;if(e.moveTo(n.x,n.y),t.length===1){e.arc(n.x,n.y,e.lineWidth/2,0,Math.PI*2),e.fill();return}if(t.length===2){let r=t[1];e.lineTo(r.x,r.y),e.stroke();return}for(let r=1;r<t.length-1;r++){let a=t[r],i=t[r+1],s=(a.x+i.x)/2,u=(a.y+i.y)/2;e.quadraticCurveTo(a.x,a.y,s,u);}let o=t[t.length-1];e.lineTo(o.x,o.y),e.stroke();}var ye=60,pn=60,ot=[{label:"Red",value:"rgb(239, 68, 68)"},{label:"Amber",value:"rgb(245, 158, 11)"},{label:"Blue",value:"rgb(59, 130, 246)"},{label:"Green",value:"rgb(34, 197, 94)"},{label:"Neutral",value:"rgb(244, 244, 245)"}],rt=[{label:"Small",value:2,dot:6},{label:"Medium",value:4,dot:9},{label:"Large",value:6,dot:12}],at=[{value:"bug",label:"Bug"},{value:"feature",label:"Idea"},{value:"other",label:"Other"}],fn=[{value:"shot",label:"Screenshot",hint:"This page, instantly"},{value:"screen",label:"Screen",hint:"Pick a window or tab"},{value:"video",label:"Video",hint:"Record up to 60s"}];function Ee(){let{client:e,isOpen:t,closeCapture:n,user:o,capture:r}=Z(),[a,i]=useState(1),[s,u]=useState(null),[c,f]=useState({kind:"idle"}),[b,v]=useState(false),[x,y]=useState(0),[E,C]=useState(null),[k,M]=useState("arrow"),[N,S]=useState(ot[0].value),[D,m]=useState(rt[1].value),[p,w]=useState(""),[L,I]=useState("bug"),[O,j]=useState(o?.email??""),[A,q]=useState(null),[B,Y]=useState(null),[St,de]=useState(0),[K,Q]=useState(null),[U,me]=useState(null),[At,Pt]=useState(false),ee=useRef(null),Te=useRef(null),Me=useRef(null),X=useRef(false);if(useEffect(()=>{if(t)return X.current=false,i(1),u(null),w(""),Y(null),de(0),me(null),v(false),y(0),C(null),Q(l=>(l?.cancel(),null)),f(r?.mode==="manual"?{kind:"manual"}:{kind:"idle"}),()=>{X.current=true;}},[t,r]),useEffect(()=>{if(!t)return;Me.current=document.activeElement??null;let l=document.documentElement,h=l.style.overflow,P=l.style.paddingRight,H=window.innerWidth-l.clientWidth;l.style.overflow="hidden",H>0&&(l.style.paddingRight=`${H}px`);let F=false,_=()=>{if(!F){F=true,l.style.overflow=h,l.style.paddingRight=P;try{Me.current?.focus?.();}catch{}}};return window.addEventListener("pagehide",_),()=>{window.removeEventListener("pagehide",_),_();}},[t]),useEffect(()=>{if(!t)return;function l(h){if(h.key==="Escape"){h.preventDefault(),n();return}if(h.key!=="Tab")return;let P=Te.current;if(!P)return;let H=En(P);if(H.length===0)return;let F=H[0],_=H[H.length-1],fe=document.activeElement;h.shiftKey&&(fe===F||!P.contains(fe))?(h.preventDefault(),_.focus()):!h.shiftKey&&fe===_&&(h.preventDefault(),F.focus());}return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[t,n]),useEffect(()=>{if(!t||c.kind!=="manual")return;function l(h){let F=Array.from(h.clipboardData?.items??[]).find(_=>_.type.startsWith("image/"))?.getAsFile();F&&(h.preventDefault(),Se(F));}return window.addEventListener("paste",l),()=>window.removeEventListener("paste",l)},[t,c.kind]),useEffect(()=>{if(!A)return;let l=Date.now(),h=window.setInterval(()=>{let P=Math.floor((Date.now()-l)/1e3);de(P),P>=ye&&Pe();},250);return ()=>window.clearInterval(h)},[A]),!t)return null;async function pe(l){X.current=false,f({kind:"capturing"});try{let h=await We({...r,mode:l,target:r?.target??document.documentElement});return X.current?!1:(It(h),f({kind:"ready",capture:h}),!0)}catch(h){return X.current||f({kind:"manual",error:h instanceof Error?h.message:"Automatic screenshot capture was unavailable."}),false}}async function Ne(l){u(l),C(null),l!=="video"&&De(),l==="shot"?await pe(r?.mode??"auto"):l==="screen"?await pe("true-screen"):await pe(r?.mode??"auto")&&await Ie();}function Se(l){if(!l.type.startsWith("image/")){toast.error("Choose a PNG, JPEG, or WebP screenshot.");return}let h=$e(l,["Manual screenshot upload used."]);f({kind:"ready",capture:h});}function It(l){l.warnings.length!==0&&toast.warning("Screenshot captured, but iframe, video, canvas, or cross-origin content may be incomplete.");}async function Ae(){try{let l=await Ze(ye);q(l);}catch(l){toast.error(l instanceof Error?l.message:"Microphone unavailable");}}async function Pe(){if(A)try{let l=await A.stop();Y({blob:l.blob,durationMs:l.durationMs});}catch(l){toast.error(l instanceof Error?l.message:"Could not stop recording");}finally{q(null);}}function Dt(){A?.cancel(),q(null),Y(null),de(0);}async function Ie(){try{let l=await Qe(pn);Q(l),l.stream.getVideoTracks()[0]?.addEventListener("ended",()=>{te();});}catch(l){toast.error(l instanceof Error?l.message:"Screen capture unavailable");}}async function te(){if(!K)return;let l=K;Q(null);try{let h=await l.stop();me({blob:h.blob,durationMs:h.durationMs});}catch(h){toast.error(h instanceof Error?h.message:"Could not stop recording");}}function De(){K?.cancel(),Q(null),me(null);}let Ot=c.kind==="ready";async function Ht(){if(a===1){if(K&&await te(),c.kind==="ready"){let l=await ee.current?.flatten();C(l??c.capture.blob);}i(2);}else a===2?i(3):await Bt();}function Ft(){a>1&&i(l=>l-1);}async function Bt(){if(c.kind!=="ready")return;let l=p.trim(),{capture:h}=c;v(true),y(0);try{let P=E??h.blob,H=await e.submit({rawText:l.length>0?l:void 0,category:L,submitterEmail:O.trim()||void 0,screenshot:P,audio:B?.blob,audioDurationMs:B?.durationMs,video:U?.blob,videoDurationMs:U?.durationMs,context:Je(h)},{onUploadProgress:F=>y(Math.min(.95,F))});y(1),toast.success("Feedback sent \u2014 thank you."),H.id,n();}catch(P){toast.error(P instanceof Error?P.message:"Could not submit feedback"),v(false);}}function _t(l){l.target===l.currentTarget&&!b&&n();}let ne=Math.round(x*100),oe=s==="video",Vt=a===1&&!Ot||b,zt=a<3?"Next":b?ne<95?`Uploading ${ne}%\u2026`:"Almost done\u2026":"Send feedback";return jsx("div",{role:"dialog","aria-modal":"true","aria-label":"Send feedback",className:"lumen-modal-backdrop","data-lumen-capture-ignore":"true",onMouseDown:_t,children:jsxs("div",{ref:Te,className:"lumen-modal","data-lumen-drawing":At?"true":void 0,children:[jsx(bn,{onDismiss:n}),jsxs("header",{className:"lumen-modal-header",children:[jsxs("h2",{className:"lumen-modal-title",children:[jsx("span",{className:"lumen-modal-title-dot","aria-hidden":"true"}),"Send feedback"]}),jsx("button",{type:"button",onClick:n,className:"lumen-icon-btn","aria-label":"Close",children:"\xD7"})]}),jsx(gn,{step:a}),jsxs("div",{className:"lumen-modal-body",children:[a===1?jsxs("div",{className:"lumen-pane",children:[jsx("div",{className:"lumen-method",role:"group","aria-label":"Capture method",children:fn.map(l=>jsxs("button",{type:"button",className:"lumen-method-btn","aria-pressed":s===l.value,onClick:()=>Ne(l.value),disabled:c.kind==="capturing",children:[jsx("span",{className:"lumen-method-label",children:l.label}),jsx("span",{className:"lumen-method-hint",children:l.hint})]},l.value))}),c.kind==="idle"?jsxs("div",{className:"lumen-cap-empty",children:[jsx("p",{children:"Pick a capture method above \u2014 nothing is captured until you choose, so take your time positioning the screen."}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:()=>f({kind:"manual"}),children:"Or upload a screenshot"})]}):null,c.kind==="capturing"?jsxs("p",{className:"lumen-status",children:[jsx("span",{className:"lumen-spinner","aria-hidden":"true"}),"Capturing\u2026"]}):null,c.kind==="manual"?jsxs("div",{className:"lumen-manual-capture",children:[jsx("p",{className:"lumen-status",children:c.error?"Automatic capture was unavailable. Upload or paste a screenshot to continue.":"Upload or paste a screenshot to continue."}),jsxs("label",{className:"lumen-manual-drop",children:[jsx("span",{children:"Choose or paste a screenshot"}),jsx("input",{type:"file",accept:"image/png,image/jpeg,image/webp",onChange:l=>{let h=l.currentTarget.files?.[0];h&&Se(h),l.currentTarget.value="";}})]})]}):null,c.kind==="ready"?jsxs(Fragment,{children:[oe?null:jsxs("div",{className:"lumen-toolbar",children:[jsxs("div",{className:"lumen-segmented",role:"group","aria-label":"Annotation tool",children:[jsx(xe,{label:"Arrow",active:k==="arrow",onClick:()=>M("arrow")}),jsx(xe,{label:"Box",active:k==="rect",onClick:()=>M("rect")}),jsx(xe,{label:"Draw",active:k==="freehand",onClick:()=>M("freehand")})]}),jsx("span",{className:"lumen-toolbar-sep"}),jsx("div",{className:"lumen-swatches",role:"group","aria-label":"Color",children:ot.map(l=>jsx("button",{type:"button",className:"lumen-swatch",style:{background:l.value},"aria-label":l.label,"aria-pressed":N===l.value,onClick:()=>S(l.value)},l.value))}),jsx("div",{className:"lumen-stroke-sizes",role:"group","aria-label":"Stroke width",children:rt.map(l=>jsx("button",{type:"button",className:"lumen-stroke-size","aria-label":l.label,"aria-pressed":D===l.value,onClick:()=>m(l.value),children:jsx("span",{className:"lumen-stroke-size-dot",style:{width:l.dot,height:l.dot}})},l.value))}),jsx("span",{className:"lumen-toolbar-spacer"}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:()=>ee.current?.undo(),children:"Undo"}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:()=>ee.current?.reset(),children:"Clear"})]}),jsx("div",{className:"lumen-annotate",children:jsx(nt,{ref:ee,screenshot:c.capture.blob,tool:k,color:N,strokeWidth:D,onDrawingChange:Pt})}),jsxs("div",{className:"lumen-cap-actions",children:[jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:()=>s&&Ne(s),children:oe?"\u21BB Re-record":"\u21BB Recapture"}),oe?K?jsxs("span",{className:"lumen-recording",children:[jsx("span",{className:"lumen-rec-dot","aria-hidden":"true"}),jsx("span",{className:"lumen-rec-time",children:"Recording\u2026"}),jsx("button",{type:"button",className:"lumen-btn-ghost",onClick:te,children:"Stop"})]}):U?jsxs("span",{className:"lumen-cap-note",children:["\u2713 ",Math.round(U.durationMs/1e3),"s recorded"]}):null:jsxs("span",{className:"lumen-cap-note",children:[it(s)," captured \xB7 switch method above anytime"]})]})]}):null]}):null,a===2?jsxs("div",{className:"lumen-pane lumen-form",children:[jsxs("label",{className:"lumen-label",children:[jsx("span",{children:"What happened?"}),jsx("textarea",{value:p,onChange:l=>w(l.target.value),rows:3,placeholder:"Describe the issue or idea\u2026",className:"lumen-input",autoFocus:true})]}),jsxs("div",{className:"lumen-label",children:[jsx("span",{children:"Add a voice note (optional)"}),jsxs("div",{className:"lumen-audio-row",children:[!A&&!B?jsx("button",{type:"button",onClick:Ae,className:"lumen-btn-ghost",children:"Record voice note"}):null,A?jsxs(Fragment,{children:[jsxs("span",{className:"lumen-recording",children:[jsx("span",{className:"lumen-rec-dot","aria-hidden":"true"}),jsx(hn,{stream:A.stream}),jsxs("span",{className:"lumen-rec-time",children:[St,"s / ",ye,"s"]})]}),jsx("button",{type:"button",onClick:Pe,className:"lumen-btn-ghost",children:"Stop"}),jsx("button",{type:"button",onClick:Dt,className:"lumen-btn-ghost",children:"Cancel"})]}):null,B&&!A?jsxs(Fragment,{children:[jsx(vn,{blob:B.blob,durationMs:B.durationMs}),jsx("button",{type:"button",onClick:()=>Y(null),className:"lumen-btn-ghost",children:"Remove"})]}):null]})]}),jsxs("div",{className:"lumen-label",children:[jsx("span",{children:"Category"}),jsx("div",{className:"lumen-category",role:"group","aria-label":"Feedback category",children:at.map(l=>jsx("button",{type:"button",className:"lumen-category-opt","aria-pressed":L===l.value,onClick:()=>I(l.value),children:l.label},l.value))})]}),jsxs("label",{className:"lumen-label",children:[jsx("span",{children:"Your email (optional)"}),jsx("input",{type:"email",value:O,onChange:l=>j(l.target.value),placeholder:"you@example.com",className:"lumen-input"})]})]}):null,a===3?jsxs("div",{className:"lumen-pane lumen-review",children:[jsxs("div",{className:"lumen-review-row",children:[jsx("span",{className:"lumen-review-k",children:"Capture"}),jsxs("span",{className:"lumen-review-v",children:[it(s),oe?"":" \xB7 annotated",jsx("button",{type:"button",className:"lumen-edit",onClick:()=>i(1),children:"edit"})]})]}),jsxs("div",{className:"lumen-review-row",children:[jsx("span",{className:"lumen-review-k",children:"Category"}),jsxs("span",{className:"lumen-review-v",children:[jsx("span",{className:"lumen-chip",children:at.find(l=>l.value===L)?.label}),jsx("button",{type:"button",className:"lumen-edit",onClick:()=>i(2),children:"edit"})]})]}),jsxs("div",{className:"lumen-review-row",children:[jsx("span",{className:"lumen-review-k",children:"Description"}),jsxs("span",{className:"lumen-review-v",children:[p.trim()?p.trim():jsx("span",{className:"lumen-muted-empty",children:"\u2014"}),jsx("button",{type:"button",className:"lumen-edit",onClick:()=>i(2),children:"edit"})]})]}),jsxs("div",{className:"lumen-review-row",children:[jsx("span",{className:"lumen-review-k",children:"Material"}),jsxs("span",{className:"lumen-review-v lumen-attach-row",children:[B?jsxs("span",{className:"lumen-attach",children:["\u{1F399} Voice ",Math.round(B.durationMs/1e3),"s",jsx("button",{type:"button",className:"lumen-att-x","aria-label":"Remove voice note",onClick:()=>Y(null),children:"\xD7"})]}):null,U?jsxs("span",{className:"lumen-attach",children:["\u25B6 Video ",Math.round(U.durationMs/1e3),"s",jsx("button",{type:"button",className:"lumen-att-x","aria-label":"Remove video",onClick:De,children:"\xD7"})]}):null,O.trim()?jsxs("span",{className:"lumen-attach",children:["\u2709 ",O.trim()]}):null,!B&&!A?jsx("button",{type:"button",className:"lumen-btn-ghost lumen-add-btn",onClick:()=>{i(2),Ae();},children:"+ Voice note"}):null,K?jsxs(Fragment,{children:[jsxs("span",{className:"lumen-attach",children:[jsx("span",{className:"lumen-rec-dot","aria-hidden":"true"}),"Recording\u2026"]}),jsx("button",{type:"button",className:"lumen-btn-ghost lumen-add-btn",onClick:te,children:"Stop"})]}):U?null:jsx("button",{type:"button",className:"lumen-btn-ghost lumen-add-btn",onClick:Ie,children:"+ Screen recording"})]})]})]}):null]}),jsxs("footer",{className:"lumen-modal-footer",children:[b?jsx("div",{className:"lumen-progress",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":ne,children:jsx("div",{className:"lumen-progress-fill",style:{width:`${ne}%`}})}):null,jsxs("div",{className:"lumen-modal-actions",children:[jsx("button",{type:"button",onClick:a===1?n:Ft,className:"lumen-btn-ghost",disabled:b,children:a===1?"Cancel":"Back"}),jsx("button",{type:"button",onClick:Ht,className:"lumen-btn-primary",disabled:Vt,children:zt})]})]})]})})}function it(e){return e==="video"?"Screen recording":e==="screen"?"Screen capture":"Screenshot"}function gn({step:e}){let t=[{n:1,label:"Capture"},{n:2,label:"Describe"},{n:3,label:"Review"}];return jsx("div",{className:"lumen-stepper","aria-hidden":"true",children:t.map((n,o)=>jsxs("div",{className:"lumen-step"+(e===n.n?" lumen-step-active":"")+(e>n.n?" lumen-step-done":""),children:[jsx("span",{className:"lumen-step-num",children:n.n}),jsx("span",{className:"lumen-step-lbl",children:n.label}),o<t.length-1?jsx("span",{className:"lumen-step-bar"}):null]},n.n))})}function xe({label:e,active:t,onClick:n}){return jsx("button",{type:"button",onClick:n,className:"lumen-tool","aria-pressed":t,children:e})}function bn({onDismiss:e}){let t=useRef(null),n=useRef(0),o=useRef(null);function r(s){s.currentTarget.setPointerCapture(s.pointerId),t.current=s.clientY,n.current=performance.now(),o.current=s.currentTarget.parentElement;}function a(s){if(t.current==null||!o.current)return;let u=Math.max(0,s.clientY-t.current);o.current.style.transform=`translateY(${u}px)`;}function i(s){if(t.current==null||!o.current)return;let u=Math.max(0,s.clientY-t.current),c=Math.max(1,performance.now()-n.current),f=u/c;o.current.style.transform="",o.current.style.transition="",t.current=null,(u>80||f>.6)&&e();}return jsx("div",{className:"lumen-modal-grabber","aria-hidden":"true",onPointerDown:r,onPointerMove:a,onPointerUp:i,onPointerCancel:i})}function hn({stream:e}){let t=useRef(null);return useEffect(()=>{let n=t.current;if(!n)return;let o=Math.min(window.devicePixelRatio||1,2),r=n.clientWidth||88,a=n.clientHeight||22;n.width=Math.round(r*o),n.height=Math.round(a*o);let i=n.getContext("2d");if(!i)return;i.scale(o,o);let s=window.AudioContext??window.webkitAudioContext;if(!s)return;let u=new s,c=u.createMediaStreamSource(e),f=u.createAnalyser();f.fftSize=1024,f.smoothingTimeConstant=.6,c.connect(f);let b=new Uint8Array(f.fftSize),v=18,x=3,y=3,E=Math.max(2,(r-x*(v-1))/v),C=Math.min(E/2,3),k=new Array(v).fill(0),M=0,N=false;function S(){if(N)return;f.getByteTimeDomainData(b);let D=Math.floor(b.length/v);i.clearRect(0,0,r,a),i.fillStyle=yn("--lumen-danger")||"rgb(239,68,68)";for(let m=0;m<v;m++){let p=0;for(let A=0;A<D;A++){let q=Math.abs((b[m*D+A]??128)-128);q>p&&(p=q);}let w=Math.min(1,p/128*1.8),L=k[m]??0;k[m]=w>L?w:L+(w-L)*.35;let I=Math.max(y,k[m]*a),O=m*(E+x),j=(a-I)/2;wn(i,O,j,E,I,C),i.fill();}M=requestAnimationFrame(S);}return M=requestAnimationFrame(S),()=>{N=true,cancelAnimationFrame(M);try{c.disconnect();}catch{}u.close();}},[e]),jsx("canvas",{ref:t,className:"lumen-waveform","aria-hidden":"true"})}function wn(e,t,n,o,r,a){let i=Math.min(a,o/2,r/2);e.beginPath();let s=e;if(typeof s.roundRect=="function"){s.roundRect(t,n,o,r,i);return}e.moveTo(t+i,n),e.arcTo(t+o,n,t+o,n+r,i),e.arcTo(t+o,n+r,t,n+r,i),e.arcTo(t,n+r,t,n,i),e.arcTo(t,n,t+o,n,i),e.closePath();}function vn({blob:e,durationMs:t}){let[n,o]=useState("");return useEffect(()=>{let r=URL.createObjectURL(e);return o(r),()=>{URL.revokeObjectURL(r);}},[e]),jsxs("div",{className:"lumen-audio-preview",children:[jsx("audio",{controls:true,preload:"metadata",src:n,className:"lumen-audio-el"}),jsxs("span",{className:"lumen-audio-meta",children:[Math.round(t/1e3),"s"]})]})}function yn(e){return typeof window>"u"?"":getComputedStyle(document.documentElement).getPropertyValue(e).trim()}var xn='a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';function En(e){return Array.from(e.querySelectorAll(xn)).filter(t=>!t.hasAttribute("disabled")&&t.offsetParent!==null)}function st(){if(typeof document>"u"||typeof window>"u")return 0;let e=window.innerWidth,t=window.innerHeight;if(e===0||t===0)return 0;let n=t-4,o=[Math.round(e*.1),Math.round(e*.5),Math.round(e*.9)],r=new Set,a=0;for(let i of o){let s=document.elementsFromPoint(i,n);for(let u of s){if(r.has(u))continue;r.add(u);let c=window.getComputedStyle(u);if(c.position!=="fixed"&&c.position!=="sticky")continue;let f=u.getBoundingClientRect();f.bottom<t-8||f.bottom>t+8||f.width<e*.6||f.height>a&&(a=f.height);}}return a}function Ce(e,t){if(typeof document>"u"||typeof window>"u")return 0;let n=window.innerWidth,o=window.innerHeight,r=0;for(let a of e){let i;try{i=document.querySelectorAll(a);}catch{continue}for(let s of Array.from(i)){let u=s.getBoundingClientRect();if(u.height===0||u.width===0)continue;let c=0;switch(t){case "bottom":if(u.bottom<o-8)break;c=Math.max(0,o-u.top);break;case "top":if(u.top>8)break;c=Math.max(0,u.bottom);break;case "left":if(u.left>8)break;c=Math.max(0,u.right);break;case "right":if(u.right<n-8)break;c=Math.max(0,n-u.left);break}c>r&&(r=c);}}return r}function lt(e){let[t,n]=useState(()=>({bottom:e.offset.y,right:e.offset.x,left:e.offset.x,top:e.offset.y})),o=useRef(t),r=Rn(e.avoid),a=e.placement,i=e.offset.x,s=e.offset.y;return useEffect(()=>{if(typeof window>"u")return;let u=0,c=false,f=()=>{if(u=0,c)return;let E=a[0]==="b"?"bottom":"top",C=a[1]==="r"?"right":"left",k=0,M=0;e.avoid==="auto"&&E==="bottom"?k=st():Array.isArray(e.avoid)&&(k=Ce(e.avoid,E),M=Ce(e.avoid,C));let N={bottom:E==="bottom"?s+k:0,top:E==="top"?s+k:0,right:C==="right"?i+M:0,left:C==="left"?i+M:0},S=o.current;(N.bottom!==S.bottom||N.top!==S.top||N.right!==S.right||N.left!==S.left)&&(o.current=N,n(N));},b=()=>{u||(u=window.requestAnimationFrame(f));};b();let v=typeof ResizeObserver<"u"?new ResizeObserver(b):null;v?.observe(document.documentElement);let x=typeof MutationObserver<"u"?new MutationObserver(b):null;x?.observe(document.body,{childList:true,subtree:true,attributes:true,attributeFilter:["class","style","hidden"]}),window.addEventListener("resize",b);let y=window.visualViewport;return y?.addEventListener("resize",b),y?.addEventListener("scroll",b),()=>{c=true,u&&window.cancelAnimationFrame(u),v?.disconnect(),x?.disconnect(),window.removeEventListener("resize",b),y?.removeEventListener("resize",b),y?.removeEventListener("scroll",b);}},[a,i,s,r]),t}function Rn(e){return e===false?"false":e==="auto"?"auto":e.join("|")}function ut(e){let[t,n]=useState(false);return useEffect(()=>{if(!e){n(false);return}if(typeof window>"u")return;let o=window.visualViewport;if(!o||typeof window.matchMedia!="function"||!window.matchMedia("(pointer: coarse)").matches)return;let r=100,a=0,i=()=>{a=0;let u=window.innerHeight-o.height;n(u>r);},s=()=>{a||(a=window.requestAnimationFrame(i));};return s(),o.addEventListener("resize",s),o.addEventListener("scroll",s),()=>{a&&window.cancelAnimationFrame(a),o.removeEventListener("resize",s),o.removeEventListener("scroll",s);}},[e]),t}function pt({config:e,portalTarget:t,hidden:n,onClick:o}){let[r,a]=useState(null),i=useRef(null),s=lt(e),u=ut(e.hideOnKeyboard);if(useEffect(()=>{typeof document>"u"||a(t??document.body);},[t]),An(i,!n&&!u),!r)return null;let c=e.placement,f=c[0]==="b"?"bottom":"top",b=c[1]==="r"?"right":"left",v=f==="bottom"?s.bottom:s.top,x=b==="right"?s.right:s.left,y={position:"fixed",[f]:e.safeArea?`calc(${v}px + env(safe-area-inset-${f}, 0px))`:`${v}px`,[b]:e.safeArea?`calc(${x}px + env(safe-area-inset-${b}, 0px))`:`${x}px`,zIndex:e.zIndex,opacity:n||u?0:1,pointerEvents:n||u?"none":"auto",transition:"opacity 160ms ease"};return createPortal(jsxs("button",{ref:i,type:"button",className:"lumen-btn lumen-btn-primary lumen-btn-floating",style:y,"aria-label":e.label,"aria-hidden":n||u?true:void 0,tabIndex:n||u?-1:0,onClick:o,"data-lumen-trigger":"","data-lumen-capture-ignore":"true",children:[e.icon,jsx("span",{children:e.label})]}),r)}function An(e,t){let n=useRef(false);useEffect(()=>{if(process.env.NODE_ENV==="production"||!t||n.current||typeof window>"u")return;let o=window.setTimeout(()=>{let r=e.current;if(!r)return;let a=r.getBoundingClientRect();if(a.width===0||a.height===0)return;let i=a.left+a.width/2,s=a.top+a.height/2,u=document.elementsFromPoint(i,s),c=ct(window.getComputedStyle(r).zIndex);for(let f of u){if(f===r||r.contains(f))continue;if(ct(window.getComputedStyle(f).zIndex)>c){n.current=true,console.warn("[lumen] trigger is occluded by",f);break}}},250);return ()=>window.clearTimeout(o)},[t,e]);}function ct(e){let t=parseInt(e,10);return Number.isNaN(t)?0:t}function ft({mount:e,label:t,icon:n,onClick:o}){let[r,a]=useState(null);return useEffect(()=>{if(typeof document>"u")return;let i=e instanceof HTMLElement?e:e.current??null;a(i);},[e]),r?createPortal(jsxs("button",{type:"button",className:"lumen-btn lumen-btn-primary",onClick:o,"aria-label":t,"data-lumen-trigger":"","data-lumen-capture-ignore":"true",children:[n,jsx("span",{children:t})]}),r):null}function ht({config:e,portalTarget:t,hidden:n,onClick:o}){let[r,a]=useState(null),[i,s]=useState(false),u=useRef(null);if(useEffect(()=>{typeof document>"u"||a(t??document.body);},[t]),!r)return null;let c=`lumen-notch lumen-notch-${e.edge}${i?" lumen-notch-expanded":""}`;function f(y){u.current={x:y.clientX,y:y.clientY},s(true),y.currentTarget.setPointerCapture(y.pointerId);}function b(y){let E=u.current;if(!E)return;let C=y.clientX-E.x,k=y.clientY-E.y;(e.edge==="top"&&k>16||e.edge==="bottom"&&k<-16||e.edge==="right"&&C<-16||e.edge==="left"&&C>16)&&(u.current=null,o());}function v(){u.current=null,s(false);}function x(){u.current=null,s(false);}return createPortal(jsxs("button",{type:"button",className:c,style:{zIndex:e.zIndex,opacity:n?0:1,pointerEvents:n?"none":"auto"},"aria-label":e.label,"aria-hidden":n?true:void 0,tabIndex:n?-1:0,onClick:o,onPointerDown:f,onPointerMove:b,onPointerUp:v,onPointerCancel:x,onMouseEnter:()=>s(true),onMouseLeave:()=>s(false),"data-lumen-trigger":"","data-lumen-capture-ignore":"true",children:[jsx("span",{className:"lumen-notch-handle","aria-hidden":"true"}),jsxs("span",{className:"lumen-notch-label",children:[e.icon,e.label]})]}),r)}function wt(e){return {kind:"notch",edge:e.edge??"top",label:e.label??"Feedback",icon:e.icon,zIndex:e.zIndex??2147483600}}function vt(e){return {kind:"floating",placement:e.placement??"br",offset:{x:e.offset?.x??16,y:e.offset?.y??16},safeArea:e.safeArea??true,avoid:e.avoid===false?false:e.avoid==null?"auto":Array.isArray(e.avoid)?e.avoid:[e.avoid],hideOnKeyboard:e.hideOnKeyboard??true,zIndex:e.zIndex??2147483600,label:e.label??"Feedback",icon:e.icon}}var qn={"--lumen-bg":"background","--lumen-fg":"foreground","--lumen-primary":"accent","--lumen-radius":"radius"};function yt(e){let t=useId();useEffect(()=>{if(typeof document>"u")return;let n=document.documentElement,o=`data-lumen-theme-${Kn(t)}`,r={};if(e==="auto"||e==null)n.removeAttribute("data-lumen-theme");else if(e==="light"||e==="dark")r["data-lumen-theme"]=n.getAttribute("data-lumen-theme"),n.setAttribute("data-lumen-theme",e);else for(let[a,i]of Object.entries(qn)){let s=e[i];typeof s=="string"&&s.length>0&&(r[a]=n.style.getPropertyValue(a)||null,n.style.setProperty(a,s));}return n.setAttribute(o,""),()=>{n.removeAttribute(o);for(let[a,i]of Object.entries(r))a.startsWith("--")?i?n.style.setProperty(a,i):n.style.removeProperty(a):i==null?n.removeAttribute(a):n.setAttribute(a,i);}},[e,t]);}function Kn(e){return e.replace(/[^a-zA-Z0-9]/g,"")}var xt=Symbol.for("lumen.history.patched"),ke="lumen:locationchange";function Xn(){if(typeof window>"u")return;let e=window;if(e[xt])return;e[xt]=true;let t=()=>window.dispatchEvent(new Event(ke)),n=history.pushState;history.pushState=function(...r){let a=n.apply(this,r);return t(),a};let o=history.replaceState;history.replaceState=function(...r){let a=o.apply(this,r);return t(),a},window.addEventListener("popstate",t);}function Et(e){let[t,n]=useState(false);return useEffect(()=>{if(!e){n(false);return}if(typeof window>"u")return;Xn();let o=()=>{try{n(!!e({pathname:window.location.pathname}));}catch{n(false);}};return o(),window.addEventListener(ke,o),window.addEventListener("popstate",o),()=>{window.removeEventListener(ke,o),window.removeEventListener("popstate",o);}},[e]),t}var Zn=["wv","Capacitor","Cordova","Expo","FBAN","FBAV","Instagram","Line/","Twitter"];function Ct(){let[e,t]=useState(false);return useEffect(()=>{if(typeof window>"u")return;let n=window;if(n.ReactNativeWebView){t(true);return}let o=n.webkit;if(o&&o.messageHandlers){t(true);return}let r=navigator.userAgent||"";Zn.some(a=>r.includes(a))&&t(true);},[]),e}var Lt="lumen.config.v1.",to=3600*1e3;function Rt(e,t){let[n,o]=useState(()=>({trigger:null,enabled:true,loading:true}));return useEffect(()=>{if(typeof window>"u")return;let r=ro(e);r&&o({trigger:r.trigger,enabled:kt(r.trigger),loading:false});let a=new AbortController,i=window.setTimeout(()=>a.abort(),5e3),s=`${t.replace(/\/$/,"")}/api/v1/sdk/config?apiKey=${encodeURIComponent(e)}`;return fetch(s,{method:"GET",mode:"cors",credentials:"omit",signal:a.signal}).then(async u=>{if(!u.ok)throw new Error(`HTTP ${u.status}`);let c=await u.json(),f=Tt(c.trigger);if(!f)throw new Error("Malformed config response");ao(e,f),o({trigger:f,enabled:kt(f),loading:false});}).catch(()=>{o(u=>u.loading?{trigger:null,enabled:true,loading:false}:u);}).finally(()=>window.clearTimeout(i)),()=>{window.clearTimeout(i),a.abort();}},[e,t]),n}function kt(e){return e.kind!=="headless"}var no=["br","bl","tr","tl"],oo=["top","right","bottom","left"];function Tt(e){if(!e||typeof e!="object")return null;let t=e;if(t.enabled===false)return {kind:"headless"};let n=typeof t.label=="string"?t.label:"Feedback";return t.kind==="floating"?{kind:"floating",placement:no.find(r=>r===t.placement)??"br",label:n}:t.kind==="notch"?{kind:"notch",edge:oo.find(r=>r===t.edge)??"top",label:n}:null}function ro(e){try{let t=window.localStorage.getItem(Lt+e);if(!t)return null;let n=JSON.parse(t);if(typeof n?.fetchedAt!="number"||Date.now()-n.fetchedAt>to)return null;let o=Tt(n.trigger);return o?{fetchedAt:n.fetchedAt,trigger:o}:null}catch{return null}}function ao(e,t){try{window.localStorage.setItem(Lt+e,JSON.stringify({fetchedAt:Date.now(),trigger:t}));}catch{}}var Nt="https://shakebugs.vercel.app";function so({apiKey:e,apiUrl:t,user:n,amplitude:o,floatingButton:r=true,trigger:a,hideOn:i,theme:s,portalTarget:u,capture:c,children:f}){let[b,v]=useState(false),[x]=useState(false),[y]=useState(null),E=useMemo(()=>new Ue({apiKey:e,apiUrl:t,user:n,amplitude:o}),[e,t,n?.id,n?.email,n?.name,o?.userId,o?.deviceId,o?.sessionId]);useEffect(()=>{Xe({ignoreUrlPrefix:(t??Nt).replace(/\/$/,"")});},[t]);let C=useCallback(()=>v(true),[]),k=useCallback(()=>v(false),[]),M=useCallback(E.submit.bind(E),[E]),N=Ct(),S=Et(i);yt(s);let D=Rt(a?"":e,t??Nt),m=useMemo(()=>({client:E,user:n,isOpen:b,isSubmitting:x,error:y,open:C,close:k,openCapture:C,closeCapture:k,submit:M,isNativeShell:N,capture:c}),[E,n,b,x,y,C,k,M,N,c]),p=lo({explicit:a,remote:D.trigger,remoteLoading:D.loading,floatingButton:r});return jsxs(he.Provider,{value:m,children:[f,p?.kind==="floating"?jsx(pt,{config:vt(p),portalTarget:u,hidden:S,onClick:C}):null,p?.kind==="notch"?jsx(ht,{config:wt(p),portalTarget:u,hidden:S,onClick:C}):null,p?.kind==="inline"?jsx(ft,{mount:p.mount,label:p.label??"Feedback",icon:p.icon,onClick:C}):null,jsx(Ee,{})]})}function lo(e){return e.explicit?e.explicit:e.floatingButton===false?{kind:"headless"}:e.remote?e.remote:e.remoteLoading?null:{kind:"floating"}}function co({variant:e="default",floating:t=false,className:n,children:o="Feedback",onClick:r,...a}){let{openCapture:i}=Z(),s=["lumen-btn",e==="default"?"lumen-btn-primary":null,e==="ghost"?"lumen-btn-ghost":null,e==="outline"?"lumen-btn-outline":null,t?"lumen-btn-floating":null,n].filter(Boolean).join(" ");return jsx("button",{type:"button",className:s,onClick:u=>{r?.(u),u.defaultPrevented||i();},...a,children:o})}
4
+ export{Ee as CaptureModal,co as FeedbackButton,so as LumenProvider,Z as useLumen};//# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map