@campfire-interactive/shell-header 0.11.0 → 0.12.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.
Files changed (2) hide show
  1. package/dist/index.js +52 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -604,6 +604,9 @@ function UserMenu({
604
604
  ] });
605
605
  }
606
606
 
607
+ // src/ShellHeader.tsx
608
+ import { useRef as useRef6, useState as useState7 } from "react";
609
+
607
610
  // src/AboutModal.tsx
608
611
  import { useEffect as useEffect4, useState as useState4 } from "react";
609
612
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -872,7 +875,7 @@ function normalizeRect(x0, y0, x1, y1) {
872
875
  h: Math.abs(y1 - y0)
873
876
  };
874
877
  }
875
- function BugReportModal({ config, onClose }) {
878
+ function BugReportModal({ config, initialScreenshot, onClose }) {
876
879
  const [view, setView] = useState6("form");
877
880
  const [title, setTitle] = useState6("");
878
881
  const [description, setDescription] = useState6("");
@@ -886,6 +889,21 @@ function BugReportModal({ config, onClose }) {
886
889
  const displayCanvasRef = useRef4(null);
887
890
  const dragStartRef = useRef4(null);
888
891
  const [mode, setMode] = useState6("crop");
892
+ const initialLoadedRef = useRef4(false);
893
+ useEffect6(() => {
894
+ if (!initialScreenshot || initialLoadedRef.current) return;
895
+ initialLoadedRef.current = true;
896
+ let cancelled = false;
897
+ void blobToCanvas(initialScreenshot).then((image) => {
898
+ if (cancelled) return;
899
+ originalRef.current = cloneCanvas(image);
900
+ workCanvasRef.current = image;
901
+ setView("editor");
902
+ });
903
+ return () => {
904
+ cancelled = true;
905
+ };
906
+ }, [initialScreenshot]);
889
907
  const closeUnlessBusy = useCallback(() => {
890
908
  if (submitState === "submitting" || capturing) return;
891
909
  if (screenshot) URL.revokeObjectURL(screenshot.previewUrl);
@@ -1229,9 +1247,10 @@ function cloneCanvas(source) {
1229
1247
  }
1230
1248
 
1231
1249
  // src/useBugReportShortcut.ts
1232
- import { useEffect as useEffect7, useState as useState7 } from "react";
1233
- function useBugReportShortcut(enabled) {
1234
- const [isOpen, setIsOpen] = useState7(false);
1250
+ import { useEffect as useEffect7, useRef as useRef5 } from "react";
1251
+ function useBugReportShortcut(enabled, onShortcut) {
1252
+ const handlerRef = useRef5(onShortcut);
1253
+ handlerRef.current = onShortcut;
1235
1254
  useEffect7(() => {
1236
1255
  if (!enabled) return;
1237
1256
  function handleKeyDown(e) {
@@ -1244,12 +1263,11 @@ function useBugReportShortcut(enabled) {
1244
1263
  if (tag === "INPUT" || tag === "TEXTAREA" || target.isContentEditable) return;
1245
1264
  }
1246
1265
  e.preventDefault();
1247
- setIsOpen((open) => !open);
1266
+ handlerRef.current();
1248
1267
  }
1249
1268
  document.addEventListener("keydown", handleKeyDown);
1250
1269
  return () => document.removeEventListener("keydown", handleKeyDown);
1251
1270
  }, [enabled]);
1252
- return [isOpen, setIsOpen];
1253
1271
  }
1254
1272
 
1255
1273
  // src/assets/campfire-wordmark.png
@@ -1287,7 +1305,21 @@ function ShellHeader({
1287
1305
  }) {
1288
1306
  const currentApp = appCatalog.find((a) => a.id === appId);
1289
1307
  const [aboutOpen, setAboutOpen] = useAboutShortcut(about !== void 0);
1290
- const [bugOpen, setBugOpen] = useBugReportShortcut(bugReport !== void 0);
1308
+ const [bugOpen, setBugOpen] = useState7(false);
1309
+ const [bugShot, setBugShot] = useState7(null);
1310
+ const bugCaptureBusy = useRef6(false);
1311
+ useBugReportShortcut(bugReport !== void 0, () => {
1312
+ if (bugOpen) {
1313
+ setBugOpen(false);
1314
+ return;
1315
+ }
1316
+ if (bugCaptureBusy.current) return;
1317
+ bugCaptureBusy.current = true;
1318
+ captureTabScreenshot().then((shot) => setBugShot(shot)).catch(() => setBugShot(null)).finally(() => {
1319
+ bugCaptureBusy.current = false;
1320
+ setBugOpen(true);
1321
+ });
1322
+ });
1291
1323
  const brandStyle = brandWidth ? { width: `${brandWidth}px`, flexShrink: 0, boxSizing: "border-box" } : void 0;
1292
1324
  return /* @__PURE__ */ jsxs7(Fragment4, { children: [
1293
1325
  /* @__PURE__ */ jsxs7("header", { className: "cfi-sh-header", children: [
@@ -1332,17 +1364,27 @@ function ShellHeader({
1332
1364
  ] })
1333
1365
  ] }),
1334
1366
  about && aboutOpen && /* @__PURE__ */ jsx7(AboutModal, { about, onClose: () => setAboutOpen(false) }),
1335
- bugReport && bugOpen && /* @__PURE__ */ jsx7(BugReportModal, { config: bugReport, onClose: () => setBugOpen(false) })
1367
+ bugReport && bugOpen && /* @__PURE__ */ jsx7(
1368
+ BugReportModal,
1369
+ {
1370
+ config: bugReport,
1371
+ initialScreenshot: bugShot,
1372
+ onClose: () => {
1373
+ setBugOpen(false);
1374
+ setBugShot(null);
1375
+ }
1376
+ }
1377
+ )
1336
1378
  ] });
1337
1379
  }
1338
1380
 
1339
1381
  // src/LocaleSwitcher.tsx
1340
- import { useState as useState8, useRef as useRef5, useEffect as useEffect8 } from "react";
1382
+ import { useState as useState8, useRef as useRef7, useEffect as useEffect8 } from "react";
1341
1383
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1342
1384
  function LocaleSwitcher({ currentLocale, supportedLocales, onLocaleChange }) {
1343
1385
  const [open, setOpen] = useState8(false);
1344
1386
  const [updating, setUpdating] = useState8(false);
1345
- const ref = useRef5(null);
1387
+ const ref = useRef7(null);
1346
1388
  useEffect8(() => {
1347
1389
  function handleClickOutside(e) {
1348
1390
  if (ref.current && !ref.current.contains(e.target)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campfire-interactive/shell-header",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Shared shell header with app switcher for Campfire Suite",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",