@fogg/bug-reporter 1.0.1 → 1.0.3

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.cjs CHANGED
@@ -1,8 +1,35 @@
1
1
  'use strict';
2
2
 
3
- var chunk6TCI6T2U_cjs = require('./chunk-6TCI6T2U.cjs');
4
- var react = require('react');
3
+ var React = require('react');
5
4
  var reactDom = require('react-dom');
5
+ var html2canvas = require('html2canvas');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
+ var html2canvas__default = /*#__PURE__*/_interopDefault(html2canvas);
29
+
30
+ var __defProp = Object.defineProperty;
31
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
32
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
33
 
7
34
  // src/diagnostics/ua.ts
8
35
  function detectBrowserAndOS(userAgent) {
@@ -71,14 +98,14 @@ function collectDiagnostics(config, options) {
71
98
  var ConsoleBuffer = class {
72
99
  constructor(maxEntries) {
73
100
  this.maxEntries = maxEntries;
74
- chunk6TCI6T2U_cjs.__publicField(this, "entries", []);
75
- chunk6TCI6T2U_cjs.__publicField(this, "originals", /* @__PURE__ */ new Map());
76
- chunk6TCI6T2U_cjs.__publicField(this, "installed", false);
77
- chunk6TCI6T2U_cjs.__publicField(this, "onWindowError", (event) => {
101
+ __publicField(this, "entries", []);
102
+ __publicField(this, "originals", /* @__PURE__ */ new Map());
103
+ __publicField(this, "installed", false);
104
+ __publicField(this, "onWindowError", (event) => {
78
105
  var _a;
79
106
  this.push("error", [event.message, event.error instanceof Error ? (_a = event.error.stack) != null ? _a : "" : ""]);
80
107
  });
81
- chunk6TCI6T2U_cjs.__publicField(this, "onUnhandledRejection", (event) => {
108
+ __publicField(this, "onUnhandledRejection", (event) => {
82
109
  this.push("error", ["Unhandled promise rejection", event.reason]);
83
110
  });
84
111
  }
@@ -166,11 +193,11 @@ function extractMethod(input, init) {
166
193
  var NetworkBuffer = class {
167
194
  constructor(maxEntries) {
168
195
  this.maxEntries = maxEntries;
169
- chunk6TCI6T2U_cjs.__publicField(this, "entries", []);
170
- chunk6TCI6T2U_cjs.__publicField(this, "installed", false);
171
- chunk6TCI6T2U_cjs.__publicField(this, "originalFetch");
172
- chunk6TCI6T2U_cjs.__publicField(this, "originalXhrOpen");
173
- chunk6TCI6T2U_cjs.__publicField(this, "originalXhrSend");
196
+ __publicField(this, "entries", []);
197
+ __publicField(this, "installed", false);
198
+ __publicField(this, "originalFetch");
199
+ __publicField(this, "originalXhrOpen");
200
+ __publicField(this, "originalXhrSend");
174
201
  }
175
202
  install() {
176
203
  if (this.installed) {
@@ -311,7 +338,7 @@ var NetworkBuffer = class {
311
338
  }
312
339
  }
313
340
  };
314
- var BugReporterContext = react.createContext(void 0);
341
+ var BugReporterContext = React.createContext(void 0);
315
342
 
316
343
  // src/core/defaults.ts
317
344
  var DEFAULT_MASK_SELECTORS = [
@@ -371,6 +398,18 @@ function withDefaults(config) {
371
398
  };
372
399
  }
373
400
 
401
+ // src/types/index.ts
402
+ var BugReporterError = class extends Error {
403
+ constructor(code, message, cause) {
404
+ super(message);
405
+ __publicField(this, "code");
406
+ __publicField(this, "cause");
407
+ this.name = "BugReporterError";
408
+ this.code = code;
409
+ this.cause = cause;
410
+ }
411
+ };
412
+
374
413
  // src/storage/local-public.ts
375
414
  var LocalPublicProvider = class {
376
415
  constructor(options) {
@@ -398,7 +437,7 @@ var LocalPublicProvider = class {
398
437
  body: form
399
438
  });
400
439
  if (!response.ok) {
401
- throw new chunk6TCI6T2U_cjs.BugReporterError("UPLOAD_ERROR", `Local upload failed (${response.status}).`);
440
+ throw new BugReporterError("UPLOAD_ERROR", `Local upload failed (${response.status}).`);
402
441
  }
403
442
  const payload = await response.json();
404
443
  onProgress == null ? void 0 : onProgress(1);
@@ -441,7 +480,7 @@ var ProxyProvider = class {
441
480
  body: blob
442
481
  });
443
482
  if (!response.ok) {
444
- throw new chunk6TCI6T2U_cjs.BugReporterError("UPLOAD_ERROR", `Proxy upload failed (${response.status}).`);
483
+ throw new BugReporterError("UPLOAD_ERROR", `Proxy upload failed (${response.status}).`);
445
484
  }
446
485
  const payload = await response.json();
447
486
  onProgress == null ? void 0 : onProgress(1);
@@ -473,11 +512,11 @@ var S3PresignedProvider = class {
473
512
  body: JSON.stringify({ files })
474
513
  });
475
514
  if (!response.ok) {
476
- throw new chunk6TCI6T2U_cjs.BugReporterError("UPLOAD_ERROR", `Failed to prepare uploads (${response.status}).`);
515
+ throw new BugReporterError("UPLOAD_ERROR", `Failed to prepare uploads (${response.status}).`);
477
516
  }
478
517
  const payload = await response.json();
479
518
  if (!((_a = payload.uploads) == null ? void 0 : _a.length)) {
480
- throw new chunk6TCI6T2U_cjs.BugReporterError("UPLOAD_ERROR", "Presign endpoint did not return upload instructions.");
519
+ throw new BugReporterError("UPLOAD_ERROR", "Presign endpoint did not return upload instructions.");
481
520
  }
482
521
  return payload.uploads;
483
522
  }
@@ -493,7 +532,7 @@ var S3PresignedProvider = class {
493
532
  body: formData
494
533
  });
495
534
  if (!response.ok) {
496
- throw new chunk6TCI6T2U_cjs.BugReporterError("UPLOAD_ERROR", `S3 form upload failed (${response.status}).`);
535
+ throw new BugReporterError("UPLOAD_ERROR", `S3 form upload failed (${response.status}).`);
497
536
  }
498
537
  } else {
499
538
  const response = await fetch(instruction.uploadUrl, {
@@ -502,7 +541,7 @@ var S3PresignedProvider = class {
502
541
  body: blob
503
542
  });
504
543
  if (!response.ok) {
505
- throw new chunk6TCI6T2U_cjs.BugReporterError("UPLOAD_ERROR", `S3 upload failed (${response.status}).`);
544
+ throw new BugReporterError("UPLOAD_ERROR", `S3 upload failed (${response.status}).`);
506
545
  }
507
546
  }
508
547
  onProgress == null ? void 0 : onProgress(1);
@@ -604,7 +643,7 @@ async function uploadAssets(options) {
604
643
  for (const asset of options.assets) {
605
644
  const instruction = byId.get(asset.id);
606
645
  if (!instruction) {
607
- throw new chunk6TCI6T2U_cjs.BugReporterError("UPLOAD_ERROR", `No upload instruction for asset ${asset.id}.`);
646
+ throw new BugReporterError("UPLOAD_ERROR", `No upload instruction for asset ${asset.id}.`);
608
647
  }
609
648
  const ref = await withRetry(
610
649
  () => options.provider.upload(instruction, asset.blob, (inner) => {
@@ -671,7 +710,7 @@ async function submitReport(options) {
671
710
  };
672
711
  const transformed = options.config.hooks.beforeSubmit ? await options.config.hooks.beforeSubmit(payloadBase) : payloadBase;
673
712
  if (!transformed) {
674
- throw new chunk6TCI6T2U_cjs.BugReporterError("ABORTED", "Submission aborted by beforeSubmit hook.");
713
+ throw new BugReporterError("ABORTED", "Submission aborted by beforeSubmit hook.");
675
714
  }
676
715
  console.log("[bug-reporter] payload to submit", transformed);
677
716
  console.log("[bug-reporter] payload to submit (json)", JSON.stringify(transformed, null, 2));
@@ -686,7 +725,7 @@ async function submitReport(options) {
686
725
  });
687
726
  if (!response.ok) {
688
727
  const body = await response.text().catch(() => "");
689
- throw new chunk6TCI6T2U_cjs.BugReporterError("SUBMIT_ERROR", `Report submit failed (${response.status}): ${body || response.statusText}`);
728
+ throw new BugReporterError("SUBMIT_ERROR", `Report submit failed (${response.status}): ${body || response.statusText}`);
690
729
  }
691
730
  return await response.json();
692
731
  }
@@ -711,21 +750,21 @@ var BASE_STATE = {
711
750
  error: void 0
712
751
  };
713
752
  function BugReporterProvider({ config, children }) {
714
- const resolvedConfig = react.useMemo(() => withDefaults(config), [config]);
753
+ const resolvedConfig = React.useMemo(() => withDefaults(config), [config]);
715
754
  const initialDockSide = resolvedConfig.theme.position === "bottom-left" || resolvedConfig.theme.position === "top-left" ? "left" : "right";
716
- const [state, setState] = react.useState(() => ({
755
+ const [state, setState] = React.useState(() => ({
717
756
  ...BASE_STATE,
718
757
  dockSide: initialDockSide,
719
758
  attributes: { ...resolvedConfig.attributes }
720
759
  }));
721
- const [sessionActive, setSessionActive] = react.useState(false);
722
- const consoleBufferRef = react.useRef(null);
723
- const networkBufferRef = react.useRef(null);
724
- const assetsRef = react.useRef([]);
725
- const resetAssets = react.useCallback((assets) => {
760
+ const [sessionActive, setSessionActive] = React.useState(false);
761
+ const consoleBufferRef = React.useRef(null);
762
+ const networkBufferRef = React.useRef(null);
763
+ const assetsRef = React.useRef([]);
764
+ const resetAssets = React.useCallback((assets) => {
726
765
  assets.forEach((asset) => revokeObjectUrl(asset.previewUrl));
727
766
  }, []);
728
- const open = react.useCallback(() => {
767
+ const open = React.useCallback(() => {
729
768
  setSessionActive(true);
730
769
  setState((prev) => ({
731
770
  ...prev,
@@ -733,13 +772,13 @@ function BugReporterProvider({ config, children }) {
733
772
  error: void 0
734
773
  }));
735
774
  }, []);
736
- const close = react.useCallback(() => {
775
+ const close = React.useCallback(() => {
737
776
  setState((prev) => ({
738
777
  ...prev,
739
778
  isOpen: false
740
779
  }));
741
780
  }, []);
742
- const reset = react.useCallback(() => {
781
+ const reset = React.useCallback(() => {
743
782
  var _a, _b;
744
783
  setSessionActive(false);
745
784
  setState((prev) => {
@@ -754,13 +793,13 @@ function BugReporterProvider({ config, children }) {
754
793
  (_a = consoleBufferRef.current) == null ? void 0 : _a.clear();
755
794
  (_b = networkBufferRef.current) == null ? void 0 : _b.clear();
756
795
  }, [resetAssets, resolvedConfig.attributes]);
757
- const setStep = react.useCallback((step) => {
796
+ const setStep = React.useCallback((step) => {
758
797
  setState((prev) => ({ ...prev, step }));
759
798
  }, []);
760
- const setDockSide = react.useCallback((dockSide) => {
799
+ const setDockSide = React.useCallback((dockSide) => {
761
800
  setState((prev) => ({ ...prev, dockSide }));
762
801
  }, []);
763
- const updateDraft = react.useCallback((next) => {
802
+ const updateDraft = React.useCallback((next) => {
764
803
  setState((prev) => ({
765
804
  ...prev,
766
805
  draft: {
@@ -769,13 +808,13 @@ function BugReporterProvider({ config, children }) {
769
808
  }
770
809
  }));
771
810
  }, []);
772
- const setAttributes = react.useCallback((next) => {
811
+ const setAttributes = React.useCallback((next) => {
773
812
  setState((prev) => ({
774
813
  ...prev,
775
814
  attributes: next
776
815
  }));
777
816
  }, []);
778
- const updateAttribute = react.useCallback((key, value2) => {
817
+ const updateAttribute = React.useCallback((key, value2) => {
779
818
  setState((prev) => ({
780
819
  ...prev,
781
820
  attributes: {
@@ -784,7 +823,7 @@ function BugReporterProvider({ config, children }) {
784
823
  }
785
824
  }));
786
825
  }, []);
787
- const setAssetByType = react.useCallback((type, next) => {
826
+ const setAssetByType = React.useCallback((type, next) => {
788
827
  setState((prev) => {
789
828
  const previous = prev.assets.find((asset) => asset.type === type);
790
829
  if (previous) {
@@ -797,13 +836,13 @@ function BugReporterProvider({ config, children }) {
797
836
  };
798
837
  });
799
838
  }, []);
800
- const setScreenshot = react.useCallback((asset) => {
839
+ const setScreenshot = React.useCallback((asset) => {
801
840
  setAssetByType("screenshot", asset);
802
841
  }, [setAssetByType]);
803
- const setRecording = react.useCallback((asset) => {
842
+ const setRecording = React.useCallback((asset) => {
804
843
  setAssetByType("recording", asset);
805
844
  }, [setAssetByType]);
806
- const submit = react.useCallback(async () => {
845
+ const submit = React.useCallback(async () => {
807
846
  var _a, _b, _c, _d, _e, _f;
808
847
  setState((prev) => ({
809
848
  ...prev,
@@ -848,10 +887,10 @@ function BugReporterProvider({ config, children }) {
848
887
  (_f = (_e = resolvedConfig.hooks).onError) == null ? void 0 : _f.call(_e, error);
849
888
  }
850
889
  }, [resolvedConfig, state.assets, state.attributes, state.draft]);
851
- const retrySubmit = react.useCallback(async () => {
890
+ const retrySubmit = React.useCallback(async () => {
852
891
  await submit();
853
892
  }, [submit]);
854
- const getDiagnosticsPreview = react.useCallback(() => {
893
+ const getDiagnosticsPreview = React.useCallback(() => {
855
894
  var _a, _b, _c, _d;
856
895
  const logs = resolvedConfig.features.consoleLogs ? (_b = (_a = consoleBufferRef.current) == null ? void 0 : _a.snapshot()) != null ? _b : [] : [];
857
896
  const requests = resolvedConfig.features.networkInfo ? (_d = (_c = networkBufferRef.current) == null ? void 0 : _c.snapshot()) != null ? _d : [] : [];
@@ -863,7 +902,7 @@ function BugReporterProvider({ config, children }) {
863
902
  })
864
903
  };
865
904
  }, [resolvedConfig.features.consoleLogs, resolvedConfig.features.networkInfo]);
866
- react.useEffect(() => {
905
+ React.useEffect(() => {
867
906
  if (!sessionActive) {
868
907
  return;
869
908
  }
@@ -892,10 +931,10 @@ function BugReporterProvider({ config, children }) {
892
931
  resolvedConfig.features.consoleLogs,
893
932
  resolvedConfig.features.networkInfo
894
933
  ]);
895
- react.useEffect(() => {
934
+ React.useEffect(() => {
896
935
  assetsRef.current = state.assets;
897
936
  }, [state.assets]);
898
- react.useEffect(() => {
937
+ React.useEffect(() => {
899
938
  return () => {
900
939
  var _a, _b;
901
940
  resetAssets(assetsRef.current);
@@ -903,7 +942,7 @@ function BugReporterProvider({ config, children }) {
903
942
  (_b = networkBufferRef.current) == null ? void 0 : _b.uninstall();
904
943
  };
905
944
  }, [resetAssets]);
906
- const value = react.useMemo(
945
+ const value = React.useMemo(
907
946
  () => ({
908
947
  config: resolvedConfig,
909
948
  state,
@@ -939,10 +978,10 @@ function BugReporterProvider({ config, children }) {
939
978
  getDiagnosticsPreview
940
979
  ]
941
980
  );
942
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(BugReporterContext.Provider, { value }, children);
981
+ return /* @__PURE__ */ React__namespace.createElement(BugReporterContext.Provider, { value }, children);
943
982
  }
944
983
  function useBugReporter() {
945
- const context = react.useContext(BugReporterContext);
984
+ const context = React.useContext(BugReporterContext);
946
985
  if (!context) {
947
986
  throw new Error("useBugReporter must be used inside BugReporterProvider.");
948
987
  }
@@ -956,7 +995,7 @@ function getFocusable(node) {
956
995
  ).filter((el) => !el.hasAttribute("disabled"));
957
996
  }
958
997
  function useFocusTrap(enabled, containerRef) {
959
- react.useEffect(() => {
998
+ React.useEffect(() => {
960
999
  const container = containerRef.current;
961
1000
  if (!enabled || !container) {
962
1001
  return;
@@ -1367,7 +1406,7 @@ function LauncherButton({ position, text, themeMode = "dark", buttonColor }) {
1367
1406
  buttonColor: resolvedButtonColor,
1368
1407
  themeMode
1369
1408
  });
1370
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
1409
+ return /* @__PURE__ */ React__namespace.createElement(
1371
1410
  "button",
1372
1411
  {
1373
1412
  type: "button",
@@ -1379,9 +1418,9 @@ function LauncherButton({ position, text, themeMode = "dark", buttonColor }) {
1379
1418
  );
1380
1419
  }
1381
1420
  function Modal({ isOpen, dockSide, themeMode, buttonColor, title, zIndex, onRequestClose, children }) {
1382
- const dialogRef = react.useRef(null);
1421
+ const dialogRef = React.useRef(null);
1383
1422
  useFocusTrap(isOpen, dialogRef);
1384
- react.useEffect(() => {
1423
+ React.useEffect(() => {
1385
1424
  if (!isOpen) {
1386
1425
  return;
1387
1426
  }
@@ -1400,23 +1439,402 @@ function Modal({ isOpen, dockSide, themeMode, buttonColor, title, zIndex, onRequ
1400
1439
  const overlayStyle = getModalOverlayStyle({ dockSide, themeMode, zIndex });
1401
1440
  const modalStyle = getModalStyle({ dockSide, themeMode, buttonColor });
1402
1441
  return reactDom.createPortal(
1403
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: overlayStyle }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { ref: dialogRef, style: modalStyle, role: "dialog", "aria-modal": "true", "aria-label": title }, children)),
1442
+ /* @__PURE__ */ React__namespace.createElement("div", { style: overlayStyle }, /* @__PURE__ */ React__namespace.createElement("div", { ref: dialogRef, style: modalStyle, role: "dialog", "aria-modal": "true", "aria-label": title }, children)),
1404
1443
  document.body
1405
1444
  );
1406
1445
  }
1446
+ function applyMasking(selectors) {
1447
+ const masked = [];
1448
+ for (const selector of selectors) {
1449
+ document.querySelectorAll(selector).forEach((element) => {
1450
+ masked.push({ element, previous: element.style.filter });
1451
+ element.style.filter = "blur(12px)";
1452
+ });
1453
+ }
1454
+ return masked;
1455
+ }
1456
+ function resetMasking(masked) {
1457
+ masked.forEach(({ element, previous }) => {
1458
+ element.style.filter = previous;
1459
+ });
1460
+ }
1461
+ function scrubText(root, patterns) {
1462
+ var _a, _b;
1463
+ if (!patterns.length) {
1464
+ return [];
1465
+ }
1466
+ const walkers = [];
1467
+ const regexes = patterns.map((pattern) => typeof pattern === "string" ? new RegExp(pattern, "g") : pattern);
1468
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
1469
+ while (walker.nextNode()) {
1470
+ const text = walker.currentNode;
1471
+ let replaced = (_a = text.textContent) != null ? _a : "";
1472
+ for (const regex of regexes) {
1473
+ replaced = replaced.replace(regex, "[redacted]");
1474
+ }
1475
+ if (replaced !== text.textContent) {
1476
+ walkers.push({ node: text, previous: (_b = text.textContent) != null ? _b : "" });
1477
+ text.textContent = replaced;
1478
+ }
1479
+ }
1480
+ return walkers;
1481
+ }
1482
+ function restoreText(changed) {
1483
+ changed.forEach(({ node, previous }) => {
1484
+ node.textContent = previous;
1485
+ });
1486
+ }
1487
+ function createSelectionOverlay() {
1488
+ return new Promise((resolve, reject) => {
1489
+ const overlay = document.createElement("div");
1490
+ overlay.setAttribute("data-bug-reporter-overlay", "true");
1491
+ overlay.style.position = "fixed";
1492
+ overlay.style.inset = "0";
1493
+ overlay.style.background = "rgba(0,0,0,0.35)";
1494
+ overlay.style.cursor = "crosshair";
1495
+ overlay.style.zIndex = "2147483647";
1496
+ const box = document.createElement("div");
1497
+ box.style.position = "fixed";
1498
+ box.style.border = "2px solid #ffffff";
1499
+ box.style.background = "rgba(27, 116, 228, 0.2)";
1500
+ box.style.pointerEvents = "none";
1501
+ box.style.display = "none";
1502
+ overlay.appendChild(box);
1503
+ const cleanup = () => {
1504
+ overlay.removeEventListener("mousedown", onMouseDown);
1505
+ overlay.removeEventListener("mousemove", onMouseMove);
1506
+ overlay.removeEventListener("mouseup", onMouseUp);
1507
+ window.removeEventListener("keydown", onKeyDown);
1508
+ overlay.remove();
1509
+ };
1510
+ let startX = 0;
1511
+ let startY = 0;
1512
+ let isDragging = false;
1513
+ const onKeyDown = (event) => {
1514
+ if (event.key === "Escape") {
1515
+ cleanup();
1516
+ reject(new BugReporterError("ABORTED", "Screenshot capture cancelled."));
1517
+ }
1518
+ };
1519
+ const onMouseDown = (event) => {
1520
+ isDragging = true;
1521
+ startX = event.clientX;
1522
+ startY = event.clientY;
1523
+ box.style.display = "block";
1524
+ box.style.left = `${startX}px`;
1525
+ box.style.top = `${startY}px`;
1526
+ box.style.width = "0px";
1527
+ box.style.height = "0px";
1528
+ };
1529
+ const onMouseMove = (event) => {
1530
+ if (!isDragging) {
1531
+ return;
1532
+ }
1533
+ const left = Math.min(startX, event.clientX);
1534
+ const top = Math.min(startY, event.clientY);
1535
+ const width = Math.abs(startX - event.clientX);
1536
+ const height = Math.abs(startY - event.clientY);
1537
+ box.style.left = `${left}px`;
1538
+ box.style.top = `${top}px`;
1539
+ box.style.width = `${width}px`;
1540
+ box.style.height = `${height}px`;
1541
+ };
1542
+ const onMouseUp = (event) => {
1543
+ if (!isDragging) {
1544
+ return;
1545
+ }
1546
+ isDragging = false;
1547
+ const left = Math.min(startX, event.clientX);
1548
+ const top = Math.min(startY, event.clientY);
1549
+ const width = Math.abs(startX - event.clientX);
1550
+ const height = Math.abs(startY - event.clientY);
1551
+ cleanup();
1552
+ if (width < 8 || height < 8) {
1553
+ reject(new BugReporterError("CAPTURE_ERROR", "Selection area is too small."));
1554
+ return;
1555
+ }
1556
+ resolve({ left, top, width, height });
1557
+ };
1558
+ overlay.addEventListener("mousedown", onMouseDown);
1559
+ overlay.addEventListener("mousemove", onMouseMove);
1560
+ overlay.addEventListener("mouseup", onMouseUp);
1561
+ window.addEventListener("keydown", onKeyDown);
1562
+ document.body.appendChild(overlay);
1563
+ });
1564
+ }
1565
+ function rectsIntersect(a, b) {
1566
+ return !(a.left + a.width <= b.left || b.left + b.width <= a.left || a.top + a.height <= b.top || b.top + b.height <= a.top);
1567
+ }
1568
+ function intersectsCrossOriginIframe(selection) {
1569
+ const iframes = Array.from(document.querySelectorAll("iframe"));
1570
+ for (const iframe of iframes) {
1571
+ const rect = iframe.getBoundingClientRect();
1572
+ if (rect.width <= 0 || rect.height <= 0) {
1573
+ continue;
1574
+ }
1575
+ if (!rectsIntersect(selection, {
1576
+ left: rect.left,
1577
+ top: rect.top,
1578
+ width: rect.width,
1579
+ height: rect.height
1580
+ })) {
1581
+ continue;
1582
+ }
1583
+ try {
1584
+ if (!iframe.contentWindow || !iframe.contentDocument) {
1585
+ return true;
1586
+ }
1587
+ void iframe.contentDocument.location.href;
1588
+ } catch (e) {
1589
+ return true;
1590
+ }
1591
+ }
1592
+ return false;
1593
+ }
1594
+ async function captureWithDisplayMedia(selection) {
1595
+ var _a;
1596
+ if (!((_a = navigator.mediaDevices) == null ? void 0 : _a.getDisplayMedia)) {
1597
+ throw new BugReporterError("CAPTURE_ERROR", "This page contains iframe content that needs screen-capture permission.");
1598
+ }
1599
+ let stream = null;
1600
+ const video = document.createElement("video");
1601
+ video.muted = true;
1602
+ video.playsInline = true;
1603
+ try {
1604
+ stream = await navigator.mediaDevices.getDisplayMedia({
1605
+ video: true,
1606
+ audio: false
1607
+ });
1608
+ video.srcObject = stream;
1609
+ await video.play();
1610
+ if (!video.videoWidth || !video.videoHeight) {
1611
+ await new Promise((resolve) => {
1612
+ video.onloadedmetadata = () => resolve();
1613
+ });
1614
+ }
1615
+ if (!video.videoWidth || !video.videoHeight) {
1616
+ throw new BugReporterError("CAPTURE_ERROR", "Could not read screen-capture frame.");
1617
+ }
1618
+ const scaleX = video.videoWidth / window.innerWidth;
1619
+ const scaleY = video.videoHeight / window.innerHeight;
1620
+ const sx = Math.max(0, Math.round(selection.left * scaleX));
1621
+ const sy = Math.max(0, Math.round(selection.top * scaleY));
1622
+ const sw = Math.max(1, Math.round(selection.width * scaleX));
1623
+ const sh = Math.max(1, Math.round(selection.height * scaleY));
1624
+ const canvas = document.createElement("canvas");
1625
+ canvas.width = sw;
1626
+ canvas.height = sh;
1627
+ const context = canvas.getContext("2d");
1628
+ if (!context) {
1629
+ throw new BugReporterError("CAPTURE_ERROR", "Canvas 2D context unavailable.");
1630
+ }
1631
+ context.drawImage(video, sx, sy, sw, sh, 0, 0, sw, sh);
1632
+ return await canvasToBlob(canvas);
1633
+ } catch (error) {
1634
+ if (error instanceof BugReporterError) {
1635
+ throw error;
1636
+ }
1637
+ if (error instanceof DOMException && error.name === "NotAllowedError") {
1638
+ throw new BugReporterError("PERMISSION_DENIED", "Permission denied for screen capture.", error);
1639
+ }
1640
+ throw new BugReporterError("CAPTURE_ERROR", "Fallback screen capture failed.", error);
1641
+ } finally {
1642
+ stream == null ? void 0 : stream.getTracks().forEach((track) => track.stop());
1643
+ video.srcObject = null;
1644
+ }
1645
+ }
1646
+ function canvasToBlob(canvas) {
1647
+ return new Promise((resolve, reject) => {
1648
+ canvas.toBlob((blob) => {
1649
+ if (!blob) {
1650
+ reject(new BugReporterError("CAPTURE_ERROR", "Failed to build screenshot blob."));
1651
+ return;
1652
+ }
1653
+ resolve(blob);
1654
+ }, "image/png");
1655
+ });
1656
+ }
1657
+ async function captureScreenshotArea(options) {
1658
+ const selection = await createSelectionOverlay();
1659
+ const masked = applyMasking(options.maskSelectors);
1660
+ const textChanges = scrubText(document.body, options.redactTextPatterns);
1661
+ try {
1662
+ if (intersectsCrossOriginIframe(selection)) {
1663
+ return await captureWithDisplayMedia(selection);
1664
+ }
1665
+ const baseCanvas = await html2canvas__default.default(document.documentElement, {
1666
+ useCORS: true,
1667
+ scrollX: -window.scrollX,
1668
+ scrollY: -window.scrollY,
1669
+ backgroundColor: null,
1670
+ logging: false,
1671
+ windowWidth: document.documentElement.scrollWidth,
1672
+ windowHeight: document.documentElement.scrollHeight
1673
+ });
1674
+ const scaleX = baseCanvas.width / window.innerWidth;
1675
+ const scaleY = baseCanvas.height / window.innerHeight;
1676
+ const sx = Math.round(selection.left * scaleX);
1677
+ const sy = Math.round(selection.top * scaleY);
1678
+ const sw = Math.round(selection.width * scaleX);
1679
+ const sh = Math.round(selection.height * scaleY);
1680
+ const cropped = document.createElement("canvas");
1681
+ cropped.width = sw;
1682
+ cropped.height = sh;
1683
+ const context = cropped.getContext("2d");
1684
+ if (!context) {
1685
+ throw new BugReporterError("CAPTURE_ERROR", "Canvas 2D context unavailable.");
1686
+ }
1687
+ context.drawImage(baseCanvas, sx, sy, sw, sh, 0, 0, sw, sh);
1688
+ return await canvasToBlob(cropped);
1689
+ } catch (error) {
1690
+ if (!intersectsCrossOriginIframe(selection)) {
1691
+ try {
1692
+ return await captureWithDisplayMedia(selection);
1693
+ } catch (fallbackError) {
1694
+ if (fallbackError instanceof BugReporterError) {
1695
+ throw fallbackError;
1696
+ }
1697
+ }
1698
+ }
1699
+ if (error instanceof BugReporterError) {
1700
+ throw error;
1701
+ }
1702
+ throw new BugReporterError("CAPTURE_ERROR", "Screenshot capture failed.", error);
1703
+ } finally {
1704
+ resetMasking(masked);
1705
+ restoreText(textChanges);
1706
+ }
1707
+ }
1708
+
1709
+ // src/core/recording.ts
1710
+ function pickMimeType() {
1711
+ const candidates = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"];
1712
+ for (const candidate of candidates) {
1713
+ if (typeof MediaRecorder !== "undefined" && MediaRecorder.isTypeSupported(candidate)) {
1714
+ return candidate;
1715
+ }
1716
+ }
1717
+ return "video/webm";
1718
+ }
1719
+ async function startScreenRecording(options) {
1720
+ var _a;
1721
+ if (!((_a = navigator.mediaDevices) == null ? void 0 : _a.getDisplayMedia)) {
1722
+ throw new BugReporterError("RECORDING_ERROR", "Screen recording is not supported by this browser.");
1723
+ }
1724
+ let stream;
1725
+ try {
1726
+ stream = await navigator.mediaDevices.getDisplayMedia({
1727
+ video: true,
1728
+ audio: false
1729
+ });
1730
+ } catch (error) {
1731
+ throw new BugReporterError("PERMISSION_DENIED", "Permission denied for screen recording.", error);
1732
+ }
1733
+ const mimeType = pickMimeType();
1734
+ let recorder;
1735
+ try {
1736
+ recorder = new MediaRecorder(stream, { mimeType });
1737
+ } catch (error) {
1738
+ stream.getTracks().forEach((track) => track.stop());
1739
+ throw new BugReporterError("RECORDING_ERROR", "Could not initialize MediaRecorder.", error);
1740
+ }
1741
+ const chunks = [];
1742
+ const startedAt = Date.now();
1743
+ let latestSize = 0;
1744
+ let tickSeconds = 0;
1745
+ let completed = false;
1746
+ let isCancelled = false;
1747
+ let resolvePromise;
1748
+ let rejectPromise;
1749
+ const promise = new Promise((resolve, reject) => {
1750
+ resolvePromise = resolve;
1751
+ rejectPromise = reject;
1752
+ });
1753
+ const tickInterval = window.setInterval(() => {
1754
+ var _a2;
1755
+ tickSeconds += 1;
1756
+ (_a2 = options.onTick) == null ? void 0 : _a2.call(options, tickSeconds);
1757
+ }, 1e3);
1758
+ const hardStop = window.setTimeout(() => {
1759
+ if (recorder.state !== "inactive") {
1760
+ recorder.stop();
1761
+ }
1762
+ }, options.maxSeconds * 1e3);
1763
+ const teardown = () => {
1764
+ if (completed) {
1765
+ return;
1766
+ }
1767
+ completed = true;
1768
+ window.clearInterval(tickInterval);
1769
+ window.clearTimeout(hardStop);
1770
+ stream.getTracks().forEach((track) => track.stop());
1771
+ };
1772
+ recorder.addEventListener("dataavailable", (event) => {
1773
+ if (!event.data || event.data.size === 0) {
1774
+ return;
1775
+ }
1776
+ chunks.push(event.data);
1777
+ latestSize += event.data.size;
1778
+ if (latestSize > options.maxBytes) {
1779
+ isCancelled = true;
1780
+ recorder.stop();
1781
+ rejectPromise(
1782
+ new BugReporterError(
1783
+ "VALIDATION_ERROR",
1784
+ `Recording exceeds max size (${Math.round(options.maxBytes / 1024 / 1024)}MB).`
1785
+ )
1786
+ );
1787
+ }
1788
+ });
1789
+ recorder.addEventListener("error", (event) => {
1790
+ teardown();
1791
+ rejectPromise(new BugReporterError("RECORDING_ERROR", "Recording failed.", event));
1792
+ });
1793
+ recorder.addEventListener("stop", () => {
1794
+ teardown();
1795
+ if (isCancelled) {
1796
+ return;
1797
+ }
1798
+ const blob = new Blob(chunks, { type: mimeType });
1799
+ resolvePromise({
1800
+ blob,
1801
+ mimeType,
1802
+ durationMs: Date.now() - startedAt
1803
+ });
1804
+ });
1805
+ recorder.start(300);
1806
+ return {
1807
+ stop: () => {
1808
+ if (recorder.state !== "inactive") {
1809
+ recorder.stop();
1810
+ }
1811
+ },
1812
+ cancel: () => {
1813
+ isCancelled = true;
1814
+ if (recorder.state !== "inactive") {
1815
+ recorder.stop();
1816
+ }
1817
+ teardown();
1818
+ rejectPromise(new BugReporterError("ABORTED", "Recording cancelled by user."));
1819
+ },
1820
+ promise
1821
+ };
1822
+ }
1407
1823
 
1408
1824
  // src/core/lazy.ts
1825
+ var screenshotCaptureModule = { captureScreenshotArea };
1826
+ var screenRecordingModule = { startScreenRecording };
1409
1827
  async function loadScreenshotCapture() {
1410
- return import('./screenshot-AWRHVVWJ.cjs');
1828
+ return screenshotCaptureModule;
1411
1829
  }
1412
1830
  async function loadScreenRecording() {
1413
- return import('./recording-DZREYVVL.cjs');
1831
+ return screenRecordingModule;
1414
1832
  }
1415
1833
 
1416
1834
  // src/core/validation.ts
1417
1835
  function validateScreenshotSize(size, maxBytes) {
1418
1836
  if (size > maxBytes) {
1419
- throw new chunk6TCI6T2U_cjs.BugReporterError(
1837
+ throw new BugReporterError(
1420
1838
  "VALIDATION_ERROR",
1421
1839
  `Screenshot exceeds max size (${Math.round(maxBytes / 1024 / 1024)}MB).`
1422
1840
  );
@@ -1424,7 +1842,7 @@ function validateScreenshotSize(size, maxBytes) {
1424
1842
  }
1425
1843
  function validateVideoSize(size, maxBytes) {
1426
1844
  if (size > maxBytes) {
1427
- throw new chunk6TCI6T2U_cjs.BugReporterError("VALIDATION_ERROR", `Recording exceeds max size (${Math.round(maxBytes / 1024 / 1024)}MB).`);
1845
+ throw new BugReporterError("VALIDATION_ERROR", `Recording exceeds max size (${Math.round(maxBytes / 1024 / 1024)}MB).`);
1428
1846
  }
1429
1847
  }
1430
1848
  function drawArrow(ctx, start, end) {
@@ -1441,14 +1859,14 @@ function drawArrow(ctx, start, end) {
1441
1859
  ctx.closePath();
1442
1860
  ctx.fill();
1443
1861
  }
1444
- var AnnotationCanvas = react.forwardRef(function AnnotationCanvas2({ imageUrl }, ref) {
1445
- const canvasRef = react.useRef(null);
1446
- const imageRef = react.useRef(null);
1447
- const [tool, setTool] = react.useState("rectangle");
1448
- const [shapes, setShapes] = react.useState([]);
1449
- const [draftShape, setDraftShape] = react.useState(null);
1450
- const dragStartRef = react.useRef(null);
1451
- const redraw = react.useCallback(
1862
+ var AnnotationCanvas = React.forwardRef(function AnnotationCanvas2({ imageUrl }, ref) {
1863
+ const canvasRef = React.useRef(null);
1864
+ const imageRef = React.useRef(null);
1865
+ const [tool, setTool] = React.useState("rectangle");
1866
+ const [shapes, setShapes] = React.useState([]);
1867
+ const [draftShape, setDraftShape] = React.useState(null);
1868
+ const dragStartRef = React.useRef(null);
1869
+ const redraw = React.useCallback(
1452
1870
  (ctx) => {
1453
1871
  const canvas = canvasRef.current;
1454
1872
  const image = imageRef.current;
@@ -1477,7 +1895,7 @@ var AnnotationCanvas = react.forwardRef(function AnnotationCanvas2({ imageUrl },
1477
1895
  },
1478
1896
  [draftShape, shapes]
1479
1897
  );
1480
- react.useEffect(() => {
1898
+ React.useEffect(() => {
1481
1899
  const image = new Image();
1482
1900
  image.crossOrigin = "anonymous";
1483
1901
  image.onload = () => {
@@ -1496,7 +1914,7 @@ var AnnotationCanvas = react.forwardRef(function AnnotationCanvas2({ imageUrl },
1496
1914
  };
1497
1915
  image.src = imageUrl;
1498
1916
  }, [imageUrl, redraw]);
1499
- react.useEffect(() => {
1917
+ React.useEffect(() => {
1500
1918
  const canvas = canvasRef.current;
1501
1919
  if (!canvas) {
1502
1920
  return;
@@ -1507,7 +1925,7 @@ var AnnotationCanvas = react.forwardRef(function AnnotationCanvas2({ imageUrl },
1507
1925
  }
1508
1926
  redraw(ctx);
1509
1927
  }, [redraw]);
1510
- const getCoords = react.useCallback((event) => {
1928
+ const getCoords = React.useCallback((event) => {
1511
1929
  const canvas = canvasRef.current;
1512
1930
  if (!canvas) {
1513
1931
  return { x: 0, y: 0 };
@@ -1550,7 +1968,7 @@ var AnnotationCanvas = react.forwardRef(function AnnotationCanvas2({ imageUrl },
1550
1968
  }
1551
1969
  setDraftShape(null);
1552
1970
  };
1553
- const canvasToBlob = react.useCallback(async () => {
1971
+ const canvasToBlob2 = React.useCallback(async () => {
1554
1972
  const canvas = canvasRef.current;
1555
1973
  if (!canvas) {
1556
1974
  throw new Error("Annotation canvas unavailable.");
@@ -1563,23 +1981,23 @@ var AnnotationCanvas = react.forwardRef(function AnnotationCanvas2({ imageUrl },
1563
1981
  }
1564
1982
  return blob;
1565
1983
  }, []);
1566
- react.useImperativeHandle(
1984
+ React.useImperativeHandle(
1567
1985
  ref,
1568
1986
  () => ({
1569
- exportBlob: canvasToBlob,
1987
+ exportBlob: canvasToBlob2,
1570
1988
  clear: () => setShapes([]),
1571
1989
  hasAnnotations: () => shapes.length > 0
1572
1990
  }),
1573
- [canvasToBlob, shapes.length]
1991
+ [canvasToBlob2, shapes.length]
1574
1992
  );
1575
- const toolButtons = react.useMemo(
1993
+ const toolButtons = React.useMemo(
1576
1994
  () => [
1577
1995
  { value: "rectangle", label: "Rectangle" },
1578
1996
  { value: "arrow", label: "Arrow" }
1579
1997
  ],
1580
1998
  []
1581
1999
  );
1582
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.annotation }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.annotationTools, role: "toolbar", "aria-label": "Annotation tools" }, toolButtons.map((option) => /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2000
+ return /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.annotation }, /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.annotationTools, role: "toolbar", "aria-label": "Annotation tools" }, toolButtons.map((option) => /* @__PURE__ */ React__namespace.createElement(
1583
2001
  "button",
1584
2002
  {
1585
2003
  key: option.value,
@@ -1588,7 +2006,7 @@ var AnnotationCanvas = react.forwardRef(function AnnotationCanvas2({ imageUrl },
1588
2006
  onClick: () => setTool(option.value)
1589
2007
  },
1590
2008
  option.label
1591
- )), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: getButtonStyle("secondary"), onClick: () => setShapes([]) }, "Clear")), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2009
+ )), /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: getButtonStyle("secondary"), onClick: () => setShapes([]) }, "Clear")), /* @__PURE__ */ React__namespace.createElement(
1592
2010
  "canvas",
1593
2011
  {
1594
2012
  ref: canvasRef,
@@ -1612,12 +2030,12 @@ function StepRecording({ onBack, onNext, embedded = false, compact = false }) {
1612
2030
  state: { assets },
1613
2031
  setRecording
1614
2032
  } = useBugReporter();
1615
- const recording = react.useMemo(() => assets.find((asset) => asset.type === "recording"), [assets]);
1616
- const activeRef = react.useRef(null);
1617
- const mountedRef = react.useRef(true);
1618
- const [isRecording, setIsRecording] = react.useState(Boolean(sharedRecording));
1619
- const [seconds, setSeconds] = react.useState((_a = sharedRecording == null ? void 0 : sharedRecording.seconds) != null ? _a : 0);
1620
- const [error, setError] = react.useState(null);
2033
+ const recording = React.useMemo(() => assets.find((asset) => asset.type === "recording"), [assets]);
2034
+ const activeRef = React.useRef(null);
2035
+ const mountedRef = React.useRef(true);
2036
+ const [isRecording, setIsRecording] = React.useState(Boolean(sharedRecording));
2037
+ const [seconds, setSeconds] = React.useState((_a = sharedRecording == null ? void 0 : sharedRecording.seconds) != null ? _a : 0);
2038
+ const [error, setError] = React.useState(null);
1621
2039
  const start = async () => {
1622
2040
  if (sharedRecording) {
1623
2041
  setError("Recording is already in progress.");
@@ -1676,7 +2094,7 @@ function StepRecording({ onBack, onNext, embedded = false, compact = false }) {
1676
2094
  }
1677
2095
  (_a2 = activeRef.current) == null ? void 0 : _a2.stop();
1678
2096
  };
1679
- react.useEffect(() => {
2097
+ React.useEffect(() => {
1680
2098
  mountedRef.current = true;
1681
2099
  const sync = () => {
1682
2100
  var _a2, _b;
@@ -1692,10 +2110,10 @@ function StepRecording({ onBack, onNext, embedded = false, compact = false }) {
1692
2110
  };
1693
2111
  }, []);
1694
2112
  if (compact) {
1695
- const compactRecordingAction = !isRecording ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: { ...getButtonStyle("primary", { fullWidth: true }), ...inlineStyles.captureButton }, onClick: start }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { style: inlineStyles.captureIcon, viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("circle", { cx: "12", cy: "12", r: "4.5" }), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 8.5h3l1.2-2h8.6l1.2 2h3v7h-3l-1.2 2H7.7l-1.2-2h-3z" })), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("span", null, recording ? "Retake recording" : "Record a video"), recording ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("span", { style: inlineStyles.captureDone }, "Saved") : null) : /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: { ...getButtonStyle("danger", { fullWidth: true }), ...inlineStyles.captureButton }, onClick: stop }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { style: inlineStyles.captureIcon, viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("rect", { x: "7", y: "7", width: "10", height: "10" })), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("span", null, "Stop (", seconds, "s)"));
1696
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.captureItem }, compactRecordingAction, error ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: { ...inlineStyles.error, marginTop: "8px" } }, error) : null);
2113
+ const compactRecordingAction = !isRecording ? /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: { ...getButtonStyle("primary", { fullWidth: true }), ...inlineStyles.captureButton }, onClick: start }, /* @__PURE__ */ React__namespace.createElement("svg", { style: inlineStyles.captureIcon, viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" }, /* @__PURE__ */ React__namespace.createElement("circle", { cx: "12", cy: "12", r: "4.5" }), /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 8.5h3l1.2-2h8.6l1.2 2h3v7h-3l-1.2 2H7.7l-1.2-2h-3z" })), /* @__PURE__ */ React__namespace.createElement("span", null, recording ? "Retake recording" : "Record a video"), recording ? /* @__PURE__ */ React__namespace.createElement("span", { style: inlineStyles.captureDone }, "Saved") : null) : /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: { ...getButtonStyle("danger", { fullWidth: true }), ...inlineStyles.captureButton }, onClick: stop }, /* @__PURE__ */ React__namespace.createElement("svg", { style: inlineStyles.captureIcon, viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" }, /* @__PURE__ */ React__namespace.createElement("rect", { x: "7", y: "7", width: "10", height: "10" })), /* @__PURE__ */ React__namespace.createElement("span", null, "Stop (", seconds, "s)"));
2114
+ return /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.captureItem }, compactRecordingAction, error ? /* @__PURE__ */ React__namespace.createElement("p", { style: { ...inlineStyles.error, marginTop: "8px" } }, error) : null);
1697
2115
  }
1698
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: embedded ? void 0 : inlineStyles.step }, embedded ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("h3", { style: inlineStyles.h3 }, "Screen recording") : /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("h2", { style: inlineStyles.h2 }, "Screen recording"), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.p }, "Record up to ", config.storage.limits.maxVideoSeconds, " seconds. You can minimize this sidebar while recording."), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.actions }, onBack ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: getButtonStyle("secondary", { disabled: isRecording }), onClick: onBack, disabled: isRecording }, "Back") : null, !isRecording ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: getButtonStyle("primary"), onClick: start }, recording ? "Retake recording" : "Record a video") : /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: getButtonStyle("danger"), onClick: stop }, "Stop (", seconds, "s)")), recording ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("video", { src: recording.previewUrl, style: inlineStyles.preview, controls: true }) : null, error ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.error }, error) : null, onNext ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.actions }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: getButtonStyle("primary"), onClick: onNext }, "Continue")) : null);
2116
+ return /* @__PURE__ */ React__namespace.createElement("div", { style: embedded ? void 0 : inlineStyles.step }, embedded ? /* @__PURE__ */ React__namespace.createElement("h3", { style: inlineStyles.h3 }, "Screen recording") : /* @__PURE__ */ React__namespace.createElement("h2", { style: inlineStyles.h2 }, "Screen recording"), /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.p }, "Record up to ", config.storage.limits.maxVideoSeconds, " seconds. You can minimize this sidebar while recording."), /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.actions }, onBack ? /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: getButtonStyle("secondary", { disabled: isRecording }), onClick: onBack, disabled: isRecording }, "Back") : null, !isRecording ? /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: getButtonStyle("primary"), onClick: start }, recording ? "Retake recording" : "Record a video") : /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: getButtonStyle("danger"), onClick: stop }, "Stop (", seconds, "s)")), recording ? /* @__PURE__ */ React__namespace.createElement("video", { src: recording.previewUrl, style: inlineStyles.preview, controls: true }) : null, error ? /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.error }, error) : null, onNext ? /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.actions }, /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: getButtonStyle("primary"), onClick: onNext }, "Continue")) : null);
1699
2117
  }
1700
2118
 
1701
2119
  // src/components/StepDescribe.tsx
@@ -1708,13 +2126,13 @@ function StepDescribe({ onNext, CustomForm }) {
1708
2126
  updateAttribute,
1709
2127
  setScreenshot
1710
2128
  } = useBugReporter();
1711
- const screenshot = react.useMemo(() => assets.find((asset) => asset.type === "screenshot"), [assets]);
1712
- const recording = react.useMemo(() => assets.find((asset) => asset.type === "recording"), [assets]);
1713
- const annotationRef = react.useRef(null);
1714
- const customFormRef = react.useRef(null);
1715
- const [isCapturing, setIsCapturing] = react.useState(false);
1716
- const [error, setError] = react.useState(null);
1717
- react.useEffect(() => {
2129
+ const screenshot = React.useMemo(() => assets.find((asset) => asset.type === "screenshot"), [assets]);
2130
+ const recording = React.useMemo(() => assets.find((asset) => asset.type === "recording"), [assets]);
2131
+ const annotationRef = React.useRef(null);
2132
+ const customFormRef = React.useRef(null);
2133
+ const [isCapturing, setIsCapturing] = React.useState(false);
2134
+ const [error, setError] = React.useState(null);
2135
+ React.useEffect(() => {
1718
2136
  if (!CustomForm) {
1719
2137
  return;
1720
2138
  }
@@ -1794,7 +2212,7 @@ function StepDescribe({ onNext, CustomForm }) {
1794
2212
  onNext();
1795
2213
  };
1796
2214
  const canContinue = Boolean(draft.title.trim()) && (!config.features.screenshot || Boolean(screenshot));
1797
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: { ...inlineStyles.step, display: "flex", flexDirection: "column", minHeight: "100%" } }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("h2", { style: inlineStyles.h2 }, "Report a bug"), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.p }, "Provide enough context so engineers can reproduce what happened."), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("label", { style: inlineStyles.field }, "Title", /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2215
+ return /* @__PURE__ */ React__namespace.createElement("div", { style: { ...inlineStyles.step, display: "flex", flexDirection: "column", minHeight: "100%" } }, /* @__PURE__ */ React__namespace.createElement("h2", { style: inlineStyles.h2 }, "Report a bug"), /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.p }, "Provide enough context so engineers can reproduce what happened."), /* @__PURE__ */ React__namespace.createElement("label", { style: inlineStyles.field }, "Title", /* @__PURE__ */ React__namespace.createElement(
1798
2216
  "input",
1799
2217
  {
1800
2218
  style: inlineStyles.input,
@@ -1803,7 +2221,7 @@ function StepDescribe({ onNext, CustomForm }) {
1803
2221
  placeholder: "Short summary",
1804
2222
  required: true
1805
2223
  }
1806
- )), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("label", { style: inlineStyles.field }, "Description", /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2224
+ )), /* @__PURE__ */ React__namespace.createElement("label", { style: inlineStyles.field }, "Description", /* @__PURE__ */ React__namespace.createElement(
1807
2225
  "textarea",
1808
2226
  {
1809
2227
  style: inlineStyles.input,
@@ -1812,7 +2230,7 @@ function StepDescribe({ onNext, CustomForm }) {
1812
2230
  placeholder: "What happened?",
1813
2231
  rows: 4
1814
2232
  }
1815
- )), CustomForm ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { ref: customFormRef }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(CustomForm, { attributes, setAttributes, updateAttribute })) : null, config.features.screenshot || config.features.recording ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(chunk6TCI6T2U_cjs.React.Fragment, null, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("h3", { style: inlineStyles.h3 }, "Capture"), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.captureRow }, config.features.screenshot ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.captureItem }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2233
+ )), CustomForm ? /* @__PURE__ */ React__namespace.createElement("div", { ref: customFormRef }, /* @__PURE__ */ React__namespace.createElement(CustomForm, { attributes, setAttributes, updateAttribute })) : null, config.features.screenshot || config.features.recording ? /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement("h3", { style: inlineStyles.h3 }, "Capture"), /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.captureRow }, config.features.screenshot ? /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.captureItem }, /* @__PURE__ */ React__namespace.createElement(
1816
2234
  "button",
1817
2235
  {
1818
2236
  type: "button",
@@ -1820,10 +2238,10 @@ function StepDescribe({ onNext, CustomForm }) {
1820
2238
  onClick: startCapture,
1821
2239
  disabled: isCapturing
1822
2240
  },
1823
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { style: inlineStyles.captureIcon, viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M4 8.5h3l1.2-2h7.6l1.2 2h3v9H4z" }), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("circle", { cx: "12", cy: "13", r: "3.5" })),
1824
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("span", null, isCapturing ? "Capturing..." : screenshot ? "Retake screenshot" : "Screenshot"),
1825
- screenshot ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("span", { style: inlineStyles.captureDone }, "Saved") : null
1826
- )) : null, config.features.recording ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(StepRecording, { embedded: true, compact: true }) : null), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.captureNote }, config.features.screenshot && config.features.recording ? `Capture a screenshot and optionally record up to ${config.storage.limits.maxVideoSeconds} seconds.` : config.features.screenshot ? "Capture the relevant area before continuing." : `Record up to ${config.storage.limits.maxVideoSeconds} seconds.`), screenshot ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.previewWrapper }, config.features.annotations ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(AnnotationCanvas, { ref: annotationRef, imageUrl: screenshot.previewUrl }) : /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("img", { src: screenshot.previewUrl, alt: "Screenshot preview", style: inlineStyles.preview })) : null, !screenshot && recording ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.captureNote }, "Recording saved.") : null) : null, error ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.error }, error) : null, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2241
+ /* @__PURE__ */ React__namespace.createElement("svg", { style: inlineStyles.captureIcon, viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false" }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M4 8.5h3l1.2-2h7.6l1.2 2h3v9H4z" }), /* @__PURE__ */ React__namespace.createElement("circle", { cx: "12", cy: "13", r: "3.5" })),
2242
+ /* @__PURE__ */ React__namespace.createElement("span", null, isCapturing ? "Capturing..." : screenshot ? "Retake screenshot" : "Screenshot"),
2243
+ screenshot ? /* @__PURE__ */ React__namespace.createElement("span", { style: inlineStyles.captureDone }, "Saved") : null
2244
+ )) : null, config.features.recording ? /* @__PURE__ */ React__namespace.createElement(StepRecording, { embedded: true, compact: true }) : null), /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.captureNote }, config.features.screenshot && config.features.recording ? `Capture a screenshot and optionally record up to ${config.storage.limits.maxVideoSeconds} seconds.` : config.features.screenshot ? "Capture the relevant area before continuing." : `Record up to ${config.storage.limits.maxVideoSeconds} seconds.`), screenshot ? /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.previewWrapper }, config.features.annotations ? /* @__PURE__ */ React__namespace.createElement(AnnotationCanvas, { ref: annotationRef, imageUrl: screenshot.previewUrl }) : /* @__PURE__ */ React__namespace.createElement("img", { src: screenshot.previewUrl, alt: "Screenshot preview", style: inlineStyles.preview })) : null, !screenshot && recording ? /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.captureNote }, "Recording saved.") : null) : null, error ? /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.error }, error) : null, /* @__PURE__ */ React__namespace.createElement(
1827
2245
  "div",
1828
2246
  {
1829
2247
  style: {
@@ -1836,7 +2254,7 @@ function StepDescribe({ onNext, CustomForm }) {
1836
2254
  paddingBottom: "12px"
1837
2255
  }
1838
2256
  },
1839
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2257
+ /* @__PURE__ */ React__namespace.createElement(
1840
2258
  "button",
1841
2259
  {
1842
2260
  type: "button",
@@ -1855,7 +2273,7 @@ function StepReview({ onBack }) {
1855
2273
  state: { assets, draft, isSubmitting, uploadProgress, error },
1856
2274
  submit
1857
2275
  } = useBugReporter();
1858
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: { ...inlineStyles.step, display: "flex", flexDirection: "column", minHeight: "100%" } }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("h2", { style: inlineStyles.h2 }, "Review and submit"), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.p }, "Confirm details, then send your report."), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.summary }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("strong", null, draft.title || "Untitled bug report"), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.p }, draft.description || "No description provided.")), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.assets }, assets.map((asset) => /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { key: asset.id, style: inlineStyles.assetCard }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("span", { style: inlineStyles.assetType }, asset.type), asset.type === "recording" ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("video", { src: asset.previewUrl, controls: true, style: inlineStyles.preview }) : /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("img", { src: asset.previewUrl, alt: `${asset.type} preview`, style: inlineStyles.preview })))), isSubmitting ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.uploadProgress, "aria-live": "polite" }, "Uploading assets: ", Math.round(uploadProgress * 100), "%", /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.progressTrack }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: { ...inlineStyles.progressFill, width: `${Math.round(uploadProgress * 100)}%` } }))) : null, error ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.error }, error) : null, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2276
+ return /* @__PURE__ */ React__namespace.createElement("div", { style: { ...inlineStyles.step, display: "flex", flexDirection: "column", minHeight: "100%" } }, /* @__PURE__ */ React__namespace.createElement("h2", { style: inlineStyles.h2 }, "Review and submit"), /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.p }, "Confirm details, then send your report."), /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.summary }, /* @__PURE__ */ React__namespace.createElement("strong", null, draft.title || "Untitled bug report"), /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.p }, draft.description || "No description provided.")), /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.assets }, assets.map((asset) => /* @__PURE__ */ React__namespace.createElement("div", { key: asset.id, style: inlineStyles.assetCard }, /* @__PURE__ */ React__namespace.createElement("span", { style: inlineStyles.assetType }, asset.type), asset.type === "recording" ? /* @__PURE__ */ React__namespace.createElement("video", { src: asset.previewUrl, controls: true, style: inlineStyles.preview }) : /* @__PURE__ */ React__namespace.createElement("img", { src: asset.previewUrl, alt: `${asset.type} preview`, style: inlineStyles.preview })))), isSubmitting ? /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.uploadProgress, "aria-live": "polite" }, "Uploading assets: ", Math.round(uploadProgress * 100), "%", /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.progressTrack }, /* @__PURE__ */ React__namespace.createElement("div", { style: { ...inlineStyles.progressFill, width: `${Math.round(uploadProgress * 100)}%` } }))) : null, error ? /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.error }, error) : null, /* @__PURE__ */ React__namespace.createElement(
1859
2277
  "div",
1860
2278
  {
1861
2279
  style: {
@@ -1868,7 +2286,7 @@ function StepReview({ onBack }) {
1868
2286
  paddingBottom: "12px"
1869
2287
  }
1870
2288
  },
1871
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2289
+ /* @__PURE__ */ React__namespace.createElement(
1872
2290
  "button",
1873
2291
  {
1874
2292
  type: "button",
@@ -1878,7 +2296,7 @@ function StepReview({ onBack }) {
1878
2296
  },
1879
2297
  "Back"
1880
2298
  ),
1881
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2299
+ /* @__PURE__ */ React__namespace.createElement(
1882
2300
  "button",
1883
2301
  {
1884
2302
  type: "button",
@@ -1895,15 +2313,15 @@ function StepReview({ onBack }) {
1895
2313
  var DOCK_SIDES = ["left", "right", "top", "bottom"];
1896
2314
  function DockIcon({ side }) {
1897
2315
  if (side === "left") {
1898
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 5.5h4.5v13H3.5z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
2316
+ return /* @__PURE__ */ React__namespace.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 5.5h4.5v13H3.5z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
1899
2317
  }
1900
2318
  if (side === "right") {
1901
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M16 5.5h4.5v13H16z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
2319
+ return /* @__PURE__ */ React__namespace.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ React__namespace.createElement("path", { d: "M16 5.5h4.5v13H16z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
1902
2320
  }
1903
2321
  if (side === "top") {
1904
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 5.5h17v4.5h-17z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
2322
+ return /* @__PURE__ */ React__namespace.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 5.5h17v4.5h-17z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
1905
2323
  }
1906
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M3.5 14h17v4.5h-17z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
2324
+ return /* @__PURE__ */ React__namespace.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 5.5h17v13h-17z" }), /* @__PURE__ */ React__namespace.createElement("path", { d: "M3.5 14h17v4.5h-17z", fill: "currentColor", stroke: "none", opacity: "0.85" }));
1907
2325
  }
1908
2326
  function BugReporterShell({ CustomForm, launcherPosition, launcherText, themeMode, buttonColor }) {
1909
2327
  const { config, state, setDockSide, setStep, close, reset } = useBugReporter();
@@ -1917,7 +2335,7 @@ function BugReporterShell({ CustomForm, launcherPosition, launcherText, themeMod
1917
2335
  close();
1918
2336
  };
1919
2337
  const modalTitle = state.step === "success" ? "Report submitted" : "Report a bug";
1920
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(chunk6TCI6T2U_cjs.React.Fragment, null, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(LauncherButton, { position: launcherPosition, text: launcherText, themeMode, buttonColor }), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2338
+ return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement(LauncherButton, { position: launcherPosition, text: launcherText, themeMode, buttonColor }), /* @__PURE__ */ React__namespace.createElement(
1921
2339
  Modal,
1922
2340
  {
1923
2341
  isOpen: state.isOpen,
@@ -1928,9 +2346,9 @@ function BugReporterShell({ CustomForm, launcherPosition, launcherText, themeMod
1928
2346
  zIndex: config.theme.zIndex + 1,
1929
2347
  onRequestClose: requestClose
1930
2348
  },
1931
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.modalHeader }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.dockControls, role: "group", "aria-label": "Dock side" }, DOCK_SIDES.map((side) => {
2349
+ /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.modalHeader }, /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.dockControls, role: "group", "aria-label": "Dock side" }, DOCK_SIDES.map((side) => {
1932
2350
  const isActive = state.dockSide === side;
1933
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2351
+ return /* @__PURE__ */ React__namespace.createElement(
1934
2352
  "button",
1935
2353
  {
1936
2354
  key: side,
@@ -1940,11 +2358,11 @@ function BugReporterShell({ CustomForm, launcherPosition, launcherText, themeMod
1940
2358
  "aria-pressed": isActive,
1941
2359
  "aria-label": `Dock ${side}`
1942
2360
  },
1943
- /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(DockIcon, { side })
2361
+ /* @__PURE__ */ React__namespace.createElement(DockIcon, { side })
1944
2362
  );
1945
- })), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { style: inlineStyles.iconButton, type: "button", onClick: requestClose, "aria-label": "Close bug reporter" }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("path", { d: "M6 6 18 18M18 6 6 18" })))),
1946
- state.step === "describe" ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(StepDescribe, { onNext: nextFromDescribe, CustomForm }) : null,
1947
- state.step === "review" || state.step === "submitting" ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2363
+ })), /* @__PURE__ */ React__namespace.createElement("button", { style: inlineStyles.iconButton, type: "button", onClick: requestClose, "aria-label": "Close bug reporter" }, /* @__PURE__ */ React__namespace.createElement("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", style: inlineStyles.iconSvg }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M6 6 18 18M18 6 6 18" })))),
2364
+ state.step === "describe" ? /* @__PURE__ */ React__namespace.createElement(StepDescribe, { onNext: nextFromDescribe, CustomForm }) : null,
2365
+ state.step === "review" || state.step === "submitting" ? /* @__PURE__ */ React__namespace.createElement(
1948
2366
  StepReview,
1949
2367
  {
1950
2368
  onBack: () => {
@@ -1952,7 +2370,7 @@ function BugReporterShell({ CustomForm, launcherPosition, launcherText, themeMod
1952
2370
  }
1953
2371
  }
1954
2372
  ) : null,
1955
- state.step === "success" ? /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.step }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("h2", { style: inlineStyles.h2 }, "Thanks, report submitted"), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("p", { style: inlineStyles.p }, "Your bug report has been sent successfully."), /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("div", { style: inlineStyles.actions }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement("button", { type: "button", style: getButtonStyle("primary"), onClick: requestClose }, "Close"))) : null
2373
+ state.step === "success" ? /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.step }, /* @__PURE__ */ React__namespace.createElement("h2", { style: inlineStyles.h2 }, "Thanks, report submitted"), /* @__PURE__ */ React__namespace.createElement("p", { style: inlineStyles.p }, "Your bug report has been sent successfully."), /* @__PURE__ */ React__namespace.createElement("div", { style: inlineStyles.actions }, /* @__PURE__ */ React__namespace.createElement("button", { type: "button", style: getButtonStyle("primary"), onClick: requestClose }, "Close"))) : null
1956
2374
  ));
1957
2375
  }
1958
2376
  function BugReporter({
@@ -1965,7 +2383,7 @@ function BugReporter({
1965
2383
  }) {
1966
2384
  var _a, _b;
1967
2385
  const resolvedButtonColor = (_b = buttonColor != null ? buttonColor : (_a = config.theme) == null ? void 0 : _a.primaryColor) != null ? _b : "#3b82f6";
1968
- return /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(BugReporterProvider, { config }, /* @__PURE__ */ chunk6TCI6T2U_cjs.React.createElement(
2386
+ return /* @__PURE__ */ React__namespace.createElement(BugReporterProvider, { config }, /* @__PURE__ */ React__namespace.createElement(
1969
2387
  BugReporterShell,
1970
2388
  {
1971
2389
  CustomForm,
@@ -1977,11 +2395,8 @@ function BugReporter({
1977
2395
  ));
1978
2396
  }
1979
2397
 
1980
- Object.defineProperty(exports, "BugReporterError", {
1981
- enumerable: true,
1982
- get: function () { return chunk6TCI6T2U_cjs.BugReporterError; }
1983
- });
1984
2398
  exports.BugReporter = BugReporter;
2399
+ exports.BugReporterError = BugReporterError;
1985
2400
  exports.BugReporterProvider = BugReporterProvider;
1986
2401
  exports.useBugReporter = useBugReporter;
1987
2402
  //# sourceMappingURL=index.cjs.map