@lightworkai.official/debug-capture 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -80
- package/dist/index.d.ts +1 -10
- package/dist/index.mjs +9 -14
- package/dist/portal.d.ts +24 -0
- package/package.json +1 -1
- package/src/index.ts +10 -54
- package/src/portal.ts +65 -0
- package/dist/mytickets/api.d.ts +0 -115
- package/dist/mytickets/format.d.ts +0 -84
- package/dist/mytickets/sanitize.d.ts +0 -66
- package/dist/mytickets/strings.d.ts +0 -74
- package/dist/mytickets/toolbar.d.ts +0 -17
- package/src/mytickets/api.ts +0 -226
- package/src/mytickets/format.ts +0 -191
- package/src/mytickets/sanitize.ts +0 -221
- package/src/mytickets/strings.ts +0 -217
- package/src/mytickets/toolbar.ts +0 -48
package/README.md
CHANGED
|
@@ -52,126 +52,90 @@ knowing before you ship:
|
|
|
52
52
|
|
|
53
53
|
## The other half: letting people track what they reported
|
|
54
54
|
|
|
55
|
-
Filing a report is one side.
|
|
56
|
-
|
|
57
|
-
team's answer, and a "still a problem" button — the reporter-facing
|
|
58
|
-
counterpart to the agent's ticket list, as a component you drop on a route of
|
|
59
|
-
your own.
|
|
55
|
+
Filing a report is one side. Seeing what became of it is the other — and that
|
|
56
|
+
side is a **link**, not a component.
|
|
60
57
|
|
|
61
58
|
```tsx
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
export default function SupportPage() {
|
|
65
|
-
return <MyTicketsPanel />; // or openMyTickets() for a modal
|
|
66
|
-
}
|
|
59
|
+
<SupportPortalButton /> {/* "ดูปัญหาที่แจ้ง" */}
|
|
67
60
|
```
|
|
68
61
|
|
|
69
|
-
|
|
62
|
+
It opens the reporter's ticket list on the support host, already signed in. The
|
|
63
|
+
host application renders a button and nothing else.
|
|
64
|
+
|
|
65
|
+
This used to be an embedded panel — a ticket list, a thread and a reply editor,
|
|
66
|
+
ported to React, Vue and Angular over a read API. It worked. It also meant every
|
|
67
|
+
change to the way a ticket looks had to land in four repositories and be
|
|
68
|
+
released before anyone saw it. The support host renders that screen already, so
|
|
69
|
+
now it owns it. Jira and Zendesk are the same shape for the same reason.
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
The trade is a context switch: someone checking a report leaves the app they
|
|
72
|
+
were in. If that matters more to you than the maintenance, the panel is still in
|
|
73
|
+
the 0.6.x line.
|
|
74
|
+
|
|
75
|
+
### It needs to know who is asking
|
|
72
76
|
|
|
73
77
|
`realmKey` is public by design — it ships in your client source, and that is
|
|
74
78
|
fine for filing, because the worst a stolen key buys is noise the rate limits
|
|
75
79
|
already absorb. **Reading is different.** "List the tickets for this email"
|
|
76
80
|
behind a public key is an endpoint that reads *everyone's* reports.
|
|
77
81
|
|
|
78
|
-
So your server vouches for your user. Ask the support team for the realm's
|
|
79
|
-
secret (an admin sets `authConfig.reporterSecret` on the realm), keep
|
|
80
|
-
**server**, and mint a short-lived token:
|
|
82
|
+
So your server vouches for your user. Ask the support team for the realm's
|
|
83
|
+
reporter secret (an admin sets `authConfig.reporterSecret` on the realm), keep
|
|
84
|
+
it on your **server**, and mint a short-lived token:
|
|
81
85
|
|
|
82
86
|
```ts
|
|
83
87
|
// your backend — e.g. app/api/support-token/route.ts
|
|
84
88
|
import jwt from "jsonwebtoken";
|
|
85
89
|
|
|
86
90
|
export async function GET() {
|
|
87
|
-
const user = await currentUser();
|
|
91
|
+
const user = await currentUser(); // however you authenticate
|
|
88
92
|
const token = jwt.sign(
|
|
89
93
|
{ sub: user.id, email: user.email, name: user.fullName },
|
|
90
|
-
process.env.SUPPORT_REPORTER_SECRET!,
|
|
91
|
-
{ algorithm: "HS256", expiresIn: "
|
|
94
|
+
process.env.SUPPORT_REPORTER_SECRET!,
|
|
95
|
+
{ algorithm: "HS256", expiresIn: "2m" },
|
|
92
96
|
);
|
|
93
97
|
return Response.json({ token });
|
|
94
98
|
}
|
|
95
99
|
```
|
|
96
100
|
|
|
101
|
+
Wire it once, as the `identity` callback:
|
|
102
|
+
|
|
97
103
|
```ts
|
|
98
|
-
// your config — the callback just fetches that
|
|
99
104
|
configureDebugCapture({
|
|
100
105
|
host, realmKey, app: { name: "ERP" },
|
|
101
|
-
identity: () => fetch("/api/support-token").then((r) => r.json())
|
|
106
|
+
identity: async () => (await fetch("/api/support-token").then((r) => r.json())).token,
|
|
102
107
|
});
|
|
103
108
|
```
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
`identity` is optional. Without it, filing still works exactly as before — the
|
|
110
|
-
report is simply anonymous, and the panel says "sign in to see your reports"
|
|
111
|
-
rather than showing an empty list. With it, submissions are linked to the person
|
|
112
|
-
too, and the identity in the token wins over any `requesterEmail` in the body.
|
|
110
|
+
The **secret never reaches the browser** — the callback fetches a finished token
|
|
111
|
+
from your own backend. Returning `null` means "nobody is signed in", and the
|
|
112
|
+
button says so rather than opening a dead link.
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
Two things about the token, both enforced on our side rather than yours:
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
- It is spent **once**. Re-opening the link from history signs nobody in.
|
|
117
|
+
- It must be **seconds old**. The hand-off refuses anything older than two
|
|
118
|
+
minutes regardless of its own `exp`, because it travels in a URL — which means
|
|
119
|
+
browser history, `Referer`, and every access log in between. A long-lived
|
|
120
|
+
token is still perfectly good for the API; it just cannot be spent as a link.
|
|
120
121
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- **รอคุณตอบกลับ** in amber when the team is waiting on this person
|
|
124
|
-
- **คำตอบจากทีม** — มีวิธีแก้ไข > ตอบกลับแล้ว > ยังไม่มีการตอบกลับ
|
|
125
|
-
- a status hero, a progress timeline including reopens, the conversation, and
|
|
126
|
-
**ยังมีปัญหา** when the realm enables `selfServiceReopen`
|
|
122
|
+
You do not have to shorten `expiresIn` for this: the token is fetched at click
|
|
123
|
+
time, so it is always fresh when it is used.
|
|
127
124
|
|
|
128
|
-
|
|
129
|
-
underline, bullets, numbers, link, image. TipTap is a PEER dependency, so an app
|
|
130
|
-
that already has it pays nothing for it. Images upload first and are referenced
|
|
131
|
-
by the token the server mints; pasting a screenshot straight in works, which is
|
|
132
|
-
how one usually arrives.
|
|
125
|
+
### Doing it without our button
|
|
133
126
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
This package is the **core**: the capture buffers, the bundle, the ingest client,
|
|
137
|
-
the sanitiser, the status maps, the comparators, the dates, the strings — and one
|
|
138
|
-
stylesheet. It renders no panel UI.
|
|
139
|
-
|
|
140
|
-
The panel is real components in the framework packages:
|
|
141
|
-
`@lightworkai.official/debug-capture-vue` ships `.vue` single-file components,
|
|
142
|
-
`@lightworkai.official/debug-capture-react` ships `.tsx`, and
|
|
143
|
-
`@lightworkai.official/debug-capture-angular` ships standalone components. Each is markup
|
|
144
|
-
over the shared functions — the filtering, sorting and formatting exist once,
|
|
145
|
-
here.
|
|
146
|
-
|
|
147
|
-
Import the stylesheet once, from anywhere:
|
|
127
|
+
`openSupportPortal()` is the same thing as a function, and `supportPortalUrl()`
|
|
128
|
+
builds the URL if you would rather render your own anchor:
|
|
148
129
|
|
|
149
130
|
```ts
|
|
150
|
-
import "@lightworkai.official/debug-capture
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Every colour in it is a custom property, so a host restyles by setting variables
|
|
154
|
-
rather than by fighting specificity:
|
|
131
|
+
import { openSupportPortal, supportPortalUrl } from "@lightworkai.official/debug-capture";
|
|
155
132
|
|
|
156
|
-
|
|
157
|
-
|
|
133
|
+
await openSupportPortal(); // navigates in place
|
|
134
|
+
await openSupportPortal({ target: "_blank" }); // new tab, noopener
|
|
158
135
|
```
|
|
159
136
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
is the capture payload the *team* reads, and offering it as a download put the
|
|
163
|
-
one artefact the reporter has no use for on their page. The screenshot they drew
|
|
164
|
-
on is theirs, and it is shown as a picture.
|
|
165
|
-
|
|
166
|
-
Message bodies are HTML written by other people and rendered inside *your* page,
|
|
167
|
-
so they go through an allowlist sanitiser: a small tag set, no event handlers,
|
|
168
|
-
links forced to `rel="noopener noreferrer nofollow"`, and images restricted to
|
|
169
|
-
the host's own inline URLs — a remote `<img>` would make every ticket a tracking
|
|
170
|
-
pixel aimed at whoever opens it.
|
|
171
|
-
|
|
172
|
-
Both outcomes dispatch a cancelable event (`lw-ticket-replied`,
|
|
173
|
-
`lw-ticket-reopened`, and their `-failed` pairs) before the built-in toast, so an
|
|
174
|
-
app with its own notification system calls `preventDefault()` and shows its own.
|
|
137
|
+
`supportPortalUrl(host, realmKey, token)` is pure and safe to call on a server.
|
|
138
|
+
|
|
175
139
|
|
|
176
140
|
## Installing
|
|
177
141
|
|
package/dist/index.d.ts
CHANGED
|
@@ -32,14 +32,5 @@ export { createAnnotator } from "./ui/annotator";
|
|
|
32
32
|
export type { Annotator, AnnotatorTool } from "./ui/annotator";
|
|
33
33
|
export { strings as reporterStrings } from "./ui/strings";
|
|
34
34
|
export type { Strings as ReporterStrings } from "./ui/strings";
|
|
35
|
-
export {
|
|
36
|
-
export type { MyTicket, MyTicketListItem, MyTicketDetail, TicketMessage, TicketAttachment, StatusEvent, StatusColumn, RealmConfig, } from "./mytickets/api";
|
|
37
|
-
export { ticketKey, formatDateTime, statusMaps, hasSolution, hasTeamReply, responseRank, compareBy, matchesKeyword, pageOf, pageCount, PAGE_SIZE, } from "./mytickets/format";
|
|
38
|
-
export type { StatusMaps, Sort, SortKey } from "./mytickets/format";
|
|
39
|
-
export { toPlainText, looksLikeHtml, renderBody, cleanHtml, htmlIsEmpty, ALLOWED_TAGS, ALLOWED_ATTR, isAllowedHref, isAllowedImageSrc, } from "./mytickets/sanitize";
|
|
40
|
-
export { NOTE_TOOLBAR, FULL_TOOLBAR } from "./mytickets/toolbar";
|
|
41
|
-
export type { EditorTool } from "./mytickets/toolbar";
|
|
42
|
-
export { ticketStrings } from "./mytickets/strings";
|
|
43
|
-
export type { TicketStrings } from "./mytickets/strings";
|
|
44
|
-
export { statusTone, STATUS_TONES } from "./mytickets/format";
|
|
35
|
+
export { openSupportPortal, supportPortalUrl, NoIdentityError } from "./portal";
|
|
45
36
|
export type * from "./types";
|
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 f(){if(!_)throw Error("[debug-capture] configureDebugCapture() has not been called");return _}function V0(){return _!==null}function T(){let $=f().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,C=W.source?w0(W.source.replace(/^→\s*/,"")).split(/[?#]/)[0]:null;if(C&&(w===C||w.startsWith(C)))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 C2($){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 M2($){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 C0($,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=($)=>C0($,Q1,U2),N2=150000,B2=40000,e0=($)=>C0($,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(C0($,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=C2(Q.target);if(!z)return;let W=M2(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 M0(){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 C1($,j){for(let J of[...$])J(j)}function P0($){return H1(F1,$)}function D0($={type:"manual"}){C1(F1,$)}function N0($){return H1(w1,$)}function B0($){C1(w1,$)}var i2=15000,o2=["ResizeObserver loop","Script error.","Non-Error promise rejection captured"],M1=!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(M1||typeof window>"u")return;M1=!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($),
|
|
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(C),z.remove()};Y.addEventListener("click",w);let C=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 $=f(),{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:M0(),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
|
-
${
|
|
35
|
+
${E1(j)}${z}`}).join(`
|
|
36
36
|
|
|
37
|
-
`)}function
|
|
38
|
-
`)}function
|
|
39
|
-
↳ ${J.afterNote}`:
|
|
40
|
-
`)}function
|
|
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 C4($,j){return`debug-report_${H4($.context.capturedAt)}.${j}`}function M4($){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 $=f().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 A0($,j){let J=f(),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},C=await fetch(`${J.host.replace(/\/$/,"")}/ingest/tickets`,{method:"POST",headers:{"content-type":"application/json","x-realm-key":J.realmKey},body:JSON.stringify(w)});if(!C.ok){let U=C.headers.get("retry-after"),P=await C.json().then((I)=>I.error).catch(()=>null);throw Error(C.status===429?`Too many reports — try again in ${U??"a moment"}s`:P??`Report failed (${C.status})`)}return await C.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",L4="rgba(250, 204, 21, 0.4)",E0=22,g1="#2563eb",m1=9,v1=11,y1=18,b1=4,Z0=8,A4=[{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 C(){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 B(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 A4.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*C(),y:G.top-y1*C()}}function S(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")S(Z,G,X);else if(G.tool==="highlight")Z.fillStyle=L4,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 B(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),M=v1*X;Z.beginPath(),Z.arc(H.x,H.y,M,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-M*0.4,H.y-M*0.4),Z.lineTo(H.x+M*0.4,H.y+M*0.4),Z.moveTo(H.x+M*0.4,H.y-M*0.4),Z.lineTo(H.x-M*0.4,H.y+M*0.4),Z.stroke(),Z.restore()}function q(){if(!w)return;let Z=C();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*C()/2+3*C();for(let F of B(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*C())}function K0(Z,G){let X=6*C();for(let V=Q.length-1;V>=0;V-=1){let F=Q[V];if(F.tool==="arrow"){let M=F.x2-F.x1,O=F.y2-F.y1,x=Math.hypot(M,O)||1,h=Math.max(0,Math.min(1,((Z-F.x1)*M+(G-F.y1)*O)/(x*x)));if(Math.hypot(Z-(F.x1+h*M),G-(F.y1+h*O))<=X+4*C())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:M,top:O,right:x,bottom:h}=H;if(G.includes("w"))M=Math.min(x-Z0,M+V);if(G.includes("e"))x=Math.max(M+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=M,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(),q()}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*C())};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",(M)=>{if(M.stopPropagation(),M.key==="Enter")c(!0);else if(M.key==="Escape")c(!1)}),requestAnimationFrame(()=>{if(L!==H)return;H.focus(),H.select(),H.addEventListener("blur",()=>c(!0))}),q()}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,q()}function i0(Z){let{x:G,y:X}=U(Z);if(K){K.x2=G,K.y2=X,q();return}if(Y){let F=Q[W];if(!F)return;let H=G-Y.x,M=X-Y.y;if(Y.grip==="body")r1(F,Y.start,H,M);else l1(F,Y.grip,Y.start,H,M);q();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]?B(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();q()}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,q()}function G0(){if(W<0)return;Q.splice(W,1),W=-1,J(),q()}return $.addEventListener("pointerdown",d0),$.addEventListener("pointermove",i0),$.addEventListener("pointerup",t),$.addEventListener("pointercancel",t),$.addEventListener("dblclick",o0),$.tabIndex=0,$.addEventListener("keydown",c0),q(),{setTool(Z){z=Z,W=-1,$.style.cursor=Z?"crosshair":"default",q()},deleteSelected:G0,clear(){Q.length=0,W=-1,J(),q()},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=C();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={" ":" ","&":"&","<":"<",">":">",""":'"',"'":"'"};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(/ /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 T4($){d1=$}var E4=[{tool:"rect",key:"toolRect"},{tool:"arrow",key:"toolArrow"},{tool:"highlight",key:"toolHighlight"},{tool:"text",key:"toolText"}];function x4(){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(f().locale),Q=await k0();if(Q.method==="cancelled"){this.close();return}this.bundle=R0({reason:j,note:"",screenshotDataUrl:Q.dataUrl,screenshotMethod:Q.method,erroredQueries:h4()}),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 C=R("div","meta");C.innerHTML="";let{context:U}=J;for(let[S,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"),q=document.createElement("b");q.textContent=`${S}: `,D.append(q,document.createTextNode(k)),C.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,C),J.screenshotDataUrl)Q.append(...this.screenshotSection(j,J.screenshotDataUrl));else Q.append(R("p","status",j.noScreenshot));let B=R("div","foot"),N=i(j.close);N.addEventListener("click",()=>this.close()),B.append(N,P,R("span","grow"),I),Q.append(B),I.addEventListener("click",async()=>{I.disabled=!0,P.dataset.tone="",P.textContent=j.submitting;try{let S=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:S,bubbles:!0,composed:!0,cancelable:!0}));if(this.close(),k)d(`${j.submitted} — #${S.number}`,"success")}catch(S){let k=S instanceof Error?S.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 B of Y)B.setAttribute("aria-pressed",String(B===I))};for(let{tool:I,key:B}of E4){let N=i(j[B]);N.setAttribute("aria-pressed","false"),N.addEventListener("click",()=>{let S=N.getAttribute("aria-pressed")==="true";w(S?null:N),this.annotator?.setTool(S?null:I)}),Y.push(N),z.append(N)}z.append(R("span","sep"));let C=i(j.deleteSelected);C.addEventListener("click",()=>this.annotator?.deleteSelected());let U=i(j.clearAll);U.addEventListener("click",()=>{this.annotator?.clear(),w(null)}),z.append(C,U);let P=new Image;return P.onload=()=>{W.width=P.naturalWidth,W.height=P.naturalHeight,this.annotator=x0(W,P,()=>{w(null),C.disabled=!this.annotator?.hasSelection()})},P.src=J,[Q,z,R("p","status",j.annotateHelp),K]}}}function h4(){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,x4())}var i1=!1;function p4($={}){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(f().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 g4=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 m4($){try{let{pathname:j}=new URL($,"http://x");try{return decodeURIComponent(j)}catch{return j}}catch{return $.split(/[?#]/)[0]??$}}function v4($,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,C=(Y>0?z[Y-1]:null)??null,U=w!==null&&C!==null?Math.max(0,w-C):null;if(w===null)return Q(U);let P=w,I=Math.max(P,W(Y)),B=(D)=>D!==null&&D>=P&&(D<I||I===Number.POSITIVE_INFINITY),N=j.filter((D)=>B(g0(D.startedAt))),S=J.filter((D)=>g4.has(D.level)&&B(g0(D.at))),k=N.map((D)=>D.durationMs).filter((D)=>typeof D==="number");return{elapsedMs:U,requests:N,failedRequests:N.filter(o1),consoleErrors:S,slowestMs:k.length>0?Math.max(...k):null}})}function y4($,j){return $.requests.length===0&&$.consoleErrors.length===0&&($.elapsedMs===null||$.elapsedMs<j)}function b4($){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 u4="/sso";function c1($,j,J){let Q=new URL(u4,$.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 d4($={}){let j=f();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,T4 as setErroredQueriesSource,m4 as requestPath,n as reporterStrings,v as redactUrl,g as redactLabel,m as redactHeaders,y as redactBody,d4 as openSupportPortal,P0 as onLaunch,N0 as onCrash,D0 as launch,y4 as isQuietStep,o1 as isFailedRequest,V0 as isConfigured,p4 as installDebugCapture,M4 as hasCause,S0 as getNetworkLog,I0 as getConsoleLog,f as getConfig,M0 as getActionTrail,b4 as formatDuration,O0 as errorSignature,B0 as emitCrash,p0 as defineReporterElement,x0 as createAnnotator,v4 as correlateActionTrail,e1 as configureDebugCapture,k0 as captureScreen,w4 as bundleToMarkdown,C4 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};
|
package/dist/portal.d.ts
ADDED
|
@@ -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.
|
|
3
|
+
"version": "0.7.0",
|
|
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",
|