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.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ BookDemoButton: () => BookDemoButton,
34
35
  FeedbackButton: () => FeedbackButton,
35
36
  GLITCHGRAB_SHORTCUT: () => GLITCHGRAB_SHORTCUT2,
36
37
  GLITCHGRAB_SHORTCUT_MAC: () => GLITCHGRAB_SHORTCUT_MAC2,
@@ -67,7 +68,7 @@ __export(index_exports, {
67
68
  module.exports = __toCommonJS(index_exports);
68
69
 
69
70
  // src/provider.tsx
70
- var import_react3 = require("react");
71
+ var import_react4 = require("react");
71
72
 
72
73
  // src/error-boundary.tsx
73
74
  var React = __toESM(require("react"));
@@ -688,9 +689,9 @@ function topStackFrame(stack) {
688
689
  if (!stack) return "";
689
690
  const lines = stack.split("\n");
690
691
  for (const line of lines) {
691
- const t = line.trim();
692
- if (t.startsWith("at ") || t.includes("@")) {
693
- return t;
692
+ const t2 = line.trim();
693
+ if (t2.startsWith("at ") || t2.includes("@")) {
694
+ return t2;
694
695
  }
695
696
  }
696
697
  return "";
@@ -1327,7 +1328,7 @@ function initialsOf(name) {
1327
1328
  }
1328
1329
  function ReporterChip({
1329
1330
  reporter,
1330
- t
1331
+ t: t2
1331
1332
  }) {
1332
1333
  var _a;
1333
1334
  const [avatarFailed, setAvatarFailed] = (0, import_react.useState)(false);
@@ -1363,9 +1364,9 @@ function ReporterChip({
1363
1364
  fontSize: "8px",
1364
1365
  fontWeight: 700,
1365
1366
  letterSpacing: "0.02em",
1366
- background: isAnonymous ? t.inputBg : t.accent,
1367
- color: isAnonymous ? t.textMuted : t.accentText,
1368
- border: `1px solid ${isAnonymous ? t.inputBorder : "transparent"}`
1367
+ background: isAnonymous ? t2.inputBg : t2.accent,
1368
+ color: isAnonymous ? t2.textMuted : t2.accentText,
1369
+ border: `1px solid ${isAnonymous ? t2.inputBorder : "transparent"}`
1369
1370
  },
1370
1371
  children: showAvatarImage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1371
1372
  "img",
@@ -1396,7 +1397,7 @@ function ReporterChip({
1396
1397
  {
1397
1398
  style: {
1398
1399
  fontSize: "11px",
1399
- color: t.textMuted,
1400
+ color: t2.textMuted,
1400
1401
  overflow: "hidden",
1401
1402
  textOverflow: "ellipsis",
1402
1403
  whiteSpace: "nowrap"
@@ -1509,7 +1510,9 @@ function ReportDialog({
1509
1510
  types,
1510
1511
  showSeverity = true,
1511
1512
  captureScreenshot = captureViaHtml2Canvas,
1512
- reporter
1513
+ reporter,
1514
+ onClose,
1515
+ headerSlot
1513
1516
  }) {
1514
1517
  const [isEnhancing, setIsEnhancing] = (0, import_react.useState)(false);
1515
1518
  const [isEnhanced, setIsEnhanced] = (0, import_react.useState)(false);
@@ -1651,7 +1654,7 @@ function ReportDialog({
1651
1654
  (_c = tiles[next]) == null ? void 0 : _c.focus();
1652
1655
  };
1653
1656
  const isDark = useIsDark();
1654
- const t = getTheme(isDark);
1657
+ const t2 = getTheme(isDark);
1655
1658
  const canZoomPreview = previewNatural !== null && typeof window !== "undefined" && (previewNatural.w > window.innerWidth - 32 || previewNatural.h > window.innerHeight - 80);
1656
1659
  const handleFileUpload = (e) => {
1657
1660
  const files = e.target.files;
@@ -1827,7 +1830,7 @@ function ReportDialog({
1827
1830
  sarvamChunksRef.current = [];
1828
1831
  const stream = streamRef.current;
1829
1832
  streamRef.current = null;
1830
- stream == null ? void 0 : stream.getTracks().forEach((t2) => t2.stop());
1833
+ stream == null ? void 0 : stream.getTracks().forEach((t22) => t22.stop());
1831
1834
  try {
1832
1835
  (_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
1833
1836
  } catch (e) {
@@ -1850,6 +1853,7 @@ function ReportDialog({
1850
1853
  const handleClose = () => {
1851
1854
  stopVoice();
1852
1855
  setIsOpen(false);
1856
+ onClose == null ? void 0 : onClose();
1853
1857
  closePreview();
1854
1858
  setAnnotatingIndex(null);
1855
1859
  setStep(1);
@@ -1888,7 +1892,7 @@ function ReportDialog({
1888
1892
  if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
1889
1893
  };
1890
1894
  rec.onstop = async () => {
1891
- stream.getTracks().forEach((t2) => t2.stop());
1895
+ stream.getTracks().forEach((t22) => t22.stop());
1892
1896
  if (streamRef.current === stream) streamRef.current = null;
1893
1897
  mediaRecorderRef.current = null;
1894
1898
  const chunks = sarvamChunksRef.current;
@@ -2089,7 +2093,7 @@ function ReportDialog({
2089
2093
  button[data-gg-type]{transition:transform .15s ease,border-color .15s ease,box-shadow .15s ease,background-color .15s ease}
2090
2094
  button[data-gg-type]:hover{transform:translateY(-2px);box-shadow:0 6px 16px rgba(0,0,0,.18)}
2091
2095
  button[data-gg-type]:active{transform:translateY(0) scale(.985);box-shadow:none}
2092
- button[data-gg-type]:focus-visible{outline:2px solid ${t.accent};outline-offset:2px}
2096
+ button[data-gg-type]:focus-visible{outline:2px solid ${t2.accent};outline-offset:2px}
2093
2097
  @keyframes gg-star-pop{0%{transform:scale(.6);opacity:0}60%{transform:scale(1.12)}100%{transform:scale(1);opacity:1}}
2094
2098
  button[data-gg-star]{transition:transform .12s ease}
2095
2099
  button[data-gg-star]:hover{transform:scale(1.18)}
@@ -2132,12 +2136,12 @@ function ReportDialog({
2132
2136
  maxHeight: "calc(100dvh - 32px)",
2133
2137
  display: "flex",
2134
2138
  flexDirection: "column",
2135
- backgroundColor: t.bg,
2139
+ backgroundColor: t2.bg,
2136
2140
  borderRadius: "12px",
2137
2141
  boxShadow: "0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)",
2138
2142
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2139
2143
  overflow: "hidden",
2140
- color: t.text,
2144
+ color: t2.text,
2141
2145
  isolation: "isolate"
2142
2146
  },
2143
2147
  children: [
@@ -2147,7 +2151,7 @@ function ReportDialog({
2147
2151
  style: {
2148
2152
  flexShrink: 0,
2149
2153
  padding: "16px 16px 12px",
2150
- borderBottom: `1px solid ${t.border}`
2154
+ borderBottom: `1px solid ${t2.border}`
2151
2155
  },
2152
2156
  children: [
2153
2157
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -2193,7 +2197,7 @@ function ReportDialog({
2193
2197
  "path",
2194
2198
  {
2195
2199
  d: "M10 3L5 8L10 13",
2196
- stroke: t.textMuted,
2200
+ stroke: t2.textMuted,
2197
2201
  strokeWidth: "2",
2198
2202
  strokeLinecap: "round",
2199
2203
  strokeLinejoin: "round"
@@ -2209,7 +2213,7 @@ function ReportDialog({
2209
2213
  style: {
2210
2214
  fontSize: "15px",
2211
2215
  fontWeight: 600,
2212
- color: t.text
2216
+ color: t2.text
2213
2217
  },
2214
2218
  children: step === 1 ? "What's on your mind?" : "Tell us more"
2215
2219
  }
@@ -2236,9 +2240,9 @@ function ReportDialog({
2236
2240
  lineHeight: 1,
2237
2241
  padding: "3px 6px",
2238
2242
  borderRadius: "4px",
2239
- border: `1px solid ${t.inputBorder}`,
2240
- background: t.inputBg,
2241
- color: t.textMuted,
2243
+ border: `1px solid ${t2.inputBorder}`,
2244
+ background: t2.inputBg,
2245
+ color: t2.textMuted,
2242
2246
  whiteSpace: "nowrap"
2243
2247
  },
2244
2248
  children: getShortcutLabel()
@@ -2271,7 +2275,7 @@ function ReportDialog({
2271
2275
  "path",
2272
2276
  {
2273
2277
  d: "M4 4L12 12M12 4L4 12",
2274
- stroke: t.textMuted,
2278
+ stroke: t2.textMuted,
2275
2279
  strokeWidth: "2",
2276
2280
  strokeLinecap: "round"
2277
2281
  }
@@ -2308,7 +2312,7 @@ function ReportDialog({
2308
2312
  width: "8px",
2309
2313
  height: "8px",
2310
2314
  borderRadius: "50%",
2311
- backgroundColor: s <= step ? t.accent : t.inputBorder,
2315
+ backgroundColor: s <= step ? t2.accent : t2.inputBorder,
2312
2316
  transition: "background-color 0.2s ease"
2313
2317
  }
2314
2318
  }
@@ -2319,7 +2323,7 @@ function ReportDialog({
2319
2323
  style: {
2320
2324
  width: "40px",
2321
2325
  height: "2px",
2322
- backgroundColor: s < step ? t.accent : t.inputBorder,
2326
+ backgroundColor: s < step ? t2.accent : t2.inputBorder,
2323
2327
  transition: "background-color 0.2s ease"
2324
2328
  }
2325
2329
  }
@@ -2348,7 +2352,7 @@ function ReportDialog({
2348
2352
  style: {
2349
2353
  textAlign: "center",
2350
2354
  padding: "20px 0",
2351
- color: t.accent,
2355
+ color: t2.accent,
2352
2356
  fontSize: "14px",
2353
2357
  fontWeight: 500
2354
2358
  },
@@ -2358,6 +2362,7 @@ function ReportDialog({
2358
2362
  ]
2359
2363
  }
2360
2364
  ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2365
+ step === 1 && headerSlot ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
2361
2366
  step === 1 && sendFeedback2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2362
2367
  "div",
2363
2368
  {
@@ -2378,7 +2383,7 @@ function ReportDialog({
2378
2383
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2379
2384
  "span",
2380
2385
  {
2381
- style: { fontSize: "13px", fontWeight: 600, color: t.text },
2386
+ style: { fontSize: "13px", fontWeight: 600, color: t2.text },
2382
2387
  children: "How are we doing?"
2383
2388
  }
2384
2389
  ),
@@ -2431,9 +2436,9 @@ function ReportDialog({
2431
2436
  marginBottom: "16px"
2432
2437
  },
2433
2438
  children: [
2434
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1, height: "1px", background: t.border } }),
2435
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t.textMuted }, children: "or report something" }),
2436
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1, height: "1px", background: t.border } })
2439
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1, height: "1px", background: t2.border } }),
2440
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t2.textMuted }, children: "or report something" }),
2441
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1, height: "1px", background: t2.border } })
2437
2442
  ]
2438
2443
  }
2439
2444
  ),
@@ -2446,9 +2451,9 @@ function ReportDialog({
2446
2451
  gap: "10px",
2447
2452
  marginBottom: "14px",
2448
2453
  padding: "8px 10px",
2449
- border: `1px solid ${t.inputBorder}`,
2454
+ border: `1px solid ${t2.inputBorder}`,
2450
2455
  borderRadius: "8px",
2451
- background: t.inputBg
2456
+ background: t2.inputBg
2452
2457
  },
2453
2458
  children: [
2454
2459
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -2461,12 +2466,12 @@ function ReportDialog({
2461
2466
  height: "24px",
2462
2467
  objectFit: "cover",
2463
2468
  borderRadius: "4px",
2464
- border: `1px solid ${t.border}`,
2469
+ border: `1px solid ${t2.border}`,
2465
2470
  flexShrink: 0
2466
2471
  }
2467
2472
  }
2468
2473
  ),
2469
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t.textMuted, flex: 1 }, children: "Screenshot attached" }),
2474
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t2.textMuted, flex: 1 }, children: "Screenshot attached" }),
2470
2475
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2471
2476
  "button",
2472
2477
  {
@@ -2476,7 +2481,7 @@ function ReportDialog({
2476
2481
  style: {
2477
2482
  border: "none",
2478
2483
  background: "transparent",
2479
- color: t.textMuted,
2484
+ color: t2.textMuted,
2480
2485
  cursor: "pointer",
2481
2486
  fontSize: "15px",
2482
2487
  lineHeight: 1,
@@ -2514,20 +2519,20 @@ function ReportDialog({
2514
2519
  gap: "9px",
2515
2520
  padding: "18px 10px",
2516
2521
  borderRadius: "8px",
2517
- border: `1px solid ${t.inputBorder}`,
2518
- background: t.inputBg,
2522
+ border: `1px solid ${t2.inputBorder}`,
2523
+ background: t2.inputBg,
2519
2524
  cursor: "pointer",
2520
- color: t.text,
2525
+ color: t2.text,
2521
2526
  fontFamily: "inherit"
2522
2527
  },
2523
2528
  onMouseEnter: (e) => {
2524
- e.currentTarget.style.borderColor = t.accent;
2529
+ e.currentTarget.style.borderColor = t2.accent;
2525
2530
  },
2526
2531
  onMouseLeave: (e) => {
2527
- e.currentTarget.style.borderColor = t.inputBorder;
2532
+ e.currentTarget.style.borderColor = t2.inputBorder;
2528
2533
  },
2529
2534
  children: [
2530
- getTypeIcon(type, t.accent, 22),
2535
+ getTypeIcon(type, t2.accent, 22),
2531
2536
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2532
2537
  "span",
2533
2538
  {
@@ -2559,18 +2564,18 @@ function ReportDialog({
2559
2564
  marginBottom: "10px",
2560
2565
  padding: "4px 10px 4px 8px",
2561
2566
  borderRadius: "999px",
2562
- border: `1px solid ${isRating ? "rgba(245,158,11,0.4)" : t.inputBorder}`,
2563
- background: isRating ? "rgba(245,158,11,0.1)" : t.inputBg,
2564
- color: t.text,
2567
+ border: `1px solid ${isRating ? "rgba(245,158,11,0.4)" : t2.inputBorder}`,
2568
+ background: isRating ? "rgba(245,158,11,0.1)" : t2.inputBg,
2569
+ color: t2.text,
2565
2570
  fontSize: "11px",
2566
2571
  fontWeight: 600,
2567
2572
  fontFamily: "inherit",
2568
2573
  cursor: "pointer"
2569
2574
  },
2570
2575
  children: [
2571
- getTypeIcon(reportType, isRating ? "#f59e0b" : t.accent, 13),
2576
+ getTypeIcon(reportType, isRating ? "#f59e0b" : t2.accent, 13),
2572
2577
  getTypeLabel(reportType),
2573
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: t.textMuted, fontWeight: 400 }, children: "\xB7 change" })
2578
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
2574
2579
  ]
2575
2580
  }
2576
2581
  ),
@@ -2607,7 +2612,7 @@ function ReportDialog({
2607
2612
  {
2608
2613
  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",
2609
2614
  fill: filled ? "#f59e0b" : "transparent",
2610
- stroke: filled ? "#f59e0b" : t.inputBorder,
2615
+ stroke: filled ? "#f59e0b" : t2.inputBorder,
2611
2616
  strokeWidth: "1.5",
2612
2617
  strokeLinejoin: "round"
2613
2618
  }
@@ -2638,24 +2643,24 @@ function ReportDialog({
2638
2643
  minHeight: "100px",
2639
2644
  padding: enhanceText2 ? "28px 12px 36px" : transcribeAudio2 ? "10px 12px 36px" : "10px 12px",
2640
2645
  borderRadius: "8px",
2641
- border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t.accent : t.inputBorder}`,
2646
+ border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t2.accent : t2.inputBorder}`,
2642
2647
  fontSize: "14px",
2643
2648
  fontFamily: "inherit",
2644
2649
  resize: "none",
2645
2650
  outline: "none",
2646
2651
  boxSizing: "border-box",
2647
- color: t.text,
2648
- backgroundColor: t.inputBg,
2652
+ color: t2.text,
2653
+ backgroundColor: t2.inputBg,
2649
2654
  transition: "border-color 0.2s ease"
2650
2655
  },
2651
2656
  onKeyDown: handleSpaceDown,
2652
2657
  onKeyUp: handleSpaceUp,
2653
2658
  onFocus: (e) => {
2654
- e.target.style.borderColor = t.accent;
2659
+ e.target.style.borderColor = t2.accent;
2655
2660
  },
2656
2661
  onBlur: (e) => {
2657
2662
  if (!isListening && !isTranscribing)
2658
- e.target.style.borderColor = t.inputBorder;
2663
+ e.target.style.borderColor = t2.inputBorder;
2659
2664
  },
2660
2665
  autoFocus: true
2661
2666
  }
@@ -2772,13 +2777,13 @@ function ReportDialog({
2772
2777
  display: "inline-flex",
2773
2778
  alignItems: "center",
2774
2779
  gap: "4px",
2775
- background: t.inputBg,
2780
+ background: t2.inputBg,
2776
2781
  border: "none",
2777
2782
  padding: "2px 6px",
2778
2783
  borderRadius: "4px",
2779
2784
  fontFamily: "inherit",
2780
2785
  fontSize: "11px",
2781
- color: t.textMuted,
2786
+ color: t2.textMuted,
2782
2787
  cursor: !description.trim() || isEnhancing ? "default" : "pointer",
2783
2788
  opacity: !description.trim() ? 0.5 : 1,
2784
2789
  zIndex: 1
@@ -2797,7 +2802,7 @@ function ReportDialog({
2797
2802
  "path",
2798
2803
  {
2799
2804
  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",
2800
- stroke: t.textMuted,
2805
+ stroke: t2.textMuted,
2801
2806
  strokeWidth: "1.5",
2802
2807
  strokeLinejoin: "round"
2803
2808
  }
@@ -2826,9 +2831,9 @@ function ReportDialog({
2826
2831
  alignItems: "center",
2827
2832
  justifyContent: "center",
2828
2833
  background: "transparent",
2829
- border: `1.5px solid ${isListening ? "#ef4444" : t.inputBorder}`,
2834
+ border: `1.5px solid ${isListening ? "#ef4444" : t2.inputBorder}`,
2830
2835
  borderRadius: "6px",
2831
- color: isListening ? "#ef4444" : t.textMuted,
2836
+ color: isListening ? "#ef4444" : t2.textMuted,
2832
2837
  cursor: "pointer",
2833
2838
  zIndex: 1,
2834
2839
  padding: 0,
@@ -2898,7 +2903,7 @@ function ReportDialog({
2898
2903
  gap: "5px",
2899
2904
  marginTop: "5px",
2900
2905
  fontSize: "11px",
2901
- color: t.text,
2906
+ color: t2.text,
2902
2907
  opacity: 0.55,
2903
2908
  userSelect: "none"
2904
2909
  },
@@ -2923,7 +2928,7 @@ function ReportDialog({
2923
2928
  padding: "6px 8px",
2924
2929
  borderRadius: "6px",
2925
2930
  background: isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.05)",
2926
- border: `1px solid ${t.accent}40`
2931
+ border: `1px solid ${t2.accent}40`
2927
2932
  },
2928
2933
  children: [
2929
2934
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -2938,7 +2943,7 @@ function ReportDialog({
2938
2943
  "path",
2939
2944
  {
2940
2945
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
2941
- stroke: t.accent,
2946
+ stroke: t2.accent,
2942
2947
  strokeWidth: "1.5",
2943
2948
  strokeLinejoin: "round"
2944
2949
  }
@@ -2950,7 +2955,7 @@ function ReportDialog({
2950
2955
  {
2951
2956
  style: {
2952
2957
  fontSize: "11px",
2953
- color: t.textMuted,
2958
+ color: t2.textMuted,
2954
2959
  flex: 1
2955
2960
  },
2956
2961
  children: "AI enhanced"
@@ -2967,9 +2972,9 @@ function ReportDialog({
2967
2972
  style: {
2968
2973
  padding: "2px 8px",
2969
2974
  borderRadius: "4px",
2970
- border: `1px solid ${t.accent}`,
2971
- background: t.accent,
2972
- color: t.accentText,
2975
+ border: `1px solid ${t2.accent}`,
2976
+ background: t2.accent,
2977
+ color: t2.accentText,
2973
2978
  fontSize: "11px",
2974
2979
  fontWeight: 600,
2975
2980
  cursor: "pointer",
@@ -2990,9 +2995,9 @@ function ReportDialog({
2990
2995
  style: {
2991
2996
  padding: "2px 8px",
2992
2997
  borderRadius: "4px",
2993
- border: `1px solid ${t.inputBorder}`,
2998
+ border: `1px solid ${t2.inputBorder}`,
2994
2999
  background: "transparent",
2995
- color: t.textMuted,
3000
+ color: t2.textMuted,
2996
3001
  fontSize: "11px",
2997
3002
  fontWeight: 600,
2998
3003
  cursor: "pointer",
@@ -3022,7 +3027,7 @@ function ReportDialog({
3022
3027
  {
3023
3028
  style: {
3024
3029
  fontSize: "12px",
3025
- color: t.textMuted,
3030
+ color: t2.textMuted,
3026
3031
  marginBottom: "6px",
3027
3032
  display: "block",
3028
3033
  fontWeight: 500
@@ -3061,7 +3066,7 @@ function ReportDialog({
3061
3066
  width: "100%",
3062
3067
  height: "100%",
3063
3068
  borderRadius: "6px",
3064
- border: `1px solid ${t.border}`,
3069
+ border: `1px solid ${t2.border}`,
3065
3070
  objectFit: "cover",
3066
3071
  objectPosition: "top",
3067
3072
  cursor: "zoom-in",
@@ -3131,8 +3136,8 @@ function ReportDialog({
3131
3136
  height: "24px",
3132
3137
  borderRadius: "50%",
3133
3138
  border: "none",
3134
- background: t.accent,
3135
- color: t.accentText,
3139
+ background: t2.accent,
3140
+ color: t2.accentText,
3136
3141
  padding: 0,
3137
3142
  cursor: "pointer",
3138
3143
  display: "flex",
@@ -3185,7 +3190,7 @@ function ReportDialog({
3185
3190
  gap: "8px",
3186
3191
  padding: "6px 8px",
3187
3192
  borderRadius: "6px",
3188
- border: `1px solid ${t.border}`
3193
+ border: `1px solid ${t2.border}`
3189
3194
  },
3190
3195
  children: [
3191
3196
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -3201,7 +3206,7 @@ function ReportDialog({
3201
3206
  "path",
3202
3207
  {
3203
3208
  d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
3204
- stroke: t.textMuted,
3209
+ stroke: t2.textMuted,
3205
3210
  strokeWidth: "1.5",
3206
3211
  strokeLinecap: "round",
3207
3212
  strokeLinejoin: "round"
@@ -3211,7 +3216,7 @@ function ReportDialog({
3211
3216
  "path",
3212
3217
  {
3213
3218
  d: "M14 2v6h6",
3214
- stroke: t.textMuted,
3219
+ stroke: t2.textMuted,
3215
3220
  strokeWidth: "1.5",
3216
3221
  strokeLinecap: "round",
3217
3222
  strokeLinejoin: "round"
@@ -3225,7 +3230,7 @@ function ReportDialog({
3225
3230
  {
3226
3231
  style: {
3227
3232
  fontSize: "11px",
3228
- color: t.text,
3233
+ color: t2.text,
3229
3234
  flex: 1,
3230
3235
  overflow: "hidden",
3231
3236
  textOverflow: "ellipsis",
@@ -3237,7 +3242,7 @@ function ReportDialog({
3237
3242
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3238
3243
  "span",
3239
3244
  {
3240
- style: { fontSize: "10px", color: t.textMuted },
3245
+ style: { fontSize: "10px", color: t2.textMuted },
3241
3246
  children: [
3242
3247
  (a.size / 1024).toFixed(0),
3243
3248
  "KB"
@@ -3312,7 +3317,7 @@ function ReportDialog({
3312
3317
  },
3313
3318
  onDragLeave: () => setScreenshotDragOver(false),
3314
3319
  style: {
3315
- border: `1.5px dashed ${screenshotDragOver ? t.accent : t.inputBorder}`,
3320
+ border: `1.5px dashed ${screenshotDragOver ? t2.accent : t2.inputBorder}`,
3316
3321
  borderRadius: "8px",
3317
3322
  padding: screenshots.length + attachments.length > 0 ? "8px 12px" : "18px 12px",
3318
3323
  textAlign: "center",
@@ -3327,7 +3332,7 @@ function ReportDialog({
3327
3332
  margin: 0,
3328
3333
  fontSize: "11px",
3329
3334
  fontWeight: 500,
3330
- color: t.textMuted
3335
+ color: t2.textMuted
3331
3336
  },
3332
3337
  children: screenshotDragOver ? "Drop to attach" : "+ Add more \xB7 Drag & drop \xB7 Paste"
3333
3338
  }
@@ -3353,7 +3358,7 @@ function ReportDialog({
3353
3358
  width: "18",
3354
3359
  height: "18",
3355
3360
  rx: "2",
3356
- stroke: t.textMuted,
3361
+ stroke: t2.textMuted,
3357
3362
  strokeWidth: "1.5"
3358
3363
  }
3359
3364
  ),
@@ -3363,7 +3368,7 @@ function ReportDialog({
3363
3368
  cx: "8.5",
3364
3369
  cy: "8.5",
3365
3370
  r: "1.5",
3366
- stroke: t.textMuted,
3371
+ stroke: t2.textMuted,
3367
3372
  strokeWidth: "1.5"
3368
3373
  }
3369
3374
  ),
@@ -3371,7 +3376,7 @@ function ReportDialog({
3371
3376
  "path",
3372
3377
  {
3373
3378
  d: "M21 15l-5-5L5 21",
3374
- stroke: t.textMuted,
3379
+ stroke: t2.textMuted,
3375
3380
  strokeWidth: "1.5",
3376
3381
  strokeLinecap: "round",
3377
3382
  strokeLinejoin: "round"
@@ -3387,7 +3392,7 @@ function ReportDialog({
3387
3392
  margin: 0,
3388
3393
  fontSize: "12px",
3389
3394
  fontWeight: 600,
3390
- color: t.text
3395
+ color: t2.text
3391
3396
  },
3392
3397
  children: screenshotDragOver ? "Drop to attach" : "Add screenshots or files"
3393
3398
  }
@@ -3398,7 +3403,7 @@ function ReportDialog({
3398
3403
  style: {
3399
3404
  margin: "3px 0 0",
3400
3405
  fontSize: "11px",
3401
- color: t.textMuted
3406
+ color: t2.textMuted
3402
3407
  },
3403
3408
  children: "Images, PDF, DOC, XLS \xB7 Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
3404
3409
  }
@@ -3413,7 +3418,7 @@ function ReportDialog({
3413
3418
  {
3414
3419
  style: {
3415
3420
  fontSize: "12px",
3416
- color: t.textMuted,
3421
+ color: t2.textMuted,
3417
3422
  marginBottom: "6px",
3418
3423
  display: "block"
3419
3424
  },
@@ -3429,9 +3434,9 @@ function ReportDialog({
3429
3434
  flex: 1,
3430
3435
  padding: "6px 0",
3431
3436
  borderRadius: "6px",
3432
- border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,
3433
- background: severity === s ? t.accent : "transparent",
3434
- color: severity === s ? t.accentText : t.text,
3437
+ border: `1px solid ${severity === s ? t2.accent : t2.inputBorder}`,
3438
+ background: severity === s ? t2.accent : "transparent",
3439
+ color: severity === s ? t2.accentText : t2.text,
3435
3440
  fontSize: "12px",
3436
3441
  fontWeight: 600,
3437
3442
  cursor: "pointer",
@@ -3467,8 +3472,8 @@ function ReportDialog({
3467
3472
  padding: "10px",
3468
3473
  borderRadius: "8px",
3469
3474
  border: "none",
3470
- backgroundColor: submitDisabled ? t.bgSecondary : t.accent,
3471
- color: submitDisabled ? t.textMuted : t.accentText,
3475
+ backgroundColor: submitDisabled ? t2.bgSecondary : t2.accent,
3476
+ color: submitDisabled ? t2.textMuted : t2.accentText,
3472
3477
  fontSize: "14px",
3473
3478
  fontWeight: 600,
3474
3479
  cursor: submitDisabled ? "not-allowed" : "pointer",
@@ -3487,20 +3492,20 @@ function ReportDialog({
3487
3492
  {
3488
3493
  style: {
3489
3494
  padding: "8px 16px 10px",
3490
- borderTop: `1px solid ${t.border}`,
3495
+ borderTop: `1px solid ${t2.border}`,
3491
3496
  display: "flex",
3492
3497
  alignItems: "center",
3493
3498
  justifyContent: "space-between",
3494
3499
  gap: "12px"
3495
3500
  },
3496
3501
  children: [
3497
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReporterChip, { reporter, t }),
3502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReporterChip, { reporter, t: t2 }),
3498
3503
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3499
3504
  "span",
3500
3505
  {
3501
3506
  style: {
3502
3507
  fontSize: "11px",
3503
- color: t.textMuted,
3508
+ color: t2.textMuted,
3504
3509
  whiteSpace: "nowrap",
3505
3510
  flexShrink: 0
3506
3511
  },
@@ -3628,8 +3633,8 @@ function ReportDialog({
3628
3633
  padding: "8px 14px",
3629
3634
  borderRadius: "999px",
3630
3635
  border: "none",
3631
- background: t.accent,
3632
- color: t.accentText,
3636
+ background: t2.accent,
3637
+ color: t2.accentText,
3633
3638
  fontSize: "13px",
3634
3639
  fontWeight: 700,
3635
3640
  cursor: "pointer",
@@ -3668,7 +3673,7 @@ function ReportDialog({
3668
3673
  "span",
3669
3674
  {
3670
3675
  style: {
3671
- color: t.textMuted,
3676
+ color: t2.textMuted,
3672
3677
  fontSize: "12px"
3673
3678
  },
3674
3679
  children: [
@@ -3854,6 +3859,400 @@ function getTypeIcon(type, color, size = 24) {
3854
3859
  }
3855
3860
  }
3856
3861
 
3862
+ // src/booking-dialog.tsx
3863
+ var import_react3 = require("react");
3864
+ var import_jsx_runtime3 = require("react/jsx-runtime");
3865
+ var t = {
3866
+ bg: "#141414",
3867
+ surface: "#1c1c1c",
3868
+ border: "#2a2a2a",
3869
+ text: "#e5e5e5",
3870
+ muted: "#9aa0a6",
3871
+ accent: "#3b82f6",
3872
+ danger: "#f87171"
3873
+ };
3874
+ function localZone() {
3875
+ try {
3876
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
3877
+ } catch (e) {
3878
+ return "UTC";
3879
+ }
3880
+ }
3881
+ function dayKey(iso) {
3882
+ return new Date(iso).toDateString();
3883
+ }
3884
+ function formatDay(iso) {
3885
+ return new Date(iso).toLocaleDateString(void 0, {
3886
+ weekday: "short",
3887
+ day: "numeric",
3888
+ month: "short"
3889
+ });
3890
+ }
3891
+ function formatTime(iso) {
3892
+ return new Date(iso).toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" });
3893
+ }
3894
+ function BookingDialog({
3895
+ token,
3896
+ baseUrl,
3897
+ open,
3898
+ onClose
3899
+ }) {
3900
+ var _a;
3901
+ const [step, setStep] = (0, import_react3.useState)("slots");
3902
+ const [slots, setSlots] = (0, import_react3.useState)(null);
3903
+ const [heading, setHeading] = (0, import_react3.useState)({
3904
+ title: "Book a demo",
3905
+ description: null
3906
+ });
3907
+ const [whatsappUrl, setWhatsappUrl] = (0, import_react3.useState)(null);
3908
+ const [selected, setSelected] = (0, import_react3.useState)(null);
3909
+ const [name, setName] = (0, import_react3.useState)("");
3910
+ const [email, setEmail] = (0, import_react3.useState)("");
3911
+ const [phone, setPhone] = (0, import_react3.useState)("");
3912
+ const [note, setNote] = (0, import_react3.useState)("");
3913
+ const [code, setCode] = (0, import_react3.useState)("");
3914
+ const [bookingId, setBookingId] = (0, import_react3.useState)(null);
3915
+ const [meetUrl, setMeetUrl] = (0, import_react3.useState)(null);
3916
+ const [busy, setBusy] = (0, import_react3.useState)(false);
3917
+ const [error, setError] = (0, import_react3.useState)(null);
3918
+ const headers = (0, import_react3.useMemo)(
3919
+ () => ({ Authorization: `Bearer ${token}`, "Content-Type": "application/json" }),
3920
+ [token]
3921
+ );
3922
+ const loadSlots = (0, import_react3.useCallback)(async () => {
3923
+ var _a2, _b, _c;
3924
+ setError(null);
3925
+ setSlots(null);
3926
+ try {
3927
+ const from = (/* @__PURE__ */ new Date()).toISOString();
3928
+ const to = new Date(Date.now() + 21 * 864e5).toISOString();
3929
+ const res = await fetch(
3930
+ `${baseUrl}/api/v1/sdk/booking/availability?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`,
3931
+ { headers }
3932
+ );
3933
+ const json = await res.json();
3934
+ if (!json.success) {
3935
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't load available times");
3936
+ setSlots([]);
3937
+ return;
3938
+ }
3939
+ setSlots((_b = json.data.slots) != null ? _b : []);
3940
+ setHeading({ title: json.data.title, description: json.data.description });
3941
+ setWhatsappUrl((_c = json.data.whatsappUrl) != null ? _c : null);
3942
+ } catch (e) {
3943
+ setError("Couldn't reach the booking service");
3944
+ setSlots([]);
3945
+ }
3946
+ }, [baseUrl, headers]);
3947
+ (0, import_react3.useEffect)(() => {
3948
+ if (!open) return;
3949
+ setStep("slots");
3950
+ setSelected(null);
3951
+ setCode("");
3952
+ setBookingId(null);
3953
+ setError(null);
3954
+ void loadSlots();
3955
+ }, [open, loadSlots]);
3956
+ (0, import_react3.useEffect)(() => {
3957
+ if (!open) return;
3958
+ const onKey = (e) => {
3959
+ if (e.key === "Escape") onClose();
3960
+ };
3961
+ document.addEventListener("keydown", onKey, true);
3962
+ return () => document.removeEventListener("keydown", onKey, true);
3963
+ }, [open, onClose]);
3964
+ if (!open) return null;
3965
+ const byDay = /* @__PURE__ */ new Map();
3966
+ for (const slot of slots != null ? slots : []) {
3967
+ const key = dayKey(slot.startsAt);
3968
+ byDay.set(key, [...(_a = byDay.get(key)) != null ? _a : [], slot]);
3969
+ }
3970
+ async function startBooking() {
3971
+ var _a2;
3972
+ if (!selected) return;
3973
+ setBusy(true);
3974
+ setError(null);
3975
+ try {
3976
+ const res = await fetch(`${baseUrl}/api/v1/sdk/booking`, {
3977
+ method: "POST",
3978
+ headers,
3979
+ body: JSON.stringify({
3980
+ name,
3981
+ email,
3982
+ phone,
3983
+ note,
3984
+ startsAt: selected.startsAt,
3985
+ timezone: localZone()
3986
+ })
3987
+ });
3988
+ const json = await res.json();
3989
+ if (!json.success) {
3990
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't hold that slot");
3991
+ return;
3992
+ }
3993
+ setBookingId(json.data.bookingId);
3994
+ setStep("code");
3995
+ } catch (e) {
3996
+ setError("Couldn't reach the booking service");
3997
+ } finally {
3998
+ setBusy(false);
3999
+ }
4000
+ }
4001
+ async function confirmBooking() {
4002
+ var _a2;
4003
+ if (!bookingId) return;
4004
+ setBusy(true);
4005
+ setError(null);
4006
+ try {
4007
+ const res = await fetch(`${baseUrl}/api/v1/sdk/booking/verify`, {
4008
+ method: "POST",
4009
+ headers,
4010
+ body: JSON.stringify({ bookingId, code })
4011
+ });
4012
+ const json = await res.json();
4013
+ if (!json.success) {
4014
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't confirm that code");
4015
+ return;
4016
+ }
4017
+ setMeetUrl(json.data.meetUrl);
4018
+ setStep("done");
4019
+ } catch (e) {
4020
+ setError("Couldn't reach the booking service");
4021
+ } finally {
4022
+ setBusy(false);
4023
+ }
4024
+ }
4025
+ const canSubmitDetails = name.trim() && email.includes("@") && phone.replace(/\D/g, "").length >= 8;
4026
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4027
+ "div",
4028
+ {
4029
+ onClick: (e) => {
4030
+ if (e.target === e.currentTarget) onClose();
4031
+ },
4032
+ style: {
4033
+ position: "fixed",
4034
+ inset: 0,
4035
+ zIndex: 2147483e3,
4036
+ background: "rgba(0,0,0,.6)",
4037
+ display: "flex",
4038
+ alignItems: "center",
4039
+ justifyContent: "center",
4040
+ padding: 16,
4041
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
4042
+ },
4043
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
4044
+ "div",
4045
+ {
4046
+ role: "dialog",
4047
+ "aria-modal": "true",
4048
+ "aria-label": heading.title,
4049
+ style: {
4050
+ width: "min(440px, 100%)",
4051
+ maxHeight: "min(660px, 90vh)",
4052
+ display: "flex",
4053
+ flexDirection: "column",
4054
+ background: t.bg,
4055
+ color: t.text,
4056
+ borderRadius: 16,
4057
+ boxShadow: "0 20px 60px rgba(0,0,0,.55)",
4058
+ overflow: "hidden"
4059
+ },
4060
+ children: [
4061
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
4062
+ "div",
4063
+ {
4064
+ style: {
4065
+ padding: "16px 18px",
4066
+ borderBottom: `1px solid ${t.border}`,
4067
+ display: "flex",
4068
+ alignItems: "flex-start",
4069
+ justifyContent: "space-between",
4070
+ gap: 12
4071
+ },
4072
+ children: [
4073
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
4074
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: 15, fontWeight: 600 }, children: heading.title }),
4075
+ heading.description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: 12, color: t.muted, marginTop: 2 }, children: heading.description })
4076
+ ] }),
4077
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4078
+ "button",
4079
+ {
4080
+ onClick: onClose,
4081
+ "aria-label": "Close",
4082
+ style: { border: 0, background: "transparent", color: t.muted, fontSize: 20, cursor: "pointer", lineHeight: 1 },
4083
+ children: "\xD7"
4084
+ }
4085
+ )
4086
+ ]
4087
+ }
4088
+ ),
4089
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: 18, overflowY: "auto", flex: "1 1 auto" }, children: [
4090
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { color: t.danger, fontSize: 12, marginBottom: 12, lineHeight: 1.5 }, children: error }),
4091
+ step === "slots" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
4092
+ whatsappUrl && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
4093
+ "a",
4094
+ {
4095
+ href: whatsappUrl,
4096
+ target: "_blank",
4097
+ rel: "noreferrer",
4098
+ style: {
4099
+ display: "block",
4100
+ marginBottom: 16,
4101
+ padding: "10px 14px",
4102
+ borderRadius: 10,
4103
+ border: `1px solid ${t.border}`,
4104
+ background: t.surface,
4105
+ color: t.text,
4106
+ fontSize: 13,
4107
+ textDecoration: "none"
4108
+ },
4109
+ children: [
4110
+ "\u{1F4AC} Rather book on WhatsApp?",
4111
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { display: "block", fontSize: 11, color: t.muted, marginTop: 2 }, children: "We'll ask the same questions in chat." })
4112
+ ]
4113
+ }
4114
+ ),
4115
+ slots === null && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { color: t.muted, fontSize: 13 }, children: "Finding times\u2026" }),
4116
+ (slots == null ? void 0 : slots.length) === 0 && !error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { color: t.muted, fontSize: 13 }, children: "No times available right now." }),
4117
+ [...byDay.entries()].map(([day, daySlots]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: 18 }, children: [
4118
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: 11, color: t.muted, marginBottom: 8, textTransform: "uppercase", letterSpacing: ".6px" }, children: formatDay(daySlots[0].startsAt) }),
4119
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4120
+ "button",
4121
+ {
4122
+ onClick: () => {
4123
+ setSelected(slot);
4124
+ setStep("details");
4125
+ },
4126
+ style: {
4127
+ padding: "8px 14px",
4128
+ borderRadius: 999,
4129
+ border: `1px solid ${t.border}`,
4130
+ background: t.surface,
4131
+ color: t.text,
4132
+ fontSize: 13,
4133
+ cursor: "pointer"
4134
+ },
4135
+ children: formatTime(slot.startsAt)
4136
+ },
4137
+ slot.startsAt
4138
+ )) })
4139
+ ] }, day))
4140
+ ] }),
4141
+ step === "details" && selected && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4142
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: 13, color: t.muted }, children: [
4143
+ formatDay(selected.startsAt),
4144
+ " \xB7 ",
4145
+ formatTime(selected.startsAt),
4146
+ " \xB7 ",
4147
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4148
+ "button",
4149
+ {
4150
+ onClick: () => setStep("slots"),
4151
+ style: { border: 0, background: "transparent", color: t.accent, cursor: "pointer", fontSize: 13, padding: 0 },
4152
+ children: "change"
4153
+ }
4154
+ )
4155
+ ] }),
4156
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "Your name", value: name, onChange: setName }),
4157
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "Email", value: email, onChange: setEmail, type: "email" }),
4158
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4159
+ Field,
4160
+ {
4161
+ label: "Mobile number",
4162
+ value: phone,
4163
+ onChange: setPhone,
4164
+ type: "tel",
4165
+ hint: "We send a code here to confirm, then a reminder before the call."
4166
+ }
4167
+ ),
4168
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "Anything we should know? (optional)", value: note, onChange: setNote }),
4169
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4170
+ "button",
4171
+ {
4172
+ onClick: startBooking,
4173
+ disabled: !canSubmitDetails || busy,
4174
+ style: primaryStyle(!canSubmitDetails || busy),
4175
+ children: busy ? "Sending code\u2026" : "Send verification code"
4176
+ }
4177
+ )
4178
+ ] }),
4179
+ step === "code" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4180
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("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." }),
4181
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "Code", value: code, onChange: setCode }),
4182
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4183
+ "button",
4184
+ {
4185
+ onClick: confirmBooking,
4186
+ disabled: code.trim().length < 4 || busy,
4187
+ style: primaryStyle(code.trim().length < 4 || busy),
4188
+ children: busy ? "Confirming\u2026" : "Confirm booking"
4189
+ }
4190
+ )
4191
+ ] }),
4192
+ step === "done" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4193
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: 15, fontWeight: 600 }, children: "You're booked." }),
4194
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.6 }, children: [
4195
+ selected && `${formatDay(selected.startsAt)} at ${formatTime(selected.startsAt)}. `,
4196
+ "A calendar invite is on its way to ",
4197
+ email,
4198
+ ", and we'll send a WhatsApp reminder before the call."
4199
+ ] }),
4200
+ meetUrl && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: meetUrl, target: "_blank", rel: "noreferrer", style: { ...primaryStyle(false), textAlign: "center", textDecoration: "none" }, children: "Open the meeting link" })
4201
+ ] })
4202
+ ] })
4203
+ ]
4204
+ }
4205
+ )
4206
+ }
4207
+ );
4208
+ }
4209
+ function primaryStyle(disabled) {
4210
+ return {
4211
+ marginTop: 4,
4212
+ padding: "10px 16px",
4213
+ borderRadius: 999,
4214
+ border: 0,
4215
+ background: disabled ? "#2a2a2a" : t.accent,
4216
+ color: disabled ? "#6b7280" : "#fff",
4217
+ fontSize: 14,
4218
+ fontWeight: 500,
4219
+ cursor: disabled ? "default" : "pointer"
4220
+ };
4221
+ }
4222
+ function Field({
4223
+ label,
4224
+ value,
4225
+ onChange,
4226
+ type = "text",
4227
+ hint
4228
+ }) {
4229
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: { display: "block", fontSize: 11, color: t.muted }, children: [
4230
+ label,
4231
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4232
+ "input",
4233
+ {
4234
+ type,
4235
+ value,
4236
+ onChange: (e) => onChange(e.target.value),
4237
+ style: {
4238
+ display: "block",
4239
+ width: "100%",
4240
+ boxSizing: "border-box",
4241
+ marginTop: 4,
4242
+ padding: "9px 12px",
4243
+ background: t.surface,
4244
+ color: t.text,
4245
+ border: `1px solid ${t.border}`,
4246
+ borderRadius: 8,
4247
+ fontSize: 13,
4248
+ outline: "none"
4249
+ }
4250
+ }
4251
+ ),
4252
+ hint && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginTop: 4, fontSize: 10, color: t.muted }, children: hint })
4253
+ ] });
4254
+ }
4255
+
3857
4256
  // src/rejection.ts
3858
4257
  var DETAILS_MAX_LENGTH = 1e3;
3859
4258
  var MESSAGE_MAX_LENGTH = 200;
@@ -3909,6 +4308,36 @@ function describeShape(reason) {
3909
4308
  return "";
3910
4309
  }
3911
4310
  }
4311
+ var EVENT_URL_MAX_LENGTH = 120;
4312
+ function isEventLike(reason) {
4313
+ try {
4314
+ if (typeof Event !== "undefined" && reason instanceof Event) return true;
4315
+ const source = reason;
4316
+ return typeof (source == null ? void 0 : source.type) === "string" && typeof (source == null ? void 0 : source.isTrusted) === "boolean";
4317
+ } catch (e) {
4318
+ return false;
4319
+ }
4320
+ }
4321
+ function describeEvent(reason) {
4322
+ var _a, _b, _c, _d, _e;
4323
+ const parts = [];
4324
+ try {
4325
+ const source = reason;
4326
+ const name = ((_a = source.constructor) == null ? void 0 : _a.name) || "Event";
4327
+ parts.push(`${name} ("${String((_b = source.type) != null ? _b : "")}")`);
4328
+ } catch (e) {
4329
+ parts.push("Event");
4330
+ }
4331
+ try {
4332
+ const target = reason.target;
4333
+ const tag = (_c = target == null ? void 0 : target.tagName) == null ? void 0 : _c.toLowerCase();
4334
+ if (tag) parts.push(`from <${tag}>`);
4335
+ 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);
4336
+ if (url) parts.push(`\u2014 ${url.split(/[?#]/)[0].slice(0, EVENT_URL_MAX_LENGTH)}`);
4337
+ } catch (e) {
4338
+ }
4339
+ return parts.join(" ").slice(0, MESSAGE_MAX_LENGTH);
4340
+ }
3912
4341
  function describeRejection(reason) {
3913
4342
  var _a, _b, _c, _d, _e, _f, _g, _h;
3914
4343
  try {
@@ -3933,7 +4362,7 @@ function describeRejection(reason) {
3933
4362
  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 : "";
3934
4363
  const details = serialize(reason);
3935
4364
  return {
3936
- message: message || describeShape(reason),
4365
+ message: message || (isEventLike(reason) ? describeEvent(reason) : describeShape(reason)),
3937
4366
  stack,
3938
4367
  details
3939
4368
  };
@@ -3961,11 +4390,11 @@ function matchesShortcut(e) {
3961
4390
  }
3962
4391
 
3963
4392
  // src/provider.tsx
3964
- var import_jsx_runtime3 = require("react/jsx-runtime");
4393
+ var import_jsx_runtime4 = require("react/jsx-runtime");
3965
4394
  var DEFAULT_BASE_URL2 = "https://glitchgrab.dev";
3966
- var GlitchgrabContext = (0, import_react3.createContext)(null);
4395
+ var GlitchgrabContext = (0, import_react4.createContext)(null);
3967
4396
  function useGlitchgrab() {
3968
- const ctx = (0, import_react3.useContext)(GlitchgrabContext);
4397
+ const ctx = (0, import_react4.useContext)(GlitchgrabContext);
3969
4398
  if (!ctx) {
3970
4399
  throw new Error("useGlitchgrab must be used within a GlitchgrabProvider");
3971
4400
  }
@@ -3988,7 +4417,7 @@ function GlitchgrabProviderInner({
3988
4417
  context: appContext2,
3989
4418
  responseBodyOrigins: responseBodyOrigins2
3990
4419
  }) {
3991
- const visitedPagesRef = (0, import_react3.useRef)([]);
4420
+ const visitedPagesRef = (0, import_react4.useRef)([]);
3992
4421
  setRelease(release2);
3993
4422
  if (appContext2) setContexts(appContext2);
3994
4423
  registerCaptureConfig({
@@ -4000,12 +4429,12 @@ function GlitchgrabProviderInner({
4000
4429
  onError,
4001
4430
  onReportSent
4002
4431
  });
4003
- (0, import_react3.useEffect)(() => {
4432
+ (0, import_react4.useEffect)(() => {
4004
4433
  if (enableBreadcrumbs) {
4005
4434
  initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
4006
4435
  }
4007
4436
  }, [enableBreadcrumbs, maxBreadcrumbs2, responseBodyOrigins2 == null ? void 0 : responseBodyOrigins2.join(",")]);
4008
- (0, import_react3.useEffect)(() => {
4437
+ (0, import_react4.useEffect)(() => {
4009
4438
  try {
4010
4439
  if (typeof window === "undefined") return;
4011
4440
  const trackPage = () => {
@@ -4042,7 +4471,7 @@ function GlitchgrabProviderInner({
4042
4471
  } catch (e) {
4043
4472
  }
4044
4473
  }, []);
4045
- (0, import_react3.useEffect)(() => {
4474
+ (0, import_react4.useEffect)(() => {
4046
4475
  try {
4047
4476
  if (typeof window === "undefined") return;
4048
4477
  if (process.env.NODE_ENV === "development") return;
@@ -4169,7 +4598,7 @@ function GlitchgrabProviderInner({
4169
4598
  } catch (e) {
4170
4599
  }
4171
4600
  }, [token, baseUrl, onError, onReportSent, session, ignoreErrors]);
4172
- const report = (0, import_react3.useCallback)(
4601
+ const report = (0, import_react4.useCallback)(
4173
4602
  async (type, description, metadata) => {
4174
4603
  var _a;
4175
4604
  try {
@@ -4203,11 +4632,11 @@ function GlitchgrabProviderInner({
4203
4632
  },
4204
4633
  [token, baseUrl, onReportSent, session]
4205
4634
  );
4206
- const reportBug = (0, import_react3.useCallback)(
4635
+ const reportBug = (0, import_react4.useCallback)(
4207
4636
  (description, metadata) => report("BUG", description, metadata),
4208
4637
  [report]
4209
4638
  );
4210
- const feedback = (0, import_react3.useCallback)(
4639
+ const feedback = (0, import_react4.useCallback)(
4211
4640
  async (rating, message, metadata) => {
4212
4641
  try {
4213
4642
  const context = captureContext(visitedPagesRef.current);
@@ -4235,32 +4664,32 @@ function GlitchgrabProviderInner({
4235
4664
  },
4236
4665
  [token, baseUrl, session]
4237
4666
  );
4238
- const openFeedbackDialog = (0, import_react3.useCallback)(() => {
4667
+ const openFeedbackDialog = (0, import_react4.useCallback)(() => {
4239
4668
  if (typeof window !== "undefined") {
4240
4669
  window.dispatchEvent(
4241
4670
  new CustomEvent("glitchgrab:open-report", { detail: { type: "RATING" } })
4242
4671
  );
4243
4672
  }
4244
4673
  }, []);
4245
- const captureError2 = (0, import_react3.useCallback)(
4674
+ const captureError2 = (0, import_react4.useCallback)(
4246
4675
  (error, options) => {
4247
4676
  captureError(error, options);
4248
4677
  },
4249
4678
  []
4250
4679
  );
4251
- const setContext2 = (0, import_react3.useCallback)((key, value) => {
4680
+ const setContext2 = (0, import_react4.useCallback)((key, value) => {
4252
4681
  setContext(key, value);
4253
4682
  }, []);
4254
- const setContexts2 = (0, import_react3.useCallback)((values) => {
4683
+ const setContexts2 = (0, import_react4.useCallback)((values) => {
4255
4684
  setContexts(values);
4256
4685
  }, []);
4257
- const addBreadcrumb2 = (0, import_react3.useCallback)(
4686
+ const addBreadcrumb2 = (0, import_react4.useCallback)(
4258
4687
  (message, data) => {
4259
4688
  addBreadcrumb("custom", message, data);
4260
4689
  },
4261
4690
  []
4262
4691
  );
4263
- const enhance = (0, import_react3.useCallback)(
4692
+ const enhance = (0, import_react4.useCallback)(
4264
4693
  async (text, screenshot) => {
4265
4694
  try {
4266
4695
  const ctx = captureContext(visitedPagesRef.current);
@@ -4276,7 +4705,7 @@ function GlitchgrabProviderInner({
4276
4705
  },
4277
4706
  [token, baseUrl]
4278
4707
  );
4279
- const transcribe = (0, import_react3.useCallback)(
4708
+ const transcribe = (0, import_react4.useCallback)(
4280
4709
  async (blob) => {
4281
4710
  try {
4282
4711
  return await transcribeAudio(blob, token, baseUrl);
@@ -4286,12 +4715,37 @@ function GlitchgrabProviderInner({
4286
4715
  },
4287
4716
  [token, baseUrl]
4288
4717
  );
4289
- const openReportDialog = (0, import_react3.useCallback)((options) => {
4718
+ const openReportDialog = (0, import_react4.useCallback)((options) => {
4290
4719
  if (typeof window !== "undefined") {
4291
4720
  window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
4292
4721
  }
4293
4722
  }, []);
4294
- (0, import_react3.useEffect)(() => {
4723
+ (0, import_react4.useEffect)(() => {
4724
+ try {
4725
+ if (typeof document === "undefined") return;
4726
+ document.documentElement.setAttribute("data-glitchgrab-sdk", "1");
4727
+ return () => document.documentElement.removeAttribute("data-glitchgrab-sdk");
4728
+ } catch (e) {
4729
+ }
4730
+ }, []);
4731
+ const [projectName, setProjectName] = (0, import_react4.useState)(null);
4732
+ const [bookingOpen, setBookingOpen] = (0, import_react4.useState)(false);
4733
+ const openBookingDialog = (0, import_react4.useCallback)(() => setBookingOpen(true), []);
4734
+ (0, import_react4.useEffect)(() => {
4735
+ let cancelled = false;
4736
+ fetch(`${baseUrl}/api/v1/sdk/project`, {
4737
+ headers: { Authorization: `Bearer ${token}` }
4738
+ }).then((r) => r.ok ? r.json() : null).then((json) => {
4739
+ var _a;
4740
+ if (cancelled || !(json == null ? void 0 : json.success) || !((_a = json.data) == null ? void 0 : _a.name)) return;
4741
+ setProjectName(json.data.name);
4742
+ }).catch(() => {
4743
+ });
4744
+ return () => {
4745
+ cancelled = true;
4746
+ };
4747
+ }, [baseUrl, token]);
4748
+ (0, import_react4.useEffect)(() => {
4295
4749
  try {
4296
4750
  if (typeof window === "undefined") return;
4297
4751
  const handleKeyDown = (e) => {
@@ -4305,7 +4759,7 @@ function GlitchgrabProviderInner({
4305
4759
  } catch (e) {
4306
4760
  }
4307
4761
  }, [openReportDialog]);
4308
- const reporter = (0, import_react3.useMemo)(() => {
4762
+ const reporter = (0, import_react4.useMemo)(() => {
4309
4763
  var _a;
4310
4764
  if (!session) return null;
4311
4765
  const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
@@ -4315,11 +4769,11 @@ function GlitchgrabProviderInner({
4315
4769
  avatarUrl: typeof avatar === "string" ? avatar : null
4316
4770
  };
4317
4771
  }, [session]);
4318
- const [shortcutLabel, setShortcutLabel] = (0, import_react3.useState)(GLITCHGRAB_SHORTCUT2);
4319
- (0, import_react3.useEffect)(() => {
4772
+ const [shortcutLabel, setShortcutLabel] = (0, import_react4.useState)(GLITCHGRAB_SHORTCUT2);
4773
+ (0, import_react4.useEffect)(() => {
4320
4774
  setShortcutLabel(getShortcutLabel2());
4321
4775
  }, []);
4322
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
4776
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4323
4777
  GlitchgrabContext.Provider,
4324
4778
  {
4325
4779
  value: {
@@ -4334,11 +4788,12 @@ function GlitchgrabProviderInner({
4334
4788
  openFeedbackDialog,
4335
4789
  addBreadcrumb: addBreadcrumb2,
4336
4790
  openReportDialog,
4791
+ openBookingDialog,
4337
4792
  enhanceText: enhance,
4338
4793
  shortcutLabel
4339
4794
  },
4340
4795
  children: [
4341
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4796
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4342
4797
  GlitchgrabErrorBoundary,
4343
4798
  {
4344
4799
  token,
@@ -4350,27 +4805,51 @@ function GlitchgrabProviderInner({
4350
4805
  children
4351
4806
  }
4352
4807
  ),
4353
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ReportDialog, { report, sendFeedback: feedback, enhanceText: enhance, transcribeAudio: transcribe, types, showSeverity, reporter })
4808
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4809
+ BookingDialog,
4810
+ {
4811
+ token,
4812
+ baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
4813
+ open: bookingOpen,
4814
+ onClose: () => setBookingOpen(false)
4815
+ }
4816
+ ),
4817
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4818
+ ReportDialog,
4819
+ {
4820
+ report,
4821
+ sendFeedback: feedback,
4822
+ enhanceText: enhance,
4823
+ transcribeAudio: transcribe,
4824
+ types,
4825
+ showSeverity,
4826
+ reporter,
4827
+ headerSlot: projectName ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
4828
+ "Reporting to ",
4829
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { style: { color: "#e5e5e5" }, children: projectName })
4830
+ ] }) : null
4831
+ }
4832
+ )
4354
4833
  ]
4355
4834
  }
4356
4835
  );
4357
4836
  }
4358
4837
  function GlitchgrabProvider(props) {
4359
- if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: props.children });
4838
+ if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: props.children });
4360
4839
  const resolvedProps = {
4361
4840
  ...props,
4362
4841
  baseUrl: props.baseUrl || DEFAULT_BASE_URL2
4363
4842
  };
4364
4843
  try {
4365
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
4844
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
4366
4845
  } catch (e) {
4367
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: props.children });
4846
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: props.children });
4368
4847
  }
4369
4848
  }
4370
4849
 
4371
4850
  // src/report-button.tsx
4372
- var import_react4 = require("react");
4373
- var import_jsx_runtime4 = require("react/jsx-runtime");
4851
+ var import_react5 = require("react");
4852
+ var import_jsx_runtime5 = require("react/jsx-runtime");
4374
4853
  function useGlitchgrabSafe() {
4375
4854
  try {
4376
4855
  return useGlitchgrab();
@@ -4385,7 +4864,7 @@ function ReportButton({
4385
4864
  children
4386
4865
  }) {
4387
4866
  var _a, _b;
4388
- const [capturing, setCapturing] = (0, import_react4.useState)(false);
4867
+ const [capturing, setCapturing] = (0, import_react5.useState)(false);
4389
4868
  const glitchgrab = useGlitchgrabSafe();
4390
4869
  if (!glitchgrab) return null;
4391
4870
  const handleClick = async () => {
@@ -4394,7 +4873,7 @@ function ReportButton({
4394
4873
  setCapturing(false);
4395
4874
  };
4396
4875
  if (children) {
4397
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: children({ onClick: handleClick, capturing }) });
4876
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: children({ onClick: handleClick, capturing }) });
4398
4877
  }
4399
4878
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4400
4879
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4402,7 +4881,7 @@ function ReportButton({
4402
4881
  ...isLeft ? { left: "16px" } : { right: "16px" },
4403
4882
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4404
4883
  };
4405
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4884
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4406
4885
  "button",
4407
4886
  {
4408
4887
  type: "button",
@@ -4437,7 +4916,7 @@ function ReportButton({
4437
4916
  },
4438
4917
  "aria-label": label,
4439
4918
  children: [
4440
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4919
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4441
4920
  "svg",
4442
4921
  {
4443
4922
  width: "16",
@@ -4445,7 +4924,7 @@ function ReportButton({
4445
4924
  viewBox: "0 0 16 16",
4446
4925
  fill: "none",
4447
4926
  style: { flexShrink: 0 },
4448
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4927
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4449
4928
  "path",
4450
4929
  {
4451
4930
  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",
@@ -4460,8 +4939,38 @@ function ReportButton({
4460
4939
  );
4461
4940
  }
4462
4941
 
4942
+ // src/book-demo-button.tsx
4943
+ var import_jsx_runtime6 = require("react/jsx-runtime");
4944
+ function BookDemoButton({
4945
+ label = "Book a demo",
4946
+ className,
4947
+ children
4948
+ }) {
4949
+ const { openBookingDialog } = useGlitchgrab();
4950
+ if (children) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: children({ onClick: openBookingDialog }) });
4951
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4952
+ "button",
4953
+ {
4954
+ type: "button",
4955
+ onClick: openBookingDialog,
4956
+ className,
4957
+ style: className ? void 0 : {
4958
+ padding: "10px 18px",
4959
+ borderRadius: 999,
4960
+ border: 0,
4961
+ background: "#3b82f6",
4962
+ color: "#fff",
4963
+ fontSize: 14,
4964
+ fontWeight: 500,
4965
+ cursor: "pointer"
4966
+ },
4967
+ children: label
4968
+ }
4969
+ );
4970
+ }
4971
+
4463
4972
  // src/feedback-button.tsx
4464
- var import_jsx_runtime5 = require("react/jsx-runtime");
4973
+ var import_jsx_runtime7 = require("react/jsx-runtime");
4465
4974
  function useGlitchgrabSafe2() {
4466
4975
  try {
4467
4976
  return useGlitchgrab();
@@ -4480,7 +4989,7 @@ function FeedbackButton({
4480
4989
  if (!glitchgrab) return null;
4481
4990
  const handleClick = () => glitchgrab.openFeedbackDialog();
4482
4991
  if (children) {
4483
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: children({ onClick: handleClick }) });
4992
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: children({ onClick: handleClick }) });
4484
4993
  }
4485
4994
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4486
4995
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4488,7 +4997,7 @@ function FeedbackButton({
4488
4997
  ...isLeft ? { left: "16px" } : { right: "16px" },
4489
4998
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4490
4999
  };
4491
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5000
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4492
5001
  "button",
4493
5002
  {
4494
5003
  type: "button",
@@ -4521,7 +5030,7 @@ function FeedbackButton({
4521
5030
  },
4522
5031
  "aria-label": label,
4523
5032
  children: [
4524
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5033
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4525
5034
  "svg",
4526
5035
  {
4527
5036
  width: "16",
@@ -4530,7 +5039,7 @@ function FeedbackButton({
4530
5039
  fill: "none",
4531
5040
  style: { flexShrink: 0 },
4532
5041
  "aria-hidden": "true",
4533
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5042
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4534
5043
  "path",
4535
5044
  {
4536
5045
  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",
@@ -4546,18 +5055,18 @@ function FeedbackButton({
4546
5055
  }
4547
5056
 
4548
5057
  // src/use-reports.ts
4549
- var import_react5 = require("react");
5058
+ var import_react6 = require("react");
4550
5059
  var BASE_URL = "https://glitchgrab.dev";
4551
5060
  function useGlitchgrabReports({
4552
5061
  token,
4553
5062
  userId,
4554
5063
  limit = 100
4555
5064
  }) {
4556
- const [reports, setReports] = (0, import_react5.useState)([]);
4557
- const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
4558
- const [isFetching, setIsFetching] = (0, import_react5.useState)(false);
4559
- const [error, setError] = (0, import_react5.useState)(null);
4560
- const fetchReports = (0, import_react5.useCallback)(async () => {
5065
+ const [reports, setReports] = (0, import_react6.useState)([]);
5066
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
5067
+ const [isFetching, setIsFetching] = (0, import_react6.useState)(false);
5068
+ const [error, setError] = (0, import_react6.useState)(null);
5069
+ const fetchReports = (0, import_react6.useCallback)(async () => {
4561
5070
  var _a, _b;
4562
5071
  if (!token || !userId) {
4563
5072
  setIsLoading(false);
@@ -4583,7 +5092,7 @@ function useGlitchgrabReports({
4583
5092
  setIsFetching(false);
4584
5093
  }
4585
5094
  }, [token, userId, limit]);
4586
- (0, import_react5.useEffect)(() => {
5095
+ (0, import_react6.useEffect)(() => {
4587
5096
  fetchReports();
4588
5097
  }, [fetchReports]);
4589
5098
  return { reports, isLoading, isFetching, error, refetch: fetchReports };
@@ -4620,9 +5129,9 @@ function useGlitchgrabActions({
4620
5129
  onSuccess,
4621
5130
  onError
4622
5131
  }) {
4623
- const [isPending, setIsPending] = (0, import_react5.useState)(false);
4624
- const [error, setError] = (0, import_react5.useState)(null);
4625
- const run = (0, import_react5.useCallback)(
5132
+ const [isPending, setIsPending] = (0, import_react6.useState)(false);
5133
+ const [error, setError] = (0, import_react6.useState)(null);
5134
+ const run = (0, import_react6.useCallback)(
4626
5135
  async (reportId, body) => {
4627
5136
  setIsPending(true);
4628
5137
  setError(null);
@@ -4652,7 +5161,7 @@ function useGlitchgrabActions({
4652
5161
  }
4653
5162
 
4654
5163
  // src/use-feedback.ts
4655
- var import_react6 = require("react");
5164
+ var import_react7 = require("react");
4656
5165
  var DEFAULT_BASE_URL3 = "https://glitchgrab.dev";
4657
5166
  function buildUrl({
4658
5167
  approvedOnly,
@@ -4678,11 +5187,11 @@ async function fetchGlitchgrabFeedback(query) {
4678
5187
  }
4679
5188
  function useGlitchgrabFeedback(query) {
4680
5189
  const { token, approvedOnly, userId, minRating, limit, baseUrl } = query;
4681
- const [feedback, setFeedback] = (0, import_react6.useState)([]);
4682
- const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
4683
- const [isFetching, setIsFetching] = (0, import_react6.useState)(false);
4684
- const [error, setError] = (0, import_react6.useState)(null);
4685
- const load = (0, import_react6.useCallback)(async () => {
5190
+ const [feedback, setFeedback] = (0, import_react7.useState)([]);
5191
+ const [isLoading, setIsLoading] = (0, import_react7.useState)(true);
5192
+ const [isFetching, setIsFetching] = (0, import_react7.useState)(false);
5193
+ const [error, setError] = (0, import_react7.useState)(null);
5194
+ const load = (0, import_react7.useCallback)(async () => {
4686
5195
  if (!token) {
4687
5196
  setIsLoading(false);
4688
5197
  return;
@@ -4706,13 +5215,14 @@ function useGlitchgrabFeedback(query) {
4706
5215
  setIsFetching(false);
4707
5216
  }
4708
5217
  }, [token, approvedOnly, userId, minRating, limit, baseUrl]);
4709
- (0, import_react6.useEffect)(() => {
5218
+ (0, import_react7.useEffect)(() => {
4710
5219
  load();
4711
5220
  }, [load]);
4712
5221
  return { feedback, isLoading, isFetching, error, refetch: load };
4713
5222
  }
4714
5223
  // Annotate the CommonJS export names for ESM import in node:
4715
5224
  0 && (module.exports = {
5225
+ BookDemoButton,
4716
5226
  FeedbackButton,
4717
5227
  GLITCHGRAB_SHORTCUT,
4718
5228
  GLITCHGRAB_SHORTCUT_MAC,