@impakers/debug 1.4.4 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js CHANGED
@@ -1568,6 +1568,61 @@ function findNearestComponentSource(element, maxAncestors = 10) {
1568
1568
  return getSourceLocation(element);
1569
1569
  }
1570
1570
 
1571
+ // src/utils/capture-element.ts
1572
+ var UNSUPPORTED_COLOR_RE = /oklab|oklch|color-mix/i;
1573
+ var COLOR_DECLARATION_RE = /[^{};\n]+:\s*[^;{}]*(?:oklab|oklch|color-mix|lch|lab)\([^)]*(?:\([^)]*\))*[^)]*\)[^;{}]*/gi;
1574
+ function sanitizeUnsupportedColors(clonedDoc) {
1575
+ clonedDoc.querySelectorAll("style").forEach((styleEl) => {
1576
+ const text = styleEl.textContent || "";
1577
+ if (UNSUPPORTED_COLOR_RE.test(text)) {
1578
+ styleEl.textContent = text.replace(COLOR_DECLARATION_RE, "");
1579
+ }
1580
+ });
1581
+ clonedDoc.querySelectorAll("*").forEach((el) => {
1582
+ const s = el.style;
1583
+ if (!s?.cssText) return;
1584
+ if (UNSUPPORTED_COLOR_RE.test(s.cssText)) {
1585
+ s.cssText = s.cssText.replace(COLOR_DECLARATION_RE, "");
1586
+ }
1587
+ });
1588
+ }
1589
+ async function captureElement(el, options = {}) {
1590
+ const { quality = 0.7, maxScale = 2 } = options;
1591
+ const html2canvas = (await import("html2canvas")).default;
1592
+ const canvas = await html2canvas(el, {
1593
+ useCORS: true,
1594
+ allowTaint: true,
1595
+ scale: Math.min(window.devicePixelRatio, maxScale),
1596
+ logging: false,
1597
+ onclone: (clonedDoc) => sanitizeUnsupportedColors(clonedDoc)
1598
+ });
1599
+ return canvas.toDataURL("image/jpeg", quality);
1600
+ }
1601
+ async function captureFullPage(options = {}) {
1602
+ const { quality = 0.5, hideSelectors = [] } = options;
1603
+ const defaultSelectors = ["[data-impakers-debug]", "[data-annotation-popup]", "[data-annotation-marker]"];
1604
+ const allSelectors = [...defaultSelectors, ...hideSelectors];
1605
+ const hiddenEls = document.querySelectorAll(allSelectors.join(", "));
1606
+ try {
1607
+ hiddenEls.forEach((el) => el.style.visibility = "hidden");
1608
+ const html2canvas = (await import("html2canvas")).default;
1609
+ const canvas = await html2canvas(document.body, {
1610
+ useCORS: true,
1611
+ allowTaint: true,
1612
+ scale: 1,
1613
+ logging: false,
1614
+ width: window.innerWidth,
1615
+ height: window.innerHeight,
1616
+ onclone: (clonedDoc) => sanitizeUnsupportedColors(clonedDoc)
1617
+ });
1618
+ return canvas.toDataURL("image/jpeg", quality);
1619
+ } catch {
1620
+ return void 0;
1621
+ } finally {
1622
+ hiddenEls.forEach((el) => el.style.visibility = "");
1623
+ }
1624
+ }
1625
+
1571
1626
  // src/core/collector.ts
1572
1627
  var MAX_ERRORS = 20;
1573
1628
  var MAX_LOGS = 50;
@@ -2098,23 +2153,6 @@ async function uploadFile(endpoint, file, context, taskId) {
2098
2153
  }
2099
2154
  return res.json();
2100
2155
  }
2101
- async function updateTaskStatus(endpoint, taskId, status) {
2102
- const snapshots = snapshotCaches("feedbacks:");
2103
- mutateMatchingCaches(
2104
- "feedbacks:",
2105
- (items) => items.map((item) => item.id === taskId ? { ...item, status } : item)
2106
- );
2107
- try {
2108
- await apiFetch(`${endpoint}/${taskId}/status`, {
2109
- method: "PATCH",
2110
- body: JSON.stringify({ status })
2111
- });
2112
- revalidateCachedFeedbackLists(endpoint);
2113
- } catch (error) {
2114
- restoreSnapshots(snapshots);
2115
- throw error;
2116
- }
2117
- }
2118
2156
 
2119
2157
  // src/core/sourcemap-resolver.ts
2120
2158
  var import_trace_mapping = require("@jridgewell/trace-mapping");
@@ -2225,6 +2263,7 @@ var styles_module_default2 = classNames2;
2225
2263
 
2226
2264
  // src/components/annotation-marker/index.tsx
2227
2265
  var import_jsx_runtime3 = require("react/jsx-runtime");
2266
+ var IN_PROGRESS_MARKER_COLOR = "#3b82f6";
2228
2267
  var DONE_MARKER_COLOR = "#9ca3af";
2229
2268
  function AnnotationMarker({
2230
2269
  annotation,
@@ -2238,7 +2277,8 @@ function AnnotationMarker({
2238
2277
  }) {
2239
2278
  const animClass = !isAnimated ? styles_module_default2.enter : "";
2240
2279
  const isDone = annotation.status === "done" || annotation.status === "resolved";
2241
- const markerColor = isDone ? DONE_MARKER_COLOR : accentColor;
2280
+ const isInProgress = annotation.status === "in_progress";
2281
+ const markerColor = isDone ? DONE_MARKER_COLOR : isInProgress ? IN_PROGRESS_MARKER_COLOR : accentColor;
2242
2282
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2243
2283
  "div",
2244
2284
  {
@@ -2341,8 +2381,7 @@ function CommentThread({
2341
2381
  top,
2342
2382
  bottom,
2343
2383
  onClose,
2344
- onReply,
2345
- onResolve
2384
+ onReply
2346
2385
  }) {
2347
2386
  const [replyText, setReplyText] = (0, import_react3.useState)("");
2348
2387
  const [exiting, setExiting] = (0, import_react3.useState)(false);
@@ -2436,25 +2475,7 @@ function CommentThread({
2436
2475
  cleanup();
2437
2476
  if (!targetEl) return;
2438
2477
  try {
2439
- const html2canvas = (await import("html2canvas")).default;
2440
- const canvas = await html2canvas(targetEl, {
2441
- useCORS: true,
2442
- allowTaint: true,
2443
- scale: Math.min(window.devicePixelRatio, 2),
2444
- logging: false,
2445
- onclone: (clonedDoc) => {
2446
- const unsupported = /oklab|oklch|color-mix|(?<![a-z])lch|(?<![a-z])lab/i;
2447
- clonedDoc.querySelectorAll("style").forEach((styleEl) => {
2448
- if (unsupported.test(styleEl.textContent || "")) {
2449
- styleEl.textContent = (styleEl.textContent || "").replace(
2450
- /[^{};\n]+:\s*[^;{}]*(?:oklab|oklch|color-mix|lch|lab)\([^)]*(?:\([^)]*\))*[^)]*\)[^;{}]*/gi,
2451
- ""
2452
- );
2453
- }
2454
- });
2455
- }
2456
- });
2457
- const base64 = canvas.toDataURL("image/jpeg", 0.7);
2478
+ const base64 = await captureElement(targetEl);
2458
2479
  setPendingImage(base64);
2459
2480
  } catch (err) {
2460
2481
  console.error("[@impakers/debug] DOM \uC2A4\uD06C\uB9B0\uC0F7 \uC2E4\uD328:", err);
@@ -2515,10 +2536,7 @@ function CommentThread({
2515
2536
  ] }),
2516
2537
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles_module_default3.title, children: feedbackTitle })
2517
2538
  ] }),
2518
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles_module_default3.headerActions, children: [
2519
- onResolve && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: styles_module_default3.headerAction, onClick: () => onResolve(task.id), title: "\uC644\uB8CC \uCC98\uB9AC", type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "20 6 9 17 4 12" }) }) }),
2520
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: styles_module_default3.headerAction, onClick: handleClose, title: "\uB2EB\uAE30", type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M18 6L6 18M6 6l12 12" }) }) })
2521
- ] })
2539
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles_module_default3.headerActions, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: styles_module_default3.headerAction, onClick: handleClose, title: "\uB2EB\uAE30", type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M18 6L6 18M6 6l12 12" }) }) }) })
2522
2540
  ] }),
2523
2541
  task.comments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2524
2542
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles_module_default3.divider }),
@@ -2942,11 +2960,10 @@ function InboxPanel({
2942
2960
  endpoint,
2943
2961
  currentUserName,
2944
2962
  currentUserId,
2945
- onClose,
2946
- onStatusChange
2963
+ onClose
2947
2964
  }) {
2948
2965
  const [tab, setTab] = (0, import_react5.useState)("page");
2949
- const [statusFilter, setStatusFilter] = (0, import_react5.useState)("open");
2966
+ const [statusFilter, setStatusFilter] = (0, import_react5.useState)("todo");
2950
2967
  const [exiting, setExiting] = (0, import_react5.useState)(false);
2951
2968
  const [selectedItem, setSelectedItem] = (0, import_react5.useState)(null);
2952
2969
  const [comments, setComments] = (0, import_react5.useState)([]);
@@ -3021,17 +3038,11 @@ function InboxPanel({
3021
3038
  }
3022
3039
  if (e.key === "Escape") handleClose();
3023
3040
  }, [handleSendReply, handleClose]);
3024
- const handleToggleStatus = (0, import_react5.useCallback)((item, e) => {
3025
- e.stopPropagation();
3026
- const newStatus = item.status === "done" ? "todo" : "done";
3027
- onStatusChange?.(item.id, newStatus);
3028
- }, [onStatusChange]);
3029
3041
  const rawItems = tab === "page" ? pageItems : allItems;
3030
- const items = rawItems.filter(
3031
- (item) => statusFilter === "resolved" ? item.status === "done" : item.status !== "done"
3032
- );
3033
- const openCount = rawItems.filter((item) => item.status !== "done").length;
3034
- const resolvedCount = rawItems.filter((item) => item.status === "done").length;
3042
+ const items = rawItems.filter((item) => item.status === statusFilter);
3043
+ const todoCount = rawItems.filter((item) => item.status === "todo").length;
3044
+ const inProgressCount = rawItems.filter((item) => item.status === "in_progress").length;
3045
+ const doneCount = rawItems.filter((item) => item.status === "done").length;
3035
3046
  if (typeof document === "undefined") return null;
3036
3047
  return (0, import_react_dom.createPortal)(
3037
3048
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-impakers-debug": "", children: [
@@ -3154,24 +3165,36 @@ function InboxPanel({
3154
3165
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3155
3166
  "button",
3156
3167
  {
3157
- className: `${styles_module_default5.filterChip} ${statusFilter === "open" ? styles_module_default5.active : ""}`,
3158
- onClick: () => setStatusFilter("open"),
3168
+ className: `${styles_module_default5.filterChip} ${statusFilter === "todo" ? styles_module_default5.active : ""}`,
3169
+ onClick: () => setStatusFilter("todo"),
3170
+ type: "button",
3171
+ children: [
3172
+ "\uC9C4\uD589\uC804",
3173
+ todoCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.filterCount, children: todoCount })
3174
+ ]
3175
+ }
3176
+ ),
3177
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3178
+ "button",
3179
+ {
3180
+ className: `${styles_module_default5.filterChip} ${statusFilter === "in_progress" ? styles_module_default5.active : ""}`,
3181
+ onClick: () => setStatusFilter("in_progress"),
3159
3182
  type: "button",
3160
3183
  children: [
3161
- "Open",
3162
- openCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.filterCount, children: openCount })
3184
+ "\uC9C4\uD589\uC911",
3185
+ inProgressCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.filterCount, children: inProgressCount })
3163
3186
  ]
3164
3187
  }
3165
3188
  ),
3166
3189
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3167
3190
  "button",
3168
3191
  {
3169
- className: `${styles_module_default5.filterChip} ${statusFilter === "resolved" ? styles_module_default5.active : ""}`,
3170
- onClick: () => setStatusFilter("resolved"),
3192
+ className: `${styles_module_default5.filterChip} ${statusFilter === "done" ? styles_module_default5.active : ""}`,
3193
+ onClick: () => setStatusFilter("done"),
3171
3194
  type: "button",
3172
3195
  children: [
3173
- "Resolved",
3174
- resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.filterCount, children: resolvedCount })
3196
+ "\uC644\uB8CC",
3197
+ doneCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.filterCount, children: doneCount })
3175
3198
  ]
3176
3199
  }
3177
3200
  )
@@ -3185,17 +3208,7 @@ function InboxPanel({
3185
3208
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardInfo, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardMeta, children: [
3186
3209
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardAuthor, children: item.authorName }),
3187
3210
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardTime, children: timeAgo2(item.createdAt) })
3188
- ] }) }),
3189
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3190
- "button",
3191
- {
3192
- className: `${styles_module_default5.checkBtn} ${item.status === "done" ? styles_module_default5.checked : ""}`,
3193
- onClick: (e) => handleToggleStatus(item, e),
3194
- type: "button",
3195
- title: item.status === "done" ? "\uBBF8\uC644\uB8CC\uB85C \uBCC0\uACBD" : "\uC644\uB8CC \uCC98\uB9AC",
3196
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "20 6 9 17 4 12" }) })
3197
- }
3198
- )
3211
+ ] }) })
3199
3212
  ] }),
3200
3213
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardTitle, children: item.title.replace(/^\[피드백\]\s*/, "") }),
3201
3214
  item.screenshot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardScreenshot, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: item.screenshot, alt: "screenshot" }) }),
@@ -3700,35 +3713,7 @@ function DebugWidget({ endpoint, getUser, onHide }) {
3700
3713
  setSubmitting(true);
3701
3714
  try {
3702
3715
  const metadata = collectMetadata(getUser);
3703
- let screenshot;
3704
- const debugEls = document.querySelectorAll("[data-impakers-debug], [data-annotation-popup], [data-annotation-marker]");
3705
- try {
3706
- debugEls.forEach((el) => el.style.visibility = "hidden");
3707
- const html2canvas = (await import("html2canvas")).default;
3708
- const canvas = await html2canvas(document.body, {
3709
- useCORS: true,
3710
- allowTaint: true,
3711
- scale: 1,
3712
- logging: false,
3713
- width: window.innerWidth,
3714
- height: window.innerHeight,
3715
- onclone: (clonedDoc) => {
3716
- const unsupported = /oklab|oklch|color-mix|(?<![a-z])lch|(?<![a-z])lab/i;
3717
- clonedDoc.querySelectorAll("style").forEach((styleEl) => {
3718
- if (unsupported.test(styleEl.textContent || "")) {
3719
- styleEl.textContent = (styleEl.textContent || "").replace(
3720
- /[^{};\n]+:\s*[^;{}]*(?:oklab|oklch|color-mix|lch|lab)\([^)]*(?:\([^)]*\))*[^)]*\)[^;{}]*/gi,
3721
- ""
3722
- );
3723
- }
3724
- });
3725
- }
3726
- });
3727
- screenshot = canvas.toDataURL("image/jpeg", 0.5);
3728
- } catch {
3729
- } finally {
3730
- debugEls.forEach((el) => el.style.visibility = "");
3731
- }
3716
+ const screenshot = await captureFullPage();
3732
3717
  let resolvedSource = pendingAnnotation.resolvedSource || pendingAnnotation.sourceFile || "";
3733
3718
  let resolvedName = pendingAnnotation.resolvedName || null;
3734
3719
  if (!pendingAnnotation.resolvedSource && pendingAnnotation.sourceFile?.includes("/chunks/")) {
@@ -3801,7 +3786,8 @@ ${elementInfo.join("\n")}`);
3801
3786
  isFixed: pendingAnnotation.isFixed || false,
3802
3787
  element: pendingAnnotation.element,
3803
3788
  boundingBox: pendingAnnotation.boundingBox
3804
- }
3789
+ },
3790
+ authorName: getUser?.()?.name ? String(getUser().name) : void 0
3805
3791
  });
3806
3792
  setShowToast(true);
3807
3793
  originalSetTimeout(() => setShowToast(false), 3e3);
@@ -3970,7 +3956,7 @@ ${elementInfo.join("\n")}`);
3970
3956
  title: task.title || "\uD53C\uB4DC\uBC31",
3971
3957
  status: task.status,
3972
3958
  priority: task.priority,
3973
- authorName: getUser?.()?.name ? String(getUser().name) : "\uC775\uBA85",
3959
+ authorName: task.authorName || "\uC775\uBA85",
3974
3960
  feedbackUrl: task.feedbackUrl || currentPath,
3975
3961
  createdAt: task.createdAt,
3976
3962
  commentCount: task.commentCount || 0
@@ -4022,14 +4008,7 @@ ${elementInfo.join("\n")}`);
4022
4008
  endpoint,
4023
4009
  currentUserName: getUser?.()?.name ? String(getUser().name) : "\uC775\uBA85",
4024
4010
  currentUserId: getUser?.()?.id ? String(getUser().id) : void 0,
4025
- onClose: () => setShowInbox(false),
4026
- onStatusChange: async (taskId, status) => {
4027
- try {
4028
- await updateTaskStatus(endpoint, taskId, status);
4029
- } catch (err) {
4030
- console.error("[@impakers/debug] \uC0C1\uD0DC \uBCC0\uACBD \uC2E4\uD328:", err);
4031
- }
4032
- }
4011
+ onClose: () => setShowInbox(false)
4033
4012
  }
4034
4013
  ),
4035
4014
  showSettings && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(