@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.mjs CHANGED
@@ -1534,6 +1534,61 @@ function findNearestComponentSource(element, maxAncestors = 10) {
1534
1534
  return getSourceLocation(element);
1535
1535
  }
1536
1536
 
1537
+ // src/utils/capture-element.ts
1538
+ var UNSUPPORTED_COLOR_RE = /oklab|oklch|color-mix/i;
1539
+ var COLOR_DECLARATION_RE = /[^{};\n]+:\s*[^;{}]*(?:oklab|oklch|color-mix|lch|lab)\([^)]*(?:\([^)]*\))*[^)]*\)[^;{}]*/gi;
1540
+ function sanitizeUnsupportedColors(clonedDoc) {
1541
+ clonedDoc.querySelectorAll("style").forEach((styleEl) => {
1542
+ const text = styleEl.textContent || "";
1543
+ if (UNSUPPORTED_COLOR_RE.test(text)) {
1544
+ styleEl.textContent = text.replace(COLOR_DECLARATION_RE, "");
1545
+ }
1546
+ });
1547
+ clonedDoc.querySelectorAll("*").forEach((el) => {
1548
+ const s = el.style;
1549
+ if (!s?.cssText) return;
1550
+ if (UNSUPPORTED_COLOR_RE.test(s.cssText)) {
1551
+ s.cssText = s.cssText.replace(COLOR_DECLARATION_RE, "");
1552
+ }
1553
+ });
1554
+ }
1555
+ async function captureElement(el, options = {}) {
1556
+ const { quality = 0.7, maxScale = 2 } = options;
1557
+ const html2canvas = (await import("html2canvas")).default;
1558
+ const canvas = await html2canvas(el, {
1559
+ useCORS: true,
1560
+ allowTaint: true,
1561
+ scale: Math.min(window.devicePixelRatio, maxScale),
1562
+ logging: false,
1563
+ onclone: (clonedDoc) => sanitizeUnsupportedColors(clonedDoc)
1564
+ });
1565
+ return canvas.toDataURL("image/jpeg", quality);
1566
+ }
1567
+ async function captureFullPage(options = {}) {
1568
+ const { quality = 0.5, hideSelectors = [] } = options;
1569
+ const defaultSelectors = ["[data-impakers-debug]", "[data-annotation-popup]", "[data-annotation-marker]"];
1570
+ const allSelectors = [...defaultSelectors, ...hideSelectors];
1571
+ const hiddenEls = document.querySelectorAll(allSelectors.join(", "));
1572
+ try {
1573
+ hiddenEls.forEach((el) => el.style.visibility = "hidden");
1574
+ const html2canvas = (await import("html2canvas")).default;
1575
+ const canvas = await html2canvas(document.body, {
1576
+ useCORS: true,
1577
+ allowTaint: true,
1578
+ scale: 1,
1579
+ logging: false,
1580
+ width: window.innerWidth,
1581
+ height: window.innerHeight,
1582
+ onclone: (clonedDoc) => sanitizeUnsupportedColors(clonedDoc)
1583
+ });
1584
+ return canvas.toDataURL("image/jpeg", quality);
1585
+ } catch {
1586
+ return void 0;
1587
+ } finally {
1588
+ hiddenEls.forEach((el) => el.style.visibility = "");
1589
+ }
1590
+ }
1591
+
1537
1592
  // src/core/collector.ts
1538
1593
  var MAX_ERRORS = 20;
1539
1594
  var MAX_LOGS = 50;
@@ -2064,23 +2119,6 @@ async function uploadFile(endpoint, file, context, taskId) {
2064
2119
  }
2065
2120
  return res.json();
2066
2121
  }
2067
- async function updateTaskStatus(endpoint, taskId, status) {
2068
- const snapshots = snapshotCaches("feedbacks:");
2069
- mutateMatchingCaches(
2070
- "feedbacks:",
2071
- (items) => items.map((item) => item.id === taskId ? { ...item, status } : item)
2072
- );
2073
- try {
2074
- await apiFetch(`${endpoint}/${taskId}/status`, {
2075
- method: "PATCH",
2076
- body: JSON.stringify({ status })
2077
- });
2078
- revalidateCachedFeedbackLists(endpoint);
2079
- } catch (error) {
2080
- restoreSnapshots(snapshots);
2081
- throw error;
2082
- }
2083
- }
2084
2122
 
2085
2123
  // src/core/sourcemap-resolver.ts
2086
2124
  import { AnyMap, originalPositionFor } from "@jridgewell/trace-mapping";
@@ -2191,6 +2229,7 @@ var styles_module_default2 = classNames2;
2191
2229
 
2192
2230
  // src/components/annotation-marker/index.tsx
2193
2231
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
2232
+ var IN_PROGRESS_MARKER_COLOR = "#3b82f6";
2194
2233
  var DONE_MARKER_COLOR = "#9ca3af";
2195
2234
  function AnnotationMarker({
2196
2235
  annotation,
@@ -2204,7 +2243,8 @@ function AnnotationMarker({
2204
2243
  }) {
2205
2244
  const animClass = !isAnimated ? styles_module_default2.enter : "";
2206
2245
  const isDone = annotation.status === "done" || annotation.status === "resolved";
2207
- const markerColor = isDone ? DONE_MARKER_COLOR : accentColor;
2246
+ const isInProgress = annotation.status === "in_progress";
2247
+ const markerColor = isDone ? DONE_MARKER_COLOR : isInProgress ? IN_PROGRESS_MARKER_COLOR : accentColor;
2208
2248
  return /* @__PURE__ */ jsxs3(
2209
2249
  "div",
2210
2250
  {
@@ -2307,8 +2347,7 @@ function CommentThread({
2307
2347
  top,
2308
2348
  bottom,
2309
2349
  onClose,
2310
- onReply,
2311
- onResolve
2350
+ onReply
2312
2351
  }) {
2313
2352
  const [replyText, setReplyText] = useState2("");
2314
2353
  const [exiting, setExiting] = useState2(false);
@@ -2402,25 +2441,7 @@ function CommentThread({
2402
2441
  cleanup();
2403
2442
  if (!targetEl) return;
2404
2443
  try {
2405
- const html2canvas = (await import("html2canvas")).default;
2406
- const canvas = await html2canvas(targetEl, {
2407
- useCORS: true,
2408
- allowTaint: true,
2409
- scale: Math.min(window.devicePixelRatio, 2),
2410
- logging: false,
2411
- onclone: (clonedDoc) => {
2412
- const unsupported = /oklab|oklch|color-mix|(?<![a-z])lch|(?<![a-z])lab/i;
2413
- clonedDoc.querySelectorAll("style").forEach((styleEl) => {
2414
- if (unsupported.test(styleEl.textContent || "")) {
2415
- styleEl.textContent = (styleEl.textContent || "").replace(
2416
- /[^{};\n]+:\s*[^;{}]*(?:oklab|oklch|color-mix|lch|lab)\([^)]*(?:\([^)]*\))*[^)]*\)[^;{}]*/gi,
2417
- ""
2418
- );
2419
- }
2420
- });
2421
- }
2422
- });
2423
- const base64 = canvas.toDataURL("image/jpeg", 0.7);
2444
+ const base64 = await captureElement(targetEl);
2424
2445
  setPendingImage(base64);
2425
2446
  } catch (err) {
2426
2447
  console.error("[@impakers/debug] DOM \uC2A4\uD06C\uB9B0\uC0F7 \uC2E4\uD328:", err);
@@ -2481,10 +2502,7 @@ function CommentThread({
2481
2502
  ] }),
2482
2503
  /* @__PURE__ */ jsx4("div", { className: styles_module_default3.title, children: feedbackTitle })
2483
2504
  ] }),
2484
- /* @__PURE__ */ jsxs4("div", { className: styles_module_default3.headerActions, children: [
2485
- onResolve && /* @__PURE__ */ jsx4("button", { className: styles_module_default3.headerAction, onClick: () => onResolve(task.id), title: "\uC644\uB8CC \uCC98\uB9AC", type: "button", children: /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx4("polyline", { points: "20 6 9 17 4 12" }) }) }),
2486
- /* @__PURE__ */ jsx4("button", { className: styles_module_default3.headerAction, onClick: handleClose, title: "\uB2EB\uAE30", type: "button", children: /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx4("path", { d: "M18 6L6 18M6 6l12 12" }) }) })
2487
- ] })
2505
+ /* @__PURE__ */ jsx4("div", { className: styles_module_default3.headerActions, children: /* @__PURE__ */ jsx4("button", { className: styles_module_default3.headerAction, onClick: handleClose, title: "\uB2EB\uAE30", type: "button", children: /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx4("path", { d: "M18 6L6 18M6 6l12 12" }) }) }) })
2488
2506
  ] }),
2489
2507
  task.comments.length > 0 && /* @__PURE__ */ jsxs4(Fragment, { children: [
2490
2508
  /* @__PURE__ */ jsx4("div", { className: styles_module_default3.divider }),
@@ -2908,11 +2926,10 @@ function InboxPanel({
2908
2926
  endpoint,
2909
2927
  currentUserName,
2910
2928
  currentUserId,
2911
- onClose,
2912
- onStatusChange
2929
+ onClose
2913
2930
  }) {
2914
2931
  const [tab, setTab] = useState4("page");
2915
- const [statusFilter, setStatusFilter] = useState4("open");
2932
+ const [statusFilter, setStatusFilter] = useState4("todo");
2916
2933
  const [exiting, setExiting] = useState4(false);
2917
2934
  const [selectedItem, setSelectedItem] = useState4(null);
2918
2935
  const [comments, setComments] = useState4([]);
@@ -2987,17 +3004,11 @@ function InboxPanel({
2987
3004
  }
2988
3005
  if (e.key === "Escape") handleClose();
2989
3006
  }, [handleSendReply, handleClose]);
2990
- const handleToggleStatus = useCallback4((item, e) => {
2991
- e.stopPropagation();
2992
- const newStatus = item.status === "done" ? "todo" : "done";
2993
- onStatusChange?.(item.id, newStatus);
2994
- }, [onStatusChange]);
2995
3007
  const rawItems = tab === "page" ? pageItems : allItems;
2996
- const items = rawItems.filter(
2997
- (item) => statusFilter === "resolved" ? item.status === "done" : item.status !== "done"
2998
- );
2999
- const openCount = rawItems.filter((item) => item.status !== "done").length;
3000
- const resolvedCount = rawItems.filter((item) => item.status === "done").length;
3008
+ const items = rawItems.filter((item) => item.status === statusFilter);
3009
+ const todoCount = rawItems.filter((item) => item.status === "todo").length;
3010
+ const inProgressCount = rawItems.filter((item) => item.status === "in_progress").length;
3011
+ const doneCount = rawItems.filter((item) => item.status === "done").length;
3001
3012
  if (typeof document === "undefined") return null;
3002
3013
  return createPortal(
3003
3014
  /* @__PURE__ */ jsxs6("div", { "data-impakers-debug": "", children: [
@@ -3120,24 +3131,36 @@ function InboxPanel({
3120
3131
  /* @__PURE__ */ jsxs6(
3121
3132
  "button",
3122
3133
  {
3123
- className: `${styles_module_default5.filterChip} ${statusFilter === "open" ? styles_module_default5.active : ""}`,
3124
- onClick: () => setStatusFilter("open"),
3134
+ className: `${styles_module_default5.filterChip} ${statusFilter === "todo" ? styles_module_default5.active : ""}`,
3135
+ onClick: () => setStatusFilter("todo"),
3136
+ type: "button",
3137
+ children: [
3138
+ "\uC9C4\uD589\uC804",
3139
+ todoCount > 0 && /* @__PURE__ */ jsx6("span", { className: styles_module_default5.filterCount, children: todoCount })
3140
+ ]
3141
+ }
3142
+ ),
3143
+ /* @__PURE__ */ jsxs6(
3144
+ "button",
3145
+ {
3146
+ className: `${styles_module_default5.filterChip} ${statusFilter === "in_progress" ? styles_module_default5.active : ""}`,
3147
+ onClick: () => setStatusFilter("in_progress"),
3125
3148
  type: "button",
3126
3149
  children: [
3127
- "Open",
3128
- openCount > 0 && /* @__PURE__ */ jsx6("span", { className: styles_module_default5.filterCount, children: openCount })
3150
+ "\uC9C4\uD589\uC911",
3151
+ inProgressCount > 0 && /* @__PURE__ */ jsx6("span", { className: styles_module_default5.filterCount, children: inProgressCount })
3129
3152
  ]
3130
3153
  }
3131
3154
  ),
3132
3155
  /* @__PURE__ */ jsxs6(
3133
3156
  "button",
3134
3157
  {
3135
- className: `${styles_module_default5.filterChip} ${statusFilter === "resolved" ? styles_module_default5.active : ""}`,
3136
- onClick: () => setStatusFilter("resolved"),
3158
+ className: `${styles_module_default5.filterChip} ${statusFilter === "done" ? styles_module_default5.active : ""}`,
3159
+ onClick: () => setStatusFilter("done"),
3137
3160
  type: "button",
3138
3161
  children: [
3139
- "Resolved",
3140
- resolvedCount > 0 && /* @__PURE__ */ jsx6("span", { className: styles_module_default5.filterCount, children: resolvedCount })
3162
+ "\uC644\uB8CC",
3163
+ doneCount > 0 && /* @__PURE__ */ jsx6("span", { className: styles_module_default5.filterCount, children: doneCount })
3141
3164
  ]
3142
3165
  }
3143
3166
  )
@@ -3151,17 +3174,7 @@ function InboxPanel({
3151
3174
  /* @__PURE__ */ jsx6("div", { className: styles_module_default5.cardInfo, children: /* @__PURE__ */ jsxs6("div", { className: styles_module_default5.cardMeta, children: [
3152
3175
  /* @__PURE__ */ jsx6("span", { className: styles_module_default5.cardAuthor, children: item.authorName }),
3153
3176
  /* @__PURE__ */ jsx6("span", { className: styles_module_default5.cardTime, children: timeAgo2(item.createdAt) })
3154
- ] }) }),
3155
- /* @__PURE__ */ jsx6(
3156
- "button",
3157
- {
3158
- className: `${styles_module_default5.checkBtn} ${item.status === "done" ? styles_module_default5.checked : ""}`,
3159
- onClick: (e) => handleToggleStatus(item, e),
3160
- type: "button",
3161
- title: item.status === "done" ? "\uBBF8\uC644\uB8CC\uB85C \uBCC0\uACBD" : "\uC644\uB8CC \uCC98\uB9AC",
3162
- children: /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("polyline", { points: "20 6 9 17 4 12" }) })
3163
- }
3164
- )
3177
+ ] }) })
3165
3178
  ] }),
3166
3179
  /* @__PURE__ */ jsx6("div", { className: styles_module_default5.cardTitle, children: item.title.replace(/^\[피드백\]\s*/, "") }),
3167
3180
  item.screenshot && /* @__PURE__ */ jsx6("div", { className: styles_module_default5.cardScreenshot, children: /* @__PURE__ */ jsx6("img", { src: item.screenshot, alt: "screenshot" }) }),
@@ -3666,35 +3679,7 @@ function DebugWidget({ endpoint, getUser, onHide }) {
3666
3679
  setSubmitting(true);
3667
3680
  try {
3668
3681
  const metadata = collectMetadata(getUser);
3669
- let screenshot;
3670
- const debugEls = document.querySelectorAll("[data-impakers-debug], [data-annotation-popup], [data-annotation-marker]");
3671
- try {
3672
- debugEls.forEach((el) => el.style.visibility = "hidden");
3673
- const html2canvas = (await import("html2canvas")).default;
3674
- const canvas = await html2canvas(document.body, {
3675
- useCORS: true,
3676
- allowTaint: true,
3677
- scale: 1,
3678
- logging: false,
3679
- width: window.innerWidth,
3680
- height: window.innerHeight,
3681
- onclone: (clonedDoc) => {
3682
- const unsupported = /oklab|oklch|color-mix|(?<![a-z])lch|(?<![a-z])lab/i;
3683
- clonedDoc.querySelectorAll("style").forEach((styleEl) => {
3684
- if (unsupported.test(styleEl.textContent || "")) {
3685
- styleEl.textContent = (styleEl.textContent || "").replace(
3686
- /[^{};\n]+:\s*[^;{}]*(?:oklab|oklch|color-mix|lch|lab)\([^)]*(?:\([^)]*\))*[^)]*\)[^;{}]*/gi,
3687
- ""
3688
- );
3689
- }
3690
- });
3691
- }
3692
- });
3693
- screenshot = canvas.toDataURL("image/jpeg", 0.5);
3694
- } catch {
3695
- } finally {
3696
- debugEls.forEach((el) => el.style.visibility = "");
3697
- }
3682
+ const screenshot = await captureFullPage();
3698
3683
  let resolvedSource = pendingAnnotation.resolvedSource || pendingAnnotation.sourceFile || "";
3699
3684
  let resolvedName = pendingAnnotation.resolvedName || null;
3700
3685
  if (!pendingAnnotation.resolvedSource && pendingAnnotation.sourceFile?.includes("/chunks/")) {
@@ -3767,7 +3752,8 @@ ${elementInfo.join("\n")}`);
3767
3752
  isFixed: pendingAnnotation.isFixed || false,
3768
3753
  element: pendingAnnotation.element,
3769
3754
  boundingBox: pendingAnnotation.boundingBox
3770
- }
3755
+ },
3756
+ authorName: getUser?.()?.name ? String(getUser().name) : void 0
3771
3757
  });
3772
3758
  setShowToast(true);
3773
3759
  originalSetTimeout(() => setShowToast(false), 3e3);
@@ -3936,7 +3922,7 @@ ${elementInfo.join("\n")}`);
3936
3922
  title: task.title || "\uD53C\uB4DC\uBC31",
3937
3923
  status: task.status,
3938
3924
  priority: task.priority,
3939
- authorName: getUser?.()?.name ? String(getUser().name) : "\uC775\uBA85",
3925
+ authorName: task.authorName || "\uC775\uBA85",
3940
3926
  feedbackUrl: task.feedbackUrl || currentPath,
3941
3927
  createdAt: task.createdAt,
3942
3928
  commentCount: task.commentCount || 0
@@ -3988,14 +3974,7 @@ ${elementInfo.join("\n")}`);
3988
3974
  endpoint,
3989
3975
  currentUserName: getUser?.()?.name ? String(getUser().name) : "\uC775\uBA85",
3990
3976
  currentUserId: getUser?.()?.id ? String(getUser().id) : void 0,
3991
- onClose: () => setShowInbox(false),
3992
- onStatusChange: async (taskId, status) => {
3993
- try {
3994
- await updateTaskStatus(endpoint, taskId, status);
3995
- } catch (err) {
3996
- console.error("[@impakers/debug] \uC0C1\uD0DC \uBCC0\uACBD \uC2E4\uD328:", err);
3997
- }
3998
- }
3977
+ onClose: () => setShowInbox(false)
3999
3978
  }
4000
3979
  ),
4001
3980
  showSettings && /* @__PURE__ */ jsx8(