hyperframes 0.7.16 → 0.7.18

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.
@@ -7311,16 +7311,16 @@ function buildCompositionThumbnailUrl({
7311
7311
  }) {
7312
7312
  const thumbnailBase = previewUrl.replace("/preview/comp/", "/thumbnail/").replace(/\/preview$/, "/thumbnail/index.html");
7313
7313
  const midTime = seekTime + duration / 2;
7314
- const thumbnailUrl = new URL(thumbnailBase, origin);
7315
- thumbnailUrl.searchParams.set("t", midTime.toFixed(2));
7316
- thumbnailUrl.searchParams.set("v", THUMBNAIL_URL_VERSION);
7314
+ const thumbnailUrl2 = new URL(thumbnailBase, origin);
7315
+ thumbnailUrl2.searchParams.set("t", midTime.toFixed(2));
7316
+ thumbnailUrl2.searchParams.set("v", THUMBNAIL_URL_VERSION);
7317
7317
  if (selector) {
7318
- thumbnailUrl.searchParams.set("selector", selector);
7318
+ thumbnailUrl2.searchParams.set("selector", selector);
7319
7319
  if (selectorIndex != null && selectorIndex > 0) {
7320
- thumbnailUrl.searchParams.set("selectorIndex", String(selectorIndex));
7320
+ thumbnailUrl2.searchParams.set("selectorIndex", String(selectorIndex));
7321
7321
  }
7322
7322
  }
7323
- return thumbnailUrl.toString();
7323
+ return thumbnailUrl2.toString();
7324
7324
  }
7325
7325
  var CompositionThumbnail = memo13(function CompositionThumbnail2({
7326
7326
  previewUrl,
@@ -19739,7 +19739,7 @@ var FileTree = memo24(function FileTree2({
19739
19739
  });
19740
19740
 
19741
19741
  // src/App.tsx
19742
- import { useState as useState91, useCallback as useCallback106, useRef as useRef88, useMemo as useMemo37, useEffect as useEffect65, useLayoutEffect as useLayoutEffect3 } from "react";
19742
+ import { useState as useState91, useCallback as useCallback106, useRef as useRef89, useMemo as useMemo37, useEffect as useEffect66, useLayoutEffect as useLayoutEffect3 } from "react";
19743
19743
 
19744
19744
  // src/components/renders/useRenderQueue.ts
19745
19745
  import { useState as useState36, useEffect as useEffect26, useCallback as useCallback32, useRef as useRef34, useMemo as useMemo18 } from "react";
@@ -23659,7 +23659,10 @@ function useDomSelection({
23659
23659
  }
23660
23660
  if (!doc) return;
23661
23661
  const element = findElementForSelection(doc, selection, activeCompPath);
23662
- if (!element) return;
23662
+ if (!element) {
23663
+ applyDomSelection(null, { revealPanel: false });
23664
+ return;
23665
+ }
23663
23666
  const nextSelection = await buildDomSelectionFromTarget(element);
23664
23667
  if (nextSelection) {
23665
23668
  applyDomSelection(nextSelection, {
@@ -29375,6 +29378,134 @@ function useGsapAwareEditing({
29375
29378
  };
29376
29379
  }
29377
29380
 
29381
+ // src/hooks/useStudioSelectionPublisher.ts
29382
+ import { useEffect as useEffect35, useRef as useRef55 } from "react";
29383
+
29384
+ // src/utils/studioSelectionSnapshot.ts
29385
+ function round32(value) {
29386
+ return Math.round(value * 1e3) / 1e3;
29387
+ }
29388
+ function thumbnailUrl({
29389
+ projectId,
29390
+ selection,
29391
+ currentTime
29392
+ }) {
29393
+ const compPath = encodeURIComponent(
29394
+ selection.compositionPath || selection.sourceFile || "index.html"
29395
+ );
29396
+ const params = new URLSearchParams({
29397
+ t: String(round32(currentTime)),
29398
+ format: "png"
29399
+ });
29400
+ if (selection.selector) params.set("selector", selection.selector);
29401
+ if (selection.selectorIndex != null) params.set("selectorIndex", String(selection.selectorIndex));
29402
+ return `/api/projects/${encodeURIComponent(projectId)}/thumbnail/${compPath}?${params.toString()}`;
29403
+ }
29404
+ function buildStudioSelectionSnapshot({
29405
+ projectId,
29406
+ selection,
29407
+ currentTime
29408
+ }) {
29409
+ return {
29410
+ schemaVersion: 1,
29411
+ projectId,
29412
+ compositionPath: selection.compositionPath,
29413
+ sourceFile: selection.sourceFile,
29414
+ currentTime: round32(currentTime),
29415
+ target: {
29416
+ id: selection.id,
29417
+ hfId: selection.hfId,
29418
+ selector: selection.selector,
29419
+ selectorIndex: selection.selectorIndex
29420
+ },
29421
+ label: selection.label,
29422
+ tagName: selection.tagName,
29423
+ boundingBox: {
29424
+ x: round32(selection.boundingBox.x),
29425
+ y: round32(selection.boundingBox.y),
29426
+ width: round32(selection.boundingBox.width),
29427
+ height: round32(selection.boundingBox.height)
29428
+ },
29429
+ textContent: selection.textContent,
29430
+ dataAttributes: { ...selection.dataAttributes },
29431
+ inlineStyles: { ...selection.inlineStyles },
29432
+ computedStyles: { ...selection.computedStyles },
29433
+ textFields: selection.textFields.map((field) => ({
29434
+ key: field.key,
29435
+ label: field.label,
29436
+ value: field.value,
29437
+ tagName: field.tagName,
29438
+ source: field.source
29439
+ })),
29440
+ capabilities: { ...selection.capabilities },
29441
+ thumbnailUrl: thumbnailUrl({ projectId, selection, currentTime })
29442
+ };
29443
+ }
29444
+
29445
+ // src/hooks/useStudioSelectionPublisher.ts
29446
+ function reportSelectionPublishError(error) {
29447
+ if (error instanceof Error && error.name === "AbortError") return;
29448
+ const errorName = error instanceof Error ? error.name : typeof error;
29449
+ const errorMessage = error instanceof Error ? error.message : String(error);
29450
+ trackStudioEvent("studio_selection_publish_failed", {
29451
+ error_name: errorName,
29452
+ error_message: errorMessage.slice(0, 500)
29453
+ });
29454
+ console.warn("[Studio] Failed to update agent selection context", error);
29455
+ }
29456
+ function putSelection(projectId, selection, signal) {
29457
+ return fetch(`/api/projects/${encodeURIComponent(projectId)}/selection`, {
29458
+ method: "PUT",
29459
+ headers: { "Content-Type": "application/json" },
29460
+ body: JSON.stringify({ selection }),
29461
+ signal
29462
+ }).then(() => void 0);
29463
+ }
29464
+ function useStudioSelectionPublisher({
29465
+ projectId,
29466
+ domEditSelection,
29467
+ domEditSelectionRef,
29468
+ refreshKey,
29469
+ previewDocumentVersion,
29470
+ refreshDomEditSelectionFromPreview
29471
+ }) {
29472
+ const lastSelectionRefreshKeyRef = useRef55(refreshKey);
29473
+ const pendingSelectionRefreshKeyRef = useRef55(null);
29474
+ useEffect35(() => {
29475
+ if (!projectId) return;
29476
+ const selection = domEditSelection?.element.isConnected ? buildStudioSelectionSnapshot({
29477
+ projectId,
29478
+ selection: domEditSelection,
29479
+ currentTime: usePlayerStore.getState().currentTime
29480
+ }) : null;
29481
+ const controller = new AbortController();
29482
+ void putSelection(projectId, selection, controller.signal).catch(reportSelectionPublishError);
29483
+ return () => controller.abort();
29484
+ }, [domEditSelection, projectId]);
29485
+ useEffect35(() => {
29486
+ if (!projectId) return;
29487
+ return () => {
29488
+ void putSelection(projectId, null).catch(reportSelectionPublishError);
29489
+ };
29490
+ }, [projectId]);
29491
+ useEffect35(() => {
29492
+ if (lastSelectionRefreshKeyRef.current === refreshKey) return;
29493
+ lastSelectionRefreshKeyRef.current = refreshKey;
29494
+ pendingSelectionRefreshKeyRef.current = domEditSelectionRef.current ? refreshKey : null;
29495
+ if (!projectId || !domEditSelectionRef.current) return;
29496
+ const controller = new AbortController();
29497
+ void putSelection(projectId, null, controller.signal).catch(reportSelectionPublishError);
29498
+ return () => controller.abort();
29499
+ }, [domEditSelectionRef, projectId, refreshKey]);
29500
+ useEffect35(() => {
29501
+ if (pendingSelectionRefreshKeyRef.current === null) return;
29502
+ pendingSelectionRefreshKeyRef.current = null;
29503
+ const selection = domEditSelectionRef.current;
29504
+ if (!selection) return;
29505
+ void refreshDomEditSelectionFromPreview(selection);
29506
+ }, [domEditSelectionRef, previewDocumentVersion, refreshDomEditSelectionFromPreview]);
29507
+ }
29508
+
29378
29509
  // src/hooks/useDomEditSession.ts
29379
29510
  function useDomEditSession({
29380
29511
  projectId,
@@ -29402,6 +29533,7 @@ function useDomEditSession({
29402
29533
  projectIdRef,
29403
29534
  previewIframe,
29404
29535
  refreshKey,
29536
+ previewDocumentVersion,
29405
29537
  rightPanelTab,
29406
29538
  applyStudioManualEditsToPreviewRef,
29407
29539
  syncPreviewHistoryHotkey,
@@ -29467,6 +29599,14 @@ function useDomEditSession({
29467
29599
  domEditSelectionRef,
29468
29600
  domEditSelection
29469
29601
  });
29602
+ useStudioSelectionPublisher({
29603
+ projectId,
29604
+ domEditSelection,
29605
+ domEditSelectionRef,
29606
+ refreshKey,
29607
+ previewDocumentVersion,
29608
+ refreshDomEditSelectionFromPreview
29609
+ });
29470
29610
  const { version: gsapCacheVersion, bump: bumpGsapCache } = useGsapCacheVersion();
29471
29611
  const {
29472
29612
  commitMutation: gsapCommitMutation,
@@ -29820,7 +29960,7 @@ function useDomEditSession({
29820
29960
  }
29821
29961
 
29822
29962
  // src/hooks/useSdkSession.ts
29823
- import { useState as useState47, useEffect as useEffect35, useCallback as useCallback65 } from "react";
29963
+ import { useState as useState47, useEffect as useEffect36, useCallback as useCallback65 } from "react";
29824
29964
  import { openComposition } from "@hyperframes/sdk";
29825
29965
  async function readProjectFileOptional(projectId, path) {
29826
29966
  if (path.includes("\0") || path.includes("..")) return void 0;
@@ -29850,7 +29990,7 @@ function shouldReloadOnFileChange(activeCompPath, content, withinSuppressWindow)
29850
29990
  function useSdkSession(projectId, activeCompPath, domEditSaveTimestampRef) {
29851
29991
  const [session, setSession] = useState47(null);
29852
29992
  const [reloadToken, setReloadToken] = useState47(0);
29853
- useEffect35(() => {
29993
+ useEffect36(() => {
29854
29994
  if (!activeCompPath) return;
29855
29995
  const compPath = activeCompPath;
29856
29996
  const readProjectId = projectId ?? null;
@@ -29875,7 +30015,7 @@ function useSdkSession(projectId, activeCompPath, domEditSaveTimestampRef) {
29875
30015
  es.addEventListener("file-change", handler);
29876
30016
  return () => es.close();
29877
30017
  }, [activeCompPath, projectId]);
29878
- useEffect35(() => {
30018
+ useEffect36(() => {
29879
30019
  if (!projectId || !activeCompPath) {
29880
30020
  setSession(null);
29881
30021
  return;
@@ -29904,13 +30044,13 @@ function useSdkSession(projectId, activeCompPath, domEditSaveTimestampRef) {
29904
30044
  }
29905
30045
 
29906
30046
  // src/hooks/useSdkSelectionSync.ts
29907
- import { useEffect as useEffect36 } from "react";
30047
+ import { useEffect as useEffect37 } from "react";
29908
30048
  function toHfIds(group, primary) {
29909
30049
  const source = group.length > 0 ? group : primary ? [primary] : [];
29910
30050
  return source.flatMap((s) => s.hfId ? [s.hfId] : []);
29911
30051
  }
29912
30052
  function useSdkSelectionSync(session, domEditSelection, domEditGroupSelections) {
29913
- useEffect36(() => {
30053
+ useEffect37(() => {
29914
30054
  if (!session) return;
29915
30055
  session.setSelection(toHfIds(domEditGroupSelections, domEditSelection));
29916
30056
  }, [session, domEditSelection, domEditGroupSelections]);
@@ -30149,7 +30289,7 @@ function useBlockHandlers({
30149
30289
  }
30150
30290
 
30151
30291
  // src/hooks/useAppHotkeys.ts
30152
- import { useCallback as useCallback67, useEffect as useEffect37, useRef as useRef55 } from "react";
30292
+ import { useCallback as useCallback67, useEffect as useEffect38, useRef as useRef56 } from "react";
30153
30293
  function iframeContentWindow(iframe) {
30154
30294
  try {
30155
30295
  return iframe?.contentWindow ?? null;
@@ -30357,8 +30497,8 @@ function useAppHotkeys({
30357
30497
  activeCompPath,
30358
30498
  forceReloadSdkSession
30359
30499
  }) {
30360
- const previewHotkeyWindowRef = useRef55(null);
30361
- const previewHistoryCleanupRef = useRef55(null);
30500
+ const previewHotkeyWindowRef = useRef56(null);
30501
+ const previewHistoryCleanupRef = useRef56(null);
30362
30502
  const handleTimelineToggleHotkey = useCallback67(
30363
30503
  (event) => {
30364
30504
  if (!shouldHandleTimelineToggleHotkey(event)) return;
@@ -30416,7 +30556,7 @@ function useAppHotkeys({
30416
30556
  );
30417
30557
  const handleUndo = useCallback67(() => applyHistory("undo"), [applyHistory]);
30418
30558
  const handleRedo = useCallback67(() => applyHistory("redo"), [applyHistory]);
30419
- const cbRef = useRef55(null);
30559
+ const cbRef = useRef56(null);
30420
30560
  cbRef.current = {
30421
30561
  toggleTimelineVisibility,
30422
30562
  handleTimelineElementDelete,
@@ -30450,7 +30590,7 @@ function useAppHotkeys({
30450
30590
  }
30451
30591
  if (!isEditableTarget(event.target)) dispatchPlainKey(event, key, cb);
30452
30592
  }, []);
30453
- useEffect37(() => {
30593
+ useEffect38(() => {
30454
30594
  window.addEventListener("keydown", handleAppKeyDown, true);
30455
30595
  return () => window.removeEventListener("keydown", handleAppKeyDown, true);
30456
30596
  }, [handleAppKeyDown]);
@@ -30468,7 +30608,7 @@ function useAppHotkeys({
30468
30608
  },
30469
30609
  [handleAppKeyDown]
30470
30610
  );
30471
- useEffect37(
30611
+ useEffect38(
30472
30612
  () => () => {
30473
30613
  safeRemoveListener(
30474
30614
  previewHotkeyWindowRef.current,
@@ -30509,7 +30649,7 @@ function useAppHotkeys({
30509
30649
  },
30510
30650
  [handleHistoryHotkey]
30511
30651
  );
30512
- useEffect37(
30652
+ useEffect38(
30513
30653
  () => () => {
30514
30654
  previewHistoryCleanupRef.current?.();
30515
30655
  previewHistoryCleanupRef.current = null;
@@ -30526,7 +30666,7 @@ function useAppHotkeys({
30526
30666
  }
30527
30667
 
30528
30668
  // src/hooks/useClipboard.ts
30529
- import { useCallback as useCallback68, useRef as useRef56 } from "react";
30669
+ import { useCallback as useCallback68, useRef as useRef57 } from "react";
30530
30670
 
30531
30671
  // src/utils/clipboardPayload.ts
30532
30672
  function insertAsSibling(source, newHtml, selector, selectorIndex) {
@@ -30641,8 +30781,8 @@ function useClipboard({
30641
30781
  handleDomEditElementDelete,
30642
30782
  previewIframeRef
30643
30783
  }) {
30644
- const clipboardRef = useRef56(null);
30645
- const projectIdRef = useRef56(projectId);
30784
+ const clipboardRef = useRef57(null);
30785
+ const projectIdRef = useRef57(projectId);
30646
30786
  projectIdRef.current = projectId;
30647
30787
  const handleCopy = useCallback68(() => {
30648
30788
  const { selectedElementId, elements } = usePlayerStore.getState();
@@ -30786,7 +30926,7 @@ function selectedKeyframePercentagesForElement(selectedKeyframes, activeElementI
30786
30926
  }
30787
30927
 
30788
30928
  // src/hooks/useCaptionDetection.ts
30789
- import { useEffect as useEffect38 } from "react";
30929
+ import { useEffect as useEffect39 } from "react";
30790
30930
 
30791
30931
  // src/captions/types.ts
30792
30932
  var DEFAULT_STYLE = {
@@ -31038,7 +31178,7 @@ function useCaptionDetection({
31038
31178
  captionSync,
31039
31179
  setRightCollapsed
31040
31180
  }) {
31041
- useEffect38(() => {
31181
+ useEffect39(() => {
31042
31182
  if (!projectId) return;
31043
31183
  let activating = false;
31044
31184
  const tryActivateCaptions = () => {
@@ -31117,7 +31257,7 @@ function useCaptionDetection({
31117
31257
  window.removeEventListener("message", handleMessage);
31118
31258
  };
31119
31259
  }, [activeCompPath, projectId, compIdToSrc, captionSync, previewIframeRef]);
31120
- useEffect38(() => {
31260
+ useEffect39(() => {
31121
31261
  if (captionEditMode) {
31122
31262
  setRightCollapsed(!captionHasSelection);
31123
31263
  }
@@ -31129,7 +31269,7 @@ import { useCallback as useCallback70 } from "react";
31129
31269
  import { createElement } from "react";
31130
31270
 
31131
31271
  // src/player/components/AudioWaveform.tsx
31132
- import { memo as memo25, useRef as useRef57, useState as useState49, useCallback as useCallback69, useEffect as useEffect39 } from "react";
31272
+ import { memo as memo25, useRef as useRef58, useState as useState49, useCallback as useCallback69, useEffect as useEffect40 } from "react";
31133
31273
  import { jsx as jsx64, jsxs as jsxs55 } from "react/jsx-runtime";
31134
31274
  var BAR_W = 2;
31135
31275
  var GAP = 1;
@@ -31177,12 +31317,12 @@ var AudioWaveform = memo25(function AudioWaveform2({
31177
31317
  trimStartFraction,
31178
31318
  trimEndFraction
31179
31319
  }) {
31180
- const containerRef = useRef57(null);
31181
- const barsRef = useRef57(null);
31182
- const roRef = useRef57(null);
31320
+ const containerRef = useRef58(null);
31321
+ const barsRef = useRef58(null);
31322
+ const roRef = useRef58(null);
31183
31323
  const cacheKey = waveformUrl ?? audioUrl;
31184
31324
  const [peaks, setPeaks] = useState49(peaksCache.get(cacheKey) ?? null);
31185
- useEffect39(() => {
31325
+ useEffect40(() => {
31186
31326
  if (peaks || !cacheKey) return;
31187
31327
  let cancelled = false;
31188
31328
  let promise = decodeInFlight.get(cacheKey);
@@ -31238,10 +31378,10 @@ var AudioWaveform = memo25(function AudioWaveform2({
31238
31378
  },
31239
31379
  [draw]
31240
31380
  );
31241
- useEffect39(() => {
31381
+ useEffect40(() => {
31242
31382
  draw();
31243
31383
  }, [draw]);
31244
- useEffect39(
31384
+ useEffect40(
31245
31385
  () => () => {
31246
31386
  roRef.current?.disconnect();
31247
31387
  },
@@ -31383,15 +31523,15 @@ function useRenderClipContent({
31383
31523
  }
31384
31524
 
31385
31525
  // src/hooks/useConsoleErrorCapture.ts
31386
- import { useCallback as useCallback71, useEffect as useEffect40, useRef as useRef58, useState as useState50 } from "react";
31526
+ import { useCallback as useCallback71, useEffect as useEffect41, useRef as useRef59, useState as useState50 } from "react";
31387
31527
  function useConsoleErrorCapture(previewIframe) {
31388
31528
  const [consoleErrors, setConsoleErrors] = useState50(null);
31389
- const consoleErrorsRef = useRef58([]);
31529
+ const consoleErrorsRef = useRef59([]);
31390
31530
  const resetErrors = useCallback71(() => {
31391
31531
  consoleErrorsRef.current = [];
31392
31532
  setConsoleErrors(null);
31393
31533
  }, []);
31394
- useEffect40(() => {
31534
+ useEffect41(() => {
31395
31535
  if (!previewIframe) return;
31396
31536
  let patchedWin = null;
31397
31537
  let origConsoleError = null;
@@ -31616,7 +31756,7 @@ function useFrameCapture({
31616
31756
  }
31617
31757
 
31618
31758
  // src/hooks/useLintModal.ts
31619
- import { useState as useState52, useCallback as useCallback73, useEffect as useEffect41, useRef as useRef59, useMemo as useMemo24 } from "react";
31759
+ import { useState as useState52, useCallback as useCallback73, useEffect as useEffect42, useRef as useRef60, useMemo as useMemo24 } from "react";
31620
31760
  function parseFinding(f) {
31621
31761
  return {
31622
31762
  severity: f.severity === "error" ? "error" : "warning",
@@ -31630,7 +31770,7 @@ function useLintModal(projectId, refreshKey) {
31630
31770
  const [lintModal, setLintModal] = useState52(null);
31631
31771
  const [linting, setLinting] = useState52(false);
31632
31772
  const [backgroundFindings, setBackgroundFindings] = useState52([]);
31633
- const autoLintRanRef = useRef59(false);
31773
+ const autoLintRanRef = useRef60(false);
31634
31774
  const runLint = useCallback73(
31635
31775
  async (opts) => {
31636
31776
  if (!projectId) return;
@@ -31657,8 +31797,8 @@ function useLintModal(projectId, refreshKey) {
31657
31797
  [projectId]
31658
31798
  );
31659
31799
  const handleLint = useCallback73(() => runLint(), [runLint]);
31660
- const prevProjectIdRef = useRef59(projectId);
31661
- useEffect41(() => {
31800
+ const prevProjectIdRef = useRef60(projectId);
31801
+ useEffect42(() => {
31662
31802
  if (projectId !== prevProjectIdRef.current) {
31663
31803
  autoLintRanRef.current = false;
31664
31804
  prevProjectIdRef.current = projectId;
@@ -31667,7 +31807,7 @@ function useLintModal(projectId, refreshKey) {
31667
31807
  autoLintRanRef.current = true;
31668
31808
  void runLint({ background: true });
31669
31809
  }, [projectId, runLint]);
31670
- useEffect41(() => {
31810
+ useEffect42(() => {
31671
31811
  if (!projectId || !refreshKey) return;
31672
31812
  const timer = setTimeout(() => void runLint({ background: true }), 1e3);
31673
31813
  return () => clearTimeout(timer);
@@ -31690,7 +31830,7 @@ function useLintModal(projectId, refreshKey) {
31690
31830
  );
31691
31831
  const findingsByElement = useMemo24(() => groupFindings((f) => f.elementId), [groupFindings]);
31692
31832
  const findingsByFile = useMemo24(() => groupFindings((f) => f.file), [groupFindings]);
31693
- useEffect41(() => {
31833
+ useEffect42(() => {
31694
31834
  usePlayerStore.getState().setLintFindingsByElement(findingsByElement);
31695
31835
  }, [findingsByElement]);
31696
31836
  return {
@@ -31727,10 +31867,10 @@ function useCompositionDimensions() {
31727
31867
  }
31728
31868
 
31729
31869
  // src/hooks/useToast.ts
31730
- import { useState as useState54, useCallback as useCallback74, useRef as useRef60 } from "react";
31870
+ import { useState as useState54, useCallback as useCallback74, useRef as useRef61 } from "react";
31731
31871
  function useToast() {
31732
31872
  const [appToast, setAppToast] = useState54(null);
31733
- const timerRef = useRef60(null);
31873
+ const timerRef = useRef61(null);
31734
31874
  const showToast = useCallback74((message, tone = "error") => {
31735
31875
  if (timerRef.current) clearTimeout(timerRef.current);
31736
31876
  setAppToast({ message, tone });
@@ -31747,7 +31887,7 @@ function useToast() {
31747
31887
  }
31748
31888
 
31749
31889
  // src/hooks/useStudioUrlState.ts
31750
- import { useCallback as useCallback75, useEffect as useEffect42, useRef as useRef61, useState as useState55 } from "react";
31890
+ import { useCallback as useCallback75, useEffect as useEffect43, useRef as useRef62, useState as useState55 } from "react";
31751
31891
 
31752
31892
  // src/utils/studioUrlState.ts
31753
31893
  var VALID_TABS = ["layers", "design", "renders"];
@@ -31871,12 +32011,12 @@ function useStudioUrlState({
31871
32011
  initialState: initialState2
31872
32012
  }) {
31873
32013
  const currentTime = usePlayerStore((s) => s.currentTime);
31874
- const hydratedSeekRef = useRef61(initialState2.currentTime == null);
31875
- const hydratedInitialTimeRef = useRef61(initialState2.currentTime == null);
31876
- const hydratedSelectionRef = useRef61(initialState2.selection == null);
32014
+ const hydratedSeekRef = useRef62(initialState2.currentTime == null);
32015
+ const hydratedInitialTimeRef = useRef62(initialState2.currentTime == null);
32016
+ const hydratedSelectionRef = useRef62(initialState2.selection == null);
31877
32017
  const [selectionHydrated, setSelectionHydrated] = useState55(initialState2.selection == null);
31878
- const pendingSelectionRef = useRef61(initialState2.selection);
31879
- const stableTimeRef = useRef61(initialState2.currentTime);
32018
+ const pendingSelectionRef = useRef62(initialState2.selection);
32019
+ const stableTimeRef = useRef62(initialState2.currentTime);
31880
32020
  const buildUrlState = useCallback75(
31881
32021
  () => ({
31882
32022
  activeCompPath,
@@ -31922,7 +32062,7 @@ function useStudioUrlState({
31922
32062
  },
31923
32063
  [activeCompPath, applyDomSelection, buildDomSelectionFromTarget, previewIframeRef]
31924
32064
  );
31925
- useEffect42(() => {
32065
+ useEffect43(() => {
31926
32066
  if (!projectId || hydratedSeekRef.current || compositionLoading) return;
31927
32067
  const nextTime = duration > 0 ? clampNumber2(initialState2.currentTime ?? 0, 0, duration) : Math.max(0, initialState2.currentTime ?? 0);
31928
32068
  usePlayerStore.getState().requestSeek(nextTime);
@@ -31930,7 +32070,7 @@ function useStudioUrlState({
31930
32070
  hydratedSeekRef.current = true;
31931
32071
  }, [projectId, compositionLoading, duration, initialState2.currentTime]);
31932
32072
  const selectionHydrationTime = selectionHydrated ? 0 : currentTime;
31933
- useEffect42(() => {
32073
+ useEffect43(() => {
31934
32074
  if (!projectId || hydratedSelectionRef.current || compositionLoading) return;
31935
32075
  if (!hydratedSeekRef.current) return;
31936
32076
  const targetTime = initialState2.currentTime;
@@ -31957,7 +32097,7 @@ function useStudioUrlState({
31957
32097
  projectId,
31958
32098
  refreshKey
31959
32099
  ]);
31960
- useEffect42(() => {
32100
+ useEffect43(() => {
31961
32101
  if (hydratedInitialTimeRef.current) return;
31962
32102
  const targetTime = stableTimeRef.current;
31963
32103
  if (targetTime == null) {
@@ -31967,7 +32107,7 @@ function useStudioUrlState({
31967
32107
  if (Math.abs(currentTime - targetTime) > 0.05) return;
31968
32108
  hydratedInitialTimeRef.current = true;
31969
32109
  }, [currentTime]);
31970
- useEffect42(() => {
32110
+ useEffect43(() => {
31971
32111
  if (!activeCompPathHydrated) return;
31972
32112
  if (!hydratedSeekRef.current) return;
31973
32113
  if (!hydratedInitialTimeRef.current) return;
@@ -31978,12 +32118,12 @@ function useStudioUrlState({
31978
32118
  }, 200);
31979
32119
  return () => window.clearTimeout(handle);
31980
32120
  }, [activeCompPathHydrated, buildUrlState, currentTime, duration, isPlaying, projectId]);
31981
- useEffect42(() => {
32121
+ useEffect43(() => {
31982
32122
  if (!activeCompPathHydrated) return;
31983
32123
  if (!projectId) return;
31984
32124
  replaceHash(buildStudioHash(projectId, buildUrlState()));
31985
32125
  }, [activeCompPathHydrated, buildUrlState, projectId]);
31986
- useEffect42(() => {
32126
+ useEffect43(() => {
31987
32127
  if (!projectId) return;
31988
32128
  const onHashChange = () => {
31989
32129
  if (parseProjectIdFromHash(window.location.hash) !== projectId) return;
@@ -32004,7 +32144,7 @@ function useStudioUrlState({
32004
32144
  }
32005
32145
 
32006
32146
  // src/hooks/useStudioContextValue.ts
32007
- import { useCallback as useCallback76, useMemo as useMemo25, useRef as useRef62, useState as useState56 } from "react";
32147
+ import { useCallback as useCallback76, useMemo as useMemo25, useRef as useRef63, useState as useState56 } from "react";
32008
32148
  function buildStudioContextValue(input) {
32009
32149
  return {
32010
32150
  projectId: input.projectId,
@@ -32049,7 +32189,7 @@ function useInspectorState(rightPanelTab, rightInspectorPanes, rightCollapsed, i
32049
32189
  }
32050
32190
  function useDragOverlay(onImportFiles) {
32051
32191
  const [active, setActive] = useState56(false);
32052
- const counterRef = useRef62(0);
32192
+ const counterRef = useRef63(0);
32053
32193
  const onDragOver = useCallback76((e) => {
32054
32194
  if (!e.dataTransfer.types.includes("Files")) return;
32055
32195
  e.preventDefault();
@@ -32150,7 +32290,7 @@ import {
32150
32290
  createContext as createContext5,
32151
32291
  useCallback as useCallback77,
32152
32292
  useContext as useContext5,
32153
- useEffect as useEffect43,
32293
+ useEffect as useEffect44,
32154
32294
  useMemo as useMemo27,
32155
32295
  useState as useState57
32156
32296
  } from "react";
@@ -32174,7 +32314,7 @@ function useViewModeState(enabled) {
32174
32314
  const [viewMode, setMode] = useState57(
32175
32315
  () => enabled ? readViewModeFromUrl() : "timeline"
32176
32316
  );
32177
- useEffect43(() => {
32317
+ useEffect44(() => {
32178
32318
  if (!enabled) return;
32179
32319
  const onPopState = () => setMode(readViewModeFromUrl());
32180
32320
  window.addEventListener("popstate", onPopState);
@@ -32548,10 +32688,10 @@ function StudioHeader({
32548
32688
  }
32549
32689
 
32550
32690
  // src/hooks/useGestureCommit.ts
32551
- import { useState as useState59, useCallback as useCallback79, useRef as useRef64, useEffect as useEffect45 } from "react";
32691
+ import { useState as useState59, useCallback as useCallback79, useRef as useRef65, useEffect as useEffect46 } from "react";
32552
32692
 
32553
32693
  // src/hooks/useGestureRecording.ts
32554
- import { useCallback as useCallback78, useEffect as useEffect44, useRef as useRef63, useState as useState58 } from "react";
32694
+ import { useCallback as useCallback78, useEffect as useEffect45, useRef as useRef64, useState as useState58 } from "react";
32555
32695
  function readBasePosition(element, iframeEl) {
32556
32696
  let baseOpacity = 1;
32557
32697
  let baseScale = 1;
@@ -32670,11 +32810,11 @@ function createRecordingRefs() {
32670
32810
  function useGestureRecording() {
32671
32811
  const [isRecording, setIsRecording] = useState58(false);
32672
32812
  const [recordingDuration, setRecordingDuration] = useState58(0);
32673
- const isRecordingRef = useRef63(false);
32674
- const refs = useRef63(createRecordingRefs());
32675
- const samplesRef = useRef63(refs.current.samples);
32676
- const trailRef = useRef63(refs.current.trail);
32677
- useEffect44(() => {
32813
+ const isRecordingRef = useRef64(false);
32814
+ const refs = useRef64(createRecordingRefs());
32815
+ const samplesRef = useRef64(refs.current.samples);
32816
+ const trailRef = useRef64(refs.current.trail);
32817
+ useEffect45(() => {
32678
32818
  const r = refs.current;
32679
32819
  return () => {
32680
32820
  r.cleanup?.();
@@ -33065,12 +33205,12 @@ function useGestureCommit({
33065
33205
  }) {
33066
33206
  const gestureRecording = useGestureRecording();
33067
33207
  const [gestureState, setGestureState] = useState59("idle");
33068
- const gestureStateRef = useRef64("idle");
33069
- const recordingAutoStopRef = useRef64(void 0);
33070
- const recordingStartTimeRef = useRef64(0);
33071
- const commitInFlightRef = useRef64(false);
33072
- const capturedSelectionRef = useRef64(null);
33073
- useEffect45(() => () => clearInterval(recordingAutoStopRef.current), []);
33208
+ const gestureStateRef = useRef65("idle");
33209
+ const recordingAutoStopRef = useRef65(void 0);
33210
+ const recordingStartTimeRef = useRef65(0);
33211
+ const commitInFlightRef = useRef65(false);
33212
+ const capturedSelectionRef = useRef65(null);
33213
+ useEffect46(() => () => clearInterval(recordingAutoStopRef.current), []);
33074
33214
  const stopAndCommitRecording = useCallback79(async () => {
33075
33215
  clearInterval(recordingAutoStopRef.current);
33076
33216
  if (commitInFlightRef.current) {
@@ -33389,12 +33529,12 @@ import {
33389
33529
  useState as useState66,
33390
33530
  useCallback as useCallback84,
33391
33531
  useImperativeHandle,
33392
- useRef as useRef69,
33532
+ useRef as useRef70,
33393
33533
  forwardRef as forwardRef3
33394
33534
  } from "react";
33395
33535
 
33396
33536
  // src/components/sidebar/CompositionsTab.tsx
33397
- import { memo as memo27, useCallback as useCallback80, useEffect as useEffect46, useRef as useRef65, useState as useState60 } from "react";
33537
+ import { memo as memo27, useCallback as useCallback80, useEffect as useEffect47, useRef as useRef66, useState as useState60 } from "react";
33398
33538
  import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
33399
33539
  var DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
33400
33540
  var CARD_W = 80;
@@ -33462,9 +33602,9 @@ function CompCard({
33462
33602
  }) {
33463
33603
  const [hovered, setHovered] = useState60(false);
33464
33604
  const [stageSize, setStageSize] = useState60(DEFAULT_PREVIEW_STAGE);
33465
- const iframeRef = useRef65(null);
33466
- const hoverTimer = useRef65(null);
33467
- const syncTimer = useRef65(null);
33605
+ const iframeRef = useRef66(null);
33606
+ const hoverTimer = useRef66(null);
33607
+ const syncTimer = useRef66(null);
33468
33608
  const requestIframePlaybackSync = useCallback80((shouldPlay) => {
33469
33609
  if (syncTimer.current) {
33470
33610
  clearTimeout(syncTimer.current);
@@ -33496,10 +33636,10 @@ function CompCard({
33496
33636
  });
33497
33637
  const thumbnailOffsetX = (CARD_W - stageSize.width * previewScale) / 2;
33498
33638
  const thumbnailOffsetY = (CARD_H - stageSize.height * previewScale) / 2;
33499
- useEffect46(() => {
33639
+ useEffect47(() => {
33500
33640
  requestIframePlaybackSync(hovered);
33501
33641
  }, [hovered, requestIframePlaybackSync]);
33502
- useEffect46(() => {
33642
+ useEffect47(() => {
33503
33643
  return () => {
33504
33644
  if (hoverTimer.current) clearTimeout(hoverTimer.current);
33505
33645
  if (syncTimer.current) clearTimeout(syncTimer.current);
@@ -33623,14 +33763,14 @@ var CompositionsTab = memo27(function CompositionsTab2({
33623
33763
  });
33624
33764
 
33625
33765
  // src/components/sidebar/AssetsTab.tsx
33626
- import { memo as memo28, useState as useState63, useCallback as useCallback82, useRef as useRef67, useMemo as useMemo29, useEffect as useEffect49 } from "react";
33766
+ import { memo as memo28, useState as useState63, useCallback as useCallback82, useRef as useRef68, useMemo as useMemo29, useEffect as useEffect50 } from "react";
33627
33767
 
33628
33768
  // src/components/ui/VideoFrameThumbnail.tsx
33629
- import { useState as useState61, useEffect as useEffect47 } from "react";
33769
+ import { useState as useState61, useEffect as useEffect48 } from "react";
33630
33770
  import { jsx as jsx70 } from "react/jsx-runtime";
33631
33771
  function VideoFrameThumbnail({ src }) {
33632
33772
  const [frame, setFrame] = useState61(null);
33633
- useEffect47(() => {
33773
+ useEffect48(() => {
33634
33774
  const video = document.createElement("video");
33635
33775
  video.crossOrigin = "anonymous";
33636
33776
  video.muted = true;
@@ -33765,7 +33905,7 @@ var CATEGORY_LABELS = {
33765
33905
  var FILTER_ORDER = ["audio", "images", "video", "fonts"];
33766
33906
 
33767
33907
  // src/components/sidebar/AudioRow.tsx
33768
- import { useState as useState62, useRef as useRef66, useEffect as useEffect48, useCallback as useCallback81 } from "react";
33908
+ import { useState as useState62, useRef as useRef67, useEffect as useEffect49, useCallback as useCallback81 } from "react";
33769
33909
  import { Fragment as Fragment20, jsx as jsx72, jsxs as jsxs60 } from "react/jsx-runtime";
33770
33910
  function AudioRow({
33771
33911
  projectId,
@@ -33780,22 +33920,22 @@ function AudioRow({
33780
33920
  const [contextMenu, setContextMenu] = useState62(null);
33781
33921
  const [playing, setPlaying] = useState62(false);
33782
33922
  const [bars, setBars] = useState62([]);
33783
- const audioRef = useRef66(null);
33784
- const actxRef = useRef66(null);
33785
- const analyserRef = useRef66(null);
33786
- const sourceRef = useRef66(null);
33787
- const animRef = useRef66(0);
33923
+ const audioRef = useRef67(null);
33924
+ const actxRef = useRef67(null);
33925
+ const analyserRef = useRef67(null);
33926
+ const sourceRef = useRef67(null);
33927
+ const animRef = useRef67(0);
33788
33928
  const name = basename(asset);
33789
33929
  const subtype = getAudioSubtype(asset);
33790
33930
  const serveUrl = `/api/projects/${projectId}/preview/${asset}`;
33791
- useEffect48(() => {
33931
+ useEffect49(() => {
33792
33932
  return () => {
33793
33933
  cancelAnimationFrame(animRef.current);
33794
33934
  audioRef.current?.pause();
33795
33935
  actxRef.current?.close();
33796
33936
  };
33797
33937
  }, []);
33798
- useEffect48(() => {
33938
+ useEffect49(() => {
33799
33939
  if (playing) {
33800
33940
  const barCount = 24;
33801
33941
  const loop = () => {
@@ -34060,15 +34200,15 @@ var AssetsTab = memo28(function AssetsTab2({
34060
34200
  onDelete,
34061
34201
  onRename
34062
34202
  }) {
34063
- const fileInputRef = useRef67(null);
34203
+ const fileInputRef = useRef68(null);
34064
34204
  const [dragOver, setDragOver] = useState63(false);
34065
34205
  const [copiedPath, setCopiedPath] = useState63(null);
34066
34206
  const [activeFilter, setActiveFilter] = useState63("all");
34067
34207
  const [searchQuery, setSearchQuery] = useState63("");
34068
34208
  const [manifest, setManifest] = useState63(/* @__PURE__ */ new Map());
34069
- const manifest404Ref = useRef67(/* @__PURE__ */ new Set());
34209
+ const manifest404Ref = useRef68(/* @__PURE__ */ new Set());
34070
34210
  const assetsKey = assets.join("|");
34071
- useEffect49(() => {
34211
+ useEffect50(() => {
34072
34212
  if (manifest404Ref.current.has(projectId)) return;
34073
34213
  let cancelled = false;
34074
34214
  fetch(`/api/projects/${projectId}/preview/.media/manifest.jsonl`).then((r) => {
@@ -34352,11 +34492,11 @@ var AssetsTab = memo28(function AssetsTab2({
34352
34492
  });
34353
34493
 
34354
34494
  // src/components/sidebar/BlocksTab.tsx
34355
- import { memo as memo29, useState as useState65, useCallback as useCallback83, useRef as useRef68, useEffect as useEffect51 } from "react";
34495
+ import { memo as memo29, useState as useState65, useCallback as useCallback83, useRef as useRef69, useEffect as useEffect52 } from "react";
34356
34496
  import { createPortal as createPortal5 } from "react-dom";
34357
34497
 
34358
34498
  // src/hooks/useBlockCatalog.ts
34359
- import { useState as useState64, useEffect as useEffect50, useMemo as useMemo30 } from "react";
34499
+ import { useState as useState64, useEffect as useEffect51, useMemo as useMemo30 } from "react";
34360
34500
 
34361
34501
  // src/utils/blockCategories.ts
34362
34502
  import {
@@ -34385,7 +34525,7 @@ function useBlockCatalog() {
34385
34525
  const [error, setError] = useState64(null);
34386
34526
  const [search, setSearch] = useState64("");
34387
34527
  const [category, setCategory] = useState64(null);
34388
- useEffect50(() => {
34528
+ useEffect51(() => {
34389
34529
  let cancelled = false;
34390
34530
  (async () => {
34391
34531
  try {
@@ -34646,7 +34786,7 @@ function BlockCard({
34646
34786
  }) {
34647
34787
  const [hovered, setHovered] = useState65(false);
34648
34788
  const [adding, setAdding] = useState65(false);
34649
- const hoverTimer = useRef68(null);
34789
+ const hoverTimer = useRef69(null);
34650
34790
  const colors = getCategoryColors(category);
34651
34791
  const needsWebGL = tags?.includes("html-in-canvas") || tags?.includes("webgl");
34652
34792
  const handleEnter = useCallback83(() => {
@@ -34663,7 +34803,7 @@ function BlockCard({
34663
34803
  setHovered(false);
34664
34804
  onPreview?.(null);
34665
34805
  }, [onPreview]);
34666
- useEffect51(() => {
34806
+ useEffect52(() => {
34667
34807
  return () => {
34668
34808
  if (hoverTimer.current) clearTimeout(hoverTimer.current);
34669
34809
  };
@@ -34817,8 +34957,8 @@ function PromptPreviewModal({
34817
34957
  }) {
34818
34958
  const [value, setValue] = useState65(prompt);
34819
34959
  const [copied, setCopied] = useState65(false);
34820
- const textareaRef = useRef68(null);
34821
- useEffect51(() => {
34960
+ const textareaRef = useRef69(null);
34961
+ useEffect52(() => {
34822
34962
  requestAnimationFrame(() => textareaRef.current?.focus());
34823
34963
  }, []);
34824
34964
  const handleCopy = useCallback83(() => {
@@ -34944,7 +35084,7 @@ var LeftSidebar = memo30(
34944
35084
  takeoverContent
34945
35085
  }, ref) {
34946
35086
  const [tab, setTab] = useState66(getPersistedTab);
34947
- const tabRef = useRef69(tab);
35087
+ const tabRef = useRef70(tab);
34948
35088
  tabRef.current = tab;
34949
35089
  const selectTab = useCallback84((t) => {
34950
35090
  setTab(t);
@@ -35354,7 +35494,7 @@ function StudioLeftSidebar({
35354
35494
  import { useState as useState75, useMemo as useMemo33 } from "react";
35355
35495
 
35356
35496
  // src/captions/components/CaptionOverlay.tsx
35357
- import { memo as memo31, useState as useState67, useCallback as useCallback86, useRef as useRef70 } from "react";
35497
+ import { memo as memo31, useState as useState67, useCallback as useCallback86, useRef as useRef71 } from "react";
35358
35498
 
35359
35499
  // src/captions/keyboard.ts
35360
35500
  var CAPTION_NUDGE_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]);
@@ -35543,10 +35683,10 @@ var CaptionOverlay = memo31(function CaptionOverlay2({ iframeRef }) {
35543
35683
  const selectSegment = useCaptionStore((s) => s.selectSegment);
35544
35684
  const clearSelection = useCaptionStore((s) => s.clearSelection);
35545
35685
  const [wordBoxes, setWordBoxes] = useState67([]);
35546
- const overlayRef = useRef70(null);
35547
- const modelRef = useRef70(model);
35686
+ const overlayRef = useRef71(null);
35687
+ const modelRef = useRef71(model);
35548
35688
  modelRef.current = model;
35549
- const interactionRef = useRef70(null);
35689
+ const interactionRef = useRef71(null);
35550
35690
  useMountEffect(() => {
35551
35691
  if (!isEditMode) return;
35552
35692
  let prevBoxes = [];
@@ -35833,7 +35973,7 @@ var CaptionOverlay = memo31(function CaptionOverlay2({ iframeRef }) {
35833
35973
  });
35834
35974
 
35835
35975
  // src/captions/components/CaptionTimeline.tsx
35836
- import { memo as memo32, useCallback as useCallback87, useRef as useRef71 } from "react";
35976
+ import { memo as memo32, useCallback as useCallback87, useRef as useRef72 } from "react";
35837
35977
  import { jsx as jsx79, jsxs as jsxs67 } from "react/jsx-runtime";
35838
35978
  var GROUP_COLORS = [
35839
35979
  "#3CE6AC",
@@ -35856,7 +35996,7 @@ var CaptionTimeline = memo32(function CaptionTimeline2({
35856
35996
  const selectSegment = useCaptionStore((s) => s.selectSegment);
35857
35997
  const updateSegmentTiming = useCaptionStore((s) => s.updateSegmentTiming);
35858
35998
  const splitGroup = useCaptionStore((s) => s.splitGroup);
35859
- const dragRef = useRef71(null);
35999
+ const dragRef = useRef72(null);
35860
36000
  const handleEdgePointerDown = useCallback87(
35861
36001
  (e, segId, edge, originalStart, originalEnd) => {
35862
36002
  e.stopPropagation();
@@ -35978,10 +36118,10 @@ var CaptionTimeline = memo32(function CaptionTimeline2({
35978
36118
  });
35979
36119
 
35980
36120
  // src/components/editor/DomEditOverlay.tsx
35981
- import { memo as memo35, useEffect as useEffect52, useMemo as useMemo31, useRef as useRef75, useState as useState70 } from "react";
36121
+ import { memo as memo35, useEffect as useEffect53, useMemo as useMemo31, useRef as useRef76, useState as useState70 } from "react";
35982
36122
 
35983
36123
  // src/components/editor/marqueeCommit.ts
35984
- import { useCallback as useCallback88, useRef as useRef72, useState as useState68 } from "react";
36124
+ import { useCallback as useCallback88, useRef as useRef73, useState as useState68 } from "react";
35985
36125
 
35986
36126
  // src/utils/marqueeGeometry.ts
35987
36127
  function rectsOverlap(a, b) {
@@ -36172,7 +36312,7 @@ async function runMarqueeIntersection(rect, iframe, overlayEl, activeComposition
36172
36312
  return hits;
36173
36313
  }
36174
36314
  function useMarqueeGestures(deps) {
36175
- const marqueeRef = useRef72(null);
36315
+ const marqueeRef = useRef73(null);
36176
36316
  const [marqueeRect, setMarqueeRect] = useState68(null);
36177
36317
  const [candidateRects, setCandidateRects] = useState68([]);
36178
36318
  const commitMarquee = useCallback88(
@@ -36348,7 +36488,7 @@ function hasDomEditRotationChanged(initialAngle, nextAngle) {
36348
36488
  }
36349
36489
 
36350
36490
  // src/components/editor/useDomEditOverlayRects.ts
36351
- import { useRef as useRef73, useState as useState69 } from "react";
36491
+ import { useRef as useRef74, useState as useState69 } from "react";
36352
36492
  function childRectsEqual(a, b) {
36353
36493
  if (a.length !== b.length) return false;
36354
36494
  for (let i = 0; i < a.length; i++) {
@@ -36369,13 +36509,13 @@ function useDomEditOverlayRects({
36369
36509
  const [hoverRect, setHoverRectState] = useState69(null);
36370
36510
  const [groupOverlayItems, setGroupOverlayItemsState] = useState69([]);
36371
36511
  const [childRects, setChildRectsState] = useState69([]);
36372
- const overlayRectRef = useRef73(null);
36373
- const hoverRectRef = useRef73(null);
36374
- const groupOverlayItemsRef = useRef73([]);
36375
- const resolvedElementRef = useRef73(null);
36376
- const resolvedHoverElementRef = useRef73(null);
36377
- const resolvedGroupElementRef = useRef73(/* @__PURE__ */ new Map());
36378
- const childRectsRef = useRef73([]);
36512
+ const overlayRectRef = useRef74(null);
36513
+ const hoverRectRef = useRef74(null);
36514
+ const groupOverlayItemsRef = useRef74([]);
36515
+ const resolvedElementRef = useRef74(null);
36516
+ const resolvedHoverElementRef = useRef74(null);
36517
+ const resolvedGroupElementRef = useRef74(/* @__PURE__ */ new Map());
36518
+ const childRectsRef = useRef74([]);
36379
36519
  const setOverlayRect = (next) => {
36380
36520
  if (rectsEqual(overlayRectRef.current, next)) return;
36381
36521
  overlayRectRef.current = next;
@@ -37831,7 +37971,7 @@ function createDomEditOverlayGestureHandlers(opts) {
37831
37971
  }
37832
37972
 
37833
37973
  // src/components/editor/SnapGuideOverlay.tsx
37834
- import { memo as memo33, useRef as useRef74 } from "react";
37974
+ import { memo as memo33, useRef as useRef75 } from "react";
37835
37975
  import { jsx as jsx82, jsxs as jsxs69 } from "react/jsx-runtime";
37836
37976
  var MAX_GUIDES = 6;
37837
37977
  var MAX_SPACING_GUIDES = 4;
@@ -37843,12 +37983,12 @@ var SnapGuideOverlay = memo33(function SnapGuideOverlay2({
37843
37983
  overlayWidth,
37844
37984
  overlayHeight
37845
37985
  }) {
37846
- const guideElsRef = useRef74([]);
37847
- const spacingElsRef = useRef74([]);
37848
- const spacingLabelElsRef = useRef74([]);
37849
- const overlayWidthRef = useRef74(overlayWidth);
37986
+ const guideElsRef = useRef75([]);
37987
+ const spacingElsRef = useRef75([]);
37988
+ const spacingLabelElsRef = useRef75([]);
37989
+ const overlayWidthRef = useRef75(overlayWidth);
37850
37990
  overlayWidthRef.current = overlayWidth;
37851
- const overlayHeightRef = useRef74(overlayHeight);
37991
+ const overlayHeightRef = useRef75(overlayHeight);
37852
37992
  overlayHeightRef.current = overlayHeight;
37853
37993
  useMountEffect(() => {
37854
37994
  let frame = 0;
@@ -38030,9 +38170,9 @@ var DomEditOverlay = memo35(function DomEditOverlay2({
38030
38170
  onRotationCommit,
38031
38171
  onMarqueeSelect
38032
38172
  }) {
38033
- const overlayRef = useRef75(null);
38034
- const boxRef = useRef75(null);
38035
- const onMarqueeSelectRef = useRef75(onMarqueeSelect);
38173
+ const overlayRef = useRef76(null);
38174
+ const boxRef = useRef76(null);
38175
+ const onMarqueeSelectRef = useRef76(onMarqueeSelect);
38036
38176
  onMarqueeSelectRef.current = onMarqueeSelect;
38037
38177
  const selectionShapeStyles = (() => {
38038
38178
  const fallback = {
@@ -38056,39 +38196,39 @@ var DomEditOverlay = memo35(function DomEditOverlay2({
38056
38196
  return fallback;
38057
38197
  }
38058
38198
  })();
38059
- const gestureRef = useRef75(null);
38060
- const groupGestureRef = useRef75(null);
38061
- const blockedMoveRef = useRef75(null);
38062
- const suppressNextBoxClickRef = useRef75(false);
38063
- const suppressNextBoxMouseDownRef = useRef75(false);
38064
- const suppressNextOverlayMouseDownRef = useRef75(false);
38065
- const snapGuidesRef = useRef75(null);
38066
- const rafPausedRef = useRef75(false);
38067
- const selectionRef = useRef75(selection);
38199
+ const gestureRef = useRef76(null);
38200
+ const groupGestureRef = useRef76(null);
38201
+ const blockedMoveRef = useRef76(null);
38202
+ const suppressNextBoxClickRef = useRef76(false);
38203
+ const suppressNextBoxMouseDownRef = useRef76(false);
38204
+ const suppressNextOverlayMouseDownRef = useRef76(false);
38205
+ const snapGuidesRef = useRef76(null);
38206
+ const rafPausedRef = useRef76(false);
38207
+ const selectionRef = useRef76(selection);
38068
38208
  selectionRef.current = selection;
38069
- const activeCompositionPathRef = useRef75(activeCompositionPath);
38209
+ const activeCompositionPathRef = useRef76(activeCompositionPath);
38070
38210
  activeCompositionPathRef.current = activeCompositionPath;
38071
- const groupSelectionsRef = useRef75(groupSelections);
38211
+ const groupSelectionsRef = useRef76(groupSelections);
38072
38212
  groupSelectionsRef.current = groupSelections;
38073
- const hoverSelectionRef = useRef75(hoverSelection);
38213
+ const hoverSelectionRef = useRef76(hoverSelection);
38074
38214
  hoverSelectionRef.current = hoverSelection;
38075
- const onPathOffsetCommitRef = useRef75(onPathOffsetCommit);
38215
+ const onPathOffsetCommitRef = useRef76(onPathOffsetCommit);
38076
38216
  onPathOffsetCommitRef.current = onPathOffsetCommit;
38077
- const onGroupPathOffsetCommitRef = useRef75(onGroupPathOffsetCommit);
38217
+ const onGroupPathOffsetCommitRef = useRef76(onGroupPathOffsetCommit);
38078
38218
  onGroupPathOffsetCommitRef.current = onGroupPathOffsetCommit;
38079
- const onBoxSizeCommitRef = useRef75(onBoxSizeCommit);
38219
+ const onBoxSizeCommitRef = useRef76(onBoxSizeCommit);
38080
38220
  onBoxSizeCommitRef.current = onBoxSizeCommit;
38081
- const onRotationCommitRef = useRef75(onRotationCommit);
38221
+ const onRotationCommitRef = useRef76(onRotationCommit);
38082
38222
  onRotationCommitRef.current = onRotationCommit;
38083
- const onBlockedMoveRef = useRef75(onBlockedMove);
38223
+ const onBlockedMoveRef = useRef76(onBlockedMove);
38084
38224
  onBlockedMoveRef.current = onBlockedMove;
38085
- const onManualDragStartRef = useRef75(onManualDragStart);
38225
+ const onManualDragStartRef = useRef76(onManualDragStart);
38086
38226
  onManualDragStartRef.current = onManualDragStart;
38087
- const onCanvasPointerMoveRef = useRef75(onCanvasPointerMove);
38227
+ const onCanvasPointerMoveRef = useRef76(onCanvasPointerMove);
38088
38228
  onCanvasPointerMoveRef.current = onCanvasPointerMove;
38089
- const onCanvasPointerLeaveRef = useRef75(onCanvasPointerLeave);
38229
+ const onCanvasPointerLeaveRef = useRef76(onCanvasPointerLeave);
38090
38230
  onCanvasPointerLeaveRef.current = onCanvasPointerLeave;
38091
- const onSelectionChangeRef = useRef75(onSelectionChange);
38231
+ const onSelectionChangeRef = useRef76(onSelectionChange);
38092
38232
  onSelectionChangeRef.current = onSelectionChange;
38093
38233
  const {
38094
38234
  overlayRect,
@@ -38143,9 +38283,9 @@ var DomEditOverlay = memo35(function DomEditOverlay2({
38143
38283
  frame = requestAnimationFrame(update);
38144
38284
  return () => cancelAnimationFrame(frame);
38145
38285
  });
38146
- const offCanvasElementsRef = useRef75(/* @__PURE__ */ new Map());
38286
+ const offCanvasElementsRef = useRef76(/* @__PURE__ */ new Map());
38147
38287
  const [offCanvasRects, setOffCanvasRects] = useState70([]);
38148
- useEffect52(() => {
38288
+ useEffect53(() => {
38149
38289
  const iframe = iframeRef.current;
38150
38290
  const overlay = overlayRef.current;
38151
38291
  if (!iframe || !overlay || compRect.width <= 0) {
@@ -38488,10 +38628,10 @@ var DomEditOverlay = memo35(function DomEditOverlay2({
38488
38628
  });
38489
38629
 
38490
38630
  // src/components/editor/MotionPathOverlay.tsx
38491
- import { memo as memo36, useEffect as useEffect54, useRef as useRef78, useState as useState72 } from "react";
38631
+ import { memo as memo36, useEffect as useEffect55, useRef as useRef79, useState as useState72 } from "react";
38492
38632
 
38493
38633
  // src/contexts/DomEditContext.tsx
38494
- import { createContext as createContext6, useCallback as useCallback89, useContext as useContext6, useMemo as useMemo32, useRef as useRef76 } from "react";
38634
+ import { createContext as createContext6, useCallback as useCallback89, useContext as useContext6, useMemo as useMemo32, useRef as useRef77 } from "react";
38495
38635
  import { jsx as jsx85 } from "react/jsx-runtime";
38496
38636
  var DomEditActionsContext = createContext6(null);
38497
38637
  var DomEditSelectionContext = createContext6(null);
@@ -38587,7 +38727,7 @@ function DomEditProvider({
38587
38727
  },
38588
38728
  children
38589
38729
  }) {
38590
- const commitMutationRef = useRef76(commitMutation);
38730
+ const commitMutationRef = useRef77(commitMutation);
38591
38731
  commitMutationRef.current = commitMutation;
38592
38732
  const stableCommitMutation = useCallback89(
38593
38733
  (mutation, options) => commitMutationRef.current(mutation, options),
@@ -38938,7 +39078,7 @@ function commitCreatePath(targetSelector, position, x, y, commit) {
38938
39078
  }
38939
39079
 
38940
39080
  // src/components/editor/useMotionPathData.ts
38941
- import { useEffect as useEffect53, useRef as useRef77, useState as useState71 } from "react";
39081
+ import { useEffect as useEffect54, useRef as useRef78, useState as useState71 } from "react";
38942
39082
  function transformTranslate(el) {
38943
39083
  const t = el.ownerDocument?.defaultView?.getComputedStyle(el).transform;
38944
39084
  if (!t || t === "none") return { x: 0, y: 0 };
@@ -39004,12 +39144,12 @@ function hasMotionPathPlugin(iframe) {
39004
39144
  function useMotionPathData(iframeRef, selector) {
39005
39145
  const [rect, setRect] = useState71(null);
39006
39146
  const [geometry, setGeometry] = useState71(null);
39007
- const resolvedForRef = useRef77(null);
39147
+ const resolvedForRef = useRef78(null);
39008
39148
  const geometryResolved = resolvedForRef.current === selector;
39009
39149
  const [visibleInPreview, setVisibleInPreview] = useState71(true);
39010
39150
  const [home, setHome] = useState71(null);
39011
39151
  const [pScale, setPScale] = useState71(1);
39012
- useEffect53(() => {
39152
+ useEffect54(() => {
39013
39153
  if (!selector) {
39014
39154
  setRect(null);
39015
39155
  setHome(null);
@@ -39052,7 +39192,7 @@ function useMotionPathData(iframeRef, selector) {
39052
39192
  raf = requestAnimationFrame(tick);
39053
39193
  return () => cancelAnimationFrame(raf);
39054
39194
  }, [selector, iframeRef]);
39055
- useEffect53(() => {
39195
+ useEffect54(() => {
39056
39196
  if (!selector) {
39057
39197
  setGeometry(null);
39058
39198
  return;
@@ -39100,22 +39240,22 @@ var MotionPathOverlay = memo36(function MotionPathOverlay2({
39100
39240
  const armed = usePlayerStore((s) => s.motionPathArmed);
39101
39241
  const setMotionPathArmed = usePlayerStore((s) => s.setMotionPathArmed);
39102
39242
  const setMotionPathCreateAvailable = usePlayerStore((s) => s.setMotionPathCreateAvailable);
39103
- const dragRef = useRef78(null);
39104
- const parkTimerRef = useRef78(void 0);
39243
+ const dragRef = useRef79(null);
39244
+ const parkTimerRef = useRef79(void 0);
39105
39245
  const animId = editableAnimationId(selectedGsapAnimations ?? [], geometry?.kind ?? "linear");
39106
- useEffect54(() => () => clearTimeout(parkTimerRef.current), [animId]);
39246
+ useEffect55(() => () => clearTimeout(parkTimerRef.current), [animId]);
39107
39247
  const createMode = geometryResolved && !geometry && Boolean(selection?.element) && !isPlaying;
39108
39248
  const createSelector = createMode ? selectorFor(selection) : null;
39109
39249
  const compW = compositionSize?.width ?? null;
39110
39250
  const canCreate = createMode && hasMotionPathPlugin(iframeRef.current);
39111
- useEffect54(() => {
39251
+ useEffect55(() => {
39112
39252
  setMotionPathCreateAvailable(Boolean(canCreate));
39113
39253
  return () => setMotionPathCreateAvailable(false);
39114
39254
  }, [canCreate, setMotionPathCreateAvailable]);
39115
- useEffect54(() => {
39255
+ useEffect55(() => {
39116
39256
  if (armed && !canCreate) setMotionPathArmed(false);
39117
39257
  }, [armed, canCreate, setMotionPathArmed]);
39118
- useEffect54(() => {
39258
+ useEffect55(() => {
39119
39259
  if (!armed || !createSelector || !compW) return;
39120
39260
  const surface = iframeRef.current?.ownerDocument?.querySelector(
39121
39261
  "[data-preview-pan-surface]"
@@ -39416,7 +39556,7 @@ var MotionPathOverlay = memo36(function MotionPathOverlay2({
39416
39556
  });
39417
39557
 
39418
39558
  // src/components/editor/SnapToolbar.tsx
39419
- import { memo as memo37, useCallback as useCallback90, useEffect as useEffect55, useRef as useRef79, useState as useState73 } from "react";
39559
+ import { memo as memo37, useCallback as useCallback90, useEffect as useEffect56, useRef as useRef80, useState as useState73 } from "react";
39420
39560
  import { MagnetStraight, GridFour, Path } from "@phosphor-icons/react";
39421
39561
  import { jsx as jsx88, jsxs as jsxs73 } from "react/jsx-runtime";
39422
39562
  var SNAP_DEFAULTS = {
@@ -39440,8 +39580,8 @@ var SnapToolbar = memo37(function SnapToolbar2({ onSnapChange }) {
39440
39580
  const motionPathCreateAvailable = usePlayerStore((s) => s.motionPathCreateAvailable);
39441
39581
  const motionPathArmed = usePlayerStore((s) => s.motionPathArmed);
39442
39582
  const setMotionPathArmed = usePlayerStore((s) => s.setMotionPathArmed);
39443
- const popoverRef = useRef79(null);
39444
- const gridButtonRef = useRef79(null);
39583
+ const popoverRef = useRef80(null);
39584
+ const gridButtonRef = useRef80(null);
39445
39585
  const updatePrefs = useCallback90(
39446
39586
  (patch) => {
39447
39587
  setPrefs((prev) => {
@@ -39459,7 +39599,7 @@ var SnapToolbar = memo37(function SnapToolbar2({ onSnapChange }) {
39459
39599
  const toggleGrid = useCallback90(() => {
39460
39600
  updatePrefs({ gridVisible: !prefs.gridVisible });
39461
39601
  }, [prefs.gridVisible, updatePrefs]);
39462
- useEffect55(() => {
39602
+ useEffect56(() => {
39463
39603
  const handleKeyDown = (e) => {
39464
39604
  const t = e.target;
39465
39605
  if (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement) return;
@@ -39477,7 +39617,7 @@ var SnapToolbar = memo37(function SnapToolbar2({ onSnapChange }) {
39477
39617
  document.addEventListener("keydown", handleKeyDown);
39478
39618
  return () => document.removeEventListener("keydown", handleKeyDown);
39479
39619
  }, [updatePrefs]);
39480
- useEffect55(() => {
39620
+ useEffect56(() => {
39481
39621
  if (!gridPopoverOpen) return;
39482
39622
  const handleClickOutside = (e) => {
39483
39623
  const target = e.target;
@@ -39580,7 +39720,7 @@ var SnapToolbar = memo37(function SnapToolbar2({ onSnapChange }) {
39580
39720
  });
39581
39721
 
39582
39722
  // src/components/StudioFeedbackBar.tsx
39583
- import { memo as memo38, useState as useState74, useCallback as useCallback91, useRef as useRef80, useEffect as useEffect56 } from "react";
39723
+ import { memo as memo38, useState as useState74, useCallback as useCallback91, useRef as useRef81, useEffect as useEffect57 } from "react";
39584
39724
  import { Fragment as Fragment29, jsx as jsx89, jsxs as jsxs74 } from "react/jsx-runtime";
39585
39725
  var DEFAULT_FEEDBACK_INTERVAL = 10;
39586
39726
  var AUTO_DISMISS_MS = 2e4;
@@ -39639,9 +39779,9 @@ var StudioFeedbackBar = memo38(function StudioFeedbackBar2() {
39639
39779
  const [comment, setComment] = useState74("");
39640
39780
  const [submitted, setSubmitted] = useState74(false);
39641
39781
  const [exiting, setExiting] = useState74(false);
39642
- const inputRef = useRef80(null);
39643
- const dismissTimerRef = useRef80(null);
39644
- useEffect56(() => {
39782
+ const inputRef = useRef81(null);
39783
+ const dismissTimerRef = useRef81(null);
39784
+ useEffect57(() => {
39645
39785
  incrementSessionCount();
39646
39786
  const showTimer = setTimeout(() => {
39647
39787
  if (shouldShowFeedback()) {
@@ -39650,7 +39790,7 @@ var StudioFeedbackBar = memo38(function StudioFeedbackBar2() {
39650
39790
  }, 3e3);
39651
39791
  return () => clearTimeout(showTimer);
39652
39792
  }, []);
39653
- useEffect56(() => {
39793
+ useEffect57(() => {
39654
39794
  if (!visible || rating !== null || submitted) return;
39655
39795
  dismissTimerRef.current = setTimeout(() => {
39656
39796
  handleDismiss();
@@ -39659,7 +39799,7 @@ var StudioFeedbackBar = memo38(function StudioFeedbackBar2() {
39659
39799
  if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);
39660
39800
  };
39661
39801
  }, [visible, rating, submitted]);
39662
- useEffect56(() => {
39802
+ useEffect57(() => {
39663
39803
  if (rating !== null && inputRef.current) {
39664
39804
  inputRef.current.focus();
39665
39805
  }
@@ -40005,15 +40145,15 @@ function StudioPreviewArea({
40005
40145
  import {
40006
40146
  useCallback as useCallback101,
40007
40147
  useMemo as useMemo34,
40008
- useRef as useRef85,
40148
+ useRef as useRef86,
40009
40149
  useState as useState84
40010
40150
  } from "react";
40011
40151
 
40012
40152
  // src/components/editor/LayersPanel.tsx
40013
- import { memo as memo39, useState as useState77, useCallback as useCallback93, useEffect as useEffect57, useRef as useRef82 } from "react";
40153
+ import { memo as memo39, useState as useState77, useCallback as useCallback93, useEffect as useEffect58, useRef as useRef83 } from "react";
40014
40154
 
40015
40155
  // src/components/editor/useLayerDrag.ts
40016
- import { useRef as useRef81, useState as useState76, useCallback as useCallback92 } from "react";
40156
+ import { useRef as useRef82, useState as useState76, useCallback as useCallback92 } from "react";
40017
40157
  var DRAG_THRESHOLD_PX2 = 4;
40018
40158
  function isLayerDraggable(layer) {
40019
40159
  if (!(layer.selector || layer.id)) return false;
@@ -40080,7 +40220,7 @@ function useLayerDrag({
40080
40220
  onReorder,
40081
40221
  onSingleSibling
40082
40222
  }) {
40083
- const dragRef = useRef81(null);
40223
+ const dragRef = useRef82(null);
40084
40224
  const [dragKey, setDragKey] = useState76(null);
40085
40225
  const [insertionLineY, setInsertionLineY] = useState76(null);
40086
40226
  const handleRowPointerDown = useCallback92(
@@ -40210,8 +40350,8 @@ var LayersPanel = memo39(function LayersPanel2() {
40210
40350
  } = useDomEditContext();
40211
40351
  const [layers, setLayers] = useState77([]);
40212
40352
  const [collapsed, setCollapsed] = useState77({});
40213
- const prevDocVersionRef = useRef82(0);
40214
- const scrollContainerRef = useRef82(null);
40353
+ const prevDocVersionRef = useRef83(0);
40354
+ const scrollContainerRef = useRef83(null);
40215
40355
  const isMasterView = !activeCompPath || activeCompPath === "index.html";
40216
40356
  const collectLayers = useCallback93(() => {
40217
40357
  const iframe = previewIframeRef.current;
@@ -40233,10 +40373,10 @@ var LayersPanel = memo39(function LayersPanel2() {
40233
40373
  });
40234
40374
  setLayers(sortLayersByZIndex(items));
40235
40375
  }, [previewIframeRef, activeCompPath, isMasterView, activeGroupElement, setActiveGroupElement]);
40236
- useEffect57(() => {
40376
+ useEffect58(() => {
40237
40377
  collectLayers();
40238
40378
  }, [collectLayers, refreshKey]);
40239
- useEffect57(() => {
40379
+ useEffect58(() => {
40240
40380
  const iframe = previewIframeRef.current;
40241
40381
  if (!iframe) return;
40242
40382
  const handleLoad = () => {
@@ -40246,7 +40386,7 @@ var LayersPanel = memo39(function LayersPanel2() {
40246
40386
  iframe.addEventListener("load", handleLoad);
40247
40387
  return () => iframe.removeEventListener("load", handleLoad);
40248
40388
  }, [previewIframeRef, collectLayers]);
40249
- useEffect57(() => {
40389
+ useEffect58(() => {
40250
40390
  if (!compositionLoading) {
40251
40391
  const timer = setTimeout(collectLayers, 100);
40252
40392
  return () => clearTimeout(timer);
@@ -41121,7 +41261,7 @@ function ParamControl({
41121
41261
  }
41122
41262
 
41123
41263
  // src/components/renders/RenderQueue.tsx
41124
- import { memo as memo44, useState as useState81, useRef as useRef83, useEffect as useEffect58 } from "react";
41264
+ import { memo as memo44, useState as useState81, useRef as useRef84, useEffect as useEffect59 } from "react";
41125
41265
 
41126
41266
  // src/components/renders/RenderQueueItem.tsx
41127
41267
  import { memo as memo43, useCallback as useCallback97, useState as useState80 } from "react";
@@ -41336,7 +41476,7 @@ var FORMAT_INFO = {
41336
41476
  };
41337
41477
  function FormatInfoTooltip({ format }) {
41338
41478
  const [open, setOpen] = useState81(false);
41339
- const timeoutRef = useRef83(void 0);
41479
+ const timeoutRef = useRef84(void 0);
41340
41480
  const show = () => {
41341
41481
  clearTimeout(timeoutRef.current);
41342
41482
  setOpen(true);
@@ -41344,7 +41484,7 @@ function FormatInfoTooltip({ format }) {
41344
41484
  const hide = () => {
41345
41485
  timeoutRef.current = setTimeout(() => setOpen(false), 120);
41346
41486
  };
41347
- useEffect58(() => () => clearTimeout(timeoutRef.current), []);
41487
+ useEffect59(() => () => clearTimeout(timeoutRef.current), []);
41348
41488
  const info = FORMAT_INFO[format];
41349
41489
  return /* @__PURE__ */ jsxs82("div", { className: "relative", onPointerEnter: show, onPointerLeave: hide, children: [
41350
41490
  /* @__PURE__ */ jsxs82(
@@ -41503,8 +41643,8 @@ var RenderQueue = memo44(function RenderQueue2({
41503
41643
  isRendering,
41504
41644
  compositionDimensions
41505
41645
  }) {
41506
- const listRef = useRef83(null);
41507
- useEffect58(() => {
41646
+ const listRef = useRef84(null);
41647
+ useEffect59(() => {
41508
41648
  if (listRef.current) {
41509
41649
  listRef.current.scrollTo({ top: listRef.current.scrollHeight, behavior: "smooth" });
41510
41650
  }
@@ -41586,7 +41726,7 @@ var RenderQueue = memo44(function RenderQueue2({
41586
41726
  });
41587
41727
 
41588
41728
  // src/components/panels/SlideshowPanel.tsx
41589
- import { useState as useState83, useEffect as useEffect59, useCallback as useCallback99, useRef as useRef84 } from "react";
41729
+ import { useState as useState83, useEffect as useEffect60, useCallback as useCallback99, useRef as useRef85 } from "react";
41590
41730
  import { parseSlideshowManifest } from "@hyperframes/core/slideshow";
41591
41731
 
41592
41732
  // src/components/panels/SlideshowSubPanels.tsx
@@ -42223,9 +42363,9 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
42223
42363
  );
42224
42364
  const currentTime = usePlayerStore((s) => s.currentTime);
42225
42365
  const { domEditSelection } = useDomEditSelectionContext();
42226
- const manifestRef = useRef84(manifest);
42227
- const notesCtrlRef = useRef84(makeSlideshowNotesController());
42228
- useEffect59(() => {
42366
+ const manifestRef = useRef85(manifest);
42367
+ const notesCtrlRef = useRef85(makeSlideshowNotesController());
42368
+ useEffect60(() => {
42229
42369
  if (!compHtml) {
42230
42370
  notesCtrlRef.current.flush();
42231
42371
  setManifest({ slides: [] });
@@ -42259,7 +42399,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
42259
42399
  },
42260
42400
  [onPersistNotes]
42261
42401
  );
42262
- useEffect59(() => {
42402
+ useEffect60(() => {
42263
42403
  const ctrl = notesCtrlRef.current;
42264
42404
  return () => {
42265
42405
  ctrl.flush();
@@ -42673,8 +42813,8 @@ function StudioRightPanel({
42673
42813
  coalesceKey: activeCompPath ? `slideshow-notes:${activeCompPath}` : "slideshow-notes"
42674
42814
  });
42675
42815
  const [layersPanePercent, setLayersPanePercent] = useState84(40);
42676
- const splitContainerRef = useRef85(null);
42677
- const splitDragRef = useRef85(null);
42816
+ const splitContainerRef = useRef86(null);
42817
+ const splitDragRef = useRef86(null);
42678
42818
  const renderJobs = renderQueue.jobs;
42679
42819
  const inspectorTabActive = rightPanelTab === "design" || rightPanelTab === "layers";
42680
42820
  const slideshowScenes = useMemo34(() => {
@@ -42910,7 +43050,7 @@ function StudioRightPanel({
42910
43050
  }
42911
43051
 
42912
43052
  // src/components/TimelineToolbar.tsx
42913
- import { useRef as useRef86 } from "react";
43053
+ import { useRef as useRef87 } from "react";
42914
43054
 
42915
43055
  // src/hooks/useEnableKeyframes.ts
42916
43056
  import { useCallback as useCallback102 } from "react";
@@ -43185,7 +43325,7 @@ function useEnableKeyframes(sessionRef) {
43185
43325
  import { Fragment as Fragment34, jsx as jsx101, jsxs as jsxs86 } from "react/jsx-runtime";
43186
43326
  function useKeyframeToggle(session) {
43187
43327
  const currentTime = usePlayerStore((s) => s.currentTime);
43188
- const sessionRef = useRef86(session);
43328
+ const sessionRef = useRef87(session);
43189
43329
  sessionRef.current = session;
43190
43330
  const onToggle = useEnableKeyframes(
43191
43331
  sessionRef
@@ -43375,14 +43515,14 @@ function TimelineToolbar({
43375
43515
  }
43376
43516
 
43377
43517
  // src/hooks/useStoryboard.ts
43378
- import { useCallback as useCallback103, useEffect as useEffect60, useState as useState85 } from "react";
43518
+ import { useCallback as useCallback103, useEffect as useEffect61, useState as useState85 } from "react";
43379
43519
  function useStoryboard(projectId) {
43380
43520
  const [data, setData] = useState85(null);
43381
43521
  const [loading, setLoading] = useState85(true);
43382
43522
  const [error, setError] = useState85(null);
43383
43523
  const [reloadKey, setReloadKey] = useState85(0);
43384
43524
  const reload = useCallback103(() => setReloadKey((k) => k + 1), []);
43385
- useEffect60(() => {
43525
+ useEffect61(() => {
43386
43526
  if (!projectId) return;
43387
43527
  let cancelled = false;
43388
43528
  setLoading(true);
@@ -43428,11 +43568,11 @@ function StoryboardDirection({ globals, frameCount }) {
43428
43568
  }
43429
43569
 
43430
43570
  // src/components/storyboard/FramePoster.tsx
43431
- import { useEffect as useEffect61, useState as useState86 } from "react";
43571
+ import { useEffect as useEffect62, useState as useState86 } from "react";
43432
43572
  import { jsx as jsx103 } from "react/jsx-runtime";
43433
43573
  function FramePoster({ projectId, src, seconds, title, fit = "cover" }) {
43434
43574
  const [failed2, setFailed] = useState86(false);
43435
- useEffect61(() => setFailed(false), [src, seconds]);
43575
+ useEffect62(() => setFailed(false), [src, seconds]);
43436
43576
  if (failed2) {
43437
43577
  return /* @__PURE__ */ jsx103("div", { className: "flex h-full w-full items-center justify-center text-[11px] text-neutral-600", children: "Preview unavailable" });
43438
43578
  }
@@ -43605,7 +43745,7 @@ function StoryboardScriptPanel({ script }) {
43605
43745
  }
43606
43746
 
43607
43747
  // src/components/storyboard/StoryboardSourceEditor.tsx
43608
- import { useCallback as useCallback104, useEffect as useEffect62, useMemo as useMemo35, useRef as useRef87, useState as useState87 } from "react";
43748
+ import { useCallback as useCallback104, useEffect as useEffect63, useMemo as useMemo35, useRef as useRef88, useState as useState87 } from "react";
43609
43749
  import { marked } from "marked";
43610
43750
  import DOMPurify from "dompurify";
43611
43751
  import { jsx as jsx108, jsxs as jsxs91 } from "react/jsx-runtime";
@@ -43617,7 +43757,7 @@ function useEditableFile(path, onSaved) {
43617
43757
  const [loading, setLoading] = useState87(true);
43618
43758
  const [saving, setSaving] = useState87(false);
43619
43759
  const [error, setError] = useState87(null);
43620
- useEffect62(() => {
43760
+ useEffect63(() => {
43621
43761
  if (!path) return;
43622
43762
  let cancelled = false;
43623
43763
  setLoading(true);
@@ -43654,8 +43794,8 @@ function hardenLinks(node) {
43654
43794
  }
43655
43795
  function useMarkdownPreview(source) {
43656
43796
  const [debounced, setDebounced] = useState87(source);
43657
- const primed = useRef87(false);
43658
- useEffect62(() => {
43797
+ const primed = useRef88(false);
43798
+ useEffect63(() => {
43659
43799
  if (!primed.current && source !== "") {
43660
43800
  primed.current = true;
43661
43801
  setDebounced(source);
@@ -43687,8 +43827,8 @@ function StoryboardSourceEditor({
43687
43827
  const activePath = files.some((f) => f.path === selected) ? selected : files[0]?.path ?? "";
43688
43828
  const file = useEditableFile(activePath, onSaved);
43689
43829
  const previewHtml = useMarkdownPreview(file.content);
43690
- useEffect62(() => onDirtyChange?.(file.dirty), [onDirtyChange, file.dirty]);
43691
- useEffect62(() => {
43830
+ useEffect63(() => onDirtyChange?.(file.dirty), [onDirtyChange, file.dirty]);
43831
+ useEffect63(() => {
43692
43832
  if (!file.dirty) return;
43693
43833
  const onBeforeUnload = (event) => {
43694
43834
  event.preventDefault();
@@ -43760,7 +43900,7 @@ function StoryboardSourceEditor({
43760
43900
  }
43761
43901
 
43762
43902
  // src/components/storyboard/StoryboardFrameFocus.tsx
43763
- import { useCallback as useCallback105, useEffect as useEffect63, useState as useState88 } from "react";
43903
+ import { useCallback as useCallback105, useEffect as useEffect64, useState as useState88 } from "react";
43764
43904
  import { setFrameStatus, setFrameVoiceover } from "@hyperframes/core/storyboard";
43765
43905
  import { jsx as jsx109, jsxs as jsxs92 } from "react/jsx-runtime";
43766
43906
  function StoryboardFrameFocus({
@@ -43805,7 +43945,7 @@ function StoryboardFrameFocus({
43805
43945
  const handleNavigate = (delta) => {
43806
43946
  if (confirmLeave()) onNavigate(delta);
43807
43947
  };
43808
- useEffect63(() => {
43948
+ useEffect64(() => {
43809
43949
  const onKey = (e) => {
43810
43950
  const el = document.activeElement;
43811
43951
  if (el instanceof HTMLTextAreaElement || el instanceof HTMLInputElement) return;
@@ -44121,7 +44261,7 @@ function StudioSplash({ waiting }) {
44121
44261
  }
44122
44262
 
44123
44263
  // src/hooks/useServerConnection.ts
44124
- import { useEffect as useEffect64, useState as useState90 } from "react";
44264
+ import { useEffect as useEffect65, useState as useState90 } from "react";
44125
44265
  function useServerConnection() {
44126
44266
  const [projectId, setProjectId] = useState90(null);
44127
44267
  const [resolving, setResolving] = useState90(true);
@@ -44162,7 +44302,7 @@ function useServerConnection() {
44162
44302
  if (retryTimer !== null) clearTimeout(retryTimer);
44163
44303
  };
44164
44304
  });
44165
- useEffect64(() => {
44305
+ useEffect65(() => {
44166
44306
  const onHashChange = () => {
44167
44307
  const next = parseProjectIdFromHash(window.location.hash);
44168
44308
  if (next && next !== projectId) setProjectId(next);
@@ -44177,9 +44317,9 @@ function useServerConnection() {
44177
44317
  import { jsx as jsx113, jsxs as jsxs96 } from "react/jsx-runtime";
44178
44318
  function StudioApp() {
44179
44319
  const { projectId, resolving, waitingForServer } = useServerConnection();
44180
- const initialUrlStateRef = useRef88(readStudioUrlStateFromWindow());
44320
+ const initialUrlStateRef = useRef89(readStudioUrlStateFromWindow());
44181
44321
  const viewModeValue = useViewModeState(STUDIO_STORYBOARD_ENABLED);
44182
- useEffect65(() => {
44322
+ useEffect66(() => {
44183
44323
  if (resolving || waitingForServer) return;
44184
44324
  if (hasFiredSessionStart()) return;
44185
44325
  markSessionStartFired();
@@ -44193,12 +44333,12 @@ function StudioApp() {
44193
44333
  const [previewIframe, setPreviewIframe] = useState91(null);
44194
44334
  const [compositionLoading, setCompositionLoading] = useState91(true);
44195
44335
  const [refreshKey, setRefreshKey] = useState91(0);
44196
- const [, setPreviewDocumentVersion] = useState91(0);
44336
+ const [previewDocumentVersion, setPreviewDocumentVersion] = useState91(0);
44197
44337
  const [blockPreview, setBlockPreview] = useState91(null);
44198
- const previewIframeRef = useRef88(null);
44199
- const activeCompPathRef = useRef88(activeCompPath);
44338
+ const previewIframeRef = useRef89(null);
44339
+ const activeCompPathRef = useRef89(activeCompPath);
44200
44340
  activeCompPathRef.current = activeCompPath;
44201
- const leftSidebarRef = useRef88(null);
44341
+ const leftSidebarRef = useRef89(null);
44202
44342
  const renderQueue = useRenderQueue(projectId);
44203
44343
  const captionEditMode = useCaptionStore((s) => s.isEditMode);
44204
44344
  const captionHasSelection = useCaptionStore((s) => s.selectedSegmentIds.size > 0);
@@ -44213,7 +44353,7 @@ function StudioApp() {
44213
44353
  const maxEnd = timelineElements.length > 0 ? Math.max(...timelineElements.map((el) => el.start + el.duration)) : 0;
44214
44354
  return Math.max(timelineDuration, maxEnd);
44215
44355
  }, [timelineDuration, timelineElements]);
44216
- const refreshTimersRef = useRef88([]);
44356
+ const refreshTimersRef = useRef89([]);
44217
44357
  const refreshPreviewDocumentVersion = useCallback106(() => {
44218
44358
  for (const id of refreshTimersRef.current) clearTimeout(id);
44219
44359
  refreshTimersRef.current = [];
@@ -44223,7 +44363,7 @@ function StudioApp() {
44223
44363
  window.setTimeout(() => setPreviewDocumentVersion((v) => v + 1), 300)
44224
44364
  );
44225
44365
  }, []);
44226
- useEffect65(
44366
+ useEffect66(
44227
44367
  () => () => {
44228
44368
  for (const id of refreshTimersRef.current) clearTimeout(id);
44229
44369
  },
@@ -44244,9 +44384,9 @@ function StudioApp() {
44244
44384
  rightPanelTab: initialUrlStateRef.current.rightPanelTab
44245
44385
  });
44246
44386
  const editHistory = usePersistentEditHistory({ projectId });
44247
- const domEditSaveTimestampRef = useRef88(0);
44248
- const pendingTimelineEditPathRef = useRef88(/* @__PURE__ */ new Set());
44249
- const isGestureRecordingRef = useRef88(false);
44387
+ const domEditSaveTimestampRef = useRef89(0);
44388
+ const pendingTimelineEditPathRef = useRef89(/* @__PURE__ */ new Set());
44389
+ const isGestureRecordingRef = useRef89(false);
44250
44390
  const reloadPreview = useCallback106(() => setRefreshKey((k) => k + 1), []);
44251
44391
  const fileManager = useFileManager({
44252
44392
  projectId,
@@ -44256,7 +44396,7 @@ function StudioApp() {
44256
44396
  setRefreshKey
44257
44397
  });
44258
44398
  const sdkHandle = useSdkSession(projectId, activeCompPath, domEditSaveTimestampRef);
44259
- useEffect65(() => {
44399
+ useEffect66(() => {
44260
44400
  if (activeCompPathHydrated) return;
44261
44401
  if (!fileManager.fileTreeLoaded) return;
44262
44402
  const nextCompPath = normalizeStudioCompositionPath(
@@ -44316,18 +44456,18 @@ function StudioApp() {
44316
44456
  setRightCollapsed: panelLayout.setRightCollapsed,
44317
44457
  setRightPanelTab: panelLayout.setRightPanelTab
44318
44458
  });
44319
- const clearDomSelectionRef = useRef88(() => {
44459
+ const clearDomSelectionRef = useRef89(() => {
44320
44460
  });
44321
- const domEditSelectionBridgeRef = useRef88(null);
44322
- const handleDomEditElementDeleteRef = useRef88(
44461
+ const domEditSelectionBridgeRef = useRef89(null);
44462
+ const handleDomEditElementDeleteRef = useRef89(
44323
44463
  async () => {
44324
44464
  }
44325
44465
  );
44326
44466
  const domEditDeleteBridge = (s) => handleDomEditElementDeleteRef.current(s);
44327
- const resetKeyframesRef = useRef88(() => false);
44328
- const deleteSelectedKeyframesRef = useRef88(() => {
44467
+ const resetKeyframesRef = useRef89(() => false);
44468
+ const deleteSelectedKeyframesRef = useRef89(() => {
44329
44469
  });
44330
- const invalidateGsapCacheRef = useRef88(() => {
44470
+ const invalidateGsapCacheRef = useRef89(() => {
44331
44471
  });
44332
44472
  const { handleCopy, handlePaste, handleCut } = useClipboard({
44333
44473
  projectId,
@@ -44370,7 +44510,7 @@ function StudioApp() {
44370
44510
  forceReloadSdkSession: sdkHandle.forceReload,
44371
44511
  onToggleRecording: STUDIO_KEYFRAMES_ENABLED ? () => handleToggleRecordingRef.current() : void 0
44372
44512
  });
44373
- const sidebarTabRef = useRef88({
44513
+ const sidebarTabRef = useRef89({
44374
44514
  select: (t) => leftSidebarRef.current?.selectTab(t),
44375
44515
  get: () => leftSidebarRef.current?.getTab() ?? "compositions"
44376
44516
  });
@@ -44400,6 +44540,7 @@ function StudioApp() {
44400
44540
  projectIdRef: fileManager.projectIdRef,
44401
44541
  previewIframe,
44402
44542
  refreshKey,
44543
+ previewDocumentVersion,
44403
44544
  rightPanelTab: panelLayout.rightPanelTab,
44404
44545
  applyStudioManualEditsToPreviewRef: previewPersistence.applyStudioManualEditsToPreviewRef,
44405
44546
  syncPreviewHistoryHotkey: appHotkeys.syncPreviewHistoryHotkey,
@@ -44462,9 +44603,9 @@ function StudioApp() {
44462
44603
  resetErrors: resetConsoleErrors
44463
44604
  } = useConsoleErrorCapture(previewIframe);
44464
44605
  const dragOverlay = useDragOverlay(fileManager.handleImportFiles);
44465
- const handleToggleRecordingRef = useRef88(() => {
44606
+ const handleToggleRecordingRef = useRef89(() => {
44466
44607
  });
44467
- const domEditSessionRef = useRef88(domEditSession);
44608
+ const domEditSessionRef = useRef89(domEditSession);
44468
44609
  domEditSessionRef.current = domEditSession;
44469
44610
  const { gestureState, gestureRecording, handleToggleRecording } = useGestureCommit({
44470
44611
  domEditSessionRef,
@@ -44473,7 +44614,7 @@ function StudioApp() {
44473
44614
  isGestureRecordingRef
44474
44615
  });
44475
44616
  handleToggleRecordingRef.current = handleToggleRecording;
44476
- const canvasRectRef = useRef88(null);
44617
+ const canvasRectRef = useRef89(null);
44477
44618
  useLayoutEffect3(() => {
44478
44619
  if (gestureState !== "recording" || !previewIframe) {
44479
44620
  canvasRectRef.current = null;
@@ -44699,11 +44840,11 @@ function StudioApp() {
44699
44840
  }
44700
44841
 
44701
44842
  // src/hooks/useElementPicker.ts
44702
- import { useState as useState92, useCallback as useCallback107, useRef as useRef89 } from "react";
44843
+ import { useState as useState92, useCallback as useCallback107, useRef as useRef90 } from "react";
44703
44844
  function useElementPicker(iframeRef, options) {
44704
44845
  const [isPickMode, setIsPickMode] = useState92(false);
44705
44846
  const [pickedElement, setPickedElement] = useState92(null);
44706
- const activeOverrideRef = useRef89(null);
44847
+ const activeOverrideRef = useRef90(null);
44707
44848
  const getActiveIframe = useCallback107(() => {
44708
44849
  return activeOverrideRef.current ?? iframeRef.current;
44709
44850
  }, [iframeRef]);
@@ -44782,7 +44923,7 @@ function useElementPicker(iframeRef, options) {
44782
44923
  window.addEventListener("message", handleMessage);
44783
44924
  return () => window.removeEventListener("message", handleMessage);
44784
44925
  });
44785
- const optionsRef = useRef89(options);
44926
+ const optionsRef = useRef90(options);
44786
44927
  optionsRef.current = options;
44787
44928
  const syncToSource = useCallback107(
44788
44929
  (elementId, selector, op) => {
@@ -44893,7 +45034,7 @@ function useElementPicker(iframeRef, options) {
44893
45034
  },
44894
45035
  [pickedElement, getActiveIframe, syncToSource]
44895
45036
  );
44896
- const activeIframeRef = useRef89(null);
45037
+ const activeIframeRef = useRef90(null);
44897
45038
  activeIframeRef.current = getActiveIframe();
44898
45039
  return {
44899
45040
  isPickMode,