@designfever/web-review-kit 0.7.0 → 0.7.2

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.
@@ -5573,7 +5573,10 @@ var buildTargetSrc = (target) => {
5573
5573
  return `${url.pathname}${url.search}${url.hash}`;
5574
5574
  };
5575
5575
  var getFrameRouteTarget = (targetWindow, reviewPathPrefix) => {
5576
- return normalizeTarget(targetWindow.location.pathname, reviewPathPrefix);
5576
+ return normalizeTarget(
5577
+ `${targetWindow.location.pathname}${targetWindow.location.search}${targetWindow.location.hash}`,
5578
+ reviewPathPrefix
5579
+ );
5577
5580
  };
5578
5581
  var updateShellUrl = (target, size, source) => {
5579
5582
  const url = new URL(window.location.href);
@@ -5748,7 +5751,7 @@ var ABOUT_SECTIONS = [
5748
5751
  },
5749
5752
  {
5750
5753
  title: "Figma token",
5751
- body: "Add a browser-safe Figma token in Settings only when the host page already supports the Figma overlay helper. The package stores it in localStorage as figma-token and does not own a server-side Figma integration."
5754
+ body: "Project owners can set FIGMA_TOKEN on the server. Reviewers who cannot change env can add a browser-local Figma token in Settings; it is stored as figma-token and used only as an image-store fallback."
5752
5755
  },
5753
5756
  {
5754
5757
  title: "User ID",
@@ -6048,12 +6051,13 @@ var writeStoredFigmaToken = (token) => {
6048
6051
  return;
6049
6052
  }
6050
6053
  };
6051
- var getStoredReviewUserId = () => {
6052
- if (typeof window === "undefined") return "";
6054
+ var getStoredReviewUserId = (fallback = "") => {
6055
+ const normalizedFallback = fallback.trim();
6056
+ if (typeof window === "undefined") return normalizedFallback;
6053
6057
  try {
6054
- return window.localStorage.getItem(REVIEW_USER_ID_STORAGE_KEY) ?? "";
6058
+ return window.localStorage.getItem(REVIEW_USER_ID_STORAGE_KEY)?.trim() || normalizedFallback;
6055
6059
  } catch {
6056
- return "";
6060
+ return normalizedFallback;
6057
6061
  }
6058
6062
  };
6059
6063
  var writeStoredReviewUserId = (userId) => {
@@ -17547,15 +17551,18 @@ var useReviewFigmaImages = ({
17547
17551
  // src/react-shell/hooks/use.review.settings.ts
17548
17552
  var import_react20 = require("react");
17549
17553
  var useReviewSettings = ({
17554
+ defaultReviewUserId = "",
17550
17555
  onCancelReviewMode,
17551
17556
  onCloseInitialPrompt,
17552
17557
  onCloseSitemap,
17553
17558
  onReloadTargetFrame
17554
17559
  }) => {
17555
17560
  const [figmaTokenDraft, setFigmaTokenDraft] = (0, import_react20.useState)(getStoredFigmaToken);
17556
- const [reviewUserId, setReviewUserId] = (0, import_react20.useState)(getStoredReviewUserId);
17561
+ const [reviewUserId, setReviewUserId] = (0, import_react20.useState)(
17562
+ () => getStoredReviewUserId(defaultReviewUserId)
17563
+ );
17557
17564
  const [reviewUserIdDraft, setReviewUserIdDraft] = (0, import_react20.useState)(
17558
- getStoredReviewUserId
17565
+ () => getStoredReviewUserId(defaultReviewUserId)
17559
17566
  );
17560
17567
  const [reviewTheme, setReviewTheme] = (0, import_react20.useState)(getStoredReviewTheme);
17561
17568
  const [reviewThemeDraft, setReviewThemeDraft] = (0, import_react20.useState)(getStoredReviewTheme);
@@ -17576,7 +17583,7 @@ var useReviewSettings = ({
17576
17583
  onCloseSitemap();
17577
17584
  onCloseInitialPrompt();
17578
17585
  setFigmaTokenDraft(getStoredFigmaToken());
17579
- setReviewUserIdDraft(getStoredReviewUserId());
17586
+ setReviewUserIdDraft(getStoredReviewUserId(defaultReviewUserId));
17580
17587
  setReviewThemeDraft(reviewTheme);
17581
17588
  setFigmaSettingsStatus("");
17582
17589
  setIsFigmaTokenVisible(false);
@@ -17586,6 +17593,7 @@ var useReviewSettings = ({
17586
17593
  onCancelReviewMode,
17587
17594
  onCloseInitialPrompt,
17588
17595
  onCloseSitemap,
17596
+ defaultReviewUserId,
17589
17597
  reviewTheme
17590
17598
  ]);
17591
17599
  const saveReviewSettings = (0, import_react20.useCallback)(
@@ -17612,6 +17620,12 @@ var useReviewSettings = ({
17612
17620
  },
17613
17621
  [closeFigmaSettings, onReloadTargetFrame]
17614
17622
  );
17623
+ (0, import_react20.useEffect)(() => {
17624
+ if (getStoredReviewUserId()) return;
17625
+ const nextDefaultUserId = defaultReviewUserId.trim();
17626
+ setReviewUserId(nextDefaultUserId);
17627
+ setReviewUserIdDraft(nextDefaultUserId);
17628
+ }, [defaultReviewUserId]);
17615
17629
  (0, import_react20.useEffect)(() => {
17616
17630
  if (typeof window === "undefined" || !window.matchMedia) return void 0;
17617
17631
  const query = window.matchMedia("(prefers-color-scheme: light)");
@@ -18012,6 +18026,7 @@ function normalizeLegacyAdapterMap(adapters) {
18012
18026
  statusOptions: [...REVIEW_WORKFLOW_STATUS_OPTIONS],
18013
18027
  assigneeTitle: DEFAULT_ASSIGNEE_TITLE,
18014
18028
  assigneeOptions: [],
18029
+ defaultUserId: adapters.defaultUserId?.trim() ?? "",
18015
18030
  updateStatus: ({ id, status }) => adapters.local.update(id, { status }),
18016
18031
  updateAssignee: ({ id, assigneeId, assigneeName }) => adapters.local.update(id, { assigneeId, assigneeName }),
18017
18032
  syncSubmission: ({ id, patch }) => adapters.local.update(id, patch),
@@ -18026,6 +18041,7 @@ function normalizeLegacyAdapterMap(adapters) {
18026
18041
  statusOptions: [...REVIEW_WORKFLOW_STATUS_OPTIONS],
18027
18042
  assigneeTitle: DEFAULT_ASSIGNEE_TITLE,
18028
18043
  assigneeOptions: [],
18044
+ defaultUserId: adapters.defaultUserId?.trim() ?? "",
18029
18045
  updateStatus: ({ id, status }) => adapters.remote?.update(id, { status }) ?? Promise.reject(new Error("Remote adapter is not available.")),
18030
18046
  updateAssignee: ({ id, assigneeId, assigneeName }) => adapters.remote?.update(id, { assigneeId, assigneeName }) ?? Promise.reject(new Error("Remote adapter is not available.")),
18031
18047
  writeModes: [],
@@ -18048,6 +18064,7 @@ function normalizeShellAdapter(adapterConfig) {
18048
18064
  };
18049
18065
  const assigneeTitle = adapterConfig.assigneeTitle?.trim() || DEFAULT_ASSIGNEE_TITLE;
18050
18066
  const assigneeOptions = [...adapterConfig.assigneeOptions ?? []];
18067
+ const defaultUserId = adapterConfig.defaultUserId?.trim() ?? "";
18051
18068
  const updateAdapter = adapterConfig.update;
18052
18069
  const updateStatus = adapterConfig.updateStatus ? adapterConfig.updateStatus : updateAdapter ? ({ id, status }) => updateAdapter(id, { status }) : void 0;
18053
18070
  const updateAssignee = adapterConfig.updateAssignee ? adapterConfig.updateAssignee : updateAdapter ? ({ id, assigneeId, assigneeName, assigneeOption }) => updateAdapter(id, {
@@ -18064,6 +18081,7 @@ function normalizeShellAdapter(adapterConfig) {
18064
18081
  statusOptions,
18065
18082
  assigneeTitle,
18066
18083
  assigneeOptions,
18084
+ defaultUserId,
18067
18085
  updateStatus,
18068
18086
  updateAssignee,
18069
18087
  syncSubmission: adapterConfig.syncSubmission,
@@ -18620,8 +18638,10 @@ var ReviewShell = ({
18620
18638
  });
18621
18639
  const sourceShortcutCleanupRef = (0, import_react24.useRef)(null);
18622
18640
  const sourceInspectorInteractionRef = (0, import_react24.useRef)(false);
18641
+ const sectionOutlineCountRef = (0, import_react24.useRef)(0);
18623
18642
  const [sourceInspectorState, setSourceInspectorState] = (0, import_react24.useState)(null);
18624
18643
  const [sectionOutline, setSectionOutline] = (0, import_react24.useState)(null);
18644
+ const [targetFrameLoadVersion, setTargetFrameLoadVersion] = (0, import_react24.useState)(0);
18625
18645
  const [sectionOutlineFilter, setSectionOutlineFilter] = (0, import_react24.useState)(
18626
18646
  () => getStoredSourceTreeFilter()
18627
18647
  );
@@ -18723,6 +18743,9 @@ var ReviewShell = ({
18723
18743
  [filteredSectionOutline]
18724
18744
  );
18725
18745
  const isSectionOutlineFiltering = sectionOutlineFilterTerms.length > 0;
18746
+ (0, import_react24.useEffect)(() => {
18747
+ sectionOutlineCountRef.current = sectionOutlineTotalCount;
18748
+ }, [sectionOutlineTotalCount]);
18726
18749
  const {
18727
18750
  activeItems,
18728
18751
  activeRemainingItemCount,
@@ -18874,6 +18897,7 @@ var ReviewShell = ({
18874
18897
  setReviewThemeDraft,
18875
18898
  setReviewUserIdDraft
18876
18899
  } = useReviewSettings({
18900
+ defaultReviewUserId: activeAdapterEntry.defaultUserId,
18877
18901
  onCancelReviewMode: cancelReviewMode,
18878
18902
  onCloseInitialPrompt: closePromptModal,
18879
18903
  onCloseSitemap: closeSitemap,
@@ -19303,32 +19327,78 @@ var ReviewShell = ({
19303
19327
  const setSectionOutlineWithDefaultCollapse = (0, import_react24.useCallback)(
19304
19328
  (nextSectionOutline) => {
19305
19329
  setSectionOutline(nextSectionOutline);
19330
+ sectionOutlineCountRef.current = getSectionOutlineEntryCount(nextSectionOutline);
19306
19331
  setCollapsedSectionOutlineIds(
19307
19332
  getDefaultCollapsedSectionOutlineIds(nextSectionOutline)
19308
19333
  );
19309
19334
  },
19310
19335
  []
19311
19336
  );
19337
+ const refreshCurrentSectionOutline = (0, import_react24.useCallback)(
19338
+ (resetCollapse = false) => {
19339
+ const nextSectionOutline = getCurrentSectionOutline();
19340
+ if (!nextSectionOutline) return false;
19341
+ setSectionOutline(nextSectionOutline);
19342
+ const nextCount = getSectionOutlineEntryCount(nextSectionOutline);
19343
+ const shouldResetCollapse = resetCollapse || sectionOutlineCountRef.current === 0;
19344
+ sectionOutlineCountRef.current = nextCount;
19345
+ if (shouldResetCollapse) {
19346
+ setCollapsedSectionOutlineIds(
19347
+ getDefaultCollapsedSectionOutlineIds(nextSectionOutline)
19348
+ );
19349
+ }
19350
+ return true;
19351
+ },
19352
+ [getCurrentSectionOutline]
19353
+ );
19312
19354
  (0, import_react24.useEffect)(() => {
19313
19355
  if (sidePanel !== "source" || !isListVisible) return void 0;
19314
19356
  const refreshSectionOutline = () => {
19315
- const nextSectionOutline = getCurrentSectionOutline();
19316
- if (!nextSectionOutline) return;
19317
- setSectionOutlineWithDefaultCollapse(nextSectionOutline);
19357
+ refreshCurrentSectionOutline(true);
19318
19358
  };
19319
19359
  const animationFrame = window.requestAnimationFrame(refreshSectionOutline);
19320
19360
  const firstTimeout = window.setTimeout(refreshSectionOutline, 120);
19321
19361
  const secondTimeout = window.setTimeout(refreshSectionOutline, 500);
19362
+ const thirdTimeout = window.setTimeout(refreshSectionOutline, 1200);
19322
19363
  return () => {
19323
19364
  window.cancelAnimationFrame(animationFrame);
19324
19365
  window.clearTimeout(firstTimeout);
19325
19366
  window.clearTimeout(secondTimeout);
19367
+ window.clearTimeout(thirdTimeout);
19326
19368
  };
19327
19369
  }, [
19328
- getCurrentSectionOutline,
19329
19370
  isListVisible,
19330
- setSectionOutlineWithDefaultCollapse,
19371
+ refreshCurrentSectionOutline,
19331
19372
  sidePanel,
19373
+ targetFrameLoadVersion,
19374
+ targetSrc
19375
+ ]);
19376
+ (0, import_react24.useEffect)(() => {
19377
+ if (sidePanel !== "source" || !isListVisible) return void 0;
19378
+ const frameDocument = iframeRef.current?.contentDocument;
19379
+ const body = frameDocument?.body;
19380
+ if (!body) return void 0;
19381
+ let refreshTimeout = null;
19382
+ const scheduleRefresh = () => {
19383
+ if (refreshTimeout) window.clearTimeout(refreshTimeout);
19384
+ refreshTimeout = window.setTimeout(() => {
19385
+ refreshTimeout = null;
19386
+ refreshCurrentSectionOutline(false);
19387
+ }, 80);
19388
+ };
19389
+ const observer = new MutationObserver(scheduleRefresh);
19390
+ observer.observe(body, { childList: true, subtree: true });
19391
+ scheduleRefresh();
19392
+ return () => {
19393
+ if (refreshTimeout) window.clearTimeout(refreshTimeout);
19394
+ observer.disconnect();
19395
+ };
19396
+ }, [
19397
+ iframeRef,
19398
+ isListVisible,
19399
+ refreshCurrentSectionOutline,
19400
+ sidePanel,
19401
+ targetFrameLoadVersion,
19332
19402
  targetSrc
19333
19403
  ]);
19334
19404
  const toggleQaPanel = (0, import_react24.useCallback)(() => {
@@ -19342,16 +19412,12 @@ var ReviewShell = ({
19342
19412
  return;
19343
19413
  }
19344
19414
  setSidePanel("source");
19345
- const nextSectionOutline = getCurrentSectionOutline();
19346
- if (nextSectionOutline) {
19347
- setSectionOutlineWithDefaultCollapse(nextSectionOutline);
19348
- }
19415
+ refreshCurrentSectionOutline(true);
19349
19416
  setIsListVisible(true);
19350
19417
  }, [
19351
- getCurrentSectionOutline,
19352
19418
  isListVisible,
19353
19419
  isSourceInspectorEnabled,
19354
- setSectionOutlineWithDefaultCollapse,
19420
+ refreshCurrentSectionOutline,
19355
19421
  setIsListVisible,
19356
19422
  sidePanel
19357
19423
  ]);
@@ -19658,6 +19724,7 @@ var ReviewShell = ({
19658
19724
  return cleanupSourceOpenShortcut;
19659
19725
  }, [cleanupSourceOpenShortcut]);
19660
19726
  const loadTargetFrame = (0, import_react24.useCallback)(() => {
19727
+ setTargetFrameLoadVersion((currentVersion) => currentVersion + 1);
19661
19728
  initReviewKit();
19662
19729
  refreshTargetFigmaConfig();
19663
19730
  setTargetFigmaOverlayLocked(
@@ -19666,20 +19733,16 @@ var ReviewShell = ({
19666
19733
  );
19667
19734
  bindSourceOpenShortcut();
19668
19735
  if (sidePanel === "source" && isListVisible) {
19669
- const nextSectionOutline = getCurrentSectionOutline();
19670
- if (nextSectionOutline) {
19671
- setSectionOutlineWithDefaultCollapse(nextSectionOutline);
19672
- }
19736
+ refreshCurrentSectionOutline(true);
19673
19737
  }
19674
19738
  }, [
19675
19739
  bindSourceOpenShortcut,
19676
- getCurrentSectionOutline,
19677
19740
  iframeRef,
19678
19741
  initReviewKit,
19679
19742
  isListVisible,
19680
19743
  mode,
19681
19744
  refreshTargetFigmaConfig,
19682
- setSectionOutlineWithDefaultCollapse,
19745
+ refreshCurrentSectionOutline,
19683
19746
  sidePanel
19684
19747
  ]);
19685
19748
  (0, import_react24.useEffect)(() => {