@lightworkai.official/debug-capture 0.6.0 → 0.7.1

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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- var M2={maxRequests:60,maxConsoleEntries:120,maxActions:80,maxBodyChars:20000},L=null;function C2($){L=$}function B(){if(!L)throw Error("[debug-capture] configureDebugCapture() has not been called");return L}function F0(){return L!==null}function x(){let $=B().app;return{name:$.name,version:$.version??"0.0.0",environment:$.environment??U2()}}function U2(){if(typeof window>"u")return"unknown";let $=window.location.hostname;if($==="localhost"||$==="127.0.0.1"||$.endsWith(".local"))return"development";return"production"}function E($){let j=L?.capture?.[$];return typeof j==="number"?j:M2[$]}function $1($){let j=L?.module;if(!j)return null;try{return j($)??null}catch{return null}}function $0(){let $=L?.redact;return{headers:$?.headers??[],queryKeys:($?.queryKeys??[]).map((j)=>j.toLowerCase()),bodyKeys:($?.bodyKeys??[]).map((j)=>j.toLowerCase())}}function j1(){return L?.capture?.overlaySelectors??[]}function J1($){if(typeof window>"u")return!1;let j;try{j=new URL($,window.location.href)}catch{return!1}if(P2(j))return!1;if(j.origin===window.location.origin)return!0;return(L?.capture?.bodyOrigins??[]).some((J)=>{try{return new URL(J).origin===j.origin}catch{return!1}})}function P2($){if(!L?.host)return!1;try{if(new URL(L.host).origin!==$.origin)return!1}catch{return!1}return $.pathname.startsWith("/ingest/")}var v="‹redacted›",w2=/^(authorization|proxy-authorization|cookie|set-cookie|x-[a-z-]*token|x-csrf[a-z-]*|x-xsrf[a-z-]*)$/i,I2=new Set(["access_token","token","id_token","refresh_token","code","secret","client_secret","password","apikey","api_key","signature","x-amz-signature","x-amz-credential"]),D2=/(password|passwd|token|secret|authorization|refresh|client_secret|otp|pin)/i,B2=/[\w.+-]+@[\w-]+\.[\w.-]+/g,N2=/\d(?:[\d\s-]{7,})\d/g;function g($){return $.replace(B2,v).replace(N2,v)}function q2($){if(w2.test($))return!0;return $0().headers.some((J)=>J.toLowerCase()===$.toLowerCase())}function m($){let j={};for(let[J,Q]of Object.entries($))j[J]=q2(J)?v:Q;return j}function y($){try{let j=/^https?:\/\//i.test($),J=new URL($,j?void 0:"http://local.invalid"),Q=!1;if(J.searchParams.forEach((Z,z)=>{if(I2.has(z.toLowerCase())||$0().queryKeys.includes(z.toLowerCase()))J.searchParams.set(z,v),Q=!0}),!Q)return $;return j?J.toString():`${J.pathname}${J.search}`}catch{return $}}function H0($,j){if(j>6||$===null||typeof $!=="object")return $;if(Array.isArray($))return $.map((Q)=>H0(Q,j+1));let J={};for(let[Q,Z]of Object.entries($)){let z=D2.test(Q)||$0().bodyKeys.some((V)=>Q.toLowerCase().includes(V));J[Q]=z?v:H0(Z,j+1)}return J}function b($,j){if($==null)return null;let J=$,Q=$.trim();if(Q.startsWith("{")||Q.startsWith("["))try{let Z=JSON.parse(Q);J=JSON.stringify(H0(Z,0))}catch{}if(J.length>j)return`${J.slice(0,j)}… [truncated ${J.length-j} chars]`;return J}var M0=120,C0=40,d=($,j)=>$.length>j?`${$.slice(0,j)}…`:$,U0=($)=>{try{return decodeURIComponent($)}catch{return $}},u=[],Q1=0,Z1=!1;function n($,j,J,Q){let Z=d(j,M0),z=u[u.length-1];if($==="navigate"&&z?.kind==="click"){let Y=Z.replace(/^ไปที่\s*/,"");if(z.detail.includes(`→ ${Y}`))return z.at=new Date().toISOString(),z;let F=Y.split(/[?#]/)[0]??Y,C=z.source?U0(z.source.replace(/^→\s*/,"")).split(/[?#]/)[0]:null;if(C&&(F===C||F.startsWith(C)))return z.detail=d(`${z.detail} → ${Y}`,M0),z.source=void 0,z.at=new Date().toISOString(),z}if(z&&z.kind===$&&z.detail===Z){if(z.at=new Date().toISOString(),$!=="navigate")z.count=(z.count??1)+1;return z}Q1+=1;let V={id:`act_${Q1}`,at:new Date().toISOString(),kind:$,detail:Z,count:1,source:J,html:J0(Q)};u.push(V);while(u.length>E("maxActions"))S2(u.shift());return V}var R2=200000,r=0;function J0($){if(!$)return;if(r+$.length>R2)return;return r+=$.length,$}function S2($){if(!$)return;if(r-=($.html?.length??0)+($.afterHtml?.length??0),r<0)r=0}function P0($){return $&&$>1?` (×${$})`:""}function j0($){return $ instanceof Element&&Boolean($.closest("[data-debug-reporter]"))}var O2='button, a[href], [role="button"], [role="tab"], [role="menuitem"], [role="option"], [role="switch"], [role="checkbox"], [role="radio"], [role="link"], summary, input, select, textarea',_2={button:"ปุ่ม",a:"ลิงก์",input:"ช่อง",textarea:"ช่อง",select:"ตัวเลือก",summary:"ส่วนขยาย"},z1={button:"ปุ่ม",tab:"แท็บ",menuitem:"เมนู",option:"ตัวเลือก",switch:"สวิตช์",checkbox:"ช่องเลือก",radio:"ตัวเลือก",link:"ลิงก์"};function f2($){let j=$.getAttribute("role");if(j&&z1[j])return z1[j];return _2[$.tagName.toLowerCase()]??"ปุ่ม"}function L2($,j){try{let J=$,Q=0;while(J&&Q<=j){let Z=G1(J);if(Z&&typeof Z.memoizedProps?.onClick==="function")return J;J=J.parentElement,Q+=1}}catch{}return null}function k2($){let j=$.getAttribute("aria-label")?.trim();if(j)return j;let J=$.getAttribute("title")?.trim();if(J)return J;if($ instanceof HTMLInputElement||$ instanceof HTMLTextAreaElement||$ instanceof HTMLSelectElement)return($.getAttribute("placeholder")||$.getAttribute("name")||"").trim();if($ instanceof HTMLImageElement)return($.getAttribute("alt")||"").trim();let Q=($.textContent??"").replace(/\s+/g," ").trim();if(Q)return Q;if($ instanceof HTMLAnchorElement){let Z=$.getAttribute("href");if(Z?.startsWith("/"))return U0(Z)}return""}function A2($){if(!($ instanceof Element))return null;let j=$.closest(O2)??L2($,4);if(!j)return null;let J=j.tagName.toLowerCase();if(J==="html"||J==="body")return null;return j}function T2($){let j=g(k2($));if(!j)return null;return`${f2($)} “${d(j,C0)}”`}var Y1=6000,x2=4000,E2=/(?:^|\s)!?(?:fixed|absolute|sticky|inset-\S+|z-\S+|top-\S+|bottom-\S+|left-\S+|right-\S+|w-screen|h-screen|min-h-screen|max-h-screen|translate-\S+|scale-\S+)(?=\s|$)/g;function p2($){$.querySelectorAll("script, style, link, iframe, object, embed, noscript, canvas, video, audio").forEach((Z)=>Z.remove());let j=[$,...Array.from($.querySelectorAll("*"))];for(let Z of j){for(let V of Array.from(Z.attributes)){let Y=V.name.toLowerCase();if(Y.startsWith("on")||Y==="srcdoc"||Y==="value"||Y.startsWith("data-"))Z.removeAttribute(V.name)}if(Z instanceof HTMLAnchorElement)Z.setAttribute("href","#");if(Z instanceof HTMLImageElement)Z.removeAttribute("src");let z=Z.getAttribute("class");if(z){let V=z.replace(E2," ").replace(/\s+/g," ").trim();if(V)Z.setAttribute("class",V);else Z.removeAttribute("class")}}let J=document.createTreeWalker($,NodeFilter.SHOW_TEXT),Q=J.nextNode();while(Q){if(Q.nodeValue)Q.nodeValue=g(Q.nodeValue);Q=J.nextNode()}}function w0($,j,J){try{let Q=$.outerHTML;if(!Q||Q.length>j)return;let Z=$.cloneNode(!0);p2(Z);let z=Z.outerHTML;return z&&z.length<=J?z:void 0}catch{return}}var h2=($)=>w0($,Y1,x2),v2=150000,g2=40000,W1=($)=>w0($,v2,g2);function m2($){if(!($ instanceof HTMLInputElement)&&!($ instanceof HTMLTextAreaElement)&&!($ instanceof HTMLSelectElement))return null;let j=$.name||$.id||$.getAttribute("aria-label")||$.getAttribute("placeholder")||$.tagName.toLowerCase();return`ช่อง “${g(j)}”`}var V1=80;function G1($){let j=Object.keys($).find((J)=>J.startsWith("__reactFiber$")||J.startsWith("__reactInternalInstance$"));return j?$[j]:null}function y2($){if(typeof $!=="function")return null;try{let j=Function.prototype.toString.call($);return(j.match(/\.(?:push|replace)\(\s*['"`]([^'"`]+)['"`]/)??j.match(/redirect\(\s*['"`]([^'"`]+)['"`]/))?.[1]??null}catch{return null}}function K1($){if(!$)return;return`→ ${$.length>V1?`${$.slice(0,V1)}…`:$}`}function b2($){try{let j=$.closest("a[href]")?.getAttribute("href");if(j&&j.startsWith("/"))return K1(j);let J=G1($),Q=0;while(J&&Q<30){if(typeof J.memoizedProps?.onClick==="function")return K1(y2(J.memoizedProps.onClick));J=J.return,Q+=1}return}catch{return}}var u2='[role="dialog"], [role="alertdialog"], [role="menu"], [role="listbox"], [role="status"], [role="alert"]';function d2(){let $=j1();return $.length?$.join(", "):u2}function c2($){let j=$.getAttribute("role");if(j==="status"||j==="alert")return"ข้อความแจ้งเตือน";if(j==="menu")return"เมนู";if(j==="listbox")return"รายการตัวเลือก";if(j==="alertdialog")return"กล่องยืนยัน";return"กล่องโต้ตอบ"}function i2($){let j=$.getAttribute("aria-label")?.trim();if(j)return j;let J=$.getAttribute("aria-labelledby");if(J){let z=J.split(/\s+/).map((V)=>document.getElementById(V)?.textContent?.trim()??"").filter(Boolean).join(" ");if(z)return z}let Z=$.querySelector('[data-slot="dialog-title"], h1, h2, h3, [role="heading"]')?.textContent?.replace(/\s+/g," ").trim();if(Z)return Z;return($.textContent??"").replace(/\s+/g," ").trim()}function F1($){let j=g(i2($)),J=c2($);return j?`เปิด ${J} “${d(j,C0)}”`:`เปิด ${J}`}var o2='[aria-busy="true"], [role="progressbar"], [data-loading="true"], .animate-pulse, .animate-spin',l2=/กำลังโหลด|กำลังค้นหา|กำลังดำเนินการ|\bloading\b/i;function n2($){if($.querySelector(o2))return!0;return l2.test($.textContent??"")}var r2=400,s2=250,a2=8000;function t2($,j){if(typeof MutationObserver>"u"){j.html=J0(W1($));return}let J=Date.now(),Q=!1,Z=()=>{Q=!0,V.disconnect(),window.clearInterval(Y),window.clearTimeout(F)},z=()=>{if(Q)return;if(Z(),!$.isConnected)return;j.detail=d(F1($),M0),j.html=J0(W1($))},V=new MutationObserver(()=>{J=Date.now()});V.observe($,{childList:!0,subtree:!0,attributes:!0,characterData:!0});let Y=window.setInterval(()=>{if(Q)return;if(!$.isConnected){Z();return}if(Date.now()-J>=r2&&!n2($))z()},s2),F=window.setTimeout(z,a2)}function e2($){if(j0($))return;let j=n("ui",F1($));if(j)t2($,j)}function $4(){if(typeof MutationObserver>"u")return;let $=new WeakSet;new MutationObserver((J)=>{for(let Q of J)for(let Z of Array.from(Q.addedNodes)){if(!(Z instanceof Element))continue;let z=d2(),V=Z.matches(z)?[Z]:Array.from(Z.querySelectorAll(z));for(let Y of V){if($.has(Y))continue;$.add(Y),e2(Y)}}}).observe(document.body,{childList:!0,subtree:!0})}var j4=1600,J4=2500;function X1($){return{disabled:$.hasAttribute("disabled")||$.getAttribute("aria-disabled")==="true",busy:$.getAttribute("aria-busy")==="true",text:d(($.textContent??"").replace(/\s+/g," ").trim(),C0)}}function Q4($,j){if(!$.disabled&&j.disabled)return"ปุ่มถูกปิดใช้งานหลังคลิก";if(!$.busy&&j.busy)return"ปุ่มเข้าสู่สถานะกำลังโหลด";if($.text!==j.text&&j.text)return`ข้อความเปลี่ยนเป็น “${j.text}”`;return null}function Z4($,j){if(typeof MutationObserver>"u")return;let J=X1($),Q=!1,Z=(Y,F)=>{if(Q)return;if(Q=!0,z.disconnect(),window.clearTimeout(V),j.afterNote=Y,F)j.afterHtml=J0(w0($,Y1,J4))},z=new MutationObserver(()=>{if(!$.isConnected){Z("องค์ประกอบหายไปจากหน้าจอ",!1);return}let Y=Q4(J,X1($));if(Y)Z(Y,!0)});z.observe($,{attributes:!0,attributeFilter:["disabled","aria-disabled","aria-busy","class"],childList:!0,subtree:!0,characterData:!0});let V=window.setTimeout(()=>{if(!Q&&!$.isConnected){Z("องค์ประกอบหายไปจากหน้าจอ",!1);return}Q=!0,z.disconnect()},j4)}function H1(){if(Z1||typeof window>"u")return;Z1=!0,document.addEventListener("click",(Q)=>{if(j0(Q.target))return;let Z=A2(Q.target);if(!Z)return;let z=T2(Z);if(!z)return;let V=n("click",`คลิก ${z}`,b2(Z),h2(Z));if(V)Z4(Z,V)},{capture:!0,passive:!0}),document.addEventListener("change",(Q)=>{if(j0(Q.target))return;let Z=m2(Q.target);if(Z)n("input",`แก้ไข ${Z}`)},{capture:!0,passive:!0}),document.addEventListener("submit",(Q)=>{if(j0(Q.target))return;n("submit","ส่งฟอร์ม")},{capture:!0,passive:!0});let $=()=>n("navigate",`ไปที่ ${U0(y(location.pathname+location.search))}`),j=history.pushState.bind(history),J=history.replaceState.bind(history);history.pushState=(...Q)=>{let Z=j(...Q);return $(),Z},history.replaceState=(...Q)=>{let Z=J(...Q);return $(),Z},window.addEventListener("popstate",$),$4()}function I0(){return u.map(($)=>({...$}))}var M1=2000,Q0=[],C1=0,U1=!1;function D0($,j){C1+=1,Q0.push({id:`log_${C1}`,at:new Date().toISOString(),level:$,message:j.length>M1?`${j.slice(0,M1)}…`:j});while(Q0.length>E("maxConsoleEntries"))Q0.shift()}function z4(){let $=new WeakSet;return(j,J)=>{if(typeof J==="object"&&J!==null){if($.has(J))return"[Circular]";$.add(J)}if(typeof J==="bigint")return J.toString();return J}}function P1($){if(typeof $==="string")return $;if($ instanceof Error)return`${$.name}: ${$.message}`;try{return JSON.stringify($,z4())??String($)}catch{return String($)}}function w1(){if(U1||typeof window>"u")return;U1=!0;let $=["log","info","warn","error","debug"];for(let j of $){let J=console[j].bind(console);console[j]=(...Q)=>{D0(j,Q.map(P1).join(" ")),J(...Q)}}window.addEventListener("error",(j)=>{let J=j.filename?` (${j.filename}:${j.lineno}:${j.colno})`:"";D0("exception",`${j.message}${J}`)}),window.addEventListener("unhandledrejection",(j)=>{let J=j.reason instanceof Error?`${j.reason.name}: ${j.reason.message}`:P1(j.reason);D0("unhandledrejection",J)})}function B0(){return Q0.map(($)=>({...$}))}var I1=new Set,D1=new Set;function B1($,j){return $.add(j),()=>$.delete(j)}function N1($,j){for(let J of[...$])J(j)}function N0($){return B1(I1,$)}function q0($={type:"manual"}){N1(I1,$)}function R0($){return B1(D1,$)}function S0($){N1(D1,$)}var W4=15000,V4=["ResizeObserver loop","Script error.","Non-Error promise rejection captured"],q1=!1,R1=0;function K4($){return V4.some((j)=>$.includes(j))}function S1($){let j=$.message??"";if(!j||K4(j))return;let J=Date.now();if(J-R1<W4)return;R1=J,S0({...$,message:j})}function O1(){if(q1||typeof window>"u")return;q1=!0,window.addEventListener("error",($)=>{if(!$.message&&!$.error)return;let j=$.error instanceof Error?$.error:null;S1({type:"runtime-error",message:$.message||(j?j.message:"Unknown error"),stack:j?.stack})}),window.addEventListener("unhandledrejection",($)=>{let j=$.reason;S1({type:"unhandledrejection",message:j instanceof Error?j.message:String(j),stack:j instanceof Error?j.stack:void 0})})}var k1=4000,X4=1e6,Y4=1e7,Z0=[],_1=0,f1=!1;function A1($){Z0.push($);while(Z0.length>E("maxRequests"))Z0.shift()}function T1(){return _1+=1,`req_${_1}`}function L1($){let j={};if(!$)return j;if($ instanceof Headers)$.forEach((J,Q)=>{j[Q]=J});else if(Array.isArray($))for(let[J,Q]of $)j[J]=Q;else Object.assign(j,$);return j}function G4($){let j={};return $.forEach((J,Q)=>{j[Q]=J}),j}function F4($){if($==null)return null;if(typeof $==="string")return $;if($ instanceof URLSearchParams)return $.toString();if(typeof FormData<"u"&&$ instanceof FormData)return`[FormData: ${Array.from($.keys()).join(", ")}]`;if(typeof Blob<"u"&&$ instanceof Blob)return`[Blob ${$.size} bytes]`;if($ instanceof ArrayBuffer)return`[ArrayBuffer ${$.byteLength} bytes]`;return"[binary]"}function H4($,j){let J="",Q="GET",Z={},z=null;if(typeof $==="string")J=$;else if($ instanceof URL)J=$.toString();else J=$.url,Q=$.method||Q,Z=L1($.headers);if(j){if(j.method)Q=j.method;if(j.headers)Z={...Z,...L1(j.headers)};if(j.body!==void 0)z=F4(j.body)}return{method:Q.toUpperCase(),url:J,headers:Z,body:z}}function x1($){return!J1($)}function M4($,j){if(x1(j.url)){j.responseSnippet="[body not captured for this origin]";return}let J=$.headers.get("content-type")??"",Q=Number($.headers.get("content-length")??"0"),Z=Q?`, ~${Q} bytes`:"";if(!/json|text|xml|html|javascript|urlencoded/i.test(J)){j.responseSnippet=`[binary ${J||"unknown"}${Z}]`;return}if(Q>X4){j.responseSnippet=`[response ${J||"text"}${Z} — omitted]`;return}try{$.clone().text().then((z)=>{j.responseSnippet=b(z,E("maxBodyChars"))}).catch(()=>{})}catch{}}function E1($,j){if(/[?&]_rsc=/.test($))return!0;for(let J of Object.keys(j)){let Q=J.toLowerCase();if(Q==="rsc"||Q==="next-router-prefetch"||Q==="next-router-state-tree")return!0}return!1}function C4(){if(typeof window>"u"||typeof window.fetch!=="function")return;let $=window.fetch.bind(window);window.fetch=Object.assign(async(j,J)=>{let Q=H4(j,J);if(E1(Q.url,Q.headers))return $(j,J);let Z={id:T1(),startedAt:new Date().toISOString(),method:Q.method,url:y(Q.url),requestHeaders:m(Q.headers),requestBody:b(Q.body,k1),status:null,statusText:null,durationMs:null,via:"fetch"};A1(Z);let z=performance.now();try{let V=await $(j,J);return Z.status=V.status,Z.statusText=V.statusText,Z.durationMs=Math.round(performance.now()-z),Z.responseHeaders=m(G4(V.headers)),M4(V,Z),V}catch(V){throw Z.durationMs=Math.round(performance.now()-z),Z.error=V instanceof Error?`${V.name}: ${V.message}`:String(V),V}},$)}function U4(){if(typeof window>"u"||typeof window.XMLHttpRequest!=="function")return;let $=XMLHttpRequest.prototype,j=$.open,J=$.send,Q=function(z,V){let Y=typeof V==="string"?V:V.toString();return this.__cibEntry=E1(Y,{})?void 0:{id:T1(),startedAt:"",method:(z||"GET").toUpperCase(),url:y(Y),requestHeaders:{},requestBody:null,status:null,statusText:null,durationMs:null,via:"xhr"},j.apply(this,arguments)},Z=function(z){let V=this.__cibEntry;if(V){V.startedAt=new Date().toISOString(),V.requestBody=typeof z==="string"?b(z,k1):z==null?null:"[non-string body]";let Y=performance.now();A1(V),this.addEventListener("loadend",()=>{if(V.status=this.status||null,V.statusText=this.statusText||null,V.durationMs=Math.round(performance.now()-Y),x1(V.url))V.responseSnippet="[body not captured for this origin]";else if(this.responseType===""||this.responseType==="text")try{V.responseSnippet=b(this.responseText||"",E("maxBodyChars"))}catch{}else{let F=this.getResponseHeader("content-type")??this.responseType;V.responseSnippet=`[binary ${F}]`}})}return J.apply(this,arguments)};$.open=Q,$.send=Z}function p1(){if(f1)return;f1=!0,C4(),U4()}function O0(){let $=Z0.map((J)=>({...J})),j=0;for(let J=$.length-1;J>=0;J-=1){let Q=$[J],Z=Q?.responseSnippet;if(!Q||typeof Z!=="string"||Z.length===0)continue;if(j+Z.length>Y4)Q.responseSnippet=`[response omitted — report size budget reached (${Z.length.toLocaleString()} chars)]`;else j+=Z.length}return $}var P4={title:"รายงานปัญหา",summaryLabel:"หัวข้อปัญหา",summaryRequired:"(ต้องกรอกก่อนแจ้งปัญหา)",summaryPlaceholder:"สรุปปัญหาสั้น ๆ เช่น กดบันทึกร่างแล้ว error",detailLabel:"อธิบายปัญหา (ไม่บังคับ)",detailPlaceholder:"เกิดอะไรขึ้น? กำลังทำอะไรอยู่ตอนที่พบปัญหา?",annotateTitle:"วาดบนรูป",annotateHint:"ทำเครื่องหมายจุดที่มีปัญหาก่อนแนบ — วงกรอบ ชี้ลูกศร ไฮไลต์ หรือพิมพ์ข้อความ",annotateApply:"ใช้รูปนี้",cancel:"ยกเลิก",toolRect:"กรอบ",toolArrow:"ลูกศร",toolHighlight:"ไฮไลต์",toolText:"ข้อความ",deleteSelected:"ลบที่เลือก",clearAll:"ล้างทั้งหมด",annotateHelp:"เลือกเครื่องมือแล้วลากบนรูป · ไม่ได้เลือกเครื่องมือ = ย้าย/ปรับขนาดสิ่งที่วาดไว้ · กดกากบาทมุมขวาบนของรูปทรงเพื่อลบ",capturing:"กำลังเก็บภาพหน้าจอ…",noScreenshot:"ไม่มีภาพหน้าจอ — ยังส่งรายงานได้",cancelled:"ยกเลิกการเก็บภาพหน้าจอแล้ว",close:"ปิด",submit:"แจ้งปัญหา",submitting:"กำลังส่ง…",submitted:"แจ้งปัญหาสำเร็จ",crashed:"เกิดข้อผิดพลาดในระบบ",crashAction:"แจ้งปัญหา",failed:"ส่งรายงานไม่สำเร็จ",captured:"เก็บข้อมูลแล้ว",reporter:"ผู้แจ้ง",page:"หน้า"},w4={title:"Report a problem",summaryLabel:"Summary",summaryRequired:"(required)",summaryPlaceholder:"One line, e.g. saving a draft returns an error",detailLabel:"Details (optional)",detailPlaceholder:"What happened? What were you doing at the time?",annotateTitle:"Draw on the image",annotateHint:"Mark what went wrong before attaching — box it, point at it, highlight it, or type on it",annotateApply:"Use this image",cancel:"Cancel",toolRect:"Box",toolArrow:"Arrow",toolHighlight:"Highlight",toolText:"Text",deleteSelected:"Delete selected",clearAll:"Clear all",annotateHelp:"Pick a tool and drag on the image · no tool selected = move/resize what you drew · press the ✕ on a shape to delete it",capturing:"Capturing the screen…",noScreenshot:"No screenshot — you can still send the report",cancelled:"Screen capture cancelled",close:"Close",submit:"Send report",submitting:"Sending…",submitted:"Report sent",crashed:"Something went wrong",crashAction:"Report it",failed:"Could not send the report",captured:"Captured",reporter:"Reporter",page:"Page"};function s($){return $==="en"?w4:P4}var _0=null;function I4(){if(typeof document>"u")return null;if(_0?.isConnected)return _0;let $=document.createElement("lw-debug-toasts");$.dataset.debugReporter="true";let j=$.attachShadow({mode:"open"}),J=document.createElement("style");J.textContent=`
1
+ var t1={maxRequests:60,maxConsoleEntries:120,maxActions:80,maxBodyChars:20000},_=null;function e1($){_=$}function B(){if(!_)throw Error("[debug-capture] configureDebugCapture() has not been called");return _}function V0(){return _!==null}function T(){let $=B().app;return{name:$.name,version:$.version??"0.0.0",environment:$.environment??$2()}}function $2(){if(typeof window>"u")return"unknown";let $=window.location.hostname;if($==="localhost"||$==="127.0.0.1"||$.endsWith(".local"))return"development";return"production"}function E($){let j=_?.capture?.[$];return typeof j==="number"?j:t1[$]}function l0($){let j=_?.module;if(!j)return null;try{return j($)??null}catch{return null}}function e(){let $=_?.redact;return{headers:$?.headers??[],queryKeys:($?.queryKeys??[]).map((j)=>j.toLowerCase()),bodyKeys:($?.bodyKeys??[]).map((j)=>j.toLowerCase())}}function r0(){return _?.capture?.overlaySelectors??[]}function n0($){if(typeof window>"u")return!1;let j;try{j=new URL($,window.location.href)}catch{return!1}if(j2(j))return!1;if(j.origin===window.location.origin)return!0;return(_?.capture?.bodyOrigins??[]).some((J)=>{try{return new URL(J).origin===j.origin}catch{return!1}})}function j2($){if(!_?.host)return!1;try{if(new URL(_.host).origin!==$.origin)return!1}catch{return!1}return $.pathname.startsWith("/ingest/")}var p="‹redacted›",J2=/^(authorization|proxy-authorization|cookie|set-cookie|x-[a-z-]*token|x-csrf[a-z-]*|x-xsrf[a-z-]*)$/i,Q2=new Set(["access_token","token","id_token","refresh_token","code","secret","client_secret","password","apikey","api_key","signature","x-amz-signature","x-amz-credential"]),z2=/(password|passwd|token|secret|authorization|refresh|client_secret|otp|pin)/i,Z2=/[\w.+-]+@[\w-]+\.[\w.-]+/g,W2=/\d(?:[\d\s-]{7,})\d/g;function g($){return $.replace(Z2,p).replace(W2,p)}function K2($){if(J2.test($))return!0;return e().headers.some((J)=>J.toLowerCase()===$.toLowerCase())}function m($){let j={};for(let[J,Q]of Object.entries($))j[J]=K2(J)?p:Q;return j}function v($){try{let j=/^https?:\/\//i.test($),J=new URL($,j?void 0:"http://local.invalid"),Q=!1;if(J.searchParams.forEach((z,W)=>{if(Q2.has(W.toLowerCase())||e().queryKeys.includes(W.toLowerCase()))J.searchParams.set(W,p),Q=!0}),!Q)return $;return j?J.toString():`${J.pathname}${J.search}`}catch{return $}}function X0($,j){if(j>6||$===null||typeof $!=="object")return $;if(Array.isArray($))return $.map((Q)=>X0(Q,j+1));let J={};for(let[Q,z]of Object.entries($)){let W=z2.test(Q)||e().bodyKeys.some((K)=>Q.toLowerCase().includes(K));J[Q]=W?p:X0(z,j+1)}return J}function y($,j){if($==null)return null;let J=$,Q=$.trim();if(Q.startsWith("{")||Q.startsWith("["))try{let z=JSON.parse(Q);J=JSON.stringify(X0(z,0))}catch{}if(J.length>j)return`${J.slice(0,j)}… [truncated ${J.length-j} chars]`;return J}var Y0=120,F0=40,u=($,j)=>$.length>j?`${$.slice(0,j)}…`:$,w0=($)=>{try{return decodeURIComponent($)}catch{return $}},b=[],s0=0,a0=!1;function l($,j,J,Q){let z=u(j,Y0),W=b[b.length-1];if($==="navigate"&&W?.kind==="click"){let Y=z.replace(/^ไปที่\s*/,"");if(W.detail.includes(`→ ${Y}`))return W.at=new Date().toISOString(),W;let w=Y.split(/[?#]/)[0]??Y,M=W.source?w0(W.source.replace(/^→\s*/,"")).split(/[?#]/)[0]:null;if(M&&(w===M||w.startsWith(M)))return W.detail=u(`${W.detail} → ${Y}`,Y0),W.source=void 0,W.at=new Date().toISOString(),W}if(W&&W.kind===$&&W.detail===z){if(W.at=new Date().toISOString(),$!=="navigate")W.count=(W.count??1)+1;return W}s0+=1;let K={id:`act_${s0}`,at:new Date().toISOString(),kind:$,detail:z,count:1,source:J,html:j0(Q)};b.push(K);while(b.length>E("maxActions"))V2(b.shift());return K}var G2=200000,r=0;function j0($){if(!$)return;if(r+$.length>G2)return;return r+=$.length,$}function V2($){if(!$)return;if(r-=($.html?.length??0)+($.afterHtml?.length??0),r<0)r=0}function H0($){return $&&$>1?` (×${$})`:""}function $0($){return $ instanceof Element&&Boolean($.closest("[data-debug-reporter]"))}var X2='button, a[href], [role="button"], [role="tab"], [role="menuitem"], [role="option"], [role="switch"], [role="checkbox"], [role="radio"], [role="link"], summary, input, select, textarea',Y2={button:"ปุ่ม",a:"ลิงก์",input:"ช่อง",textarea:"ช่อง",select:"ตัวเลือก",summary:"ส่วนขยาย"},t0={button:"ปุ่ม",tab:"แท็บ",menuitem:"เมนู",option:"ตัวเลือก",switch:"สวิตช์",checkbox:"ช่องเลือก",radio:"ตัวเลือก",link:"ลิงก์"};function F2($){let j=$.getAttribute("role");if(j&&t0[j])return t0[j];return Y2[$.tagName.toLowerCase()]??"ปุ่ม"}function w2($,j){try{let J=$,Q=0;while(J&&Q<=j){let z=z1(J);if(z&&typeof z.memoizedProps?.onClick==="function")return J;J=J.parentElement,Q+=1}}catch{}return null}function H2($){let j=$.getAttribute("aria-label")?.trim();if(j)return j;let J=$.getAttribute("title")?.trim();if(J)return J;if($ instanceof HTMLInputElement||$ instanceof HTMLTextAreaElement||$ instanceof HTMLSelectElement)return($.getAttribute("placeholder")||$.getAttribute("name")||"").trim();if($ instanceof HTMLImageElement)return($.getAttribute("alt")||"").trim();let Q=($.textContent??"").replace(/\s+/g," ").trim();if(Q)return Q;if($ instanceof HTMLAnchorElement){let z=$.getAttribute("href");if(z?.startsWith("/"))return w0(z)}return""}function M2($){if(!($ instanceof Element))return null;let j=$.closest(X2)??w2($,4);if(!j)return null;let J=j.tagName.toLowerCase();if(J==="html"||J==="body")return null;return j}function C2($){let j=g(H2($));if(!j)return null;return`${F2($)} “${u(j,F0)}”`}var Q1=6000,U2=4000,I2=/(?:^|\s)!?(?:fixed|absolute|sticky|inset-\S+|z-\S+|top-\S+|bottom-\S+|left-\S+|right-\S+|w-screen|h-screen|min-h-screen|max-h-screen|translate-\S+|scale-\S+)(?=\s|$)/g;function P2($){$.querySelectorAll("script, style, link, iframe, object, embed, noscript, canvas, video, audio").forEach((z)=>z.remove());let j=[$,...Array.from($.querySelectorAll("*"))];for(let z of j){for(let K of Array.from(z.attributes)){let Y=K.name.toLowerCase();if(Y.startsWith("on")||Y==="srcdoc"||Y==="value"||Y.startsWith("data-"))z.removeAttribute(K.name)}if(z instanceof HTMLAnchorElement)z.setAttribute("href","#");if(z instanceof HTMLImageElement)z.removeAttribute("src");let W=z.getAttribute("class");if(W){let K=W.replace(I2," ").replace(/\s+/g," ").trim();if(K)z.setAttribute("class",K);else z.removeAttribute("class")}}let J=document.createTreeWalker($,NodeFilter.SHOW_TEXT),Q=J.nextNode();while(Q){if(Q.nodeValue)Q.nodeValue=g(Q.nodeValue);Q=J.nextNode()}}function M0($,j,J){try{let Q=$.outerHTML;if(!Q||Q.length>j)return;let z=$.cloneNode(!0);P2(z);let W=z.outerHTML;return W&&W.length<=J?W:void 0}catch{return}}var D2=($)=>M0($,Q1,U2),N2=150000,B2=40000,e0=($)=>M0($,N2,B2);function S2($){if(!($ instanceof HTMLInputElement)&&!($ instanceof HTMLTextAreaElement)&&!($ instanceof HTMLSelectElement))return null;let j=$.name||$.id||$.getAttribute("aria-label")||$.getAttribute("placeholder")||$.tagName.toLowerCase();return`ช่อง “${g(j)}”`}var $1=80;function z1($){let j=Object.keys($).find((J)=>J.startsWith("__reactFiber$")||J.startsWith("__reactInternalInstance$"));return j?$[j]:null}function q2($){if(typeof $!=="function")return null;try{let j=Function.prototype.toString.call($);return(j.match(/\.(?:push|replace)\(\s*['"`]([^'"`]+)['"`]/)??j.match(/redirect\(\s*['"`]([^'"`]+)['"`]/))?.[1]??null}catch{return null}}function j1($){if(!$)return;return`→ ${$.length>$1?`${$.slice(0,$1)}…`:$}`}function f2($){try{let j=$.closest("a[href]")?.getAttribute("href");if(j&&j.startsWith("/"))return j1(j);let J=z1($),Q=0;while(J&&Q<30){if(typeof J.memoizedProps?.onClick==="function")return j1(q2(J.memoizedProps.onClick));J=J.return,Q+=1}return}catch{return}}var R2='[role="dialog"], [role="alertdialog"], [role="menu"], [role="listbox"], [role="status"], [role="alert"]';function k2(){let $=r0();return $.length?$.join(", "):R2}function O2($){let j=$.getAttribute("role");if(j==="status"||j==="alert")return"ข้อความแจ้งเตือน";if(j==="menu")return"เมนู";if(j==="listbox")return"รายการตัวเลือก";if(j==="alertdialog")return"กล่องยืนยัน";return"กล่องโต้ตอบ"}function _2($){let j=$.getAttribute("aria-label")?.trim();if(j)return j;let J=$.getAttribute("aria-labelledby");if(J){let W=J.split(/\s+/).map((K)=>document.getElementById(K)?.textContent?.trim()??"").filter(Boolean).join(" ");if(W)return W}let z=$.querySelector('[data-slot="dialog-title"], h1, h2, h3, [role="heading"]')?.textContent?.replace(/\s+/g," ").trim();if(z)return z;return($.textContent??"").replace(/\s+/g," ").trim()}function Z1($){let j=g(_2($)),J=O2($);return j?`เปิด ${J} “${u(j,F0)}”`:`เปิด ${J}`}var L2='[aria-busy="true"], [role="progressbar"], [data-loading="true"], .animate-pulse, .animate-spin',A2=/กำลังโหลด|กำลังค้นหา|กำลังดำเนินการ|\bloading\b/i;function T2($){if($.querySelector(L2))return!0;return A2.test($.textContent??"")}var E2=400,x2=250,h2=8000;function p2($,j){if(typeof MutationObserver>"u"){j.html=j0(e0($));return}let J=Date.now(),Q=!1,z=()=>{Q=!0,K.disconnect(),window.clearInterval(Y),window.clearTimeout(w)},W=()=>{if(Q)return;if(z(),!$.isConnected)return;j.detail=u(Z1($),Y0),j.html=j0(e0($))},K=new MutationObserver(()=>{J=Date.now()});K.observe($,{childList:!0,subtree:!0,attributes:!0,characterData:!0});let Y=window.setInterval(()=>{if(Q)return;if(!$.isConnected){z();return}if(Date.now()-J>=E2&&!T2($))W()},x2),w=window.setTimeout(W,h2)}function g2($){if($0($))return;let j=l("ui",Z1($));if(j)p2($,j)}function m2(){if(typeof MutationObserver>"u")return;let $=new WeakSet;new MutationObserver((J)=>{for(let Q of J)for(let z of Array.from(Q.addedNodes)){if(!(z instanceof Element))continue;let W=k2(),K=z.matches(W)?[z]:Array.from(z.querySelectorAll(W));for(let Y of K){if($.has(Y))continue;$.add(Y),g2(Y)}}}).observe(document.body,{childList:!0,subtree:!0})}var v2=1600,y2=2500;function J1($){return{disabled:$.hasAttribute("disabled")||$.getAttribute("aria-disabled")==="true",busy:$.getAttribute("aria-busy")==="true",text:u(($.textContent??"").replace(/\s+/g," ").trim(),F0)}}function b2($,j){if(!$.disabled&&j.disabled)return"ปุ่มถูกปิดใช้งานหลังคลิก";if(!$.busy&&j.busy)return"ปุ่มเข้าสู่สถานะกำลังโหลด";if($.text!==j.text&&j.text)return`ข้อความเปลี่ยนเป็น “${j.text}”`;return null}function u2($,j){if(typeof MutationObserver>"u")return;let J=J1($),Q=!1,z=(Y,w)=>{if(Q)return;if(Q=!0,W.disconnect(),window.clearTimeout(K),j.afterNote=Y,w)j.afterHtml=j0(M0($,Q1,y2))},W=new MutationObserver(()=>{if(!$.isConnected){z("องค์ประกอบหายไปจากหน้าจอ",!1);return}let Y=b2(J,J1($));if(Y)z(Y,!0)});W.observe($,{attributes:!0,attributeFilter:["disabled","aria-disabled","aria-busy","class"],childList:!0,subtree:!0,characterData:!0});let K=window.setTimeout(()=>{if(!Q&&!$.isConnected){z("องค์ประกอบหายไปจากหน้าจอ",!1);return}Q=!0,W.disconnect()},v2)}function W1(){if(a0||typeof window>"u")return;a0=!0,document.addEventListener("click",(Q)=>{if($0(Q.target))return;let z=M2(Q.target);if(!z)return;let W=C2(z);if(!W)return;let K=l("click",`คลิก ${W}`,f2(z),D2(z));if(K)u2(z,K)},{capture:!0,passive:!0}),document.addEventListener("change",(Q)=>{if($0(Q.target))return;let z=S2(Q.target);if(z)l("input",`แก้ไข ${z}`)},{capture:!0,passive:!0}),document.addEventListener("submit",(Q)=>{if($0(Q.target))return;l("submit","ส่งฟอร์ม")},{capture:!0,passive:!0});let $=()=>l("navigate",`ไปที่ ${w0(v(location.pathname+location.search))}`),j=history.pushState.bind(history),J=history.replaceState.bind(history);history.pushState=(...Q)=>{let z=j(...Q);return $(),z},history.replaceState=(...Q)=>{let z=J(...Q);return $(),z},window.addEventListener("popstate",$),m2()}function C0(){return b.map(($)=>({...$}))}var K1=2000,J0=[],G1=0,V1=!1;function U0($,j){G1+=1,J0.push({id:`log_${G1}`,at:new Date().toISOString(),level:$,message:j.length>K1?`${j.slice(0,K1)}…`:j});while(J0.length>E("maxConsoleEntries"))J0.shift()}function d2(){let $=new WeakSet;return(j,J)=>{if(typeof J==="object"&&J!==null){if($.has(J))return"[Circular]";$.add(J)}if(typeof J==="bigint")return J.toString();return J}}function X1($){if(typeof $==="string")return $;if($ instanceof Error)return`${$.name}: ${$.message}`;try{return JSON.stringify($,d2())??String($)}catch{return String($)}}function Y1(){if(V1||typeof window>"u")return;V1=!0;let $=["log","info","warn","error","debug"];for(let j of $){let J=console[j].bind(console);console[j]=(...Q)=>{U0(j,Q.map(X1).join(" ")),J(...Q)}}window.addEventListener("error",(j)=>{let J=j.filename?` (${j.filename}:${j.lineno}:${j.colno})`:"";U0("exception",`${j.message}${J}`)}),window.addEventListener("unhandledrejection",(j)=>{let J=j.reason instanceof Error?`${j.reason.name}: ${j.reason.message}`:X1(j.reason);U0("unhandledrejection",J)})}function I0(){return J0.map(($)=>({...$}))}var F1=new Set,w1=new Set;function H1($,j){return $.add(j),()=>$.delete(j)}function M1($,j){for(let J of[...$])J(j)}function P0($){return H1(F1,$)}function D0($={type:"manual"}){M1(F1,$)}function N0($){return H1(w1,$)}function B0($){M1(w1,$)}var i2=15000,o2=["ResizeObserver loop","Script error.","Non-Error promise rejection captured"],C1=!1,U1=0;function c2($){return o2.some((j)=>$.includes(j))}function I1($){let j=$.message??"";if(!j||c2(j))return;let J=Date.now();if(J-U1<i2)return;U1=J,B0({...$,message:j})}function P1(){if(C1||typeof window>"u")return;C1=!0,window.addEventListener("error",($)=>{if(!$.message&&!$.error)return;let j=$.error instanceof Error?$.error:null;I1({type:"runtime-error",message:$.message||(j?j.message:"Unknown error"),stack:j?.stack})}),window.addEventListener("unhandledrejection",($)=>{let j=$.reason;I1({type:"unhandledrejection",message:j instanceof Error?j.message:String(j),stack:j instanceof Error?j.stack:void 0})})}var S1=4000,l2=1e6,r2=1e7,Q0=[],D1=0,N1=!1;function q1($){Q0.push($);while(Q0.length>E("maxRequests"))Q0.shift()}function f1(){return D1+=1,`req_${D1}`}function B1($){let j={};if(!$)return j;if($ instanceof Headers)$.forEach((J,Q)=>{j[Q]=J});else if(Array.isArray($))for(let[J,Q]of $)j[J]=Q;else Object.assign(j,$);return j}function n2($){let j={};return $.forEach((J,Q)=>{j[Q]=J}),j}function s2($){if($==null)return null;if(typeof $==="string")return $;if($ instanceof URLSearchParams)return $.toString();if(typeof FormData<"u"&&$ instanceof FormData)return`[FormData: ${Array.from($.keys()).join(", ")}]`;if(typeof Blob<"u"&&$ instanceof Blob)return`[Blob ${$.size} bytes]`;if($ instanceof ArrayBuffer)return`[ArrayBuffer ${$.byteLength} bytes]`;return"[binary]"}function a2($,j){let J="",Q="GET",z={},W=null;if(typeof $==="string")J=$;else if($ instanceof URL)J=$.toString();else J=$.url,Q=$.method||Q,z=B1($.headers);if(j){if(j.method)Q=j.method;if(j.headers)z={...z,...B1(j.headers)};if(j.body!==void 0)W=s2(j.body)}return{method:Q.toUpperCase(),url:J,headers:z,body:W}}function R1($){return!n0($)}function t2($,j){if(R1(j.url)){j.responseSnippet="[body not captured for this origin]";return}let J=$.headers.get("content-type")??"",Q=Number($.headers.get("content-length")??"0"),z=Q?`, ~${Q} bytes`:"";if(!/json|text|xml|html|javascript|urlencoded/i.test(J)){j.responseSnippet=`[binary ${J||"unknown"}${z}]`;return}if(Q>l2){j.responseSnippet=`[response ${J||"text"}${z} — omitted]`;return}try{$.clone().text().then((W)=>{j.responseSnippet=y(W,E("maxBodyChars"))}).catch(()=>{})}catch{}}function k1($,j){if(/[?&]_rsc=/.test($))return!0;for(let J of Object.keys(j)){let Q=J.toLowerCase();if(Q==="rsc"||Q==="next-router-prefetch"||Q==="next-router-state-tree")return!0}return!1}function e2(){if(typeof window>"u"||typeof window.fetch!=="function")return;let $=window.fetch.bind(window);window.fetch=Object.assign(async(j,J)=>{let Q=a2(j,J);if(k1(Q.url,Q.headers))return $(j,J);let z={id:f1(),startedAt:new Date().toISOString(),method:Q.method,url:v(Q.url),requestHeaders:m(Q.headers),requestBody:y(Q.body,S1),status:null,statusText:null,durationMs:null,via:"fetch"};q1(z);let W=performance.now();try{let K=await $(j,J);return z.status=K.status,z.statusText=K.statusText,z.durationMs=Math.round(performance.now()-W),z.responseHeaders=m(n2(K.headers)),t2(K,z),K}catch(K){throw z.durationMs=Math.round(performance.now()-W),z.error=K instanceof Error?`${K.name}: ${K.message}`:String(K),K}},$)}function $4(){if(typeof window>"u"||typeof window.XMLHttpRequest!=="function")return;let $=XMLHttpRequest.prototype,j=$.open,J=$.send,Q=function(W,K){let Y=typeof K==="string"?K:K.toString();return this.__cibEntry=k1(Y,{})?void 0:{id:f1(),startedAt:"",method:(W||"GET").toUpperCase(),url:v(Y),requestHeaders:{},requestBody:null,status:null,statusText:null,durationMs:null,via:"xhr"},j.apply(this,arguments)},z=function(W){let K=this.__cibEntry;if(K){K.startedAt=new Date().toISOString(),K.requestBody=typeof W==="string"?y(W,S1):W==null?null:"[non-string body]";let Y=performance.now();q1(K),this.addEventListener("loadend",()=>{if(K.status=this.status||null,K.statusText=this.statusText||null,K.durationMs=Math.round(performance.now()-Y),R1(K.url))K.responseSnippet="[body not captured for this origin]";else if(this.responseType===""||this.responseType==="text")try{K.responseSnippet=y(this.responseText||"",E("maxBodyChars"))}catch{}else{let w=this.getResponseHeader("content-type")??this.responseType;K.responseSnippet=`[binary ${w}]`}})}return J.apply(this,arguments)};$.open=Q,$.send=z}function O1(){if(N1)return;N1=!0,e2(),$4()}function S0(){let $=Q0.map((J)=>({...J})),j=0;for(let J=$.length-1;J>=0;J-=1){let Q=$[J],z=Q?.responseSnippet;if(!Q||typeof z!=="string"||z.length===0)continue;if(j+z.length>r2)Q.responseSnippet=`[response omitted — report size budget reached (${z.length.toLocaleString()} chars)]`;else j+=z.length}return $}var j4={title:"รายงานปัญหา",summaryLabel:"หัวข้อปัญหา",summaryRequired:"(ต้องกรอกก่อนแจ้งปัญหา)",summaryPlaceholder:"สรุปปัญหาสั้น ๆ เช่น กดบันทึกร่างแล้ว error",detailLabel:"อธิบายปัญหา (ไม่บังคับ)",detailPlaceholder:"เกิดอะไรขึ้น? กำลังทำอะไรอยู่ตอนที่พบปัญหา?",annotateTitle:"วาดบนรูป",annotateHint:"ทำเครื่องหมายจุดที่มีปัญหาก่อนแนบ — วงกรอบ ชี้ลูกศร ไฮไลต์ หรือพิมพ์ข้อความ",annotateApply:"ใช้รูปนี้",cancel:"ยกเลิก",toolRect:"กรอบ",toolArrow:"ลูกศร",toolHighlight:"ไฮไลต์",toolText:"ข้อความ",deleteSelected:"ลบที่เลือก",clearAll:"ล้างทั้งหมด",annotateHelp:"เลือกเครื่องมือแล้วลากบนรูป · ไม่ได้เลือกเครื่องมือ = ย้าย/ปรับขนาดสิ่งที่วาดไว้ · กดกากบาทมุมขวาบนของรูปทรงเพื่อลบ",capturing:"กำลังเก็บภาพหน้าจอ…",noScreenshot:"ไม่มีภาพหน้าจอ — ยังส่งรายงานได้",cancelled:"ยกเลิกการเก็บภาพหน้าจอแล้ว",close:"ปิด",submit:"แจ้งปัญหา",submitting:"กำลังส่ง…",submitted:"แจ้งปัญหาสำเร็จ",crashed:"เกิดข้อผิดพลาดในระบบ",crashAction:"แจ้งปัญหา",failed:"ส่งรายงานไม่สำเร็จ",captured:"เก็บข้อมูลแล้ว",reporter:"ผู้แจ้ง",page:"หน้า"},J4={title:"Report a problem",summaryLabel:"Summary",summaryRequired:"(required)",summaryPlaceholder:"One line, e.g. saving a draft returns an error",detailLabel:"Details (optional)",detailPlaceholder:"What happened? What were you doing at the time?",annotateTitle:"Draw on the image",annotateHint:"Mark what went wrong before attaching — box it, point at it, highlight it, or type on it",annotateApply:"Use this image",cancel:"Cancel",toolRect:"Box",toolArrow:"Arrow",toolHighlight:"Highlight",toolText:"Text",deleteSelected:"Delete selected",clearAll:"Clear all",annotateHelp:"Pick a tool and drag on the image · no tool selected = move/resize what you drew · press the ✕ on a shape to delete it",capturing:"Capturing the screen…",noScreenshot:"No screenshot — you can still send the report",cancelled:"Screen capture cancelled",close:"Close",submit:"Send report",submitting:"Sending…",submitted:"Report sent",crashed:"Something went wrong",crashAction:"Report it",failed:"Could not send the report",captured:"Captured",reporter:"Reporter",page:"Page"};function n($){return $==="en"?J4:j4}var q0=null;function Q4(){if(typeof document>"u")return null;if(q0?.isConnected)return q0;let $=document.createElement("lw-debug-toasts");$.dataset.debugReporter="true";let j=$.attachShadow({mode:"open"}),J=document.createElement("style");J.textContent=`
2
2
  :host { all: initial; }
3
3
  .stack {
4
4
  position: fixed; top: 16px; right: 16px; z-index: 2147483001;
@@ -30,15 +30,15 @@ var M2={maxRequests:60,maxConsoleEntries:120,maxActions:80,maxBodyChars:20000},L
30
30
  }
31
31
  @keyframes in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
32
32
  @media (prefers-reduced-motion: reduce) { .toast { animation: none; } }
33
- `;let Q=document.createElement("div");return Q.className="stack",Q.setAttribute("role","status"),Q.setAttribute("aria-live","polite"),j.append(J,Q),document.body.append($),_0=Q,Q}function c($,j="success",J){let Q=I4();if(!Q)return;let Z=document.createElement("div");Z.className="toast",Z.dataset.tone=j;let z=document.createElement("span");z.className="dot";let V=document.createElement("span");V.textContent=$;let Y=document.createElement("button");Y.type="button",Y.className="close",Y.textContent="✕",Y.setAttribute("aria-label","ปิด");let F=()=>{window.clearTimeout(C),Z.remove()};Y.addEventListener("click",F);let C=j==="error"||J?0:window.setTimeout(F,6000);if(Z.append(z,V),J){let P=document.createElement("button");P.type="button",P.className="action",P.textContent=J.label,P.addEventListener("click",()=>{F(),J.onClick()}),Z.append(P)}Z.append(Y),Q.append(Z)}function h1($,j,J){let Q=$.filter((z)=>Boolean(z.error)||z.status!=null&&z.status>=400).slice(-20).map((z)=>({method:z.method,url:z.url,status:z.status,error:z.error,at:z.startedAt})),Z=j.filter((z)=>z.level==="error"||z.level==="exception"||z.level==="unhandledrejection").slice(-20).map((z)=>z.message);return{failedRequests:Q,errors:Z,erroredQueries:J.slice(0,20)}}function v1($){return $.failedRequests.length+$.errors.length+$.erroredQueries.length}function D4(){let $={memoryUsedMb:null,memoryLimitMb:null,domContentLoadedMs:null,loadEventMs:null};if(typeof performance>"u")return $;let j=performance.memory;if(j)$.memoryUsedMb=Math.round(j.usedJSHeapSize/1024/1024),$.memoryLimitMb=Math.round(j.jsHeapSizeLimit/1024/1024);let[J]=performance.getEntriesByType("navigation");if(J)$.domContentLoadedMs=Math.round(J.domContentLoadedEventEnd),$.loadEventMs=Math.round(J.loadEventEnd);return $}function f0($,j){if(!$)return j;try{return $()}catch{return j}}function g1(){let $=B(),{pathname:j,search:J,href:Q}=window.location;return{capturedAt:new Date().toISOString(),route:{href:Q,pathname:j,search:J},module:$1(j),user:f0($.user,{}),apiHeaders:m(f0($.headers,{})),app:{name:x().name,version:x().version,environment:x().environment},client:{userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,online:navigator.onLine,viewport:{width:window.innerWidth,height:window.innerHeight,dpr:window.devicePixelRatio},screen:{width:window.screen.width,height:window.screen.height}},performance:D4(),extra:f0($.extra,{})}}var B4=2,N4={manual:"ผู้ใช้แจ้งเอง","runtime-error":"ข้อผิดพลาด runtime (auto)",unhandledrejection:"Promise rejection (auto)","framework-error":"หน้าจอค้าง/พัง (auto)"};function L0($){let j=O0(),J=B0();return{context:g1(),reason:$.reason,note:$.note,cause:h1(j,J,$.erroredQueries),actionTrail:I0(),network:j,console:J,screenshotDataUrl:$.screenshotDataUrl,screenshotMethod:$.screenshotMethod,meta:{generatedBy:"lightwork-debug-capture",schemaVersion:B4}}}function m1($){return $.replace(/'/g,"'\\''")}function y1($){let j=[`curl -X ${$.method} '${$.url}'`];for(let[J,Q]of Object.entries($.requestHeaders))j.push(` -H '${J}: ${m1(Q)}'`);if($.requestBody)j.push(` --data '${m1($.requestBody)}'`);return j.join(" \\\n")}function q4($){if($.error)return`ERR ${$.error}`;return`${$.status??"—"} ${$.statusText??""}`.trim()}function R4($){if($.length===0)return"No network activity captured.";return $.map((j)=>{let J=j.durationMs!=null?`${j.durationMs}ms`:"—",Q=`# [${q4(j)}] ${j.method} ${j.url} (${J}, ${j.startedAt})`,Z=j.responseSnippet?`
33
+ `;let Q=document.createElement("div");return Q.className="stack",Q.setAttribute("role","status"),Q.setAttribute("aria-live","polite"),j.append(J,Q),document.body.append($),q0=Q,Q}function d($,j="success",J){let Q=Q4();if(!Q)return;let z=document.createElement("div");z.className="toast",z.dataset.tone=j;let W=document.createElement("span");W.className="dot";let K=document.createElement("span");K.textContent=$;let Y=document.createElement("button");Y.type="button",Y.className="close",Y.textContent="✕",Y.setAttribute("aria-label","ปิด");let w=()=>{window.clearTimeout(M),z.remove()};Y.addEventListener("click",w);let M=j==="error"||J?0:window.setTimeout(w,6000);if(z.append(W,K),J){let U=document.createElement("button");U.type="button",U.className="action",U.textContent=J.label,U.addEventListener("click",()=>{w(),J.onClick()}),z.append(U)}z.append(Y),Q.append(z)}function _1($,j,J){let Q=$.filter((W)=>Boolean(W.error)||W.status!=null&&W.status>=400).slice(-20).map((W)=>({method:W.method,url:W.url,status:W.status,error:W.error,at:W.startedAt})),z=j.filter((W)=>W.level==="error"||W.level==="exception"||W.level==="unhandledrejection").slice(-20).map((W)=>W.message);return{failedRequests:Q,errors:z,erroredQueries:J.slice(0,20)}}function L1($){return $.failedRequests.length+$.errors.length+$.erroredQueries.length}function z4(){let $={memoryUsedMb:null,memoryLimitMb:null,domContentLoadedMs:null,loadEventMs:null};if(typeof performance>"u")return $;let j=performance.memory;if(j)$.memoryUsedMb=Math.round(j.usedJSHeapSize/1024/1024),$.memoryLimitMb=Math.round(j.jsHeapSizeLimit/1024/1024);let[J]=performance.getEntriesByType("navigation");if(J)$.domContentLoadedMs=Math.round(J.domContentLoadedEventEnd),$.loadEventMs=Math.round(J.loadEventEnd);return $}function f0($,j){if(!$)return j;try{return $()}catch{return j}}function A1(){let $=B(),{pathname:j,search:J,href:Q}=window.location;return{capturedAt:new Date().toISOString(),route:{href:Q,pathname:j,search:J},module:l0(j),user:f0($.user,{}),apiHeaders:m(f0($.headers,{})),app:{name:T().name,version:T().version,environment:T().environment},client:{userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,online:navigator.onLine,viewport:{width:window.innerWidth,height:window.innerHeight,dpr:window.devicePixelRatio},screen:{width:window.screen.width,height:window.screen.height}},performance:z4(),extra:f0($.extra,{})}}var Z4=2,W4={manual:"ผู้ใช้แจ้งเอง","runtime-error":"ข้อผิดพลาด runtime (auto)",unhandledrejection:"Promise rejection (auto)","framework-error":"หน้าจอค้าง/พัง (auto)"};function R0($){let j=S0(),J=I0();return{context:A1(),reason:$.reason,note:$.note,cause:_1(j,J,$.erroredQueries),actionTrail:C0(),network:j,console:J,screenshotDataUrl:$.screenshotDataUrl,screenshotMethod:$.screenshotMethod,meta:{generatedBy:"lightwork-debug-capture",schemaVersion:Z4}}}function T1($){return $.replace(/'/g,"'\\''")}function E1($){let j=[`curl -X ${$.method} '${$.url}'`];for(let[J,Q]of Object.entries($.requestHeaders))j.push(` -H '${J}: ${T1(Q)}'`);if($.requestBody)j.push(` --data '${T1($.requestBody)}'`);return j.join(" \\\n")}function K4($){if($.error)return`ERR ${$.error}`;return`${$.status??"—"} ${$.statusText??""}`.trim()}function G4($){if($.length===0)return"No network activity captured.";return $.map((j)=>{let J=j.durationMs!=null?`${j.durationMs}ms`:"—",Q=`# [${K4(j)}] ${j.method} ${j.url} (${J}, ${j.startedAt})`,z=j.responseSnippet?`
34
34
  # response: ${j.responseSnippet}`:"";return`${Q}
35
- ${y1(j)}${Z}`}).join(`
35
+ ${E1(j)}${z}`}).join(`
36
36
 
37
- `)}function S4($){if($.length===0)return"No console output captured.";return $.map((j)=>`[${j.at}] ${j.level.toUpperCase()}: ${j.message}`).join(`
38
- `)}function O4($){if($.length===0)return"No user actions captured.";let j=0;return $.map((J)=>{let Q=J.source?` (${J.source})`:"",Z=`${J.detail}${P0(J.count)}${Q}`;if(J.kind==="ui")return` ↳ [${J.at}] ${Z}`;j+=1;let z=`${j}. [${J.at}] ${Z}`;return J.afterNote?`${z}
39
- ↳ ${J.afterNote}`:z}).join(`
40
- `)}function _4($){let j=[];for(let J of $.failedRequests)j.push(`✗ ${J.status??J.error??"ERR"} ${J.method} ${J.url}`);for(let J of $.errors)j.push(`⚠ ${J}`);for(let J of $.erroredQueries)j.push(`⚠ React Query error: ${J.key} — ${J.error}`);return j}function f4($){let{context:j}=$;return[`User : ${j.user.fullName??"—"} (${j.user.email??"—"})`,`Unit : ${j.user.unit??"—"}`,`Roles : ${j.user.roles?.join(", ")||"—"}`,`Route : ${j.route.href}`,`Module : ${j.module?`${j.module.label} (${j.module.key})`:"—"}`,`App : ${j.app.name} v${j.app.version} · ${j.app.environment}`,`Memory : ${j.performance.memoryUsedMb??"—"}/${j.performance.memoryLimitMb??"—"} MB`,`Client : ${j.client.userAgent}`,`Viewport : ${j.client.viewport.width}×${j.client.viewport.height} @${j.client.viewport.dpr}x`,`Reason : ${N4[$.reason.type]}${$.reason.message?` — ${$.reason.message}`:""}`,`Captured : ${$.network.length} requests · ${$.console.length} console · ${$.actionTrail.length} actions · screenshot=${$.screenshotMethod}`]}function L4($){let j=_4($.cause),J=[`## \uD83D\uDC1E ${$.context.app.name} — Debug Report`,`**Generated:** ${$.context.capturedAt}`,"",...f4($).map((Q)=>`- ${Q.replace(/\s{2,}:/,":")}`),"",`**หมายเหตุจากผู้แจ้ง:** ${$.note.trim()||"(ไม่มี)"}`];if(j.length>0)J.push("","### ⚠ สาเหตุที่น่าจะเป็น","```",...j,"```");return J.push("",`<details><summary>ขั้นตอน (${$.actionTrail.length})</summary>`,"","```",O4($.actionTrail),"```","</details>","",`<details><summary>Network (${$.network.length})</summary>`,"","```",R4($.network),"```","</details>","",`<details><summary>Console (${$.console.length})</summary>`,"","```",S4($.console),"```","</details>","","_ข้อมูลลับ (token, cookie) ถูกปกปิดอัตโนมัติ · ภาพหน้าจออยู่ในไฟล์ .zip_"),J.join(`
41
- `)}function k4($){return $.replace(/[:.]/g,"-").replace("T","_").slice(0,19)}function A4($,j){return`debug-report_${k4($.context.capturedAt)}.${j}`}function T4($){return v1($.cause)>0}async function k0(){if(typeof navigator<"u"&&Boolean(navigator.mediaDevices?.getDisplayMedia)){let J=await x4();if(J.status==="ok")return{dataUrl:J.dataUrl,method:"display-media"};if(J.status==="cancelled")return{dataUrl:null,method:"cancelled"}}let j=await h4();if(j)return{dataUrl:j,method:"html-to-image"};return{dataUrl:null,method:"none"}}async function x4(){let $=null;try{let j={video:{frameRate:30},audio:!1,preferCurrentTab:!0,selfBrowserSurface:"include",surfaceSwitching:"exclude"};$=await navigator.mediaDevices.getDisplayMedia(j);let J=await E4($);return J?{status:"ok",dataUrl:J}:{status:"error"}}catch(j){if(j instanceof DOMException&&(j.name==="NotAllowedError"||j.name==="AbortError"))return{status:"cancelled"};return{status:"error"}}finally{$?.getTracks().forEach((j)=>j.stop())}}async function E4($){let j=document.createElement("video");j.srcObject=$,j.muted=!0,j.playsInline=!0,await new Promise((V)=>{let Y=!1,F=()=>{if(Y)return;Y=!0,V()};j.onloadedmetadata=()=>{j.play().then(F).catch(F)},window.setTimeout(F,1500)}),await p4(j);let{videoWidth:J,videoHeight:Q}=j;if(!J||!Q)return null;let Z=document.createElement("canvas");Z.width=J,Z.height=Q;let z=Z.getContext("2d");if(!z)return null;z.drawImage(j,0,0,J,Q),j.pause(),j.srcObject=null;try{return Z.toDataURL("image/png")}catch{return null}}function p4($){return new Promise((j)=>{let J=!1,Q=()=>{if(J)return;J=!0,j()},Z=$;if(typeof Z.requestVideoFrameCallback==="function")Z.requestVideoFrameCallback(()=>Q()),window.setTimeout(Q,1000);else window.setTimeout(Q,250)})}async function h4(){let $=B().screenshotFallback;if(!$)return null;let j=await $().catch(()=>null);if(!j)return null;try{return await j(document.body,{cacheBust:!0,pixelRatio:Math.min(window.devicePixelRatio||1,2),filter:(J)=>!(J instanceof HTMLElement&&J.dataset?.debugReporter==="true")})}catch{return null}}var v4=2000,g4=0.82,m4=3000000;function y4($){return new Promise((j,J)=>{let Q=new Image;Q.onload=()=>j(Q),Q.onerror=()=>J(Error("could not read the screenshot")),Q.src=$})}async function b1($){try{let j=await y4($),J=Math.max(j.naturalWidth,j.naturalHeight),Q=Math.min(1,v4/J),Z=document.createElement("canvas");Z.width=Math.max(1,Math.round(j.naturalWidth*Q)),Z.height=Math.max(1,Math.round(j.naturalHeight*Q));let z=Z.getContext("2d");if(!z)return $;z.fillStyle="#fff",z.fillRect(0,0,Z.width,Z.height),z.drawImage(j,0,0,Z.width,Z.height);let V=g4,Y=Z.toDataURL("image/jpeg",V);while(Y.length>m4&&V>0.4)V-=0.15,Y=Z.toDataURL("image/jpeg",V);return Y}catch{return $}}var b4=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,u4=/^\d+$/,d4=/^[0-9a-f]{16,}$/i;function A0($){if($.reason.type==="manual")return null;let j=$.cause?.failedRequests?.[0];if(!j?.url)return null;let J;try{J=new URL(j.url,"http://x").pathname}catch{J=j.url}let Q=J.split("/").map((z)=>b4.test(z)||u4.test(z)||d4.test(z)?":id":z).join("/"),Z=j.status??(j.error?"ERR":"?");return`${j.method??"REQ"} ${Q} ${Z}`}var T0=2000000;function z0($){let{screenshotDataUrl:j,...J}=$;return JSON.stringify(J).length}function x0($,j=2000000){if(z0($)<=j)return $;let J=$.network.map((Z)=>({...Z})),Q={...$,network:J};for(let Z of J){if(z0(Q)<=j)return Q;if(typeof Z.responseSnippet==="string"&&Z.responseSnippet.length>35)Z.responseSnippet="[body dropped — report size budget]";if(typeof Z.requestBody==="string"&&Z.requestBody.length>35)Z.requestBody="[body dropped — report size budget]"}while(Q.network.length>1&&z0(Q)>j)Q.network=Q.network.slice(1);while(Q.console.length>1&&z0(Q)>j)Q.console=Q.console.slice(1);return Q}var u1=32768;function c4($){let j="";for(let J=0;J<$.length;J+=u1)j+=String.fromCharCode(...$.subarray(J,J+u1));return btoa(j)}function i4($){return{dataUri:`data:application/json;base64,${c4(new TextEncoder().encode(JSON.stringify($)))}`,filename:"debug-bundle.json"}}async function E0($,j){let J=B(),Q=x0(j,T0),{context:Z,note:z}=Q,V=[];if(Q.screenshotDataUrl){let P=await b1(Q.screenshotDataUrl);V.push({dataUri:P,filename:"screenshot.jpg"})}V.push(i4(Q));let Y=A0(Q),F={title:$,description:z.trim()||void 0,category:Z.module?.label||x().name,routeUrl:Z.route.href,priority:"MEDIUM",requesterEmail:Z.user.email??void 0,requesterName:Z.user.fullName??void 0,customFields:{unit:Z.user.unit??"",appVersion:Z.app.version,environment:Z.app.environment,reasonType:Q.reason.type,appName:x().name,module:Z.module?.label??""},context:{...Y?{signature:Y}:{},capturedAt:Z.capturedAt,reason:Q.reason,cause:Q.cause,actionTrail:Q.actionTrail,client:Z.client,performance:Z.performance,apiHeaders:Z.apiHeaders,extra:Z.extra,counts:{network:Q.network.length,console:Q.console.length,actions:Q.actionTrail.length},screenshotMethod:Q.screenshotMethod},attachments:V},C=await fetch(`${J.host.replace(/\/$/,"")}/ingest/tickets`,{method:"POST",headers:{"content-type":"application/json","x-realm-key":J.realmKey},body:JSON.stringify(F)});if(!C.ok){let P=C.headers.get("retry-after"),I=await C.json().then((w)=>w.error).catch(()=>null);throw Error(C.status===429?`Too many reports — try again in ${P??"a moment"}s`:I??`Report failed (${C.status})`)}return await C.json()}var a=Math.PI/6;function d1($,j,J){let Q=j.x-$.x,Z=j.y-$.y,z=Math.hypot(Q,Z),V=Math.atan2(Z,Q),Y=[{x:j.x,y:j.y},{x:j.x-J*Math.cos(V-a),y:j.y-J*Math.sin(V-a)},{x:j.x-J*Math.cos(V+a),y:j.y-J*Math.sin(V+a)}],F=J*Math.cos(a)*0.92;if(z<=F)return{shaft:null,head:Y};return{shaft:{from:$,to:{x:j.x-F*Math.cos(V),y:j.y-F*Math.sin(V)}},head:Y}}var p0="#f44336",o4="rgba(250, 204, 21, 0.4)",h0=22,c1="#2563eb",i1=9,o1=11,l1=18,n1=4,W0=8,l4=[{id:"nw",fx:0,fy:0,cursor:"nwse-resize"},{id:"n",fx:0.5,fy:0,cursor:"ns-resize"},{id:"ne",fx:1,fy:0,cursor:"nesw-resize"},{id:"e",fx:1,fy:0.5,cursor:"ew-resize"},{id:"se",fx:1,fy:1,cursor:"nwse-resize"},{id:"s",fx:0.5,fy:1,cursor:"ns-resize"},{id:"sw",fx:0,fy:1,cursor:"nesw-resize"},{id:"w",fx:0,fy:0.5,cursor:"ew-resize"}];function v0($,j,J){let Q=[],Z=null,z=-1,V=null,Y=null,F=$.getContext("2d");function C(){let W=$.getBoundingClientRect().width;return W>0?$.width/W:1}function P(W){let K=$.getBoundingClientRect();return{x:(W.clientX-K.left)/K.width*$.width,y:(W.clientY-K.top)/K.height*$.height}}function I(W){let K=W.size??h0;if(!F)return(W.text?.length??0)*K*0.6;F.save(),F.font=`600 ${K}px system-ui, sans-serif`;let G=F.measureText(W.text??"").width;return F.restore(),G}function w(W){if(W.tool==="text"){let K=W.size??h0;return{left:W.x1,top:W.y1,right:W.x1+I(W),bottom:W.y1+K*1.25}}return{left:Math.min(W.x1,W.x2),top:Math.min(W.y1,W.y2),right:Math.max(W.x1,W.x2),bottom:Math.max(W.y1,W.y2)}}function q(W){if(W.tool==="arrow")return[{id:"tail",x:W.x1,y:W.y1,cursor:"move"},{id:"head",x:W.x2,y:W.y2,cursor:"move"}];let K=w(W);if(W.tool==="text")return[{id:"size",x:K.right,y:K.bottom,cursor:"nwse-resize"}];return l4.map((G)=>({id:G.id,x:K.left+(K.right-K.left)*G.fx,y:K.top+(K.bottom-K.top)*G.fy,cursor:G.cursor}))}function N(W){let K=w(W);return{x:K.right+l1*C(),y:K.top-l1*C()}}function R(W,K,G){let{shaft:X,head:H}=d1({x:K.x1,y:K.y1},{x:K.x2,y:K.y2},Math.max(10,16*G));if(X)W.lineCap="butt",W.beginPath(),W.moveTo(X.from.x,X.from.y),W.lineTo(X.to.x,X.to.y),W.stroke();W.beginPath(),W.moveTo(H[0].x,H[0].y),W.lineTo(H[1].x,H[1].y),W.lineTo(H[2].x,H[2].y),W.closePath(),W.fill()}function _(W,K,G){W.save(),W.lineWidth=Math.max(2,3*G),W.strokeStyle=p0,W.fillStyle=p0;let X=w(K);if(K.tool==="rect")W.strokeRect(X.left,X.top,X.right-X.left,X.bottom-X.top);else if(K.tool==="arrow")R(W,K,G);else if(K.tool==="highlight")W.fillStyle=o4,W.fillRect(X.left,X.top,X.right-X.left,X.bottom-X.top);else if(K.tool==="text"&&K.text){let H=K.size??h0;W.font=`600 ${H}px system-ui, sans-serif`,W.textBaseline="top";let M=H*0.22;W.fillStyle="rgba(255,255,255,0.92)",W.fillRect(X.left-M,X.top-M,X.right-X.left+M*2,X.bottom-X.top+M*2),W.fillStyle=p0,W.fillText(K.text,X.left,X.top)}W.restore()}function D(W,K,G){let X=w(K);W.save(),W.strokeStyle=c1,W.lineWidth=Math.max(1,1.5*G),W.setLineDash([6*G,4*G]),W.strokeRect(X.left,X.top,X.right-X.left,X.bottom-X.top),W.setLineDash([]);let H=i1*G;for(let f of q(K))W.fillStyle="#fff",W.strokeStyle=c1,W.lineWidth=Math.max(1,1.5*G),W.beginPath(),W.rect(f.x-H/2,f.y-H/2,H,H),W.fill(),W.stroke();let M=N(K),U=o1*G;W.beginPath(),W.arc(M.x,M.y,U,0,Math.PI*2),W.fillStyle="#dc2626",W.fill(),W.strokeStyle="#fff",W.lineWidth=Math.max(1.5,2*G),W.beginPath(),W.moveTo(M.x-U*0.4,M.y-U*0.4),W.lineTo(M.x+U*0.4,M.y+U*0.4),W.moveTo(M.x+U*0.4,M.y-U*0.4),W.lineTo(M.x-U*0.4,M.y+U*0.4),W.stroke(),W.restore()}function S(){if(!F)return;let W=C();if(F.clearRect(0,0,$.width,$.height),F.drawImage(j,0,0,$.width,$.height),Q.forEach((G,X)=>{if(X!==t)_(F,G,W)}),V)_(F,V,W);let K=Q[z];if(K&&!V)D(F,K,W)}function i0(W,K,G,X,H){return Math.abs(W-G)<=H&&Math.abs(K-X)<=H}function o0(W,K){let G=Q[z];if(!G)return null;let X=i1*C()/2+3*C();for(let H of q(G))if(i0(W,K,H.x,H.y,X))return H.id;return null}function l0(W,K){let G=Q[z];if(!G)return!1;let X=N(G);return i0(W,K,X.x,X.y,o1*C())}function Y0(W,K){let G=6*C();for(let X=Q.length-1;X>=0;X-=1){let H=Q[X];if(H.tool==="arrow"){let U=H.x2-H.x1,f=H.y2-H.y1,p=Math.hypot(U,f)||1,h=Math.max(0,Math.min(1,((W-H.x1)*U+(K-H.y1)*f)/(p*p)));if(Math.hypot(W-(H.x1+h*U),K-(H.y1+h*f))<=G+4*C())return X;continue}let M=w(H);if(W>=M.left-G&&W<=M.right+G&&K>=M.top-G&&K<=M.bottom+G)return X}return-1}function X2(W,K,G,X,H){if(K==="tail"){W.x1=G.x1+X,W.y1=G.y1+H;return}if(K==="head"){W.x2=G.x2+X,W.y2=G.y2+H;return}if(K==="size"){let H2=(G.size??24)+H;W.size=Math.max(10,H2);return}let M=w(G),{left:U,top:f,right:p,bottom:h}=M;if(K.includes("w"))U=Math.min(p-W0,U+X);if(K.includes("e"))p=Math.max(U+W0,p+X);if(K.includes("n"))f=Math.min(h-W0,f+H);if(K.includes("s"))h=Math.max(f+W0,h+H);W.x1=U,W.y1=f,W.x2=p,W.y2=h}function Y2(W,K,G,X){W.x1=K.x1+G,W.y1=K.y1+X,W.x2=K.x2+G,W.y2=K.y2+X}let k=null,t=-1,A={x:0,y:0,size:24};function G2(){let W=$.getBoundingClientRect().width;return W>0?W/$.width:1}function F2(W,K){if(!F)return W.length*K*0.6;F.save(),F.font=`600 ${K}px system-ui, sans-serif`;let G=F.measureText(W||" ").width;return F.restore(),G}function n0(){if(!k)return;let W=$.parentElement;if(!W)return;let K=$.getBoundingClientRect(),G=W.getBoundingClientRect(),X=G2(),H=A.size*X;k.style.left=`${K.left-G.left+A.x*X}px`,k.style.top=`${K.top-G.top+A.y*X}px`,k.style.fontSize=`${H}px`,k.style.width=`${Math.max(40,F2(k.value,H)+H)}px`}function l(W){let K=k;if(!K)return;k=null;let G=K.value.trim(),X=t;if(t=-1,K.remove(),W&&G){if(X>=0&&Q[X])Q[X].text=G,z=X;else Q.push({tool:"text",x1:A.x,y1:A.y,x2:A.x,y2:A.y,text:G,size:A.size}),z=Q.length-1;J()}else if(X>=0)z=X;$.focus(),S()}function r0(W,K,G=-1){l(!0);let X=$.parentElement;if(!X)return;if(getComputedStyle(X).position==="static")X.style.position="relative";let H=G>=0?Q[G]:void 0;t=G,A={x:H?.x1??W,y:H?.y1??K,size:H?.size??Math.round(24*C())};let M=document.createElement("input");M.type="text",M.className="text-edit",M.value=H?.text??"",M.setAttribute("aria-label","ข้อความบนภาพ"),M.placeholder="ข้อความ",k=M,X.append(M),n0(),M.addEventListener("input",n0),M.addEventListener("keydown",(U)=>{if(U.stopPropagation(),U.key==="Enter")l(!0);else if(U.key==="Escape")l(!1)}),requestAnimationFrame(()=>{if(k!==M)return;M.focus(),M.select(),M.addEventListener("blur",()=>l(!0))}),S()}function s0(W){let{x:K,y:G}=P(W);if($.setPointerCapture(W.pointerId),l0(K,G)){G0();return}let X=o0(K,G);if(X&&Q[z]){Y={grip:X,x:K,y:G,start:{...Q[z]}};return}if(Z==="text"){if(W.preventDefault(),$.hasPointerCapture(W.pointerId))$.releasePointerCapture(W.pointerId);Z=null,J(),r0(K,G);return}if(Z){V={tool:Z,x1:K,y1:G,x2:K,y2:G},z=-1;return}let H=Y0(K,G);z=H,Y=H>=0?{grip:"body",x:K,y:G,start:{...Q[H]}}:null,S()}function a0(W){let{x:K,y:G}=P(W);if(V){V.x2=K,V.y2=G,S();return}if(Y){let H=Q[z];if(!H)return;let M=K-Y.x,U=G-Y.y;if(Y.grip==="body")Y2(H,Y.start,M,U);else X2(H,Y.grip,Y.start,M,U);S();return}if(Z){$.style.cursor="crosshair";return}if(l0(K,G)){$.style.cursor="pointer";return}let X=o0(K,G);if(X){let H=Q[z]?q(Q[z]).find((M)=>M.id===X):null;$.style.cursor=H?.cursor??"pointer";return}$.style.cursor=Y0(K,G)>=0?"move":"default"}function e(){if(V){if(!(Math.abs(V.x2-V.x1)<n1&&Math.abs(V.y2-V.y1)<n1))Q.push(V),z=Q.length-1,Z=null,J();V=null}if(Y)Y=null,J();S()}function t0(W){let K=$.getBoundingClientRect(),G=(W.clientX-K.left)/K.width*$.width,X=(W.clientY-K.top)/K.height*$.height,H=Y0(G,X),M=Q[H];if(!M||M.tool!=="text")return;W.preventDefault(),r0(M.x1,M.y1,H)}function e0(W){if(z<0)return;if(W.key==="Delete"||W.key==="Backspace")W.preventDefault(),G0();else if(W.key==="Escape")z=-1,S()}function G0(){if(z<0)return;Q.splice(z,1),z=-1,J(),S()}return $.addEventListener("pointerdown",s0),$.addEventListener("pointermove",a0),$.addEventListener("pointerup",e),$.addEventListener("pointercancel",e),$.addEventListener("dblclick",t0),$.tabIndex=0,$.addEventListener("keydown",e0),S(),{setTool(W){Z=W,z=-1,$.style.cursor=W?"crosshair":"default",S()},deleteSelected:G0,clear(){Q.length=0,z=-1,J(),S()},hasShapes:()=>Q.length>0,hasSelection:()=>z>=0,toDataUrl(){let W=document.createElement("canvas");W.width=j.naturalWidth,W.height=j.naturalHeight;let K=W.getContext("2d");if(!K)return $.toDataURL("image/png");K.drawImage(j,0,0);let G=C();for(let X of Q)_(K,X,G);return W.toDataURL("image/png")},destroy(){l(!1),$.removeEventListener("pointerdown",s0),$.removeEventListener("pointermove",a0),$.removeEventListener("pointerup",e),$.removeEventListener("pointercancel",e),$.removeEventListener("dblclick",t0),$.removeEventListener("keydown",e0)}}}var r1=`
37
+ `)}function V4($){if($.length===0)return"No console output captured.";return $.map((j)=>`[${j.at}] ${j.level.toUpperCase()}: ${j.message}`).join(`
38
+ `)}function X4($){if($.length===0)return"No user actions captured.";let j=0;return $.map((J)=>{let Q=J.source?` (${J.source})`:"",z=`${J.detail}${H0(J.count)}${Q}`;if(J.kind==="ui")return` ↳ [${J.at}] ${z}`;j+=1;let W=`${j}. [${J.at}] ${z}`;return J.afterNote?`${W}
39
+ ↳ ${J.afterNote}`:W}).join(`
40
+ `)}function Y4($){let j=[];for(let J of $.failedRequests)j.push(`✗ ${J.status??J.error??"ERR"} ${J.method} ${J.url}`);for(let J of $.errors)j.push(`⚠ ${J}`);for(let J of $.erroredQueries)j.push(`⚠ React Query error: ${J.key} — ${J.error}`);return j}function F4($){let{context:j}=$;return[`User : ${j.user.fullName??"—"} (${j.user.email??"—"})`,`Unit : ${j.user.unit??"—"}`,`Roles : ${j.user.roles?.join(", ")||"—"}`,`Route : ${j.route.href}`,`Module : ${j.module?`${j.module.label} (${j.module.key})`:"—"}`,`App : ${j.app.name} v${j.app.version} · ${j.app.environment}`,`Memory : ${j.performance.memoryUsedMb??"—"}/${j.performance.memoryLimitMb??"—"} MB`,`Client : ${j.client.userAgent}`,`Viewport : ${j.client.viewport.width}×${j.client.viewport.height} @${j.client.viewport.dpr}x`,`Reason : ${W4[$.reason.type]}${$.reason.message?` — ${$.reason.message}`:""}`,`Captured : ${$.network.length} requests · ${$.console.length} console · ${$.actionTrail.length} actions · screenshot=${$.screenshotMethod}`]}function w4($){let j=Y4($.cause),J=[`## \uD83D\uDC1E ${$.context.app.name} — Debug Report`,`**Generated:** ${$.context.capturedAt}`,"",...F4($).map((Q)=>`- ${Q.replace(/\s{2,}:/,":")}`),"",`**หมายเหตุจากผู้แจ้ง:** ${$.note.trim()||"(ไม่มี)"}`];if(j.length>0)J.push("","### ⚠ สาเหตุที่น่าจะเป็น","```",...j,"```");return J.push("",`<details><summary>ขั้นตอน (${$.actionTrail.length})</summary>`,"","```",X4($.actionTrail),"```","</details>","",`<details><summary>Network (${$.network.length})</summary>`,"","```",G4($.network),"```","</details>","",`<details><summary>Console (${$.console.length})</summary>`,"","```",V4($.console),"```","</details>","","_ข้อมูลลับ (token, cookie) ถูกปกปิดอัตโนมัติ · ภาพหน้าจออยู่ในไฟล์ .zip_"),J.join(`
41
+ `)}function H4($){return $.replace(/[:.]/g,"-").replace("T","_").slice(0,19)}function M4($,j){return`debug-report_${H4($.context.capturedAt)}.${j}`}function C4($){return L1($.cause)>0}async function k0(){if(typeof navigator<"u"&&Boolean(navigator.mediaDevices?.getDisplayMedia)){let J=await U4();if(J.status==="ok")return{dataUrl:J.dataUrl,method:"display-media"};if(J.status==="cancelled")return{dataUrl:null,method:"cancelled"}}let j=await D4();if(j)return{dataUrl:j,method:"html-to-image"};return{dataUrl:null,method:"none"}}async function U4(){let $=null;try{let j={video:{frameRate:30},audio:!1,preferCurrentTab:!0,selfBrowserSurface:"include",surfaceSwitching:"exclude"};$=await navigator.mediaDevices.getDisplayMedia(j);let J=await I4($);return J?{status:"ok",dataUrl:J}:{status:"error"}}catch(j){if(j instanceof DOMException&&(j.name==="NotAllowedError"||j.name==="AbortError"))return{status:"cancelled"};return{status:"error"}}finally{$?.getTracks().forEach((j)=>j.stop())}}async function I4($){let j=document.createElement("video");j.srcObject=$,j.muted=!0,j.playsInline=!0,await new Promise((K)=>{let Y=!1,w=()=>{if(Y)return;Y=!0,K()};j.onloadedmetadata=()=>{j.play().then(w).catch(w)},window.setTimeout(w,1500)}),await P4(j);let{videoWidth:J,videoHeight:Q}=j;if(!J||!Q)return null;let z=document.createElement("canvas");z.width=J,z.height=Q;let W=z.getContext("2d");if(!W)return null;W.drawImage(j,0,0,J,Q),j.pause(),j.srcObject=null;try{return z.toDataURL("image/png")}catch{return null}}function P4($){return new Promise((j)=>{let J=!1,Q=()=>{if(J)return;J=!0,j()},z=$;if(typeof z.requestVideoFrameCallback==="function")z.requestVideoFrameCallback(()=>Q()),window.setTimeout(Q,1000);else window.setTimeout(Q,250)})}async function D4(){let $=B().screenshotFallback;if(!$)return null;let j=await $().catch(()=>null);if(!j)return null;try{return await j(document.body,{cacheBust:!0,pixelRatio:Math.min(window.devicePixelRatio||1,2),filter:(J)=>!(J instanceof HTMLElement&&J.dataset?.debugReporter==="true")})}catch{return null}}var N4=2000,B4=0.82,S4=3000000;function q4($){return new Promise((j,J)=>{let Q=new Image;Q.onload=()=>j(Q),Q.onerror=()=>J(Error("could not read the screenshot")),Q.src=$})}async function x1($){try{let j=await q4($),J=Math.max(j.naturalWidth,j.naturalHeight),Q=Math.min(1,N4/J),z=document.createElement("canvas");z.width=Math.max(1,Math.round(j.naturalWidth*Q)),z.height=Math.max(1,Math.round(j.naturalHeight*Q));let W=z.getContext("2d");if(!W)return $;W.fillStyle="#fff",W.fillRect(0,0,z.width,z.height),W.drawImage(j,0,0,z.width,z.height);let K=B4,Y=z.toDataURL("image/jpeg",K);while(Y.length>S4&&K>0.4)K-=0.15,Y=z.toDataURL("image/jpeg",K);return Y}catch{return $}}var f4=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,R4=/^\d+$/,k4=/^[0-9a-f]{16,}$/i;function O0($){if($.reason.type==="manual")return null;let j=$.cause?.failedRequests?.[0];if(!j?.url)return null;let J;try{J=new URL(j.url,"http://x").pathname}catch{J=j.url}let Q=J.split("/").map((W)=>f4.test(W)||R4.test(W)||k4.test(W)?":id":W).join("/"),z=j.status??(j.error?"ERR":"?");return`${j.method??"REQ"} ${Q} ${z}`}var _0=2000000;function z0($){let{screenshotDataUrl:j,...J}=$;return JSON.stringify(J).length}function L0($,j=2000000){if(z0($)<=j)return $;let J=$.network.map((z)=>({...z})),Q={...$,network:J};for(let z of J){if(z0(Q)<=j)return Q;if(typeof z.responseSnippet==="string"&&z.responseSnippet.length>35)z.responseSnippet="[body dropped — report size budget]";if(typeof z.requestBody==="string"&&z.requestBody.length>35)z.requestBody="[body dropped — report size budget]"}while(Q.network.length>1&&z0(Q)>j)Q.network=Q.network.slice(1);while(Q.console.length>1&&z0(Q)>j)Q.console=Q.console.slice(1);return Q}var h1=32768;function O4($){let j="";for(let J=0;J<$.length;J+=h1)j+=String.fromCharCode(...$.subarray(J,J+h1));return btoa(j)}function _4($){return{dataUri:`data:application/json;base64,${O4(new TextEncoder().encode(JSON.stringify($)))}`,filename:"debug-bundle.json"}}async function L4(){let $=B().identity;if(!$)return{};try{let j=await $();return j?{authorization:`Bearer ${j}`}:{}}catch{return{}}}async function A0($,j){let J=B(),Q=L0(j,_0),{context:z,note:W}=Q,K=[];if(Q.screenshotDataUrl){let U=await x1(Q.screenshotDataUrl);K.push({dataUri:U,filename:"screenshot.jpg"})}K.push(_4(Q));let Y=O0(Q),w={title:$,description:W.trim()||void 0,category:z.module?.label||T().name,routeUrl:z.route.href,priority:"MEDIUM",requesterEmail:z.user.email??void 0,requesterName:z.user.fullName??void 0,customFields:{unit:z.user.unit??"",appVersion:z.app.version,environment:z.app.environment,reasonType:Q.reason.type,appName:T().name,module:z.module?.label??""},context:{...Y?{signature:Y}:{},capturedAt:z.capturedAt,reason:Q.reason,cause:Q.cause,actionTrail:Q.actionTrail,client:z.client,performance:z.performance,apiHeaders:z.apiHeaders,extra:z.extra,counts:{network:Q.network.length,console:Q.console.length,actions:Q.actionTrail.length},screenshotMethod:Q.screenshotMethod},attachments:K},M=await fetch(`${J.host.replace(/\/$/,"")}/ingest/tickets`,{method:"POST",headers:{"content-type":"application/json","x-realm-key":J.realmKey,...await L4()},body:JSON.stringify(w)});if(!M.ok){let U=M.headers.get("retry-after"),P=await M.json().then((I)=>I.error).catch(()=>null);throw Error(M.status===429?`Too many reports — try again in ${U??"a moment"}s`:P??`Report failed (${M.status})`)}return await M.json()}var s=Math.PI/6;function p1($,j,J){let Q=j.x-$.x,z=j.y-$.y,W=Math.hypot(Q,z),K=Math.atan2(z,Q),Y=[{x:j.x,y:j.y},{x:j.x-J*Math.cos(K-s),y:j.y-J*Math.sin(K-s)},{x:j.x-J*Math.cos(K+s),y:j.y-J*Math.sin(K+s)}],w=J*Math.cos(s)*0.92;if(W<=w)return{shaft:null,head:Y};return{shaft:{from:$,to:{x:j.x-w*Math.cos(K),y:j.y-w*Math.sin(K)}},head:Y}}var T0="#f44336",A4="rgba(250, 204, 21, 0.4)",E0=22,g1="#2563eb",m1=9,v1=11,y1=18,b1=4,Z0=8,T4=[{id:"nw",fx:0,fy:0,cursor:"nwse-resize"},{id:"n",fx:0.5,fy:0,cursor:"ns-resize"},{id:"ne",fx:1,fy:0,cursor:"nesw-resize"},{id:"e",fx:1,fy:0.5,cursor:"ew-resize"},{id:"se",fx:1,fy:1,cursor:"nwse-resize"},{id:"s",fx:0.5,fy:1,cursor:"ns-resize"},{id:"sw",fx:0,fy:1,cursor:"nesw-resize"},{id:"w",fx:0,fy:0.5,cursor:"ew-resize"}];function x0($,j,J){let Q=[],z=null,W=-1,K=null,Y=null,w=$.getContext("2d");function M(){let Z=$.getBoundingClientRect().width;return Z>0?$.width/Z:1}function U(Z){let G=$.getBoundingClientRect();return{x:(Z.clientX-G.left)/G.width*$.width,y:(Z.clientY-G.top)/G.height*$.height}}function P(Z){let G=Z.size??E0;if(!w)return(Z.text?.length??0)*G*0.6;w.save(),w.font=`600 ${G}px system-ui, sans-serif`;let X=w.measureText(Z.text??"").width;return w.restore(),X}function I(Z){if(Z.tool==="text"){let G=Z.size??E0;return{left:Z.x1,top:Z.y1,right:Z.x1+P(Z),bottom:Z.y1+G*1.25}}return{left:Math.min(Z.x1,Z.x2),top:Math.min(Z.y1,Z.y2),right:Math.max(Z.x1,Z.x2),bottom:Math.max(Z.y1,Z.y2)}}function S(Z){if(Z.tool==="arrow")return[{id:"tail",x:Z.x1,y:Z.y1,cursor:"move"},{id:"head",x:Z.x2,y:Z.y2,cursor:"move"}];let G=I(Z);if(Z.tool==="text")return[{id:"size",x:G.right,y:G.bottom,cursor:"nwse-resize"}];return T4.map((X)=>({id:X.id,x:G.left+(G.right-G.left)*X.fx,y:G.top+(G.bottom-G.top)*X.fy,cursor:X.cursor}))}function N(Z){let G=I(Z);return{x:G.right+y1*M(),y:G.top-y1*M()}}function q(Z,G,X){let{shaft:V,head:F}=p1({x:G.x1,y:G.y1},{x:G.x2,y:G.y2},Math.max(10,16*X));if(V)Z.lineCap="butt",Z.beginPath(),Z.moveTo(V.from.x,V.from.y),Z.lineTo(V.to.x,V.to.y),Z.stroke();Z.beginPath(),Z.moveTo(F[0].x,F[0].y),Z.lineTo(F[1].x,F[1].y),Z.lineTo(F[2].x,F[2].y),Z.closePath(),Z.fill()}function k(Z,G,X){Z.save(),Z.lineWidth=Math.max(2,3*X),Z.strokeStyle=T0,Z.fillStyle=T0;let V=I(G);if(G.tool==="rect")Z.strokeRect(V.left,V.top,V.right-V.left,V.bottom-V.top);else if(G.tool==="arrow")q(Z,G,X);else if(G.tool==="highlight")Z.fillStyle=A4,Z.fillRect(V.left,V.top,V.right-V.left,V.bottom-V.top);else if(G.tool==="text"&&G.text){let F=G.size??E0;Z.font=`600 ${F}px system-ui, sans-serif`,Z.textBaseline="top";let H=F*0.22;Z.fillStyle="rgba(255,255,255,0.92)",Z.fillRect(V.left-H,V.top-H,V.right-V.left+H*2,V.bottom-V.top+H*2),Z.fillStyle=T0,Z.fillText(G.text,V.left,V.top)}Z.restore()}function D(Z,G,X){let V=I(G);Z.save(),Z.strokeStyle=g1,Z.lineWidth=Math.max(1,1.5*X),Z.setLineDash([6*X,4*X]),Z.strokeRect(V.left,V.top,V.right-V.left,V.bottom-V.top),Z.setLineDash([]);let F=m1*X;for(let O of S(G))Z.fillStyle="#fff",Z.strokeStyle=g1,Z.lineWidth=Math.max(1,1.5*X),Z.beginPath(),Z.rect(O.x-F/2,O.y-F/2,F,F),Z.fill(),Z.stroke();let H=N(G),C=v1*X;Z.beginPath(),Z.arc(H.x,H.y,C,0,Math.PI*2),Z.fillStyle="#dc2626",Z.fill(),Z.strokeStyle="#fff",Z.lineWidth=Math.max(1.5,2*X),Z.beginPath(),Z.moveTo(H.x-C*0.4,H.y-C*0.4),Z.lineTo(H.x+C*0.4,H.y+C*0.4),Z.moveTo(H.x+C*0.4,H.y-C*0.4),Z.lineTo(H.x-C*0.4,H.y+C*0.4),Z.stroke(),Z.restore()}function f(){if(!w)return;let Z=M();if(w.clearRect(0,0,$.width,$.height),w.drawImage(j,0,0,$.width,$.height),Q.forEach((X,V)=>{if(V!==a)k(w,X,Z)}),K)k(w,K,Z);let G=Q[W];if(G&&!K)D(w,G,Z)}function m0(Z,G,X,V,F){return Math.abs(Z-X)<=F&&Math.abs(G-V)<=F}function v0(Z,G){let X=Q[W];if(!X)return null;let V=m1*M()/2+3*M();for(let F of S(X))if(m0(Z,G,F.x,F.y,V))return F.id;return null}function y0(Z,G){let X=Q[W];if(!X)return!1;let V=N(X);return m0(Z,G,V.x,V.y,v1*M())}function K0(Z,G){let X=6*M();for(let V=Q.length-1;V>=0;V-=1){let F=Q[V];if(F.tool==="arrow"){let C=F.x2-F.x1,O=F.y2-F.y1,x=Math.hypot(C,O)||1,h=Math.max(0,Math.min(1,((Z-F.x1)*C+(G-F.y1)*O)/(x*x)));if(Math.hypot(Z-(F.x1+h*C),G-(F.y1+h*O))<=X+4*M())return V;continue}let H=I(F);if(Z>=H.left-X&&Z<=H.right+X&&G>=H.top-X&&G<=H.bottom+X)return V}return-1}function l1(Z,G,X,V,F){if(G==="tail"){Z.x1=X.x1+V,Z.y1=X.y1+F;return}if(G==="head"){Z.x2=X.x2+V,Z.y2=X.y2+F;return}if(G==="size"){let a1=(X.size??24)+F;Z.size=Math.max(10,a1);return}let H=I(X),{left:C,top:O,right:x,bottom:h}=H;if(G.includes("w"))C=Math.min(x-Z0,C+V);if(G.includes("e"))x=Math.max(C+Z0,x+V);if(G.includes("n"))O=Math.min(h-Z0,O+F);if(G.includes("s"))h=Math.max(O+Z0,h+F);Z.x1=C,Z.y1=O,Z.x2=x,Z.y2=h}function r1(Z,G,X,V){Z.x1=G.x1+X,Z.y1=G.y1+V,Z.x2=G.x2+X,Z.y2=G.y2+V}let L=null,a=-1,A={x:0,y:0,size:24};function n1(){let Z=$.getBoundingClientRect().width;return Z>0?Z/$.width:1}function s1(Z,G){if(!w)return Z.length*G*0.6;w.save(),w.font=`600 ${G}px system-ui, sans-serif`;let X=w.measureText(Z||" ").width;return w.restore(),X}function b0(){if(!L)return;let Z=$.parentElement;if(!Z)return;let G=$.getBoundingClientRect(),X=Z.getBoundingClientRect(),V=n1(),F=A.size*V;L.style.left=`${G.left-X.left+A.x*V}px`,L.style.top=`${G.top-X.top+A.y*V}px`,L.style.fontSize=`${F}px`,L.style.width=`${Math.max(40,s1(L.value,F)+F)}px`}function c(Z){let G=L;if(!G)return;L=null;let X=G.value.trim(),V=a;if(a=-1,G.remove(),Z&&X){if(V>=0&&Q[V])Q[V].text=X,W=V;else Q.push({tool:"text",x1:A.x,y1:A.y,x2:A.x,y2:A.y,text:X,size:A.size}),W=Q.length-1;J()}else if(V>=0)W=V;$.focus(),f()}function u0(Z,G,X=-1){c(!0);let V=$.parentElement;if(!V)return;if(getComputedStyle(V).position==="static")V.style.position="relative";let F=X>=0?Q[X]:void 0;a=X,A={x:F?.x1??Z,y:F?.y1??G,size:F?.size??Math.round(24*M())};let H=document.createElement("input");H.type="text",H.className="text-edit",H.value=F?.text??"",H.setAttribute("aria-label","ข้อความบนภาพ"),H.placeholder="ข้อความ",L=H,V.append(H),b0(),H.addEventListener("input",b0),H.addEventListener("keydown",(C)=>{if(C.stopPropagation(),C.key==="Enter")c(!0);else if(C.key==="Escape")c(!1)}),requestAnimationFrame(()=>{if(L!==H)return;H.focus(),H.select(),H.addEventListener("blur",()=>c(!0))}),f()}function d0(Z){let{x:G,y:X}=U(Z);if($.setPointerCapture(Z.pointerId),y0(G,X)){G0();return}let V=v0(G,X);if(V&&Q[W]){Y={grip:V,x:G,y:X,start:{...Q[W]}};return}if(z==="text"){if(Z.preventDefault(),$.hasPointerCapture(Z.pointerId))$.releasePointerCapture(Z.pointerId);z=null,J(),u0(G,X);return}if(z){K={tool:z,x1:G,y1:X,x2:G,y2:X},W=-1;return}let F=K0(G,X);W=F,Y=F>=0?{grip:"body",x:G,y:X,start:{...Q[F]}}:null,f()}function i0(Z){let{x:G,y:X}=U(Z);if(K){K.x2=G,K.y2=X,f();return}if(Y){let F=Q[W];if(!F)return;let H=G-Y.x,C=X-Y.y;if(Y.grip==="body")r1(F,Y.start,H,C);else l1(F,Y.grip,Y.start,H,C);f();return}if(z){$.style.cursor="crosshair";return}if(y0(G,X)){$.style.cursor="pointer";return}let V=v0(G,X);if(V){let F=Q[W]?S(Q[W]).find((H)=>H.id===V):null;$.style.cursor=F?.cursor??"pointer";return}$.style.cursor=K0(G,X)>=0?"move":"default"}function t(){if(K){if(!(Math.abs(K.x2-K.x1)<b1&&Math.abs(K.y2-K.y1)<b1))Q.push(K),W=Q.length-1,z=null,J();K=null}if(Y)Y=null,J();f()}function o0(Z){let G=$.getBoundingClientRect(),X=(Z.clientX-G.left)/G.width*$.width,V=(Z.clientY-G.top)/G.height*$.height,F=K0(X,V),H=Q[F];if(!H||H.tool!=="text")return;Z.preventDefault(),u0(H.x1,H.y1,F)}function c0(Z){if(W<0)return;if(Z.key==="Delete"||Z.key==="Backspace")Z.preventDefault(),G0();else if(Z.key==="Escape")W=-1,f()}function G0(){if(W<0)return;Q.splice(W,1),W=-1,J(),f()}return $.addEventListener("pointerdown",d0),$.addEventListener("pointermove",i0),$.addEventListener("pointerup",t),$.addEventListener("pointercancel",t),$.addEventListener("dblclick",o0),$.tabIndex=0,$.addEventListener("keydown",c0),f(),{setTool(Z){z=Z,W=-1,$.style.cursor=Z?"crosshair":"default",f()},deleteSelected:G0,clear(){Q.length=0,W=-1,J(),f()},hasShapes:()=>Q.length>0,hasSelection:()=>W>=0,toDataUrl(){let Z=document.createElement("canvas");Z.width=j.naturalWidth,Z.height=j.naturalHeight;let G=Z.getContext("2d");if(!G)return $.toDataURL("image/png");G.drawImage(j,0,0);let X=M();for(let V of Q)k(G,V,X);return Z.toDataURL("image/png")},destroy(){c(!1),$.removeEventListener("pointerdown",d0),$.removeEventListener("pointermove",i0),$.removeEventListener("pointerup",t),$.removeEventListener("pointercancel",t),$.removeEventListener("dblclick",o0),$.removeEventListener("keydown",c0)}}}var u1=`
42
42
  :host { all: initial; }
43
43
  * { box-sizing: border-box; }
44
44
 
@@ -121,9 +121,4 @@ canvas { width: 100%; height: auto; display: block; border: 1px solid #e2e8f0; b
121
121
  border-radius: 0 0 16px 16px;
122
122
  }
123
123
  .foot .grow { flex: 1; }
124
- `;var o="lw-debug-reporter",s1=()=>[];function n4($){s1=$}var r4=[{tool:"rect",key:"toolRect"},{tool:"arrow",key:"toolArrow"},{tool:"highlight",key:"toolHighlight"},{tool:"text",key:"toolText"}];function s4(){return class extends HTMLElement{root;stop=null;annotator=null;bundle=null;busy=!1;constructor(){super();this.root=this.attachShadow({mode:"open"})}connectedCallback(){this.dataset.debugReporter="true",this.stop=N0((j)=>void this.open(j))}disconnectedCallback(){this.stop?.(),this.stop=null,this.close()}async open(j){if(this.busy)return;this.busy=!0;let J=s(B().locale),Q=await k0();if(Q.method==="cancelled"){this.close();return}this.bundle=L0({reason:j,note:"",screenshotDataUrl:Q.dataUrl,screenshotMethod:Q.method,erroredQueries:a4()}),this.renderForm(J)}close(){this.annotator?.destroy(),this.annotator=null,this.bundle=null,this.busy=!1,this.root.replaceChildren()}shell(j){let J=document.createElement("style");J.textContent=r1;let Q=document.createElement("div");Q.className="backdrop";let Z=document.createElement("div");return Z.className="panel",Z.setAttribute("role","dialog"),Z.setAttribute("aria-modal","true"),Z.setAttribute("aria-label",j.title),Q.append(Z),this.root.replaceChildren(J,Q),Z}renderShell(j,J){let Q=this.shell(j),Z=O("div","head");Z.append(O("h2","",j.title)),Q.append(Z,O("p","status",J))}renderForm(j){let J=this.bundle;if(!J)return;let Q=this.shell(j),Z=O("div","head"),z=i("✕","icon");z.setAttribute("aria-label",j.close),z.addEventListener("click",()=>this.close()),Z.append(O("h2","",j.title),z);let V=document.createElement("input");V.type="text",V.placeholder=j.summaryPlaceholder;let Y=g0(j.summaryLabel,j.summaryRequired,!0),F=document.createElement("textarea");F.placeholder=j.detailPlaceholder;let C=O("div","meta");C.innerHTML="";let{context:P}=J;for(let[R,_]of[[j.reporter,`${P.user.fullName??"—"} (${P.user.email??"—"})`],[j.page,P.route.href],[j.captured,`${J.network.length} network · ${J.console.length} console · ${J.actionTrail.length} actions`]]){let D=document.createElement("div"),S=document.createElement("b");S.textContent=`${R}: `,D.append(S,document.createTextNode(_)),C.append(D)}let I=O("p","status",""),w=i(j.submit,"primary");if(w.disabled=!0,V.addEventListener("input",()=>{w.disabled=V.value.trim().length===0}),Q.append(Z,Y,V,g0(j.detailLabel),F,C),J.screenshotDataUrl)Q.append(...this.screenshotSection(j,J.screenshotDataUrl));else Q.append(O("p","status",j.noScreenshot));let q=O("div","foot"),N=i(j.close);N.addEventListener("click",()=>this.close()),q.append(N,I,O("span","grow"),w),Q.append(q),w.addEventListener("click",async()=>{w.disabled=!0,I.dataset.tone="",I.textContent=j.submitting;try{let R=await E0(V.value.trim(),{...J,note:F.value,screenshotDataUrl:this.annotator?.hasShapes()?this.annotator.toDataUrl():J.screenshotDataUrl}),_=this.dispatchEvent(new CustomEvent("lw-report-submitted",{detail:R,bubbles:!0,composed:!0,cancelable:!0}));if(this.close(),_)c(`${j.submitted} — #${R.number}`,"success")}catch(R){let _=R instanceof Error?R.message:j.failed;I.dataset.tone="error",I.textContent=_,c(`${j.failed} — ${_}`,"error"),w.disabled=!1}}),V.focus()}screenshotSection(j,J){let Q=g0(j.annotateHint),Z=O("div","tools"),z=document.createElement("canvas"),V=O("div","shot");V.append(z);let Y=[],F=(w)=>{for(let q of Y)q.setAttribute("aria-pressed",String(q===w))};for(let{tool:w,key:q}of r4){let N=i(j[q]);N.setAttribute("aria-pressed","false"),N.addEventListener("click",()=>{let R=N.getAttribute("aria-pressed")==="true";F(R?null:N),this.annotator?.setTool(R?null:w)}),Y.push(N),Z.append(N)}Z.append(O("span","sep"));let C=i(j.deleteSelected);C.addEventListener("click",()=>this.annotator?.deleteSelected());let P=i(j.clearAll);P.addEventListener("click",()=>{this.annotator?.clear(),F(null)}),Z.append(C,P);let I=new Image;return I.onload=()=>{z.width=I.naturalWidth,z.height=I.naturalHeight,this.annotator=v0(z,I,()=>{F(null),C.disabled=!this.annotator?.hasSelection()})},I.src=J,[Q,Z,O("p","status",j.annotateHelp),V]}}}function a4(){try{return s1()}catch{return[]}}function O($,j="",J=""){let Q=document.createElement($);if(j)Q.className=j;if(J)Q.textContent=J;return Q}function i($,j=""){let J=document.createElement("button");if(J.type="button",J.textContent=$,j)J.className=j;return J}function g0($,j="",J=!1){let Q=document.createElement("label");if(Q.append(document.createTextNode($)),J){let Z=document.createElement("span");Z.className="req",Z.textContent=" *",Q.append(Z)}if(j){let Z=document.createElement("span");Z.className="hint",Z.textContent=` ${j}`,Q.append(Z)}return Q}function m0(){if(typeof window>"u"||customElements.get(o))return;customElements.define(o,s4())}var a1=!1;function t4($={}){if(a1||typeof window>"u")return;if(!F0()){console.error("[debug-capture] configureDebugCapture() must be called before install");return}if(a1=!0,p1(),w1(),H1(),O1(),$.ui===!1)return;let j=s(B().locale);if(R0((J)=>{c(J.message??j.crashed,"error",{label:j.crashAction,onClick:()=>q0(J)})}),m0(),!document.querySelector(o))document.body.append(document.createElement(o))}var e4=new Set(["error","exception","unhandledrejection"]);function t1($){if($.error)return!0;return $.status!==null&&$.status>=400}function y0($){if(!$)return null;let j=Date.parse($);return Number.isNaN(j)?null:j}function $5($){try{let{pathname:j}=new URL($,"http://x");try{return decodeURIComponent(j)}catch{return j}}catch{return $.split(/[?#]/)[0]??$}}function j5($,j,J){let Q=(V)=>({elapsedMs:V,requests:[],failedRequests:[],consoleErrors:[],slowestMs:null});if($.length===0)return[];let Z=$.map((V)=>y0(V.at)),z=(V)=>{for(let Y=V+1;Y<Z.length;Y+=1){let F=Z[Y];if(F!=null)return F}return Number.POSITIVE_INFINITY};return $.map((V,Y)=>{let F=Z[Y]??null,C=(Y>0?Z[Y-1]:null)??null,P=F!==null&&C!==null?Math.max(0,F-C):null;if(F===null)return Q(P);let I=F,w=Math.max(I,z(Y)),q=(D)=>D!==null&&D>=I&&(D<w||w===Number.POSITIVE_INFINITY),N=j.filter((D)=>q(y0(D.startedAt))),R=J.filter((D)=>e4.has(D.level)&&q(y0(D.at))),_=N.map((D)=>D.durationMs).filter((D)=>typeof D==="number");return{elapsedMs:P,requests:N,failedRequests:N.filter(t1),consoleErrors:R,slowestMs:_.length>0?Math.max(..._):null}})}function J5($,j){return $.requests.length===0&&$.consoleErrors.length===0&&($.elapsedMs===null||$.elapsedMs<j)}function Q5($){if($<1000)return`${Math.round($)} มิลลิวินาที`;let j=$/1000;if(j<10)return`${j.toFixed(1)} วิ`;if(j<60)return`${Math.round(j)} วิ`;let J=Math.floor(j/60),Q=Math.round(j%60);return Q===0?`${J} นาที`:`${J} นาที ${Q} วิ`}class X0 extends Error{status;constructor($,j){super($);this.status=j}}class K0 extends Error{constructor(){super("[debug-capture] no reporter identity — configure `identity` to use the tickets panel")}}function e1(){return B().host.replace(/\/$/,"")}async function Z5(){let $=B().identity;if(!$)throw new K0;let j=await $();if(!j)throw new K0;return j}async function T($,j={}){let J=await Z5(),Q=await fetch(`${e1()}/ingest/me${$}`,{...j,headers:{"x-realm-key":B().realmKey,authorization:`Bearer ${J}`,...j.body?{"content-type":"application/json"}:{},...j.headers}});if(!Q.ok){let Z=await Q.json().then((z)=>z.error).catch(()=>null);throw new X0(Z??`Request failed (${Q.status})`,Q.status)}return await Q.json()}async function z5(){let{items:$}=await T("/tickets");return $}function W5($){return T(`/tickets/${encodeURIComponent($)}`)}function V5($){return T(`/tickets/by-number/${$}`)}function K5($){return T(`/attachments/${encodeURIComponent($)}`)}function X5($){return T(`/tickets/${encodeURIComponent($)}/history`)}function Y5($,j){return T(`/tickets/${encodeURIComponent($)}/messages`,{method:"POST",body:JSON.stringify({body:j})})}function G5($,j,J){return T(`/tickets/${encodeURIComponent($)}/messages/${encodeURIComponent(j)}`,{method:"PUT",body:JSON.stringify({body:J})})}function F5($,j){return T(`/tickets/${encodeURIComponent($)}/reopen`,{method:"POST",body:JSON.stringify({note:j?.trim()||void 0})})}function H5($,j,J){return T(`/tickets/${encodeURIComponent($)}/inline-image`,{method:"POST",body:JSON.stringify({dataUri:j,filename:J})})}var V0=null;function M5(){if(!V0){let $=encodeURIComponent(B().realmKey);V0=fetch(`${e1()}/ingest/config?key=${$}`).then((j)=>{if(!j.ok)throw new X0(`Config failed (${j.status})`,j.status);return j.json()}).catch((j)=>{throw V0=null,j})}return V0}function $2($,j){let J=($??"").trim().toUpperCase().replace(/[^A-Z0-9]+/g,"");return J?`${J}-${j}`:`#${j}`}function C5($,j,J){if(!$)return"—";let Q=new Date($);if(Number.isNaN(Q.getTime()))return"—";try{return new Intl.DateTimeFormat(J==="en"?"en-GB":"th-TH-u-ca-buddhist",{dateStyle:"medium",timeStyle:"short",timeZone:j}).format(Q)}catch{return Q.toISOString().slice(0,16).replace("T"," ")}}function U5($,j){let J=new Map($.map((Z)=>[Z.key,Z])),Q=$.map((Z)=>Z.key);return{labelOf:(Z)=>J.get(Z)?.label??Z,columnOf:(Z)=>J.get(Z),isAwaitingReply:(Z)=>J.get(Z)?.awaitingReply===!0,isClosed:(Z)=>J.get(Z)?.bucket==="closed",rankOf:(Z)=>{let z=Q.indexOf(Z);return z===-1?Q.length:z},options:[{value:"",label:j},...$.map((Z)=>({value:Z.key,label:Z.label}))]}}function j2($){return Boolean($.resolutionNote&&$.resolutionNote.trim())}function J2($){return $.agentReplyCount>0}function b0($){return j2($)?2:J2($)?1:0}function P5($,j,J,Q){let Z=j.trim().toLowerCase();if(!Z)return!0;return[$2(J,$.number),String($.number),$.title,$.category??"",Q($.status)].join(" ").toLowerCase().includes(Z)}function w5($,j,J){let Q=$.direction==="asc"?1:-1;return(Z,z)=>{let V=0;switch($.key){case"number":V=Z.number-z.number;break;case"title":V=(Z.title??"").localeCompare(z.title??"","th");break;case"module":V=(Z.category??"").localeCompare(z.category??"","th");break;case"status":V=j.rankOf(Z.status)-j.rankOf(z.status);break;case"response":V=b0(Z)-b0(z);break;case"createdAt":V=Date.parse(Z.createdAt)-Date.parse(z.createdAt);break;case"updatedAt":V=Date.parse(Z.updatedAt)-Date.parse(z.updatedAt);break}return V!==0?V*Q:(Z.number-z.number)*Q}}var d0=10;function I5($,j,J=d0){return $.slice((j-1)*J,j*J)}function D5($,j=d0){return Math.max(1,Math.ceil($/j))}var u0={blue:{fg:"#1c5cab",bg:"#e8f1fd"},amber:{fg:"#92400e",bg:"#fef3c7"},violet:{fg:"#4a3aa7",bg:"#ece9fb"},emerald:{fg:"#0f766e",bg:"#d9f2ec"},gray:{fg:"#4b5563",bg:"#f1f2f4"},red:{fg:"#b91c1c",bg:"#fde8e8"},sky:{fg:"#0369a1",bg:"#e0f2fe"},rose:{fg:"#be123c",bg:"#ffe4e9"},teal:{fg:"#0f766e",bg:"#d7f2ef"},orange:{fg:"#c2410c",bg:"#ffedd5"}};function B5($){return u0[$??""]??u0.gray}var Q2=new Set(["p","br","strong","b","em","i","u","s","code","pre","ul","ol","li","blockquote","h1","h2","h3","a","img","span"]),Z2=new Set(["href","target","rel","src","alt","title"]),N5=/^\/api\/inline\/[a-f0-9]{64}$/i;function z2($){return/^(?:https?:\/\/|mailto:|#|\/)/i.test($.trim())}function W2($,j){try{let J=new URL($.trim(),j);return J.origin===new URL(j).origin&&N5.test(J.pathname)}catch{return!1}}var q5=/<\/(p|div|li|h[1-6]|tr)\s*>/gi,R5=/<br\s*\/?>/gi,S5=/<[^>]*>/g,O5={"&nbsp;":" ","&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"};function c0($){return/<[a-z/][^>]*>/i.test($)}function _5($){if(!c0($))return $;return $.replace(R5,`
125
- `).replace(q5,`
126
- `).replace(S5,"").replace(/&[a-z#0-9]+;/gi,(j)=>O5[j.toLowerCase()]??j).split(`
127
- `).map((j)=>j.trim()).filter(Boolean).join(`
128
- `)}function V2($,j,J){if($.textContent="",!c0(j)){for(let[Z,z]of j.split(`
129
- `).entries()){if(Z)$.append(document.createElement("br"));$.append(document.createTextNode(z))}return}let Q=new DOMParser().parseFromString(j,"text/html");for(let Z of Array.from(Q.body.childNodes)){let z=K2(Z,J);if(z)$.append(z)}}var f5=new Set(["script","style","iframe","object","embed","noscript","template","svg","math"]);function K2($,j){if($.nodeType===3)return document.createTextNode($.nodeValue??"");if($.nodeType!==1)return null;let J=$,Q=J.tagName.toLowerCase();if(f5.has(Q))return null;let Z=Q2.has(Q),z=Z?document.createElement(Q):document.createDocumentFragment();if(Z){let V=z;for(let Y of Array.from(J.attributes)){let F=Y.name.toLowerCase();if(!Z2.has(F))continue;if(F==="href"&&!z2(Y.value))continue;if(F==="src"){if(Q!=="img"||!W2(Y.value,j))continue;V.setAttribute("src",T5(Y.value,j));continue}V.setAttribute(F,Y.value)}if(Q==="a")V.setAttribute("target","_blank"),V.setAttribute("rel","noopener noreferrer nofollow");if(Q==="img"&&!V.getAttribute("src"))return null}for(let V of Array.from(J.childNodes)){let Y=K2(V,j);if(Y)z.append(Y)}return z}function L5($,j){let J=document.createElement("div");V2(J,$,j);let Q=k5(j);if(Q)for(let Z of Array.from(J.querySelectorAll("img"))){let z=Z.getAttribute("src")??"";if(z.startsWith(`${Q}/`))Z.setAttribute("src",z.slice(Q.length))}return J.innerHTML}function k5($){try{return new URL($).origin}catch{return null}}function A5($){if(!$)return!0;if(/<img\b/i.test($))return!1;return $.replace(/<[^>]*>/g,"").replace(/&nbsp;/g," ").trim()===""}function T5($,j){let J=$.trim();if(!J.startsWith("/"))return J;return`${j.replace(/\/$/,"")}${J}`}var x5=["bold","italic","underline","bulletList","orderedList","link","image"],E5=["bold","italic","underline","strike","code","bulletList","orderedList","blockquote","link","image"];var p5={title:"ปัญหาที่แจ้ง",intro:"ปัญหาที่คุณแจ้งไว้ พร้อมสถานะล่าสุด",searchPlaceholder:"ค้นหาเลขที่/หัวข้อ/โมดูล",searchLabel:"ค้นหาปัญหาที่แจ้ง",allStatuses:"ทุกสถานะ",count:($)=>`${$} รายการ`,colNumber:"เลขที่",colTitle:"หัวข้อ",colModule:"โมดูล",colStatus:"สถานะ",colResponse:"คำตอบจากทีม",colCreated:"แจ้งเมื่อ",colUpdated:"อัปเดตล่าสุด",awaitingReply:"รอคุณตอบกลับ",hasSolution:"มีวิธีแก้ไข",hasReply:"ตอบกลับแล้ว",noReply:"ยังไม่มีการตอบกลับ",empty:"คุณยังไม่ได้แจ้งปัญหา",emptyFiltered:"ไม่พบรายการที่ตรงกับการค้นหา",loading:"กำลังโหลด…",listFailed:"โหลดรายการไม่สำเร็จ",detailFailed:"โหลดรายงานไม่สำเร็จ",signedOut:"กรุณาเข้าสู่ระบบเพื่อดูปัญหาที่แจ้งไว้",back:"กลับไปรายการ",reportedBy:"แจ้งเมื่อ",conversation:"การสนทนา",resolution:"วิธีแก้ไข",noMessages:"ยังไม่มีข้อความ",you:"คุณ",team:"ทีมงาน",reporterRole:"ผู้แจ้ง",edited:"แก้ไขแล้ว",edit:"แก้ไข",saveEdit:"บันทึกการแก้ไข",cancel:"ยกเลิก",replyPlaceholder:"พิมพ์ข้อความถึงทีมงาน",bold:"ตัวหนา",italic:"ตัวเอียง",underline:"ขีดเส้นใต้",strike:"ขีดฆ่า",code:"โค้ด",blockquote:"ยกคำพูด",bulletList:"รายการหัวข้อ",orderedList:"รายการตัวเลข",link:"ลิงก์",linkPrompt:"ใส่ลิงก์",linkNeedsSelection:"เลือกข้อความที่ต้องการทำลิงก์ก่อน",linkInvalid:"ลิงก์ต้องขึ้นต้นด้วย http:// หรือ https://",attachImage:"แนบรูป",uploading:"กำลังอัปโหลดรูป…",send:"ส่งข้อความ",sending:"กำลังส่ง…",sent:"ส่งข้อความแล้ว",sendFailed:"ส่งไม่สำเร็จ ลองใหม่อีกครั้ง",reopen:"ยังมีปัญหา",reopenHint:"ถ้าปัญหายังไม่หาย แจ้งทีมงานอีกครั้งได้",reopening:"กำลังแจ้ง…",reopened:"แจ้งทีมงานอีกครั้งแล้ว — เรากำลังดูให้ครับ",reopenFailed:"เปิดเรื่องไม่สำเร็จ ลองใหม่อีกครั้ง",close:"ปิด",retry:"ลองใหม่",page:"หน้า",of:($,j)=>`หน้า ${$} จาก ${j}`,prev:"ก่อนหน้า",next:"ถัดไป"},h5={title:"My reports",intro:"The problems you have reported, with their latest status",searchPlaceholder:"Search number / title / module",searchLabel:"Search my reports",allStatuses:"All statuses",count:($)=>`${$} item${$===1?"":"s"}`,colNumber:"No.",colTitle:"Title",colModule:"Module",colStatus:"Status",colResponse:"Team response",colCreated:"Reported",colUpdated:"Last update",awaitingReply:"Awaiting your reply",hasSolution:"Solution provided",hasReply:"Replied",noReply:"No reply yet",empty:"You have not reported anything yet",emptyFiltered:"Nothing matches that search",loading:"Loading…",listFailed:"Could not load your reports",detailFailed:"Could not load this report",signedOut:"Sign in to see the problems you have reported",back:"Back to the list",reportedBy:"Reported",conversation:"Conversation",resolution:"Solution",noMessages:"No messages yet",you:"You",team:"Support",reporterRole:"Reporter",edited:"edited",edit:"Edit",saveEdit:"Save changes",cancel:"Cancel",replyPlaceholder:"Write a message to the team",bold:"Bold",italic:"Italic",underline:"Underline",strike:"Strikethrough",code:"Code",blockquote:"Quote",bulletList:"Bulleted list",orderedList:"Numbered list",link:"Link",linkPrompt:"Enter a link",linkNeedsSelection:"Select the text you want to link first",linkInvalid:"A link must start with http:// or https://",attachImage:"Add an image",uploading:"Uploading the image…",send:"Send",sending:"Sending…",sent:"Message sent",sendFailed:"Could not send — try again",reopen:"Still a problem",reopenHint:"If the problem is not fixed, tell the team again",reopening:"Sending…",reopened:"The team has been notified — we are looking at it",reopenFailed:"Could not reopen — try again",close:"Close",retry:"Try again",page:"Page",of:($,j)=>`Page ${$} of ${j}`,prev:"Previous",next:"Next"};function v5($){return $==="en"?h5:p5}export{H5 as uploadInlineImage,x0 as trimToBudget,_5 as toPlainText,y1 as toCurl,v5 as ticketStrings,$2 as ticketKey,E0 as submitBundle,B5 as statusTone,U5 as statusMaps,c as showToast,n4 as setErroredQueriesSource,b0 as responseRank,$5 as requestPath,s as reporterStrings,Y5 as replyToTicket,F5 as reopenMyTicket,V2 as renderBody,y as redactUrl,g as redactLabel,m as redactHeaders,b as redactBody,I5 as pageOf,D5 as pageCount,N0 as onLaunch,R0 as onCrash,P5 as matchesKeyword,c0 as looksLikeHtml,z5 as listMyTickets,q0 as launch,J5 as isQuietStep,t1 as isFailedRequest,F0 as isConfigured,W2 as isAllowedImageSrc,z2 as isAllowedHref,t4 as installDebugCapture,A5 as htmlIsEmpty,J2 as hasTeamReply,j2 as hasSolution,T4 as hasCause,O0 as getNetworkLog,X5 as getMyTicketHistory,V5 as getMyTicketByNumber,W5 as getMyTicket,B0 as getConsoleLog,B as getConfig,K5 as getAttachmentUrl,I0 as getActionTrail,Q5 as formatDuration,C5 as formatDateTime,M5 as fetchRealmConfig,A0 as errorSignature,S0 as emitCrash,G5 as editMyMessage,m0 as defineReporterElement,v0 as createAnnotator,j5 as correlateActionTrail,C2 as configureDebugCapture,w5 as compareBy,L5 as cleanHtml,k0 as captureScreen,L4 as bundleToMarkdown,A4 as bundleFileName,L0 as buildBundle,x as appInfo,P0 as actionCountSuffix,X0 as TicketApiError,u0 as STATUS_TONES,o as REPORTER_TAG,v as REDACTED,d0 as PAGE_SIZE,K0 as NoIdentityError,x5 as NOTE_TOOLBAR,E5 as FULL_TOOLBAR,T0 as BUNDLE_BUDGET_BYTES,Q2 as ALLOWED_TAGS,Z2 as ALLOWED_ATTR};
124
+ `;var o="lw-debug-reporter",d1=()=>[];function E4($){d1=$}var x4=[{tool:"rect",key:"toolRect"},{tool:"arrow",key:"toolArrow"},{tool:"highlight",key:"toolHighlight"},{tool:"text",key:"toolText"}];function h4(){return class extends HTMLElement{root;stop=null;annotator=null;bundle=null;busy=!1;constructor(){super();this.root=this.attachShadow({mode:"open"})}connectedCallback(){this.dataset.debugReporter="true",this.stop=P0((j)=>void this.open(j))}disconnectedCallback(){this.stop?.(),this.stop=null,this.close()}async open(j){if(this.busy)return;this.busy=!0;let J=n(B().locale),Q=await k0();if(Q.method==="cancelled"){this.close();return}this.bundle=R0({reason:j,note:"",screenshotDataUrl:Q.dataUrl,screenshotMethod:Q.method,erroredQueries:p4()}),this.renderForm(J)}close(){this.annotator?.destroy(),this.annotator=null,this.bundle=null,this.busy=!1,this.root.replaceChildren()}shell(j){let J=document.createElement("style");J.textContent=u1;let Q=document.createElement("div");Q.className="backdrop";let z=document.createElement("div");return z.className="panel",z.setAttribute("role","dialog"),z.setAttribute("aria-modal","true"),z.setAttribute("aria-label",j.title),Q.append(z),this.root.replaceChildren(J,Q),z}renderShell(j,J){let Q=this.shell(j),z=R("div","head");z.append(R("h2","",j.title)),Q.append(z,R("p","status",J))}renderForm(j){let J=this.bundle;if(!J)return;let Q=this.shell(j),z=R("div","head"),W=i("✕","icon");W.setAttribute("aria-label",j.close),W.addEventListener("click",()=>this.close()),z.append(R("h2","",j.title),W);let K=document.createElement("input");K.type="text",K.placeholder=j.summaryPlaceholder;let Y=h0(j.summaryLabel,j.summaryRequired,!0),w=document.createElement("textarea");w.placeholder=j.detailPlaceholder;let M=R("div","meta");M.innerHTML="";let{context:U}=J;for(let[q,k]of[[j.reporter,`${U.user.fullName??"—"} (${U.user.email??"—"})`],[j.page,U.route.href],[j.captured,`${J.network.length} network · ${J.console.length} console · ${J.actionTrail.length} actions`]]){let D=document.createElement("div"),f=document.createElement("b");f.textContent=`${q}: `,D.append(f,document.createTextNode(k)),M.append(D)}let P=R("p","status",""),I=i(j.submit,"primary");if(I.disabled=!0,K.addEventListener("input",()=>{I.disabled=K.value.trim().length===0}),Q.append(z,Y,K,h0(j.detailLabel),w,M),J.screenshotDataUrl)Q.append(...this.screenshotSection(j,J.screenshotDataUrl));else Q.append(R("p","status",j.noScreenshot));let S=R("div","foot"),N=i(j.close);N.addEventListener("click",()=>this.close()),S.append(N,P,R("span","grow"),I),Q.append(S),I.addEventListener("click",async()=>{I.disabled=!0,P.dataset.tone="",P.textContent=j.submitting;try{let q=await A0(K.value.trim(),{...J,note:w.value,screenshotDataUrl:this.annotator?.hasShapes()?this.annotator.toDataUrl():J.screenshotDataUrl}),k=this.dispatchEvent(new CustomEvent("lw-report-submitted",{detail:q,bubbles:!0,composed:!0,cancelable:!0}));if(this.close(),k)d(`${j.submitted} — #${q.number}`,"success")}catch(q){let k=q instanceof Error?q.message:j.failed;P.dataset.tone="error",P.textContent=k,d(`${j.failed} — ${k}`,"error"),I.disabled=!1}}),K.focus()}screenshotSection(j,J){let Q=h0(j.annotateHint),z=R("div","tools"),W=document.createElement("canvas"),K=R("div","shot");K.append(W);let Y=[],w=(I)=>{for(let S of Y)S.setAttribute("aria-pressed",String(S===I))};for(let{tool:I,key:S}of x4){let N=i(j[S]);N.setAttribute("aria-pressed","false"),N.addEventListener("click",()=>{let q=N.getAttribute("aria-pressed")==="true";w(q?null:N),this.annotator?.setTool(q?null:I)}),Y.push(N),z.append(N)}z.append(R("span","sep"));let M=i(j.deleteSelected);M.addEventListener("click",()=>this.annotator?.deleteSelected());let U=i(j.clearAll);U.addEventListener("click",()=>{this.annotator?.clear(),w(null)}),z.append(M,U);let P=new Image;return P.onload=()=>{W.width=P.naturalWidth,W.height=P.naturalHeight,this.annotator=x0(W,P,()=>{w(null),M.disabled=!this.annotator?.hasSelection()})},P.src=J,[Q,z,R("p","status",j.annotateHelp),K]}}}function p4(){try{return d1()}catch{return[]}}function R($,j="",J=""){let Q=document.createElement($);if(j)Q.className=j;if(J)Q.textContent=J;return Q}function i($,j=""){let J=document.createElement("button");if(J.type="button",J.textContent=$,j)J.className=j;return J}function h0($,j="",J=!1){let Q=document.createElement("label");if(Q.append(document.createTextNode($)),J){let z=document.createElement("span");z.className="req",z.textContent=" *",Q.append(z)}if(j){let z=document.createElement("span");z.className="hint",z.textContent=` ${j}`,Q.append(z)}return Q}function p0(){if(typeof window>"u"||customElements.get(o))return;customElements.define(o,h4())}var i1=!1;function g4($={}){if(i1||typeof window>"u")return;if(!V0()){console.error("[debug-capture] configureDebugCapture() must be called before install");return}if(i1=!0,O1(),Y1(),W1(),P1(),$.ui===!1)return;let j=n(B().locale);if(N0((J)=>{d(J.message??j.crashed,"error",{label:j.crashAction,onClick:()=>D0(J)})}),p0(),!document.querySelector(o))document.body.append(document.createElement(o))}var m4=new Set(["error","exception","unhandledrejection"]);function o1($){if($.error)return!0;return $.status!==null&&$.status>=400}function g0($){if(!$)return null;let j=Date.parse($);return Number.isNaN(j)?null:j}function v4($){try{let{pathname:j}=new URL($,"http://x");try{return decodeURIComponent(j)}catch{return j}}catch{return $.split(/[?#]/)[0]??$}}function y4($,j,J){let Q=(K)=>({elapsedMs:K,requests:[],failedRequests:[],consoleErrors:[],slowestMs:null});if($.length===0)return[];let z=$.map((K)=>g0(K.at)),W=(K)=>{for(let Y=K+1;Y<z.length;Y+=1){let w=z[Y];if(w!=null)return w}return Number.POSITIVE_INFINITY};return $.map((K,Y)=>{let w=z[Y]??null,M=(Y>0?z[Y-1]:null)??null,U=w!==null&&M!==null?Math.max(0,w-M):null;if(w===null)return Q(U);let P=w,I=Math.max(P,W(Y)),S=(D)=>D!==null&&D>=P&&(D<I||I===Number.POSITIVE_INFINITY),N=j.filter((D)=>S(g0(D.startedAt))),q=J.filter((D)=>m4.has(D.level)&&S(g0(D.at))),k=N.map((D)=>D.durationMs).filter((D)=>typeof D==="number");return{elapsedMs:U,requests:N,failedRequests:N.filter(o1),consoleErrors:q,slowestMs:k.length>0?Math.max(...k):null}})}function b4($,j){return $.requests.length===0&&$.consoleErrors.length===0&&($.elapsedMs===null||$.elapsedMs<j)}function u4($){if($<1000)return`${Math.round($)} มิลลิวินาที`;let j=$/1000;if(j<10)return`${j.toFixed(1)} วิ`;if(j<60)return`${Math.round(j)} วิ`;let J=Math.floor(j/60),Q=Math.round(j%60);return Q===0?`${J} นาที`:`${J} นาที ${Q} วิ`}var d4="/sso";function c1($,j,J){let Q=new URL(d4,$.endsWith("/")?$:`${$}/`);return Q.searchParams.set("realm",j),Q.searchParams.set("token",J),Q.toString()}class W0 extends Error{constructor($="No identity provider is configured, or nobody is signed in"){super($);this.name="NoIdentityError"}}async function i4($={}){let j=B();if(!j.identity)throw new W0;let J=await j.identity();if(!J)throw new W0;let Q=c1(j.host,j.realmKey,J);if($.target==="_blank")window.open(Q,"_blank","noopener,noreferrer");else window.location.assign(Q)}export{L0 as trimToBudget,E1 as toCurl,c1 as supportPortalUrl,A0 as submitBundle,d as showToast,E4 as setErroredQueriesSource,v4 as requestPath,n as reporterStrings,v as redactUrl,g as redactLabel,m as redactHeaders,y as redactBody,i4 as openSupportPortal,P0 as onLaunch,N0 as onCrash,D0 as launch,b4 as isQuietStep,o1 as isFailedRequest,V0 as isConfigured,g4 as installDebugCapture,C4 as hasCause,S0 as getNetworkLog,I0 as getConsoleLog,B as getConfig,C0 as getActionTrail,u4 as formatDuration,O0 as errorSignature,B0 as emitCrash,p0 as defineReporterElement,x0 as createAnnotator,y4 as correlateActionTrail,e1 as configureDebugCapture,k0 as captureScreen,w4 as bundleToMarkdown,M4 as bundleFileName,R0 as buildBundle,T as appInfo,H0 as actionCountSuffix,o as REPORTER_TAG,p as REDACTED,W0 as NoIdentityError,_0 as BUNDLE_BUDGET_BYTES};
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Build the hand-off URL. Separate from opening it so the assembly can be
3
+ * tested without a browser, and so a host that wants its own link element
4
+ * rather than our button has something to point it at.
5
+ */
6
+ export declare function supportPortalUrl(host: string, realmKey: string, token: string): string;
7
+ export declare class NoIdentityError extends Error {
8
+ constructor(message?: string);
9
+ }
10
+ /**
11
+ * Open the portal, signed in as the current user.
12
+ *
13
+ * The token is fetched at click time and not before. It is minted to live about
14
+ * two minutes and is spent on arrival, so one obtained at page load would
15
+ * usually be dead by the time anybody pressed anything.
16
+ *
17
+ * Same origin by default. A new tab is available but is not the default: the
18
+ * point of this is that the support system owns the whole ticket experience,
19
+ * and leaving the host app open behind it invites the two to disagree about
20
+ * what a ticket says.
21
+ */
22
+ export declare function openSupportPortal(options?: {
23
+ target?: "_self" | "_blank";
24
+ }): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightworkai.official/debug-capture",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "Report-a-problem widget: rolling network/console/action capture, annotated screenshot, and submission to a Lightwork Support host",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",
package/src/index.ts CHANGED
@@ -51,59 +51,15 @@ export { createAnnotator } from "./ui/annotator";
51
51
  export type { Annotator, AnnotatorTool } from "./ui/annotator";
52
52
  export { strings as reporterStrings } from "./ui/strings";
53
53
  export type { Strings as ReporterStrings } from "./ui/strings";
54
- export {
55
- listMyTickets,
56
- getMyTicket,
57
- getMyTicketByNumber,
58
- getMyTicketHistory,
59
- replyToTicket,
60
- editMyMessage,
61
- reopenMyTicket,
62
- uploadInlineImage,
63
- getAttachmentUrl,
64
- fetchRealmConfig,
65
- TicketApiError,
66
- NoIdentityError,
67
- } from "./mytickets/api";
68
- export type {
69
- MyTicket,
70
- MyTicketListItem,
71
- MyTicketDetail,
72
- TicketMessage,
73
- TicketAttachment,
74
- StatusEvent,
75
- StatusColumn,
76
- RealmConfig,
77
- } from "./mytickets/api";
78
- export {
79
- ticketKey,
80
- formatDateTime,
81
- statusMaps,
82
- hasSolution,
83
- hasTeamReply,
84
- responseRank,
85
- compareBy,
86
- matchesKeyword,
87
- pageOf,
88
- pageCount,
89
- PAGE_SIZE,
90
- } from "./mytickets/format";
91
- export type { StatusMaps, Sort, SortKey } from "./mytickets/format";
92
- export {
93
- toPlainText,
94
- looksLikeHtml,
95
- renderBody,
96
- cleanHtml,
97
- htmlIsEmpty,
98
- ALLOWED_TAGS,
99
- ALLOWED_ATTR,
100
- isAllowedHref,
101
- isAllowedImageSrc,
102
- } from "./mytickets/sanitize";
103
- export { NOTE_TOOLBAR, FULL_TOOLBAR } from "./mytickets/toolbar";
104
- export type { EditorTool } from "./mytickets/toolbar";
105
- export { ticketStrings } from "./mytickets/strings";
106
- export type { TicketStrings } from "./mytickets/strings";
107
- export { statusTone, STATUS_TONES } from "./mytickets/format";
54
+ /*
55
+ * The reporter's own tickets are no longer a component this library ships.
56
+ *
57
+ * They were: a read API, a ticket list, a thread, a reply editor, ported to
58
+ * React, Vue and Angular. It worked, and it meant every change to the way a
59
+ * ticket looks had to land in four places. The support host renders that screen
60
+ * already, so the library now hands someone to it instead — one button, one
61
+ * link, and the ticket UI maintained where it lives.
62
+ */
63
+ export { openSupportPortal, supportPortalUrl, NoIdentityError } from "./portal";
108
64
 
109
65
  export type * from "./types";
package/src/portal.ts ADDED
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Sending someone to their tickets on the support host.
3
+ *
4
+ * This replaces an embedded panel, and the trade is worth stating. The panel
5
+ * meant a read API, a ticket screen ported to three frameworks, and every
6
+ * change to the way a ticket looks landing in four repositories. A link means
7
+ * the host renders a button and nothing else; the portal is maintained in one
8
+ * place, by the people who own it. It is the shape Jira and Zendesk use, for
9
+ * the same reason.
10
+ *
11
+ * The cost is honest too: it is a context switch. Someone checking a report
12
+ * leaves the app they were in.
13
+ */
14
+ import { getConfig } from "./config";
15
+
16
+ /**
17
+ * Where a signed-in hand-off lands. Stable on purpose — it goes in other
18
+ * teams' configuration, and moving it means asking them all to redeploy.
19
+ */
20
+ const PORTAL_PATH = "/sso";
21
+
22
+ /**
23
+ * Build the hand-off URL. Separate from opening it so the assembly can be
24
+ * tested without a browser, and so a host that wants its own link element
25
+ * rather than our button has something to point it at.
26
+ */
27
+ export function supportPortalUrl(host: string, realmKey: string, token: string): string {
28
+ const url = new URL(PORTAL_PATH, host.endsWith("/") ? host : `${host}/`);
29
+ url.searchParams.set("realm", realmKey);
30
+ url.searchParams.set("token", token);
31
+ return url.toString();
32
+ }
33
+
34
+ export class NoIdentityError extends Error {
35
+ constructor(message = "No identity provider is configured, or nobody is signed in") {
36
+ super(message);
37
+ this.name = "NoIdentityError";
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Open the portal, signed in as the current user.
43
+ *
44
+ * The token is fetched at click time and not before. It is minted to live about
45
+ * two minutes and is spent on arrival, so one obtained at page load would
46
+ * usually be dead by the time anybody pressed anything.
47
+ *
48
+ * Same origin by default. A new tab is available but is not the default: the
49
+ * point of this is that the support system owns the whole ticket experience,
50
+ * and leaving the host app open behind it invites the two to disagree about
51
+ * what a ticket says.
52
+ */
53
+ export async function openSupportPortal(options: { target?: "_self" | "_blank" } = {}): Promise<void> {
54
+ const config = getConfig();
55
+ if (!config.identity) throw new NoIdentityError();
56
+
57
+ const token = await config.identity();
58
+ // Null is "nobody is signed in", which the host answers, not us — it has a
59
+ // login screen and we do not know where it is.
60
+ if (!token) throw new NoIdentityError();
61
+
62
+ const url = supportPortalUrl(config.host, config.realmKey, token);
63
+ if (options.target === "_blank") window.open(url, "_blank", "noopener,noreferrer");
64
+ else window.location.assign(url);
65
+ }
package/src/submit.ts CHANGED
@@ -46,6 +46,25 @@ function bundleAttachment(bundle: DebugBundle): { dataUri: string; filename: str
46
46
  return { dataUri: `data:application/json;base64,${base64}`, filename: "debug-bundle.json" };
47
47
  }
48
48
 
49
+ /**
50
+ * The host's proof of who is filing, when it has any.
51
+ *
52
+ * Never throws. Filing a report has to keep working for an app that has not
53
+ * wired identity up, for one where nobody is signed in, and for one whose token
54
+ * endpoint is having a bad day — a bug report is the last thing that should
55
+ * fail because of a side quest.
56
+ */
57
+ async function identityHeader(): Promise<Record<string, string>> {
58
+ const provider = getConfig().identity;
59
+ if (!provider) return {};
60
+ try {
61
+ const token = await provider();
62
+ return token ? { authorization: `Bearer ${token}` } : {};
63
+ } catch {
64
+ return {};
65
+ }
66
+ }
67
+
49
68
  export async function submitBundle(title: string, bundle: DebugBundle): Promise<FiledTicket> {
50
69
  const config = getConfig();
51
70
  const trimmed = trimToBudget(bundle, BUNDLE_BUDGET_BYTES);
@@ -118,9 +137,23 @@ export async function submitBundle(title: string, bundle: DebugBundle): Promise<
118
137
  // authenticated /api routes rather than inside them, because it is the one
119
138
  // surface a public key reaches. Assuming the prefix cost a 404 that no unit
120
139
  // test could have caught — it only appears against a real server.
140
+ /*
141
+ * Present the identity token if the host has one.
142
+ *
143
+ * The realm key alone files an ANONYMOUS report: `requesterEmail` in the body
144
+ * is caller-supplied under a public key, so the server cannot believe it, and
145
+ * the ticket lands with no `requesterId` — which is the field that makes it
146
+ * appear in the reporter's own list. It would show up eventually, when their
147
+ * next sign-in claims earlier reports by email, and "eventually" is not what
148
+ * someone expects after pressing send and seeing it succeed.
149
+ */
121
150
  const res = await fetch(`${config.host.replace(/\/$/, "")}/ingest/tickets`, {
122
151
  method: "POST",
123
- headers: { "content-type": "application/json", "x-realm-key": config.realmKey },
152
+ headers: {
153
+ "content-type": "application/json",
154
+ "x-realm-key": config.realmKey,
155
+ ...(await identityHeader()),
156
+ },
124
157
  body: JSON.stringify(body),
125
158
  });
126
159