glitchgrab 1.32.0 → 1.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -5,10 +5,10 @@ import {
5
5
  createContext,
6
6
  useContext,
7
7
  useRef as useRef3,
8
- useEffect as useEffect3,
9
- useCallback,
10
- useMemo,
11
- useState as useState3
8
+ useEffect as useEffect4,
9
+ useCallback as useCallback2,
10
+ useMemo as useMemo2,
11
+ useState as useState4
12
12
  } from "react";
13
13
 
14
14
  // src/error-boundary.tsx
@@ -630,9 +630,9 @@ function topStackFrame(stack) {
630
630
  if (!stack) return "";
631
631
  const lines = stack.split("\n");
632
632
  for (const line of lines) {
633
- const t = line.trim();
634
- if (t.startsWith("at ") || t.includes("@")) {
635
- return t;
633
+ const t2 = line.trim();
634
+ if (t2.startsWith("at ") || t2.includes("@")) {
635
+ return t2;
636
636
  }
637
637
  }
638
638
  return "";
@@ -1273,7 +1273,7 @@ function initialsOf(name) {
1273
1273
  }
1274
1274
  function ReporterChip({
1275
1275
  reporter,
1276
- t
1276
+ t: t2
1277
1277
  }) {
1278
1278
  var _a;
1279
1279
  const [avatarFailed, setAvatarFailed] = useState2(false);
@@ -1309,9 +1309,9 @@ function ReporterChip({
1309
1309
  fontSize: "8px",
1310
1310
  fontWeight: 700,
1311
1311
  letterSpacing: "0.02em",
1312
- background: isAnonymous ? t.inputBg : t.accent,
1313
- color: isAnonymous ? t.textMuted : t.accentText,
1314
- border: `1px solid ${isAnonymous ? t.inputBorder : "transparent"}`
1312
+ background: isAnonymous ? t2.inputBg : t2.accent,
1313
+ color: isAnonymous ? t2.textMuted : t2.accentText,
1314
+ border: `1px solid ${isAnonymous ? t2.inputBorder : "transparent"}`
1315
1315
  },
1316
1316
  children: showAvatarImage ? /* @__PURE__ */ jsx2(
1317
1317
  "img",
@@ -1342,7 +1342,7 @@ function ReporterChip({
1342
1342
  {
1343
1343
  style: {
1344
1344
  fontSize: "11px",
1345
- color: t.textMuted,
1345
+ color: t2.textMuted,
1346
1346
  overflow: "hidden",
1347
1347
  textOverflow: "ellipsis",
1348
1348
  whiteSpace: "nowrap"
@@ -1455,7 +1455,9 @@ function ReportDialog({
1455
1455
  types,
1456
1456
  showSeverity = true,
1457
1457
  captureScreenshot = captureViaHtml2Canvas,
1458
- reporter
1458
+ reporter,
1459
+ onClose,
1460
+ headerSlot
1459
1461
  }) {
1460
1462
  const [isEnhancing, setIsEnhancing] = useState2(false);
1461
1463
  const [isEnhanced, setIsEnhanced] = useState2(false);
@@ -1597,7 +1599,7 @@ function ReportDialog({
1597
1599
  (_c = tiles[next]) == null ? void 0 : _c.focus();
1598
1600
  };
1599
1601
  const isDark = useIsDark();
1600
- const t = getTheme(isDark);
1602
+ const t2 = getTheme(isDark);
1601
1603
  const canZoomPreview = previewNatural !== null && typeof window !== "undefined" && (previewNatural.w > window.innerWidth - 32 || previewNatural.h > window.innerHeight - 80);
1602
1604
  const handleFileUpload = (e) => {
1603
1605
  const files = e.target.files;
@@ -1773,7 +1775,7 @@ function ReportDialog({
1773
1775
  sarvamChunksRef.current = [];
1774
1776
  const stream = streamRef.current;
1775
1777
  streamRef.current = null;
1776
- stream == null ? void 0 : stream.getTracks().forEach((t2) => t2.stop());
1778
+ stream == null ? void 0 : stream.getTracks().forEach((t22) => t22.stop());
1777
1779
  try {
1778
1780
  (_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
1779
1781
  } catch (e) {
@@ -1796,6 +1798,7 @@ function ReportDialog({
1796
1798
  const handleClose = () => {
1797
1799
  stopVoice();
1798
1800
  setIsOpen(false);
1801
+ onClose == null ? void 0 : onClose();
1799
1802
  closePreview();
1800
1803
  setAnnotatingIndex(null);
1801
1804
  setStep(1);
@@ -1834,7 +1837,7 @@ function ReportDialog({
1834
1837
  if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
1835
1838
  };
1836
1839
  rec.onstop = async () => {
1837
- stream.getTracks().forEach((t2) => t2.stop());
1840
+ stream.getTracks().forEach((t22) => t22.stop());
1838
1841
  if (streamRef.current === stream) streamRef.current = null;
1839
1842
  mediaRecorderRef.current = null;
1840
1843
  const chunks = sarvamChunksRef.current;
@@ -2035,7 +2038,7 @@ function ReportDialog({
2035
2038
  button[data-gg-type]{transition:transform .15s ease,border-color .15s ease,box-shadow .15s ease,background-color .15s ease}
2036
2039
  button[data-gg-type]:hover{transform:translateY(-2px);box-shadow:0 6px 16px rgba(0,0,0,.18)}
2037
2040
  button[data-gg-type]:active{transform:translateY(0) scale(.985);box-shadow:none}
2038
- button[data-gg-type]:focus-visible{outline:2px solid ${t.accent};outline-offset:2px}
2041
+ button[data-gg-type]:focus-visible{outline:2px solid ${t2.accent};outline-offset:2px}
2039
2042
  @keyframes gg-star-pop{0%{transform:scale(.6);opacity:0}60%{transform:scale(1.12)}100%{transform:scale(1);opacity:1}}
2040
2043
  button[data-gg-star]{transition:transform .12s ease}
2041
2044
  button[data-gg-star]:hover{transform:scale(1.18)}
@@ -2078,12 +2081,12 @@ function ReportDialog({
2078
2081
  maxHeight: "calc(100dvh - 32px)",
2079
2082
  display: "flex",
2080
2083
  flexDirection: "column",
2081
- backgroundColor: t.bg,
2084
+ backgroundColor: t2.bg,
2082
2085
  borderRadius: "12px",
2083
2086
  boxShadow: "0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)",
2084
2087
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2085
2088
  overflow: "hidden",
2086
- color: t.text,
2089
+ color: t2.text,
2087
2090
  isolation: "isolate"
2088
2091
  },
2089
2092
  children: [
@@ -2093,7 +2096,7 @@ function ReportDialog({
2093
2096
  style: {
2094
2097
  flexShrink: 0,
2095
2098
  padding: "16px 16px 12px",
2096
- borderBottom: `1px solid ${t.border}`
2099
+ borderBottom: `1px solid ${t2.border}`
2097
2100
  },
2098
2101
  children: [
2099
2102
  /* @__PURE__ */ jsxs2(
@@ -2139,7 +2142,7 @@ function ReportDialog({
2139
2142
  "path",
2140
2143
  {
2141
2144
  d: "M10 3L5 8L10 13",
2142
- stroke: t.textMuted,
2145
+ stroke: t2.textMuted,
2143
2146
  strokeWidth: "2",
2144
2147
  strokeLinecap: "round",
2145
2148
  strokeLinejoin: "round"
@@ -2155,7 +2158,7 @@ function ReportDialog({
2155
2158
  style: {
2156
2159
  fontSize: "15px",
2157
2160
  fontWeight: 600,
2158
- color: t.text
2161
+ color: t2.text
2159
2162
  },
2160
2163
  children: step === 1 ? "What's on your mind?" : "Tell us more"
2161
2164
  }
@@ -2182,9 +2185,9 @@ function ReportDialog({
2182
2185
  lineHeight: 1,
2183
2186
  padding: "3px 6px",
2184
2187
  borderRadius: "4px",
2185
- border: `1px solid ${t.inputBorder}`,
2186
- background: t.inputBg,
2187
- color: t.textMuted,
2188
+ border: `1px solid ${t2.inputBorder}`,
2189
+ background: t2.inputBg,
2190
+ color: t2.textMuted,
2188
2191
  whiteSpace: "nowrap"
2189
2192
  },
2190
2193
  children: getShortcutLabel()
@@ -2217,7 +2220,7 @@ function ReportDialog({
2217
2220
  "path",
2218
2221
  {
2219
2222
  d: "M4 4L12 12M12 4L4 12",
2220
- stroke: t.textMuted,
2223
+ stroke: t2.textMuted,
2221
2224
  strokeWidth: "2",
2222
2225
  strokeLinecap: "round"
2223
2226
  }
@@ -2254,7 +2257,7 @@ function ReportDialog({
2254
2257
  width: "8px",
2255
2258
  height: "8px",
2256
2259
  borderRadius: "50%",
2257
- backgroundColor: s <= step ? t.accent : t.inputBorder,
2260
+ backgroundColor: s <= step ? t2.accent : t2.inputBorder,
2258
2261
  transition: "background-color 0.2s ease"
2259
2262
  }
2260
2263
  }
@@ -2265,7 +2268,7 @@ function ReportDialog({
2265
2268
  style: {
2266
2269
  width: "40px",
2267
2270
  height: "2px",
2268
- backgroundColor: s < step ? t.accent : t.inputBorder,
2271
+ backgroundColor: s < step ? t2.accent : t2.inputBorder,
2269
2272
  transition: "background-color 0.2s ease"
2270
2273
  }
2271
2274
  }
@@ -2294,7 +2297,7 @@ function ReportDialog({
2294
2297
  style: {
2295
2298
  textAlign: "center",
2296
2299
  padding: "20px 0",
2297
- color: t.accent,
2300
+ color: t2.accent,
2298
2301
  fontSize: "14px",
2299
2302
  fontWeight: 500
2300
2303
  },
@@ -2304,6 +2307,7 @@ function ReportDialog({
2304
2307
  ]
2305
2308
  }
2306
2309
  ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
2310
+ step === 1 && headerSlot ? /* @__PURE__ */ jsx2("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
2307
2311
  step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs2(
2308
2312
  "div",
2309
2313
  {
@@ -2324,7 +2328,7 @@ function ReportDialog({
2324
2328
  /* @__PURE__ */ jsx2(
2325
2329
  "span",
2326
2330
  {
2327
- style: { fontSize: "13px", fontWeight: 600, color: t.text },
2331
+ style: { fontSize: "13px", fontWeight: 600, color: t2.text },
2328
2332
  children: "How are we doing?"
2329
2333
  }
2330
2334
  ),
@@ -2377,9 +2381,9 @@ function ReportDialog({
2377
2381
  marginBottom: "16px"
2378
2382
  },
2379
2383
  children: [
2380
- /* @__PURE__ */ jsx2("span", { style: { flex: 1, height: "1px", background: t.border } }),
2381
- /* @__PURE__ */ jsx2("span", { style: { fontSize: "11px", color: t.textMuted }, children: "or report something" }),
2382
- /* @__PURE__ */ jsx2("span", { style: { flex: 1, height: "1px", background: t.border } })
2384
+ /* @__PURE__ */ jsx2("span", { style: { flex: 1, height: "1px", background: t2.border } }),
2385
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: "11px", color: t2.textMuted }, children: "or report something" }),
2386
+ /* @__PURE__ */ jsx2("span", { style: { flex: 1, height: "1px", background: t2.border } })
2383
2387
  ]
2384
2388
  }
2385
2389
  ),
@@ -2392,9 +2396,9 @@ function ReportDialog({
2392
2396
  gap: "10px",
2393
2397
  marginBottom: "14px",
2394
2398
  padding: "8px 10px",
2395
- border: `1px solid ${t.inputBorder}`,
2399
+ border: `1px solid ${t2.inputBorder}`,
2396
2400
  borderRadius: "8px",
2397
- background: t.inputBg
2401
+ background: t2.inputBg
2398
2402
  },
2399
2403
  children: [
2400
2404
  /* @__PURE__ */ jsx2(
@@ -2407,12 +2411,12 @@ function ReportDialog({
2407
2411
  height: "24px",
2408
2412
  objectFit: "cover",
2409
2413
  borderRadius: "4px",
2410
- border: `1px solid ${t.border}`,
2414
+ border: `1px solid ${t2.border}`,
2411
2415
  flexShrink: 0
2412
2416
  }
2413
2417
  }
2414
2418
  ),
2415
- /* @__PURE__ */ jsx2("span", { style: { fontSize: "11px", color: t.textMuted, flex: 1 }, children: "Screenshot attached" }),
2419
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: "11px", color: t2.textMuted, flex: 1 }, children: "Screenshot attached" }),
2416
2420
  /* @__PURE__ */ jsx2(
2417
2421
  "button",
2418
2422
  {
@@ -2422,7 +2426,7 @@ function ReportDialog({
2422
2426
  style: {
2423
2427
  border: "none",
2424
2428
  background: "transparent",
2425
- color: t.textMuted,
2429
+ color: t2.textMuted,
2426
2430
  cursor: "pointer",
2427
2431
  fontSize: "15px",
2428
2432
  lineHeight: 1,
@@ -2460,20 +2464,20 @@ function ReportDialog({
2460
2464
  gap: "9px",
2461
2465
  padding: "18px 10px",
2462
2466
  borderRadius: "8px",
2463
- border: `1px solid ${t.inputBorder}`,
2464
- background: t.inputBg,
2467
+ border: `1px solid ${t2.inputBorder}`,
2468
+ background: t2.inputBg,
2465
2469
  cursor: "pointer",
2466
- color: t.text,
2470
+ color: t2.text,
2467
2471
  fontFamily: "inherit"
2468
2472
  },
2469
2473
  onMouseEnter: (e) => {
2470
- e.currentTarget.style.borderColor = t.accent;
2474
+ e.currentTarget.style.borderColor = t2.accent;
2471
2475
  },
2472
2476
  onMouseLeave: (e) => {
2473
- e.currentTarget.style.borderColor = t.inputBorder;
2477
+ e.currentTarget.style.borderColor = t2.inputBorder;
2474
2478
  },
2475
2479
  children: [
2476
- getTypeIcon(type, t.accent, 22),
2480
+ getTypeIcon(type, t2.accent, 22),
2477
2481
  /* @__PURE__ */ jsx2(
2478
2482
  "span",
2479
2483
  {
@@ -2505,18 +2509,18 @@ function ReportDialog({
2505
2509
  marginBottom: "10px",
2506
2510
  padding: "4px 10px 4px 8px",
2507
2511
  borderRadius: "999px",
2508
- border: `1px solid ${isRating ? "rgba(245,158,11,0.4)" : t.inputBorder}`,
2509
- background: isRating ? "rgba(245,158,11,0.1)" : t.inputBg,
2510
- color: t.text,
2512
+ border: `1px solid ${isRating ? "rgba(245,158,11,0.4)" : t2.inputBorder}`,
2513
+ background: isRating ? "rgba(245,158,11,0.1)" : t2.inputBg,
2514
+ color: t2.text,
2511
2515
  fontSize: "11px",
2512
2516
  fontWeight: 600,
2513
2517
  fontFamily: "inherit",
2514
2518
  cursor: "pointer"
2515
2519
  },
2516
2520
  children: [
2517
- getTypeIcon(reportType, isRating ? "#f59e0b" : t.accent, 13),
2521
+ getTypeIcon(reportType, isRating ? "#f59e0b" : t2.accent, 13),
2518
2522
  getTypeLabel(reportType),
2519
- /* @__PURE__ */ jsx2("span", { style: { color: t.textMuted, fontWeight: 400 }, children: "\xB7 change" })
2523
+ /* @__PURE__ */ jsx2("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
2520
2524
  ]
2521
2525
  }
2522
2526
  ),
@@ -2553,7 +2557,7 @@ function ReportDialog({
2553
2557
  {
2554
2558
  d: "M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.4 6.8 19.1l1-5.8L3.5 9.2l5.9-.9L12 3z",
2555
2559
  fill: filled ? "#f59e0b" : "transparent",
2556
- stroke: filled ? "#f59e0b" : t.inputBorder,
2560
+ stroke: filled ? "#f59e0b" : t2.inputBorder,
2557
2561
  strokeWidth: "1.5",
2558
2562
  strokeLinejoin: "round"
2559
2563
  }
@@ -2584,24 +2588,24 @@ function ReportDialog({
2584
2588
  minHeight: "100px",
2585
2589
  padding: enhanceText2 ? "28px 12px 36px" : transcribeAudio2 ? "10px 12px 36px" : "10px 12px",
2586
2590
  borderRadius: "8px",
2587
- border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t.accent : t.inputBorder}`,
2591
+ border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t2.accent : t2.inputBorder}`,
2588
2592
  fontSize: "14px",
2589
2593
  fontFamily: "inherit",
2590
2594
  resize: "none",
2591
2595
  outline: "none",
2592
2596
  boxSizing: "border-box",
2593
- color: t.text,
2594
- backgroundColor: t.inputBg,
2597
+ color: t2.text,
2598
+ backgroundColor: t2.inputBg,
2595
2599
  transition: "border-color 0.2s ease"
2596
2600
  },
2597
2601
  onKeyDown: handleSpaceDown,
2598
2602
  onKeyUp: handleSpaceUp,
2599
2603
  onFocus: (e) => {
2600
- e.target.style.borderColor = t.accent;
2604
+ e.target.style.borderColor = t2.accent;
2601
2605
  },
2602
2606
  onBlur: (e) => {
2603
2607
  if (!isListening && !isTranscribing)
2604
- e.target.style.borderColor = t.inputBorder;
2608
+ e.target.style.borderColor = t2.inputBorder;
2605
2609
  },
2606
2610
  autoFocus: true
2607
2611
  }
@@ -2718,13 +2722,13 @@ function ReportDialog({
2718
2722
  display: "inline-flex",
2719
2723
  alignItems: "center",
2720
2724
  gap: "4px",
2721
- background: t.inputBg,
2725
+ background: t2.inputBg,
2722
2726
  border: "none",
2723
2727
  padding: "2px 6px",
2724
2728
  borderRadius: "4px",
2725
2729
  fontFamily: "inherit",
2726
2730
  fontSize: "11px",
2727
- color: t.textMuted,
2731
+ color: t2.textMuted,
2728
2732
  cursor: !description.trim() || isEnhancing ? "default" : "pointer",
2729
2733
  opacity: !description.trim() ? 0.5 : 1,
2730
2734
  zIndex: 1
@@ -2743,7 +2747,7 @@ function ReportDialog({
2743
2747
  "path",
2744
2748
  {
2745
2749
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 15l.75 2.25L22 18l-2.25.75L19 21l-.75-2.25L16 18l2.25-.75L19 15z",
2746
- stroke: t.textMuted,
2750
+ stroke: t2.textMuted,
2747
2751
  strokeWidth: "1.5",
2748
2752
  strokeLinejoin: "round"
2749
2753
  }
@@ -2772,9 +2776,9 @@ function ReportDialog({
2772
2776
  alignItems: "center",
2773
2777
  justifyContent: "center",
2774
2778
  background: "transparent",
2775
- border: `1.5px solid ${isListening ? "#ef4444" : t.inputBorder}`,
2779
+ border: `1.5px solid ${isListening ? "#ef4444" : t2.inputBorder}`,
2776
2780
  borderRadius: "6px",
2777
- color: isListening ? "#ef4444" : t.textMuted,
2781
+ color: isListening ? "#ef4444" : t2.textMuted,
2778
2782
  cursor: "pointer",
2779
2783
  zIndex: 1,
2780
2784
  padding: 0,
@@ -2844,7 +2848,7 @@ function ReportDialog({
2844
2848
  gap: "5px",
2845
2849
  marginTop: "5px",
2846
2850
  fontSize: "11px",
2847
- color: t.text,
2851
+ color: t2.text,
2848
2852
  opacity: 0.55,
2849
2853
  userSelect: "none"
2850
2854
  },
@@ -2869,7 +2873,7 @@ function ReportDialog({
2869
2873
  padding: "6px 8px",
2870
2874
  borderRadius: "6px",
2871
2875
  background: isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.05)",
2872
- border: `1px solid ${t.accent}40`
2876
+ border: `1px solid ${t2.accent}40`
2873
2877
  },
2874
2878
  children: [
2875
2879
  /* @__PURE__ */ jsx2(
@@ -2884,7 +2888,7 @@ function ReportDialog({
2884
2888
  "path",
2885
2889
  {
2886
2890
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
2887
- stroke: t.accent,
2891
+ stroke: t2.accent,
2888
2892
  strokeWidth: "1.5",
2889
2893
  strokeLinejoin: "round"
2890
2894
  }
@@ -2896,7 +2900,7 @@ function ReportDialog({
2896
2900
  {
2897
2901
  style: {
2898
2902
  fontSize: "11px",
2899
- color: t.textMuted,
2903
+ color: t2.textMuted,
2900
2904
  flex: 1
2901
2905
  },
2902
2906
  children: "AI enhanced"
@@ -2913,9 +2917,9 @@ function ReportDialog({
2913
2917
  style: {
2914
2918
  padding: "2px 8px",
2915
2919
  borderRadius: "4px",
2916
- border: `1px solid ${t.accent}`,
2917
- background: t.accent,
2918
- color: t.accentText,
2920
+ border: `1px solid ${t2.accent}`,
2921
+ background: t2.accent,
2922
+ color: t2.accentText,
2919
2923
  fontSize: "11px",
2920
2924
  fontWeight: 600,
2921
2925
  cursor: "pointer",
@@ -2936,9 +2940,9 @@ function ReportDialog({
2936
2940
  style: {
2937
2941
  padding: "2px 8px",
2938
2942
  borderRadius: "4px",
2939
- border: `1px solid ${t.inputBorder}`,
2943
+ border: `1px solid ${t2.inputBorder}`,
2940
2944
  background: "transparent",
2941
- color: t.textMuted,
2945
+ color: t2.textMuted,
2942
2946
  fontSize: "11px",
2943
2947
  fontWeight: 600,
2944
2948
  cursor: "pointer",
@@ -2968,7 +2972,7 @@ function ReportDialog({
2968
2972
  {
2969
2973
  style: {
2970
2974
  fontSize: "12px",
2971
- color: t.textMuted,
2975
+ color: t2.textMuted,
2972
2976
  marginBottom: "6px",
2973
2977
  display: "block",
2974
2978
  fontWeight: 500
@@ -3007,7 +3011,7 @@ function ReportDialog({
3007
3011
  width: "100%",
3008
3012
  height: "100%",
3009
3013
  borderRadius: "6px",
3010
- border: `1px solid ${t.border}`,
3014
+ border: `1px solid ${t2.border}`,
3011
3015
  objectFit: "cover",
3012
3016
  objectPosition: "top",
3013
3017
  cursor: "zoom-in",
@@ -3077,8 +3081,8 @@ function ReportDialog({
3077
3081
  height: "24px",
3078
3082
  borderRadius: "50%",
3079
3083
  border: "none",
3080
- background: t.accent,
3081
- color: t.accentText,
3084
+ background: t2.accent,
3085
+ color: t2.accentText,
3082
3086
  padding: 0,
3083
3087
  cursor: "pointer",
3084
3088
  display: "flex",
@@ -3131,7 +3135,7 @@ function ReportDialog({
3131
3135
  gap: "8px",
3132
3136
  padding: "6px 8px",
3133
3137
  borderRadius: "6px",
3134
- border: `1px solid ${t.border}`
3138
+ border: `1px solid ${t2.border}`
3135
3139
  },
3136
3140
  children: [
3137
3141
  /* @__PURE__ */ jsxs2(
@@ -3147,7 +3151,7 @@ function ReportDialog({
3147
3151
  "path",
3148
3152
  {
3149
3153
  d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
3150
- stroke: t.textMuted,
3154
+ stroke: t2.textMuted,
3151
3155
  strokeWidth: "1.5",
3152
3156
  strokeLinecap: "round",
3153
3157
  strokeLinejoin: "round"
@@ -3157,7 +3161,7 @@ function ReportDialog({
3157
3161
  "path",
3158
3162
  {
3159
3163
  d: "M14 2v6h6",
3160
- stroke: t.textMuted,
3164
+ stroke: t2.textMuted,
3161
3165
  strokeWidth: "1.5",
3162
3166
  strokeLinecap: "round",
3163
3167
  strokeLinejoin: "round"
@@ -3171,7 +3175,7 @@ function ReportDialog({
3171
3175
  {
3172
3176
  style: {
3173
3177
  fontSize: "11px",
3174
- color: t.text,
3178
+ color: t2.text,
3175
3179
  flex: 1,
3176
3180
  overflow: "hidden",
3177
3181
  textOverflow: "ellipsis",
@@ -3183,7 +3187,7 @@ function ReportDialog({
3183
3187
  /* @__PURE__ */ jsxs2(
3184
3188
  "span",
3185
3189
  {
3186
- style: { fontSize: "10px", color: t.textMuted },
3190
+ style: { fontSize: "10px", color: t2.textMuted },
3187
3191
  children: [
3188
3192
  (a.size / 1024).toFixed(0),
3189
3193
  "KB"
@@ -3258,7 +3262,7 @@ function ReportDialog({
3258
3262
  },
3259
3263
  onDragLeave: () => setScreenshotDragOver(false),
3260
3264
  style: {
3261
- border: `1.5px dashed ${screenshotDragOver ? t.accent : t.inputBorder}`,
3265
+ border: `1.5px dashed ${screenshotDragOver ? t2.accent : t2.inputBorder}`,
3262
3266
  borderRadius: "8px",
3263
3267
  padding: screenshots.length + attachments.length > 0 ? "8px 12px" : "18px 12px",
3264
3268
  textAlign: "center",
@@ -3273,7 +3277,7 @@ function ReportDialog({
3273
3277
  margin: 0,
3274
3278
  fontSize: "11px",
3275
3279
  fontWeight: 500,
3276
- color: t.textMuted
3280
+ color: t2.textMuted
3277
3281
  },
3278
3282
  children: screenshotDragOver ? "Drop to attach" : "+ Add more \xB7 Drag & drop \xB7 Paste"
3279
3283
  }
@@ -3299,7 +3303,7 @@ function ReportDialog({
3299
3303
  width: "18",
3300
3304
  height: "18",
3301
3305
  rx: "2",
3302
- stroke: t.textMuted,
3306
+ stroke: t2.textMuted,
3303
3307
  strokeWidth: "1.5"
3304
3308
  }
3305
3309
  ),
@@ -3309,7 +3313,7 @@ function ReportDialog({
3309
3313
  cx: "8.5",
3310
3314
  cy: "8.5",
3311
3315
  r: "1.5",
3312
- stroke: t.textMuted,
3316
+ stroke: t2.textMuted,
3313
3317
  strokeWidth: "1.5"
3314
3318
  }
3315
3319
  ),
@@ -3317,7 +3321,7 @@ function ReportDialog({
3317
3321
  "path",
3318
3322
  {
3319
3323
  d: "M21 15l-5-5L5 21",
3320
- stroke: t.textMuted,
3324
+ stroke: t2.textMuted,
3321
3325
  strokeWidth: "1.5",
3322
3326
  strokeLinecap: "round",
3323
3327
  strokeLinejoin: "round"
@@ -3333,7 +3337,7 @@ function ReportDialog({
3333
3337
  margin: 0,
3334
3338
  fontSize: "12px",
3335
3339
  fontWeight: 600,
3336
- color: t.text
3340
+ color: t2.text
3337
3341
  },
3338
3342
  children: screenshotDragOver ? "Drop to attach" : "Add screenshots or files"
3339
3343
  }
@@ -3344,7 +3348,7 @@ function ReportDialog({
3344
3348
  style: {
3345
3349
  margin: "3px 0 0",
3346
3350
  fontSize: "11px",
3347
- color: t.textMuted
3351
+ color: t2.textMuted
3348
3352
  },
3349
3353
  children: "Images, PDF, DOC, XLS \xB7 Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
3350
3354
  }
@@ -3359,7 +3363,7 @@ function ReportDialog({
3359
3363
  {
3360
3364
  style: {
3361
3365
  fontSize: "12px",
3362
- color: t.textMuted,
3366
+ color: t2.textMuted,
3363
3367
  marginBottom: "6px",
3364
3368
  display: "block"
3365
3369
  },
@@ -3375,9 +3379,9 @@ function ReportDialog({
3375
3379
  flex: 1,
3376
3380
  padding: "6px 0",
3377
3381
  borderRadius: "6px",
3378
- border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,
3379
- background: severity === s ? t.accent : "transparent",
3380
- color: severity === s ? t.accentText : t.text,
3382
+ border: `1px solid ${severity === s ? t2.accent : t2.inputBorder}`,
3383
+ background: severity === s ? t2.accent : "transparent",
3384
+ color: severity === s ? t2.accentText : t2.text,
3381
3385
  fontSize: "12px",
3382
3386
  fontWeight: 600,
3383
3387
  cursor: "pointer",
@@ -3413,8 +3417,8 @@ function ReportDialog({
3413
3417
  padding: "10px",
3414
3418
  borderRadius: "8px",
3415
3419
  border: "none",
3416
- backgroundColor: submitDisabled ? t.bgSecondary : t.accent,
3417
- color: submitDisabled ? t.textMuted : t.accentText,
3420
+ backgroundColor: submitDisabled ? t2.bgSecondary : t2.accent,
3421
+ color: submitDisabled ? t2.textMuted : t2.accentText,
3418
3422
  fontSize: "14px",
3419
3423
  fontWeight: 600,
3420
3424
  cursor: submitDisabled ? "not-allowed" : "pointer",
@@ -3433,20 +3437,20 @@ function ReportDialog({
3433
3437
  {
3434
3438
  style: {
3435
3439
  padding: "8px 16px 10px",
3436
- borderTop: `1px solid ${t.border}`,
3440
+ borderTop: `1px solid ${t2.border}`,
3437
3441
  display: "flex",
3438
3442
  alignItems: "center",
3439
3443
  justifyContent: "space-between",
3440
3444
  gap: "12px"
3441
3445
  },
3442
3446
  children: [
3443
- /* @__PURE__ */ jsx2(ReporterChip, { reporter, t }),
3447
+ /* @__PURE__ */ jsx2(ReporterChip, { reporter, t: t2 }),
3444
3448
  /* @__PURE__ */ jsx2(
3445
3449
  "span",
3446
3450
  {
3447
3451
  style: {
3448
3452
  fontSize: "11px",
3449
- color: t.textMuted,
3453
+ color: t2.textMuted,
3450
3454
  whiteSpace: "nowrap",
3451
3455
  flexShrink: 0
3452
3456
  },
@@ -3574,8 +3578,8 @@ function ReportDialog({
3574
3578
  padding: "8px 14px",
3575
3579
  borderRadius: "999px",
3576
3580
  border: "none",
3577
- background: t.accent,
3578
- color: t.accentText,
3581
+ background: t2.accent,
3582
+ color: t2.accentText,
3579
3583
  fontSize: "13px",
3580
3584
  fontWeight: 700,
3581
3585
  cursor: "pointer",
@@ -3614,7 +3618,7 @@ function ReportDialog({
3614
3618
  "span",
3615
3619
  {
3616
3620
  style: {
3617
- color: t.textMuted,
3621
+ color: t2.textMuted,
3618
3622
  fontSize: "12px"
3619
3623
  },
3620
3624
  children: [
@@ -3800,6 +3804,400 @@ function getTypeIcon(type, color, size = 24) {
3800
3804
  }
3801
3805
  }
3802
3806
 
3807
+ // src/booking-dialog.tsx
3808
+ import { useCallback, useEffect as useEffect3, useMemo, useState as useState3 } from "react";
3809
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
3810
+ var t = {
3811
+ bg: "#141414",
3812
+ surface: "#1c1c1c",
3813
+ border: "#2a2a2a",
3814
+ text: "#e5e5e5",
3815
+ muted: "#9aa0a6",
3816
+ accent: "#3b82f6",
3817
+ danger: "#f87171"
3818
+ };
3819
+ function localZone() {
3820
+ try {
3821
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
3822
+ } catch (e) {
3823
+ return "UTC";
3824
+ }
3825
+ }
3826
+ function dayKey(iso) {
3827
+ return new Date(iso).toDateString();
3828
+ }
3829
+ function formatDay(iso) {
3830
+ return new Date(iso).toLocaleDateString(void 0, {
3831
+ weekday: "short",
3832
+ day: "numeric",
3833
+ month: "short"
3834
+ });
3835
+ }
3836
+ function formatTime(iso) {
3837
+ return new Date(iso).toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" });
3838
+ }
3839
+ function BookingDialog({
3840
+ token,
3841
+ baseUrl,
3842
+ open,
3843
+ onClose
3844
+ }) {
3845
+ var _a;
3846
+ const [step, setStep] = useState3("slots");
3847
+ const [slots, setSlots] = useState3(null);
3848
+ const [heading, setHeading] = useState3({
3849
+ title: "Book a demo",
3850
+ description: null
3851
+ });
3852
+ const [whatsappUrl, setWhatsappUrl] = useState3(null);
3853
+ const [selected, setSelected] = useState3(null);
3854
+ const [name, setName] = useState3("");
3855
+ const [email, setEmail] = useState3("");
3856
+ const [phone, setPhone] = useState3("");
3857
+ const [note, setNote] = useState3("");
3858
+ const [code, setCode] = useState3("");
3859
+ const [bookingId, setBookingId] = useState3(null);
3860
+ const [meetUrl, setMeetUrl] = useState3(null);
3861
+ const [busy, setBusy] = useState3(false);
3862
+ const [error, setError] = useState3(null);
3863
+ const headers = useMemo(
3864
+ () => ({ Authorization: `Bearer ${token}`, "Content-Type": "application/json" }),
3865
+ [token]
3866
+ );
3867
+ const loadSlots = useCallback(async () => {
3868
+ var _a2, _b, _c;
3869
+ setError(null);
3870
+ setSlots(null);
3871
+ try {
3872
+ const from = (/* @__PURE__ */ new Date()).toISOString();
3873
+ const to = new Date(Date.now() + 21 * 864e5).toISOString();
3874
+ const res = await fetch(
3875
+ `${baseUrl}/api/v1/sdk/booking/availability?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`,
3876
+ { headers }
3877
+ );
3878
+ const json = await res.json();
3879
+ if (!json.success) {
3880
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't load available times");
3881
+ setSlots([]);
3882
+ return;
3883
+ }
3884
+ setSlots((_b = json.data.slots) != null ? _b : []);
3885
+ setHeading({ title: json.data.title, description: json.data.description });
3886
+ setWhatsappUrl((_c = json.data.whatsappUrl) != null ? _c : null);
3887
+ } catch (e) {
3888
+ setError("Couldn't reach the booking service");
3889
+ setSlots([]);
3890
+ }
3891
+ }, [baseUrl, headers]);
3892
+ useEffect3(() => {
3893
+ if (!open) return;
3894
+ setStep("slots");
3895
+ setSelected(null);
3896
+ setCode("");
3897
+ setBookingId(null);
3898
+ setError(null);
3899
+ void loadSlots();
3900
+ }, [open, loadSlots]);
3901
+ useEffect3(() => {
3902
+ if (!open) return;
3903
+ const onKey = (e) => {
3904
+ if (e.key === "Escape") onClose();
3905
+ };
3906
+ document.addEventListener("keydown", onKey, true);
3907
+ return () => document.removeEventListener("keydown", onKey, true);
3908
+ }, [open, onClose]);
3909
+ if (!open) return null;
3910
+ const byDay = /* @__PURE__ */ new Map();
3911
+ for (const slot of slots != null ? slots : []) {
3912
+ const key = dayKey(slot.startsAt);
3913
+ byDay.set(key, [...(_a = byDay.get(key)) != null ? _a : [], slot]);
3914
+ }
3915
+ async function startBooking() {
3916
+ var _a2;
3917
+ if (!selected) return;
3918
+ setBusy(true);
3919
+ setError(null);
3920
+ try {
3921
+ const res = await fetch(`${baseUrl}/api/v1/sdk/booking`, {
3922
+ method: "POST",
3923
+ headers,
3924
+ body: JSON.stringify({
3925
+ name,
3926
+ email,
3927
+ phone,
3928
+ note,
3929
+ startsAt: selected.startsAt,
3930
+ timezone: localZone()
3931
+ })
3932
+ });
3933
+ const json = await res.json();
3934
+ if (!json.success) {
3935
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't hold that slot");
3936
+ return;
3937
+ }
3938
+ setBookingId(json.data.bookingId);
3939
+ setStep("code");
3940
+ } catch (e) {
3941
+ setError("Couldn't reach the booking service");
3942
+ } finally {
3943
+ setBusy(false);
3944
+ }
3945
+ }
3946
+ async function confirmBooking() {
3947
+ var _a2;
3948
+ if (!bookingId) return;
3949
+ setBusy(true);
3950
+ setError(null);
3951
+ try {
3952
+ const res = await fetch(`${baseUrl}/api/v1/sdk/booking/verify`, {
3953
+ method: "POST",
3954
+ headers,
3955
+ body: JSON.stringify({ bookingId, code })
3956
+ });
3957
+ const json = await res.json();
3958
+ if (!json.success) {
3959
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't confirm that code");
3960
+ return;
3961
+ }
3962
+ setMeetUrl(json.data.meetUrl);
3963
+ setStep("done");
3964
+ } catch (e) {
3965
+ setError("Couldn't reach the booking service");
3966
+ } finally {
3967
+ setBusy(false);
3968
+ }
3969
+ }
3970
+ const canSubmitDetails = name.trim() && email.includes("@") && phone.replace(/\D/g, "").length >= 8;
3971
+ return /* @__PURE__ */ jsx3(
3972
+ "div",
3973
+ {
3974
+ onClick: (e) => {
3975
+ if (e.target === e.currentTarget) onClose();
3976
+ },
3977
+ style: {
3978
+ position: "fixed",
3979
+ inset: 0,
3980
+ zIndex: 2147483e3,
3981
+ background: "rgba(0,0,0,.6)",
3982
+ display: "flex",
3983
+ alignItems: "center",
3984
+ justifyContent: "center",
3985
+ padding: 16,
3986
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
3987
+ },
3988
+ children: /* @__PURE__ */ jsxs3(
3989
+ "div",
3990
+ {
3991
+ role: "dialog",
3992
+ "aria-modal": "true",
3993
+ "aria-label": heading.title,
3994
+ style: {
3995
+ width: "min(440px, 100%)",
3996
+ maxHeight: "min(660px, 90vh)",
3997
+ display: "flex",
3998
+ flexDirection: "column",
3999
+ background: t.bg,
4000
+ color: t.text,
4001
+ borderRadius: 16,
4002
+ boxShadow: "0 20px 60px rgba(0,0,0,.55)",
4003
+ overflow: "hidden"
4004
+ },
4005
+ children: [
4006
+ /* @__PURE__ */ jsxs3(
4007
+ "div",
4008
+ {
4009
+ style: {
4010
+ padding: "16px 18px",
4011
+ borderBottom: `1px solid ${t.border}`,
4012
+ display: "flex",
4013
+ alignItems: "flex-start",
4014
+ justifyContent: "space-between",
4015
+ gap: 12
4016
+ },
4017
+ children: [
4018
+ /* @__PURE__ */ jsxs3("div", { children: [
4019
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: 15, fontWeight: 600 }, children: heading.title }),
4020
+ heading.description && /* @__PURE__ */ jsx3("div", { style: { fontSize: 12, color: t.muted, marginTop: 2 }, children: heading.description })
4021
+ ] }),
4022
+ /* @__PURE__ */ jsx3(
4023
+ "button",
4024
+ {
4025
+ onClick: onClose,
4026
+ "aria-label": "Close",
4027
+ style: { border: 0, background: "transparent", color: t.muted, fontSize: 20, cursor: "pointer", lineHeight: 1 },
4028
+ children: "\xD7"
4029
+ }
4030
+ )
4031
+ ]
4032
+ }
4033
+ ),
4034
+ /* @__PURE__ */ jsxs3("div", { style: { padding: 18, overflowY: "auto", flex: "1 1 auto" }, children: [
4035
+ error && /* @__PURE__ */ jsx3("div", { style: { color: t.danger, fontSize: 12, marginBottom: 12, lineHeight: 1.5 }, children: error }),
4036
+ step === "slots" && /* @__PURE__ */ jsxs3(Fragment2, { children: [
4037
+ whatsappUrl && /* @__PURE__ */ jsxs3(
4038
+ "a",
4039
+ {
4040
+ href: whatsappUrl,
4041
+ target: "_blank",
4042
+ rel: "noreferrer",
4043
+ style: {
4044
+ display: "block",
4045
+ marginBottom: 16,
4046
+ padding: "10px 14px",
4047
+ borderRadius: 10,
4048
+ border: `1px solid ${t.border}`,
4049
+ background: t.surface,
4050
+ color: t.text,
4051
+ fontSize: 13,
4052
+ textDecoration: "none"
4053
+ },
4054
+ children: [
4055
+ "\u{1F4AC} Rather book on WhatsApp?",
4056
+ /* @__PURE__ */ jsx3("span", { style: { display: "block", fontSize: 11, color: t.muted, marginTop: 2 }, children: "We'll ask the same questions in chat." })
4057
+ ]
4058
+ }
4059
+ ),
4060
+ slots === null && /* @__PURE__ */ jsx3("div", { style: { color: t.muted, fontSize: 13 }, children: "Finding times\u2026" }),
4061
+ (slots == null ? void 0 : slots.length) === 0 && !error && /* @__PURE__ */ jsx3("div", { style: { color: t.muted, fontSize: 13 }, children: "No times available right now." }),
4062
+ [...byDay.entries()].map(([day, daySlots]) => /* @__PURE__ */ jsxs3("div", { style: { marginBottom: 18 }, children: [
4063
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: 11, color: t.muted, marginBottom: 8, textTransform: "uppercase", letterSpacing: ".6px" }, children: formatDay(daySlots[0].startsAt) }),
4064
+ /* @__PURE__ */ jsx3("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: daySlots.map((slot) => /* @__PURE__ */ jsx3(
4065
+ "button",
4066
+ {
4067
+ onClick: () => {
4068
+ setSelected(slot);
4069
+ setStep("details");
4070
+ },
4071
+ style: {
4072
+ padding: "8px 14px",
4073
+ borderRadius: 999,
4074
+ border: `1px solid ${t.border}`,
4075
+ background: t.surface,
4076
+ color: t.text,
4077
+ fontSize: 13,
4078
+ cursor: "pointer"
4079
+ },
4080
+ children: formatTime(slot.startsAt)
4081
+ },
4082
+ slot.startsAt
4083
+ )) })
4084
+ ] }, day))
4085
+ ] }),
4086
+ step === "details" && selected && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4087
+ /* @__PURE__ */ jsxs3("div", { style: { fontSize: 13, color: t.muted }, children: [
4088
+ formatDay(selected.startsAt),
4089
+ " \xB7 ",
4090
+ formatTime(selected.startsAt),
4091
+ " \xB7 ",
4092
+ /* @__PURE__ */ jsx3(
4093
+ "button",
4094
+ {
4095
+ onClick: () => setStep("slots"),
4096
+ style: { border: 0, background: "transparent", color: t.accent, cursor: "pointer", fontSize: 13, padding: 0 },
4097
+ children: "change"
4098
+ }
4099
+ )
4100
+ ] }),
4101
+ /* @__PURE__ */ jsx3(Field, { label: "Your name", value: name, onChange: setName }),
4102
+ /* @__PURE__ */ jsx3(Field, { label: "Email", value: email, onChange: setEmail, type: "email" }),
4103
+ /* @__PURE__ */ jsx3(
4104
+ Field,
4105
+ {
4106
+ label: "Mobile number",
4107
+ value: phone,
4108
+ onChange: setPhone,
4109
+ type: "tel",
4110
+ hint: "We send a code here to confirm, then a reminder before the call."
4111
+ }
4112
+ ),
4113
+ /* @__PURE__ */ jsx3(Field, { label: "Anything we should know? (optional)", value: note, onChange: setNote }),
4114
+ /* @__PURE__ */ jsx3(
4115
+ "button",
4116
+ {
4117
+ onClick: startBooking,
4118
+ disabled: !canSubmitDetails || busy,
4119
+ style: primaryStyle(!canSubmitDetails || busy),
4120
+ children: busy ? "Sending code\u2026" : "Send verification code"
4121
+ }
4122
+ )
4123
+ ] }),
4124
+ step === "code" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4125
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.5 }, children: "We sent a 4-digit code to your phone. Your slot is held for 10 minutes." }),
4126
+ /* @__PURE__ */ jsx3(Field, { label: "Code", value: code, onChange: setCode }),
4127
+ /* @__PURE__ */ jsx3(
4128
+ "button",
4129
+ {
4130
+ onClick: confirmBooking,
4131
+ disabled: code.trim().length < 4 || busy,
4132
+ style: primaryStyle(code.trim().length < 4 || busy),
4133
+ children: busy ? "Confirming\u2026" : "Confirm booking"
4134
+ }
4135
+ )
4136
+ ] }),
4137
+ step === "done" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4138
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: 15, fontWeight: 600 }, children: "You're booked." }),
4139
+ /* @__PURE__ */ jsxs3("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.6 }, children: [
4140
+ selected && `${formatDay(selected.startsAt)} at ${formatTime(selected.startsAt)}. `,
4141
+ "A calendar invite is on its way to ",
4142
+ email,
4143
+ ", and we'll send a WhatsApp reminder before the call."
4144
+ ] }),
4145
+ meetUrl && /* @__PURE__ */ jsx3("a", { href: meetUrl, target: "_blank", rel: "noreferrer", style: { ...primaryStyle(false), textAlign: "center", textDecoration: "none" }, children: "Open the meeting link" })
4146
+ ] })
4147
+ ] })
4148
+ ]
4149
+ }
4150
+ )
4151
+ }
4152
+ );
4153
+ }
4154
+ function primaryStyle(disabled) {
4155
+ return {
4156
+ marginTop: 4,
4157
+ padding: "10px 16px",
4158
+ borderRadius: 999,
4159
+ border: 0,
4160
+ background: disabled ? "#2a2a2a" : t.accent,
4161
+ color: disabled ? "#6b7280" : "#fff",
4162
+ fontSize: 14,
4163
+ fontWeight: 500,
4164
+ cursor: disabled ? "default" : "pointer"
4165
+ };
4166
+ }
4167
+ function Field({
4168
+ label,
4169
+ value,
4170
+ onChange,
4171
+ type = "text",
4172
+ hint
4173
+ }) {
4174
+ return /* @__PURE__ */ jsxs3("label", { style: { display: "block", fontSize: 11, color: t.muted }, children: [
4175
+ label,
4176
+ /* @__PURE__ */ jsx3(
4177
+ "input",
4178
+ {
4179
+ type,
4180
+ value,
4181
+ onChange: (e) => onChange(e.target.value),
4182
+ style: {
4183
+ display: "block",
4184
+ width: "100%",
4185
+ boxSizing: "border-box",
4186
+ marginTop: 4,
4187
+ padding: "9px 12px",
4188
+ background: t.surface,
4189
+ color: t.text,
4190
+ border: `1px solid ${t.border}`,
4191
+ borderRadius: 8,
4192
+ fontSize: 13,
4193
+ outline: "none"
4194
+ }
4195
+ }
4196
+ ),
4197
+ hint && /* @__PURE__ */ jsx3("div", { style: { marginTop: 4, fontSize: 10, color: t.muted }, children: hint })
4198
+ ] });
4199
+ }
4200
+
3803
4201
  // src/rejection.ts
3804
4202
  var DETAILS_MAX_LENGTH = 1e3;
3805
4203
  var MESSAGE_MAX_LENGTH = 200;
@@ -3855,6 +4253,36 @@ function describeShape(reason) {
3855
4253
  return "";
3856
4254
  }
3857
4255
  }
4256
+ var EVENT_URL_MAX_LENGTH = 120;
4257
+ function isEventLike(reason) {
4258
+ try {
4259
+ if (typeof Event !== "undefined" && reason instanceof Event) return true;
4260
+ const source = reason;
4261
+ return typeof (source == null ? void 0 : source.type) === "string" && typeof (source == null ? void 0 : source.isTrusted) === "boolean";
4262
+ } catch (e) {
4263
+ return false;
4264
+ }
4265
+ }
4266
+ function describeEvent(reason) {
4267
+ var _a, _b, _c, _d, _e;
4268
+ const parts = [];
4269
+ try {
4270
+ const source = reason;
4271
+ const name = ((_a = source.constructor) == null ? void 0 : _a.name) || "Event";
4272
+ parts.push(`${name} ("${String((_b = source.type) != null ? _b : "")}")`);
4273
+ } catch (e) {
4274
+ parts.push("Event");
4275
+ }
4276
+ try {
4277
+ const target = reason.target;
4278
+ const tag = (_c = target == null ? void 0 : target.tagName) == null ? void 0 : _c.toLowerCase();
4279
+ if (tag) parts.push(`from <${tag}>`);
4280
+ const url = (_e = (_d = readString(target == null ? void 0 : target.currentSrc)) != null ? _d : readString(target == null ? void 0 : target.src)) != null ? _e : readString(target == null ? void 0 : target.href);
4281
+ if (url) parts.push(`\u2014 ${url.split(/[?#]/)[0].slice(0, EVENT_URL_MAX_LENGTH)}`);
4282
+ } catch (e) {
4283
+ }
4284
+ return parts.join(" ").slice(0, MESSAGE_MAX_LENGTH);
4285
+ }
3858
4286
  function describeRejection(reason) {
3859
4287
  var _a, _b, _c, _d, _e, _f, _g, _h;
3860
4288
  try {
@@ -3879,7 +4307,7 @@ function describeRejection(reason) {
3879
4307
  const message = (_h = (_g = (_f = (_e = (_d = (_c = (_b = readString(source.message)) != null ? _b : readString(nestedError)) != null ? _c : readString(nestedError == null ? void 0 : nestedError.message)) != null ? _d : readScalar(source.code)) != null ? _e : readString(source.name)) != null ? _f : readScalar(source.status)) != null ? _g : readString(source.statusText)) != null ? _h : "";
3880
4308
  const details = serialize(reason);
3881
4309
  return {
3882
- message: message || describeShape(reason),
4310
+ message: message || (isEventLike(reason) ? describeEvent(reason) : describeShape(reason)),
3883
4311
  stack,
3884
4312
  details
3885
4313
  };
@@ -3907,7 +4335,7 @@ function matchesShortcut(e) {
3907
4335
  }
3908
4336
 
3909
4337
  // src/provider.tsx
3910
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
4338
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
3911
4339
  var DEFAULT_BASE_URL2 = "https://glitchgrab.dev";
3912
4340
  var GlitchgrabContext = createContext(null);
3913
4341
  function useGlitchgrab() {
@@ -3946,12 +4374,12 @@ function GlitchgrabProviderInner({
3946
4374
  onError,
3947
4375
  onReportSent
3948
4376
  });
3949
- useEffect3(() => {
4377
+ useEffect4(() => {
3950
4378
  if (enableBreadcrumbs) {
3951
4379
  initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
3952
4380
  }
3953
4381
  }, [enableBreadcrumbs, maxBreadcrumbs2, responseBodyOrigins2 == null ? void 0 : responseBodyOrigins2.join(",")]);
3954
- useEffect3(() => {
4382
+ useEffect4(() => {
3955
4383
  try {
3956
4384
  if (typeof window === "undefined") return;
3957
4385
  const trackPage = () => {
@@ -3988,7 +4416,7 @@ function GlitchgrabProviderInner({
3988
4416
  } catch (e) {
3989
4417
  }
3990
4418
  }, []);
3991
- useEffect3(() => {
4419
+ useEffect4(() => {
3992
4420
  try {
3993
4421
  if (typeof window === "undefined") return;
3994
4422
  if (process.env.NODE_ENV === "development") return;
@@ -4115,7 +4543,7 @@ function GlitchgrabProviderInner({
4115
4543
  } catch (e) {
4116
4544
  }
4117
4545
  }, [token, baseUrl, onError, onReportSent, session, ignoreErrors]);
4118
- const report = useCallback(
4546
+ const report = useCallback2(
4119
4547
  async (type, description, metadata) => {
4120
4548
  var _a;
4121
4549
  try {
@@ -4149,11 +4577,11 @@ function GlitchgrabProviderInner({
4149
4577
  },
4150
4578
  [token, baseUrl, onReportSent, session]
4151
4579
  );
4152
- const reportBug = useCallback(
4580
+ const reportBug = useCallback2(
4153
4581
  (description, metadata) => report("BUG", description, metadata),
4154
4582
  [report]
4155
4583
  );
4156
- const feedback = useCallback(
4584
+ const feedback = useCallback2(
4157
4585
  async (rating, message, metadata) => {
4158
4586
  try {
4159
4587
  const context = captureContext(visitedPagesRef.current);
@@ -4181,32 +4609,32 @@ function GlitchgrabProviderInner({
4181
4609
  },
4182
4610
  [token, baseUrl, session]
4183
4611
  );
4184
- const openFeedbackDialog = useCallback(() => {
4612
+ const openFeedbackDialog = useCallback2(() => {
4185
4613
  if (typeof window !== "undefined") {
4186
4614
  window.dispatchEvent(
4187
4615
  new CustomEvent("glitchgrab:open-report", { detail: { type: "RATING" } })
4188
4616
  );
4189
4617
  }
4190
4618
  }, []);
4191
- const captureError2 = useCallback(
4619
+ const captureError2 = useCallback2(
4192
4620
  (error, options) => {
4193
4621
  captureError(error, options);
4194
4622
  },
4195
4623
  []
4196
4624
  );
4197
- const setContext2 = useCallback((key, value) => {
4625
+ const setContext2 = useCallback2((key, value) => {
4198
4626
  setContext(key, value);
4199
4627
  }, []);
4200
- const setContexts2 = useCallback((values) => {
4628
+ const setContexts2 = useCallback2((values) => {
4201
4629
  setContexts(values);
4202
4630
  }, []);
4203
- const addBreadcrumb2 = useCallback(
4631
+ const addBreadcrumb2 = useCallback2(
4204
4632
  (message, data) => {
4205
4633
  addBreadcrumb("custom", message, data);
4206
4634
  },
4207
4635
  []
4208
4636
  );
4209
- const enhance = useCallback(
4637
+ const enhance = useCallback2(
4210
4638
  async (text, screenshot) => {
4211
4639
  try {
4212
4640
  const ctx = captureContext(visitedPagesRef.current);
@@ -4222,7 +4650,7 @@ function GlitchgrabProviderInner({
4222
4650
  },
4223
4651
  [token, baseUrl]
4224
4652
  );
4225
- const transcribe = useCallback(
4653
+ const transcribe = useCallback2(
4226
4654
  async (blob) => {
4227
4655
  try {
4228
4656
  return await transcribeAudio(blob, token, baseUrl);
@@ -4232,12 +4660,37 @@ function GlitchgrabProviderInner({
4232
4660
  },
4233
4661
  [token, baseUrl]
4234
4662
  );
4235
- const openReportDialog = useCallback((options) => {
4663
+ const openReportDialog = useCallback2((options) => {
4236
4664
  if (typeof window !== "undefined") {
4237
4665
  window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
4238
4666
  }
4239
4667
  }, []);
4240
- useEffect3(() => {
4668
+ useEffect4(() => {
4669
+ try {
4670
+ if (typeof document === "undefined") return;
4671
+ document.documentElement.setAttribute("data-glitchgrab-sdk", "1");
4672
+ return () => document.documentElement.removeAttribute("data-glitchgrab-sdk");
4673
+ } catch (e) {
4674
+ }
4675
+ }, []);
4676
+ const [projectName, setProjectName] = useState4(null);
4677
+ const [bookingOpen, setBookingOpen] = useState4(false);
4678
+ const openBookingDialog = useCallback2(() => setBookingOpen(true), []);
4679
+ useEffect4(() => {
4680
+ let cancelled = false;
4681
+ fetch(`${baseUrl}/api/v1/sdk/project`, {
4682
+ headers: { Authorization: `Bearer ${token}` }
4683
+ }).then((r) => r.ok ? r.json() : null).then((json) => {
4684
+ var _a;
4685
+ if (cancelled || !(json == null ? void 0 : json.success) || !((_a = json.data) == null ? void 0 : _a.name)) return;
4686
+ setProjectName(json.data.name);
4687
+ }).catch(() => {
4688
+ });
4689
+ return () => {
4690
+ cancelled = true;
4691
+ };
4692
+ }, [baseUrl, token]);
4693
+ useEffect4(() => {
4241
4694
  try {
4242
4695
  if (typeof window === "undefined") return;
4243
4696
  const handleKeyDown = (e) => {
@@ -4251,7 +4704,7 @@ function GlitchgrabProviderInner({
4251
4704
  } catch (e) {
4252
4705
  }
4253
4706
  }, [openReportDialog]);
4254
- const reporter = useMemo(() => {
4707
+ const reporter = useMemo2(() => {
4255
4708
  var _a;
4256
4709
  if (!session) return null;
4257
4710
  const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
@@ -4261,11 +4714,11 @@ function GlitchgrabProviderInner({
4261
4714
  avatarUrl: typeof avatar === "string" ? avatar : null
4262
4715
  };
4263
4716
  }, [session]);
4264
- const [shortcutLabel, setShortcutLabel] = useState3(GLITCHGRAB_SHORTCUT2);
4265
- useEffect3(() => {
4717
+ const [shortcutLabel, setShortcutLabel] = useState4(GLITCHGRAB_SHORTCUT2);
4718
+ useEffect4(() => {
4266
4719
  setShortcutLabel(getShortcutLabel2());
4267
4720
  }, []);
4268
- return /* @__PURE__ */ jsxs3(
4721
+ return /* @__PURE__ */ jsxs4(
4269
4722
  GlitchgrabContext.Provider,
4270
4723
  {
4271
4724
  value: {
@@ -4280,11 +4733,12 @@ function GlitchgrabProviderInner({
4280
4733
  openFeedbackDialog,
4281
4734
  addBreadcrumb: addBreadcrumb2,
4282
4735
  openReportDialog,
4736
+ openBookingDialog,
4283
4737
  enhanceText: enhance,
4284
4738
  shortcutLabel
4285
4739
  },
4286
4740
  children: [
4287
- /* @__PURE__ */ jsx3(
4741
+ /* @__PURE__ */ jsx4(
4288
4742
  GlitchgrabErrorBoundary,
4289
4743
  {
4290
4744
  token,
@@ -4296,27 +4750,51 @@ function GlitchgrabProviderInner({
4296
4750
  children
4297
4751
  }
4298
4752
  ),
4299
- /* @__PURE__ */ jsx3(ReportDialog, { report, sendFeedback: feedback, enhanceText: enhance, transcribeAudio: transcribe, types, showSeverity, reporter })
4753
+ /* @__PURE__ */ jsx4(
4754
+ BookingDialog,
4755
+ {
4756
+ token,
4757
+ baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
4758
+ open: bookingOpen,
4759
+ onClose: () => setBookingOpen(false)
4760
+ }
4761
+ ),
4762
+ /* @__PURE__ */ jsx4(
4763
+ ReportDialog,
4764
+ {
4765
+ report,
4766
+ sendFeedback: feedback,
4767
+ enhanceText: enhance,
4768
+ transcribeAudio: transcribe,
4769
+ types,
4770
+ showSeverity,
4771
+ reporter,
4772
+ headerSlot: projectName ? /* @__PURE__ */ jsxs4("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
4773
+ "Reporting to ",
4774
+ /* @__PURE__ */ jsx4("strong", { style: { color: "#e5e5e5" }, children: projectName })
4775
+ ] }) : null
4776
+ }
4777
+ )
4300
4778
  ]
4301
4779
  }
4302
4780
  );
4303
4781
  }
4304
4782
  function GlitchgrabProvider(props) {
4305
- if (!props.token) return /* @__PURE__ */ jsx3(Fragment2, { children: props.children });
4783
+ if (!props.token) return /* @__PURE__ */ jsx4(Fragment3, { children: props.children });
4306
4784
  const resolvedProps = {
4307
4785
  ...props,
4308
4786
  baseUrl: props.baseUrl || DEFAULT_BASE_URL2
4309
4787
  };
4310
4788
  try {
4311
- return /* @__PURE__ */ jsx3(GlitchgrabProviderInner, { ...resolvedProps });
4789
+ return /* @__PURE__ */ jsx4(GlitchgrabProviderInner, { ...resolvedProps });
4312
4790
  } catch (e) {
4313
- return /* @__PURE__ */ jsx3(Fragment2, { children: props.children });
4791
+ return /* @__PURE__ */ jsx4(Fragment3, { children: props.children });
4314
4792
  }
4315
4793
  }
4316
4794
 
4317
4795
  // src/report-button.tsx
4318
- import { useState as useState4 } from "react";
4319
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
4796
+ import { useState as useState5 } from "react";
4797
+ import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4320
4798
  function useGlitchgrabSafe() {
4321
4799
  try {
4322
4800
  return useGlitchgrab();
@@ -4331,7 +4809,7 @@ function ReportButton({
4331
4809
  children
4332
4810
  }) {
4333
4811
  var _a, _b;
4334
- const [capturing, setCapturing] = useState4(false);
4812
+ const [capturing, setCapturing] = useState5(false);
4335
4813
  const glitchgrab = useGlitchgrabSafe();
4336
4814
  if (!glitchgrab) return null;
4337
4815
  const handleClick = async () => {
@@ -4340,7 +4818,7 @@ function ReportButton({
4340
4818
  setCapturing(false);
4341
4819
  };
4342
4820
  if (children) {
4343
- return /* @__PURE__ */ jsx4(Fragment3, { children: children({ onClick: handleClick, capturing }) });
4821
+ return /* @__PURE__ */ jsx5(Fragment4, { children: children({ onClick: handleClick, capturing }) });
4344
4822
  }
4345
4823
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4346
4824
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4348,7 +4826,7 @@ function ReportButton({
4348
4826
  ...isLeft ? { left: "16px" } : { right: "16px" },
4349
4827
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4350
4828
  };
4351
- return /* @__PURE__ */ jsxs4(
4829
+ return /* @__PURE__ */ jsxs5(
4352
4830
  "button",
4353
4831
  {
4354
4832
  type: "button",
@@ -4383,7 +4861,7 @@ function ReportButton({
4383
4861
  },
4384
4862
  "aria-label": label,
4385
4863
  children: [
4386
- /* @__PURE__ */ jsx4(
4864
+ /* @__PURE__ */ jsx5(
4387
4865
  "svg",
4388
4866
  {
4389
4867
  width: "16",
@@ -4391,7 +4869,7 @@ function ReportButton({
4391
4869
  viewBox: "0 0 16 16",
4392
4870
  fill: "none",
4393
4871
  style: { flexShrink: 0 },
4394
- children: /* @__PURE__ */ jsx4(
4872
+ children: /* @__PURE__ */ jsx5(
4395
4873
  "path",
4396
4874
  {
4397
4875
  d: "M8 1C4.134 1 1 4.134 1 8s3.134 7 7 7 7-3.134 7-7-3.134-7-7-7zm0 12.5a.75.75 0 110-1.5.75.75 0 010 1.5zm.75-3.5a.75.75 0 01-1.5 0V5a.75.75 0 011.5 0v5z",
@@ -4406,8 +4884,38 @@ function ReportButton({
4406
4884
  );
4407
4885
  }
4408
4886
 
4887
+ // src/book-demo-button.tsx
4888
+ import { Fragment as Fragment5, jsx as jsx6 } from "react/jsx-runtime";
4889
+ function BookDemoButton({
4890
+ label = "Book a demo",
4891
+ className,
4892
+ children
4893
+ }) {
4894
+ const { openBookingDialog } = useGlitchgrab();
4895
+ if (children) return /* @__PURE__ */ jsx6(Fragment5, { children: children({ onClick: openBookingDialog }) });
4896
+ return /* @__PURE__ */ jsx6(
4897
+ "button",
4898
+ {
4899
+ type: "button",
4900
+ onClick: openBookingDialog,
4901
+ className,
4902
+ style: className ? void 0 : {
4903
+ padding: "10px 18px",
4904
+ borderRadius: 999,
4905
+ border: 0,
4906
+ background: "#3b82f6",
4907
+ color: "#fff",
4908
+ fontSize: 14,
4909
+ fontWeight: 500,
4910
+ cursor: "pointer"
4911
+ },
4912
+ children: label
4913
+ }
4914
+ );
4915
+ }
4916
+
4409
4917
  // src/feedback-button.tsx
4410
- import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4918
+ import { Fragment as Fragment6, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
4411
4919
  function useGlitchgrabSafe2() {
4412
4920
  try {
4413
4921
  return useGlitchgrab();
@@ -4426,7 +4934,7 @@ function FeedbackButton({
4426
4934
  if (!glitchgrab) return null;
4427
4935
  const handleClick = () => glitchgrab.openFeedbackDialog();
4428
4936
  if (children) {
4429
- return /* @__PURE__ */ jsx5(Fragment4, { children: children({ onClick: handleClick }) });
4937
+ return /* @__PURE__ */ jsx7(Fragment6, { children: children({ onClick: handleClick }) });
4430
4938
  }
4431
4939
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4432
4940
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4434,7 +4942,7 @@ function FeedbackButton({
4434
4942
  ...isLeft ? { left: "16px" } : { right: "16px" },
4435
4943
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4436
4944
  };
4437
- return /* @__PURE__ */ jsxs5(
4945
+ return /* @__PURE__ */ jsxs6(
4438
4946
  "button",
4439
4947
  {
4440
4948
  type: "button",
@@ -4467,7 +4975,7 @@ function FeedbackButton({
4467
4975
  },
4468
4976
  "aria-label": label,
4469
4977
  children: [
4470
- /* @__PURE__ */ jsx5(
4978
+ /* @__PURE__ */ jsx7(
4471
4979
  "svg",
4472
4980
  {
4473
4981
  width: "16",
@@ -4476,7 +4984,7 @@ function FeedbackButton({
4476
4984
  fill: "none",
4477
4985
  style: { flexShrink: 0 },
4478
4986
  "aria-hidden": "true",
4479
- children: /* @__PURE__ */ jsx5(
4987
+ children: /* @__PURE__ */ jsx7(
4480
4988
  "path",
4481
4989
  {
4482
4990
  d: "M12 2.5l2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 17.4l-5.8 3 1.1-6.5L2.6 9.3l6.5-.9L12 2.5z",
@@ -4492,18 +5000,18 @@ function FeedbackButton({
4492
5000
  }
4493
5001
 
4494
5002
  // src/use-reports.ts
4495
- import { useState as useState5, useEffect as useEffect4, useCallback as useCallback2 } from "react";
5003
+ import { useState as useState6, useEffect as useEffect5, useCallback as useCallback3 } from "react";
4496
5004
  var BASE_URL = "https://glitchgrab.dev";
4497
5005
  function useGlitchgrabReports({
4498
5006
  token,
4499
5007
  userId,
4500
5008
  limit = 100
4501
5009
  }) {
4502
- const [reports, setReports] = useState5([]);
4503
- const [isLoading, setIsLoading] = useState5(true);
4504
- const [isFetching, setIsFetching] = useState5(false);
4505
- const [error, setError] = useState5(null);
4506
- const fetchReports = useCallback2(async () => {
5010
+ const [reports, setReports] = useState6([]);
5011
+ const [isLoading, setIsLoading] = useState6(true);
5012
+ const [isFetching, setIsFetching] = useState6(false);
5013
+ const [error, setError] = useState6(null);
5014
+ const fetchReports = useCallback3(async () => {
4507
5015
  var _a, _b;
4508
5016
  if (!token || !userId) {
4509
5017
  setIsLoading(false);
@@ -4529,7 +5037,7 @@ function useGlitchgrabReports({
4529
5037
  setIsFetching(false);
4530
5038
  }
4531
5039
  }, [token, userId, limit]);
4532
- useEffect4(() => {
5040
+ useEffect5(() => {
4533
5041
  fetchReports();
4534
5042
  }, [fetchReports]);
4535
5043
  return { reports, isLoading, isFetching, error, refetch: fetchReports };
@@ -4566,9 +5074,9 @@ function useGlitchgrabActions({
4566
5074
  onSuccess,
4567
5075
  onError
4568
5076
  }) {
4569
- const [isPending, setIsPending] = useState5(false);
4570
- const [error, setError] = useState5(null);
4571
- const run = useCallback2(
5077
+ const [isPending, setIsPending] = useState6(false);
5078
+ const [error, setError] = useState6(null);
5079
+ const run = useCallback3(
4572
5080
  async (reportId, body) => {
4573
5081
  setIsPending(true);
4574
5082
  setError(null);
@@ -4598,7 +5106,7 @@ function useGlitchgrabActions({
4598
5106
  }
4599
5107
 
4600
5108
  // src/use-feedback.ts
4601
- import { useState as useState6, useEffect as useEffect5, useCallback as useCallback3 } from "react";
5109
+ import { useState as useState7, useEffect as useEffect6, useCallback as useCallback4 } from "react";
4602
5110
  var DEFAULT_BASE_URL3 = "https://glitchgrab.dev";
4603
5111
  function buildUrl({
4604
5112
  approvedOnly,
@@ -4624,11 +5132,11 @@ async function fetchGlitchgrabFeedback(query) {
4624
5132
  }
4625
5133
  function useGlitchgrabFeedback(query) {
4626
5134
  const { token, approvedOnly, userId, minRating, limit, baseUrl } = query;
4627
- const [feedback, setFeedback] = useState6([]);
4628
- const [isLoading, setIsLoading] = useState6(true);
4629
- const [isFetching, setIsFetching] = useState6(false);
4630
- const [error, setError] = useState6(null);
4631
- const load = useCallback3(async () => {
5135
+ const [feedback, setFeedback] = useState7([]);
5136
+ const [isLoading, setIsLoading] = useState7(true);
5137
+ const [isFetching, setIsFetching] = useState7(false);
5138
+ const [error, setError] = useState7(null);
5139
+ const load = useCallback4(async () => {
4632
5140
  if (!token) {
4633
5141
  setIsLoading(false);
4634
5142
  return;
@@ -4652,12 +5160,13 @@ function useGlitchgrabFeedback(query) {
4652
5160
  setIsFetching(false);
4653
5161
  }
4654
5162
  }, [token, approvedOnly, userId, minRating, limit, baseUrl]);
4655
- useEffect5(() => {
5163
+ useEffect6(() => {
4656
5164
  load();
4657
5165
  }, [load]);
4658
5166
  return { feedback, isLoading, isFetching, error, refetch: load };
4659
5167
  }
4660
5168
  export {
5169
+ BookDemoButton,
4661
5170
  FeedbackButton,
4662
5171
  GLITCHGRAB_SHORTCUT2 as GLITCHGRAB_SHORTCUT,
4663
5172
  GLITCHGRAB_SHORTCUT_MAC2 as GLITCHGRAB_SHORTCUT_MAC,